[libcxx] Add support for building and testing with an ABI library not along linker paths
Summary: This patch adds support for building/testing libc++ with an ABI library that the linker would not normally find. - `CMAKE_LIBRARY_PATH` is used to specify the list of search directories. - The ABI library is now found using `find_library` instead of assuming its along the linker's search path. - `CMAKE_LIBRARY_PATH` is passed to our LIT config as `library_paths`. - For each path in `library_paths` the following flags are added `-L<path> -Wl,-rpath -Wl,<path>` Some changes in existing behavior were also added: - `target_link_libraries` is now passed the ABI library file instead of the library name. Ex `target_link_libraries(cxx "/usr/lib/libc++abi.so")` vs `target_link_libraries(cxx "c++abi")`. - `-Wl,-rpath -Wl,<path>` is now used on OSX to link to libc++ instead of env['DYLD_LIBRARY_PATH'] if `use_system_lib=False`. Reviewers: mclow.lists, danalbert, EricWF Reviewed By: EricWF Subscribers: emaste, cfe-commits Differential Revision: http://reviews.llvm.org/D5038 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@220118 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
950ee77d24
commit
9071bc098b
@ -84,104 +84,11 @@ get_target_triple(LIBCXX_TARGET_TRIPLE
|
|||||||
)
|
)
|
||||||
set(LIBCXX_TARGET_TRIPLE ${LIBCXX_TARGET_TRIPLE} CACHE STRING "Target triple.")
|
set(LIBCXX_TARGET_TRIPLE ${LIBCXX_TARGET_TRIPLE} CACHE STRING "Target triple.")
|
||||||
|
|
||||||
#===============================================================================
|
|
||||||
# Add an ABI library if appropriate
|
|
||||||
#===============================================================================
|
|
||||||
|
|
||||||
#
|
|
||||||
# _setup_abi: Set up the build to use an ABI library
|
|
||||||
#
|
|
||||||
# Parameters:
|
|
||||||
# abidefines: A list of defines needed to compile libc++ with the ABI library
|
|
||||||
# abilibs : A list of libraries to link against
|
|
||||||
# abifiles : A list of files (which may be relative paths) to copy into the
|
|
||||||
# libc++ build tree for the build. These files will also be
|
|
||||||
# installed alongside the libc++ headers.
|
|
||||||
# abidirs : A list of relative paths to create under an include directory
|
|
||||||
# in the libc++ build directory.
|
|
||||||
#
|
|
||||||
macro(setup_abi_lib abipathvar abidefines abilibs abifiles abidirs)
|
|
||||||
list(APPEND LIBCXX_CXX_FEATURE_FLAGS ${abidefines})
|
|
||||||
set(${abipathvar} "${${abipathvar}}"
|
|
||||||
CACHE PATH
|
|
||||||
"Paths to C++ ABI header directories separated by ';'." FORCE
|
|
||||||
)
|
|
||||||
set(LIBCXX_CXX_ABI_LIBRARIES ${abilibs})
|
|
||||||
set(LIBCXX_ABILIB_FILES ${abifiles})
|
|
||||||
|
|
||||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include")
|
|
||||||
foreach(_d ${abidirs})
|
|
||||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/${_d}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(fpath ${LIBCXX_ABILIB_FILES})
|
|
||||||
set(found FALSE)
|
|
||||||
foreach(incpath ${${abipathvar}})
|
|
||||||
if (EXISTS "${incpath}/${fpath}")
|
|
||||||
set(found TRUE)
|
|
||||||
get_filename_component(dstdir ${fpath} PATH)
|
|
||||||
get_filename_component(ifile ${fpath} NAME)
|
|
||||||
file(COPY "${incpath}/${fpath}"
|
|
||||||
DESTINATION "${CMAKE_BINARY_DIR}/include/${dstdir}"
|
|
||||||
)
|
|
||||||
install(FILES "${CMAKE_BINARY_DIR}/include/${fpath}"
|
|
||||||
DESTINATION include/c++/v1/${dstdir}
|
|
||||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
|
||||||
)
|
|
||||||
list(APPEND abilib_headers "${CMAKE_BINARY_DIR}/include/${fpath}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
if (NOT found)
|
|
||||||
message(FATAL_ERROR "Failed to find ${fpath}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
add_custom_target(LIBCXX_CXX_ABI_DEPS DEPENDS ${abilib_headers})
|
|
||||||
include_directories("${CMAKE_BINARY_DIR}/include")
|
|
||||||
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR
|
|
||||||
"${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libsupc++")
|
|
||||||
set(_LIBSUPCXX_INCLUDE_FILES
|
|
||||||
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_LIBNAME}" STREQUAL "libstdc++")
|
|
||||||
set(_LIBSUPCXX_DEFINES "-DLIBSTDCXX")
|
|
||||||
set(_LIBSUPCXX_LIBNAME stdc++)
|
|
||||||
else()
|
|
||||||
set(_LIBSUPCXX_DEFINES "")
|
|
||||||
set(_LIBSUPCXX_LIBNAME supc++)
|
|
||||||
endif()
|
|
||||||
setup_abi_lib("LIBCXX_LIBSUPCXX_INCLUDE_PATHS"
|
|
||||||
"-D__GLIBCXX__ ${_LIBSUPCXX_DEFINES}"
|
|
||||||
"${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_INCLUDE_FILES}" "bits"
|
|
||||||
)
|
|
||||||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi")
|
|
||||||
if (LIBCXX_CXX_ABI_INTREE)
|
|
||||||
# Link against just-built "cxxabi" target.
|
|
||||||
set(CXXABI_LIBNAME cxxabi)
|
|
||||||
else()
|
|
||||||
# Assume c++abi is installed in the system, rely on -lc++abi link flag.
|
|
||||||
set(CXXABI_LIBNAME "c++abi")
|
|
||||||
endif()
|
|
||||||
setup_abi_lib("LIBCXX_LIBCXXABI_INCLUDE_PATHS" ""
|
|
||||||
${CXXABI_LIBNAME} "cxxabi.h" ""
|
|
||||||
)
|
|
||||||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt")
|
|
||||||
setup_abi_lib("LIBCXX_LIBCXXRT_INCLUDE_PATHS" "-DLIBCXXRT"
|
|
||||||
"cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" ""
|
|
||||||
)
|
|
||||||
elseif (NOT "${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "none")
|
|
||||||
message(FATAL_ERROR
|
|
||||||
"Currently libstdc++, libsupc++, libcxxabi, libcxxrt and none are "
|
|
||||||
"supported for c++ abi."
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Configure compiler.
|
# Configure compiler.
|
||||||
include(config-ix)
|
include(config-ix)
|
||||||
|
# Configure ABI library
|
||||||
|
include(HandleLibCXXABI)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# Setup Compiler Flags
|
# Setup Compiler Flags
|
||||||
|
111
cmake/Modules/HandleLibCXXABI.cmake
Normal file
111
cmake/Modules/HandleLibCXXABI.cmake
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
# Add an ABI library if appropriate
|
||||||
|
#===============================================================================
|
||||||
|
|
||||||
|
#
|
||||||
|
# _setup_abi: Set up the build to use an ABI library
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# abidefines: A list of defines needed to compile libc++ with the ABI library
|
||||||
|
# abilibs : A list of libraries to link against
|
||||||
|
# abifiles : A list of files (which may be relative paths) to copy into the
|
||||||
|
# libc++ build tree for the build. These files will also be
|
||||||
|
# installed alongside the libc++ headers.
|
||||||
|
# abidirs : A list of relative paths to create under an include directory
|
||||||
|
# in the libc++ build directory.
|
||||||
|
#
|
||||||
|
macro(setup_abi_lib abipathvar abidefines abilibs abifiles abidirs)
|
||||||
|
list(APPEND LIBCXX_CXX_FEATURE_FLAGS ${abidefines})
|
||||||
|
set(${abipathvar} "${${abipathvar}}"
|
||||||
|
CACHE PATH
|
||||||
|
"Paths to C++ ABI header directories separated by ';'." FORCE
|
||||||
|
)
|
||||||
|
|
||||||
|
# To allow for libraries installed along non-default paths we use find_library
|
||||||
|
# to locate the ABI libraries we want. Making sure to clean the cache before
|
||||||
|
# each run of find_library.
|
||||||
|
set(LIBCXX_CXX_ABI_LIBRARIES "")
|
||||||
|
foreach(alib ${abilibs})
|
||||||
|
unset(_Res CACHE)
|
||||||
|
find_library(_Res ${alib})
|
||||||
|
if (${_Res} STREQUAL "_Res-NOTFOUND")
|
||||||
|
message(FATAL_ERROR "Failed to find ABI library: ${alib}")
|
||||||
|
else()
|
||||||
|
message(STATUS "Adding ABI library: ${_Res}")
|
||||||
|
list(APPEND LIBCXX_CXX_ABI_LIBRARIES ${_Res})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(LIBCXX_ABILIB_FILES ${abifiles})
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include")
|
||||||
|
foreach(_d ${abidirs})
|
||||||
|
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/${_d}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
foreach(fpath ${LIBCXX_ABILIB_FILES})
|
||||||
|
set(found FALSE)
|
||||||
|
foreach(incpath ${${abipathvar}})
|
||||||
|
if (EXISTS "${incpath}/${fpath}")
|
||||||
|
set(found TRUE)
|
||||||
|
get_filename_component(dstdir ${fpath} PATH)
|
||||||
|
get_filename_component(ifile ${fpath} NAME)
|
||||||
|
file(COPY "${incpath}/${fpath}"
|
||||||
|
DESTINATION "${CMAKE_BINARY_DIR}/include/${dstdir}"
|
||||||
|
)
|
||||||
|
install(FILES "${CMAKE_BINARY_DIR}/include/${fpath}"
|
||||||
|
DESTINATION include/c++/v1/${dstdir}
|
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||||
|
)
|
||||||
|
list(APPEND abilib_headers "${CMAKE_BINARY_DIR}/include/${fpath}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
if (NOT found)
|
||||||
|
message(FATAL_ERROR "Failed to find ${fpath}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_custom_target(LIBCXX_CXX_ABI_DEPS DEPENDS ${abilib_headers})
|
||||||
|
include_directories("${CMAKE_BINARY_DIR}/include")
|
||||||
|
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR
|
||||||
|
"${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libsupc++")
|
||||||
|
set(_LIBSUPCXX_INCLUDE_FILES
|
||||||
|
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_LIBNAME}" STREQUAL "libstdc++")
|
||||||
|
set(_LIBSUPCXX_DEFINES "-DLIBSTDCXX")
|
||||||
|
set(_LIBSUPCXX_LIBNAME stdc++)
|
||||||
|
else()
|
||||||
|
set(_LIBSUPCXX_DEFINES "")
|
||||||
|
set(_LIBSUPCXX_LIBNAME supc++)
|
||||||
|
endif()
|
||||||
|
setup_abi_lib("LIBCXX_LIBSUPCXX_INCLUDE_PATHS"
|
||||||
|
"-D__GLIBCXX__ ${_LIBSUPCXX_DEFINES}"
|
||||||
|
"${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_INCLUDE_FILES}" "bits"
|
||||||
|
)
|
||||||
|
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi")
|
||||||
|
if (LIBCXX_CXX_ABI_INTREE)
|
||||||
|
# Link against just-built "cxxabi" target.
|
||||||
|
set(CXXABI_LIBNAME cxxabi)
|
||||||
|
else()
|
||||||
|
# Assume c++abi is installed in the system, rely on -lc++abi link flag.
|
||||||
|
set(CXXABI_LIBNAME "c++abi")
|
||||||
|
endif()
|
||||||
|
setup_abi_lib("LIBCXX_LIBCXXABI_INCLUDE_PATHS" ""
|
||||||
|
${CXXABI_LIBNAME} "cxxabi.h" ""
|
||||||
|
)
|
||||||
|
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt")
|
||||||
|
setup_abi_lib("LIBCXX_LIBCXXRT_INCLUDE_PATHS" "-DLIBCXXRT"
|
||||||
|
"cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" ""
|
||||||
|
)
|
||||||
|
elseif (NOT "${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "none")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Currently libstdc++, libsupc++, libcxxabi, libcxxrt and none are "
|
||||||
|
"supported for c++ abi."
|
||||||
|
)
|
||||||
|
endif ()
|
27
test/lit.cfg
27
test/lit.cfg
@ -197,6 +197,7 @@ class Configuration(object):
|
|||||||
self.obj_root = None
|
self.obj_root = None
|
||||||
self.env = {}
|
self.env = {}
|
||||||
self.compile_flags = []
|
self.compile_flags = []
|
||||||
|
self.library_paths = []
|
||||||
self.link_flags = []
|
self.link_flags = []
|
||||||
self.use_system_lib = False
|
self.use_system_lib = False
|
||||||
self.use_clang_verify = False
|
self.use_clang_verify = False
|
||||||
@ -366,9 +367,19 @@ class Configuration(object):
|
|||||||
# Configure extra compiler flags.
|
# Configure extra compiler flags.
|
||||||
self.compile_flags += ['-I' + self.src_root + '/include',
|
self.compile_flags += ['-I' + self.src_root + '/include',
|
||||||
'-I' + self.src_root + '/test/support']
|
'-I' + self.src_root + '/test/support']
|
||||||
|
if sys.platform == 'linux2':
|
||||||
|
self.compile_flags += ['-D__STDC_FORMAT_MACROS',
|
||||||
|
'-D__STDC_LIMIT_MACROS',
|
||||||
|
'-D__STDC_CONSTANT_MACROS']
|
||||||
|
|
||||||
def configure_link_flags(self):
|
def configure_link_flags(self):
|
||||||
self.link_flags += ['-L' + self.obj_root + '/lib', '-lc++']
|
# Configure library search paths
|
||||||
|
lpaths = self.get_lit_conf('library_paths', '').split(';')
|
||||||
|
lpaths = [l for l in lpaths if l.strip()]
|
||||||
|
self.link_flags += ['-L' + self.obj_root + '/lib']
|
||||||
|
self.link_flags += ['-L' + l for l in lpaths]
|
||||||
|
# Configure libraries
|
||||||
|
self.link_flags += ['-lc++']
|
||||||
link_flags_str = self.get_lit_conf('link_flags')
|
link_flags_str = self.get_lit_conf('link_flags')
|
||||||
if link_flags_str is None:
|
if link_flags_str is None:
|
||||||
cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
|
cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
|
||||||
@ -394,22 +405,18 @@ class Configuration(object):
|
|||||||
elif sys.platform.startswith('freebsd'):
|
elif sys.platform.startswith('freebsd'):
|
||||||
self.link_flags += ['-lc', '-lm', '-pthread', '-lgcc_s']
|
self.link_flags += ['-lc', '-lm', '-pthread', '-lgcc_s']
|
||||||
else:
|
else:
|
||||||
self.lit_config.fatal("unrecognized system")
|
self.lit_config.fatal("unrecognized system: %r" % sys.platform)
|
||||||
|
|
||||||
self.lit_config.note(
|
self.lit_config.note(
|
||||||
"inferred link_flags as: %r" % self.link_flags)
|
"inferred link_flags as: %r" % self.link_flags)
|
||||||
if link_flags_str:
|
if link_flags_str:
|
||||||
self.link_flags += shlex.split(link_flags_str)
|
self.link_flags += shlex.split(link_flags_str)
|
||||||
|
|
||||||
if sys.platform == 'linux2':
|
# Configure library runtime search paths
|
||||||
if not self.use_system_lib:
|
if not self.use_system_lib:
|
||||||
self.link_flags += ['-Wl,-R', self.obj_root + '/lib']
|
self.link_flags += ['-Wl,-rpath', '-Wl,' + self.obj_root + '/lib']
|
||||||
self.compile_flags += ['-D__STDC_FORMAT_MACROS',
|
for l in lpaths:
|
||||||
'-D__STDC_LIMIT_MACROS',
|
self.link_flags += ['-Wl,-rpath', '-Wl,' + l]
|
||||||
'-D__STDC_CONSTANT_MACROS']
|
|
||||||
elif sys.platform.startswith('freebsd'):
|
|
||||||
if not self.use_system_lib:
|
|
||||||
self.link_flags += ['-Wl,-R', self.obj_root + '/lib']
|
|
||||||
|
|
||||||
def configure_std_flag(self):
|
def configure_std_flag(self):
|
||||||
# Try and get the std version from the command line. Fall back to
|
# Try and get the std version from the command line. Fall back to
|
||||||
|
@ -7,6 +7,7 @@ config.python_executable = "@PYTHON_EXECUTABLE@"
|
|||||||
config.enable_shared = @LIBCXX_ENABLE_SHARED@
|
config.enable_shared = @LIBCXX_ENABLE_SHARED@
|
||||||
config.cxx_abi = "@LIBCXX_CXX_ABI_LIBNAME@"
|
config.cxx_abi = "@LIBCXX_CXX_ABI_LIBNAME@"
|
||||||
config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
|
config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
|
||||||
|
config.library_paths = "@CMAKE_LIBRARY_PATH@"
|
||||||
|
|
||||||
# Let the main config do the real work.
|
# Let the main config do the real work.
|
||||||
lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/test/lit.cfg")
|
lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/test/lit.cfg")
|
||||||
|
@ -436,6 +436,36 @@ End of search list.
|
|||||||
</p>
|
</p>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!--=====================================================================-->
|
||||||
|
<h2 id="local-abi">Using a local ABI library</h2>
|
||||||
|
<!--=====================================================================-->
|
||||||
|
<p>
|
||||||
|
<strong>Note: This is not recommended in almost all cases.</strong><br>
|
||||||
|
Generally these instructions should only be used when you can't install
|
||||||
|
your ABI library.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Normally you must link libc++ against a ABI shared library that the
|
||||||
|
linker can find. If you want to build and test libc++ against an ABI
|
||||||
|
library not in the linker's path you need to set
|
||||||
|
<code>-DCMAKE_LIBRARY_PATH=/path/to/abi/lib</code> when configuring CMake.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
An example build using libc++abi would look like:
|
||||||
|
<ul>
|
||||||
|
<li><code>CC=clang CXX=clang++ cmake
|
||||||
|
-DLIBCXX_CXX_ABI=libc++abi
|
||||||
|
-DLIBCXX_LIBCXXABI_INCLUDE_PATHS="/path/to/libcxxabi/include"
|
||||||
|
-DCMAKE_LIBRARY_PATH="/path/to/libcxxabi-build/lib"
|
||||||
|
path/to/libcxx</code></li>
|
||||||
|
<li><code>make</code></li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
When testing libc++ LIT will automatically link against the proper ABI
|
||||||
|
library.
|
||||||
|
</p>
|
||||||
|
|
||||||
<!--=====================================================================-->
|
<!--=====================================================================-->
|
||||||
<h2>Design Documents</h2>
|
<h2>Design Documents</h2>
|
||||||
<!--=====================================================================-->
|
<!--=====================================================================-->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user