[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#958479: qmake passes unsupported -isystem to gcc



Package: qt5-qmake
Version: 5.12.5+dfsg-10
Severity: important
Tags: ftbfs patch upstream
Control: affects -1 + src:deepin-music
Control: block 798955 by -1

The context of this bug is #798955 aka moving glibc headers from
/usr/include to /usr/include/<triplet>. When doing this, some packages
FTBFS with the symptom that <cstdlib> or <cmath> fail to find
#include_next <stdlib.h> or #include_next <math.h> respectively. The
cause is passing -isystem /usr/include/<triplet> to the compiler. I
asked libstdc++ upstream to fix this, but the reply was that passing
this flag is unsupported (see bug log of #798955). The takeaway is:
Pass -isystem /usr/include or -isystem /usr/include/<triplet> is broken.

Unfortunately, qmake does exactly that. It collects include directories
(e.g. from pkg-config file). For instance libavutil.pc contains
includedir=/usr/include/<triplet>. The collected directories reside in a
variable INCLUDEPATH. It then passes -isystem for every path that
resides below a set of compiler include directories and -I for
everything else. Since /usr/include/<triplet> resides below
/usr/include, qmake turns the flag into -isystem. Doing so changes the
order of -isystem directories and breaks gcc. I think this is a bug in
qmake. The resuling flags are assigned to a variable INCPATH. The
relevant source can be found at:
https://sources.debian.org/src/qtbase-opensource-src/5.12.5+dfsg-10/qmake/generators/unix/unixmake2.cpp/#L196

An example of an affected package is deepin-music. I think around 10 (an
upper bound seems to be 30, but that includes other causes). You can
quickly check whether a package is affected by grepping a build log for
"-isystem /usr/include/<triplet>".

I can also propose a solution. When constructing INCPATH, any directory
that directly is a compiler search directory (not a subdirectory
thereof), the directory should be skipped. Doing so ensures that the
order of compiler search directories is not changed. The possible harm
seems quite limited given that the compiler will already search these
directories (just in the correct order).

What do you think?

Please expect that this bug becomes a regular ftbfs bug eventually.

Helmut
--- qtbase-opensource-src-5.12.5+dfsg.orig/qmake/generators/makefiledeps.cpp
+++ qtbase-opensource-src-5.12.5+dfsg/qmake/generators/makefiledeps.cpp
@@ -359,6 +359,11 @@
     return false;
 }
 
+bool QMakeSourceFileInfo::isCompilerInclude(const QString &name)
+{
+    return systemIncludes.contains(name);
+}
+
 char *QMakeSourceFileInfo::getBuffer(int s) {
     if(!spare_buffer || spare_buffer_size < s)
         spare_buffer = (char *)realloc(spare_buffer, spare_buffer_size=s);
--- qtbase-opensource-src-5.12.5+dfsg.orig/qmake/generators/makefiledeps.h
+++ qtbase-opensource-src-5.12.5+dfsg/qmake/generators/makefiledeps.h
@@ -106,6 +106,7 @@
     void addSourceFile(const QString &, uchar seek, SourceFileType type=TYPE_C);
     bool containsSourceFile(const QString &, SourceFileType type=TYPE_C);
     bool isSystemInclude(const QString &);
+    bool isCompilerInclude(const QString &);
 
     int included(const QString &file);
     QStringList dependencies(const QString &file);
--- qtbase-opensource-src-5.12.5+dfsg.orig/qmake/generators/unix/unixmake2.cpp
+++ qtbase-opensource-src-5.12.5+dfsg/qmake/generators/unix/unixmake2.cpp
@@ -202,11 +202,12 @@
             if (inc.isEmpty())
                 continue;
 
-            if (!isystem.isEmpty() && isSystemInclude(inc.toQString()))
-                t << ' ' << isystem << ' ';
+	    if (isCompilerInclude(inc.toQString()))
+		;
+	    else if (!isystem.isEmpty() && isSystemInclude(inc.toQString()))
+                t << ' ' << isystem << ' ' << escapeFilePath(inc);
             else
-                t << " -I";
-            t << escapeFilePath(inc);
+                t << " -I" << escapeFilePath(inc);
         }
     }
     if(!project->isEmpty("QMAKE_FRAMEWORKPATH_FLAGS"))

Reply to: