diff options
author | Dmitry Shevchenko <dmishe@google.com> | 2016-10-03 22:12:28 +0000 |
---|---|---|
committer | Damien Martin-Guillerez <dmarting@google.com> | 2016-10-04 08:55:09 +0000 |
commit | deeeb31f8ba0f196fbc9ca2a177d59d57ea50b32 (patch) | |
tree | 999abbd9c868be741495a0fc63a3ac77b7d31deb | |
parent | 169e68f4f3fcc000cc4fedebf15a9ea9373784e4 (diff) |
Add a way to select non-default Xcode toolchain
* Adds a flag --xcode_toolchain which sets TOOLCHAINS env variable for xcrun.
* Updates swift_library to work with this flag when selecting Swift runtime location.
* By default the flag has a null value and is not set in env.
--
MOS_MIGRATED_REVID=135033093
6 files changed, 148 insertions, 24 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java index 5d2830a049..3d71ca5ad8 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java @@ -227,6 +227,17 @@ public class AppleCommandLineOptions extends FragmentOptions { } } + @Option( + name = "xcode_toolchain", + defaultValue = "null", + category = "flags", + help = "The identifier of an Xcode toolchain to use for builds. Currently only the toolchains " + + "that ship with Xcode are supported. For example, in addition to the default toolchain" + + " Xcode 8 has 'com.apple.dt.toolchain.Swift_2_3' which can be used for building legacy" + + " Swift code." + ) + public String xcodeToolchain; + @Option(name = "apple_bitcode", converter = AppleBitcodeMode.Converter.class, // TODO(blaze-team): Default to embedded_markers when fully implemented. diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java index 59a6fc1403..e0d242703f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java @@ -84,6 +84,7 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { private final ImmutableList<String> tvosCpus; private final AppleBitcodeMode bitcodeMode; private final Label xcodeConfigLabel; + @Nullable private final String xcodeToolchain; @Nullable private final Label defaultProvisioningProfileLabel; private final boolean disableNativeSwiftRules; @@ -127,6 +128,7 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { this.xcodeConfigLabel = Preconditions.checkNotNull(appleOptions.xcodeVersionConfig, "xcodeConfigLabel"); this.defaultProvisioningProfileLabel = appleOptions.defaultProvisioningProfile; + this.xcodeToolchain = appleOptions.xcodeToolchain; this.disableNativeSwiftRules = appleOptions.disableNativeSwiftRules; } @@ -519,6 +521,17 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { return Joiner.on('-').join(components); } + /** Returns the identifier for an Xcode toolchain to use with tools. */ + @SkylarkCallable( + name = "xcode_toolchain", + doc = "Identifier for the custom Xcode toolchain to use in build or None if not specified", + allowReturnNones = true, + structField = true + ) + public String getXcodeToolchain() { + return xcodeToolchain; + } + /** * Whether the native Swift support should be disabled. Used to deprecate said functionality. */ diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java index fa16aaf3f9..8136e837ca 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java @@ -1445,9 +1445,22 @@ public final class CompilationSupport { } if (objcProvider.is(USES_SWIFT)) { - commandLine - .add("-L") - .add(AppleToolchain.swiftLibDir(appleConfiguration.getSingleArchPlatform())); + // Check if there's a swift library path already. If that's not the case - fall back to + // the default one. This is for backwards compatibility with Swift native rules. + // TODO(b/30281236): Remove when native Swift is deprecated. + boolean swiftLibDirSet = false; + for (String arg : objcProvider.get(ObjcProvider.LINKOPT)) { + if (arg.startsWith("-L") && arg.contains("usr/lib/swift")) { + swiftLibDirSet = true; + break; + } + } + + if (!swiftLibDirSet) { + commandLine + .add("-L") + .add(AppleToolchain.swiftLibDir(appleConfiguration.getSingleArchPlatform())); + } } for (String linkopt : attributes.linkopts()) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java index 009b3fddfe..4cf8e6264f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java @@ -1058,13 +1058,21 @@ public final class ReleaseBundlingSupport { return; } - CustomCommandLine.Builder commandLine = - CustomCommandLine.builder() - .addPath(intermediateArtifacts.swiftFrameworksFileZip().getExecPath()) - .add("Frameworks") - .add("--platform") - .add(platform.getLowerCaseNameInPlist()) - .addExecPath("--scan-executable", combinedArchBinary); + AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); + + CustomCommandLine.Builder commandLine = CustomCommandLine.builder(); + if (appleConfiguration.getXcodeToolchain() != null) { + commandLine.add("--toolchain").add(appleConfiguration.getXcodeToolchain()); + } + + commandLine + .add("--output_zip_path") + .addPath(intermediateArtifacts.swiftFrameworksFileZip().getExecPath()) + .add("--bundle_path") + .add("Frameworks") + .add("--platform") + .add(platform.getLowerCaseNameInPlist()) + .addExecPath("--scan-executable", combinedArchBinary); ruleContext.registerAction( ObjcRuleClasses.spawnAppleEnvActionBuilder(ruleContext, platform) @@ -1082,13 +1090,21 @@ public final class ReleaseBundlingSupport { return; } - CustomCommandLine.Builder commandLine = - CustomCommandLine.builder() - .addPath(intermediateArtifacts.swiftSupportZip().getExecPath()) - .add("SwiftSupport/" + platform.getLowerCaseNameInPlist()) - .add("--platform") - .add(platform.getLowerCaseNameInPlist()) - .addExecPath("--scan-executable", combinedArchBinary); + AppleConfiguration configuration = ruleContext.getFragment(AppleConfiguration.class); + + CustomCommandLine.Builder commandLine = CustomCommandLine.builder(); + if (configuration.getXcodeToolchain() != null) { + commandLine.add("--toolchain").add(configuration.getXcodeToolchain()); + } + + commandLine + .add("--output_zip_path") + .addPath(intermediateArtifacts.swiftSupportZip().getExecPath()) + .add("--bundle_path") + .add("SwiftSupport/" + platform.getLowerCaseNameInPlist()) + .add("--platform") + .add(platform.getLowerCaseNameInPlist()) + .addExecPath("--scan-executable", combinedArchBinary); ruleContext.registerAction( ObjcRuleClasses.spawnAppleEnvActionBuilder(ruleContext, platform) diff --git a/src/tools/xcode/swiftstdlibtoolwrapper/swiftstdlibtoolwrapper.sh b/src/tools/xcode/swiftstdlibtoolwrapper/swiftstdlibtoolwrapper.sh index 7197cdc32e..d4f2f4fc60 100755 --- a/src/tools/xcode/swiftstdlibtoolwrapper/swiftstdlibtoolwrapper.sh +++ b/src/tools/xcode/swiftstdlibtoolwrapper/swiftstdlibtoolwrapper.sh @@ -17,7 +17,9 @@ # swiftstdlibtoolwrapper runs swift-stdlib-tool and zips up the output. # This script only runs on darwin and you must have Xcode installed. # -# $1 OUTZIP - the path to place the output zip file. +# --output_zip_path - the path to place the output zip file. +# --bundle_path - the path inside of the archive to where libs will be copied. +# --toolchain - toolchain identifier to use with xcrun. set -eu @@ -25,15 +27,50 @@ MY_LOCATION=${MY_LOCATION:-"$0.runfiles/bazel_tools/tools/objc"} REALPATH="${MY_LOCATION}/realpath" WRAPPER="${MY_LOCATION}/xcrunwrapper.sh" -OUTZIP=$("${REALPATH}" "$1") -PATH_INSIDE_ZIP="$2" -shift 2 +TOOL_ARGS=() +while [[ $# -gt 0 ]]; do + ARG="$1" + shift + case "${ARG}" in + --output_zip_path) + ARG="$1" + shift + OUTZIP=$("${REALPATH}" "${ARG}") + ;; + --bundle_path) + ARG="$1" + shift + PATH_INSIDE_ZIP="$ARG" + ;; + --toolchain) + ARG="$1" + shift + TOOLCHAIN=${ARG} + ;; + # Remaining args are swift-stdlib-tool args + *) + TOOL_ARGS+=("$ARG") + ;; + esac +done + + TEMPDIR=$(mktemp -d "${TMPDIR:-/tmp}/swiftstdlibtoolZippingOutput.XXXXXX") trap "rm -rf \"$TEMPDIR\"" EXIT FULLPATH="$TEMPDIR/$PATH_INSIDE_ZIP" -$WRAPPER swift-stdlib-tool --copy --verbose --destination "$FULLPATH" "$@" +XCRUN_ARGS=() + +if [ -n "${TOOLCHAIN:-}" ]; then + XCRUN_ARGS+=(--toolchain "$TOOLCHAIN") +fi + +XCRUN_ARGS+=(swift-stdlib-tool --copy --verbose ) +XCRUN_ARGS+=(--destination "$FULLPATH") +XCRUN_ARGS+=( "${TOOL_ARGS[@]}" ) + +$WRAPPER "${XCRUN_ARGS[@]}" # Need to push/pop tempdir so it isn't the current working directory # when we remove it via the EXIT trap. diff --git a/tools/build_defs/apple/swift.bzl b/tools/build_defs/apple/swift.bzl index 9b496688a7..3cc22fe44b 100644 --- a/tools/build_defs/apple/swift.bzl +++ b/tools/build_defs/apple/swift.bzl @@ -78,6 +78,39 @@ def _module_name(ctx): """Returns a module name for the given rule context.""" return ctx.label.package.lstrip("//").replace("/", "_") + "_" + ctx.label.name +def _swift_lib_dir(ctx): + """Returns the location of swift runtime directory to link against.""" + # TODO(dmishe): Expose this template from native code. + developer_dir = "__BAZEL_XCODE_DEVELOPER_DIR__" + platform_str = ctx.fragments.apple.single_arch_platform.name_in_plist.lower() + + toolchain_name = "XcodeDefault" + if hasattr(ctx.fragments.apple, "xcode_toolchain"): + toolchain = ctx.fragments.apple.xcode_toolchain + + # We cannot use non Xcode-packaged toolchains, and the only one non-default + # toolchain known to exist (as of Xcode 8.1) is this one. + # TODO(b/29338444): Write an integration test when Xcode 8 is available. + if toolchain == "com.apple.dt.toolchain.Swift_2_3": + toolchain_name = "Swift_2.3" + + return "{0}/Toolchains/{1}.xctoolchain/usr/lib/swift/{2}".format( + developer_dir, toolchain_name, platform_str) + +def _swift_linkopts(ctx): + """Returns additional linker arguments for the given rule context.""" + return set(["-L" + _swift_lib_dir(ctx)]) + +def _swift_xcrun_args(ctx): + """Returns additional arguments that should be passed to xcrun.""" + # TODO(dmishe): Remove this check when xcode_toolchain is available by default + args = [] + if hasattr(ctx.fragments.apple, "xcode_toolchain"): + if ctx.fragments.apple.xcode_toolchain: + args += ["--toolchain", ctx.fragments.apple.xcode_toolchain] + + return args + def _swift_library_impl(ctx): """Implementation for swift_library Skylark rule.""" # TODO(b/29772303): Assert xcode version. @@ -202,7 +235,7 @@ def _swift_library_impl(ctx): # https://llvm.org/bugs/show_bug.cgi?id=19501 + ["-fmodule-map-file=%s" % x.path for x in objc_module_maps]) - args = [ + args = _swift_xcrun_args(ctx) + [ "swiftc", "-emit-object", "-emit-module-path", @@ -253,7 +286,8 @@ def _swift_library_impl(ctx): library=set([output_lib] + dep_libs), header=set([output_header]), providers=objc_providers, - uses_swift=True) + linkopt=_swift_linkopts(ctx), + uses_swift=True,) return struct( swift=struct( |