Reverts "Clean before building when framework headers change (#177512)" (#177610)

<!-- start_original_pr_link -->
Reverts: flutter/flutter#177512
<!-- end_original_pr_link -->
<!-- start_initiating_author -->
Initiated by: vashworth
<!-- end_initiating_author -->
<!-- start_revert_reason -->
Reason for reverting: May cause error:
```
Error (Xcode): Could not delete `/build/ios/Release-iphoneos`
because it was not created by the build system and it is not a subfolder of derived data.
```
<!-- end_revert_reason -->
<!-- start_original_pr_author -->
Original PR Author: vashworth
<!-- end_original_pr_author -->

<!-- start_reviewers -->
Reviewed By: {bkonyi}
<!-- end_reviewers -->

<!-- start_revert_body -->
This change reverts the following previous change:
Starting with Xcode 26, when a precompiled file changes (like a header
file in the Flutter framework), it throws an error. This PR adds a
fingerprinter to track changes to the headers. If the fingerprinting
detects a change, it cleans before building. This only applies to Xcode
26 and incremental builds. Fresh builds should not clean.

Fixes https://github.com/flutter/flutter/issues/176462.

## 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].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- 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

<!-- end_revert_body -->

Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
This commit is contained in:
auto-submit[bot] 2025-10-27 19:37:27 +00:00 committed by GitHub
parent b5d2ed668b
commit e35ecd9217
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 11 additions and 497 deletions

View File

@ -10,13 +10,11 @@ import 'package:unified_analytics/unified_analytics.dart';
import '../artifacts.dart';
import '../base/file_system.dart';
import '../base/fingerprint.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/process.dart';
import '../base/project_migrator.dart';
import '../base/utils.dart';
import '../base/version.dart';
import '../build_info.dart';
import '../cache.dart';
import '../darwin/darwin.dart';
@ -272,16 +270,6 @@ Future<XcodeBuildResult> buildXcodeProject({
'file version field before submitting to the App Store.',
);
}
final XcodeSdk sdk = environmentType == EnvironmentType.physical
? XcodeSdk.IPhoneOS
: XcodeSdk.IPhoneSimulator;
final String buildDirectoryPath = getIosBuildDirectory();
final Directory buildDirectory = globals.fs.directory(buildDirectoryPath);
final bool incrementalBuild =
buildDirectory.existsSync() &&
buildDirectory.listSync().any(
(FileSystemEntity entity) => entity.basename.contains(sdk.platformName),
);
Map<String, String>? autoSigningConfigs;
@ -322,7 +310,7 @@ Future<XcodeBuildResult> buildXcodeProject({
);
}
}
await processPodsIfNeeded(project.ios, buildDirectoryPath, buildInfo.mode);
await processPodsIfNeeded(project.ios, getIosBuildDirectory(), buildInfo.mode);
if (configOnly) {
return XcodeBuildResult(success: true);
}
@ -334,26 +322,6 @@ Future<XcodeBuildResult> buildXcodeProject({
configuration,
];
// Check the public headers before checking Xcode version so headers fingerprinter is created
// regardless of Xcode version.
final bool headersChanged = publicHeadersChanged(
environmentType: environmentType,
mode: buildInfo.mode,
buildDirectory: buildDirectoryPath,
artifacts: globals.artifacts,
fileSystem: globals.fs,
logger: globals.logger,
);
final Version? xcodeVersion = globals.xcode?.currentVersion;
if (headersChanged &&
incrementalBuild &&
(xcodeVersion != null && xcodeVersion >= Version(26, 0, 0))) {
// Xcode 26 changed the way headers are pre-compiled and will throw an error if the headers
// have changed since the last time they were compiled. To avoid this error, clean before
// building if headers have changed.
buildCommands.addAll(<String>['clean', 'build']);
}
if (globals.logger.isVerbose) {
// An environment variable to be passed to xcode_backend.sh determining
// whether to echo back executed commands.
@ -383,7 +351,7 @@ Future<XcodeBuildResult> buildXcodeProject({
scheme,
if (buildAction !=
XcodeBuildAction.archive) // dSYM files aren't copied to the archive if BUILD_DIR is set.
'BUILD_DIR=${globals.fs.path.absolute(buildDirectoryPath)}',
'BUILD_DIR=${globals.fs.path.absolute(getIosBuildDirectory())}',
]);
}
@ -405,14 +373,20 @@ Future<XcodeBuildResult> buildXcodeProject({
return XcodeBuildResult(success: false);
}
} else {
buildCommands.addAll(<String>['-sdk', sdk.platformName]);
if (environmentType == EnvironmentType.physical) {
buildCommands.addAll(<String>['-sdk', XcodeSdk.IPhoneOS.platformName]);
} else {
buildCommands.addAll(<String>['-sdk', XcodeSdk.IPhoneSimulator.platformName]);
}
}
buildCommands.add('-destination');
if (deviceID != null) {
buildCommands.add('id=$deviceID');
} else if (environmentType == EnvironmentType.physical) {
buildCommands.add(XcodeSdk.IPhoneOS.genericPlatform);
} else {
buildCommands.add(sdk.genericPlatform);
buildCommands.add(XcodeSdk.IPhoneSimulator.genericPlatform);
}
if (activeArch != null) {
@ -654,52 +628,6 @@ Future<XcodeBuildResult> buildXcodeProject({
}
}
/// Check if the Flutter framework's public headers have changed since last built.
bool publicHeadersChanged({
required BuildMode mode,
required EnvironmentType environmentType,
required String buildDirectory,
required Artifacts? artifacts,
required FileSystem fileSystem,
required Logger logger,
}) {
final String? basePath = artifacts?.getArtifactPath(
Artifact.flutterFramework,
platform: TargetPlatform.ios,
mode: mode,
environmentType: environmentType,
);
if (basePath == null) {
return false;
}
final Directory headersDirectory = fileSystem.directory(
fileSystem.path.join(basePath, 'Headers'),
);
if (!headersDirectory.existsSync()) {
return false;
}
final List<String> files = headersDirectory
.listSync()
.map<String>((FileSystemEntity header) => header.path)
.toList();
final String fingerprintPath = fileSystem.path.join(
buildDirectory,
'framework_public_headers.fingerprint',
);
final fingerprinter = Fingerprinter(
fingerprintPath: fingerprintPath,
paths: files,
fileSystem: fileSystem,
logger: logger,
);
final bool headersChanged = !fingerprinter.doesFingerprintMatch();
if (headersChanged) {
fingerprinter.writeFingerprint();
}
return headersChanged;
}
/// Extended attributes applied by Finder can cause code signing errors. Remove them.
/// https://developer.apple.com/library/archive/qa/qa1940/_index.html
Future<void> removeFinderExtendedAttributes(

View File

@ -5,7 +5,6 @@
import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
@ -315,7 +314,6 @@ void main() {
]),
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -352,7 +350,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -390,7 +387,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -427,7 +423,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -475,7 +470,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -514,7 +508,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -552,7 +545,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -588,7 +580,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -651,7 +642,6 @@ void main() {
FileSystemUtils: () => FileSystemUtils(fileSystem: fileSystem, platform: macosPlatform),
Analytics: () => fakeAnalytics,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -713,7 +703,6 @@ void main() {
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Pub: ThrowingPub.new,
Analytics: () => fakeAnalytics,
Artifacts: () => Artifacts.test(),
},
);
@ -777,7 +766,6 @@ void main() {
),
Pub: ThrowingPub.new,
Analytics: () => fakeAnalytics,
Artifacts: () => Artifacts.test(),
},
);
});
@ -821,7 +809,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -870,7 +857,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -924,7 +910,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -963,7 +948,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1020,7 +1004,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1068,7 +1051,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1110,7 +1092,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1169,7 +1150,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1214,7 +1194,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1257,7 +1236,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null),
Artifacts: () => Artifacts.test(),
},
);
@ -1301,7 +1279,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
EnvironmentType: () => EnvironmentType.physical,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1343,7 +1320,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null),
Artifacts: () => Artifacts.test(),
},
);
@ -1387,7 +1363,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null),
Artifacts: () => Artifacts.test(),
},
);
@ -1438,7 +1413,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null),
Artifacts: () => Artifacts.test(),
},
);
});
@ -1485,7 +1459,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1534,7 +1507,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1592,7 +1564,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1634,7 +1605,6 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
});

View File

@ -6,7 +6,6 @@ import 'dart:typed_data';
import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
@ -429,7 +428,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -485,7 +483,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(version: Version(15, 4, null)),
Artifacts: () => Artifacts.test(),
},
);
@ -541,7 +538,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(version: Version(15, 4, null)),
Artifacts: () => Artifacts.test(),
},
);
@ -597,7 +593,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(version: Version(15, 4, null)),
Artifacts: () => Artifacts.test(),
},
);
@ -630,7 +625,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(version: Version(15, 3, null)),
Artifacts: () => Artifacts.test(),
},
);
@ -686,7 +680,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(version: Version(15, 4, null)),
Artifacts: () => Artifacts.test(),
},
);
@ -719,7 +712,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () =>
FakeXcodeProjectInterpreterWithBuildSettings(version: Version(15, 3, null)),
Artifacts: () => Artifacts.test(),
},
);
@ -761,7 +753,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
PlistParser: () => plistUtils,
Artifacts: () => Artifacts.test(),
},
);
@ -820,7 +811,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -856,7 +846,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -915,7 +904,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -976,7 +964,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1037,7 +1024,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1068,7 +1054,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1100,7 +1085,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1161,7 +1145,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1191,7 +1174,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1253,7 +1235,6 @@ void main() {
FileSystemUtils: () => FileSystemUtils(fileSystem: fileSystem, platform: macosPlatform),
Analytics: () => fakeAnalytics,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1300,7 +1281,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1341,7 +1321,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1386,7 +1365,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1439,7 +1417,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1477,7 +1454,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1533,7 +1509,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -1592,7 +1567,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
PlistParser: () => plistUtils,
Artifacts: () => Artifacts.test(),
},
);
@ -1656,7 +1630,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
PlistParser: () => plistUtils,
Artifacts: () => Artifacts.test(),
},
);
@ -1719,7 +1692,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
PlistParser: () => plistUtils,
Artifacts: () => Artifacts.test(),
},
);
@ -1768,7 +1740,6 @@ void main() {
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
PlistParser: () => plistUtils,
Artifacts: () => Artifacts.test(),
},
);
@ -1819,7 +1790,6 @@ void main() {
Pub: ThrowingPub.new,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
PlistParser: () => plistUtils,
Artifacts: () => Artifacts.test(),
},
);
@ -1912,7 +1882,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -2005,7 +1974,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -2080,7 +2048,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -2155,7 +2122,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -2230,7 +2196,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -2307,7 +2272,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -2428,7 +2392,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -2519,7 +2482,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
@ -2612,7 +2574,6 @@ void main() {
Pub: ThrowingPub.new,
Platform: () => macosPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Artifacts: () => Artifacts.test(),
},
);
}

