Discussion:
Qt 5 LTO build on OS X 10.9 (and earlier)
(too old to reply)
René J.V. Bertin
2015-09-11 08:24:32 UTC
Permalink
Hello,

Has anyone tested building Qt 5.5.0 with link-time optimisation (qmake -config ltcg) on Mac OS X 10.9 and possibly earlier?
I'm getting a failure on the bootstrap static lib because llvm-ar is missing from the system toolchain (latest Xcode for 10.9).

It seems that the ar command works too though it complains about and ignores invalid debug info (which fits in with though doesn't fully explain my experience that LTO builds lack debug information in shared libraries).

R.
Thiago Macieira
2015-09-11 11:21:11 UTC
Permalink
Post by René J.V. Bertin
Hello,
Has anyone tested building Qt 5.5.0 with link-time optimisation (qmake
-config ltcg) on Mac OS X 10.9 and possibly earlier? I'm getting a failure
on the bootstrap static lib because llvm-ar is missing from the system
toolchain (latest Xcode for 10.9).
I've only ever tested LTO builds on Linux. That's where llvm-ar comes from --
the *official* clang + LLVM build.
Post by René J.V. Bertin
It seems that the ar command works too though it complains about and ignores
invalid debug info (which fits in with though doesn't fully explain my
experience that LTO builds lack debug information in shared libraries).
That depends on whether the .o files were fat or thin.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
René J. V. Bertin
2015-09-11 16:33:05 UTC
Permalink
Post by Thiago Macieira
I've only ever tested LTO builds on Linux. That's where llvm-ar comes from --
the *official* clang + LLVM build.
Quick check: my llvm 3.5.1 build on Linux indeed has llvm-ar, but it's got a
-3.5 suffix like all other user-visible commands. I think that's what's official
on Debian/Ubuntu at least; does Qt's build system pick up binaries named that
way?
Post by Thiago Macieira
Post by René J.V. Bertin
It seems that the ar command works too though it complains about and ignores
invalid debug info (which fits in with though doesn't fully explain my
experience that LTO builds lack debug information in shared libraries).
That depends on whether the .o files were fat or thin.
I don't know of a way to chose between those options with clang, but if I
understand you correctly and the .o files were thin, wouldn't that also cause
executables to lack debugging info? Because executables do seem to have
everything for normal debugging.

R.
Thiago Macieira
2015-09-11 17:36:07 UTC
Permalink
Post by René J. V. Bertin
Post by Thiago Macieira
I've only ever tested LTO builds on Linux. That's where llvm-ar comes from
-- the *official* clang + LLVM build.
Quick check: my llvm 3.5.1 build on Linux indeed has llvm-ar, but it's got a
-3.5 suffix like all other user-visible commands. I think that's what's
official on Debian/Ubuntu at least; does Qt's build system pick up binaries
named that way?
No, just like Qt won't pick up gcc-4.8, clang-3.5 or gcc-ar-4.9. You must
provide a PATH entry that contains the binaries without suffix or you'll have to
tinker with the mkspec (QMAKE_AR).
Post by René J. V. Bertin
Post by Thiago Macieira
Post by René J.V. Bertin
It seems that the ar command works too though it complains about and
ignores invalid debug info (which fits in with though doesn't fully
explain my experience that LTO builds lack debug information in shared
libraries).>
That depends on whether the .o files were fat or thin.
I don't know of a way to chose between those options with clang, but if I
You don't. Clang does not have -f[no-]fat-lto-objects. Clang will do whatever
it wants.

If it produces "thin" objects (LLVM bitcode only), then you must use llvm-ar
to create the .a so that the symbol table is updated with the symbols that
would have been there if the .o were "fat".
Post by René J. V. Bertin
understand you correctly and the .o files were thin, wouldn't that also
cause executables to lack debugging info? Because executables do seem to
have everything for normal debugging.
Actually, that has nothing to do with debugging.

That's just linking.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
René J. V. Bertin
2015-09-11 18:48:39 UTC
Permalink
Post by Thiago Macieira
If it produces "thin" objects (LLVM bitcode only), then you must use llvm-ar
to create the .a so that the symbol table is updated with the symbols that
would have been there if the .o were "fat".
Hmmm, I actually don't know about static libraries, I hardly use them. Of course
if they end up linked into shared libraries their debug info will get lost with
the rest. I don't suppose llvm-ar works on shared libraries, does it?
Post by Thiago Macieira
Actually, that has nothing to do with debugging.
That's just linking.
Well, yes, it's something to do with the linker, but the end result is that
symbolic or source-level (or whatever you wish to call it) is possible or not
...

R
Thiago Macieira
2015-09-11 21:49:39 UTC
Permalink
Post by René J. V. Bertin
Post by Thiago Macieira
If it produces "thin" objects (LLVM bitcode only), then you must use
llvm-ar to create the .a so that the symbol table is updated with the
symbols that would have been there if the .o were "fat".
Hmmm, I actually don't know about static libraries, I hardly use them.
libQt5Bootstrap.a, libqtharfbuzzng.a, libQt5PlatformSupport.a. If you're
trying to compile qtbase, you're building at least three of them.
Post by René J. V. Bertin
Of
course if they end up linked into shared libraries their debug info will
get lost with the rest. I don't suppose llvm-ar works on shared libraries,
does it?
I have no clue what issues with debugging there might be. I haven't
experienced that problem with GCC's LTO.
Post by René J. V. Bertin
Post by Thiago Macieira
Actually, that has nothing to do with debugging.
That's just linking.
Well, yes, it's something to do with the linker, but the end result is that
symbolic or source-level (or whatever you wish to call it) is possible or
not ...
I don't see any reason why the compiler would get lost.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
René J. V. Bertin
2015-09-11 22:19:27 UTC
Permalink
Post by Thiago Macieira
I have no clue what issues with debugging there might be. I haven't
experienced that problem with GCC's LTO.
It's like debugging an application or library built without -g. Indeed, I
haven't noticed any issue like that with gcc 5 on Linux.
Post by Thiago Macieira
Post by René J. V. Bertin
Well, yes, it's something to do with the linker, but the end result is that
symbolic or source-level (or whatever you wish to call it) is possible or
^ debugging
Post by Thiago Macieira
Post by René J. V. Bertin
not ...
I don't see any reason why the compiler would get lost.
And I have no idea why you drag the compiler into this :)

