Hello Philippe.
I mentioned ClassImp
only as another example that uses __FILE__
macro, I more concerned with ClassDef
.
And I don’t understand that. For what reason one may need that information at runtime? AFAIK, the call of DeclFileName
method is only possible at runtime (I’m including here the ROOT interactive sessions too) but why one needs that information at runtime? To open a file in an editor? As for interactive session, IMHO, it should know where header files are.
Yes, this is fragile, so I think why one would provide function for such thing at all.
IMHO, there are other ways to store information about installed files (what about actual DB or something like ls-R
that do TeX Live?).
Let’s consider one example: I compiled the ROOT source with --save-temps
with both GCC (8.2.0) and CLANG (6.0.1) to keep intermediate file and see to which location points DeclFileName
. I took as example two files in math/mathcore/
: for TMath.ii
root-build $ grep '\*DeclFileName' TMath.ii
private: virtual Bool_t CheckTObjectHashConsistency() const { static std::atomic<UChar_t> recurseBlocker(0); if (__builtin_expect(!!(recurseBlocker >= 2), 1)) { return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; } else if (recurseBlocker == 1) { return false; } else if (recurseBlocker++ == 0) { ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency = ::ROOT::Internal::HasConsistentHashMember("TString") || ::ROOT::Internal::HasConsistentHashMember(*IsA()); ++recurseBlocker; return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; } return false; } public: static Version_t Class_Version() { return 2; } virtual TClass *IsA() const { return TString::Class(); } virtual void ShowMembers(TMemberInspector &insp) const { ::ROOT::Class_ShowMembers(TString::Class(), this, insp); } void StreamerNVirtual(TBuffer &ClassDef_StreamerNVirtual_b) { TString::Streamer(ClassDef_StreamerNVirtual_b); } static const char *DeclFileName() { return "/home/vladimir/pkgs/root-extra/src/build-gcc/include/TString.h"; } private: static atomic_TClass_ptr fgIsA; public: static int ImplFileLine(); static const char *ImplFileName(); static const char *Class_Name(); static TClass *Dictionary(); static TClass *Class(); virtual void Streamer(TBuffer&) ; static int DeclFileLine() { return 460; }
(this is for class TString
) and for TComplex.ii
:
root-build $ grep '\*DeclFileName' TComplex.ii
private: virtual Bool_t CheckTObjectHashConsistency() const { static std::atomic<UChar_t> recurseBlocker(0); if (__builtin_expect(!!(recurseBlocker >= 2), 1)) { return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; } else if (recurseBlocker == 1) { return false; } else if (recurseBlocker++ == 0) { ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency = ::ROOT::Internal::HasConsistentHashMember("TComplex") || ::ROOT::Internal::HasConsistentHashMember(*IsA()); ++recurseBlocker; return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; } return false; } public: static Version_t Class_Version() { return 1; } virtual TClass *IsA() const { return TComplex::Class(); } virtual void ShowMembers(TMemberInspector &insp) const { ::ROOT::Class_ShowMembers(TComplex::Class(), this, insp); } void StreamerNVirtual(TBuffer &ClassDef_StreamerNVirtual_b) { TComplex::Streamer(ClassDef_StreamerNVirtual_b); } static const char *DeclFileName() { return "/home/vladimir/pkgs/root-extra/src/build-gcc/include/TComplex.h"; } private: static atomic_TClass_ptr fgIsA; public: static int ImplFileLine(); static const char *ImplFileName(); static const char *Class_Name(); static TClass *Dictionary(); static TClass *Class(); virtual void Streamer(TBuffer&) ; static int DeclFileLine() { return 184; }
(this is for class TComplex
).
And this is after I applied my patch for CMakeLists.txt
: for TMath.ii
root-build $ grep '\*DeclFileName' TMath.ii
private: virtual Bool_t CheckTObjectHashConsistency() const { static std::atomic<UChar_t> recurseBlocker(0); if (__builtin_expect(!!(recurseBlocker >= 2), 1)) { return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; } else if (recurseBlocker == 1) { return false; } else if (recurseBlocker++ == 0) { ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency = ::ROOT::Internal::HasConsistentHashMember("TString") || ::ROOT::Internal::HasConsistentHashMember(*IsA()); ++recurseBlocker; return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; } return false; } public: static Version_t Class_Version() { return 2; } virtual TClass *IsA() const { return TString::Class(); } virtual void ShowMembers(TMemberInspector &insp) const { ::ROOT::Class_ShowMembers(TString::Class(), this, insp); } void StreamerNVirtual(TBuffer &ClassDef_StreamerNVirtual_b) { TString::Streamer(ClassDef_StreamerNVirtual_b); } static const char *DeclFileName() { return "math/mathcore/src/TMath.cxx"; } private: static atomic_TClass_ptr fgIsA; public: static int ImplFileLine(); static const char *ImplFileName(); static const char *Class_Name(); static TClass *Dictionary(); static TClass *Class(); virtual void Streamer(TBuffer&) ; static int DeclFileLine() { return 460; }
(this is the same class TString
and obviously this is wrong value for DeclFileName
) and for TComplex.ii
root-build $ grep '\*DeclFileName' TComplex.ii
private: virtual Bool_t CheckTObjectHashConsistency() const { static std::atomic<UChar_t> recurseBlocker(0); if (__builtin_expect(!!(recurseBlocker >= 2), 1)) { return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; } else if (recurseBlocker == 1) { return false; } else if (recurseBlocker++ == 0) { ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency = ::ROOT::Internal::HasConsistentHashMember("TComplex") || ::ROOT::Internal::HasConsistentHashMember(*IsA()); ++recurseBlocker; return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; } return false; } public: static Version_t Class_Version() { return 1; } virtual TClass *IsA() const { return TComplex::Class(); } virtual void ShowMembers(TMemberInspector &insp) const { ::ROOT::Class_ShowMembers(TComplex::Class(), this, insp); } void StreamerNVirtual(TBuffer &ClassDef_StreamerNVirtual_b) { TComplex::Streamer(ClassDef_StreamerNVirtual_b); } static const char *DeclFileName() { return "math/mathcore/src/TComplex.cxx"; } private: static atomic_TClass_ptr fgIsA; public: static int ImplFileLine(); static const char *ImplFileName(); static const char *Class_Name(); static TClass *Dictionary(); static TClass *Class(); virtual void Streamer(TBuffer&) ; static int DeclFileLine() { return 184; }
(this is for class TComplex
and again it is wrong, it refers cxx
instead of h
file).