View File

@ -175,7 +175,6 @@ void main() {
),
Xcode: () => xcode,
Analytics: () => fakeAnalytics,
Artifacts: () => artifacts,
},
);
@ -214,7 +213,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(),
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
@ -300,7 +298,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
@ -416,217 +413,9 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
group('with Xcode 26', () {
late Xcode xcode;
late FakeXcodeProjectInterpreter fakeXcodeProjectInterpreter;
late FakeArtifacts fakeArtifacts;
setUp(() {
fakeXcodeProjectInterpreter = FakeXcodeProjectInterpreter(
projectInfo: projectInfo,
xcodeVersion: Version(26, 0, 0),
);
xcode = Xcode.test(
processManager: FakeProcessManager.any(),
xcodeProjectInterpreter: fakeXcodeProjectInterpreter,
);
fakeArtifacts = FakeArtifacts(
frameworkPath: fileSystem.systemTempDirectory.childDirectory('Flutter.framework').path,
);
});
testUsingContext(
'cleans before build when headers change when incremental build',
() async {
final IOSDevice iosDevice = setUpIOSDevice(
fileSystem: fileSystem,
processManager: processManager,
logger: logger,
artifacts: artifacts,
);
setUpIOSProject(fileSystem);
final FlutterProject flutterProject = FlutterProject.fromDirectory(
fileSystem.currentDirectory,
);
final buildableIOSApp = BuildableIOSApp(
flutterProject.ios,
'flutter',
'My Super Awesome App',
);
fileSystem
.directory('build/ios/Release-iphoneos/My Super Awesome App.app')
.createSync(recursive: true);
fileSystem.systemTempDirectory
.childDirectory('Flutter.framework')
.childDirectory('Headers')
.childFile('FlutterPlugin.h')
.createSync(recursive: true);
processManager.addCommands([
FakeCommand(command: _xattrArgs(flutterProject)),
const FakeCommand(
command: <String>[
'xcrun',
'xcodebuild',
'-configuration',
'Release',
'clean',
'build',
'-quiet',
'-allowProvisioningUpdates',
'-allowProvisioningDeviceRegistration',
'-workspace',
'Runner.xcworkspace',
'-scheme',
'Runner',
'BUILD_DIR=/build/ios',
'-sdk',
'iphoneos',
'-destination',
'id=123',
'ONLY_ACTIVE_ARCH=NO',
'ARCHS=arm64',
'-resultBundlePath',
'/.tmp_rand0/flutter_ios_build_temp_dirrand0/temporary_xcresult_bundle',
'-resultBundleVersion',
'3',
'FLUTTER_SUPPRESS_ANALYTICS=true',
'COMPILER_INDEX_STORE_ENABLE=NO',
],
),
const FakeCommand(
command: <String>[
'rsync',
'-8',
'-av',
'--delete',
'build/ios/Release-iphoneos/My Super Awesome App.app',
'build/ios/iphoneos',
],
),
FakeCommand(
command: <String>[
iosDeployPath,
'--id',
'123',
'--bundle',
'build/ios/iphoneos/My Super Awesome App.app',
'--app_deltas',
'build/ios/app-delta',
'--no-wifi',
'--justlaunch',
'--args',
const <String>['--enable-dart-profiling'].join(' '),
],
),
]);
final LaunchResult launchResult = await iosDevice.startApp(
buildableIOSApp,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
platformArgs: <String, Object>{},
);
expect(fileSystem.directory('build/ios/iphoneos'), exists);
expect(launchResult.started, true);
expect(processManager, hasNoRemainingExpectations);
},
overrides: <Type, Generator>{
ProcessManager: () => processManager,
FileSystem: () => fileSystem,
Logger: () => logger,
OperatingSystemUtils: () =>
FakeOperatingSystemUtils(hostPlatform: HostPlatform.darwin_x64),
Pub: () => const ThrowingPub(),
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => fakeArtifacts,
},
);
testUsingContext(
'cleans before build when headers change when fresh build',
() async {
final IOSDevice iosDevice = setUpIOSDevice(
fileSystem: fileSystem,
processManager: processManager,
logger: logger,
artifacts: artifacts,
);
setUpIOSProject(fileSystem);
final FlutterProject flutterProject = FlutterProject.fromDirectory(
fileSystem.currentDirectory,
);
final buildableIOSApp = BuildableIOSApp(
flutterProject.ios,
'flutter',
'My Super Awesome App',
);
fileSystem.directory('build/ios/iphoneos').deleteSync(recursive: true);
fileSystem.systemTempDirectory
.childDirectory('Flutter.framework')
.childDirectory('Headers')
.childFile('FlutterPlugin.h')
.createSync(recursive: true);
processManager.addCommands([
FakeCommand(command: _xattrArgs(flutterProject)),
const FakeCommand(
command: <String>[
'xcrun',
'xcodebuild',
'-configuration',
'Release',
'-quiet',
'-allowProvisioningUpdates',
'-allowProvisioningDeviceRegistration',
'-workspace',
'Runner.xcworkspace',
'-scheme',
'Runner',
'BUILD_DIR=/build/ios',
'-sdk',
'iphoneos',
'-destination',
'id=123',
'ONLY_ACTIVE_ARCH=NO',
'ARCHS=arm64',
'-resultBundlePath',
'/.tmp_rand0/flutter_ios_build_temp_dirrand0/temporary_xcresult_bundle',
'-resultBundleVersion',
'3',
'FLUTTER_SUPPRESS_ANALYTICS=true',
'COMPILER_INDEX_STORE_ENABLE=NO',
],
),
]);
await iosDevice.startApp(
buildableIOSApp,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
platformArgs: <String, Object>{},
);
expect(processManager, hasNoRemainingExpectations);
},
overrides: <Type, Generator>{
ProcessManager: () => processManager,
FileSystem: () => fileSystem,
Logger: () => logger,
OperatingSystemUtils: () =>
FakeOperatingSystemUtils(hostPlatform: HostPlatform.darwin_x64),
Pub: () => const ThrowingPub(),
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => fakeArtifacts,
},
);
});
testUsingContext(
'with concurrent build failures',
() async {
@ -721,7 +510,6 @@ void main() {
Pub: () => const ThrowingPub(),
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
});
@ -804,7 +592,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
@ -861,7 +648,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
@ -908,7 +694,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
@ -967,7 +752,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
});
@ -1048,7 +832,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
@ -1060,10 +843,7 @@ void main() {
<String>['Runner', 'free'],
logger,
);
fakeXcodeProjectInterpreter = FakeXcodeProjectInterpreter(
projectInfo: projectInfo,
xcodeVersion: Version(15, 0, 0),
);
fakeXcodeProjectInterpreter = FakeXcodeProjectInterpreter(projectInfo: projectInfo);
xcode = Xcode.test(
processManager: FakeProcessManager.any(),
xcodeProjectInterpreter: fakeXcodeProjectInterpreter,
@ -1148,7 +928,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
});
@ -1245,7 +1024,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
@ -1300,7 +1078,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(),
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
@ -1356,7 +1133,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
@ -1420,7 +1196,6 @@ void main() {
Platform: () => macPlatform,
XcodeProjectInterpreter: () => fakeXcodeProjectInterpreter,
Xcode: () => xcode,
Artifacts: () => artifacts,
},
);
});
@ -1724,21 +1499,3 @@ class FakeExactAnalytics extends Fake implements Analytics {
sentEvents.add(event);
}
}
class FakeArtifacts extends Fake implements Artifacts {
FakeArtifacts({required this.frameworkPath});
final String frameworkPath;
@override
String getArtifactPath(
Artifact artifact, {
TargetPlatform? platform,
BuildMode? mode,
EnvironmentType? environmentType,
}) {
return frameworkPath;
}
@override
LocalEngineInfo? get localEngineInfo => null;
}