My hunch is that the -g is dropped during the linking stage, it doesn't show in
the ld arguments at least. The way I think of it is that LTO basically repeats
part of the compilation or maybe just the assembly-level optimisation after
loading all code that must be linked together. If that's done after dropping -g,
that would explain the absence of debug information in the resulting binary.
(then again that might be as close to the truth as Genesis is :) )

R
Thiago Macieira
2015-09-12 03:52:24 UTC
Permalink
Post by René J. V. Bertin
Post by Thiago Macieira
I don't see any reason why the compiler would get lost.
And I have no idea why you drag the compiler into this :)
Because we're talking about LTCG, which implies the compiler is run at the
linking stage.
Post by René J. V. Bertin
My hunch is that the -g is dropped during the linking stage, it doesn't show
in the ld arguments at least.
It wouldn't show in ld's arguments. But it shows in the g++ arguments that
will eventually run ld. ltcg.prf adds the compiler flags to QMAKE_LFLAGS.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
René J. V. Bertin
2015-09-12 13:13:35 UTC
Permalink
Post by Thiago Macieira
Because we're talking about LTCG, which implies the compiler is run at the
linking stage.
In any case it (clang) doesn't show up in the process list. Also, from what I
understand clang stores some intermediate LLVM byte-code representation
(probably the same language-agnostic code that's used by the llvm backend. I'm
not sure if from there on one can still speak in terms of "invoking the
compiler" but then that might be splitting hairs.
Post by Thiago Macieira
It wouldn't show in ld's arguments. But it shows in the g++ arguments that
will eventually run ld. ltcg.prf adds the compiler flags to QMAKE_LFLAGS.
It also shows in the argument when ld is invoked through clang++ . Still, the
command doing the heavy lifting is ld, and it seems inefficient if that same
command doesn't also generate/collect the debug info. There's no noticeable
delay before or after ld is run (and some link commands are heavy and lengthy
enough that I'd expect the collection of debug info to take a noticeable time if
done before or after the optimisation+link operation).
Anyway, I'd better ask about this on an llvm ML.

R.
Thiago Macieira
2015-09-12 15:24:14 UTC
Permalink
Post by René J. V. Bertin
Post by Thiago Macieira
Because we're talking about LTCG, which implies the compiler is run at the
linking stage.
In any case it (clang) doesn't show up in the process list. Also, from what
I understand clang stores some intermediate LLVM byte-code representation
(probably the same language-agnostic code that's used by the llvm backend.
I'm not sure if from there on one can still speak in terms of "invoking the
compiler" but then that might be splitting hairs.
LTO operates in two steps:
- the "compilation" is only a parsing to intermediate language (LLVM bitcode
for Clang, GIMPLE for GCC)
- the "linking" transforms the intermediate language into machine code
Post by René J. V. Bertin
Post by Thiago Macieira
It wouldn't show in ld's arguments. But it shows in the g++ arguments that
will eventually run ld. ltcg.prf adds the compiler flags to QMAKE_LFLAGS.
It also shows in the argument when ld is invoked through clang++ . Still,
the command doing the heavy lifting is ld, and it seems inefficient if that
same command doesn't also generate/collect the debug info. There's no
noticeable delay before or after ld is run (and some link commands are
heavy and lengthy enough that I'd expect the collection of debug info to
take a noticeable time if done before or after the optimisation+link
operation).
Anyway, I'd better ask about this on an llvm ML.
Make a direct test by running clang manually.

It's possible they think "no one will debug LTO code" and haven't implemented
the feature.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
René J. V. Bertin
2015-09-12 16:20:53 UTC
Permalink
Post by Thiago Macieira
It's possible they think "no one will debug LTO code" and haven't implemented
the feature.
Possible. But that would be comparable to the idea 640Kb is RAM enough ;) and I
guess they too would like to see line numbers on backtraces they get..

R.
Guido Seifert
2015-09-12 16:47:19 UTC
Permalink
Post by René J. V. Bertin
Possible. But that would be comparable to the idea 640Kb is RAM enough ;)
HE NEVER SAID THIS... I was present, when he did not say it. :-D

