aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/xcode
diff options
context:
space:
mode:
authorGravatar Dmitry Shevchenko <dmishe@google.com>2017-03-09 22:00:00 +0000
committerGravatar Vladimir Moskva <vladmos@google.com>2017-03-10 10:28:04 +0000
commit701ff40ad9d1b6c1e3beb52064e2ae2fe27b7e29 (patch)
treec41547aee42e499012bac4f5e3f6959b5d5b913f /src/tools/xcode
parent4050dca289a72dce7d09509da56b34e688a02a73 (diff)
Introduce swift-stdlib-tool replacement
* swift-stdlib-tool is a utility that, given a binary, walks its dynamic library deps graph and picks everything that is used by Swift runtime. This tool is being removed from Xcode 8.3, hence the replacement. * The new tool has a different command line interface, but keeps backwards compatibility with native Bazel code through changes in the wrapper script. The wrapper script is still needed to handle xcrun ENV stuff. -- PiperOrigin-RevId: 149691879 MOS_MIGRATED_REVID=149691879
Diffstat (limited to 'src/tools/xcode')
-rw-r--r--src/tools/xcode/swiftstdlibtoolwrapper/BUILD10
-rw-r--r--src/tools/xcode/swiftstdlibtoolwrapper/swift_stdlib_tool.py72
-rwxr-xr-xsrc/tools/xcode/swiftstdlibtoolwrapper/swiftstdlibtoolwrapper.sh35
3 files changed, 103 insertions, 14 deletions
diff --git a/src/tools/xcode/swiftstdlibtoolwrapper/BUILD b/src/tools/xcode/swiftstdlibtoolwrapper/BUILD
index a4af5932c8..e76fe9313a 100644
--- a/src/tools/xcode/swiftstdlibtoolwrapper/BUILD
+++ b/src/tools/xcode/swiftstdlibtoolwrapper/BUILD
@@ -5,10 +5,20 @@ filegroup(
srcs = glob(["**"]),
)
+# Sources that need to be packaged into embedded tools.
+filegroup(
+ name = "swiftstdlibtoolwrapper_srcs",
+ srcs = [
+ "swift_stdlib_tool.py",
+ "swiftstdlibtoolwrapper.sh",
+ ],
+)
+
sh_binary(
name = "swiftstdlibtoolwrapper",
srcs = ["swiftstdlibtoolwrapper.sh"],
data = [
+ ":swift_stdlib_tool.py",
"//src/tools/xcode/realpath",
"//src/tools/xcode/xcrunwrapper",
],
diff --git a/src/tools/xcode/swiftstdlibtoolwrapper/swift_stdlib_tool.py b/src/tools/xcode/swiftstdlibtoolwrapper/swift_stdlib_tool.py
new file mode 100644
index 0000000000..6320d21211
--- /dev/null
+++ b/src/tools/xcode/swiftstdlibtoolwrapper/swift_stdlib_tool.py
@@ -0,0 +1,72 @@
+# pylint: disable=g-bad-file-header
+# Copyright 2017 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""A tool to find Swift runtime libraries required by a binary.
+
+This tool is modeled after Xcode's swift-stdlib-tool. Given a binary, it
+scans its transitive dylib dependencies to figure out the full set of Swift
+runtime libraries (usually named libswift*.dylib) required to run the binary.
+The libraries are then copied into the output directory.
+
+This tool is used by the Apple packaging rules to properly construct macOS, iOS,
+watchOS and tvOS app bundles.
+
+Usage:
+ swift-stdlib-tool.py BINARY_TO_SCAN PLATFORM_DIRECTORY OUTPUT_PATH
+"""
+
+import os
+import shutil
+import sys
+from macholib.MachO import MachO
+
+
+def dylib_full_path(platform_dir, relative_path):
+ """Constructs an absolute path to a platform dylib.
+
+ Args:
+ platform_dir: A path to the platforms directory in the Swift toolchain.
+ relative_path: A path to a dylib relative to the platforms directory.
+
+ Returns:
+ A normalized, absolute path to a dylib.
+ """
+ return os.path.abspath(os.path.join(platform_dir, relative_path))
+
+
+def main():
+ binary_path = sys.argv[1]
+ platform_dir = sys.argv[2]
+ out_path = sys.argv[3]
+
+ # We want any dylib linked against which name starts with "libswift"
+ seen = set()
+ queue = [binary_path]
+ while queue:
+ path = queue.pop()
+ m = MachO(path)
+ for header in m.headers:
+ for _, _, other in header.walkRelocatables():
+ if other.startswith("@rpath/libswift"):
+ full_path = dylib_full_path(platform_dir, other.lstrip("@rpath/"))
+ if full_path not in seen:
+ queue.append(full_path)
+ seen.add(full_path)
+
+ for dylib in seen:
+ shutil.copy(dylib, out_path)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/tools/xcode/swiftstdlibtoolwrapper/swiftstdlibtoolwrapper.sh b/src/tools/xcode/swiftstdlibtoolwrapper/swiftstdlibtoolwrapper.sh
index 99c920543e..9bf325f810 100755
--- a/src/tools/xcode/swiftstdlibtoolwrapper/swiftstdlibtoolwrapper.sh
+++ b/src/tools/xcode/swiftstdlibtoolwrapper/swiftstdlibtoolwrapper.sh
@@ -27,9 +27,6 @@ MY_LOCATION=${MY_LOCATION:-"$0.runfiles/bazel_tools/tools/objc"}
REALPATH="${MY_LOCATION}/realpath"
WRAPPER="${MY_LOCATION}/xcrunwrapper.sh"
-CMD_ARGS=("$@")
-
-TOOL_ARGS=()
while [[ $# -gt 0 ]]; do
ARG="$1"
shift
@@ -49,29 +46,39 @@ while [[ $# -gt 0 ]]; do
shift
TOOLCHAIN=${ARG}
;;
- # Remaining args are swift-stdlib-tool args
- *)
- TOOL_ARGS+=("$ARG")
- ;;
+ --scan-executable)
+ ARG="$1"
+ shift
+ BINARY=${ARG}
+ ;;
+ --platform)
+ ARG="$1"
+ shift
+ PLATFORM=${ARG}
+ ;;
esac
done
+# Prepare destination directory
TEMPDIR=$(mktemp -d "${TMPDIR:-/tmp}/swiftstdlibtoolZippingOutput.XXXXXX")
trap "rm -rf \"$TEMPDIR\"" EXIT
FULLPATH="$TEMPDIR/$PATH_INSIDE_ZIP"
-
-XCRUN_ARGS=()
+mkdir -p "${FULLPATH}"
if [ -n "${TOOLCHAIN:-}" ]; then
- XCRUN_ARGS+=(--toolchain "$TOOLCHAIN")
+ readonly swiftc_dir=$(dirname "$("${WRAPPER}" -f swiftc --toolchain "${TOOLCHAIN}")")
+else
+ readonly swiftc_dir=$(dirname "$("${WRAPPER}" -f swiftc)")
fi
-XCRUN_ARGS+=(swift-stdlib-tool --copy --verbose )
-XCRUN_ARGS+=(--destination "$FULLPATH")
-XCRUN_ARGS+=( "${TOOL_ARGS[@]}" )
+# Each toolchain has swift libraries directory located at
+# /path/to/swiftc/../../lib/swift/<platform>/
+# This is the same relative path that Xcode uses and is considered to be stable.
+readonly platform_dir="${swiftc_dir}/../lib/swift/${PLATFORM}"
-$WRAPPER "${XCRUN_ARGS[@]}"
+# Always use macOS system Python as it comes with macholib module.
+/usr/bin/python "${MY_LOCATION}/swift_stdlib_tool.py" "${BINARY}" "${platform_dir}" "${FULLPATH}"
# Need to push/pop tempdir so it isn't the current working directory
# when we remove it via the EXIT trap.