diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index cf67e0c2ee5af..71ff90da9f000 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -567,7 +567,7 @@ function(_add_swift_library_single target name) cmake_parse_arguments(SWIFTLIB_SINGLE "${SWIFTLIB_SINGLE_options}" "MODULE_TARGET;SDK;ARCHITECTURE;INSTALL_IN_COMPONENT;DEPLOYMENT_VERSION_OSX;DEPLOYMENT_VERSION_IOS;DEPLOYMENT_VERSION_TVOS;DEPLOYMENT_VERSION_WATCHOS" - "DEPENDS;LINK_LIBRARIES;FRAMEWORK_DEPENDS;FRAMEWORK_DEPENDS_WEAK;LLVM_COMPONENT_DEPENDS;C_COMPILE_FLAGS;SWIFT_COMPILE_FLAGS;LINK_FLAGS;PRIVATE_LINK_LIBRARIES;INTERFACE_LINK_LIBRARIES;INCORPORATE_OBJECT_LIBRARIES;FILE_DEPENDS" + "DEPENDS;LINK_LIBRARIES;FRAMEWORK_DEPENDS;FRAMEWORK_DEPENDS_WEAK;LLVM_COMPONENT_DEPENDS;C_COMPILE_FLAGS;SWIFT_COMPILE_FLAGS;LINK_FLAGS;PRIVATE_LINK_LIBRARIES;INTERFACE_LINK_LIBRARIES;INCORPORATE_OBJECT_LIBRARIES;INCORPORATE_OBJECT_LIBRARIES_SHARED_ONLY;FILE_DEPENDS" ${ARGN}) set(SWIFTLIB_SINGLE_SOURCES ${SWIFTLIB_SINGLE_UNPARSED_ARGUMENTS}) @@ -739,6 +739,12 @@ function(_add_swift_library_single target name) $) endforeach() + set(SWIFTLIB_INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS_SHARED_ONLY) + foreach(object_library ${SWIFTLIB_SINGLE_INCORPORATE_OBJECT_LIBRARIES_SHARED_ONLY}) + list(APPEND SWIFTLIB_INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS_SHARED_ONLY + $) + endforeach() + set(SWIFTLIB_SINGLE_XCODE_WORKAROUND_SOURCES) if(XCODE AND SWIFTLIB_SINGLE_TARGET_LIBRARY) set(SWIFTLIB_SINGLE_XCODE_WORKAROUND_SOURCES @@ -747,11 +753,17 @@ function(_add_swift_library_single target name) ${SWIFT_SOURCE_DIR}/cmake/dummy.cpp) endif() + set(INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS ${SWIFTLIB_INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS}) + if(${libkind} STREQUAL "SHARED") + list(APPEND INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS + ${SWIFTLIB_INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS_SHARED_ONLY}) + endif() + add_library("${target}" ${libkind} ${SWIFT_SECTIONS_OBJECT_BEGIN} ${SWIFTLIB_SINGLE_SOURCES} ${SWIFTLIB_SINGLE_EXTERNAL_SOURCES} - ${SWIFTLIB_INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS} + ${INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS} ${SWIFTLIB_SINGLE_XCODE_WORKAROUND_SOURCES} ${SWIFT_SECTIONS_OBJECT_END}) _set_target_prefix_and_suffix("${target}" "${libkind}" "${SWIFTLIB_SINGLE_SDK}") @@ -1270,7 +1282,7 @@ function(add_swift_library name) cmake_parse_arguments(SWIFTLIB "${SWIFTLIB_options}" "INSTALL_IN_COMPONENT;DEPLOYMENT_VERSION_OSX;DEPLOYMENT_VERSION_IOS;DEPLOYMENT_VERSION_TVOS;DEPLOYMENT_VERSION_WATCHOS" - "DEPENDS;LINK_LIBRARIES;SWIFT_MODULE_DEPENDS;SWIFT_MODULE_DEPENDS_OSX;SWIFT_MODULE_DEPENDS_IOS;SWIFT_MODULE_DEPENDS_TVOS;SWIFT_MODULE_DEPENDS_WATCHOS;SWIFT_MODULE_DEPENDS_FREEBSD;SWIFT_MODULE_DEPENDS_LINUX;FRAMEWORK_DEPENDS;FRAMEWORK_DEPENDS_WEAK;FRAMEWORK_DEPENDS_OSX;FRAMEWORK_DEPENDS_IOS_TVOS;LLVM_COMPONENT_DEPENDS;FILE_DEPENDS;TARGET_SDKS;C_COMPILE_FLAGS;SWIFT_COMPILE_FLAGS;SWIFT_COMPILE_FLAGS_OSX;SWIFT_COMPILE_FLAGS_IOS;SWIFT_COMPILE_FLAGS_TVOS;SWIFT_COMPILE_FLAGS_WATCHOS;LINK_FLAGS;PRIVATE_LINK_LIBRARIES;INTERFACE_LINK_LIBRARIES;INCORPORATE_OBJECT_LIBRARIES" + "DEPENDS;LINK_LIBRARIES;SWIFT_MODULE_DEPENDS;SWIFT_MODULE_DEPENDS_OSX;SWIFT_MODULE_DEPENDS_IOS;SWIFT_MODULE_DEPENDS_TVOS;SWIFT_MODULE_DEPENDS_WATCHOS;SWIFT_MODULE_DEPENDS_FREEBSD;SWIFT_MODULE_DEPENDS_LINUX;FRAMEWORK_DEPENDS;FRAMEWORK_DEPENDS_WEAK;FRAMEWORK_DEPENDS_OSX;FRAMEWORK_DEPENDS_IOS_TVOS;LLVM_COMPONENT_DEPENDS;FILE_DEPENDS;TARGET_SDKS;C_COMPILE_FLAGS;SWIFT_COMPILE_FLAGS;SWIFT_COMPILE_FLAGS_OSX;SWIFT_COMPILE_FLAGS_IOS;SWIFT_COMPILE_FLAGS_TVOS;SWIFT_COMPILE_FLAGS_WATCHOS;LINK_FLAGS;PRIVATE_LINK_LIBRARIES;INTERFACE_LINK_LIBRARIES;INCORPORATE_OBJECT_LIBRARIES;INCORPORATE_OBJECT_LIBRARIES_SHARED_ONLY" ${ARGN}) set(SWIFTLIB_SOURCES ${SWIFTLIB_UNPARSED_ARGUMENTS}) @@ -1491,6 +1503,7 @@ function(add_swift_library name) LINK_FLAGS ${SWIFTLIB_LINK_FLAGS} PRIVATE_LINK_LIBRARIES ${swiftlib_private_link_libraries_targets} INCORPORATE_OBJECT_LIBRARIES ${SWIFTLIB_INCORPORATE_OBJECT_LIBRARIES} + INCORPORATE_OBJECT_LIBRARIES_SHARED_ONLY ${SWIFTLIB_INCORPORATE_OBJECT_LIBRARIES_SHARED_ONLY} ${SWIFTLIB_DONT_EMBED_BITCODE_keyword} ${SWIFTLIB_API_NOTES_NON_OVERLAY_keyword} ${SWIFTLIB_IS_STDLIB_keyword} @@ -1682,6 +1695,7 @@ function(add_swift_library name) PRIVATE_LINK_LIBRARIES ${SWIFTLIB_PRIVATE_LINK_LIBRARIES} INTERFACE_LINK_LIBRARIES ${SWIFTLIB_INTERFACE_LINK_LIBRARIES} INCORPORATE_OBJECT_LIBRARIES ${SWIFTLIB_INCORPORATE_OBJECT_LIBRARIES} + INCORPORATE_OBJECT_LIBRARIES_SHARED_ONLY ${SWIFTLIB_INCORPORATE_OBJECT_LIBRARIES_SHARED_ONLY} ${SWIFTLIB_DONT_EMBED_BITCODE_keyword} ${SWIFTLIB_API_NOTES_NON_OVERLAY_keyword} ${SWIFTLIB_IS_STDLIB_keyword} diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 1043c610e912f..8edec1ba55aaa 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -282,6 +282,12 @@ def no_static_stdlib: Flag<["-"], "no-static-stdlib">, Flags<[HelpHidden]>, HelpText<"Don't statically link the Swift standard library">; +def static_executable : Flag<["-"], "static-executable">, + HelpText<"Statically link the executable">; +def no_static_executable : Flag<["-"], "no-static-executable">, + Flags<[HelpHidden]>, + HelpText<"Don't statically link the executable">; + def use_ld : Joined<["-"], "use-ld=">, Flags<[DoesNotAffectIncrementalBuild]>, HelpText<"Specifies the linker to be used">; diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt index 7f9d1633f47bc..e0c8898987bde 100644 --- a/lib/Driver/CMakeLists.txt +++ b/lib/Driver/CMakeLists.txt @@ -19,3 +19,33 @@ add_swift_library(swiftDriver STATIC DEPENDS SwiftOptions LINK_LIBRARIES swiftAST swiftBasic swiftFrontend swiftOption) +# Generate the static-stdlib-args.lnk file used by -static-stdlib option +# for 'GenericUnix' (eg linux) +if(SWIFT_BUILD_STATIC_STDLIB) + set(static_stdlib_lnk_file_list) + foreach(sdk ${SWIFT_CONFIGURED_SDKS}) + if("${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "ELF") + string(TOLOWER "${sdk}" lowercase_sdk) + if(SWIFT_LINUX_ICU_STATICLIB) + set(ICU_STATICLIB "TRUE") + else() + set(ICU_STATICLIB "FALSE") + endif() + set(linkfile "${lowercase_sdk}/static-stdlib-args.lnk") + add_custom_command_target(swift_static_stdlib_${sdk}_args + COMMAND + "${SWIFT_SOURCE_DIR}/utils/gen-static-stdlib-link-args" + "${sdk}" + "${SWIFTSTATICLIB_DIR}/${linkfile}" + "${ICU_STATICLIB}" + OUTPUT + "${SWIFTSTATICLIB_DIR}/${linkfile}") + + list(APPEND static_stdlib_lnk_file_list ${swift_static_stdlib_${sdk}_args}) + swift_install_in_component(stdlib + FILES "${SWIFTSTATICLIB_DIR}/${linkfile}" + DESTINATION "lib/swift_static/${lowercase_sdk}") + endif() + endforeach() + add_custom_target(swift_static_lnk_args ALL DEPENDS ${static_stdlib_lnk_file_list}) +endif() diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index db8c2ef5bfde7..a097f239ada7a 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -952,6 +952,12 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job, assert(context.Output.getPrimaryOutputType() == types::TY_Image && "Invalid linker output type."); + if (context.Args.hasFlag(options::OPT_static_executable, + options::OPT_no_static_executable, + false)) { + llvm::report_fatal_error("-static-executable is not supported on Darwin"); + } + const Driver &D = getDriver(); const llvm::Triple &Triple = getTriple(); @@ -1357,33 +1363,42 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job, // Link the standard library. Arguments.push_back("-L"); - if (context.Args.hasFlag(options::OPT_static_stdlib, - options::OPT_no_static_stdlib, - false)) { + if (context.Args.hasFlag(options::OPT_static_executable, + options::OPT_no_static_executable, + false)) { SmallString<128> StaticRuntimeLibPath; getRuntimeStaticLibraryPath(StaticRuntimeLibPath, context.Args, *this); Arguments.push_back(context.Args.MakeArgString(StaticRuntimeLibPath)); - // The following libraries are required to build a satisfactory - // static program - Arguments.push_back("-ldl"); - Arguments.push_back("-lpthread"); - Arguments.push_back("-lbsd"); - Arguments.push_back("-licui18n"); - Arguments.push_back("-licuuc"); - // The runtime uses dlopen to look for the protocol conformances. - // Therefore, we need to ensure they appear in the dynamic table. - // This happens automatically for dynamically-linked programs, but - // in this case we have to take additional measures. - Arguments.push_back("-Xlinker"); - Arguments.push_back("-export-dynamic"); - Arguments.push_back("-Xlinker"); - Arguments.push_back("--exclude-libs"); - Arguments.push_back("-Xlinker"); - Arguments.push_back("ALL"); + SmallString<128> linkFilePath = StaticRuntimeLibPath; + llvm::sys::path::append(linkFilePath, "static-executable-args.lnk"); + auto linkFile = linkFilePath.str(); + + if (llvm::sys::fs::is_regular_file(linkFile)) { + Arguments.push_back(context.Args.MakeArgString(Twine("@") + linkFile)); + } else { + llvm::report_fatal_error("-static-executable not supported on this platform"); + } + } + else if (context.Args.hasFlag(options::OPT_static_stdlib, + options::OPT_no_static_stdlib, + false)) { + SmallString<128> StaticRuntimeLibPath; + getRuntimeStaticLibraryPath(StaticRuntimeLibPath, context.Args, *this); + Arguments.push_back(context.Args.MakeArgString(StaticRuntimeLibPath)); + + SmallString<128> linkFilePath = StaticRuntimeLibPath; + llvm::sys::path::append(linkFilePath, "static-stdlib-args.lnk"); + auto linkFile = linkFilePath.str(); + if (llvm::sys::fs::is_regular_file(linkFile)) { + Arguments.push_back(context.Args.MakeArgString(Twine("@") + linkFile)); + } else { + llvm::report_fatal_error(linkFile + " not found"); + } } else { Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath)); + Arguments.push_back("-lswiftCore"); } @@ -1404,8 +1419,6 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job, Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); } - // Always add the stdlib - Arguments.push_back("-lswiftCore"); // Add any autolinking scripts to the arguments for (const Job *Cmd : context.Inputs) { diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index 6ab835e1ae087..d1b949d507031 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -177,9 +177,13 @@ else() # effort has been completed. #set(LINK_FLAGS # -Wl,--whole-archive swiftRuntime -Wl,--no-whole-archive) - find_package(ICU REQUIRED COMPONENTS uc i18n) - list(APPEND swift_core_private_link_libraries - ICU_UC ICU_I18N) + if("${SWIFT_PATH_TO_LIBICU_BUILD}" STREQUAL "") + find_package(ICU REQUIRED COMPONENTS uc i18n) + list(APPEND swift_core_private_link_libraries + ICU_UC ICU_I18N) + else() + list(APPEND swift_core_private_link_libraries -licui18n -licuuc -licudata) + endif() endif() if("${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN") @@ -209,6 +213,12 @@ if(SWIFT_CHECK_ESSENTIAL_STDLIB) target_link_libraries(swift_stdlib_essential ${RUNTIME_DEPENDENCY}) endif() + +set(shared_only_libs) +if(SWIFT_BUILD_STATIC_STDLIB AND "${SWIFT_HOST_VARIANT_SDK}" STREQUAL "LINUX") + list(APPEND shared_only_libs swiftImageInspectionShared) +endif() + add_swift_library(swiftCore ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB IS_STDLIB_CORE ${SWIFTLIB_SOURCES} # The copy_shim_headers target dependency is required to let the @@ -224,5 +234,6 @@ add_swift_library(swiftCore ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB IS_STD LINK_FLAGS ${swift_core_link_flags} PRIVATE_LINK_LIBRARIES ${swift_core_private_link_libraries} INCORPORATE_OBJECT_LIBRARIES swiftRuntime swiftStdlibStubs + INCORPORATE_OBJECT_LIBRARIES_SHARED_ONLY ${shared_only_libs} FRAMEWORK_DEPENDS ${swift_core_framework_depends} INSTALL_IN_COMPONENT stdlib) diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index 232b1359a9788..e6bc6274ed1fe 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -62,6 +62,8 @@ set(LLVM_OPTIONAL_SOURCES MutexPThread.cpp MutexWin32.cpp CygwinPort.cpp + ImageInspectionELF.cpp + ImageInspectionStatic.cpp ${swift_runtime_sources} ${swift_runtime_objc_sources} ${swift_runtime_leaks_sources}) @@ -69,6 +71,48 @@ set(LLVM_OPTIONAL_SOURCES set(swift_runtime_library_compile_flags ${swift_runtime_compile_flags}) list(APPEND swift_runtime_library_compile_flags -DswiftCore_EXPORTS) +set(sdk "${SWIFT_HOST_VARIANT_SDK}") +if(SWIFT_BUILD_STATIC_STDLIB AND "${sdk}" STREQUAL "LINUX") + list(REMOVE_ITEM swift_runtime_sources ImageInspectionELF.cpp) + set(static_binary_lnk_file_list) + string(TOLOWER "${sdk}" lowercase_sdk) + + # These two libaries are only used with the static swiftcore + add_library(swiftImageInspectionStatic STATIC ImageInspectionStatic.cpp) + set_target_properties(swiftImageInspectionStatic PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${SWIFTSTATICLIB_DIR}/${lowercase_sdk}") + + add_library(swiftImageInspectionShared STATIC ImageInspectionELF.cpp) + set_target_properties(swiftImageInspectionShared PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${SWIFTSTATICLIB_DIR}/${lowercase_sdk}") + + swift_install_in_component(stdlib + TARGETS swiftImageInspectionStatic swiftImageInspectionShared + DESTINATION "lib/swift_static/${lowercase_sdk}") + + # Generate the static-executable-args.lnk file used for ELF systems (eg linux) + set(linkfile "${lowercase_sdk}/static-executable-args.lnk") + add_custom_command_target(swift_static_binary_${sdk}_args + COMMAND + "${CMAKE_COMMAND}" -E copy + "${SWIFT_SOURCE_DIR}/utils/${lowercase}/static-executable-args.lnk" + "${SWIFTSTATICLIB_DIR}/${linkfile}" + OUTPUT + "${SWIFTSTATICLIB_DIR}/${linkfile}") + + list(APPEND static_binary_lnk_file_list ${swift_static_binary_${sdk}_args}) + swift_install_in_component(stdlib + FILES "${SWIFTSTATICLIB_DIR}/${linkfile}" + DESTINATION "lib/swift_static/${lowercase_sdk}") + add_custom_target(static_binary_magic ALL DEPENDS ${static_binary_lnk_file_list}) + + add_swift_library(swiftImageInspectionShared OBJECT_LIBRARY TARGET_LIBRARY + ImageInspectionELF.cpp + C_COMPILE_FLAGS ${swift_runtime_library_compile_flags} + LINK_FLAGS ${swift_runtime_linker_flags} + INSTALL_IN_COMPONENT never_install) +endif() + add_swift_library(swiftRuntime OBJECT_LIBRARY TARGET_LIBRARY ${swift_runtime_sources} ${swift_runtime_objc_sources} diff --git a/stdlib/public/runtime/ImageInspectionStatic.cpp b/stdlib/public/runtime/ImageInspectionStatic.cpp new file mode 100644 index 0000000000000..d57dacde78b7f --- /dev/null +++ b/stdlib/public/runtime/ImageInspectionStatic.cpp @@ -0,0 +1,64 @@ +//===-- ImageInspectionStatic.cpp -------------------------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2016 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Implementation of functions to read data sections from static executable. +// +//===----------------------------------------------------------------------===// + +#include "ImageInspection.h" +#include + +// Currently only tested on linux but should work for any ELF platform +#if defined(__ELF__) && defined(__linux__) + +// These are defined in swift_sections.S to mark the start of a section with the +// length of the data followed immediately by the section data +struct alignas(uint64_t) Section; +extern const Section protocolConformancesStart asm(".swift2_protocol_conformances_start"); +extern const Section typeMetadataStart asm(".swift2_type_metadata_start"); + +struct SectionInfo { + uint64_t size; + const char *data; +}; + +static SectionInfo +getSectionInfo(const Section *section) { + SectionInfo info; + memcpy(&info.size, section, sizeof(uint64_t)); + info.data = reinterpret_cast(section) + sizeof(uint64_t); + return info; +} + +void +swift::initializeProtocolConformanceLookup() { + auto protocolConformances = getSectionInfo(&protocolConformancesStart); + addImageProtocolConformanceBlockCallback(protocolConformances.data, + protocolConformances.size); +} + +void +swift::initializeTypeMetadataRecordLookup() { + auto typeMetadata = getSectionInfo(&typeMetadataStart); + addImageTypeMetadataRecordBlockCallback(typeMetadata.data, + typeMetadata.size); +} + +// This is called from Errors.cpp when dumping a stack trace entry. +// It could be implemented by parsing the ELF information in the +// executable. For now it returns 0 for error (cant lookup address). +int +swift::lookupSymbol(const void *address, SymbolInfo *info) { + return 0; +} + +#endif diff --git a/unittests/runtime/CMakeLists.txt b/unittests/runtime/CMakeLists.txt index dff230838d541..797bbf0a6809f 100644 --- a/unittests/runtime/CMakeLists.txt +++ b/unittests/runtime/CMakeLists.txt @@ -1,6 +1,11 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND ("${SWIFT_HOST_VARIANT_ARCH}" STREQUAL "${SWIFT_PRIMARY_VARIANT_ARCH}")) + if(SWIFT_BUILD_STATIC_STDLIB AND "${SWIFT_HOST_VARIANT_SDK}" STREQUAL "LINUX") + set(swift_runtime_test_extra_sources + "${CMAKE_CURRENT_SOURCE_DIR}/../../stdlib/public/runtime/ImageInspectionELF.cpp") + endif() + add_subdirectory(LongTests) set(PLATFORM_SOURCES) @@ -36,6 +41,7 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND # from the swiftCore dylib, so we need to link to both the runtime archive # and the stdlib. $ + ${swift_runtime_test_extra_sources} ) # FIXME: cross-compile for all variants. diff --git a/unittests/runtime/LongTests/CMakeLists.txt b/unittests/runtime/LongTests/CMakeLists.txt index cd20ed38210ed..54befa11b67f6 100644 --- a/unittests/runtime/LongTests/CMakeLists.txt +++ b/unittests/runtime/LongTests/CMakeLists.txt @@ -32,6 +32,7 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND # from the swiftCore dylib, so we need to link to both the runtime archive # and the stdlib. $ + ${swift_runtime_test_extra_sources} ) # FIXME: cross-compile for all variants. diff --git a/utils/build-script b/utils/build-script index 5d2dd9dbd1387..e0f4471bad1d6 100755 --- a/utils/build-script +++ b/utils/build-script @@ -280,6 +280,9 @@ class BuildScriptInvocation(object): if args.libdispatch_build_variant is None: args.libdispatch_build_variant = args.build_variant + if args.libicu_build_variant is None: + args.libicu_build_variant = args.build_variant + # Assertions are enabled by default. if args.assertions is None: args.assertions = True @@ -337,6 +340,7 @@ class BuildScriptInvocation(object): args.build_xctest = False args.build_foundation = False args.build_libdispatch = False + args.build_libicu = False args.build_playgroundlogger = False args.build_playgroundsupport = False @@ -585,6 +589,7 @@ class BuildScriptInvocation(object): "--lldb-build-type", args.lldb_build_variant, "--foundation-build-type", args.foundation_build_variant, "--libdispatch-build-type", args.libdispatch_build_variant, + "--libicu-build-type", args.libicu_build_variant, "--xctest-build-type", args.build_variant, "--swift-enable-assertions", str(args.swift_assertions).lower(), "--swift-stdlib-enable-assertions", str( @@ -664,6 +669,8 @@ class BuildScriptInvocation(object): impl_args += ["--skip-build-llbuild"] if not args.build_libdispatch: impl_args += ["--skip-build-libdispatch"] + if not args.build_libicu: + impl_args += ["--skip-build-libicu"] if not args.build_swiftpm: impl_args += ["--skip-build-swiftpm"] if not args.build_playgroundlogger: @@ -714,6 +721,7 @@ class BuildScriptInvocation(object): "--skip-test-xctest", "--skip-test-foundation", "--skip-test-libdispatch", + "--skip-test-libicu", "--skip-test-playgroundlogger", "--skip-test-playgroundsupport"] if args.skip_test_linux: @@ -881,6 +889,8 @@ class BuildScriptInvocation(object): product_classes = [] product_classes.append(products.CMark) product_classes.append(products.LLVM) + if self.args.build_libicu: + product_classes.append(products.LibICU) product_classes.append(products.Swift) if self.args.build_lldb: product_classes.append(products.LLDB) @@ -1130,6 +1140,7 @@ SWIFT_SOURCE_ROOT: a directory containing the source for LLVM, Clang, Swift. /swift-corelibs-xctest (optional) /swift-corelibs-foundation (optional) /swift-corelibs-libdispatch (optional) + /icu (optional) SWIFT_BUILD_ROOT: a directory in which to create out-of-tree builds. Defaults to "$SWIFT_SOURCE_ROOT/build/". @@ -1323,6 +1334,11 @@ details of the setups of other systems or automated environments.""") help="build libdispatch", action=arguments.action.optional_bool, dest="build_libdispatch") + projects_group.add_argument( + "--libicu", + help="build libicu", + action=arguments.action.optional_bool, + dest="build_libicu") projects_group.add_argument( "--playgroundlogger", help="build playgroundlogger", @@ -1422,6 +1438,12 @@ details of the setups of other systems or automated environments.""") action="store_const", const="Debug", dest="libdispatch_build_variant") + build_variant_override_group.add_argument( + "--debug-libicu", + help="build the Debug variant of libicu", + action="store_const", + const="Debug", + dest="libicu_build_variant") assertions_group = parser.add_mutually_exclusive_group(required=False) assertions_group.add_argument( diff --git a/utils/build-script-impl b/utils/build-script-impl index f0b3662304198..cabb17416dc3f 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -74,6 +74,7 @@ KNOWN_SETTINGS=( llbuild-build-type "Debug" "the CMake build variant for llbuild" foundation-build-type "Debug" "the build variant for Foundation" libdispatch-build-type "Debug" "the build variant for libdispatch" + libicu-build-type "Debug" "the build variant for libicu" playgroundlogger-build-type "Debug" "the build variant for PlaygroundLogger" playgroundsupport-build-type "Debug" "the build variant for PlaygroundSupport" xctest-build-type "Debug" "the build variant for xctest" @@ -117,6 +118,7 @@ KNOWN_SETTINGS=( skip-build-xctest "" "set to skip building xctest" skip-build-foundation "" "set to skip building foundation" skip-build-libdispatch "" "set to skip building libdispatch" + skip-build-libicu "" "set to skip building libicu" skip-build-benchmarks "" "set to skip building Swift Benchmark Suite" skip-build-playgroundlogger "" "set to skip building PlaygroundLogger" skip-build-playgroundsupport "" "set to skip building PlaygroundSupport" @@ -128,6 +130,7 @@ KNOWN_SETTINGS=( skip-test-xctest "" "set to skip testing xctest" skip-test-foundation "" "set to skip testing foundation" skip-test-libdispatch "" "set to skip testing libdispatch" + skip-test-libicu "" "set to skip testing libicu" skip-test-playgroundlogger "" "set to skip testing PlaygroundLogger" skip-test-playgroundsupport "" "set to skip testing PlaygroundSupport" skip-test-linux "" "set to skip testing Swift stdlibs for Linux" @@ -181,6 +184,7 @@ KNOWN_SETTINGS=( install-xctest "" "whether to install xctest" install-foundation "" "whether to install foundation" install-libdispatch "" "whether to install libdispatch" + install-libicu "" "whether to install libicu" install-playgroundlogger "" "whether to install PlaygroundLogger" install-playgroundsupport "" "whether to install PlaygroundSupport" darwin-install-extract-symbols "" "whether to extract symbols with dsymutil during installations" @@ -226,6 +230,7 @@ KNOWN_SETTINGS=( ninja-cmake-options "" "CMake options used for all ninja targets" foundation-cmake-options "" "CMake options used for all foundation targets" libdispatch-cmake-options "" "CMake options used for all libdispatch targets" + libicu-cmake-options "" "CMake options used for all libicu targets" llbuild-cmake-options "" "CMake options used for all llbuild targets" lldb-cmake-options "" "CMake options used for all lldb targets" llvm-cmake-options "" "CMake options used for all llvm targets" @@ -1195,6 +1200,7 @@ SWIFTPM_SOURCE_DIR="${WORKSPACE}/swiftpm" XCTEST_SOURCE_DIR="${WORKSPACE}/swift-corelibs-xctest" FOUNDATION_SOURCE_DIR="${WORKSPACE}/swift-corelibs-foundation" LIBDISPATCH_SOURCE_DIR="${WORKSPACE}/swift-corelibs-libdispatch" +LIBICU_SOURCE_DIR="${WORKSPACE}/icu" PLAYGROUNDLOGGER_SOURCE_DIR="${WORKSPACE}/swift-xcode-playground-support/PlaygroundLogger" PLAYGROUNDSUPPORT_SOURCE_DIR="${WORKSPACE}/swift-xcode-playground-support/PlaygroundSupport" @@ -1228,6 +1234,11 @@ if [[ ! "${SKIP_BUILD_LIBDISPATCH}" && ! -d ${LIBDISPATCH_SOURCE_DIR} ]]; then exit 1 fi +if [[ ! "${SKIP_BUILD_LIBICU}" && ! -d ${LIBICU_SOURCE_DIR} ]]; then + echo "Couldn't find libicu source directory." + exit 1 +fi + if [[ ! "${SKIP_BUILD_PLAYGROUNDLOGGER}" && ! -d ${PLAYGROUNDLOGGER_SOURCE_DIR} ]]; then echo "Couldn't find PlaygroundLogger source directory." exit 1 @@ -1259,7 +1270,11 @@ if [ -e "${WORKSPACE}/compiler-rt" ] ; then fi fi -PRODUCTS=(cmark llvm swift) +PRODUCTS=(cmark llvm) +if [[ ! "${SKIP_BUILD_LIBICU}" ]] ; then + PRODUCTS=("${PRODUCTS[@]}" libicu) +fi +PRODUCTS=("${PRODUCTS[@]}" swift) if [[ ! "${SKIP_BUILD_LLDB}" ]] ; then PRODUCTS=("${PRODUCTS[@]}" lldb) fi @@ -1571,6 +1586,8 @@ function build_directory_bin() { libdispatch) echo "${root}/${LIBDISPATCH_BUILD_TYPE}/bin" ;; + libicu) + ;; playgroundlogger) # FIXME: var name for build type echo "${root}/${PLAYGROUNDLOGGER_BUILD_TYPE}/bin" @@ -1699,6 +1716,8 @@ function cmake_config_opt() { ;; libdispatch) ;; + libicu) + ;; playgroundlogger) # FIXME: var name echo "--config ${PLAYGROUNDLOGGER_BUILD_TYPE}" @@ -1723,6 +1742,9 @@ function set_swiftpm_bootstrap_command() { LIBDISPATCH_BUILD_DIR="$(build_directory ${host} libdispatch)" LIBDISPATCH_BUILD_ARGS="--libdispatch-source-dir=${LIBDISPATCH_SOURCE_DIR} --libdispatch-build-dir=${LIBDISPATCH_BUILD_DIR}" fi + if [[ ! "${SKIP_BUILD_LIBICU}" ]] ; then + LIBICU_BUILD_DIR="$(build_directory ${host} libicu)" + fi if [[ ! "${SKIP_BUILD_XCTEST}" ]] ; then XCTEST_BUILD_DIR=$(build_directory ${host} xctest) fi @@ -2143,6 +2165,14 @@ for host in "${ALL_HOSTS[@]}"; do -DSWIFT_PATH_TO_LIBDISPATCH_BUILD:PATH="$(build_directory ${host} libdispatch)" ) + if [[ ! "${SKIP_BUILD_LIBICU}" ]] ; then + cmake_options=( + "${cmake_options[@]}" + -DSWIFT_PATH_TO_LIBICU_SOURCE:PATH="${LIBICU_SOURCE_DIR}" + -DSWIFT_PATH_TO_LIBICU_BUILD:PATH="$(build_directory ${host} libicu)" + ) + fi + if [[ "${CMAKE_GENERATOR}" == "Xcode" ]] ; then cmake_options=( "${cmake_options[@]}" @@ -2433,6 +2463,58 @@ for host in "${ALL_HOSTS[@]}"; do # libdispatch builds itself and doesn't use cmake continue ;; + libicu) + SWIFT_BUILD_PATH=$(build_directory ${host} swift) + LIBICU_BUILD_DIR=$(build_directory ${host} ${product}) + ICU_TMPINSTALL=$LIBICU_BUILD_DIR/tmp_install + ICU_TMPLIBDIR="${SWIFT_BUILD_PATH}/lib/swift/${SWIFT_HOST_VARIANT}/${SWIFT_HOST_VARIANT_ARCH}" + if [[ "${RECONFIGURE}" || ! -f "${LIBICU_BUILD_DIR}"/config.status ]]; then + echo "Reconfiguring libicu" + if [[ "$LIBICU_BUILD_TYPE" == "Release" ]] ; then + icu_build_variant_arg="--enable-release" + elif [[ "$LIBICU_BUILD_TYPE" == "RelWithDebInfo" ]]; then + icu_build_variant_arg="--enable-release" + else + icu_build_variant_arg="--enable-debug" + fi + call mkdir -p "${LIBICU_BUILD_DIR}" + with_pushd "${LIBICU_BUILD_DIR}" \ + call "${LIBICU_SOURCE_DIR}"/source/configure \ + ${icu_build_variant_arg} --prefix=${ICU_TMPINSTALL} \ + --libdir=${ICU_TMPLIBDIR} \ + --enable-shared --enable-static \ + --enable-strict --disable-icuio \ + --disable-plugins --disable-dyload --disable-extras \ + --disable-samples --with-data-packaging=auto + else + echo "Skipping reconfiguration of libicu" + fi + with_pushd "${LIBICU_BUILD_DIR}" \ + call make install + ICU_LIBDIR="$(build_directory ${host} swift)/lib/swift/${SWIFT_HOST_VARIANT}/${SWIFT_HOST_VARIANT_ARCH}" + ICU_LIBDIR_STATIC="$(build_directory ${host} swift)/lib/swift_static/${SWIFT_HOST_VARIANT}" + ICU_LIBDIR_STATIC_ARCH="$(build_directory ${host} swift)/lib/swift_static/${SWIFT_HOST_VARIANT}/${SWIFT_HOST_VARIANT_ARCH}" + mkdir -p "${ICU_LIBDIR_STATIC_ARCH}" + # Copy the static libs into the swift_static directory + for l in uc i18n data + do + lib="${ICU_LIBDIR}/libicu${l}.a" + cp "${lib}" "${ICU_LIBDIR_STATIC}" + cp "${lib}" "${ICU_LIBDIR_STATIC_ARCH}" + done + + # Set the PKG_CONFIG_PATH so that core-foundation can find the libraries and + # header files + export PKG_CONFIG_PATH="${ICU_TMPLIBDIR}/pkgconfig" + swift_cmake_options=( + "${swift_cmake_options[@]}" + -DSWIFT_${SWIFT_HOST_VARIANT_SDK}_ICU_UC_INCLUDE:STRING="${ICU_TMPINSTALL}/include" + -DSWIFT_${SWIFT_HOST_VARIANT_SDK}_ICU_I18N_INCLUDE:STRING="${ICU_TMPINSTALL}/include" + -DSWIFT_${SWIFT_HOST_VARIANT_SDK}_ICU_STATICLIB:BOOL=TRUE + ) + # libicu builds itself and doesn't use cmake + continue + ;; playgroundlogger) PLAYGROUNDLOGGER_BUILD_DIR=$(build_directory ${host} ${product}) SWIFTC_BIN="$(build_directory_bin ${host} swift)/swiftc" @@ -2754,6 +2836,17 @@ for host in "${ALL_HOSTS[@]}"; do echo "--- Finished tests for ${product} ---" continue ;; + libicu) + if [[ "${SKIP_TEST_LIBICU}" ]]; then + continue + fi + LIBICU_BUILD_DIR=$(build_directory ${host} ${product}) + echo "--- Running tests for ${product} ---" + with_pushd "${LIBICU_BUILD_DIR}/test" \ + call make + echo "--- Finished tests for ${product} ---" + continue + ;; playgroundlogger) SWIFT_DYLIB_PATH=$(build_directory ${host} swift)/lib/swift/macosx/ PLAYGROUNDLOGGER_FRAMEWORK_PATH=$(build_directory ${host} ${product}) @@ -2994,6 +3087,32 @@ for host in "${ALL_HOSTS[@]}"; do # As libdispatch installation is self-contained, we break early here. continue ;; + libicu) + if [[ -z "${INSTALL_LIBICU}" ]]; then + continue + fi + if [[ -z "${INSTALL_DESTDIR}" ]] ; then + echo "--install-destdir is required to install products." + exit 1 + fi + echo "--- Installing ${product} ---" + LIBICU_BUILD_DIR=$(build_directory ${host} ${product}) + ICU_LIBDIR="$(build_directory ${host} swift)/lib/swift/${SWIFT_HOST_VARIANT}/${SWIFT_HOST_VARIANT_ARCH}" + LIBICU_DEST_DIR="$(get_host_install_destdir ${host})$(get_host_install_prefix ${host})lib/swift/${SWIFT_HOST_VARIANT}" + LIBICU_DEST_DIR_STATIC="$(get_host_install_destdir ${host})$(get_host_install_prefix ${host})lib/swift_static/${SWIFT_HOST_VARIANT}" + mkdir -p ${LIBICU_DEST_DIR} + mkdir -p ${LIBICU_DEST_DIR_STATIC} + for l in uc i18n data + do + lib=${ICU_LIBDIR}/libicu${l} + echo "${lib} => ${LIBICU_DEST_DIR}" + cp -d ${lib}.so ${lib}.so.* ${LIBICU_DEST_DIR} + cp -d ${lib}.so ${lib}.so.* ${LIBICU_DEST_DIR} + cp -d ${lib}.a ${LIBICU_DEST_DIR_STATIC} + cp -d ${lib}.a ${LIBICU_DEST_DIR_STATIC} + done + continue + ;; playgroundlogger) if [[ -z "${INSTALL_PLAYGROUNDLOGGER}" ]] ; then continue diff --git a/utils/gen-static-stdlib-link-args b/utils/gen-static-stdlib-link-args new file mode 100755 index 0000000000000..092c9c0cf2d2a --- /dev/null +++ b/utils/gen-static-stdlib-link-args @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +# +# Generate the static-stdlib-args.lnk used by the -static-stdlib option for +# 'GenericUnix' (eg linux) plaforms. If libicu is built locally then include +# libicudata +# + +SDK=$1 +OUTPUTFILE=$2 +ICU_STATIC_LIB=$3 + + +if [ "${ICU_STATIC_LIB}" == "TRUE" ]; then + read -d '' ICU_LIBS <$OUTPUTFILE <