diff --git a/swiftpm/Utilities/bootstrap b/swiftpm/Utilities/bootstrap index ead6af68..95a8427f 100755 --- a/swiftpm/Utilities/bootstrap +++ b/swiftpm/Utilities/bootstrap @@ -143,6 +143,9 @@ def add_build_args(parser): dest="cross_compile_hosts", help="List of cross compile hosts targets.", default=[]) + parser.add_argument( + "--cross-compile-flags", + help="Swift flags to cross-compile the PackageDescription libraries") def add_test_args(parser): """Configures the parser with the arguments necessary for the test action.""" @@ -195,15 +198,19 @@ def parse_build_args(args): args.clang_path = get_clang_path(args) args.cmake_path = get_cmake_path(args) args.ninja_path = get_ninja_path(args) - if args.cross_compile_hosts: # Use XCBuild target directory when building for multiple arches. - args.target_dir = os.path.join(args.build_dir, "apple/Products") + if args.cross_compile_hosts: + if "macosx-arm64" in args.cross_compile_hosts: + # Use XCBuild target directory when building for multiple arches. + args.target_dir = os.path.join(args.build_dir, "apple/Products") + elif re.match('android-', args.cross_compile_hosts): + args.target_dir = os.path.join(args.build_dir, get_build_target(args,cross_compile=True)) else: args.target_dir = os.path.join(args.build_dir, get_build_target(args)) args.bootstrap_dir = os.path.join(args.target_dir, "bootstrap") args.conf = 'release' if args.release else 'debug' args.bin_dir = os.path.join(args.target_dir, args.conf) - args.bootstrap = not args.skip_cmake_bootstrap or \ - not os.path.exists(os.path.join(os.path.split(args.swiftc_path)[0], "swift-build")) + args.bootstrap = not args.skip_cmake_bootstrap # or \ +# not os.path.exists(os.path.join(os.path.split(args.swiftc_path)[0], "swift-build")) def parse_test_args(args): """Parses and cleans arguments necessary for the test action.""" @@ -270,10 +277,13 @@ def get_ninja_path(args): else: return call_output(["which", "ninja"], verbose=args.verbose) -def get_build_target(args): +def get_build_target(args, cross_compile=False): """Returns the target-triple of the current machine.""" try: - target_info_json = subprocess.check_output([args.swiftc_path, '-print-target-info'], stderr=subprocess.PIPE, universal_newlines=True).strip() + if cross_compile: + target_info_json = subprocess.check_output([args.swiftc_path, '-print-target-info'] + args.cross_compile_flags.split(), stderr=subprocess.PIPE, universal_newlines=True).strip() + else: + target_info_json = subprocess.check_output([args.swiftc_path, '-print-target-info'], stderr=subprocess.PIPE, universal_newlines=True).strip() args.target_info = json.loads(target_info_json) return args.target_info["target"]["unversionedTriple"] except Exception as e: @@ -307,8 +317,11 @@ def build(args): build_yams(args) build_swift_argument_parser(args) build_swift_driver(args) + build_swiftpm_with_cmake(args) + + if args.cross_compile_flags: + build_packagedescription_libs_with_cmake(args) - build_swiftpm_with_cmake(args) build_swiftpm_with_swiftpm(args,integrated_swift_driver=False) def test(args): @@ -441,11 +454,15 @@ def install_binary(args, binary, dest_dir): # Build functions # ----------------------------------------------------------- -def build_with_cmake(args, cmake_args, source_path, build_dir, targets=[]): +def build_with_cmake(args, cmake_args, source_path, build_dir, targets=[], cross_compile=False): """Runs CMake if needed, then builds with Ninja.""" cache_path = os.path.join(build_dir, "CMakeCache.txt") if args.reconfigure or not os.path.isfile(cache_path) or not args.swiftc_path in open(cache_path).read(): - swift_flags = "" + if cross_compile: + swift_flags = args.cross_compile_flags + " -Xcc -I@TERMUX_PREFIX@/include" + else: + swift_flags = "" + if args.sysroot: swift_flags = "-sdk %s" % args.sysroot @@ -567,29 +584,37 @@ def add_rpath_for_cmake_build(args, rpath): note(' '.join(add_rpath_cmd)) subprocess.call(add_rpath_cmd, stderr=subprocess.PIPE) +def build_packagedescription_libs_with_cmake(args): + """Builds the PackageDescription libraries using CMake.""" + note("Building PackageDescription libraries (with CMake)") + + cmake_flags = ["-DFIND_PM_DEPS:BOOL=NO"] + targets = ["PD4", "PD4_2"] + if re.match('android-', args.cross_compile_hosts): + cmake_flags.append("-DCMAKE_SYSTEM_NAME=Android") + cmake_flags.append("-DCMAKE_SYSTEM_VERSION=1") + + build_with_cmake(args, cmake_flags, args.project_root, args.bootstrap_dir, + targets, cross_compile=True) + def build_swiftpm_with_cmake(args): """Builds SwiftPM using CMake.""" note("Building SwiftPM (with CMake)") - if args.bootstrap: - cmake_flags = [ - get_llbuild_cmake_arg(args), - "-DTSC_DIR=" + os.path.join(args.tsc_build_dir, "cmake/modules"), - "-DYams_DIR=" + os.path.join(args.yams_build_dir, "cmake/modules"), - "-DArgumentParser_DIR=" + os.path.join(args.swift_argument_parser_build_dir, "cmake/modules"), - "-DSwiftDriver_DIR=" + os.path.join(args.swift_driver_build_dir, "cmake/modules"), - "-DFIND_PM_DEPS:BOOL=YES", - ] - else: - cmake_flags = [ "-DFIND_PM_DEPS:BOOL=NO" ] + cmake_flags = [ + get_llbuild_cmake_arg(args), + "-DTSC_DIR=" + os.path.join(args.tsc_build_dir, "cmake/modules"), + "-DYams_DIR=" + os.path.join(args.yams_build_dir, "cmake/modules"), + "-DArgumentParser_DIR=" + os.path.join(args.swift_argument_parser_build_dir, "cmake/modules"), + "-DSwiftDriver_DIR=" + os.path.join(args.swift_driver_build_dir, "cmake/modules"), + "-DFIND_PM_DEPS:BOOL=YES", + ] if platform.system() == 'Darwin': cmake_flags.append("-DCMAKE_C_FLAGS=-target %s%s" % (get_build_target(args), g_macos_deployment_target)) cmake_flags.append("-DCMAKE_OSX_DEPLOYMENT_TARGET=%s" % g_macos_deployment_target) - targets = [] if args.bootstrap else ["PD4", "PD4_2"] - - build_with_cmake(args, cmake_flags, args.project_root, args.bootstrap_dir, targets) + build_with_cmake(args, cmake_flags, args.project_root, args.bootstrap_dir) if args.llbuild_link_framework: add_rpath_for_cmake_build(args, args.llbuild_build_dir) @@ -610,7 +610,10 @@ def build_swiftpm_with_swiftpm(args, integrated_swift_driver): swiftpm_args.append(os.path.join(args.bootstrap_dir, "bin/swift-build")) else: note("Building SwiftPM (with a prebuilt swift-build)") - swiftpm_args.append(os.path.join(os.path.split(args.swiftc_path)[0], "swift-build")) + if re.match('android-armv7', args.cross_compile_hosts): + swiftpm_args.append(os.path.join(os.path.realpath(os.getenv("SWIFT_BINDIR")), "swift-build")) + else: + swiftpm_args.append(os.path.join(os.path.split(args.swiftc_path)[0], "swift-build")) swiftpm_args.append("--disable-sandbox") @@ -763,8 +788,10 @@ def get_swiftpm_flags(args): ) # Don't use GNU strerror_r on Android. - if 'ANDROID_DATA' in os.environ: + if 'ANDROID_DATA' in os.environ or re.match( + 'android-', args.cross_compile_hosts): build_flags.extend(["-Xswiftc", "-Xcc", "-Xswiftc", "-U_GNU_SOURCE"]) + build_flags.extend(["-Xlinker", "-landroid-spawn"]) # On ELF platforms, remove the host toolchain's stdlib absolute rpath from # installed executables and shared libraries. @@ -775,6 +802,12 @@ def get_swiftpm_flags(args): cross_compile_hosts = args.cross_compile_hosts if build_target == 'x86_64-apple-macosx' and "macosx-arm64" in cross_compile_hosts: build_flags += ["--arch", "x86_64", "--arch", "arm64"] + elif cross_compile_hosts and re.match('android-', cross_compile_hosts): + build_flags.extend([ + "--destination", "@TERMUX_PKG_BUILDDIR@/swiftpm-android-flags.json", + "-Xlinker", "-rpath", "-Xlinker", "@TERMUX_PREFIX@/lib", + "-Xcc", "-I@TERMUX_PREFIX@/include", + ]) elif cross_compile_hosts: error("cannot cross-compile for %s" % cross_compile_hosts)