[runtimes] Introduce object libraries

This is a variant of D116689 rebased on top of the new (proposed) ABI
refactoring in D120727. It should conserve the basic properties of the
original patch by @phosek, except it also allows cleaning up the merging
of libc++abi into libc++ from the libc++ side.

Differential Revision: https://reviews.llvm.org/D125393
This commit is contained in:
Louis Dionne 2022-05-11 11:06:28 -04:00
parent 80bebbc7cb
commit aa656f6c2d
7 changed files with 159 additions and 293 deletions

View File

@ -6,6 +6,14 @@
# headers of the selected ABI library. # headers of the selected ABI library.
# - libcxx-abi-shared: A target representing the selected shared ABI library. # - libcxx-abi-shared: A target representing the selected shared ABI library.
# - libcxx-abi-static: A target representing the selected static ABI library. # - libcxx-abi-static: A target representing the selected static ABI library.
#
# Furthermore, some ABI libraries also define the following target:
# - libcxx-abi-shared-objects: An object library representing a set of object files
# constituting the ABI library, suitable for bundling
# into a shared library.
# - libcxx-abi-static-objects: An object library representing a set of object files
# constituting the ABI library, suitable for bundling
# into a static library.
#=============================================================================== #===============================================================================
include(GNUInstallDirs) include(GNUInstallDirs)
@ -111,6 +119,14 @@ elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libcxxabi")
add_library(libcxx-abi-static ALIAS cxxabi_static) add_library(libcxx-abi-static ALIAS cxxabi_static)
endif() endif()
if (TARGET cxxabi_shared_objects)
add_library(libcxx-abi-shared-objects ALIAS cxxabi_shared_objects)
endif()
if (TARGET cxxabi_static_objects)
add_library(libcxx-abi-static-objects ALIAS cxxabi_static_objects)
endif()
# Link against a system-provided libc++abi # Link against a system-provided libc++abi
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "system-libcxxabi") elseif ("${LIBCXX_CXX_ABI}" STREQUAL "system-libcxxabi")
add_library(libcxx-abi-headers INTERFACE) add_library(libcxx-abi-headers INTERFACE)

View File

