Skip to content

Commit 03f1208

Browse files
authored
Fix SwiftPM scheme migration to handle when there are no BuildActionEntries (#164660)
An Xcode scheme may or may not have `BuildActionEntries`. When migrating to SwiftPM, if Flutter cannot find `BuildActionEntries` in the xcscheme, append the `PreAction` to the end of the `BuildAction`. Fixes flutter/flutter#163086. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1 parent 76d7910 commit 03f1208

File tree

2 files changed

+70
-17
lines changed

2 files changed

+70
-17
lines changed

packages/flutter_tools/lib/src/migrations/swift_package_manager_integration_migration.dart

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,18 @@ class SwiftPackageManagerIntegrationMigration extends ProjectMigrator {
311311
$newContent
312312
</PreActions>
313313
''';
314-
final String? buildActionEntries =
314+
String? buildAction =
315315
schemeLines.where((String line) => line.contains('<BuildActionEntries>')).firstOrNull;
316-
if (buildActionEntries == null) {
317-
throw Exception(
318-
'Failed to parse ${schemeFile.basename}: Could not find BuildActionEntries.',
319-
);
320-
} else {
321-
newScheme = schemeContent.replaceFirst(
322-
buildActionEntries,
323-
'$newContent$buildActionEntries',
324-
);
316+
if (buildAction == null) {
317+
// If there are no BuildActionEntries, append before end of BuildAction.
318+
buildAction =
319+
schemeLines.where((String line) => line.contains('</BuildAction>')).firstOrNull;
320+
321+
if (buildAction == null) {
322+
throw Exception('Failed to parse ${schemeFile.basename}: Could not find BuildAction.');
323+
}
325324
}
325+
newScheme = schemeContent.replaceFirst(buildAction, '$newContent$buildAction');
326326
}
327327

328328
schemeFile.writeAsStringSync(newScheme);

packages/flutter_tools/test/general.shard/migrations/swift_package_manager_integration_migration_test.dart

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ void main() {
464464
},
465465
);
466466

467-
testWithoutContext('fails if cannot find BuildActionEntries in scheme', () async {
467+
testWithoutContext('fails if cannot find BuildAction in scheme', () async {
468468
final MemoryFileSystem memoryFileSystem = MemoryFileSystem();
469469
final BufferLogger testLogger = BufferLogger.test();
470470
final FakeXcodeProject project = FakeXcodeProject(
@@ -490,7 +490,7 @@ void main() {
490490
await expectLater(
491491
() => projectMigration.migrate(),
492492
throwsToolExit(
493-
message: 'Failed to parse Runner.xcscheme: Could not find BuildActionEntries',
493+
message: 'Failed to parse Runner.xcscheme: Could not find BuildAction',
494494
),
495495
);
496496
});
@@ -525,6 +525,42 @@ void main() {
525525
);
526526
});
527527

528+
testWithoutContext('successfully updates scheme with no BuildActionEntries', () async {
529+
final MemoryFileSystem memoryFileSystem = MemoryFileSystem();
530+
final BufferLogger testLogger = BufferLogger.test();
531+
final FakeXcodeProject project = FakeXcodeProject(
532+
platform: platform.name,
533+
fileSystem: memoryFileSystem,
534+
logger: testLogger,
535+
);
536+
_createProjectFiles(project, platform);
537+
project.xcodeProjectSchemeFile().writeAsStringSync(
538+
_validBuildActions(platform, hasBuildEntries: false),
539+
);
540+
541+
final FakePlistParser plistParser = FakePlistParser.multiple(<String>[
542+
_plutilOutput(_allSectionsMigratedAsJson(platform)),
543+
_plutilOutput(_allSectionsMigratedAsJson(platform)),
544+
]);
545+
final SwiftPackageManagerIntegrationMigration projectMigration =
546+
SwiftPackageManagerIntegrationMigration(
547+
project,
548+
platform,
549+
BuildInfo.debug,
550+
xcodeProjectInterpreter: FakeXcodeProjectInterpreter(),
551+
logger: testLogger,
552+
fileSystem: memoryFileSystem,
553+
plistParser: plistParser,
554+
features: swiftPackageManagerFullyEnabledFlags,
555+
);
556+
557+
await projectMigration.migrate();
558+
expect(
559+
project.xcodeProjectSchemeFile().readAsStringSync(),
560+
_validBuildActions(platform, hasFrameworkScript: true, hasBuildEntries: false),
561+
);
562+
});
563+
528564
testWithoutContext('successfully updates scheme with preexisting PreActions', () async {
529565
final MemoryFileSystem memoryFileSystem = MemoryFileSystem();
530566
final BufferLogger testLogger = BufferLogger.test();
@@ -2621,6 +2657,7 @@ String _validBuildActions(
26212657
SupportedPlatform platform, {
26222658
bool hasPreActions = false,
26232659
bool hasFrameworkScript = false,
2660+
bool hasBuildEntries = true,
26242661
}) {
26252662
final String scriptText;
26262663
if (platform == SupportedPlatform.ios) {
@@ -2656,11 +2693,11 @@ String _validBuildActions(
26562693
\n <PreActions>
26572694
</PreActions>''';
26582695
}
2659-
return '''
2660-
<BuildAction
2661-
parallelizeBuildables = "YES"
2662-
buildImplicitDependencies = "YES">$preActions
2663-
<BuildActionEntries>
2696+
2697+
String buildEntries = '';
2698+
if (hasBuildEntries) {
2699+
buildEntries = '''
2700+
\n <BuildActionEntries>
26642701
<BuildActionEntry
26652702
buildForTesting = "YES"
26662703
buildForRunning = "YES"
@@ -2670,7 +2707,23 @@ String _validBuildActions(
26702707
${_validBuildableReference(platform)}
26712708
</BuildActionEntry>
26722709
</BuildActionEntries>
2710+
''';
2711+
}
2712+
return '''
2713+
<Scheme
2714+
LastUpgradeVersion = "1510"
2715+
version = "1.3">
2716+
<BuildAction
2717+
parallelizeBuildables = "YES"
2718+
buildImplicitDependencies = "YES">$preActions$buildEntries
26732719
</BuildAction>
2720+
<LaunchAction>
2721+
<BuildableProductRunnable
2722+
runnableDebuggingMode = "0">
2723+
${_validBuildableReference(platform)}
2724+
</BuildableProductRunnable>
2725+
</LaunchAction>
2726+
</Scheme>
26742727
''';
26752728
}
26762729

0 commit comments

Comments
 (0)