Following the recent inquiry and David Chisnall's advice, I have created a patch that makes libc++ work a lot smoother on Linux. It allows a plain "clang++ -stdlib=libc++" command line to work no matter what ABI library is used, and fixes the linking errors I encountered.
However, I have absolutely no idea what it does on other platforms. Log Message: Sort out common Linux linking issues. Using libc++ on Linux was problematic because using libsupc++ didn't pull in all necessary symbols, whereas linking against a dynamic ABI library required the user to explicitly link against the ABI library. This patch adds a new property, LIBCXX_CXX_ABI_LINK, that can be set to dynamic (the default) or static. In dynamic mode, it links against the dynamic library, and substitutes its unversioned .so file with a linker script that links against both libc++ and the ABI library. In static mode, it uses --whole-archive to force inclusion of the entire ABI library into the libc++.so. It also automatically uses libstdc++ for dynamic mode and libsupc++ for static mode if either was selected; the two ABI names are now synonyms.
diff --git a/CMakeLists.txt b/CMakeLists.txt index dd36b61..213b927 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,9 +91,8 @@ macro(setup_abi_lib abipathvar abidefines abilibs abifiles abidirs) list(APPEND LIBCXX_CXX_FEATURE_FLAGS ${abidefines}) set(${abipathvar} "${${abipathvar}}" CACHE STRINGS - "Paths to ABI include directories separate by ';'." + "Paths to ABI include directories separated by ';'." ) - set(LIBCXX_CXX_ABI_LIBRARIES ${abilibs}) set(LIBCXX_ABILIB_FILES ${abifiles}) file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include") foreach(_d ${abidirs}) @@ -131,6 +130,29 @@ macro(setup_abi_lib abipathvar abidefines abilibs abifiles abidirs) FILES_MATCHING PATTERN "*" ) + set(LIBCXX_ABILIB_FINAL_LIBRARIES + "${CMAKE_INSTALL_PREFIX}/lib/libc++.so.1.0") + if ("${LIBCXX_CXX_ABI_LINK}" STREQUAL "static") + # Force linker to look for static libraries only and make it include + # the entire library into the result. + list(APPEND link_flags "-Wl,-Bstatic" "-Wl,--whole-archive") + foreach(abilib ${abilibs}) + list(APPEND link_flags "-l${abilib}") + endforeach() + # Disable the previous linker flags again. + list(APPEND link_flags "-Wl,--no-whole-archive" "-Wl,-Bdynamic") + else() + set(LIBCXX_CXX_ABI_LIBRARIES ${abilibs}) + foreach(abilib ${abilibs}) + list(APPEND LIBCXX_ABILIB_FINAL_LIBRARIES "-l${abilib}") + endforeach() + endif() + string(REPLACE ";" " " LIBCXX_ABILIB_FINAL_LIBRARIES "${LIBCXX_ABILIB_FINAL_LIBRARIES}") + configure_file(libc++.ldscript lib/libc++.ldscript) + install(FILES "${CMAKE_BINARY_DIR}/lib/libc++.ldscript" + DESTINATION lib + RENAME libc++.so + ) endmacro() if ("${LIBCXX_CXX_ABI}" STREQUAL "libstdc++" OR @@ -139,12 +161,12 @@ if ("${LIBCXX_CXX_ABI}" STREQUAL "libstdc++" OR cxxabi.h bits/c++config.h bits/os_defines.h bits/cpu_defines.h bits/cxxabi_tweaks.h bits/cxxabi_forced.h ) - if ("${LIBCXX_CXX_ABI}" STREQUAL "libstdc++") - set(_LIBSUPCXX_DEFINES "-DLIBSTDCXX") - set(_LIBSUPCXX_LIBNAME stdc++) - else() + if ("${LIBCXX_CXX_ABI_LINK}" STREQUAL "static") set(_LIBSUPCXX_DEFINES "") set(_LIBSUPCXX_LIBNAME supc++) + else() + set(_LIBSUPCXX_DEFINES "-DLIBSTDCXX") + set(_LIBSUPCXX_LIBNAME stdc++) endif() setup_abi_lib("LIBCXX_LIBSUPCXX_INCLUDE_PATHS" "-D__GLIBCXX__ ${_LIBSUPCXX_DEFINES}" diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index cec0bee..58bfa67 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -96,6 +96,6 @@ set_target_properties(cxx ) install(TARGETS cxx - LIBRARY DESTINATION lib + LIBRARY DESTINATION lib NAMELINK_SKIP ARCHIVE DESTINATION lib ) diff --git a/libc++.ldscript b/libc++.ldscript new file mode 100644 index 0000000..362040e --- /dev/null +++ b/libc++.ldscript @@ -0,0 +1 @@ +INPUT ( ${LIBCXX_ABILIB_FINAL_LIBRARIES} ) diff --git a/www/index.html b/www/index.html index 02470ea..7a9b94b 100644 --- a/www/index.html +++ b/www/index.html @@ -208,21 +208,26 @@ against it with <code>-fno-rtti</code> is supported. (<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev">clang mailing list</a>).</p> <!--=====================================================================--> - <h2>Build on Linux using CMake and libsupc++.</h2> + <h2>Build on Linux using CMake.</h2> <!--=====================================================================--> <p> - You will need libstdc++ in order to provide libsupc++. - </p> - + When building on Linux, you need a library that provides the C++ ABI + routines. Your choices are libsupc++, libc++abi, and libcxxrt. + <p> + + <!--=====================================================================--> + <h3>Using libsupc++.</h3> + <!--=====================================================================--> + <p> - Figure out where the libsupc++ headers are on your system. On Ubuntu this - is <code>/usr/include/c++/<version></code> and - <code>/usr/include/c++/<version>/<target-triple></code> + You will need libstdc++ in order to provide libsupc++. </p> - + <p> - You can also figure this out by running + Figure out where the libsupc++ headers are on your system. Since this + changes a lot between distributions and versions, the best way of doing + this is asking GCC. You do this by running <pre> $ echo | g++ -Wp,-v -x c++ - -fsyntax-only ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" @@ -241,25 +246,31 @@ End of search list. </pre> Note the first two entries happen to be what we are looking for. This - may not be correct on other platforms. + may not be correct on other platforms. There will usually be two + directories with "c++" in the path, one for platform-independent parts and + one for platform-dependent parts which includes the target triple. You can + ignore the backward directory. </p> - + <p> We can now run CMake: <ul> <li><code>CC=clang CXX=clang++ cmake -G "Unix Makefiles" - -DLIBCXX_CXX_ABI=libstdc++ + -DLIBCXX_CXX_ABI=libsupc++ + -DLIBCXX_CXX_ABI_LINK=dynamic -DLIBCXX_LIBSUPCXX_INCLUDE_PATHS="/usr/include/c++/4.7/;/usr/include/c++/4.7/x86_64-linux-gnu/" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr <libc++-source-dir></code></li> - <li>You can also substitute <code>-DLIBCXX_CXX_ABI=libsupc++</code> - above, which will cause the library to be linked to libsupc++ instead - of libstdc++, but this is only recommended if you know that you will - never need to link against libstdc++ in the same executable as libc++. - GCC ships libsupc++ separately but only as a static library. If a - program also needs to link against libstdc++, it will provide its - own copy of libsupc++ and this can lead to subtle problems. + <li>The install prefix should be the same as for your Clang installation, + as Clang looks for the libc++ headers relative to its own location.</li> + <li>You can also substitute <code>-DLIBCXX_CXX_ABI_LINK=static</code> + above, which will cause the library to be linked statically to libsupc++ + instead of dynamically to libstdc++, but this is only recommended if you + know that you will never need to link against libstdc++ in the same + executable as libc++. GCC ships libsupc++ separately but only as a static + library. If a program also needs to link against libstdc++, it will + provide its own copy of libsupc++ and this can lead to subtle problems. <li><code>make</code></li> <li><code>sudo make install</code></li> </ul> @@ -269,7 +280,7 @@ End of search list. </p> <!--=====================================================================--> - <h2>Build on Linux using CMake and libc++abi.</h2> + <h3>Using libc++abi.</h3> <!--=====================================================================--> <p> @@ -283,37 +294,30 @@ End of search list. <ul> <li><code>CC=clang CXX=clang++ cmake -G "Unix Makefiles" -DLIBCXX_CXX_ABI=libcxxabi + -DLIBCXX_CXX_ABI_LINK=dynamic -DLIBCXX_LIBCXXABI_INCLUDE_PATHS="<libc++abi-source-dir>/include" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr <libc++-source-dir></code></li> + <li>The install prefix should be the same as for your Clang installation, + as Clang looks for the libc++ headers relative to its own location.</li> <li><code>make</code></li> <li><code>sudo make install</code></li> </ul> <p> - Unfortunately you can't simply run clang with "-stdlib=libc++" at this point, as - clang is set up to link for libc++ linked to libsupc++. To get around this - you'll have to set up your linker yourself (or patch clang). For example, - <ul> - <li><code>clang++ -stdlib=libc++ helloworld.cpp -nodefaultlibs -lc++ -lc++abi -lm -lc -lgcc_s -lgcc</code></li> - </ul> - Alternately, you could just add libc++abi to your libraries list, which in most - situations will give the same result: - <ul> - <li><code>clang++ -stdlib=libc++ helloworld.cpp -lc++abi</code></li> - </ul> + You can now run clang with -stdlib=libc++. </p> </p> <!--=====================================================================--> - <h2>Build on Linux using CMake and libcxxrt.</h2> + <h3>Using libcxxrt.</h3> <!--=====================================================================--> <p> You will need to keep the source tree of <a href="https://github.com/pathscale/libcxxrt/">libcxxrt</a> available - on your build machine and your copy of the libcxxrt shared library must - be placed where your linker will find it. + on your build machine and your copy of the libcxxrt shared or static + (see below) library must be placed where your linker will find it. </p> <p> @@ -321,25 +325,23 @@ End of search list. <ul> <li><code>CC=clang CXX=clang++ cmake -G "Unix Makefiles" -DLIBCXX_CXX_ABI=libcxxrt + -DLIBCXX_CXX_ABI_LINK=dynamic -DLIBCXX_LIBCXXRT_INCLUDE_PATHS="<libcxxrt-source-dir>/src" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr <libc++-source-dir></code></li> + <li>The install prefix should be the same as for your Clang installation, + as Clang looks for the libc++ headers relative to its own location.</li> + <li>The default method needs the shared version of libcxxrt. You can also + substitute <code>-DLIBCXX_CXX_ABI_LINK=static</code> to link against the + static version instead; however, this requires the static library to be + built as position-independent code, which it is not if you use their + build system without changes.</li> <li><code>make</code></li> <li><code>sudo make install</code></li> </ul> <p> - Unfortunately you can't simply run clang with "-stdlib=libc++" at this point, as - clang is set up to link for libc++ linked to libsupc++. To get around this - you'll have to set up your linker yourself (or patch clang). For example, - <ul> - <li><code>clang++ -stdlib=libc++ helloworld.cpp -nodefaultlibs -lc++ -lcxxrt -lm -lc -lgcc_s -lgcc</code></li> - </ul> - Alternately, you could just add libcxxrt to your libraries list, which in most - situations will give the same result: - <ul> - <li><code>clang++ -stdlib=libc++ helloworld.cpp -lcxxrt</code></li> - </ul> + You can now run clang with -stdlib=libc++. </p> </p>
_______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits