|
25 | 25 | from tools.wrapper_common import execute |
26 | 26 | from tools.wrapper_common import lipo |
27 | 27 |
|
28 | | -_OTOOL_MINIMUM_OS_VERSION_RE = re.compile( |
29 | | - r""" |
30 | | -( |
31 | | - cmd\ LC_VERSION_MIN_(?P<lc_version_min_platform>[^\n]+)\n |
32 | | - .*? |
33 | | - version\ (?P<lc_version_min_version>\d+\.\d+) |
34 | | - | |
35 | | - cmd\ LC_BUILD_VERSION |
36 | | - .*? |
37 | | - platform\ (?P<lc_build_version_platform>[^\n]+)\n |
38 | | - .*? |
39 | | - minos\ (?P<lc_build_version_minos>\d+\.\d+) |
40 | | -) |
41 | | -""", re.VERBOSE | re.MULTILINE | re.DOTALL) |
42 | | - |
43 | | -# Minimum OS versions after which the Swift runtime is packaged with the OS. If |
44 | | -# the deployment target of a binary is greater than or equal to the versions |
45 | | -# defined here it does not need to bundle the Swift runtime. |
46 | | -_MIN_OS_PLATFORM_SWIFT_PRESENCE = { |
47 | | - "ios": (12, 2), |
48 | | - "iphoneos": (12, 2), |
49 | | - "macos": (10, 14, 4), |
50 | | - "macosx": (10, 14, 4), |
51 | | - "tvos": (12, 2), |
52 | | - "watchos": (5, 2), |
53 | | -} |
54 | | - |
55 | | - |
56 | | -def _deployment_target_requires_bundled_swift_runtime(platform, version): |
57 | | - """Returns true if the given deployment target requires a bundled copy of the Swift runtime.""" |
58 | | - |
59 | | - platform = platform.lower().replace("simulator", "") |
60 | | - version = tuple(int(component) for component in version.split(".")) |
61 | | - |
62 | | - return version < _MIN_OS_PLATFORM_SWIFT_PRESENCE.get(platform, (0, 0)) |
63 | | - |
64 | | - |
65 | | -def _binary_requires_bundled_swift_runtime(binary): |
66 | | - """Returns true if the deployment target of the given binary requires a bundled copy of the Swift runtime.""" |
67 | | - |
68 | | - cmd = ["otool", "-lV", "-arch", "all", binary] |
69 | | - _, stdout, stderr = execute.execute_and_filter_output( |
70 | | - cmd, raise_on_failure=True) |
71 | | - if stderr: |
72 | | - print(stderr) |
73 | | - |
74 | | - # Loop to ensure we process all architectures within the binary. Different |
75 | | - # architectures may have different deployment targets. |
76 | | - while True: |
77 | | - match = _OTOOL_MINIMUM_OS_VERSION_RE.search(stdout) |
78 | | - if not match: |
79 | | - return False |
80 | | - |
81 | | - groups = match.groupdict() |
82 | | - # Only one of each alternative of platform and version can be set. |
83 | | - platform = groups["lc_version_min_platform"] or groups[ |
84 | | - "lc_build_version_platform"] |
85 | | - version = groups["lc_version_min_version"] or groups[ |
86 | | - "lc_build_version_minos"] |
87 | | - |
88 | | - if _deployment_target_requires_bundled_swift_runtime(platform, version): |
89 | | - return True |
90 | 28 |
|
91 | | - stdout = stdout[match.endpos:] |
92 | | - |
93 | | - |
94 | | -def _copy_swift_stdlibs(binaries_to_scan, sdk_platform, destination_path): |
| 29 | +def _copy_swift_stdlibs( |
| 30 | + *, |
| 31 | + binaries_to_scan, |
| 32 | + sdk_platform, |
| 33 | + destination_path, |
| 34 | + requires_bundled_swift_runtime): |
95 | 35 | """Copies the Swift stdlibs required by the binaries to the destination.""" |
96 | 36 | # Rely on the swift-stdlib-tool to determine the subset of Swift stdlibs that |
97 | 37 | # these binaries require. |
@@ -127,9 +67,7 @@ def _copy_swift_stdlibs(binaries_to_scan, sdk_platform, destination_path): |
127 | 67 | # is old enough that it may run on OS versions that lack the Swift runtime, |
128 | 68 | # so we detect this scenario and remove the Swift runtime from the output |
129 | 69 | # path. |
130 | | - if not any( |
131 | | - _binary_requires_bundled_swift_runtime(binary) |
132 | | - for binary in binaries_to_scan): |
| 70 | + if not requires_bundled_swift_runtime: |
133 | 71 | libswiftcore_path = os.path.join(destination_path, "libswiftCore.dylib") |
134 | 72 | if os.path.exists(libswiftcore_path): |
135 | 73 | os.remove(libswiftcore_path) |
@@ -184,13 +122,25 @@ def main(): |
184 | 122 | "--output_path", type=str, required=True, help="path to save the Swift " |
185 | 123 | "support libraries to" |
186 | 124 | ) |
| 125 | + parser.add_argument( |
| 126 | + "--requires_bundled_swift_runtime", action="store_true", default=False, |
| 127 | + help=""" |
| 128 | + if true, indicates that the Swift runtime needs to be bundled with the |
| 129 | + binary |
| 130 | + """ |
| 131 | + ) |
187 | 132 | args = parser.parse_args() |
188 | 133 |
|
189 | 134 | # Create a temporary location for the unstripped Swift stdlibs. |
190 | 135 | temp_path = tempfile.mkdtemp(prefix="swift_stdlib_tool.XXXXXX") |
191 | 136 |
|
192 | 137 | # Use the binaries to copy only the Swift stdlibs we need for this app. |
193 | | - _copy_swift_stdlibs(args.binary, args.platform, temp_path) |
| 138 | + _copy_swift_stdlibs( |
| 139 | + binaries_to_scan=args.binary, |
| 140 | + sdk_platform=args.platform, |
| 141 | + destination_path=temp_path, |
| 142 | + requires_bundled_swift_runtime=args.requires_bundled_swift_runtime, |
| 143 | + ) |
194 | 144 |
|
195 | 145 | # Determine the binary slices we need to strip with lipo. |
196 | 146 | target_archs, _ = lipo.find_archs_for_binaries(args.binary) |
|
0 commit comments