Guido
René J. V. Bertin
2015-09-13 08:51:01 UTC
Permalink
Post by Guido Seifert
HE NEVER SAID THIS... I was present, when he did not say it. :-D
[bowes in awe]

man you must have stories to tell ... (you can add the appropriate great/grand
iterator child instances yourself ;))

René J. V. Bertin
2015-09-11 19:48:32 UTC
Permalink
Post by Thiago Macieira
No, just like Qt won't pick up gcc-4.8, clang-3.5 or gcc-ar-4.9. You must
provide a PATH entry that contains the binaries without suffix or you'll have
to tinker with the mkspec (QMAKE_AR).
QMAKE_AR_LTCG in fact (and QMAKE_NM_LTCG, QMAKE_RANLIB_LTCG). On OS X that also
means tinkering with mac/sdk.prf to ensure that xcrun isn't used to undo any
compiler selection you'd make in one of "the usual ways".

About using alternate compilers: I haven't yet figured out how to get qmake to
build using the compiler of choice, as well as the config tests. For qmake the
compiler choice probably doesn't make a lot of difference, but the config tests
probably best be done with the compiler that's used to do the actual build,
don't you think?

R.
Thiago Macieira
2015-09-11 21:55:51 UTC
Permalink
Post by René J. V. Bertin
About using alternate compilers: I haven't yet figured out how to get qmake
to build using the compiler of choice, as well as the config tests. For
qmake the compiler choice probably doesn't make a lot of difference, but
the config tests probably best be done with the compiler that's used to do
the actual build, don't you think?
I wouldn't know. There's some extra magic on OS X because of the SDKs. I have
never investigated that and don't understand it.

That probably means LTCG on Mac is busted because I've never tested it.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
René J. V. Bertin
2015-09-11 22:22:18 UTC
Permalink
Post by Thiago Macieira
Post by René J. V. Bertin
About using alternate compilers: I haven't yet figured out how to get qmake
to build using the compiler of choice, as well as the config tests. For
qmake the compiler choice probably doesn't make a lot of difference, but
the config tests probably best be done with the compiler that's used to do
the actual build, don't you think?
I wouldn't know. There's some extra magic on OS X because of the SDKs. I have
never investigated that and don't understand it.
That probably means LTCG on Mac is busted because I've never tested it.
The compiler mismatch is independent from using LTO of course.

I could file a bug report on this, if at least it is supposed to be possible to
build Qt with a different compiler than the one provided via Xcode.

R.
René J. V. Bertin
2015-09-11 20:54:50 UTC
Permalink
Post by Thiago Macieira
I've only ever tested LTO builds on Linux. That's where llvm-ar comes from --
the *official* clang + LLVM build.
OK, so I tinkered with clang.conf such that a build using MacPort's clang-3.6
(clang++-mp-3.6) also uses the corresponding llvm-ar-mp-3.6 and llvm-nm-mp-3.6 ,
and qmodule.pri to make sure that clang++-mp-3.6 is the command used for linking
(crucial for a LTO build with clang).

Now, I'm seeing this failure:

