mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
2291 lines
87 KiB
Python
Executable File
2291 lines
87 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# utils/build-script - The ultimate tool for building Swift -*- python -*-
|
|
#
|
|
# This source file is part of the Swift.org open source project
|
|
#
|
|
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
# Licensed under Apache License v2.0 with Runtime Library Exception
|
|
#
|
|
# See https://swift.org/LICENSE.txt for license information
|
|
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import multiprocessing
|
|
import os
|
|
import pipes
|
|
import platform
|
|
import sys
|
|
import time
|
|
|
|
import android.adb.commands
|
|
|
|
from swift_build_support.swift_build_support import (
|
|
arguments,
|
|
debug,
|
|
diagnostics,
|
|
host,
|
|
migration,
|
|
products,
|
|
shell,
|
|
tar,
|
|
targets,
|
|
workspace
|
|
)
|
|
|
|
from swift_build_support.swift_build_support.SwiftBuildSupport import (
|
|
HOME,
|
|
SWIFT_BUILD_ROOT,
|
|
SWIFT_REPO_NAME,
|
|
SWIFT_SOURCE_ROOT,
|
|
get_all_preset_names,
|
|
get_preset_options,
|
|
)
|
|
|
|
from swift_build_support.swift_build_support.cmake import CMake
|
|
from swift_build_support.swift_build_support.targets import \
|
|
StdlibDeploymentTarget
|
|
from swift_build_support.swift_build_support.toolchain import host_toolchain
|
|
|
|
build_script_impl = os.path.join(
|
|
SWIFT_SOURCE_ROOT, SWIFT_REPO_NAME, "utils", "build-script-impl")
|
|
|
|
|
|
def exit_rejecting_arguments(message, parser=None):
|
|
print(message, file=sys.stderr)
|
|
if parser:
|
|
parser.print_usage(sys.stderr)
|
|
sys.exit(2) # 2 is the same as `argparse` error exit code.
|
|
|
|
|
|
def call_without_sleeping(command, env=None, dry_run=False, echo=False):
|
|
"""
|
|
Execute a command during which system sleep is disabled.
|
|
|
|
By default, this ignores the state of the `shell.dry_run` flag.
|
|
"""
|
|
|
|
# Disable system sleep, if possible.
|
|
if platform.system() == 'Darwin':
|
|
# Don't mutate the caller's copy of the arguments.
|
|
command = ["caffeinate"] + list(command)
|
|
|
|
shell.call(command, env=env, dry_run=dry_run, echo=echo)
|
|
|
|
|
|
class HostSpecificConfiguration(object):
|
|
|
|
"""Configuration information for an individual host."""
|
|
|
|
def __init__(self, host_target, invocation):
|
|
"""Initialize for the given `host_target`."""
|
|
|
|
# Compute the set of deployment targets to configure/build.
|
|
args = invocation.args
|
|
if host_target == args.host_target:
|
|
# This host is the user's desired product, so honor the requested
|
|
# set of targets to configure/build.
|
|
stdlib_targets_to_configure = args.stdlib_deployment_targets
|
|
if "all" in args.build_stdlib_deployment_targets:
|
|
stdlib_targets_to_build = set(stdlib_targets_to_configure)
|
|
else:
|
|
stdlib_targets_to_build = set(
|
|
args.build_stdlib_deployment_targets).intersection(
|
|
set(args.stdlib_deployment_targets))
|
|
else:
|
|
# Otherwise, this is a host we are building as part of
|
|
# cross-compiling, so we only need the target itself.
|
|
stdlib_targets_to_configure = [host_target]
|
|
stdlib_targets_to_build = set(stdlib_targets_to_configure)
|
|
|
|
# Compute the lists of **CMake** targets for each use case (configure
|
|
# vs. build vs. run) and the SDKs to configure with.
|
|
self.sdks_to_configure = set()
|
|
self.swift_stdlib_build_targets = []
|
|
self.swift_test_run_targets = []
|
|
self.swift_benchmark_build_targets = []
|
|
self.swift_benchmark_run_targets = []
|
|
for deployment_target_name in stdlib_targets_to_configure:
|
|
# Get the target object.
|
|
deployment_target = StdlibDeploymentTarget.get_target_for_name(
|
|
deployment_target_name)
|
|
if deployment_target is None:
|
|
diagnostics.fatal("unknown target: %r" % (
|
|
deployment_target_name,))
|
|
|
|
# Add the SDK to use.
|
|
deployment_platform = deployment_target.platform
|
|
self.sdks_to_configure.add(deployment_platform.sdk_name)
|
|
|
|
# If we aren't actually building this target (only configuring
|
|
# it), do nothing else.
|
|
if deployment_target_name not in stdlib_targets_to_build:
|
|
continue
|
|
|
|
# Compute which actions are desired.
|
|
build = (
|
|
deployment_platform not in invocation.platforms_to_skip_build)
|
|
test = (
|
|
deployment_platform not in invocation.platforms_to_skip_test)
|
|
test_host_only = None
|
|
build_benchmark = build and deployment_target.supports_benchmark
|
|
# FIXME: Note, `build-script-impl` computed a property here
|
|
# w.r.t. testing, but it was actually unused.
|
|
|
|
# For platforms which normally require a connected device to
|
|
# test, the default behavior is to run tests that only require
|
|
# the host (i.e., they do not attempt to execute).
|
|
if deployment_platform.is_darwin and \
|
|
deployment_platform.is_embedded and \
|
|
not deployment_platform.is_simulator:
|
|
if deployment_platform not in \
|
|
invocation.platforms_to_skip_test_host:
|
|
test_host_only = True
|
|
test = True
|
|
else:
|
|
test = False
|
|
|
|
name = deployment_target.name
|
|
|
|
for skip_test_arch in invocation.platforms_archs_to_skip_test:
|
|
if deployment_target.name == skip_test_arch.name:
|
|
test = False
|
|
|
|
if build:
|
|
# Validation and long tests require building the full standard
|
|
# library, whereas the other targets can build a slightly
|
|
# smaller subset which is faster to build.
|
|
if args.build_swift_stdlib_unittest_extra or \
|
|
args.validation_test or args.long_test:
|
|
self.swift_stdlib_build_targets.append(
|
|
"swift-stdlib-" + name)
|
|
else:
|
|
self.swift_stdlib_build_targets.append(
|
|
"swift-test-stdlib-" + name)
|
|
if build_benchmark:
|
|
self.swift_benchmark_build_targets.append(
|
|
"swift-benchmark-" + name)
|
|
# FIXME: This probably should respect `args.benchmark`, but
|
|
# a typo in build-script-impl meant we always would do this.
|
|
self.swift_benchmark_run_targets.append(
|
|
"check-swift-benchmark-" + name)
|
|
if test:
|
|
if test_host_only:
|
|
suffix = "-non-executable"
|
|
else:
|
|
suffix = ""
|
|
subset_suffix = ""
|
|
if args.validation_test and args.long_test:
|
|
subset_suffix = "-all"
|
|
elif args.validation_test:
|
|
subset_suffix = "-validation"
|
|
elif args.long_test:
|
|
subset_suffix = "-only_long"
|
|
else:
|
|
subset_suffix = ""
|
|
self.swift_test_run_targets.append("check-swift{}{}-{}".format(
|
|
subset_suffix, suffix, name))
|
|
if args.test_optimized and not test_host_only:
|
|
self.swift_test_run_targets.append(
|
|
"check-swift{}-optimize-{}".format(
|
|
subset_suffix, name))
|
|
|
|
|
|
class BuildScriptInvocation(object):
|
|
|
|
"""Represent a single build script invocation."""
|
|
|
|
@staticmethod
|
|
def validate_arguments(toolchain, args):
|
|
if toolchain.cc is None or toolchain.cxx is None:
|
|
diagnostics.fatal(
|
|
"can't find clang (please install clang-3.5 or a "
|
|
"later version)")
|
|
|
|
if toolchain.cmake is None:
|
|
diagnostics.fatal("can't find CMake (please install CMake)")
|
|
|
|
if args.distcc:
|
|
if toolchain.distcc is None:
|
|
diagnostics.fatal(
|
|
"can't find distcc (please install distcc)")
|
|
if toolchain.distcc_pump is None:
|
|
diagnostics.fatal(
|
|
"can't find distcc-pump (please install distcc-pump)")
|
|
|
|
if args.host_target is None or args.stdlib_deployment_targets is None:
|
|
diagnostics.fatal("unknown operating system")
|
|
|
|
if args.symbols_package:
|
|
if not os.path.isabs(args.symbols_package):
|
|
print(
|
|
'--symbols-package must be an absolute path '
|
|
'(was \'{}\')'.format(args.symbols_package))
|
|
return 1
|
|
if not args.install_symroot:
|
|
diagnostics.fatal(
|
|
"--install-symroot is required when specifying "
|
|
"--symbols-package.")
|
|
|
|
if args.android:
|
|
if args.android_ndk is None or \
|
|
args.android_api_level is None or \
|
|
args.android_icu_uc is None or \
|
|
args.android_icu_uc_include is None or \
|
|
args.android_icu_i18n is None or \
|
|
args.android_icu_i18n_include is None:
|
|
diagnostics.fatal(
|
|
"when building for Android, --android-ndk, "
|
|
"--android-ndk-version, --android-icu-uc, "
|
|
"--android-icu-uc-include, --android-icu-i18n, "
|
|
"and --android-icu-i18n-include must be specified")
|
|
|
|
@staticmethod
|
|
def apply_default_arguments(toolchain, args):
|
|
"""Preprocess an argument set to apply default behaviors."""
|
|
|
|
# Build cmark if any cmark-related options were specified.
|
|
if (args.cmark_build_variant is not None):
|
|
args.build_cmark = True
|
|
|
|
# Build LLDB if any LLDB-related options were specified.
|
|
if args.lldb_build_variant is not None or \
|
|
args.lldb_assertions is not None:
|
|
args.build_lldb = True
|
|
|
|
# Set the default build variant.
|
|
if args.build_variant is None:
|
|
args.build_variant = "Debug"
|
|
|
|
# Set the default stdlib-deployment-targets, if none were provided.
|
|
if args.stdlib_deployment_targets is None:
|
|
stdlib_targets = \
|
|
StdlibDeploymentTarget.default_stdlib_deployment_targets()
|
|
args.stdlib_deployment_targets = [
|
|
target.name for target in stdlib_targets]
|
|
|
|
if args.llvm_build_variant is None:
|
|
args.llvm_build_variant = args.build_variant
|
|
|
|
if args.swift_build_variant is None:
|
|
args.swift_build_variant = args.build_variant
|
|
|
|
if args.swift_stdlib_build_variant is None:
|
|
args.swift_stdlib_build_variant = args.build_variant
|
|
|
|
if args.cmark_build_variant is None:
|
|
args.cmark_build_variant = args.swift_build_variant
|
|
|
|
if args.lldb_build_variant is None:
|
|
args.lldb_build_variant = args.build_variant
|
|
|
|
if args.foundation_build_variant is None:
|
|
args.foundation_build_variant = args.build_variant
|
|
|
|
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
|
|
|
|
# Propagate the default assertions setting.
|
|
if args.cmark_assertions is None:
|
|
args.cmark_assertions = args.assertions
|
|
|
|
if args.llvm_assertions is None:
|
|
args.llvm_assertions = args.assertions
|
|
|
|
if args.swift_assertions is None:
|
|
args.swift_assertions = args.assertions
|
|
|
|
if args.swift_stdlib_assertions is None:
|
|
args.swift_stdlib_assertions = args.assertions
|
|
|
|
# Set the default CMake generator.
|
|
if args.cmake_generator is None:
|
|
args.cmake_generator = "Ninja"
|
|
|
|
# --ios-all etc are not supported by open-source Swift.
|
|
if args.ios_all:
|
|
exit_rejecting_arguments("error: --ios-all is unavailable in " +
|
|
"open-source Swift.\nUse --ios to " +
|
|
"skip iOS device tests.")
|
|
|
|
if args.tvos_all:
|
|
exit_rejecting_arguments("error: --tvos-all is unavailable in " +
|
|
"open-source Swift.\nUse --tvos to " +
|
|
"skip tvOS device tests.")
|
|
|
|
if args.watchos_all:
|
|
exit_rejecting_arguments("error: --watchos-all is unavailable " +
|
|
"in open-source Swift.\nUse --watchos " +
|
|
"to skip watchOS device tests.")
|
|
|
|
ninja_required = (
|
|
args.cmake_generator == 'Ninja' or args.build_foundation)
|
|
if ninja_required and toolchain.ninja is None:
|
|
args.build_ninja = True
|
|
|
|
# SwiftPM and XCTest have a dependency on Foundation.
|
|
# On OS X, Foundation is built automatically using xcodebuild.
|
|
# On Linux, we must ensure that it is built manually.
|
|
if ((args.build_swiftpm or args.build_xctest) and
|
|
platform.system() != "Darwin"):
|
|
args.build_foundation = True
|
|
|
|
# Foundation has a dependency on libdispatch.
|
|
# On OS X, libdispatch is provided by the OS.
|
|
# On Linux, we must ensure that it is built manually.
|
|
if (args.build_foundation and
|
|
platform.system() != "Darwin"):
|
|
args.build_libdispatch = True
|
|
|
|
# Propagate global --skip-build
|
|
if args.skip_build:
|
|
args.skip_build_linux = True
|
|
args.skip_build_freebsd = True
|
|
args.skip_build_cygwin = True
|
|
args.skip_build_osx = True
|
|
args.skip_build_ios = True
|
|
args.skip_build_tvos = True
|
|
args.skip_build_watchos = True
|
|
args.skip_build_android = True
|
|
args.skip_build_benchmarks = True
|
|
args.build_lldb = False
|
|
args.build_llbuild = False
|
|
args.build_swiftpm = False
|
|
args.build_xctest = False
|
|
args.build_foundation = False
|
|
args.build_libdispatch = False
|
|
args.build_libicu = False
|
|
args.build_playgroundlogger = False
|
|
args.build_playgroundsupport = False
|
|
|
|
# --skip-{ios,tvos,watchos} or --skip-build-{ios,tvos,watchos} are
|
|
# merely shorthands for --skip-build-{**os}-{device,simulator}
|
|
if not args.ios or args.skip_build_ios:
|
|
args.skip_build_ios_device = True
|
|
args.skip_build_ios_simulator = True
|
|
|
|
if not args.tvos or args.skip_build_tvos:
|
|
args.skip_build_tvos_device = True
|
|
args.skip_build_tvos_simulator = True
|
|
|
|
if not args.watchos or args.skip_build_watchos:
|
|
args.skip_build_watchos_device = True
|
|
args.skip_build_watchos_simulator = True
|
|
|
|
if not args.android or args.skip_build_android:
|
|
args.skip_build_android = True
|
|
|
|
# --validation-test implies --test.
|
|
if args.validation_test:
|
|
args.test = True
|
|
|
|
# --test-optimized implies --test.
|
|
if args.test_optimized:
|
|
args.test = True
|
|
|
|
# If none of tests specified skip swift stdlib test on all platforms
|
|
if not args.test and not args.validation_test and not args.long_test:
|
|
args.skip_test_linux = True
|
|
args.skip_test_freebsd = True
|
|
args.skip_test_cygwin = True
|
|
args.skip_test_osx = True
|
|
args.skip_test_ios = True
|
|
args.skip_test_tvos = True
|
|
args.skip_test_watchos = True
|
|
|
|
# --skip-test-ios is merely a shorthand for host and simulator tests.
|
|
if args.skip_test_ios:
|
|
args.skip_test_ios_host = True
|
|
args.skip_test_ios_simulator = True
|
|
# --skip-test-tvos is merely a shorthand for host and simulator tests.
|
|
if args.skip_test_tvos:
|
|
args.skip_test_tvos_host = True
|
|
args.skip_test_tvos_simulator = True
|
|
# --skip-test-watchos is merely a shorthand for host and simulator
|
|
# --tests.
|
|
if args.skip_test_watchos:
|
|
args.skip_test_watchos_host = True
|
|
args.skip_test_watchos_simulator = True
|
|
|
|
# --skip-build-{ios,tvos,watchos}-{device,simulator} implies
|
|
# --skip-test-{ios,tvos,watchos}-{host,simulator}
|
|
if args.skip_build_ios_device:
|
|
args.skip_test_ios_host = True
|
|
if args.skip_build_ios_simulator:
|
|
args.skip_test_ios_simulator = True
|
|
|
|
if args.skip_build_tvos_device:
|
|
args.skip_test_tvos_host = True
|
|
if args.skip_build_tvos_simulator:
|
|
args.skip_test_tvos_simulator = True
|
|
|
|
if args.skip_build_watchos_device:
|
|
args.skip_test_watchos_host = True
|
|
if args.skip_build_watchos_simulator:
|
|
args.skip_test_watchos_simulator = True
|
|
|
|
if args.skip_build_android:
|
|
args.skip_test_android_host = True
|
|
|
|
if not args.host_test:
|
|
args.skip_test_ios_host = True
|
|
args.skip_test_tvos_host = True
|
|
args.skip_test_watchos_host = True
|
|
args.skip_test_android_host = True
|
|
|
|
if args.build_subdir is None:
|
|
args.build_subdir = \
|
|
workspace.compute_build_subdir(args)
|
|
|
|
# Add optional stdlib-deployment-targets
|
|
if args.android:
|
|
args.stdlib_deployment_targets.append(
|
|
StdlibDeploymentTarget.Android.armv7.name)
|
|
|
|
# Infer platform flags from manually-specified configure targets.
|
|
# This doesn't apply to Darwin platforms, as they are
|
|
# already configured. No building without the platform flag, though.
|
|
|
|
android_tgts = [tgt for tgt in args.stdlib_deployment_targets
|
|
if StdlibDeploymentTarget.Android.contains(tgt)]
|
|
if not args.android and len(android_tgts) > 0:
|
|
args.android = True
|
|
args.skip_build_android = True
|
|
|
|
# ---
|
|
|
|
def __init__(self, toolchain, args):
|
|
self.toolchain = toolchain
|
|
self.args = args
|
|
|
|
self.workspace = workspace.Workspace(
|
|
source_root=SWIFT_SOURCE_ROOT,
|
|
build_root=os.path.join(SWIFT_BUILD_ROOT, args.build_subdir))
|
|
|
|
# Compute derived information from the arguments.
|
|
#
|
|
# FIXME: We should move the platform-derived arguments to be entirely
|
|
# data driven, so that we can eliminate this code duplication and just
|
|
# iterate over all supported platforms.
|
|
|
|
self.platforms_to_skip_build = set()
|
|
if args.skip_build_linux:
|
|
self.platforms_to_skip_build.add(StdlibDeploymentTarget.Linux)
|
|
if args.skip_build_freebsd:
|
|
self.platforms_to_skip_build.add(StdlibDeploymentTarget.FreeBSD)
|
|
if args.skip_build_cygwin:
|
|
self.platforms_to_skip_build.add(StdlibDeploymentTarget.Cygwin)
|
|
if args.skip_build_osx:
|
|
self.platforms_to_skip_build.add(StdlibDeploymentTarget.OSX)
|
|
if args.skip_build_ios_device:
|
|
self.platforms_to_skip_build.add(StdlibDeploymentTarget.iOS)
|
|
if args.skip_build_ios_simulator:
|
|
self.platforms_to_skip_build.add(
|
|
StdlibDeploymentTarget.iOSSimulator)
|
|
if args.skip_build_tvos_device:
|
|
self.platforms_to_skip_build.add(StdlibDeploymentTarget.AppleTV)
|
|
if args.skip_build_tvos_simulator:
|
|
self.platforms_to_skip_build.add(
|
|
StdlibDeploymentTarget.AppleTVSimulator)
|
|
if args.skip_build_watchos_device:
|
|
self.platforms_to_skip_build.add(StdlibDeploymentTarget.AppleWatch)
|
|
if args.skip_build_watchos_simulator:
|
|
self.platforms_to_skip_build.add(
|
|
StdlibDeploymentTarget.AppleWatchSimulator)
|
|
if args.skip_build_android:
|
|
self.platforms_to_skip_build.add(StdlibDeploymentTarget.Android)
|
|
|
|
self.platforms_to_skip_test = set()
|
|
self.platforms_archs_to_skip_test = set()
|
|
if args.skip_test_linux:
|
|
self.platforms_to_skip_test.add(StdlibDeploymentTarget.Linux)
|
|
if args.skip_test_freebsd:
|
|
self.platforms_to_skip_test.add(StdlibDeploymentTarget.FreeBSD)
|
|
if args.skip_test_cygwin:
|
|
self.platforms_to_skip_test.add(StdlibDeploymentTarget.Cygwin)
|
|
if args.skip_test_osx:
|
|
self.platforms_to_skip_test.add(StdlibDeploymentTarget.OSX)
|
|
if args.skip_test_ios_host:
|
|
self.platforms_to_skip_test.add(StdlibDeploymentTarget.iOS)
|
|
else:
|
|
exit_rejecting_arguments("error: iOS device tests are not " +
|
|
"supported in open-source Swift.")
|
|
if args.skip_test_ios_simulator:
|
|
self.platforms_to_skip_test.add(
|
|
StdlibDeploymentTarget.iOSSimulator)
|
|
if args.skip_test_ios_32bit_simulator:
|
|
self.platforms_archs_to_skip_test.add(
|
|
StdlibDeploymentTarget.iOSSimulator.i386)
|
|
if args.skip_test_tvos_host:
|
|
self.platforms_to_skip_test.add(StdlibDeploymentTarget.AppleTV)
|
|
else:
|
|
exit_rejecting_arguments("error: tvOS device tests are not " +
|
|
"supported in open-source Swift.")
|
|
if args.skip_test_tvos_simulator:
|
|
self.platforms_to_skip_test.add(
|
|
StdlibDeploymentTarget.AppleTVSimulator)
|
|
if args.skip_test_watchos_host:
|
|
self.platforms_to_skip_test.add(StdlibDeploymentTarget.AppleWatch)
|
|
else:
|
|
exit_rejecting_arguments("error: watchOS device tests are not " +
|
|
"supported in open-source Swift.")
|
|
if args.skip_test_watchos_simulator:
|
|
self.platforms_to_skip_test.add(
|
|
StdlibDeploymentTarget.AppleWatchSimulator)
|
|
|
|
if args.skip_test_android_host:
|
|
self.platforms_to_skip_test.add(StdlibDeploymentTarget.Android)
|
|
|
|
self.platforms_to_skip_test_host = set()
|
|
if args.skip_test_ios_host:
|
|
self.platforms_to_skip_test_host.add(StdlibDeploymentTarget.iOS)
|
|
if args.skip_test_tvos_host:
|
|
self.platforms_to_skip_test_host.add(
|
|
StdlibDeploymentTarget.AppleTV)
|
|
if args.skip_test_watchos_host:
|
|
self.platforms_to_skip_test_host.add(
|
|
StdlibDeploymentTarget.AppleWatch)
|
|
|
|
def initialize_runtime_environment(self):
|
|
"""Change the program environment for building."""
|
|
|
|
# Set an appropriate default umask.
|
|
os.umask(0o022)
|
|
|
|
# Unset environment variables that might affect how tools behave.
|
|
for v in [
|
|
'MAKEFLAGS',
|
|
'SDKROOT',
|
|
'MACOSX_DEPLOYMENT_TARGET',
|
|
'IPHONEOS_DEPLOYMENT_TARGET',
|
|
'TVOS_DEPLOYMENT_TARGET',
|
|
'WATCHOS_DEPLOYMENT_TARGET']:
|
|
os.environ.pop(v, None)
|
|
|
|
def build_ninja(self):
|
|
if not os.path.exists(self.workspace.source_dir("ninja")):
|
|
diagnostics.fatal(
|
|
"can't find source directory for ninja "
|
|
"(tried %s)" % (self.workspace.source_dir("ninja")))
|
|
|
|
ninja_build = products.Ninja(
|
|
args=self.args,
|
|
toolchain=self.toolchain,
|
|
source_dir=self.workspace.source_dir("ninja"),
|
|
build_dir=self.workspace.build_dir("build", "ninja"))
|
|
ninja_build.do_build()
|
|
self.toolchain.ninja = ninja_build.ninja_bin_path
|
|
|
|
def convert_to_impl_arguments(self):
|
|
"""convert_to_impl_arguments() -> (env, args)
|
|
|
|
Convert the invocation to an environment and list of arguments suitable
|
|
for invoking `build-script-impl`.
|
|
"""
|
|
|
|
# Create local shadows, for convenience.
|
|
args = self.args
|
|
toolchain = self.toolchain
|
|
|
|
cmake = CMake(args=args,
|
|
toolchain=self.toolchain)
|
|
|
|
impl_args = [
|
|
"--workspace", self.workspace.source_root,
|
|
"--build-dir", self.workspace.build_root,
|
|
"--install-prefix", args.install_prefix,
|
|
"--host-target", args.host_target,
|
|
"--stdlib-deployment-targets",
|
|
" ".join(args.stdlib_deployment_targets),
|
|
"--host-cc", toolchain.cc,
|
|
"--host-cxx", toolchain.cxx,
|
|
"--darwin-xcrun-toolchain", args.darwin_xcrun_toolchain,
|
|
"--darwin-deployment-version-osx=%s" % (
|
|
args.darwin_deployment_version_osx),
|
|
"--darwin-deployment-version-ios=%s" % (
|
|
args.darwin_deployment_version_ios),
|
|
"--darwin-deployment-version-tvos=%s" % (
|
|
args.darwin_deployment_version_tvos),
|
|
"--darwin-deployment-version-watchos=%s" % (
|
|
args.darwin_deployment_version_watchos),
|
|
"--cmake", toolchain.cmake,
|
|
"--cmark-build-type", args.cmark_build_variant,
|
|
"--llvm-build-type", args.llvm_build_variant,
|
|
"--swift-build-type", args.swift_build_variant,
|
|
"--swift-stdlib-build-type", args.swift_stdlib_build_variant,
|
|
"--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,
|
|
"--swiftpm-build-type", args.build_variant,
|
|
"--swift-enable-assertions", str(args.swift_assertions).lower(),
|
|
"--swift-stdlib-enable-assertions", str(
|
|
args.swift_stdlib_assertions).lower(),
|
|
"--swift-analyze-code-coverage", str(
|
|
args.swift_analyze_code_coverage).lower(),
|
|
"--cmake-generator", args.cmake_generator,
|
|
"--build-jobs", str(args.build_jobs),
|
|
"--common-cmake-options=%s" % ' '.join(
|
|
pipes.quote(opt) for opt in cmake.common_options()),
|
|
"--build-args=%s" % ' '.join(
|
|
pipes.quote(arg) for arg in cmake.build_args()),
|
|
]
|
|
|
|
# Compute any product specific cmake arguments.
|
|
for product_class in self.compute_product_classes():
|
|
product_name = product_class.product_name()
|
|
product_source_name = product_class.product_source_name()
|
|
source_dir = self.workspace.source_dir(product_source_name)
|
|
|
|
if not os.path.exists(source_dir):
|
|
diagnostics.fatal(
|
|
"can't find source directory for %s "
|
|
"(tried %s)" % (product_name, source_dir))
|
|
|
|
product = product_class(
|
|
args=args,
|
|
toolchain=self.toolchain,
|
|
source_dir=source_dir,
|
|
# FIXME: This is incorrect since it always assumes the host
|
|
# target I think?
|
|
build_dir=self.workspace.build_dir(
|
|
args.host_target, product_name))
|
|
cmake_opts = product.cmake_options
|
|
|
|
# FIXME: We should be using pipes.quote here but we run into issues
|
|
# with build-script-impl/cmake not being happy with all of the
|
|
# extra "'" in the strings. To fix this easily, we really need to
|
|
# just invoke cmake from build-script directly rather than futzing
|
|
# with build-script-impl. This makes even more sense since there
|
|
# really isn't a security issue here.
|
|
impl_args += [
|
|
"--%s-cmake-options=%s" % (product_name, ' '.join(cmake_opts))
|
|
]
|
|
|
|
if args.build_stdlib_deployment_targets:
|
|
impl_args += [
|
|
"--build-stdlib-deployment-targets", " ".join(
|
|
args.build_stdlib_deployment_targets)]
|
|
if args.cross_compile_hosts:
|
|
impl_args += [
|
|
"--cross-compile-hosts", " ".join(args.cross_compile_hosts)]
|
|
|
|
if toolchain.ninja:
|
|
impl_args += ["--ninja-bin=%s" % toolchain.ninja]
|
|
if args.distcc:
|
|
impl_args += [
|
|
"--distcc",
|
|
"--distcc-pump=%s" % toolchain.distcc_pump
|
|
]
|
|
|
|
# *NOTE* We use normal cmake to pass through tsan/ubsan options. We do
|
|
# NOT pass them to build-script-impl.
|
|
if args.enable_asan:
|
|
impl_args += ["--enable-asan"]
|
|
# If we have lsan, we need to export our suppression list. The actual
|
|
# passing in of the LSAN flag is done via the normal cmake method. We
|
|
# do not pass the flag to build-script-impl.
|
|
if args.enable_lsan:
|
|
supp_file = os.path.join(SWIFT_SOURCE_ROOT, SWIFT_REPO_NAME,
|
|
"utils",
|
|
"lsan_leaks_suppression_list.txt")
|
|
os.environ['LSAN_OPTIONS'] = 'suppressions={}'.format(supp_file)
|
|
if args.verbose_build:
|
|
impl_args += ["--verbose-build"]
|
|
if args.install_symroot:
|
|
impl_args += [
|
|
"--install-symroot", os.path.abspath(args.install_symroot)
|
|
]
|
|
|
|
if args.skip_build:
|
|
impl_args += ["--skip-build-cmark",
|
|
"--skip-build-llvm",
|
|
"--skip-build-swift"]
|
|
if args.skip_build_benchmarks:
|
|
impl_args += ["--skip-build-benchmarks"]
|
|
if not args.build_foundation:
|
|
impl_args += ["--skip-build-foundation"]
|
|
if not args.build_xctest:
|
|
impl_args += ["--skip-build-xctest"]
|
|
if not args.build_lldb:
|
|
impl_args += ["--skip-build-lldb"]
|
|
if not args.build_llbuild:
|
|
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:
|
|
impl_args += ["--skip-build-playgroundlogger"]
|
|
if not args.build_playgroundsupport:
|
|
impl_args += ["--skip-build-playgroundsupport"]
|
|
if args.build_swift_dynamic_stdlib:
|
|
impl_args += ["--build-swift-dynamic-stdlib"]
|
|
if args.build_swift_static_stdlib:
|
|
impl_args += ["--build-swift-static-stdlib"]
|
|
if args.build_swift_stdlib_unittest_extra:
|
|
impl_args += ["--build-swift-stdlib-unittest-extra"]
|
|
if args.build_swift_dynamic_sdk_overlay:
|
|
impl_args += ["--build-swift-dynamic-sdk-overlay"]
|
|
if args.build_swift_static_sdk_overlay:
|
|
impl_args += ["--build-swift-static-sdk-overlay"]
|
|
|
|
if args.skip_build_linux:
|
|
impl_args += ["--skip-build-linux"]
|
|
if args.skip_build_freebsd:
|
|
impl_args += ["--skip-build-freebsd"]
|
|
if args.skip_build_cygwin:
|
|
impl_args += ["--skip-build-cygwin"]
|
|
if args.skip_build_osx:
|
|
impl_args += ["--skip-build-osx"]
|
|
if args.skip_build_ios_device:
|
|
impl_args += ["--skip-build-ios-device"]
|
|
if args.skip_build_ios_simulator:
|
|
impl_args += ["--skip-build-ios-simulator"]
|
|
if args.skip_build_tvos_device:
|
|
impl_args += ["--skip-build-tvos-device"]
|
|
if args.skip_build_tvos_simulator:
|
|
impl_args += ["--skip-build-tvos-simulator"]
|
|
if args.skip_build_watchos_device:
|
|
impl_args += ["--skip-build-watchos-device"]
|
|
if args.skip_build_watchos_simulator:
|
|
impl_args += ["--skip-build-watchos-simulator"]
|
|
if args.skip_build_android:
|
|
impl_args += ["--skip-build-android"]
|
|
|
|
if not args.test and not args.long_test:
|
|
impl_args += ["--skip-test-swift"]
|
|
if not args.test:
|
|
impl_args += ["--skip-test-cmark",
|
|
"--skip-test-lldb",
|
|
"--skip-test-llbuild",
|
|
"--skip-test-swiftpm",
|
|
"--skip-test-xctest",
|
|
"--skip-test-foundation",
|
|
"--skip-test-libdispatch",
|
|
"--skip-test-libicu",
|
|
"--skip-test-playgroundlogger",
|
|
"--skip-test-playgroundsupport"]
|
|
if args.skip_test_linux:
|
|
impl_args += ["--skip-test-linux"]
|
|
if args.skip_test_freebsd:
|
|
impl_args += ["--skip-test-freebsd"]
|
|
if args.skip_test_cygwin:
|
|
impl_args += ["--skip-test-cygwin"]
|
|
if args.skip_test_osx:
|
|
impl_args += ["--skip-test-osx"]
|
|
if args.skip_test_ios_host:
|
|
impl_args += ["--skip-test-ios-host"]
|
|
if args.skip_test_ios_simulator:
|
|
impl_args += ["--skip-test-ios-simulator"]
|
|
if args.skip_test_ios_32bit_simulator:
|
|
impl_args += ["--skip-test-ios-32bit-simulator"]
|
|
if args.skip_test_tvos_host:
|
|
impl_args += ["--skip-test-tvos-host"]
|
|
if args.skip_test_tvos_simulator:
|
|
impl_args += ["--skip-test-tvos-simulator"]
|
|
if args.skip_test_watchos_host:
|
|
impl_args += ["--skip-test-watchos-host"]
|
|
if args.skip_test_watchos_simulator:
|
|
impl_args += ["--skip-test-watchos-simulator"]
|
|
if args.skip_test_android_host:
|
|
impl_args += ["--skip-test-android-host"]
|
|
if args.build_runtime_with_host_compiler:
|
|
impl_args += ["--build-runtime-with-host-compiler"]
|
|
if args.validation_test:
|
|
impl_args += ["--validation-test"]
|
|
if args.long_test:
|
|
impl_args += ["--long-test"]
|
|
if not args.benchmark:
|
|
impl_args += ["--skip-test-benchmarks"]
|
|
if not args.test_optimized:
|
|
impl_args += ["--skip-test-optimized"]
|
|
|
|
if args.android:
|
|
impl_args += [
|
|
"--android-ndk", args.android_ndk,
|
|
"--android-api-level", args.android_api_level,
|
|
"--android-ndk-gcc-version",
|
|
args.android_ndk_gcc_version,
|
|
"--android-icu-uc", args.android_icu_uc,
|
|
"--android-icu-uc-include", args.android_icu_uc_include,
|
|
"--android-icu-i18n", args.android_icu_i18n,
|
|
"--android-icu-i18n-include", args.android_icu_i18n_include,
|
|
]
|
|
if args.android_deploy_device_path:
|
|
impl_args += [
|
|
"--android-deploy-device-path",
|
|
args.android_deploy_device_path,
|
|
]
|
|
|
|
if platform.system() == 'Darwin':
|
|
impl_args += [
|
|
"--toolchain-prefix",
|
|
targets.darwin_toolchain_prefix(
|
|
args.install_prefix),
|
|
"--host-lipo", toolchain.lipo,
|
|
]
|
|
|
|
if toolchain.libtool is not None:
|
|
impl_args += [
|
|
"--host-libtool", toolchain.libtool,
|
|
]
|
|
|
|
# If we have extra_swift_args, combine all of them together and then
|
|
# add them as one command.
|
|
if args.extra_swift_args:
|
|
impl_args += [
|
|
"--extra-swift-args",
|
|
";".join(args.extra_swift_args)]
|
|
|
|
# If we have extra_cmake_options, combine all of them together and then
|
|
# add them as one command.
|
|
if args.extra_cmake_options:
|
|
impl_args += [
|
|
"--extra-cmake-options=%s" % ' '.join(
|
|
pipes.quote(opt) for opt in args.extra_cmake_options)
|
|
]
|
|
|
|
if args.lto_type is not None:
|
|
impl_args += [
|
|
"--llvm-enable-lto=%s" % args.lto_type,
|
|
"--swift-tools-enable-lto=%s" % args.lto_type
|
|
]
|
|
if args.llvm_max_parallel_lto_link_jobs is not None:
|
|
impl_args += [
|
|
"--llvm-num-parallel-lto-link-jobs=%s" %
|
|
min(args.llvm_max_parallel_lto_link_jobs, args.build_jobs)
|
|
]
|
|
if args.swift_tools_max_parallel_lto_link_jobs is not None:
|
|
impl_args += [
|
|
"--swift-tools-num-parallel-lto-link-jobs=%s" %
|
|
min(args.swift_tools_max_parallel_lto_link_jobs,
|
|
args.build_jobs)
|
|
]
|
|
|
|
impl_args += args.build_script_impl_args
|
|
|
|
if args.dry_run:
|
|
impl_args += ["--dry-run"]
|
|
|
|
if args.clang_profile_instr_use:
|
|
impl_args += [
|
|
"--clang-profile-instr-use=%s" %
|
|
os.path.abspath(args.clang_profile_instr_use)
|
|
]
|
|
|
|
if args.lit_args:
|
|
impl_args += ["--llvm-lit-args=%s" % args.lit_args]
|
|
|
|
if args.coverage_db:
|
|
impl_args += [
|
|
"--coverage-db=%s" %
|
|
os.path.abspath(args.coverage_db)
|
|
]
|
|
|
|
# Compute the set of host-specific variables, which we pass through to
|
|
# the build script via environment variables.
|
|
host_specific_variables = self.compute_host_specific_variables()
|
|
impl_env = {}
|
|
for (host_target, options) in host_specific_variables.items():
|
|
for (name, value) in options.items():
|
|
# We mangle into an environment variable we can easily evaluate
|
|
# from the `build-script-impl`.
|
|
impl_env["HOST_VARIABLE_{}__{}".format(
|
|
host_target.replace("-", "_"), name)] = value
|
|
|
|
return (impl_env, impl_args)
|
|
|
|
def compute_host_specific_variables(self):
|
|
"""compute_host_specific_variables(args) -> dict
|
|
|
|
Compute the host-specific options, organized as a dictionary keyed by
|
|
host of options.
|
|
"""
|
|
|
|
args = self.args
|
|
|
|
options = {}
|
|
for host_target in [args.host_target] + args.cross_compile_hosts:
|
|
# Compute the host specific configuration.
|
|
config = HostSpecificConfiguration(host_target, self)
|
|
|
|
# Convert into `build-script-impl` style variables.
|
|
options[host_target] = {
|
|
"SWIFT_SDKS": " ".join(sorted(
|
|
config.sdks_to_configure)),
|
|
"SWIFT_STDLIB_TARGETS": " ".join(
|
|
config.swift_stdlib_build_targets),
|
|
"SWIFT_BENCHMARK_TARGETS": " ".join(
|
|
config.swift_benchmark_build_targets),
|
|
"SWIFT_RUN_BENCHMARK_TARGETS": " ".join(
|
|
config.swift_benchmark_run_targets),
|
|
"SWIFT_TEST_TARGETS": " ".join(
|
|
config.swift_test_run_targets),
|
|
}
|
|
|
|
return options
|
|
|
|
def compute_product_classes(self):
|
|
"""compute_product_classes() -> list
|
|
|
|
Compute the list of all Product classes used in this build. This list
|
|
is constructed in dependency order.
|
|
"""
|
|
|
|
# FIXME: This is a weird division (returning a list of class objects),
|
|
# but it matches the existing structure of the `build-script-impl`.
|
|
|
|
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)
|
|
if self.args.build_llbuild:
|
|
product_classes.append(products.LLBuild)
|
|
if self.args.build_libdispatch:
|
|
product_classes.append(products.LibDispatch)
|
|
if self.args.build_foundation:
|
|
product_classes.append(products.Foundation)
|
|
if self.args.build_xctest:
|
|
product_classes.append(products.XCTest)
|
|
if self.args.build_swiftpm:
|
|
product_classes.append(products.SwiftPM)
|
|
return product_classes
|
|
|
|
def execute(self):
|
|
"""Execute the invocation with the configured arguments."""
|
|
|
|
# Convert to a build-script-impl invocation.
|
|
(impl_env, impl_args) = self.convert_to_impl_arguments()
|
|
|
|
# If using the legacy implementation, delegate all behavior to
|
|
# `build-script-impl`.
|
|
if self.args.legacy_impl:
|
|
# Execute the underlying build script implementation.
|
|
call_without_sleeping([build_script_impl] + impl_args,
|
|
env=impl_env, echo=True)
|
|
return
|
|
|
|
# Otherwise, we compute and execute the individual actions ourselves.
|
|
|
|
def execute_one_impl_action(host=None, product_class=None, name=None):
|
|
if host is None:
|
|
assert (product_class is None and
|
|
name == "merged-hosts-lipo"), "invalid action"
|
|
action_name = name
|
|
elif product_class is None:
|
|
assert name == "package", "invalid action"
|
|
action_name = "{}-{}".format(host.name, name)
|
|
else:
|
|
assert name is not None, "invalid action"
|
|
action_name = "{}-{}-{}".format(
|
|
host.name, product_class.product_name(), name)
|
|
call_without_sleeping(
|
|
[build_script_impl] + impl_args + [
|
|
"--only-execute", action_name],
|
|
env=impl_env, echo=self.args.verbose_build)
|
|
|
|
# Compute the list of hosts to operate on.
|
|
all_host_names = [
|
|
self.args.host_target] + self.args.cross_compile_hosts
|
|
all_hosts = [StdlibDeploymentTarget.get_target_for_name(name)
|
|
for name in all_host_names]
|
|
|
|
# Compute the list of product classes to operate on.
|
|
#
|
|
# FIXME: This should really be per-host, but the current structure
|
|
# matches that of `build-script-impl`.
|
|
product_classes = self.compute_product_classes()
|
|
|
|
# Execute each "pass".
|
|
|
|
# Build...
|
|
for host_target in all_hosts:
|
|
# FIXME: We should only compute these once.
|
|
config = HostSpecificConfiguration(host_target.name, self)
|
|
print("Building the standard library for: {}".format(
|
|
" ".join(config.swift_stdlib_build_targets)))
|
|
if config.swift_test_run_targets and (
|
|
self.args.test or self.args.long_test):
|
|
print("Running Swift tests for: {}".format(
|
|
" ".join(config.swift_test_run_targets)))
|
|
if config.swift_benchmark_run_targets and self.args.benchmark:
|
|
print("Running Swift benchmarks for: {}".format(
|
|
" ".join(config.swift_benchmark_run_targets)))
|
|
|
|
for product_class in product_classes:
|
|
execute_one_impl_action(host_target, product_class, "build")
|
|
|
|
# Test...
|
|
for host_target in all_hosts:
|
|
for product_class in product_classes:
|
|
execute_one_impl_action(host_target, product_class, "test")
|
|
|
|
# Install...
|
|
for host_target in all_hosts:
|
|
for product_class in product_classes:
|
|
execute_one_impl_action(host_target, product_class, "install")
|
|
|
|
# Package...
|
|
for host_target in all_hosts:
|
|
execute_one_impl_action(host_target, name="package")
|
|
|
|
# Lipo...
|
|
execute_one_impl_action(name="merged-hosts-lipo")
|
|
|
|
|
|
# Provide a short delay so accidentally invoked clean builds can be canceled.
|
|
def clean_delay():
|
|
sys.stdout.write('Starting clean build in ')
|
|
for i in range(3, 0, -1):
|
|
sys.stdout.write('\b%d' % i)
|
|
sys.stdout.flush()
|
|
time.sleep(1)
|
|
print('\b\b\b\bnow.')
|
|
|
|
|
|
# Main entry point for the preset mode.
|
|
def main_preset():
|
|
parser = argparse.ArgumentParser(
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
description="""Builds Swift using a preset.""")
|
|
parser.add_argument(
|
|
"-n", "--dry-run",
|
|
help="print the commands that would be executed, but do not execute "
|
|
"them",
|
|
action="store_true",
|
|
default=False)
|
|
parser.add_argument(
|
|
"--preset-file",
|
|
help="load presets from the specified file",
|
|
metavar="PATH",
|
|
action="append",
|
|
dest="preset_file_names",
|
|
default=[])
|
|
parser.add_argument(
|
|
"--preset",
|
|
help="use the specified option preset",
|
|
metavar="NAME")
|
|
parser.add_argument(
|
|
"--show-presets",
|
|
help="list all presets and exit",
|
|
action=arguments.action.optional_bool)
|
|
parser.add_argument(
|
|
"--distcc",
|
|
help="use distcc",
|
|
action=arguments.action.optional_bool)
|
|
parser.add_argument(
|
|
"-j", "--jobs",
|
|
help="the number of parallel build jobs to use",
|
|
type=int,
|
|
dest="build_jobs")
|
|
parser.add_argument(
|
|
"preset_substitutions_raw",
|
|
help="'name=value' pairs that are substituted in the preset",
|
|
nargs="*",
|
|
metavar="SUBSTITUTION")
|
|
parser.add_argument(
|
|
"--expand-build-script-invocation",
|
|
help="Print the expanded build-script invocation generated "
|
|
"by the preset, but do not run the preset",
|
|
action=arguments.action.optional_bool)
|
|
args = parser.parse_args()
|
|
|
|
if len(args.preset_file_names) == 0:
|
|
args.preset_file_names = [
|
|
os.path.join(HOME, ".swift-build-presets"),
|
|
os.path.join(
|
|
SWIFT_SOURCE_ROOT, SWIFT_REPO_NAME, "utils",
|
|
"build-presets.ini")
|
|
]
|
|
|
|
if args.show_presets:
|
|
for name in sorted(get_all_preset_names(args.preset_file_names),
|
|
key=str.lower):
|
|
print(name)
|
|
return 0
|
|
|
|
if not args.preset:
|
|
diagnostics.fatal("missing --preset option")
|
|
|
|
args.preset_substitutions = {}
|
|
|
|
for arg in args.preset_substitutions_raw:
|
|
name, value = arg.split("=", 1)
|
|
args.preset_substitutions[name] = value
|
|
|
|
preset_args = get_preset_options(
|
|
args.preset_substitutions, args.preset_file_names, args.preset)
|
|
|
|
build_script_args = [sys.argv[0]]
|
|
if args.dry_run:
|
|
build_script_args += ["--dry-run"]
|
|
build_script_args += preset_args
|
|
if args.distcc:
|
|
build_script_args += ["--distcc"]
|
|
if args.build_jobs:
|
|
build_script_args += ["--jobs", str(args.build_jobs)]
|
|
|
|
diagnostics.note(
|
|
"using preset '" + args.preset + "', which expands to \n\n" +
|
|
shell.quote_command(build_script_args) + "\n")
|
|
|
|
if args.expand_build_script_invocation:
|
|
return 0
|
|
|
|
call_without_sleeping(build_script_args)
|
|
return 0
|
|
|
|
|
|
# Main entry point for the normal mode.
|
|
def main_normal():
|
|
parser = argparse.ArgumentParser(
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
usage="""
|
|
%(prog)s [-h | --help] [OPTION ...]
|
|
%(prog)s --preset=NAME [SUBSTITUTION ...]
|
|
""",
|
|
description="""
|
|
Use this tool to build, test, and prepare binary distribution archives of Swift
|
|
and related tools.
|
|
|
|
Builds Swift (and, optionally, LLDB), incrementally, optionally
|
|
testing it thereafter. Different build configurations are maintained in
|
|
parallel.""",
|
|
epilog="""
|
|
Using option presets:
|
|
|
|
--preset-file=PATH load presets from the specified file
|
|
|
|
--preset=NAME use the specified option preset
|
|
|
|
The preset mode is mutually exclusive with other options. It is not
|
|
possible to add ad-hoc customizations to a preset. This is a deliberate
|
|
design decision. (Rationale: a preset is a certain important set of
|
|
options that we want to keep in a centralized location. If you need to
|
|
customize it, you should create another preset in a centralized location,
|
|
rather than scattering the knowledge about the build across the system.)
|
|
|
|
Presets support substitutions for controlled customizations. Substitutions
|
|
are defined in the preset file. Values for substitutions are supplied
|
|
using the name=value syntax on the command line.
|
|
|
|
|
|
Any arguments not listed are forwarded directly to Swift's
|
|
'build-script-impl'. See that script's help for details.
|
|
|
|
Environment variables
|
|
---------------------
|
|
|
|
This script respects a few environment variables, should you
|
|
choose to set them:
|
|
|
|
SWIFT_SOURCE_ROOT: a directory containing the source for LLVM, Clang, Swift.
|
|
If this script is located in a Swift
|
|
source directory, the location of SWIFT_SOURCE_ROOT will be
|
|
inferred if the variable is not set.
|
|
|
|
'build-script' expects the sources to be laid out in the following way:
|
|
|
|
$SWIFT_SOURCE_ROOT/llvm
|
|
/clang
|
|
/swift
|
|
/lldb (optional)
|
|
/llbuild (optional)
|
|
/swiftpm (optional, requires llbuild)
|
|
/compiler-rt (optional)
|
|
/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/".
|
|
|
|
Preparing to run this script
|
|
----------------------------
|
|
|
|
See README.md for instructions on cloning Swift subprojects.
|
|
|
|
If you intend to use the -l, -L, --lldb, or --debug-lldb options.
|
|
|
|
That's it; you're ready to go!
|
|
|
|
Examples
|
|
--------
|
|
|
|
Given the above layout of sources, the simplest invocation of 'build-script' is
|
|
just:
|
|
|
|
[~/src/s]$ ./swift/utils/build-script
|
|
|
|
This builds LLVM, Clang, Swift and Swift standard library in debug mode.
|
|
|
|
All builds are incremental. To incrementally build changed files, repeat the
|
|
same 'build-script' command.
|
|
|
|
Typical uses of 'build-script'
|
|
------------------------------
|
|
|
|
To build everything with optimization without debug information:
|
|
|
|
[~/src/s]$ ./swift/utils/build-script -R
|
|
|
|
To run tests, add '-t':
|
|
|
|
[~/src/s]$ ./swift/utils/build-script -R -t
|
|
|
|
To run normal tests and validation tests, add '-T':
|
|
|
|
[~/src/s]$ ./swift/utils/build-script -R -T
|
|
|
|
To build LLVM+Clang with optimization without debug information, and a
|
|
debuggable Swift compiler:
|
|
|
|
[~/src/s]$ ./swift/utils/build-script -R --debug-swift
|
|
|
|
To build a debuggable Swift standard library:
|
|
|
|
[~/src/s]$ ./swift/utils/build-script -R --debug-swift-stdlib
|
|
|
|
iOS build targets are always configured and present, but are not built by
|
|
default. To build the standard library for OS X, iOS simulator and iOS device:
|
|
|
|
[~/src/s]$ ./swift/utils/build-script -R -i
|
|
|
|
To run OS X and iOS tests that don't require a device:
|
|
|
|
[~/src/s]$ ./swift/utils/build-script -R -i -t
|
|
|
|
To use 'make' instead of 'ninja', use '-m':
|
|
|
|
[~/src/s]$ ./swift/utils/build-script -m -R
|
|
|
|
To create Xcode projects that can build Swift, use '-x':
|
|
|
|
[~/src/s]$ ./swift/utils/build-script -x -R
|
|
|
|
Preset mode in build-script
|
|
---------------------------
|
|
|
|
All buildbots and automated environments use 'build-script' in *preset mode*.
|
|
In preset mode, the command line only specifies the preset name and allows
|
|
limited customization (extra output paths). The actual options come from
|
|
the selected preset in 'utils/build-presets.ini'. For example, to build like
|
|
the incremental buildbot, run:
|
|
|
|
[~/src/s]$ ./swift/utils/build-script --preset=buildbot_incremental
|
|
|
|
To build with AddressSanitizer:
|
|
|
|
[~/src/s]$ ./swift/utils/build-script --preset=asan
|
|
|
|
To build a root for Xcode XYZ, '/tmp/xcode-xyz-root.tar.gz':
|
|
|
|
[~/src/s]$ ./swift/utils/build-script --preset=buildbot_BNI_internal_XYZ \\
|
|
install_destdir="/tmp/install"
|
|
install_symroot="/tmp/symroot"
|
|
installable_package="/tmp/xcode-xyz-root.tar.gz"
|
|
|
|
If you have your own favorite set of options, you can create your own, local,
|
|
preset. For example, let's create a preset called 'ds' (which stands for
|
|
Debug Swift):
|
|
|
|
$ cat > ~/.swift-build-presets
|
|
[preset: ds]
|
|
release
|
|
debug-swift
|
|
debug-swift-stdlib
|
|
test
|
|
build-subdir=ds
|
|
|
|
To use it, specify the '--preset=' argument:
|
|
|
|
[~/src/s]$ ./swift/utils/build-script --preset=ds
|
|
./swift/utils/build-script: using preset 'ds', which expands to
|
|
./swift/utils/build-script --release --debug-swift --debug-swift-stdlib \
|
|
--test
|
|
--build-subdir=ds --
|
|
...
|
|
|
|
Existing presets can be found in `utils/build-presets.ini`
|
|
|
|
Philosophy
|
|
----------
|
|
|
|
While you can invoke CMake directly to build Swift, this tool will save you
|
|
time by taking away the mechanical parts of the process, providing you controls
|
|
for the important options.
|
|
|
|
For all automated build environments, this tool is regarded as *the* *only* way
|
|
to build Swift. This is not a technical limitation of the Swift build system.
|
|
It is a policy decision aimed at making the builds uniform across all
|
|
environments and easily reproducible by engineers who are not familiar with the
|
|
details of the setups of other systems or automated environments.""")
|
|
|
|
parser.add_argument(
|
|
"-n", "--dry-run",
|
|
help="print the commands that would be executed, but do not execute "
|
|
"them",
|
|
action="store_true",
|
|
default=False)
|
|
parser.add_argument(
|
|
"--no-legacy-impl", dest="legacy_impl",
|
|
help="avoid legacy implementation",
|
|
action="store_false",
|
|
default=True)
|
|
|
|
targets_group = parser.add_argument_group(
|
|
title="Host and cross-compilation targets")
|
|
targets_group.add_argument(
|
|
"--host-target",
|
|
help="The host target. LLVM, Clang, and Swift will be built for this "
|
|
"target. The built LLVM and Clang will be used to compile Swift "
|
|
"for the cross-compilation targets.",
|
|
default=StdlibDeploymentTarget.host_target().name)
|
|
targets_group.add_argument(
|
|
"--cross-compile-hosts",
|
|
help="A space separated list of targets to cross-compile host Swift "
|
|
"tools for. Can be used multiple times.",
|
|
action=arguments.action.concat, type=arguments.type.shell_split,
|
|
default=[])
|
|
targets_group.add_argument(
|
|
"--stdlib-deployment-targets",
|
|
help="list of targets to compile or cross-compile the Swift standard "
|
|
"library for. %(default)s by default.",
|
|
action=arguments.action.concat, type=arguments.type.shell_split,
|
|
default=None)
|
|
targets_group.add_argument(
|
|
"--build-stdlib-deployment-targets",
|
|
help="A space-separated list that filters which of the configured "
|
|
"targets to build the Swift standard library for, or 'all'.",
|
|
type=arguments.type.shell_split, default=["all"])
|
|
|
|
projects_group = parser.add_argument_group(
|
|
title="Options to select projects")
|
|
projects_group.add_argument(
|
|
"-l", "--lldb",
|
|
help="build LLDB",
|
|
action="store_true",
|
|
dest="build_lldb")
|
|
projects_group.add_argument(
|
|
"-b", "--llbuild",
|
|
help="build llbuild",
|
|
action="store_true",
|
|
dest="build_llbuild")
|
|
projects_group.add_argument(
|
|
"-p", "--swiftpm",
|
|
help="build swiftpm",
|
|
action="store_true",
|
|
dest="build_swiftpm")
|
|
projects_group.add_argument(
|
|
"--xctest",
|
|
help="build xctest",
|
|
action=arguments.action.optional_bool,
|
|
dest="build_xctest")
|
|
projects_group.add_argument(
|
|
"--foundation",
|
|
help="build foundation",
|
|
action=arguments.action.optional_bool,
|
|
dest="build_foundation")
|
|
projects_group.add_argument(
|
|
"--libdispatch",
|
|
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",
|
|
action="store_true",
|
|
dest="build_playgroundlogger")
|
|
projects_group.add_argument(
|
|
"--playgroundsupport",
|
|
help="build PlaygroundSupport",
|
|
action="store_true",
|
|
dest="build_playgroundsupport")
|
|
projects_group.add_argument(
|
|
"--build-ninja",
|
|
help="build the Ninja tool",
|
|
action=arguments.action.optional_bool)
|
|
|
|
extra_actions_group = parser.add_argument_group(
|
|
title="Extra actions to perform before or in addition to building")
|
|
extra_actions_group.add_argument(
|
|
"-c", "--clean",
|
|
help="do a clean build",
|
|
action="store_true")
|
|
extra_actions_group.add_argument(
|
|
"--export-compile-commands",
|
|
help="generate compilation databases in addition to building",
|
|
action=arguments.action.optional_bool)
|
|
extra_actions_group.add_argument(
|
|
"--symbols-package",
|
|
metavar="PATH",
|
|
help="if provided, an archive of the symbols directory will be "
|
|
"generated at this path")
|
|
|
|
build_variant_group = parser.add_mutually_exclusive_group(required=False)
|
|
build_variant_group.add_argument(
|
|
"-d", "--debug",
|
|
help="build the Debug variant of everything (LLVM, Clang, Swift host "
|
|
"tools, target Swift standard libraries, LLDB (if enabled) "
|
|
"(default)",
|
|
action="store_const",
|
|
const="Debug",
|
|
dest="build_variant")
|
|
build_variant_group.add_argument(
|
|
"-r", "--release-debuginfo",
|
|
help="build the RelWithDebInfo variant of everything (default is "
|
|
"Debug)",
|
|
action="store_const",
|
|
const="RelWithDebInfo",
|
|
dest="build_variant")
|
|
build_variant_group.add_argument(
|
|
"-R", "--release",
|
|
help="build the Release variant of everything (default is Debug)",
|
|
action="store_const",
|
|
const="Release",
|
|
dest="build_variant")
|
|
|
|
build_variant_override_group = parser.add_argument_group(
|
|
title="Override build variant for a specific project")
|
|
build_variant_override_group.add_argument(
|
|
"--debug-llvm",
|
|
help="build the Debug variant of LLVM",
|
|
action="store_const",
|
|
const="Debug",
|
|
dest="llvm_build_variant")
|
|
build_variant_override_group.add_argument(
|
|
"--debug-swift",
|
|
help="build the Debug variant of Swift host tools",
|
|
action="store_const",
|
|
const="Debug",
|
|
dest="swift_build_variant")
|
|
build_variant_override_group.add_argument(
|
|
"--debug-swift-stdlib",
|
|
help="build the Debug variant of the Swift standard library and SDK "
|
|
"overlay",
|
|
action="store_const",
|
|
const="Debug",
|
|
dest="swift_stdlib_build_variant")
|
|
build_variant_override_group.add_argument(
|
|
"--debug-lldb",
|
|
help="build the Debug variant of LLDB",
|
|
action="store_const",
|
|
const="Debug",
|
|
dest="lldb_build_variant")
|
|
build_variant_override_group.add_argument(
|
|
"--debug-cmark",
|
|
help="build the Debug variant of CommonMark",
|
|
action="store_const",
|
|
const="Debug",
|
|
dest="cmark_build_variant")
|
|
build_variant_override_group.add_argument(
|
|
"--debug-foundation",
|
|
help="build the Debug variant of Foundation",
|
|
action="store_const",
|
|
const="Debug",
|
|
dest="foundation_build_variant")
|
|
build_variant_override_group.add_argument(
|
|
"--debug-libdispatch",
|
|
help="build the Debug variant of libdispatch",
|
|
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(
|
|
"--assertions",
|
|
help="enable assertions in all projects",
|
|
action="store_const",
|
|
const=True,
|
|
dest="assertions")
|
|
assertions_group.add_argument(
|
|
"--no-assertions",
|
|
help="disable assertions in all projects",
|
|
action="store_const",
|
|
const=False,
|
|
dest="assertions")
|
|
|
|
assertions_override_group = parser.add_argument_group(
|
|
title="Control assertions in a specific project")
|
|
assertions_override_group.add_argument(
|
|
"--cmark-assertions",
|
|
help="enable assertions in CommonMark",
|
|
action="store_const",
|
|
const=True,
|
|
dest="cmark_assertions")
|
|
assertions_override_group.add_argument(
|
|
"--llvm-assertions",
|
|
help="enable assertions in LLVM",
|
|
action="store_const",
|
|
const=True,
|
|
dest="llvm_assertions")
|
|
assertions_override_group.add_argument(
|
|
"--no-llvm-assertions",
|
|
help="disable assertions in LLVM",
|
|
action="store_const",
|
|
const=False,
|
|
dest="llvm_assertions")
|
|
assertions_override_group.add_argument(
|
|
"--swift-assertions",
|
|
help="enable assertions in Swift",
|
|
action="store_const",
|
|
const=True,
|
|
dest="swift_assertions")
|
|
assertions_override_group.add_argument(
|
|
"--no-swift-assertions",
|
|
help="disable assertions in Swift",
|
|
action="store_const",
|
|
const=False,
|
|
dest="swift_assertions")
|
|
assertions_override_group.add_argument(
|
|
"--swift-stdlib-assertions",
|
|
help="enable assertions in the Swift standard library",
|
|
action="store_const",
|
|
const=True,
|
|
dest="swift_stdlib_assertions")
|
|
assertions_override_group.add_argument(
|
|
"--no-swift-stdlib-assertions",
|
|
help="disable assertions in the Swift standard library",
|
|
action="store_const",
|
|
const=False,
|
|
dest="swift_stdlib_assertions")
|
|
assertions_override_group.add_argument(
|
|
"--lldb-assertions",
|
|
help="enable assertions in LLDB",
|
|
action="store_const",
|
|
const=True,
|
|
dest="lldb_assertions")
|
|
assertions_override_group.add_argument(
|
|
"--no-lldb-assertions",
|
|
help="disable assertions in LLDB",
|
|
action="store_const",
|
|
const=False,
|
|
dest="lldb_assertions")
|
|
|
|
# FIXME: This should be one option using choices=[...]
|
|
cmake_generator_group = parser.add_argument_group(
|
|
title="Select the CMake generator")
|
|
cmake_generator_group.add_argument(
|
|
"-x", "--xcode",
|
|
help="use CMake's Xcode generator (default is Ninja)",
|
|
action="store_const",
|
|
const="Xcode",
|
|
dest="cmake_generator")
|
|
cmake_generator_group.add_argument(
|
|
"-m", "--make",
|
|
help="use CMake's Makefile generator (default is Ninja)",
|
|
action="store_const",
|
|
const="Unix Makefiles",
|
|
dest="cmake_generator")
|
|
cmake_generator_group.add_argument(
|
|
"-e", "--eclipse",
|
|
help="use CMake's Eclipse generator (default is Ninja)",
|
|
action="store_const",
|
|
const="Eclipse CDT4 - Ninja",
|
|
dest="cmake_generator")
|
|
|
|
run_tests_group = parser.add_argument_group(
|
|
title="Run tests")
|
|
|
|
# NOTE: We can't merge -t and --test, because nargs='?' makes
|
|
# `-ti` to be treated as `-t=i`.
|
|
run_tests_group.add_argument(
|
|
"-t",
|
|
help="test Swift after building",
|
|
action="store_const",
|
|
const=True,
|
|
dest="test")
|
|
run_tests_group.add_argument(
|
|
"--test",
|
|
help="test Swift after building",
|
|
action=arguments.action.optional_bool)
|
|
run_tests_group.add_argument(
|
|
"-T",
|
|
help="run the validation test suite (implies --test)",
|
|
action="store_const",
|
|
const=True,
|
|
dest="validation_test")
|
|
run_tests_group.add_argument(
|
|
"--validation-test",
|
|
help="run the validation test suite (implies --test)",
|
|
action=arguments.action.optional_bool)
|
|
run_tests_group.add_argument(
|
|
"-o",
|
|
help="run the test suite in optimized mode too (implies --test)",
|
|
action="store_const",
|
|
const=True,
|
|
dest="test_optimized")
|
|
run_tests_group.add_argument(
|
|
"--test-optimized",
|
|
help="run the test suite in optimized mode too (implies --test)",
|
|
action=arguments.action.optional_bool)
|
|
run_tests_group.add_argument(
|
|
"--long-test",
|
|
help="run the long test suite",
|
|
action=arguments.action.optional_bool)
|
|
run_tests_group.add_argument(
|
|
"--host-test",
|
|
help="run executable tests on host devices (such as iOS or tvOS)",
|
|
action=arguments.action.optional_bool)
|
|
run_tests_group.add_argument(
|
|
"-B", "--benchmark",
|
|
help="run the Swift Benchmark Suite after building",
|
|
action="store_true")
|
|
run_tests_group.add_argument(
|
|
"--benchmark-num-o-iterations",
|
|
help="if the Swift Benchmark Suite is run after building, run N \
|
|
iterations with -O",
|
|
metavar='N', type=int, default=3)
|
|
run_tests_group.add_argument(
|
|
"--benchmark-num-onone-iterations",
|
|
help="if the Swift Benchmark Suite is run after building, run N \
|
|
iterations with -Onone", metavar='N', type=int, default=3)
|
|
run_tests_group.add_argument(
|
|
"--skip-test-osx",
|
|
help="skip testing Swift stdlibs for Mac OS X",
|
|
action=arguments.action.optional_bool)
|
|
run_tests_group.add_argument(
|
|
"--skip-test-linux",
|
|
help="skip testing Swift stdlibs for Linux",
|
|
action=arguments.action.optional_bool)
|
|
run_tests_group.add_argument(
|
|
"--skip-test-freebsd",
|
|
help="skip testing Swift stdlibs for FreeBSD",
|
|
action=arguments.action.optional_bool)
|
|
run_tests_group.add_argument(
|
|
"--skip-test-cygwin",
|
|
help="skip testing Swift stdlibs for Cygwin",
|
|
action=arguments.action.optional_bool)
|
|
parser.add_argument(
|
|
"--build-runtime-with-host-compiler",
|
|
help="Use the host compiler, not the self-built one to compile the "
|
|
"Swift runtime",
|
|
action=arguments.action.optional_bool)
|
|
|
|
run_build_group = parser.add_argument_group(
|
|
title="Run build")
|
|
run_build_group.add_argument(
|
|
"--build-swift-dynamic-stdlib",
|
|
help="build dynamic variants of the Swift standard library",
|
|
action=arguments.action.optional_bool,
|
|
default=True)
|
|
run_build_group.add_argument(
|
|
"--build-swift-static-stdlib",
|
|
help="build static variants of the Swift standard library",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--build-swift-dynamic-sdk-overlay",
|
|
help="build dynamic variants of the Swift SDK overlay",
|
|
action=arguments.action.optional_bool,
|
|
default=True)
|
|
run_build_group.add_argument(
|
|
"--build-swift-static-sdk-overlay",
|
|
help="build static variants of the Swift SDK overlay",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--build-swift-stdlib-unittest-extra",
|
|
help="Build optional StdlibUnittest components",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"-S", "--skip-build",
|
|
help="generate build directory only without building",
|
|
action="store_true")
|
|
run_build_group.add_argument(
|
|
"--skip-build-linux",
|
|
help="skip building Swift stdlibs for Linux",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--skip-build-freebsd",
|
|
help="skip building Swift stdlibs for FreeBSD",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--skip-build-cygwin",
|
|
help="skip building Swift stdlibs for Cygwin",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--skip-build-osx",
|
|
help="skip building Swift stdlibs for MacOSX",
|
|
action=arguments.action.optional_bool)
|
|
|
|
run_build_group.add_argument(
|
|
"--skip-build-ios",
|
|
help="skip building Swift stdlibs for iOS",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--skip-build-ios-device",
|
|
help="skip building Swift stdlibs for iOS devices "
|
|
"(i.e. build simulators only)",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--skip-build-ios-simulator",
|
|
help="skip building Swift stdlibs for iOS simulator "
|
|
"(i.e. build devices only)",
|
|
action=arguments.action.optional_bool)
|
|
|
|
run_build_group.add_argument(
|
|
"--skip-build-tvos",
|
|
help="skip building Swift stdlibs for tvOS",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--skip-build-tvos-device",
|
|
help="skip building Swift stdlibs for tvOS devices "
|
|
"(i.e. build simulators only)",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--skip-build-tvos-simulator",
|
|
help="skip building Swift stdlibs for tvOS simulator "
|
|
"(i.e. build devices only)",
|
|
action=arguments.action.optional_bool)
|
|
|
|
run_build_group.add_argument(
|
|
"--skip-build-watchos",
|
|
help="skip building Swift stdlibs for watchOS",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--skip-build-watchos-device",
|
|
help="skip building Swift stdlibs for watchOS devices "
|
|
"(i.e. build simulators only)",
|
|
action=arguments.action.optional_bool)
|
|
run_build_group.add_argument(
|
|
"--skip-build-watchos-simulator",
|
|
help="skip building Swift stdlibs for watchOS simulator "
|
|
"(i.e. build devices only)",
|
|
action=arguments.action.optional_bool)
|
|
|
|
run_build_group.add_argument(
|
|
"--skip-build-android",
|
|
help="skip building Swift stdlibs for Android",
|
|
action=arguments.action.optional_bool)
|
|
|
|
run_build_group.add_argument(
|
|
"--skip-build-benchmarks",
|
|
help="skip building Swift Benchmark Suite",
|
|
action=arguments.action.optional_bool)
|
|
|
|
skip_test_group = parser.add_argument_group(
|
|
title="Skip testing specified targets")
|
|
skip_test_group.add_argument(
|
|
"--skip-test-ios",
|
|
help="skip testing all iOS targets. Equivalent to specifying both "
|
|
"--skip-test-ios-simulator and --skip-test-ios-host",
|
|
action=arguments.action.optional_bool)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-ios-simulator",
|
|
help="skip testing iOS simulator targets",
|
|
action=arguments.action.optional_bool)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-ios-32bit-simulator",
|
|
help="skip testing iOS 32 bit simulator targets",
|
|
action=arguments.action.optional_bool,
|
|
default=True)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-ios-host",
|
|
help="skip testing iOS device targets on the host machine (the phone "
|
|
"itself)",
|
|
action=arguments.action.optional_bool)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-tvos",
|
|
help="skip testing all tvOS targets. Equivalent to specifying both "
|
|
"--skip-test-tvos-simulator and --skip-test-tvos-host",
|
|
action=arguments.action.optional_bool)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-tvos-simulator",
|
|
help="skip testing tvOS simulator targets",
|
|
action=arguments.action.optional_bool)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-tvos-host",
|
|
help="skip testing tvOS device targets on the host machine (the TV "
|
|
"itself)",
|
|
action=arguments.action.optional_bool)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-watchos",
|
|
help="skip testing all tvOS targets. Equivalent to specifying both "
|
|
"--skip-test-watchos-simulator and --skip-test-watchos-host",
|
|
action=arguments.action.optional_bool)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-watchos-simulator",
|
|
help="skip testing watchOS simulator targets",
|
|
action=arguments.action.optional_bool)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-watchos-host",
|
|
help="skip testing watchOS device targets on the host machine (the "
|
|
"watch itself)",
|
|
action=arguments.action.optional_bool)
|
|
skip_test_group.add_argument(
|
|
"--skip-test-android-host",
|
|
help="skip testing Android device targets on the host machine (the "
|
|
"phone itself)",
|
|
action=arguments.action.optional_bool)
|
|
|
|
parser.add_argument(
|
|
"-i", "--ios",
|
|
help="also build for iOS, but disallow tests that require an iOS "
|
|
"device",
|
|
action="store_true")
|
|
parser.add_argument(
|
|
"-I", "--ios-all",
|
|
help="also build for iOS, and allow all iOS tests",
|
|
action="store_true",
|
|
dest="ios_all")
|
|
parser.add_argument(
|
|
"--skip-ios",
|
|
help="set to skip everything iOS-related",
|
|
dest="ios",
|
|
action="store_false")
|
|
|
|
parser.add_argument(
|
|
"--tvos",
|
|
help="also build for tvOS, but disallow tests that require a tvos "
|
|
"device",
|
|
action=arguments.action.optional_bool)
|
|
parser.add_argument(
|
|
"--tvos-all",
|
|
help="also build for tvOS, and allow all tvOS tests",
|
|
action=arguments.action.optional_bool,
|
|
dest="tvos_all")
|
|
parser.add_argument(
|
|
"--skip-tvos",
|
|
help="set to skip everything tvOS-related",
|
|
dest="tvos",
|
|
action="store_false")
|
|
|
|
parser.add_argument(
|
|
"--watchos",
|
|
help="also build for watchOS, but disallow tests that require an "
|
|
"watchOS device",
|
|
action=arguments.action.optional_bool)
|
|
parser.add_argument(
|
|
"--watchos-all",
|
|
help="also build for Apple watchOS, and allow all Apple watchOS tests",
|
|
action=arguments.action.optional_bool,
|
|
dest="watchos_all")
|
|
parser.add_argument(
|
|
"--skip-watchos",
|
|
help="set to skip everything watchOS-related",
|
|
dest="watchos",
|
|
action="store_false")
|
|
|
|
parser.add_argument(
|
|
"--android",
|
|
help="also build for Android",
|
|
action=arguments.action.optional_bool)
|
|
|
|
parser.add_argument(
|
|
"--swift-analyze-code-coverage",
|
|
help="enable code coverage analysis in Swift (false, not-merged, "
|
|
"merged).",
|
|
choices=["false", "not-merged", "merged"],
|
|
default="false", # so CMake can see the inert mode as a false value
|
|
dest="swift_analyze_code_coverage")
|
|
|
|
parser.add_argument(
|
|
"--build-subdir",
|
|
help="name of the directory under $SWIFT_BUILD_ROOT where the build "
|
|
"products will be placed",
|
|
metavar="PATH")
|
|
parser.add_argument(
|
|
"--install-prefix",
|
|
help="The installation prefix. This is where built Swift products "
|
|
"(like bin, lib, and include) will be installed.",
|
|
metavar="PATH",
|
|
default=targets.install_prefix())
|
|
parser.add_argument(
|
|
"--install-symroot",
|
|
help="the path to install debug symbols into",
|
|
metavar="PATH")
|
|
|
|
parser.add_argument(
|
|
"-j", "--jobs",
|
|
help="the number of parallel build jobs to use",
|
|
type=int,
|
|
dest="build_jobs",
|
|
default=multiprocessing.cpu_count())
|
|
|
|
parser.add_argument(
|
|
"--darwin-xcrun-toolchain",
|
|
help="the name of the toolchain to use on Darwin",
|
|
default="default")
|
|
parser.add_argument(
|
|
"--cmake",
|
|
help="the path to a CMake executable that will be used to build "
|
|
"Swift",
|
|
type=arguments.type.executable,
|
|
metavar="PATH")
|
|
parser.add_argument(
|
|
"--show-sdks",
|
|
help="print installed Xcode and SDK versions",
|
|
action=arguments.action.optional_bool)
|
|
|
|
parser.add_argument(
|
|
"--extra-swift-args",
|
|
help="Pass through extra flags to swift in the form of a cmake list "
|
|
"'module_regexp;flag'. Can be called multiple times to add "
|
|
"multiple such module_regexp flag pairs. All semicolons in flags "
|
|
"must be escaped with a '\\'",
|
|
action="append", dest="extra_swift_args", default=[])
|
|
|
|
llvm_group = parser.add_argument_group(
|
|
title="Build settings specific for LLVM")
|
|
llvm_group.add_argument(
|
|
'--llvm-targets-to-build',
|
|
help='LLVM target generators to build',
|
|
default="X86;ARM;AArch64;PowerPC;SystemZ;Mips")
|
|
|
|
android_group = parser.add_argument_group(
|
|
title="Build settings for Android")
|
|
android_group.add_argument(
|
|
"--android-ndk",
|
|
help="An absolute path to the NDK that will be used as a libc "
|
|
"implementation for Android builds",
|
|
metavar="PATH")
|
|
android_group.add_argument(
|
|
"--android-api-level",
|
|
help="The Android API level to target when building for Android. "
|
|
"Currently only 21 or above is supported",
|
|
default="21")
|
|
android_group.add_argument(
|
|
"--android-ndk-gcc-version",
|
|
help="The GCC version to use when building for Android. Currently "
|
|
"only 4.9 is supported. %(default)s is also the default value. "
|
|
"This option may be used when experimenting with versions "
|
|
"of the Android NDK not officially supported by Swift",
|
|
choices=["4.8", "4.9"],
|
|
default="4.9")
|
|
android_group.add_argument(
|
|
"--android-icu-uc",
|
|
help="Path to a directory containing libicuuc.so",
|
|
metavar="PATH")
|
|
android_group.add_argument(
|
|
"--android-icu-uc-include",
|
|
help="Path to a directory containing headers for libicuuc",
|
|
metavar="PATH")
|
|
android_group.add_argument(
|
|
"--android-icu-i18n",
|
|
help="Path to a directory containing libicui18n.so",
|
|
metavar="PATH")
|
|
android_group.add_argument(
|
|
"--android-icu-i18n-include",
|
|
help="Path to a directory containing headers libicui18n",
|
|
metavar="PATH")
|
|
android_group.add_argument(
|
|
"--android-deploy-device-path",
|
|
help="Path on an Android device to which built Swift stdlib products "
|
|
"will be deployed. If running host tests, specify the '{}' "
|
|
"directory.".format(android.adb.commands.DEVICE_TEMP_DIR),
|
|
default=android.adb.commands.DEVICE_TEMP_DIR,
|
|
metavar="PATH")
|
|
|
|
parser.add_argument(
|
|
"--host-cc",
|
|
help="the absolute path to CC, the 'clang' compiler for the host "
|
|
"platform. Default is auto detected.",
|
|
type=arguments.type.executable,
|
|
metavar="PATH")
|
|
parser.add_argument(
|
|
"--host-cxx",
|
|
help="the absolute path to CXX, the 'clang++' compiler for the host "
|
|
"platform. Default is auto detected.",
|
|
type=arguments.type.executable,
|
|
metavar="PATH")
|
|
parser.add_argument(
|
|
"--host-lipo",
|
|
help="the absolute path to lipo. Default is auto detected.",
|
|
type=arguments.type.executable,
|
|
metavar="PATH")
|
|
parser.add_argument(
|
|
"--host-libtool",
|
|
help="the absolute path to libtool. Default is auto detected.",
|
|
type=arguments.type.executable,
|
|
metavar="PATH")
|
|
parser.add_argument(
|
|
"--distcc",
|
|
help="use distcc in pump mode",
|
|
action=arguments.action.optional_bool)
|
|
parser.add_argument(
|
|
"--enable-asan",
|
|
help="enable Address Sanitizer",
|
|
action=arguments.action.optional_bool)
|
|
parser.add_argument(
|
|
"--enable-ubsan",
|
|
help="enable Undefined Behavior Sanitizer",
|
|
action=arguments.action.optional_bool)
|
|
parser.add_argument(
|
|
"--enable-tsan",
|
|
help="enable Thread Sanitizer for swift tools",
|
|
action=arguments.action.optional_bool)
|
|
parser.add_argument(
|
|
"--enable-tsan-runtime",
|
|
help="enable Thread Sanitizer on the swift runtime")
|
|
parser.add_argument(
|
|
"--enable-lsan",
|
|
help="enable Leak Sanitizer for swift tools",
|
|
action=arguments.action.optional_bool)
|
|
|
|
parser.add_argument(
|
|
"--compiler-vendor",
|
|
choices=["none", "apple"],
|
|
default="none",
|
|
help="Compiler vendor name")
|
|
parser.add_argument(
|
|
"--clang-compiler-version",
|
|
help="string that indicates a compiler version for Clang",
|
|
type=arguments.type.clang_compiler_version,
|
|
metavar="MAJOR.MINOR.PATCH")
|
|
parser.add_argument(
|
|
"--clang-user-visible-version",
|
|
help="User-visible version of the embedded Clang and LLVM compilers",
|
|
type=arguments.type.clang_compiler_version,
|
|
default="5.0.0",
|
|
metavar="MAJOR.MINOR.PATCH")
|
|
parser.add_argument(
|
|
"--swift-compiler-version",
|
|
help="string that indicates a compiler version for Swift",
|
|
type=arguments.type.swift_compiler_version,
|
|
metavar="MAJOR.MINOR")
|
|
parser.add_argument(
|
|
"--swift-user-visible-version",
|
|
help="User-visible version of the embedded Swift compiler",
|
|
type=arguments.type.swift_compiler_version,
|
|
default="4.0",
|
|
metavar="MAJOR.MINOR")
|
|
|
|
parser.add_argument(
|
|
"--darwin-deployment-version-osx",
|
|
help="minimum deployment target version for OS X",
|
|
metavar="MAJOR.MINOR",
|
|
default="10.9")
|
|
parser.add_argument(
|
|
"--darwin-deployment-version-ios",
|
|
help="minimum deployment target version for iOS",
|
|
metavar="MAJOR.MINOR",
|
|
default="7.0")
|
|
parser.add_argument(
|
|
"--darwin-deployment-version-tvos",
|
|
help="minimum deployment target version for tvOS",
|
|
metavar="MAJOR.MINOR",
|
|
default="9.0")
|
|
parser.add_argument(
|
|
"--darwin-deployment-version-watchos",
|
|
help="minimum deployment target version for watchOS",
|
|
metavar="MAJOR.MINOR",
|
|
default="2.0")
|
|
|
|
parser.add_argument(
|
|
"--extra-cmake-options",
|
|
help="Pass through extra options to CMake in the form of comma "
|
|
"separated options '-DCMAKE_VAR1=YES,-DCMAKE_VAR2=/tmp'. Can be "
|
|
"called multiple times to add multiple such options.",
|
|
action=arguments.action.concat,
|
|
type=arguments.type.shell_split,
|
|
default=[])
|
|
|
|
parser.add_argument(
|
|
"--build-args",
|
|
help="arguments to the build tool. This would be prepended to the "
|
|
"default argument that is '-j8' when CMake generator is "
|
|
"\"Ninja\".",
|
|
type=arguments.type.shell_split,
|
|
default=[])
|
|
|
|
parser.add_argument(
|
|
"--verbose-build",
|
|
help="print the commands executed during the build",
|
|
action=arguments.action.optional_bool)
|
|
|
|
parser.add_argument(
|
|
"--lto",
|
|
help="use lto optimization on llvm/swift tools. This does not "
|
|
"imply using lto on the swift standard library or runtime. "
|
|
"Options: thin, full. If no optional arg is provided, full is "
|
|
"chosen by default",
|
|
metavar="LTO_TYPE",
|
|
nargs='?',
|
|
choices=['thin', 'full'],
|
|
default=None,
|
|
const='full',
|
|
dest='lto_type')
|
|
|
|
parser.add_argument(
|
|
"--clang-profile-instr-use",
|
|
help="profile file to use for clang PGO",
|
|
metavar="PATH")
|
|
|
|
default_max_lto_link_job_counts = host.max_lto_link_job_counts()
|
|
parser.add_argument(
|
|
"--llvm-max-parallel-lto-link-jobs",
|
|
help="the maximum number of parallel link jobs to use when compiling "
|
|
"llvm",
|
|
metavar="COUNT",
|
|
default=default_max_lto_link_job_counts['llvm'])
|
|
|
|
parser.add_argument(
|
|
"--swift-tools-max-parallel-lto-link-jobs",
|
|
help="the maximum number of parallel link jobs to use when compiling "
|
|
"swift tools.",
|
|
metavar="COUNT",
|
|
default=default_max_lto_link_job_counts['swift'])
|
|
|
|
parser.add_argument("--enable-sil-ownership",
|
|
help="Enable the SIL ownership model",
|
|
action='store_true')
|
|
|
|
parser.add_argument("--force-optimized-typechecker",
|
|
help="Force the type checker to be built with "
|
|
"optimization",
|
|
action='store_true')
|
|
|
|
parser.add_argument(
|
|
# Explicitly unavailable options here.
|
|
"--build-jobs",
|
|
"--common-cmake-options",
|
|
"--only-execute",
|
|
"--skip-test-optimized",
|
|
action=arguments.action.unavailable)
|
|
|
|
parser.add_argument(
|
|
"--lit-args",
|
|
help="lit args to use when testing",
|
|
metavar="LITARGS",
|
|
default="-sv")
|
|
|
|
parser.add_argument(
|
|
"--coverage-db",
|
|
help="coverage database to use when prioritizing testing",
|
|
metavar="PATH")
|
|
|
|
args = migration.parse_args(parser, sys.argv[1:])
|
|
|
|
if args.build_script_impl_args:
|
|
# If we received any impl args, check if `build-script-impl` would
|
|
# accept them or not before any further processing.
|
|
try:
|
|
migration.check_impl_args(build_script_impl,
|
|
args.build_script_impl_args)
|
|
except ValueError as e:
|
|
exit_rejecting_arguments(e, parser)
|
|
|
|
if '--check-args-only' in args.build_script_impl_args:
|
|
return 0
|
|
|
|
shell.dry_run = args.dry_run
|
|
|
|
# Prepare and validate toolchain
|
|
toolchain = host_toolchain(xcrun_toolchain=args.darwin_xcrun_toolchain)
|
|
os.environ['TOOLCHAINS'] = args.darwin_xcrun_toolchain
|
|
|
|
if args.host_cc is not None:
|
|
toolchain.cc = args.host_cc
|
|
if args.host_cxx is not None:
|
|
toolchain.cxx = args.host_cxx
|
|
if args.host_lipo is not None:
|
|
toolchain.lipo = args.host_lipo
|
|
if args.host_libtool is not None:
|
|
toolchain.libtool = args.host_libtool
|
|
if args.cmake is not None:
|
|
toolchain.cmake = args.cmake
|
|
|
|
# Preprocess the arguments to apply defaults.
|
|
BuildScriptInvocation.apply_default_arguments(toolchain, args)
|
|
|
|
# Validate the arguments.
|
|
BuildScriptInvocation.validate_arguments(toolchain, args)
|
|
|
|
# Create the build script invocation.
|
|
invocation = BuildScriptInvocation(toolchain, args)
|
|
|
|
# Sanitize the runtime environment.
|
|
invocation.initialize_runtime_environment()
|
|
|
|
# Show SDKs, if requested.
|
|
if args.show_sdks:
|
|
debug.print_xcodebuild_versions()
|
|
|
|
# Clean build directory if requested.
|
|
if args.clean:
|
|
clean_delay()
|
|
shell.rmtree(invocation.workspace.build_root)
|
|
|
|
# Create build directory.
|
|
shell.makedirs(invocation.workspace.build_root)
|
|
|
|
# Build ninja if required, which will update the toolchain.
|
|
if args.build_ninja:
|
|
invocation.build_ninja()
|
|
|
|
# Execute the underlying build script implementation.
|
|
invocation.execute()
|
|
|
|
if args.symbols_package:
|
|
print('--- Creating symbols package ---')
|
|
print('-- Package file: {} --'.format(args.symbols_package))
|
|
|
|
if platform.system() == 'Darwin':
|
|
prefix = targets.darwin_toolchain_prefix(args.install_prefix)
|
|
else:
|
|
prefix = args.install_prefix
|
|
|
|
# As a security measure, `tar` normally strips leading '/' from paths
|
|
# it is archiving. To stay safe, we change working directories, then
|
|
# run `tar` without the leading '/' (we remove it ourselves to keep
|
|
# `tar` from emitting a warning).
|
|
with shell.pushd(args.install_symroot):
|
|
tar.tar(source=prefix.lstrip('/'),
|
|
destination=args.symbols_package)
|
|
|
|
return 0
|
|
|
|
|
|
def main():
|
|
if not SWIFT_SOURCE_ROOT:
|
|
diagnostics.fatal(
|
|
"could not infer source root directory " +
|
|
"(forgot to set $SWIFT_SOURCE_ROOT environment variable?)")
|
|
|
|
if not os.path.isdir(SWIFT_SOURCE_ROOT):
|
|
diagnostics.fatal(
|
|
"source root directory \'" + SWIFT_SOURCE_ROOT +
|
|
"\' does not exist " +
|
|
"(forgot to set $SWIFT_SOURCE_ROOT environment variable?)")
|
|
|
|
# Determine if we are invoked in the preset mode and dispatch accordingly.
|
|
if any([(opt.startswith("--preset") or opt == "--show-presets")
|
|
for opt in sys.argv[1:]]):
|
|
return main_preset()
|
|
else:
|
|
return main_normal()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
sys.exit(main())
|
|
except KeyboardInterrupt:
|
|
sys.exit(1)
|