Skip to content

Commit d9adfe3

Browse files
authored
Allow FLUTTER_APPLICATION_PATH to be null for misconfigured Xcode projects (#57701)
1 parent 03d2250 commit d9adfe3

File tree

3 files changed

+83
-19
lines changed

3 files changed

+83
-19
lines changed

dev/devicelab/bin/tasks/ios_content_validation_test.dart

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,32 @@ Future<void> main() async {
2424
'--release',
2525
'--obfuscate',
2626
'--split-debug-info=foo/',
27+
'--no-codesign',
2728
]);
2829
});
29-
final String outputAppPath = path.join(
30+
final String buildPath = path.join(
3031
flutterProject.rootPath,
31-
'build/ios/iphoneos/Runner.app',
32+
'build',
33+
'ios',
34+
'iphoneos',
3235
);
33-
final String outputAppFramework = path.join(
34-
flutterProject.rootPath,
35-
outputAppPath,
36-
'Frameworks/App.framework/App',
36+
final String outputAppPath = path.join(
37+
buildPath,
38+
'Runner.app',
3739
);
38-
if (!File(outputAppFramework).existsSync()) {
39-
fail('Failed to produce expected output at $outputAppFramework');
40+
final Directory outputAppFramework = Directory(path.join(
41+
outputAppPath,
42+
'Frameworks',
43+
'App.framework',
44+
));
45+
46+
final File outputAppFrameworkBinary = File(path.join(
47+
outputAppFramework.path,
48+
'App',
49+
));
50+
51+
if (!outputAppFrameworkBinary.existsSync()) {
52+
fail('Failed to produce expected output at ${outputAppFrameworkBinary.path}');
4053
}
4154

4255
section('Validate obfuscation');
@@ -46,7 +59,7 @@ Future<void> main() async {
4659
await inDirectory(flutterProject.rootPath, () async {
4760
final String response = await eval(
4861
'grep',
49-
<String>[flutterProject.name, outputAppFramework],
62+
<String>[flutterProject.name, outputAppFrameworkBinary.path],
5063
canFail: true,
5164
);
5265
if (response.trim().contains('matches')) {
@@ -56,16 +69,63 @@ Future<void> main() async {
5669

5770
section('Validate bitcode');
5871

59-
final String outputFlutterFramework = path.join(
72+
final Directory outputFlutterFramework = Directory(path.join(
6073
flutterProject.rootPath,
6174
outputAppPath,
62-
'Frameworks/Flutter.framework/Flutter',
75+
'Frameworks',
76+
'Flutter.framework',
77+
));
78+
final File outputFlutterFrameworkBinary = File(path.join(
79+
outputFlutterFramework.path,
80+
'Flutter',
81+
));
82+
83+
if (!outputFlutterFrameworkBinary.existsSync()) {
84+
fail('Failed to produce expected output at ${outputFlutterFrameworkBinary.path}');
85+
}
86+
bitcode = await containsBitcode(outputFlutterFrameworkBinary.path);
87+
88+
section('Xcode backend script');
89+
90+
outputFlutterFramework.deleteSync(recursive: true);
91+
outputAppFramework.deleteSync(recursive: true);
92+
if (outputFlutterFramework.existsSync() || outputAppFramework.existsSync()) {
93+
fail('Failed to delete embedded frameworks');
94+
}
95+
96+
final String xcodeBackendPath = path.join(
97+
flutterDirectory.path,
98+
'packages',
99+
'flutter_tools',
100+
'bin',
101+
'xcode_backend.sh'
102+
);
103+
104+
// Simulate a commonly Xcode build setting misconfiguration
105+
// where FLUTTER_APPLICATION_PATH is missing
106+
final int result = await exec(
107+
xcodeBackendPath,
108+
<String>['embed_and_thin'],
109+
environment: <String, String>{
110+
'SOURCE_ROOT': flutterProject.iosPath,
111+
'TARGET_BUILD_DIR': buildPath,
112+
'FRAMEWORKS_FOLDER_PATH': 'Runner.app/Frameworks',
113+
'VERBOSE_SCRIPT_LOGGING': '1',
114+
'ACTION': 'install', // Skip bitcode stripping since we just checked that above.
115+
},
63116
);
64117

65-
if (!File(outputFlutterFramework).existsSync()) {
66-
fail('Failed to produce expected output at $outputFlutterFramework');
118+
if (result != 0) {
119+
fail('xcode_backend embed_and_thin failed');
120+
}
121+
122+
if (!outputFlutterFrameworkBinary.existsSync()) {
123+
fail('Failed to re-embed ${outputFlutterFrameworkBinary.path}');
124+
}
125+
126+
if (!outputAppFrameworkBinary.existsSync()) {
127+
fail('Failed to re-embed ${outputAppFrameworkBinary.path}');
67128
}
68-
bitcode = await containsBitcode(outputFlutterFramework);
69129
});
70130

71131
if (foundProjectName) {

dev/devicelab/lib/framework/apk_utils.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ class FlutterProject {
226226

227227
String get rootPath => path.join(parent.path, name);
228228
String get androidPath => path.join(rootPath, 'android');
229+
String get iosPath => path.join(rootPath, 'ios');
229230

230231
Future<void> addCustomBuildType(String name, {String initWith}) async {
231232
final File buildScript = File(

packages/flutter_tools/bin/xcode_backend.sh

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,18 @@ ThinAppFrameworks() {
264264
# Adds the App.framework as an embedded binary and the flutter_assets as
265265
# resources.
266266
EmbedFlutterFrameworks() {
267-
AssertExists "${FLUTTER_APPLICATION_PATH}"
267+
local project_path="${SOURCE_ROOT}/.."
268+
if [[ -n "$FLUTTER_APPLICATION_PATH" ]]; then
269+
project_path="${FLUTTER_APPLICATION_PATH}"
270+
fi
268271

269272
# Prefer the hidden .ios folder, but fallback to a visible ios folder if .ios
270273
# doesn't exist.
271-
local flutter_ios_out_folder="${FLUTTER_APPLICATION_PATH}/.ios/Flutter"
272-
local flutter_ios_engine_folder="${FLUTTER_APPLICATION_PATH}/.ios/Flutter/engine"
274+
local flutter_ios_out_folder="${project_path}/.ios/Flutter"
275+
local flutter_ios_engine_folder="${project_path}/.ios/Flutter/engine"
273276
if [[ ! -d ${flutter_ios_out_folder} ]]; then
274-
flutter_ios_out_folder="${FLUTTER_APPLICATION_PATH}/ios/Flutter"
275-
flutter_ios_engine_folder="${FLUTTER_APPLICATION_PATH}/ios/Flutter"
277+
flutter_ios_out_folder="${project_path}/ios/Flutter"
278+
flutter_ios_engine_folder="${project_path}/ios/Flutter"
276279
fi
277280

278281
AssertExists "${flutter_ios_out_folder}"

0 commit comments

Comments
 (0)