/opt/local/bin/llvm-ar-mp-3.6 cqs libQt5Bootstrap.a .obj/qcore_mac_objc.o
.obj/qstring_mac.o .obj/qstandardpaths_mac.o .obj/qlatincodec.o
.obj/qtextcodec.o .obj/qutfcodec.o .obj/qglobal.o .obj/qlogging.o .obj/qmalloc.o
.obj/qnumeric.o .obj/qabstractfileengine.o .obj/qbuffer.o .obj/qdatastream.o
.obj/qdebug.o .obj/qdir.o .obj/qdiriterator.o .obj/qfile.o .obj/qfileinfo.o
.obj/qfilesystementry.o .obj/qfilesystemengine.o .obj/qfsfileengine.o
.obj/qfsfileengine_iterator.o .obj/qiodevice.o .obj/qfiledevice.o
.obj/qtemporaryfile.o .obj/qtextstream.o .obj/qstandardpaths.o
.obj/qloggingcategory.o .obj/qloggingregistry.o .obj/qcoreapplication.o
.obj/qcoreglobaldata.o .obj/qmetatype.o .obj/qvariant.o .obj/qsystemerror.o
.obj/quuid.o .obj/qbitarray.o .obj/qbytearray.o .obj/qarraydata.o
.obj/qbytearraymatcher.o .obj/qcommandlineparser.o .obj/qcommandlineoption.o
.obj/qcryptographichash.o .obj/qdatetime.o .obj/qhash.o .obj/qlist.o
.obj/qlinkedlist.o .obj/qlocale.o .obj/qlocale_tools.o .obj/qmap.o
.obj/qregexp.o .obj/qpoint.o .obj/qrect.o .obj/qsize.o .obj/qline.o
.obj/qstring.o .obj/qstring_compat.o .obj/qstringlist.o .obj/qvector.o
.obj/qvsnprintf.o .obj/qxmlutils.o .obj/qxmlstream.o .obj/qjson.o
.obj/qjsondocument.o .obj/qjsonobject.o .obj/qjsonarray.o .obj/qjsonvalue.o
.obj/qjsonparser.o .obj/qjsonwriter.o .obj/qdom.o .obj/qxml.o
.obj/qfilesystemengine_unix.o .obj/qfilesystemiterator_unix.o
.obj/qfsfileengine_unix.o .obj/qcoreapplication_mac.o .obj/qcore_mac.o
rm -f ../../../lib/libQt5Bootstrap.a
mv -f libQt5Bootstrap.a ../../../lib/
...
gmake[3]: Entering directory '/opt/local/var/macports/build/qt5-kde-devel/qt5-
kde-devel-x11/work/build/qtbase/src/tools/moc'
/opt/local/var/macports/build/qt5-kde-devel/qt5-kde-devel-
x11/work/build/qtbase/bin/qmake -config ltcg -o Makefile
/opt/local/var/macports/build/qt5-kde-devel/qt5-kde-devel-x11/work/qt-
everywhere-opensource-src-5.5.0/qtbase/src/tools/moc/moc.pro
...
/opt/local/bin/clang++-mp-3.6 -L/opt/local/lib -Wl,-headerpad_max_install_names
-O3 -march=core2 -g -Wl,-dead_strip -Wl,-
syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk
-stdlib=libc++ -mmacosx-version-min=10.7 -O2 -isysroot
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk
-std=c++11 -flto -fPIC -o ../../../bin/moc .obj/moc.o .obj/preprocessor.o
.obj/generator.o .obj/parser.o .obj/token.o .obj/main.o -
L/opt/local/var/macports/build/qt5-kde-devel/qt5-kde-devel-
x11/work/build/qtbase/lib -lQt5Bootstrap -framework Foundation -framework
CoreServices -lz
Post by Thiago Macieira
ld: warning: ignoring file /opt/local/var/macports/build/qt5-kde-devel/qt5-
kde-devel-x11/work/build/qtbase/lib/libQt5Bootstrap.a, file was built for
archive which is not the architecture being linked (x86_64):
/opt/local/var/macports/build/qt5-kde-devel/qt5-kde-devel-
x11/work/build/qtbase/lib/libQt5Bootstrap.a
Undefined symbols for architecture x86_64:
"QFileInfo::filePath() const", referenced from:
(followed by several pages of missing symbols)

Googling the error suggests either a missing x86_64 architecture (not the case)
or a mismatch between the linker and ar, which is obviously also not the case:

%> llvm-ar-mp-3.6 --version
LLVM (http://llvm.org/):
LLVM version 3.6.1
Optimized build.
Built Jun 24 2015 (10:49:09).
Default target: x86_64-apple-darwin13.4.0
Host CPU: corei7-avx
%> clang++-mp-3.6 --version
clang version 3.6.1 (tags/RELEASE_361/final)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

So WTH?!

R.
Continue reading on narkive:
Loading...