@ -219,6 +219,9 @@ if (LIBCXX_ENABLE_SHARED)
cxx_set_common_defines(cxx_shared) cxx_set_common_defines(cxx_shared)
# Link against LLVM libunwind # Link against LLVM libunwind
# Note that we do need to link against libunwind directly to ensure that the correct
# dependencies are recorded when creating a linker script.
# TODO: Look into modifying the linker script creation to recursively consider interface libraries
if (LIBCXXABI_USE_LLVM_UNWINDER) if (LIBCXXABI_USE_LLVM_UNWINDER)
if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND)) if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
target_link_libraries(cxx_shared PUBLIC unwind_shared) target_link_libraries(cxx_shared PUBLIC unwind_shared)
@ -231,11 +234,7 @@ if (LIBCXX_ENABLE_SHARED)
# Link against libc++abi # Link against libc++abi
if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY) if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY)
if (APPLE) target_link_libraries(cxx_shared PRIVATE libcxx-abi-shared-objects)
target_link_libraries(cxx_shared PRIVATE "-Wl,-force_load" "$<TARGET_LINKER_FILE:libcxx-abi-static>")
else()
target_link_libraries(cxx_shared PRIVATE "-Wl,--whole-archive,-Bstatic" "$<TARGET_LINKER_FILE:libcxx-abi-static>" "-Wl,-Bdynamic,--no-whole-archive")
endif()
else() else()
target_link_libraries(cxx_shared PUBLIC libcxx-abi-shared) target_link_libraries(cxx_shared PUBLIC libcxx-abi-shared)
endif() endif()
@ -293,13 +292,6 @@ if (LIBCXX_ENABLE_STATIC)
cxx_add_common_build_flags(cxx_static) cxx_add_common_build_flags(cxx_static)
cxx_set_common_defines(cxx_static) cxx_set_common_defines(cxx_static)
if (LIBCXXABI_USE_LLVM_UNWINDER)
# If we intend to use the just-built unwinder, add a dependency so that it
# gets built, even if we technically aren't going to link it in at this
# stage.
add_dependencies(cxx_static unwind)
endif()
if (LIBCXX_HERMETIC_STATIC_LIBRARY) if (LIBCXX_HERMETIC_STATIC_LIBRARY)
# If the hermetic library doesn't define the operator new/delete functions # If the hermetic library doesn't define the operator new/delete functions
# then its code shouldn't declare them with hidden visibility. They might # then its code shouldn't declare them with hidden visibility. They might
@ -314,22 +306,7 @@ if (LIBCXX_ENABLE_STATIC)
list(APPEND LIBCXX_BUILD_TARGETS "cxx_static") list(APPEND LIBCXX_BUILD_TARGETS "cxx_static")
# Attempt to merge the libc++.a archive and the ABI library archive into one. # Attempt to merge the libc++.a archive and the ABI library archive into one.
if (LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY) if (LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY)
if (APPLE) target_link_libraries(cxx_static PRIVATE libcxx-abi-static-objects)
set(MERGE_ARCHIVES_LIBTOOL "--use-libtool" "--libtool" "${CMAKE_LIBTOOL}")
endif()
add_custom_command(TARGET cxx_static POST_BUILD
COMMAND
${Python3_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/merge_archives.py
ARGS
-o $<TARGET_LINKER_FILE:cxx_static>
--ar "${CMAKE_AR}"
${MERGE_ARCHIVES_LIBTOOL}
"$<TARGET_LINKER_FILE:cxx_static>"
"$<TARGET_LINKER_FILE:libcxx-abi-static>"
""
WORKING_DIRECTORY ${LIBCXX_BUILD_DIR}
DEPENDS ${MERGE_ARCHIVES_ABI_TARGET}
)
endif() endif()
endif() endif()

View File

@ -1,153 +0,0 @@
#!/usr/bin/env python
#===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===----------------------------------------------------------------------===##
from argparse import ArgumentParser
import distutils.spawn
import tempfile
import os
import shutil
import subprocess
import signal
import sys
temp_directory_root = None
def exit_with_cleanups(status):
if temp_directory_root is not None:
shutil.rmtree(temp_directory_root)
sys.exit(status)
def print_and_exit(msg):
sys.stderr.write(msg + '\n')
exit_with_cleanups(1)
def find_and_diagnose_missing(lib, search_paths):
if os.path.exists(lib):
return os.path.abspath(lib)
if not lib.startswith('lib') or not lib.endswith('.a'):
print_and_exit(("input file '%s' not not name a static library. "
"It should start with 'lib' and end with '.a") % lib)
for sp in search_paths:
assert type(sp) is list and len(sp) == 1
path = os.path.join(sp[0], lib)
if os.path.exists(path):
return os.path.abspath(path)
print_and_exit("input '%s' does not exist" % lib)
def execute_command(cmd, cwd=None):
"""
Execute a command, capture and return its output.
"""
kwargs = {
'stdin': subprocess.PIPE,
'stdout': subprocess.PIPE,
'stderr': subprocess.PIPE,
'cwd': cwd,
'universal_newlines': True
}
p = subprocess.Popen(cmd, **kwargs)
out, err = p.communicate()
exitCode = p.wait()
if exitCode == -signal.SIGINT:
raise KeyboardInterrupt
return out, err, exitCode
def execute_command_verbose(cmd, cwd=None, verbose=False):
"""
Execute a command and print its output on failure.
"""
out, err, exitCode = execute_command(cmd, cwd=cwd)
if exitCode != 0 or verbose:
report = "Command: %s\n" % ' '.join(["'%s'" % a for a in cmd])
if exitCode != 0:
report += "Exit Code: %d\n" % exitCode
if out:
report += "Standard Output:\n--\n%s--" % out
if err:
report += "Standard Error:\n--\n%s--" % err
if exitCode != 0:
report += "\n\nFailed!"
sys.stderr.write('%s\n' % report)
if exitCode != 0:
exit_with_cleanups(exitCode)
return out
def main():
parser = ArgumentParser(
description="Merge multiple archives into a single library")
parser.add_argument(
'-v', '--verbose', dest='verbose', action='store_true', default=False)
parser.add_argument(
'-o', '--output', dest='output', required=True,
help='The output file. stdout is used if not given',
type=str, action='store')
parser.add_argument(
'-L', dest='search_paths',
help='Paths to search for the libraries along', action='append',
nargs=1, default=[])
parser.add_argument(
'--ar', dest='ar_exe', required=False,
help='The ar executable to use, finds \'ar\' in the path if not given',
type=str, action='store')
parser.add_argument(
'--use-libtool', dest='use_libtool', action='store_true', default=False)
parser.add_argument(
'--libtool', dest='libtool_exe', required=False,
help='The libtool executable to use, finds \'libtool\' in the path if not given',
type=str, action='store')
parser.add_argument(
'archives', metavar='archives', nargs='+',
help='The archives to merge')
args = parser.parse_args()
ar_exe = args.ar_exe
if not ar_exe:
ar_exe = distutils.spawn.find_executable('ar')
if not ar_exe:
print_and_exit("failed to find 'ar' executable")
if args.use_libtool:
libtool_exe = args.libtool_exe
if not libtool_exe:
libtool_exe = distutils.spawn.find_executable('libtool')
if not libtool_exe:
print_and_exit("failed to find 'libtool' executable")
if len(args.archives) < 2:
print_and_exit('fewer than 2 inputs provided')
archives = [find_and_diagnose_missing(ar, args.search_paths)
for ar in args.archives]
print ('Merging archives: %s' % archives)
if not os.path.exists(os.path.dirname(args.output)):
print_and_exit("output path doesn't exist: '%s'" % args.output)
global temp_directory_root
temp_directory_root = tempfile.mkdtemp('.libcxx.merge.archives')
files = []
for arc in archives:
execute_command_verbose([ar_exe, 'x', arc],
cwd=temp_directory_root, verbose=args.verbose)
out = execute_command_verbose([ar_exe, 't', arc])
files.extend(out.splitlines())
if args.use_libtool:
files = [f for f in files if not f.startswith('__.SYMDEF')]
execute_command_verbose([libtool_exe, '-static', '-o', args.output] + files,
cwd=temp_directory_root, verbose=args.verbose)
else:
execute_command_verbose([ar_exe, 'rcs', args.output] + files,
cwd=temp_directory_root, verbose=args.verbose)
if __name__ == '__main__':
main()
exit_with_cleanups(0)

View File

@ -240,3 +240,15 @@ endmacro()
macro(split_list listname) macro(split_list listname)
string(REPLACE ";" " " ${listname} "${${listname}}") string(REPLACE ";" " " ${listname} "${${listname}}")
endmacro() endmacro()
# For each specified flag, add that compile flag to the provided target.
# The flags are added with the given visibility, i.e. PUBLIC|PRIVATE|INTERFACE.
function(target_add_compile_flags_if_supported target visibility)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
if (CXX_SUPPORTS_${flagname}_FLAG)
target_compile_options(${target} ${visibility} ${flag})
endif()
endforeach()
endfunction()

View File

@ -77,32 +77,13 @@ else()
add_library_flags_if(LIBCXXABI_HAS_C_LIB c) add_library_flags_if(LIBCXXABI_HAS_C_LIB c)
endif() endif()
if (LIBCXXABI_USE_COMPILER_RT) if (NOT LIBCXXABI_USE_COMPILER_RT)
find_compiler_rt_library(builtins LIBCXXABI_BUILTINS_LIBRARY) add_library_flags_if(LIBCXXABI_HAS_GCC_LIB gcc)
list(APPEND LIBCXXABI_SHARED_LIBRARIES "${LIBCXXABI_BUILTINS_LIBRARY}") endif()
endif () if (NOT LIBCXXABI_USE_LLVM_UNWINDER)
if (LIBCXXABI_USE_LLVM_UNWINDER)
# Prefer using the in-tree version of libunwind, either shared or static. If
# none are found fall back to using -lunwind.
# FIXME: Is it correct to prefer the static version of libunwind?
if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
list(APPEND LIBCXXABI_SHARED_LIBRARIES unwind_shared)
elseif (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY AND (TARGET unwind_static OR HAVE_LIBUNWIND))
list(APPEND LIBCXXABI_SHARED_LIBRARIES unwind_static)
else()
list(APPEND LIBCXXABI_SHARED_LIBRARIES unwind)
endif()
if (NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
list(APPEND LIBCXXABI_STATIC_LIBRARIES unwind_shared)
elseif (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY AND (TARGET unwind_static OR HAVE_LIBUNWIND))
# We handle this by directly merging libunwind objects into libc++abi.
else()
list(APPEND LIBCXXABI_STATIC_LIBRARIES unwind)
endif()
else()
add_library_flags_if(LIBCXXABI_HAS_GCC_S_LIB gcc_s) add_library_flags_if(LIBCXXABI_HAS_GCC_S_LIB gcc_s)
endif() endif()
if (MINGW) if (MINGW)
# MINGW_LIBRARIES is defined in config-ix.cmake # MINGW_LIBRARIES is defined in config-ix.cmake
list(APPEND LIBCXXABI_LIBRARIES ${MINGW_LIBRARIES}) list(APPEND LIBCXXABI_LIBRARIES ${MINGW_LIBRARIES})
@ -111,10 +92,6 @@ if (ANDROID AND ANDROID_PLATFORM_LEVEL LESS 21)
list(APPEND LIBCXXABI_LIBRARIES android_support) list(APPEND LIBCXXABI_LIBRARIES android_support)
endif() endif()
if (NOT LIBCXXABI_USE_COMPILER_RT)
add_library_flags_if(LIBCXXABI_HAS_GCC_LIB gcc)
endif ()
# Setup flags. # Setup flags.
if (CXX_SUPPORTS_NOSTDLIBXX_FLAG) if (CXX_SUPPORTS_NOSTDLIBXX_FLAG)
add_link_flags_if_supported(-nostdlib++) add_link_flags_if_supported(-nostdlib++)
@ -175,25 +152,43 @@ if (NOT TARGET pstl::ParallelSTL)
endif() endif()
# Build the shared library. # Build the shared library.
if (LIBCXXABI_ENABLE_SHARED) add_library(cxxabi_shared_objects OBJECT EXCLUDE_FROM_ALL ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS})
add_library(cxxabi_shared SHARED ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS}) if (LIBCXXABI_USE_LLVM_UNWINDER)
target_link_libraries(cxxabi_shared PRIVATE cxx-headers ${LIBCXXABI_SHARED_LIBRARIES} ${LIBCXXABI_LIBRARIES}) if (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY)
target_link_libraries(cxxabi_shared PUBLIC cxxabi-headers) target_sources(cxxabi_shared_objects PUBLIC $<TARGET_OBJECTS:unwind_shared_objects>)
if (TARGET pstl::ParallelSTL) else()
target_link_libraries(cxxabi_shared PUBLIC pstl::ParallelSTL) target_link_libraries(cxxabi_shared_objects PUBLIC unwind_shared)
endif() endif()
endif()
target_link_libraries(cxxabi_shared_objects PRIVATE cxx-headers ${LIBCXXABI_BUILTINS_LIBRARY} ${LIBCXXABI_SHARED_LIBRARIES} ${LIBCXXABI_LIBRARIES})
target_link_libraries(cxxabi_shared_objects PUBLIC cxxabi-headers)
set_target_properties(cxxabi_shared_objects
PROPERTIES
CXX_EXTENSIONS OFF
CXX_STANDARD 20
CXX_STANDARD_REQUIRED OFF
COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}"
DEFINE_SYMBOL ""
)
if (CMAKE_POSITION_INDEPENDENT_CODE OR NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
set_target_properties(cxxabi_shared_objects PROPERTIES POSITION_INDEPENDENT_CODE ON) # must set manually because it's an object library
endif()
if (LIBCXXABI_ENABLE_SHARED)
add_library(cxxabi_shared SHARED)
set_target_properties(cxxabi_shared set_target_properties(cxxabi_shared
PROPERTIES PROPERTIES
CXX_EXTENSIONS OFF
CXX_STANDARD 20
CXX_STANDARD_REQUIRED OFF
COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}"
LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}" LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}"
OUTPUT_NAME "c++abi" OUTPUT_NAME "c++abi"
SOVERSION "1" SOVERSION "1"
VERSION "${LIBCXXABI_LIBRARY_VERSION}" VERSION "${LIBCXXABI_LIBRARY_VERSION}"
DEFINE_SYMBOL ""
) )
target_link_libraries(cxxabi_shared
PUBLIC cxxabi_shared_objects
PRIVATE ${LIBCXXABI_SHARED_LIBRARIES} ${LIBCXXABI_LIBRARIES})
if (TARGET pstl::ParallelSTL)
target_link_libraries(cxxabi_shared PUBLIC pstl::ParallelSTL)
endif()
list(APPEND LIBCXXABI_BUILD_TARGETS "cxxabi_shared") list(APPEND LIBCXXABI_BUILD_TARGETS "cxxabi_shared")
if (LIBCXXABI_INSTALL_SHARED_LIBRARY) if (LIBCXXABI_INSTALL_SHARED_LIBRARY)
@ -231,61 +226,55 @@ if (LIBCXXABI_ENABLE_SHARED)
endif() endif()
# Build the static library. # Build the static library.
add_library(cxxabi_static_objects OBJECT EXCLUDE_FROM_ALL ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS})
if (LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY)
target_sources(cxxabi_static_objects PUBLIC $<TARGET_OBJECTS:unwind_static_objects>)
endif()
target_link_libraries(cxxabi_static_objects PRIVATE cxx-headers ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
target_link_libraries(cxxabi_static_objects PUBLIC cxxabi-headers)
set_target_properties(cxxabi_static_objects
PROPERTIES
CXX_EXTENSIONS OFF
CXX_STANDARD 20
CXX_STANDARD_REQUIRED OFF
COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}"
)
if(LIBCXXABI_HERMETIC_STATIC_LIBRARY)
target_add_compile_flags_if_supported(cxxabi_static_objects PRIVATE -fvisibility=hidden)
# If the hermetic library doesn't define the operator new/delete functions
# then its code shouldn't declare them with hidden visibility. They might
# actually be provided by a shared library at link time.
if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS)
target_add_compile_flags_if_supported(cxxabi_static_objects PRIVATE -fvisibility-global-new-delete-hidden)
endif()
target_compile_definitions(cxxabi_static_objects
PRIVATE
_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS
_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
endif()
if (LIBCXXABI_ENABLE_STATIC) if (LIBCXXABI_ENABLE_STATIC)
add_library(cxxabi_static STATIC ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS}) add_library(cxxabi_static STATIC)
target_link_libraries(cxxabi_static PRIVATE cxx-headers ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES}) if (LIBCXXABI_USE_LLVM_UNWINDER AND NOT LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY)
target_link_libraries(cxxabi_static PUBLIC cxxabi-headers) target_link_libraries(cxxabi_static PUBLIC unwind_static)
if (TARGET pstl::ParallelSTL)
target_link_libraries(cxxabi_static PUBLIC pstl::ParallelSTL)
endif() endif()
set_target_properties(cxxabi_static set_target_properties(cxxabi_static
PROPERTIES PROPERTIES
CXX_EXTENSIONS OFF
CXX_STANDARD 20
CXX_STANDARD_REQUIRED OFF
COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}"
LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}" LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}"
OUTPUT_NAME "c++abi" OUTPUT_NAME "c++abi"
) )
target_link_libraries(cxxabi_static
if(LIBCXXABI_HERMETIC_STATIC_LIBRARY) PUBLIC cxxabi_static_objects
append_flags_if_supported(CXXABI_STATIC_LIBRARY_FLAGS -fvisibility=hidden) PRIVATE ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
# If the hermetic library doesn't define the operator new/delete functions if (TARGET pstl::ParallelSTL)
# then its code shouldn't declare them with hidden visibility. They might target_link_libraries(cxxabi_static PUBLIC pstl::ParallelSTL)
# actually be provided by a shared library at link time.
if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS)
append_flags_if_supported(CXXABI_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden)
endif()
target_compile_options(cxxabi_static PRIVATE ${CXXABI_STATIC_LIBRARY_FLAGS})
target_compile_definitions(cxxabi_static
PRIVATE
_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS
_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
endif() endif()
list(APPEND LIBCXXABI_BUILD_TARGETS "cxxabi_static") list(APPEND LIBCXXABI_BUILD_TARGETS "cxxabi_static")
if (LIBCXXABI_INSTALL_STATIC_LIBRARY) if (LIBCXXABI_INSTALL_STATIC_LIBRARY)
list(APPEND LIBCXXABI_INSTALL_TARGETS "cxxabi_static") list(APPEND LIBCXXABI_INSTALL_TARGETS "cxxabi_static")
endif() endif()
if (APPLE)
set(MERGE_ARCHIVES_LIBTOOL "--use-libtool" "--libtool" "${CMAKE_LIBTOOL}")
endif()
# Merge the libc++abi.a and libunwind.a into one.
if(LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY)
add_custom_command(TARGET cxxabi_static POST_BUILD
COMMAND ${Python3_EXECUTABLE} ${LIBCXXABI_LIBCXX_PATH}/utils/merge_archives.py
ARGS
-o "$<TARGET_LINKER_FILE:cxxabi_static>"
--ar "${CMAKE_AR}"
${MERGE_ARCHIVES_LIBTOOL}
"$<TARGET_LINKER_FILE:cxxabi_static>"
"$<TARGET_LINKER_FILE:unwind_static>"
WORKING_DIRECTORY ${LIBCXXABI_BUILD_DIR}
DEPENDS unwind_static
)
endif()
endif() endif()
# Add a meta-target for both libraries. # Add a meta-target for both libraries.

View File

@ -281,3 +281,15 @@ endmacro()
macro(split_list listname) macro(split_list listname)
string(REPLACE ";" " " ${listname} "${${listname}}") string(REPLACE ";" " " ${listname} "${${listname}}")
endmacro() endmacro()
# For each specified flag, add that compile flag to the provided target.
# The flags are added with the given visibility, i.e. PUBLIC|PRIVATE|INTERFACE.
function(target_add_compile_flags_if_supported target visibility)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
if (CXX_SUPPORTS_${flagname}_FLAG)
target_compile_options(${target} ${visibility} ${flag})
endif()
endforeach()
endfunction()

View File

@ -136,27 +136,36 @@ set_property(SOURCE ${LIBUNWIND_C_SOURCES}
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
# Build the shared library. # Build the shared library.
add_library(unwind_shared_objects OBJECT EXCLUDE_FROM_ALL ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
if(CMAKE_C_COMPILER_ID STREQUAL MSVC)
target_compile_options(unwind_shared_objects PRIVATE /GR-)
else()
target_compile_options(unwind_shared_objects PRIVATE -fno-rtti)
endif()
target_link_libraries(unwind_shared_objects PRIVATE unwind-headers ${LIBUNWIND_LIBRARIES})
set_target_properties(unwind_shared_objects
PROPERTIES
CXX_EXTENSIONS OFF
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
)
if (CMAKE_POSITION_INDEPENDENT_CODE OR NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
set_target_properties(unwind_shared_objects PROPERTIES POSITION_INDEPENDENT_CODE ON) # must set manually because it's an object library
endif()
if (LIBUNWIND_ENABLE_SHARED) if (LIBUNWIND_ENABLE_SHARED)
add_library(unwind_shared SHARED ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS}) add_library(unwind_shared SHARED)
if(CMAKE_C_COMPILER_ID STREQUAL MSVC) target_link_libraries(unwind_shared PUBLIC unwind_shared_objects)
target_compile_options(unwind_shared PRIVATE /GR-)
else()
target_compile_options(unwind_shared PRIVATE -fno-rtti)
endif()
target_link_libraries(unwind_shared PRIVATE ${LIBUNWIND_LIBRARIES}
PRIVATE unwind-headers)
set_target_properties(unwind_shared set_target_properties(unwind_shared
PROPERTIES PROPERTIES
CXX_EXTENSIONS OFF
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}" LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}"
LINKER_LANGUAGE C LINKER_LANGUAGE C
OUTPUT_NAME "unwind" OUTPUT_NAME "unwind"
VERSION "1.0" VERSION "1.0"
SOVERSION "1" SOVERSION "1"
) )
list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_shared") list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_shared")
if (LIBUNWIND_INSTALL_SHARED_LIBRARY) if (LIBUNWIND_INSTALL_SHARED_LIBRARY)
list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_shared") list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_shared")
@ -164,33 +173,37 @@ if (LIBUNWIND_ENABLE_SHARED)
endif() endif()
# Build the static library. # Build the static library.
add_library(unwind_static_objects OBJECT EXCLUDE_FROM_ALL ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
if(CMAKE_C_COMPILER_ID STREQUAL MSVC)
target_compile_options(unwind_static_objects PRIVATE /GR-)
else()
target_compile_options(unwind_static_objects PRIVATE -fno-rtti)
endif()
target_link_libraries(unwind_static_objects PRIVATE unwind-headers ${LIBUNWIND_LIBRARIES})
set_target_properties(unwind_static_objects
PROPERTIES
CXX_EXTENSIONS OFF
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
)
if(LIBUNWIND_HIDE_SYMBOLS)
target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility=hidden)
target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete-hidden)
target_compile_definitions(unwind_static_objects PRIVATE _LIBUNWIND_HIDE_SYMBOLS)
endif()
if (LIBUNWIND_ENABLE_STATIC) if (LIBUNWIND_ENABLE_STATIC)
add_library(unwind_static STATIC ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS}) add_library(unwind_static STATIC)
if(CMAKE_C_COMPILER_ID STREQUAL MSVC) target_link_libraries(unwind_static PUBLIC unwind_static_objects)
target_compile_options(unwind_static PRIVATE /GR-)
else()
target_compile_options(unwind_static PRIVATE -fno-rtti)
endif()
target_link_libraries(unwind_static PRIVATE ${LIBUNWIND_LIBRARIES}
PRIVATE unwind-headers)
set_target_properties(unwind_static set_target_properties(unwind_static
PROPERTIES PROPERTIES
CXX_EXTENSIONS OFF
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}" LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}"
LINKER_LANGUAGE C LINKER_LANGUAGE C
OUTPUT_NAME "unwind" OUTPUT_NAME "unwind"
) )
if(LIBUNWIND_HIDE_SYMBOLS)
append_flags_if_supported(UNWIND_STATIC_LIBRARY_FLAGS -fvisibility=hidden)
append_flags_if_supported(UNWIND_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden)
target_compile_options(unwind_static PRIVATE ${UNWIND_STATIC_LIBRARY_FLAGS})
target_compile_definitions(unwind_static PRIVATE _LIBUNWIND_HIDE_SYMBOLS)
endif()
list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_static") list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_static")
if (LIBUNWIND_INSTALL_STATIC_LIBRARY) if (LIBUNWIND_INSTALL_STATIC_LIBRARY)
list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_static") list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_static")