Skip to content

Commit 7d1bfd1

Browse files
cbrackenGitHub Actions Bot
authored andcommitted
[iOS] Bundle dSYM packages in Flutter.xcframework (flutter#54414)
As of Xcode 16, App Store validation requires dSYMs for frameworks in app archives. Bundling dSYMs also significantly simplifies stack trace symbolification, so we should be doing this regardless. This adds both framework and simulator framework dSYMs to the Flutter.xcframework bundle. Issue: flutter/flutter#116493 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent c4b0a37 commit 7d1bfd1

File tree

2 files changed

+32
-15
lines changed

2 files changed

+32
-15
lines changed

sky/tools/create_full_ios_framework.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,20 @@ def create_framework( # pylint: disable=too-many-arguments
144144
print('Cannot find iOS simulator dylib at %s' % simulator_x64_dylib)
145145
return 1
146146

147+
# Compute dsym output paths, if enabled.
148+
framework_dsym = None
149+
simulator_dsym = None
150+
if args.dsym:
151+
framework_dsym = os.path.splitext(framework)[0] + '.dSYM'
152+
simulator_dsym = os.path.splitext(simulator_framework)[0] + '.dSYM'
153+
154+
# Emit the framework for physical devices.
147155
shutil.rmtree(framework, True)
148156
shutil.copytree(arm64_framework, framework)
149157
framework_binary = os.path.join(framework, 'Flutter')
150-
process_framework(args, dst, framework, framework_binary)
158+
process_framework(args, dst, framework_binary, framework_dsym)
151159

160+
# Emit the framework for simulators.
152161
if args.simulator_arm64_out_dir is not None:
153162
shutil.rmtree(simulator_framework, True)
154163
shutil.copytree(simulator_arm64_framework, simulator_framework)
@@ -160,22 +169,23 @@ def create_framework( # pylint: disable=too-many-arguments
160169
'lipo', simulator_x64_dylib, simulator_arm64_dylib, '-create', '-output',
161170
simulator_framework_binary
162171
])
163-
process_framework(args, dst, simulator_framework, simulator_framework_binary)
172+
process_framework(args, dst, simulator_framework_binary, simulator_dsym)
164173
else:
165174
simulator_framework = simulator_x64_framework
166175

167176
# Create XCFramework from the arm-only fat framework and the arm64/x64
168177
# simulator frameworks, or just the x64 simulator framework if only that one
169178
# exists.
170179
xcframeworks = [simulator_framework, framework]
171-
create_xcframework(location=dst, name='Flutter', frameworks=xcframeworks)
180+
dsyms = [simulator_dsym, framework_dsym] if args.dsym else None
181+
create_xcframework(location=dst, name='Flutter', frameworks=xcframeworks, dsyms=dsyms)
172182

173-
# Add the x64 simulator into the fat framework
183+
# Add the x64 simulator into the fat framework.
174184
subprocess.check_call([
175185
'lipo', arm64_dylib, simulator_x64_dylib, '-create', '-output', framework_binary
176186
])
177187

178-
process_framework(args, dst, framework, framework_binary)
188+
process_framework(args, dst, framework_binary, framework_dsym)
179189
return 0
180190

181191

@@ -216,16 +226,14 @@ def zip_archive(dst):
216226
subprocess.check_call(['zip', '-r', 'extension_safe_Flutter.dSYM.zip', 'Flutter.dSYM'], cwd=dst)
217227

218228

219-
def process_framework(args, dst, framework, framework_binary):
220-
if args.dsym:
221-
dsym_out = os.path.splitext(framework)[0] + '.dSYM'
222-
subprocess.check_call([DSYMUTIL, '-o', dsym_out, framework_binary])
229+
def process_framework(args, dst, framework_binary, dsym):
230+
if dsym:
231+
subprocess.check_call([DSYMUTIL, '-o', dsym, framework_binary])
223232

224233
if args.strip:
225234
# copy unstripped
226235
unstripped_out = os.path.join(dst, 'Flutter.unstripped')
227236
shutil.copyfile(framework_binary, unstripped_out)
228-
229237
subprocess.check_call(['strip', '-x', '-S', framework_binary])
230238

231239

sky/tools/create_xcframework.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,22 @@ def main():
2222
help='The framework paths used to create the XCFramework.',
2323
required=True
2424
)
25+
parser.add_argument(
26+
'--dsyms', nargs='+', help='The dSYM paths to be bundled in the XCFramework.', required=False
27+
)
2528
parser.add_argument('--name', help='Name of the XCFramework', type=str, required=True)
2629
parser.add_argument('--location', help='Output directory', type=str, required=True)
2730

2831
args = parser.parse_args()
2932

30-
create_xcframework(args.location, args.name, args.frameworks)
33+
create_xcframework(args.location, args.name, args.frameworks, args.dsyms)
34+
3135

36+
def create_xcframework(location, name, frameworks, dsyms=None):
37+
if dsyms and len(frameworks) != len(dsyms):
38+
print('Number of --dsyms must match number of --frameworks exactly.', file=sys.stderr)
39+
sys.exit(1)
3240

33-
def create_xcframework(location, name, frameworks):
3441
output_dir = os.path.abspath(location)
3542
output_xcframework = os.path.join(output_dir, '%s.xcframework' % name)
3643

@@ -45,11 +52,13 @@ def create_xcframework(location, name, frameworks):
4552
# -framework bar/baz.framework -output output/
4653
command = ['xcrun', 'xcodebuild', '-quiet', '-create-xcframework']
4754

48-
for framework in frameworks:
49-
command.extend(['-framework', os.path.abspath(framework)])
50-
5155
command.extend(['-output', output_xcframework])
5256

57+
for i in range(len(frameworks)): # pylint: disable=consider-using-enumerate
58+
command.extend(['-framework', os.path.abspath(frameworks[i])])
59+
if dsyms:
60+
command.extend(['-debug-symbols', os.path.abspath(dsyms[i])])
61+
5362
subprocess.check_call(command, stdout=open(os.devnull, 'w'))
5463

5564

0 commit comments

Comments
 (0)