View File

@ -800,93 +800,6 @@ duplicate symbol '_$s29plugin_1_name23PluginNamePluginC9setDouble3key5valueySS_S
expect(processManager, hasNoRemainingExpectations);
});
});
group('publicHeadersChanged', () {
const correctHeaderFingerprint =
'{"files":{"/.tmp_rand0/Flutter.framework/Headers/FlutterPlugin.h":"d41d8cd98f00b204e9800998ecf8427e"}}';
testWithoutContext('returns true when headers change', () async {
final fs = MemoryFileSystem.test();
final logger = BufferLogger.test();
final Directory mockFlutterFramework = fs.systemTempDirectory.childDirectory(
'Flutter.framework',
);
mockFlutterFramework
.childDirectory('Headers')
.childFile('FlutterPlugin.h')
.createSync(recursive: true);
final Directory mockBuildDirectory = fs.systemTempDirectory.childDirectory('build')
..createSync(recursive: true);
final File fingerprintFile =
mockBuildDirectory.childFile('framework_public_headers.fingerprint')..writeAsStringSync(
'{"files":{"/.tmp_rand0/Flutter.framework/Headers/FlutterPlugin.h":"incorrect_hash"}}',
);
final bool headersChanged = publicHeadersChanged(
environmentType: EnvironmentType.physical,
mode: BuildMode.debug,
buildDirectory: mockBuildDirectory.path,
artifacts: FakeArtifacts(frameworkPath: mockFlutterFramework.path),
fileSystem: fs,
logger: logger,
);
expect(headersChanged, isTrue);
expect(fingerprintFile.readAsStringSync(), correctHeaderFingerprint);
});
testWithoutContext('returns true when fingerprint does not exist yet', () async {
final fs = MemoryFileSystem.test();
final logger = BufferLogger.test();
final Directory mockFlutterFramework = fs.systemTempDirectory.childDirectory(
'Flutter.framework',
);
mockFlutterFramework
.childDirectory('Headers')
.childFile('FlutterPlugin.h')
.createSync(recursive: true);
final Directory mockBuildDirectory = fs.systemTempDirectory.childDirectory('build')
..createSync(recursive: true);
final File fingerprintFile = mockBuildDirectory.childFile(
'framework_public_headers.fingerprint',
);
final bool headersChanged = publicHeadersChanged(
environmentType: EnvironmentType.physical,
mode: BuildMode.debug,
buildDirectory: mockBuildDirectory.path,
artifacts: FakeArtifacts(frameworkPath: mockFlutterFramework.path),
fileSystem: fs,
logger: logger,
);
expect(headersChanged, isTrue);
expect(fingerprintFile.readAsStringSync(), correctHeaderFingerprint);
});
testWithoutContext('returns false when fingerprint has not changed', () async {
final fs = MemoryFileSystem.test();
final logger = BufferLogger.test();
final Directory mockFlutterFramework = fs.systemTempDirectory.childDirectory(
'Flutter.framework',
);
mockFlutterFramework
.childDirectory('Headers')
.childFile('FlutterPlugin.h')
.createSync(recursive: true);
final Directory mockBuildDirectory = fs.systemTempDirectory.childDirectory('build')
..createSync(recursive: true);
final File fingerprintFile = mockBuildDirectory.childFile(
'framework_public_headers.fingerprint',
)..writeAsStringSync(correctHeaderFingerprint);
final bool headersChanged = publicHeadersChanged(
environmentType: EnvironmentType.physical,
mode: BuildMode.debug,
buildDirectory: mockBuildDirectory.path,
artifacts: FakeArtifacts(frameworkPath: mockFlutterFramework.path),
fileSystem: fs,
logger: logger,
);
expect(headersChanged, isFalse);
expect(fingerprintFile.readAsStringSync(), correctHeaderFingerprint);
});
});
}
void createFakePlugins(
@ -985,18 +898,3 @@ class FakeFlutterManifest extends Fake implements FlutterManifest {
@override
YamlMap toYaml() => YamlMap.wrap(<String, String>{});
}
class FakeArtifacts extends Fake implements Artifacts {
FakeArtifacts({required this.frameworkPath});
final String frameworkPath;
@override
String getArtifactPath(
Artifact artifact, {
TargetPlatform? platform,
BuildMode? mode,
EnvironmentType? environmentType,
}) {
return frameworkPath;
}
}