Details
-
Type:
Bug
-
Status: Closed (View Workflow)
-
Priority:
High
-
Resolution: Won't Fix
-
Affects Version/s: 6.08/06, 6.09/02
-
Fix Version/s: None
-
Component/s: Dictionaries
-
Labels:None
-
Environment:
Arch Linux x86_64
GCC 6.3.0
Qt 5.8.0 (built with -reduce-relocations)
-
Development:
Description
I've been scratching my head how to workaround the following problem. This may not actually be a problem with ROOT, but I would really appreciate it if you could take a look and let me know if you have some idea for a workaround.
Let us say you have a class declared in a header file wich looks like this:
#ifndef MyClass_hh
|
#define MyClass_hh
|
|
#include <QtCore/qglobal.h>
|
|
class MyClass {
|
public:
|
MyClass();
|
~MyClass();
|
|
private:
|
ClassDef(MyClass, 1)
|
};
|
|
#endif
|
with Linkdef.h
#ifndef Linkdef_h
|
#define Linkdef_h
|
|
#pragma link C++ nestedclass;
|
#pragma link C++ nestedtypedefs;
|
|
#pragma link off all globals;
|
#pragma link off all classes;
|
#pragma link off all functions;
|
|
#pragma link C++ class MyClass;
|
|
#endif
|
And you want to make root dictionary from this class:
rootcling -f MyClassDict.cc -I/usr/include/qt MyClass.hh Linkdef.h
|
Then, this will fail if Qt5 version is recent enough (I have 5.8 but 5.5 should also work) and Qt5 was built with "-reduce-relocations" in its configure flags. The reason is that, if '-reduce-relocations' was used to build Qt5, then "qconfig.h" header (indirectly included in qglobal.h) will include a line that defines QT_REDUCE_RELOCATIONS. And then the problem is that "qglobal.h" uses "#error" to abort compilation unless the user code is compiled with -fPIC. Here's the relevant section of qglobal.h:
#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && \
|
(!defined(__PIC__) || (defined(__PIE__) && defined(Q_CC_GNU) && Q_CC_GNU >= 500))
|
# error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\
|
"Compile your code with -fPIC (-fPIE is not enough)."
|
#endif
|
Now I admit that this is a nasty thing that they added in Qt. Here are some references:
https://bugreports.qt.io/browse/QTBUG-45755
https://bugs.archlinux.org/task/45283
which explain the rationale behind the code above. But I have to find a way to workaround this issue. We are already compiling all our code with -fPIC. The MyClassDict.cxx would also be compiled with -fPIC, if it were created. The issue is that the rootcling invocation which generates MyClassDict.cxx does not define "_PIC_" and I can't add -fPIC to the rootcling flags since that flag is ignored (see rootcling_impl.cxx "ShouldIgnoreClingArgument").
It works when I add "-D_PIC_" to the rootcling arguments, but that's an ugly hack:
rootcling -f MyClassDict.cc -D__PIC__ -I/usr/include/qt MyClass.hh Linkdef.h
|
And things are actually even more complicated. While defining _PIC_ on the rootcling commandline works around this particular problem, it doesn't help when trying to compile a macro with TSystem::CompileMacro("macro.C", "kf"), since that will internally construct a rootcling call with some fixed arguments which I can't change, so I don't know how I would inject "-D_PIC_" there.
The next thing I tried is to write a "qglobal.h" wrapper and put it in a place that comes first in my include path. It looks like this:
#ifndef __qglobal_wrapper__
|
#define __qglobal_wrapper__
|
|
// If Qt5 is build with '-reduce-relocations', then user code must be compiled with -fPIC, which we do.
|
// However, rootcint / rootcling in ROOT 6 uses clang to preprocess the source files and there is no way
|
// to pass -fPIC to clang as used in rootcint.
|
// Workaround this by defining __PIC__ manually.
|
#if defined(__CLING__) && !defined(__PIC__)
|
|
#define __PIC__
|
#include_next <QtCore/qglobal.h>
|
#undef __PIC__
|
|
#else
|
|
#include_next <QtCore/qglobal.h>
|
|
#endif
|
|
#endif
|
Now this makes things mostly work, but there are some macros which I can't compile with ACLiC anymore, because after the macro_C.so is generated in TSystem::CompileMacro() it gets loaded with "gSystem->Load()" and in this step root.exe crashes with a segmentation violation, possibly due to the _PIC_ define?!
Now I'm really lost and have no more ideas...