Unverified Commit eee0dc84 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Exclude arm64 from valid iOS simulators (#73828)

parent effa7d52
......@@ -447,6 +447,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
......
......@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
......@@ -56,7 +56,6 @@
5EF266650049BC10ECFD8C86 /* Pods-Host.debug.xcconfig */,
A412A4193ADC80C963762A82 /* Pods-Host.release.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
......@@ -200,7 +199,7 @@
name = "[CP-User] Run Flutter Build hello Script";
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "set -e\nset -u\nsource \"${SRCROOT}/../hello/.ios/Flutter/flutter_export_environment.sh\"\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build";
shellScript = "set -e\nset -u\nsource \"${SRCROOT}/../hello/.ios/Flutter/flutter_export_environment.sh\"\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build\n";
};
96286B727046BA8457A788D0 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
......@@ -391,6 +390,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
INFOPLIST_FILE = Host/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
......
......@@ -68,6 +68,9 @@ def flutter_additional_ios_build_settings(target)
# When deleted, the deployment version will inherit from the higher version derived from the 'Runner' target.
# If the pod only supports a higher version, do not delete to correctly produce an error.
build_configuration.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' if inherit_deployment_target
# Apple Silicon ARM simulators not yet supported.
build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64 i386'
end
end
......
......@@ -255,7 +255,7 @@ Future<XcodeBuildResult> buildXcodeProject({
if (buildForDevice) {
buildCommands.addAll(<String>['-sdk', 'iphoneos']);
} else {
buildCommands.addAll(<String>['-sdk', 'iphonesimulator', '-arch', 'x86_64']);
buildCommands.addAll(<String>['-sdk', 'iphonesimulator']);
}
}
......
......@@ -111,7 +111,9 @@ void _updateGeneratedEnvironmentVariablesScript({
localsBuffer.writeln('#!/bin/sh');
localsBuffer.writeln('# This is a generated file; do not edit or check into version control.');
for (final String line in xcodeBuildSettings) {
localsBuffer.writeln('export "$line"');
if (!line.contains('[')) { // Exported conditional Xcode build settings do not work.
localsBuffer.writeln('export "$line"');
}
}
final File generatedModuleBuildPhaseScript = useMacOSConfig
......@@ -226,6 +228,9 @@ List<String> _xcodeBuildSettingsLines({
if (useMacOSConfig) {
// ARM not yet supported https://github.com/flutter/flutter/issues/69221
xcodeBuildSettings.add('EXCLUDED_ARCHS=arm64');
} else {
// Apple Silicon ARM simulators not yet supported.
xcodeBuildSettings.add('EXCLUDED_ARCHS[sdk=iphonesimulator*]=arm64 i386');
}
for (final MapEntry<String, String> config in buildInfo.toEnvironmentConfig().entries) {
......
......@@ -671,12 +671,14 @@ Information about project "Runner":
final String contents = config.readAsStringSync();
expect(contents.contains('ARCHS=armv7'), isTrue);
expect(contents.contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=arm64 i386'), isTrue);
final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh');
expect(buildPhaseScript.existsSync(), isTrue);
final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync();
expect(buildPhaseScriptContents.contains('ARCHS=armv7'), isTrue);
expect(buildPhaseScriptContents.contains('EXCLUDED_ARCHS'), isFalse);
});
testUsingOsxContext('sets TRACK_WIDGET_CREATION=true when trackWidgetCreation is true', () async {
......
......@@ -43,10 +43,7 @@ void main() {
// Config is updated if command succeeded.
expect(generatedConfig, exists);
expect(generatedConfig.readAsStringSync(), allOf(
contains('DART_OBFUSCATION=true'),
isNot(contains('EXCLUDED_ARCHS')),
));
expect(generatedConfig.readAsStringSync(), contains('DART_OBFUSCATION=true'));
// file that only exists if app was fully built.
final File frameworkPlist = fileSystem.file(
......
......@@ -14,200 +14,258 @@ import '../src/darwin_common.dart';
import 'test_utils.dart';
void main() {
for (final BuildMode buildMode in <BuildMode>[BuildMode.debug, BuildMode.release]) {
group(buildMode.name, () {
String flutterRoot;
String projectRoot;
String flutterBin;
Directory tempDir;
Directory buildPath;
Directory outputApp;
Directory frameworkDirectory;
Directory outputFlutterFramework;
File outputFlutterFrameworkBinary;
Directory outputAppFramework;
File outputAppFrameworkBinary;
setUpAll(() {
flutterRoot = getFlutterRoot();
tempDir = createResolvedTempDirectorySync('ios_content_validation.');
flutterBin = fileSystem.path.join(
flutterRoot,
'bin',
'flutter',
);
processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),
'create',
'--platforms=ios',
'-i',
'objc',
'hello',
], workingDirectory: tempDir.path);
group('iOS app validation', () {
String flutterRoot;
String projectRoot;
String flutterBin;
Directory tempDir;
projectRoot = tempDir.childDirectory('hello').path;
setUpAll(() {
flutterRoot = getFlutterRoot();
tempDir = createResolvedTempDirectorySync('ios_content_validation.');
flutterBin = fileSystem.path.join(
flutterRoot,
'bin',
'flutter',
);
processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),
'build',
'ios',
'--verbose',
'--no-codesign',
'--${buildMode.name}',
'--obfuscate',
'--split-debug-info=foo/',
], workingDirectory: projectRoot);
processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),
'create',
'--platforms=ios',
'-i',
'objc',
'hello',
], workingDirectory: tempDir.path);
buildPath = fileSystem.directory(fileSystem.path.join(
projectRoot,
'build',
'ios',
'iphoneos',
));
projectRoot = tempDir.childDirectory('hello').path;
});
outputApp = buildPath.childDirectory('Runner.app');
tearDownAll(() {
tryToDelete(tempDir);
});
frameworkDirectory = outputApp.childDirectory('Frameworks');
outputFlutterFramework = frameworkDirectory.childDirectory('Flutter.framework');
outputFlutterFrameworkBinary = outputFlutterFramework.childFile('Flutter');
for (final BuildMode buildMode in <BuildMode>[BuildMode.debug, BuildMode.release]) {
group('build in ${buildMode.name} mode', () {
Directory buildPath;
Directory outputApp;
Directory frameworkDirectory;
Directory outputFlutterFramework;
File outputFlutterFrameworkBinary;
Directory outputAppFramework;
File outputAppFrameworkBinary;
outputAppFramework = frameworkDirectory.childDirectory('App.framework');
outputAppFrameworkBinary = outputAppFramework.childFile('App');
});
setUpAll(() {
flutterRoot = getFlutterRoot();
tempDir = createResolvedTempDirectorySync('ios_content_validation.');
flutterBin = fileSystem.path.join(
flutterRoot,
'bin',
'flutter',
);
tearDownAll(() {
tryToDelete(tempDir);
});
processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),
'create',
'--platforms=ios',
'-i',
'objc',
'hello',
], workingDirectory: tempDir.path);
testWithoutContext('flutter build ios builds a valid app', () {
// Should only contain Flutter.framework and App.framework.
expect(frameworkDirectory.listSync().length, 2);
expect(outputAppFramework.childFile('App'), exists);
projectRoot = tempDir.childDirectory('hello').path;
final File vmSnapshot = fileSystem.file(fileSystem.path.join(
outputAppFramework.path,
'flutter_assets',
'vm_snapshot_data',
));
processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),
'build',
'ios',
'--verbose',
'--no-codesign',
'--${buildMode.name}',
'--obfuscate',
'--split-debug-info=foo/',
], workingDirectory: projectRoot);
expect(vmSnapshot.existsSync(), buildMode == BuildMode.debug);
buildPath = fileSystem.directory(fileSystem.path.join(
projectRoot,
'build',
'ios',
'iphoneos',
));
expect(outputFlutterFramework.childDirectory('Headers'), isNot(exists));
expect(outputFlutterFramework.childDirectory('Modules'), isNot(exists));
outputApp = buildPath.childDirectory('Runner.app');
// Archiving should contain a bitcode blob, but not building.
// This mimics Xcode behavior and prevents a developer from having to install a
// 300+MB app.
expect(containsBitcode(outputFlutterFrameworkBinary.path, processManager), isFalse);
});
frameworkDirectory = outputApp.childDirectory('Frameworks');
outputFlutterFramework = frameworkDirectory.childDirectory('Flutter.framework');
outputFlutterFrameworkBinary = outputFlutterFramework.childFile('Flutter');
testWithoutContext('Info.plist dart observatory Bonjour service', () {
final String infoPlistPath = fileSystem.path.join(
outputApp.path,
'Info.plist',
);
final ProcessResult bonjourServices = processManager.runSync(
<String>[
'plutil',
'-extract',
'NSBonjourServices',
'xml1',
'-o',
'-',
infoPlistPath,
],
);
final bool bonjourServicesFound = (bonjourServices.stdout as String).contains('_dartobservatory._tcp');
expect(bonjourServicesFound, buildMode == BuildMode.debug);
final ProcessResult localNetworkUsage = processManager.runSync(
<String>[
'plutil',
'-extract',
'NSLocalNetworkUsageDescription',
'xml1',
'-o',
'-',
infoPlistPath,
],
);
final bool localNetworkUsageFound = localNetworkUsage.exitCode == 0;
expect(localNetworkUsageFound, buildMode == BuildMode.debug);
});
outputAppFramework = frameworkDirectory.childDirectory('App.framework');
outputAppFrameworkBinary = outputAppFramework.childFile('App');
});
testWithoutContext('flutter build ios builds a valid app', () {
// Should only contain Flutter.framework and App.framework.
expect(frameworkDirectory.listSync().length, 2);
expect(outputAppFramework.childFile('App'), exists);
final File vmSnapshot = fileSystem.file(fileSystem.path.join(
outputAppFramework.path,
'flutter_assets',
'vm_snapshot_data',
));
expect(vmSnapshot.existsSync(), buildMode == BuildMode.debug);
testWithoutContext('check symbols', () {
final ProcessResult symbols = processManager.runSync(
<String>[
'nm',
'-g',
expect(outputFlutterFramework.childDirectory('Headers'), isNot(exists));
expect(outputFlutterFramework.childDirectory('Modules'), isNot(exists));
// Archiving should contain a bitcode blob, but not building.
// This mimics Xcode behavior and prevents a developer from having to install a
// 300+MB app.
expect(containsBitcode(outputFlutterFrameworkBinary.path, processManager), isFalse);
});
testWithoutContext('Info.plist dart observatory Bonjour service', () {
final String infoPlistPath = fileSystem.path.join(
outputApp.path,
'Info.plist',
);
final ProcessResult bonjourServices = processManager.runSync(
<String>[
'plutil',
'-extract',
'NSBonjourServices',
'xml1',
'-o',
'-',
infoPlistPath,
],
);
final bool bonjourServicesFound = (bonjourServices.stdout as String).contains('_dartobservatory._tcp');
expect(bonjourServicesFound, buildMode == BuildMode.debug);
final ProcessResult localNetworkUsage = processManager.runSync(
<String>[
'plutil',
'-extract',
'NSLocalNetworkUsageDescription',
'xml1',
'-o',
'-',
infoPlistPath,
],
);
final bool localNetworkUsageFound = localNetworkUsage.exitCode == 0;
expect(localNetworkUsageFound, buildMode == BuildMode.debug);
});
testWithoutContext('check symbols', () {
final ProcessResult symbols = processManager.runSync(
<String>[
'nm',
'-g',
outputAppFrameworkBinary.path,
'-arch',
'arm64',
],
);
final bool aotSymbolsFound = (symbols.stdout as String).contains('_kDartVmSnapshot');
expect(aotSymbolsFound, buildMode != BuildMode.debug);
});
testWithoutContext('xcode_backend embed_and_thin', () {
outputFlutterFramework.deleteSync(recursive: true);
outputAppFramework.deleteSync(recursive: true);
expect(outputFlutterFrameworkBinary.existsSync(), isFalse);
expect(outputAppFrameworkBinary.existsSync(), isFalse);
final String xcodeBackendPath = fileSystem.path.join(
flutterRoot,
'packages',
'flutter_tools',
'bin',
'xcode_backend.sh',
);
// Simulate a common Xcode build setting misconfiguration
// where FLUTTER_APPLICATION_PATH is missing
final ProcessResult xcodeBackendResult = processManager.runSync(
<String>[
xcodeBackendPath,
'embed_and_thin',
],
environment: <String, String>{
'SOURCE_ROOT': fileSystem.path.join(projectRoot, 'ios'),
'BUILT_PRODUCTS_DIR': fileSystem.path.join(
projectRoot,
'build',
'ios',
'Release-iphoneos',
),
'TARGET_BUILD_DIR': buildPath.path,
'FRAMEWORKS_FOLDER_PATH': 'Runner.app/Frameworks',
'VERBOSE_SCRIPT_LOGGING': '1',
'FLUTTER_BUILD_MODE': 'release',
'ACTION': 'install',
// Skip bitcode stripping since we just checked that above.
},
);
expect(xcodeBackendResult.exitCode, 0);
expect(outputFlutterFrameworkBinary.existsSync(), isTrue);
expect(outputAppFrameworkBinary.existsSync(), isTrue);
}, skip: !platform.isMacOS || buildMode != BuildMode.release);
testWithoutContext('validate obfuscation', () {
final ProcessResult grepResult = processManager.runSync(<String>[
'grep',
'-i',
'hello',
outputAppFrameworkBinary.path,
'-arch',
'arm64',
],
);
final bool aotSymbolsFound = (symbols.stdout as String).contains('_kDartVmSnapshot');
expect(aotSymbolsFound, buildMode != BuildMode.debug);
]);
expect(grepResult.stdout, isNot(contains('matches')));
});
});
}
testWithoutContext('xcode_backend embed_and_thin', () {
outputFlutterFramework.deleteSync(recursive: true);
outputAppFramework.deleteSync(recursive: true);
expect(outputFlutterFrameworkBinary.existsSync(), isFalse);
expect(outputAppFrameworkBinary.existsSync(), isFalse);
final String xcodeBackendPath = fileSystem.path.join(
flutterRoot,
'packages',
'flutter_tools',
'bin',
'xcode_backend.sh',
);
// Simulate a common Xcode build setting misconfiguration
// where FLUTTER_APPLICATION_PATH is missing
final ProcessResult xcodeBackendResult = processManager.runSync(
<String>[
xcodeBackendPath,
'embed_and_thin',
],
environment: <String, String>{
'SOURCE_ROOT': fileSystem.path.join(projectRoot, 'ios'),
'BUILT_PRODUCTS_DIR': fileSystem.path.join(
projectRoot,
'build',
'ios',
'Release-iphoneos',
),
'TARGET_BUILD_DIR': buildPath.path,
'FRAMEWORKS_FOLDER_PATH': 'Runner.app/Frameworks',
'VERBOSE_SCRIPT_LOGGING': '1',
'FLUTTER_BUILD_MODE': 'release',
'ACTION': 'install',
// Skip bitcode stripping since we just checked that above.
},
);
expect(xcodeBackendResult.exitCode, 0);
expect(outputFlutterFrameworkBinary.existsSync(), isTrue);
expect(outputAppFrameworkBinary.existsSync(), isTrue);
}, skip: !platform.isMacOS || buildMode != BuildMode.release);
testWithoutContext('validate obfuscation', () {
final ProcessResult grepResult = processManager.runSync(<String>[
'grep',
'-i',
'hello',
outputAppFrameworkBinary.path,
]);
expect(grepResult.stdout, isNot(contains('matches')));
});
},
skip: !platform.isMacOS,
timeout: const Timeout(Duration(minutes: 5)),
);
}
testWithoutContext('build for simulator with all available architectures', () {
final ProcessResult buildSimulator = processManager.runSync(
<String>[
flutterBin,
...getLocalEngineArguments(),
'build',
'ios',
'--simulator',
'--verbose',
'--no-codesign',
],
workingDirectory: projectRoot,
environment: <String, String>{
'FLUTTER_XCODE_ONLY_ACTIVE_ARCH': 'NO',
},
);
// This test case would fail if arm64 or i386 were not excluded.
expect(buildSimulator.exitCode, 0);
final File simulatorAppFrameworkBinary = fileSystem.file(fileSystem.path.join(
projectRoot,
'build',
'ios',
'iphonesimulator',
'Runner.app',
'Frameworks',
'App.framework',
'App',
));
expect(simulatorAppFrameworkBinary, exists);
final ProcessResult archs = processManager.runSync(
<String>['file', simulatorAppFrameworkBinary.path],
);
expect(archs.stdout, contains('Mach-O 64-bit dynamically linked shared library x86_64'));
});
}, skip: !platform.isMacOS, timeout: const Timeout(Duration(minutes: 5))
);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment