Uploaded image for project: 'ROOT'
  1. ROOT
  2. ROOT-8719

rootcling failes to parse files which include Qt5 headers if Qt5 was built with -reduce-relocations



    • 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:
    • Environment:

      Arch Linux x86_64
      GCC 6.3.0
      Qt 5.8.0 (built with -reduce-relocations)


      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 {
        ClassDef(MyClass, 1)

      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;

      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)."

      Now I admit that this is a nasty thing that they added in Qt. Here are some references:


      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__
      #include_next <QtCore/qglobal.h>

      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...




            axel Axel Naumann
            bbeische Bastian Beischer
            2 Vote for this issue
            5 Start watching this issue