diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index 2c708968dcea..d40257a2c035 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -251,6 +251,9 @@ if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) else() message(WARNING "LIBCXX_ENABLE_STATIC_ABI_LIBRARY is an experimental option") endif() + if (LIBCXX_ENABLE_STATIC AND NOT PYTHONINTERP_FOUND) + message(FATAL_ERROR "LIBCXX_ENABLE_STATIC_ABI_LIBRARY requires python but it was not found.") + endif() endif() if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT) diff --git a/libcxx/lib/CMakeLists.txt b/libcxx/lib/CMakeLists.txt index 1e7c6d4f1cec..6beb59feec41 100644 --- a/libcxx/lib/CMakeLists.txt +++ b/libcxx/lib/CMakeLists.txt @@ -193,6 +193,28 @@ if (LIBCXX_ENABLE_STATIC) OUTPUT_NAME "c++" ) list(APPEND LIBCXX_TARGETS "cxx_static") + # Attempt to merge the libc++.a archive and the ABI library archive into one. + if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) + set(MERGE_ARCHIVES_SEARCH_PATHS "") + if (LIBCXX_CXX_ABI_LIBRARY_PATH) + set(MERGE_ARCHIVES_SEARCH_PATHS "-L${LIBCXX_CXX_ABI_LIBRARY_PATH}") + endif() + if (TARGET ${LIBCXX_CXX_ABI_LIBRARY}) + set(MERGE_ARCHIVES_ABI_TARGET "$") + else() + set(MERGE_ARCHIVES_ABI_TARGET "lib${LIBCXX_CXX_ABI_LIBRARY}.a") + endif() + add_custom_command(TARGET cxx_static POST_BUILD + COMMAND + ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/merge_archives.py + ARGS + -o $ + "$" + "${MERGE_ARCHIVES_ABI_TARGET}" + "${MERGE_ARCHIVES_SEARCH_PATHS}" + WORKING_DIRECTORY ${LIBCXX_BUILD_DIR} + ) + endif() endif() # Add a meta-target for both libraries. diff --git a/libcxx/utils/merge_archives.py b/libcxx/utils/merge_archives.py index b8ba316f842d..856dd3bfae90 100755 --- a/libcxx/utils/merge_archives.py +++ b/libcxx/utils/merge_archives.py @@ -9,6 +9,7 @@ #===----------------------------------------------------------------------===## from argparse import ArgumentParser +from ctypes.util import find_library import distutils.spawn import glob import tempfile @@ -28,9 +29,18 @@ def print_and_exit(msg): sys.stderr.write(msg + '\n') exit_with_cleanups(1) -def diagnose_missing(file): - if not os.path.exists(file): - print_and_exit("input '%s' does not exist" % file) +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): @@ -79,6 +89,10 @@ def main(): '-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) parser.add_argument( 'archives', metavar='archives', nargs='+', help='The archives to merge') @@ -91,12 +105,9 @@ def main(): if len(args.archives) < 2: print_and_exit('fewer than 2 inputs provided') - archives = [] - for ar in args.archives: - diagnose_missing(ar) - # Make the path absolute so it isn't affected when we change the PWD. - archives += [os.path.abspath(ar)] - + 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)