@@ -154,37 +154,11 @@ class AOTSnapshotter {
154154 }
155155 }
156156
157- String aotSharedLibrary = _fileSystem.path.join (outputDir.path, 'app.so' );
158- String ? frameworkPath;
157+ final String assembly = _fileSystem.path.join (outputDir.path, 'snapshot_assembly.S' );
159158 if (targetingApplePlatform) {
160- // On iOS and macOS, we use Xcode to compile the snapshot into a dynamic
161- // library that the end-developer can link into their app.
162- const frameworkName = 'App.framework' ;
163- if (! quiet) {
164- final String targetArch = darwinArch! .name;
165- _logger.printStatus ('Building $frameworkName for $targetArch ...' );
166- }
167- frameworkPath = _fileSystem.path.join (outputPath, frameworkName);
168- _fileSystem.directory (frameworkPath).createSync (recursive: true );
169-
170- const frameworkSnapshotName = 'App' ;
171- aotSharedLibrary = _fileSystem.path.join (frameworkPath, frameworkSnapshotName);
172- final String relocatableObject = _fileSystem.path.join (outputPath, 'app.o' );
173- // When the minimum version is updated, remember to update
174- // template MinimumOSVersion.
175- // https://github.com/flutter/flutter/pull/62902
176- final minOSVersion = platform == TargetPlatform .ios
177- ? FlutterDarwinPlatform .ios.deploymentTarget ().toString ()
178- : FlutterDarwinPlatform .macos.deploymentTarget ().toString ();
179- genSnapshotArgs.addAll (< String > [
180- '--snapshot_kind=app-aot-macho-dylib' ,
181- '--macho=$aotSharedLibrary ' ,
182- '--macho-object=$relocatableObject ' ,
183- '--macho-min-os-version=$minOSVersion ' ,
184- '--macho-rpath=@executable_path/Frameworks,@loader_path/Frameworks' ,
185- '--macho-install-name=@rpath/$frameworkName /$frameworkSnapshotName ' ,
186- ]);
159+ genSnapshotArgs.addAll (< String > ['--snapshot_kind=app-aot-assembly' , '--assembly=$assembly ' ]);
187160 } else {
161+ final String aotSharedLibrary = _fileSystem.path.join (outputDir.path, 'app.so' );
188162 genSnapshotArgs.addAll (< String > ['--snapshot_kind=app-aot-elf' , '--elf=$aotSharedLibrary ' ]);
189163 }
190164
@@ -246,38 +220,123 @@ class AOTSnapshotter {
246220 return genSnapshotExitCode;
247221 }
248222
223+ // On iOS and macOS, we use Xcode to compile the snapshot into a dynamic library that the
224+ // end-developer can link into their app.
249225 if (targetingApplePlatform) {
250- if (extractAppleDebugSymbols) {
251- final RunResult dsymResult = await _xcode.dsymutil (< String > [
252- '-o' ,
253- '$frameworkPath .dSYM' ,
254- aotSharedLibrary,
255- ]);
256- if (dsymResult.exitCode != 0 ) {
226+ return _buildFramework (
227+ appleArch: darwinArch! ,
228+ isIOS: platform == TargetPlatform .ios,
229+ sdkRoot: sdkRoot,
230+ assemblyPath: assembly,
231+ outputPath: outputDir.path,
232+ quiet: quiet,
233+ stripAfterBuild: stripAfterBuild,
234+ extractAppleDebugSymbols: extractAppleDebugSymbols,
235+ );
236+ } else {
237+ return 0 ;
238+ }
239+ }
240+
241+ /// Builds an iOS or macOS framework at [outputPath] /App.framework from the assembly
242+ /// source at [assemblyPath] .
243+ Future <int > _buildFramework ({
244+ required DarwinArch appleArch,
245+ required bool isIOS,
246+ String ? sdkRoot,
247+ required String assemblyPath,
248+ required String outputPath,
249+ required bool quiet,
250+ required bool stripAfterBuild,
251+ required bool extractAppleDebugSymbols,
252+ }) async {
253+ final String targetArch = appleArch.name;
254+ if (! quiet) {
255+ _logger.printStatus ('Building App.framework for $targetArch ...' );
256+ }
257+
258+ final commonBuildOptions = < String > [
259+ '-arch' ,
260+ targetArch,
261+ if (isIOS)
262+ // When the minimum version is updated, remember to update
263+ // template MinimumOSVersion.
264+ // https://github.com/flutter/flutter/pull/62902
265+ '-miphoneos-version-min=${FlutterDarwinPlatform .ios .deploymentTarget ()}' ,
266+ if (sdkRoot != null ) ...< String > ['-isysroot' , sdkRoot],
267+ ];
268+
269+ final String assemblyO = _fileSystem.path.join (outputPath, 'snapshot_assembly.o' );
270+
271+ final RunResult compileResult = await _xcode.cc (< String > [
272+ ...commonBuildOptions,
273+ '-c' ,
274+ assemblyPath,
275+ '-o' ,
276+ assemblyO,
277+ ]);
278+ if (compileResult.exitCode != 0 ) {
279+ _logger.printError (
280+ 'Failed to compile AOT snapshot. Compiler terminated with exit code ${compileResult .exitCode }' ,
281+ );
282+ return compileResult.exitCode;
283+ }
284+
285+ final String frameworkDir = _fileSystem.path.join (outputPath, 'App.framework' );
286+ _fileSystem.directory (frameworkDir).createSync (recursive: true );
287+ final String appLib = _fileSystem.path.join (frameworkDir, 'App' );
288+ final linkArgs = < String > [
289+ ...commonBuildOptions,
290+ '-dynamiclib' ,
291+ '-Xlinker' ,
292+ '-rpath' ,
293+ '-Xlinker' ,
294+ '@executable_path/Frameworks' ,
295+ '-Xlinker' ,
296+ '-rpath' ,
297+ '-Xlinker' ,
298+ '@loader_path/Frameworks' ,
299+ '-fapplication-extension' ,
300+ '-install_name' ,
301+ '@rpath/App.framework/App' ,
302+ '-o' ,
303+ appLib,
304+ assemblyO,
305+ ];
306+
307+ final RunResult linkResult = await _xcode.clang (linkArgs);
308+ if (linkResult.exitCode != 0 ) {
309+ _logger.printError (
310+ 'Failed to link AOT snapshot. Linker terminated with exit code ${linkResult .exitCode }' ,
311+ );
312+ return linkResult.exitCode;
313+ }
314+
315+ if (extractAppleDebugSymbols) {
316+ final RunResult dsymResult = await _xcode.dsymutil (< String > [
317+ '-o' ,
318+ '$frameworkDir .dSYM' ,
319+ appLib,
320+ ]);
321+ if (dsymResult.exitCode != 0 ) {
322+ _logger.printError (
323+ 'Failed to generate dSYM - dsymutil terminated with exit code ${dsymResult .exitCode }' ,
324+ );
325+ return dsymResult.exitCode;
326+ }
327+
328+ if (stripAfterBuild) {
329+ // See https://www.unix.com/man-page/osx/1/strip/ for arguments
330+ final RunResult stripResult = await _xcode.strip (< String > ['-x' , appLib, '-o' , appLib]);
331+ if (stripResult.exitCode != 0 ) {
257332 _logger.printError (
258- 'Failed to generate dSYM - dsymutil terminated with exit code ${dsymResult .exitCode }' ,
333+ 'Failed to strip debugging symbols from the generated AOT snapshot - strip terminated with exit code ${stripResult .exitCode }' ,
259334 );
260- return dsymResult .exitCode;
335+ return stripResult .exitCode;
261336 }
262-
263- if (stripAfterBuild) {
264- // See https://www.unix.com/man-page/osx/1/strip/ for arguments
265- final RunResult stripResult = await _xcode.strip (< String > [
266- '-x' ,
267- aotSharedLibrary,
268- '-o' ,
269- aotSharedLibrary,
270- ]);
271- if (stripResult.exitCode != 0 ) {
272- _logger.printError (
273- 'Failed to strip debugging symbols from the generated AOT snapshot - strip terminated with exit code ${stripResult .exitCode }' ,
274- );
275- return stripResult.exitCode;
276- }
277- }
278- } else {
279- assert (! stripAfterBuild);
280337 }
338+ } else {
339+ assert (! stripAfterBuild);
281340 }
282341
283342 return 0 ;
@@ -295,6 +354,7 @@ class AOTSnapshotter {
295354 TargetPlatform .darwin,
296355 TargetPlatform .linux_x64,
297356 TargetPlatform .linux_arm64,
357+ TargetPlatform .linux_riscv64,
298358 TargetPlatform .windows_x64,
299359 TargetPlatform .windows_arm64,
300360 ].contains (platform);
0 commit comments