diff --git a/CMakeLists.txt b/CMakeLists.txt index be571722fa7f7..d1483622e5f49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -480,7 +480,9 @@ endif() set(SWIFT_BUILD_HOST_DISPATCH FALSE) if(SWIFT_ENABLE_DISPATCH AND NOT CMAKE_SYSTEM_NAME STREQUAL Darwin) - if(SWIFT_BUILD_SYNTAXPARSERLIB OR SWIFT_BUILD_SOURCEKIT) + # Only build libdispatch for the host if the host tools are being built and + # specifically if these two libraries that depend on it are built. + if(SWIFT_INCLUDE_TOOLS AND (SWIFT_BUILD_SYNTAXPARSERLIB OR SWIFT_BUILD_SOURCEKIT)) set(SWIFT_BUILD_HOST_DISPATCH TRUE) endif() diff --git a/utils/build-script b/utils/build-script index e132c85c199b7..e19967df1fa40 100755 --- a/utils/build-script +++ b/utils/build-script @@ -841,6 +841,7 @@ class BuildScriptInvocation(object): """ args = self.args + args.build_root = self.workspace.build_root options = {} for host_target in [args.host_target] + args.cross_compile_hosts: @@ -862,6 +863,8 @@ class BuildScriptInvocation(object): config.swift_benchmark_run_targets), "SWIFT_TEST_TARGETS": " ".join( config.swift_test_run_targets), + "SWIFT_FLAGS": config.swift_flags, + "SWIFT_TARGET_CMAKE_OPTIONS": config.cmake_options, } return options diff --git a/utils/build-script-impl b/utils/build-script-impl index a29e7e122ba8f..1dd5bbe252954 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -139,7 +139,6 @@ KNOWN_SETTINGS=( common-cmake-options "" "CMake options used for all targets, including LLVM/Clang" extra-cmake-options "" "Extra options to pass to CMake for all targets" ninja-cmake-options "" "CMake options used for all ninja targets" - ninja-cmake-options "" "CMake options used for all ninja targets" ## Build ... build-llvm "1" "set to 1 to build LLVM and Clang" @@ -205,6 +204,7 @@ KNOWN_SETTINGS=( swift-stdlib-os-versioning "1" "whether to build stdlib with availability based on OS versions (Darwin only)" swift-stdlib-stable-abi "" "should stdlib be built with stable ABI, if not set defaults to true on Darwin, false otherwise" swift-disable-dead-stripping "0" "turns off Darwin-specific dead stripping for Swift host tools" + common-swift-flags "" "Flags used for Swift targets other than the stdlib, like the corelibs" ## FREESTANDING Stdlib Options swift-freestanding-sdk "" "which SDK to use when building the FREESTANDING stdlib" @@ -229,6 +229,7 @@ KNOWN_SETTINGS=( cross-compile-hosts "" "space-separated list of targets to cross-compile host Swift tools for" cross-compile-with-host-tools "" "set to use the clang we build for the host to then build the cross-compile hosts" cross-compile-install-prefixes "" "semicolon-separated list of install prefixes to use for the cross-compiled hosts. The list expands, so if there are more cross-compile hosts than prefixes, unmatched hosts use the last prefix in the list" + cross-compile-deps-path "" "path for CMake to look for cross-compiled library dependencies, such as libXML2" skip-merge-lipo-cross-compile-tools "" "set to skip running merge-lipo after installing cross-compiled host Swift tools" coverage-db "" "If set, coverage database to use when prioritizing testing" skip-local-host-install "" "If we are cross-compiling multiple targets, skip an install pass locally if the hosts match" @@ -1249,6 +1250,8 @@ function calculate_targets_for_host() { SWIFT_BENCHMARK_TARGETS=($(get_host_specific_variable ${host} SWIFT_BENCHMARK_TARGETS)) SWIFT_RUN_BENCHMARK_TARGETS=($(get_host_specific_variable ${host} SWIFT_RUN_BENCHMARK_TARGETS)) SWIFT_TEST_TARGETS=($(get_host_specific_variable ${host} SWIFT_TEST_TARGETS)) + SWIFT_FLAGS=($(get_host_specific_variable ${host} SWIFT_FLAGS)) + SWIFT_TARGET_CMAKE_OPTIONS=($(get_host_specific_variable ${host} SWIFT_TARGET_CMAKE_OPTIONS)) } @@ -1390,6 +1393,14 @@ function swift_c_flags() { fi } +function common_swift_flags() { + if [ "${module_cache}" == "" ] ; then + echo "error: a module cache path has not been set" + exit 1 + fi + echo -n "${SWIFT_FLAGS[@]} ${COMMON_SWIFT_FLAGS} -module-cache-path \"${module_cache}\" " +} + function cmake_config_opt() { product=$1 if [[ "${CMAKE_GENERATOR}" == "Xcode" ]] ; then @@ -1666,6 +1677,9 @@ for host in "${ALL_HOSTS[@]}"; do -DCMAKE_BUILD_TYPE:STRING="${CMARK_BUILD_TYPE}" "${cmark_cmake_options[@]}" ) + if [[ $(is_cross_tools_host ${host}) ]] ; then + cmake_options+=("${SWIFT_TARGET_CMAKE_OPTIONS[@]}") + fi build_targets=(all) ;; @@ -1793,6 +1807,7 @@ for host in "${ALL_HOSTS[@]}"; do -DCLANG_TABLEGEN=$(build_directory "${LOCAL_HOST}" llvm)/bin/clang-tblgen -DLLVM_NATIVE_BUILD=$(build_directory "${LOCAL_HOST}" llvm) ) + cmake_options+=("${SWIFT_TARGET_CMAKE_OPTIONS[@]}") fi ;; @@ -2205,7 +2220,7 @@ for host in "${ALL_HOSTS[@]}"; do -DCMAKE_CXX_COMPILER:PATH="${CLANG_BIN}/clang++" -DCMAKE_INSTALL_PREFIX:PATH="$(get_host_install_prefix ${host})" -DCMAKE_Swift_COMPILER:PATH=${SWIFTC_BIN} - -DCMAKE_Swift_FLAGS:STRING="-module-cache-path \"${module_cache}\"" + -DCMAKE_Swift_FLAGS:STRING="$(common_swift_flags)" -DLLBUILD_ENABLE_ASSERTIONS:BOOL=$(true_false "${LLBUILD_ENABLE_ASSERTIONS}") -DLLBUILD_SUPPORT_BINDINGS:=Swift @@ -2221,6 +2236,22 @@ for host in "${ALL_HOSTS[@]}"; do -DFoundation_DIR:PATH=$(build_directory ${host} foundation)/cmake/modules ) + if [[ $(is_cross_tools_host ${host}) ]] ; then + cmake_options+=("${SWIFT_TARGET_CMAKE_OPTIONS[@]}") + + # llbuild looks for the SQlite3 library using find_package(), + # so search for it in CROSS_COMPILE_DEPS_PATH using the CMake + # process for doing so and don't use cross-compiled + # executables, see the linked CMake docs for more info: + # + # https://cmake.org/cmake/help/latest/command/find_package.html + # https://cmake.org/cmake/help/latest/command/find_program.html + cmake_options+=( + -DCMAKE_FIND_ROOT_PATH:PATH="${CROSS_COMPILE_DEPS_PATH}" + -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER + ) + fi + # Ensure on Darwin platforms that we consider only the SQLite headers # from the SDK instead of picking ones found elsewhere # (e.g. in /usr/include ) @@ -2287,7 +2318,7 @@ for host in "${ALL_HOSTS[@]}"; do -DCMAKE_C_COMPILER:PATH="${CLANG_BIN}/clang" -DCMAKE_CXX_COMPILER:PATH="${CLANG_BIN}/clang++" -DCMAKE_Swift_COMPILER:PATH=${SWIFTC_BIN} - -DCMAKE_Swift_FLAGS:STRING="-module-cache-path \"${module_cache}\"" + -DCMAKE_Swift_FLAGS:STRING="$(common_swift_flags)" -DCMAKE_INSTALL_PREFIX:PATH="$(get_host_install_prefix ${host})" -DCMAKE_INSTALL_LIBDIR:PATH="lib" @@ -2303,6 +2334,9 @@ for host in "${ALL_HOSTS[@]}"; do -DENABLE_TESTING=YES ) + if [[ $(is_cross_tools_host ${host}) ]] ; then + cmake_options+=("${SWIFT_TARGET_CMAKE_OPTIONS[@]}") + fi ;; esac @@ -2356,7 +2390,7 @@ for host in "${ALL_HOSTS[@]}"; do -DCMAKE_CXX_COMPILER:PATH=${CLANG_BIN}/clang++ -DCMAKE_SWIFT_COMPILER:PATH=${SWIFTC_BIN} -DCMAKE_Swift_COMPILER:PATH=${SWIFTC_BIN} - -DCMAKE_Swift_FLAGS:STRING="-module-cache-path \"${module_cache}\"" + -DCMAKE_Swift_FLAGS:STRING="$(common_swift_flags)" -DCMAKE_INSTALL_PREFIX:PATH=$(get_host_install_prefix ${host}) ${LIBICU_BUILD_ARGS[@]} @@ -2372,6 +2406,24 @@ for host in "${ALL_HOSTS[@]}"; do -DBUILD_SHARED_LIBS=$([[ ${product} == foundation_static ]] && echo "NO" || echo "YES") ) + if [[ $(is_cross_tools_host ${host}) ]] ; then + cmake_options+=("${SWIFT_TARGET_CMAKE_OPTIONS[@]}") + + # Foundation looks for the ICU, libXML2 and libcurl libraries + # using find_package(), so search for them in + # CROSS_COMPILE_DEPS_PATH using the CMake process for doing + # so, see the linked CMake docs for more info: + # + # https://cmake.org/cmake/help/latest/command/find_package.html + cmake_options+=( + -DCMAKE_FIND_ROOT_PATH:PATH="${CROSS_COMPILE_DEPS_PATH}" + ) + fi + if [[ "${host}" == "android-"* ]]; then + cmake_options+=( + -DCMAKE_HAVE_LIBC_PTHREAD=True + ) + fi ;; libdispatch|libdispatch_static) LIBDISPATCH_BUILD_DIR=$(build_directory ${host} ${product}) @@ -2398,7 +2450,7 @@ for host in "${ALL_HOSTS[@]}"; do -DCMAKE_CXX_COMPILER:PATH="${CLANG_BIN}/clang++" -DCMAKE_SWIFT_COMPILER:PATH="${SWIFTC_BIN}" -DCMAKE_Swift_COMPILER:PATH="${SWIFTC_BIN}" - -DCMAKE_Swift_FLAGS:STRING="-module-cache-path \"${module_cache}\"" + -DCMAKE_Swift_FLAGS:STRING="$(common_swift_flags)" -DCMAKE_INSTALL_PREFIX:PATH="$(get_host_install_prefix ${host})" -DCMAKE_INSTALL_LIBDIR:PATH="lib" @@ -2407,6 +2459,9 @@ for host in "${ALL_HOSTS[@]}"; do -DENABLE_TESTING=YES -DBUILD_SHARED_LIBS=$([[ ${product} == libdispatch_static ]] && echo "NO" || echo "YES") ) + if [[ $(is_cross_tools_host ${host}) ]] ; then + cmake_options+=("${SWIFT_TARGET_CMAKE_OPTIONS[@]}") + fi ;; esac diff --git a/utils/swift_build_support/swift_build_support/host_specific_configuration.py b/utils/swift_build_support/swift_build_support/host_specific_configuration.py index 99bcf911f62d3..a50aee83c75a6 100644 --- a/utils/swift_build_support/swift_build_support/host_specific_configuration.py +++ b/utils/swift_build_support/swift_build_support/host_specific_configuration.py @@ -72,6 +72,8 @@ def __init__(self, host_target, args): self.swift_test_run_targets = [] self.swift_benchmark_build_targets = [] self.swift_benchmark_run_targets = [] + self.swift_flags = '' + self.cmake_options = '' for deployment_target_name in stdlib_targets_to_configure: # Get the target object. deployment_target = StdlibDeploymentTarget.get_target_for_name( @@ -203,6 +205,16 @@ def __init__(self, host_target, args): "check-swift{}-optimize_none_with_implicit_dynamic-{}" .format(subset_suffix, name)) + # Only pull in these flags when cross-compiling with + # --cross-compile-hosts. + if deployment_target_name != args.host_target and \ + host_target != args.host_target: + self.add_flags_for_cross_compilation(args, deployment_target) + + def add_flags_for_cross_compilation(self, args, deployment_target): + self.swift_flags = deployment_target.platform.swift_flags(args) + self.cmake_options = deployment_target.platform.cmake_options(args) + def __platforms_to_skip_build(self, args): platforms_to_skip_build = set() if not args.build_linux: diff --git a/utils/swift_build_support/swift_build_support/targets.py b/utils/swift_build_support/swift_build_support/targets.py index d068c0e006cb4..34364458ec736 100644 --- a/utils/swift_build_support/swift_build_support/targets.py +++ b/utils/swift_build_support/swift_build_support/targets.py @@ -68,6 +68,18 @@ def contains(self, target_name): return True return False + def swift_flags(self, args): + """ + Swift compiler flags for a platform, useful for cross-compiling + """ + return '' + + def cmake_options(self, args): + """ + CMake flags to build for a platform, useful for cross-compiling + """ + return '' + class DarwinPlatform(Platform): def __init__(self, name, archs, sdk_name=None, is_simulator=False): @@ -136,6 +148,29 @@ def uses_host_tests(self): """ return True + def swift_flags(self, args): + flags = '-target %s-unknown-linux-android%s ' % (args.android_arch, + args.android_api_level) + + flags += '-resource-dir %s/swift-%s-%s/lib/swift ' % ( + args.build_root, self.name, args.android_arch) + + android_toolchain_path = '%s/toolchains/llvm/prebuilt/%s' % ( + args.android_ndk, StdlibDeploymentTarget.host_target().name) + + flags += '-sdk %s/sysroot ' % (android_toolchain_path) + flags += '-tools-directory %s/bin' % (android_toolchain_path) + return flags + + def cmake_options(self, args): + options = '-DCMAKE_SYSTEM_NAME=Android ' + options += '-DCMAKE_SYSTEM_VERSION=%s ' % (args.android_api_level) + options += '-DCMAKE_SYSTEM_PROCESSOR=%s ' % (args.android_arch if not + args.android_arch == 'armv7' + else 'armv7-a') + options += '-DCMAKE_ANDROID_NDK:PATH=%s' % (args.android_ndk) + return options + class Target(object): """ diff --git a/validation-test/BuildSystem/android_cross_compile.test b/validation-test/BuildSystem/android_cross_compile.test new file mode 100644 index 0000000000000..18cca0ea60722 --- /dev/null +++ b/validation-test/BuildSystem/android_cross_compile.test @@ -0,0 +1,7 @@ +# REQUIRES: standalone_build + +# RUN: %empty-directory(%t) +# RUN: SWIFT_BUILD_ROOT=%t %swift_src_root/utils/build-script --dry-run --cmake %cmake --libdispatch --cross-compile-hosts=android-aarch64 --skip-local-build --android --android-ndk %t/ndk/ --android-arch aarch64 --android-icu-uc %t/lib/libicuuc.so --android-icu-uc-include %t/include/ --android-icu-i18n %t/lib/libicui18n.so --android-icu-i18n-include %t/include/ --android-icu-data %t/lib/libicudata.so 2>&1 | %FileCheck %s + +# CHECK: -DCMAKE_Swift_FLAGS{{.*}}-target {{.*}}unknown-linux-android{{.*}} -sdk +# CHECK: -DCMAKE_SYSTEM_NAME=Android {{.*}} -DCMAKE_ANDROID_NDK