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
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits