Project-OSRM / osrm-backend

Open Source Routing Machine - C++ backend
http://map.project-osrm.org
BSD 2-Clause "Simplified" License
6.35k stars 3.36k forks source link

LTO_AVAILABLE check failing for clang #2120

Closed springmeyer closed 7 years ago

springmeyer commented 8 years ago

Currently the -flto configure check is failing for clang++ linux builds on travis: https://travis-ci.org/Project-OSRM/osrm-backend/jobs/116873025#L1200

The way LTO works with clang on linux is:

The reason that the configure check is failing in our builds right now is that -flto is not being passed to the linking flags for the check_cxx_compiler_flag check here. And therefore the linker is not put in LTO mode for that configure check and the .o file with LTO support cannot be read. The error in the cmake logs is: CMakeFiles/cmTryCompileExec3478428907.dir/src.cxx.o: file not recognized: File format not recognized

One workaround I've found is to do export LDFLAGS="-flto" which then triggers the check_cxx_compiler_flag to use -flto in the linker flags and then the binary produced is valid and can be run. But ideally some better workaround could be found, however my knowledge of cmake is too limited to begin to know what to do.

/cc @daniel-j-h for help.

daniel-j-h commented 8 years ago

Good that you're raising this issue! Over the last weekend I compiled a freshly releases LLVM 3.8 (and then all of osrm-backend's dependencies with Clang/libc++ for ABI compatibility), and only after reading this issue checked for lto in the compilation log --- and indeed the CMake buildsystem did not activate it! Let's fix this once and for all! Here's a quick brain dump for Clang/lto:

I played around with ld.gold three month ago (but back then in combination with GCC). Updating ld so that it points to ld.goldseems like the best bet as in: https://gist.github.com/daniel-j-h/ed3bf9e5cb458b012b5a

For Clang/lto I think we also need to use the lto-aware binutils as in: http://llvm.org/docs/GoldPlugin.html#quickstart-for-using-lto-with-autotooled-projects

Setting env CXXFLAGS='-flto' LDFLAGS='-flto' is fine when the user knows what to do. The WebKit CMakeLists has some hints on how to do this programmatically: https://github.com/WebKit/webkit/blob/master/Source/cmake/OptionsCommon.cmake

The Gentoo Wiki has some notes on solving exactly that problem: https://wiki.gentoo.org/wiki/Clang

(I remember trying to rebuild my Gentoo system a few years ago when lto in GCC was still new --- didn't work out that well :P)

springmeyer commented 8 years ago

Thanks for the further thoughts @daniel-j-h. So far, via testing osrm-backend build via node-osrm, I've got LTO working with osrm-backend using the llvm-ar, llvm-nm, and llvm-ranlib. But now I'm hitting:

/home/travis/build/Project-OSRM/node-osrm/mason_packages/linux-x86_64/binutils/2.26/bin/ld: skipping incompatible /home/travis/build/Project-OSRM/node-osrm/mason_packages/.link/lib/libosrm.a when searching for -losrm

When trying to link node-osrm against libosrm.a, as it appears that the static library is not valid. My next move is to try using the ar provided by binutils-gold rather than llvm-ar as per http://llvm.org/docs/GoldPlugin.html#quickstart-for-using-lto-with-autotooled-projects. The clang-ar wrapper described at https://wiki.gentoo.org/wiki/Clang might also be onto something.

daniel-j-h commented 8 years ago

What's the last update on this? We're building binaries with Clang now by default (?); at least it's the default CXX in node-osrm. And we probably will do so in the future, due to us not being able to upgrade to gcc 5.3 on Travis. Which means, this ticket is the main blocker for getting LTO working, I assume?

danpat commented 8 years ago

@daniel-j-h I'm using GCC5.3 in https://github.com/mapbox/route-annotator/

The approach there is to create a Docker container as part of the build. Travis supports this, and it unlocks using basically any build environment you want (route-annotator is using ubuntu-16.04). It does make the build a little slower, but given that you can locally reproduce what Travis is doing, I've found I don't get any failed builds if it works on my local machine.

See: https://github.com/mapbox/route-annotator/blob/master/.travis.yml https://github.com/mapbox/route-annotator/blob/master/Dockerfile

I'm only building one combination here at the moment, but it should be trivial to create multiple Dockerfiles for different environments and use them in the Travis build matrix.

Unfortunately, there's no Docker-for-Darwin, so this only works for Linux-based builds.

TheMarex commented 8 years ago

Just a quick update here LTO is still not enabled in node-osrm, so this issue remains valid:

https://travis-ci.org/Project-OSRM/node-osrm/jobs/153318356#L849

springmeyer commented 7 years ago

Confirmed this issue is still present. Using -flto gets disabled by the CmakeLists.txt logic (on linux when building with clang++_ due to the fact that -flto is not put in the LINKER_FLAGS for the check for whether the compiler recognizes -flto. So, even though clang++ does know about the -flto option, our CMakeLists.txt logic fails to detect this because linking fails (as you would expect when an .o is lto enabled but not thing linking).

I'm working on fixing the above problem in https://github.com/Project-OSRM/osrm-backend/pull/3377.

springmeyer commented 7 years ago

This problem has now been fixed in this proposed PR: https://github.com/Project-OSRM/osrm-backend/pull/3377. Will close this one since the underlying problems are discussed and detailed at https://github.com/Project-OSRM/osrm-backend/pull/3377.