mirror of
https://github.com/flutter/flutter
synced 2024-10-13 03:32:55 +00:00
This reverts commit 202c1b4224
.
This commit is contained in:
parent
c1cb68004a
commit
393106fbf5
|
@ -317,6 +317,7 @@
|
|||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
|
@ -443,6 +444,7 @@
|
|||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
|
@ -463,6 +465,7 @@
|
|||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
|
|
|
@ -114,6 +114,7 @@ BuildApp() {
|
|||
flutter_engine_flag="--local-engine-src-path=${FLUTTER_ENGINE}"
|
||||
fi
|
||||
|
||||
local bitcode_flag=""
|
||||
if [[ -n "$LOCAL_ENGINE" ]]; then
|
||||
if [[ $(echo "$LOCAL_ENGINE" | tr "[:upper:]" "[:lower:]") != *"$build_mode"* ]]; then
|
||||
EchoError "========================================================================"
|
||||
|
@ -130,12 +131,9 @@ BuildApp() {
|
|||
local_engine_flag="--local-engine=${LOCAL_ENGINE}"
|
||||
flutter_framework="${FLUTTER_ENGINE}/out/${LOCAL_ENGINE}/Flutter.framework"
|
||||
flutter_podspec="${FLUTTER_ENGINE}/out/${LOCAL_ENGINE}/Flutter.podspec"
|
||||
fi
|
||||
|
||||
local bitcode_flag=""
|
||||
if [[ $ENABLE_BITCODE == "YES" ]]; then
|
||||
bitcode_flag="--bitcode"
|
||||
echo "Set Bitcode!"
|
||||
if [[ $ENABLE_BITCODE == "YES" ]]; then
|
||||
bitcode_flag="--bitcode"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -e "${project_path}/.ios" ]]; then
|
||||
|
|
|
@ -179,14 +179,13 @@ class AOTSnapshotter {
|
|||
// The DWARF section confuses Xcode tooling, so this strips it. Ideally,
|
||||
// gen_snapshot would provide an argument to do this automatically.
|
||||
if (platform == TargetPlatform.ios && bitcode) {
|
||||
final IOSink sink = fs.file('$assembly.stripped.S').openWrite();
|
||||
final IOSink sink = fs.file('$assembly.bitcode').openWrite();
|
||||
for (String line in fs.file(assembly).readAsLinesSync()) {
|
||||
if (line.startsWith('.section __DWARF')) {
|
||||
break;
|
||||
}
|
||||
sink.writeln(line);
|
||||
}
|
||||
await sink.flush();
|
||||
await sink.close();
|
||||
}
|
||||
|
||||
|
@ -200,8 +199,7 @@ class AOTSnapshotter {
|
|||
if (platform == TargetPlatform.ios || platform == TargetPlatform.darwin_x64) {
|
||||
final RunResult result = await _buildFramework(
|
||||
appleArch: darwinArch,
|
||||
isIOS: platform == TargetPlatform.ios,
|
||||
assemblyPath: bitcode ? '$assembly.stripped.S' : assembly,
|
||||
assemblyPath: bitcode ? '$assembly.bitcode' : assembly,
|
||||
outputPath: outputDir.path,
|
||||
bitcode: bitcode,
|
||||
);
|
||||
|
@ -215,29 +213,26 @@ class AOTSnapshotter {
|
|||
/// source at [assemblyPath].
|
||||
Future<RunResult> _buildFramework({
|
||||
@required DarwinArch appleArch,
|
||||
@required bool isIOS,
|
||||
@required String assemblyPath,
|
||||
@required String outputPath,
|
||||
@required bool bitcode,
|
||||
}) async {
|
||||
final String targetArch = getNameForDarwinArch(appleArch);
|
||||
printStatus('Building App.framework for $targetArch...');
|
||||
|
||||
final List<String> commonBuildOptions = <String>[
|
||||
'-arch', targetArch,
|
||||
if (isIOS)
|
||||
if (appleArch == DarwinArch.arm64 || appleArch == DarwinArch.armv7)
|
||||
'-miphoneos-version-min=8.0',
|
||||
];
|
||||
|
||||
const String embedBitcodeArg = '-fembed-bitcode';
|
||||
final String assemblyO = fs.path.join(outputPath, 'snapshot_assembly.o');
|
||||
final RunResult compileResult = await xcode.cc(<String>[
|
||||
'-arch', targetArch,
|
||||
if (bitcode) embedBitcodeArg,
|
||||
...commonBuildOptions,
|
||||
'-c',
|
||||
assemblyPath,
|
||||
'-o',
|
||||
assemblyO,
|
||||
if (bitcode) '-fembed-bitcode',
|
||||
]);
|
||||
if (compileResult.exitCode != 0) {
|
||||
printError('Failed to compile AOT snapshot. Compiler terminated with exit code ${compileResult.exitCode}');
|
||||
|
@ -253,16 +248,26 @@ class AOTSnapshotter {
|
|||
'-Xlinker', '-rpath', '-Xlinker', '@executable_path/Frameworks',
|
||||
'-Xlinker', '-rpath', '-Xlinker', '@loader_path/Frameworks',
|
||||
'-install_name', '@rpath/App.framework/App',
|
||||
if (bitcode) embedBitcodeArg,
|
||||
if (bitcode && isIOS) ...<String>[embedBitcodeArg, '-isysroot', await xcode.iPhoneSdkLocation()],
|
||||
if (bitcode) '-fembed-bitcode',
|
||||
'-o', appLib,
|
||||
assemblyO,
|
||||
];
|
||||
final RunResult linkResult = await xcode.clang(linkArgs);
|
||||
if (linkResult.exitCode != 0) {
|
||||
printError('Failed to link AOT snapshot. Linker terminated with exit code ${compileResult.exitCode}');
|
||||
return linkResult;
|
||||
}
|
||||
return linkResult;
|
||||
// See https://github.com/flutter/flutter/issues/22560
|
||||
// These have to be placed in a .noindex folder to prevent Xcode from
|
||||
// using Spotlight to find them and potentially attach the wrong ones.
|
||||
final RunResult dsymResult = await xcode.dsymutil(<String>[
|
||||
appLib,
|
||||
'-o', fs.path.join(outputPath, 'App.framework.dSYM.noindex'),
|
||||
]);
|
||||
if (dsymResult.exitCode != 0) {
|
||||
printError('Failed to extract dSYM out of dynamic lib');
|
||||
}
|
||||
return dsymResult;
|
||||
}
|
||||
|
||||
/// Compiles a Dart file to kernel.
|
||||
|
|
|
@ -83,7 +83,7 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
|
|||
if (platform != TargetPlatform.ios) {
|
||||
throwToolExit('Bitcode is only supported on iOS (TargetPlatform is $targetPlatform).');
|
||||
}
|
||||
await validateBitcode(buildMode, platform);
|
||||
await validateBitcode();
|
||||
}
|
||||
|
||||
Status status;
|
||||
|
@ -150,6 +150,14 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
|
|||
'-create',
|
||||
'-output', fs.path.join(outputPath, 'App.framework', 'App'),
|
||||
]);
|
||||
final Iterable<String> dSYMs = iosBuilds.values.map<String>((String outputDir) => fs.path.join(outputDir, 'App.framework.dSYM.noindex'));
|
||||
fs.directory(fs.path.join(outputPath, 'App.framework.dSYM.noindex', 'Contents', 'Resources', 'DWARF'))..createSync(recursive: true);
|
||||
await runCheckedAsync(<String>[
|
||||
'lipo',
|
||||
'-create',
|
||||
'-output', fs.path.join(outputPath, 'App.framework.dSYM.noindex', 'Contents', 'Resources', 'DWARF', 'App'),
|
||||
...dSYMs.map((String path) => fs.path.join(path, 'Contents', 'Resources', 'DWARF', 'App'))
|
||||
]);
|
||||
} else {
|
||||
status?.cancel();
|
||||
exitCodes.forEach((DarwinArch iosArch, Future<int> exitCodeFuture) async {
|
||||
|
@ -194,18 +202,24 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> validateBitcode(BuildMode buildMode, TargetPlatform targetPlatform) async {
|
||||
Future<void> validateBitcode() async {
|
||||
final Artifacts artifacts = Artifacts.instance;
|
||||
final String flutterFrameworkPath = artifacts.getArtifactPath(
|
||||
Artifact.flutterFramework,
|
||||
mode: buildMode,
|
||||
platform: targetPlatform,
|
||||
);
|
||||
if (artifacts is! LocalEngineArtifacts) {
|
||||
throwToolExit('Bitcode is only supported with a local engine built with --bitcode.');
|
||||
}
|
||||
final String flutterFrameworkPath = artifacts.getArtifactPath(Artifact.flutterFramework);
|
||||
if (!fs.isDirectorySync(flutterFrameworkPath)) {
|
||||
throwToolExit('Flutter.framework not found at $flutterFrameworkPath');
|
||||
}
|
||||
final Xcode xcode = context.get<Xcode>();
|
||||
|
||||
// Check for bitcode in Flutter binary.
|
||||
final RunResult otoolResult = await xcode.otool(<String>[
|
||||
'-l', fs.path.join(flutterFrameworkPath, 'Flutter'),
|
||||
]);
|
||||
if (!otoolResult.stdout.contains('__LLVM')) {
|
||||
throwToolExit('The Flutter.framework at $flutterFrameworkPath does not contain bitcode.');
|
||||
}
|
||||
final RunResult clangResult = await xcode.clang(<String>['--version']);
|
||||
final String clangVersion = clangResult.stdout.split('\n').first;
|
||||
final String engineClangVersion = PlistParser.instance.getValueFromFile(
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import '../base/common.dart';
|
||||
import '../base/context.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
|
@ -101,14 +100,16 @@ class Xcode {
|
|||
return runCheckedAsync(<String>['xcrun', 'clang', ...args]);
|
||||
}
|
||||
|
||||
Future<String> iPhoneSdkLocation() async {
|
||||
final RunResult runResult = await runCheckedAsync(
|
||||
<String>['xcrun', '--sdk', 'iphoneos', '--show-sdk-path'],
|
||||
);
|
||||
if (runResult.exitCode != 0) {
|
||||
throwToolExit('Could not find iPhone SDK location: ${runResult.stderr}');
|
||||
}
|
||||
return runResult.stdout.trim();
|
||||
Future<RunResult> dsymutil(List<String> args) {
|
||||
return runCheckedAsync(<String>['xcrun', 'dsymutil', ...args]);
|
||||
}
|
||||
|
||||
Future<RunResult> strip(List<String> args) {
|
||||
return runCheckedAsync(<String>['xcrun', 'strip', ...args]);
|
||||
}
|
||||
|
||||
Future<RunResult> otool(List<String> args) {
|
||||
return runCheckedAsync(<String>['xcrun', 'otool', ...args]);
|
||||
}
|
||||
|
||||
String getSimulatorPath() {
|
||||
|
|
|
@ -116,6 +116,13 @@ void main() {
|
|||
when(mockArtifacts.getArtifactPath(Artifact.snapshotDart,
|
||||
platform: anyNamed('platform'), mode: mode)).thenReturn(kSnapshotDart);
|
||||
}
|
||||
|
||||
when(mockXcode.dsymutil(any)).thenAnswer((_) => Future<RunResult>.value(
|
||||
RunResult(
|
||||
ProcessResult(1, 0, '', ''),
|
||||
<String>['command name', 'arguments...']),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
final Map<Type, Generator> contextOverrides = <Type, Generator>{
|
||||
|
@ -203,9 +210,14 @@ void main() {
|
|||
|
||||
verify(xcode.cc(argThat(contains('-fembed-bitcode')))).called(1);
|
||||
verify(xcode.clang(argThat(contains('-fembed-bitcode')))).called(1);
|
||||
verify(xcode.dsymutil(<String>[
|
||||
'build/foo/App.framework/App',
|
||||
'-o',
|
||||
'build/foo/App.framework.dSYM.noindex',
|
||||
])).called(1);
|
||||
|
||||
final File assemblyFile = fs.file(assembly);
|
||||
final File assemblyBitcodeFile = fs.file('$assembly.stripped.S');
|
||||
final File assemblyBitcodeFile = fs.file('$assembly.bitcode');
|
||||
expect(assemblyFile.existsSync(), true);
|
||||
expect(assemblyBitcodeFile.existsSync(), true);
|
||||
expect(assemblyFile.readAsStringSync().contains('.section __DWARF'), true);
|
||||
|
@ -251,6 +263,7 @@ void main() {
|
|||
]);
|
||||
verifyNever(xcode.cc(argThat(contains('-fembed-bitcode'))));
|
||||
verifyNever(xcode.clang(argThat(contains('-fembed-bitcode'))));
|
||||
verify(xcode.dsymutil(any)).called(1);
|
||||
|
||||
final File assemblyFile = fs.file(assembly);
|
||||
final File assemblyBitcodeFile = fs.file('$assembly.bitcode');
|
||||
|
|
|
@ -248,12 +248,14 @@ flutter_tools:lib/''');
|
|||
|
||||
when(mockXcode.cc(any)).thenAnswer((_) => Future<RunResult>.value(fakeRunResult));
|
||||
when(mockXcode.clang(any)).thenAnswer((_) => Future<RunResult>.value(fakeRunResult));
|
||||
when(mockXcode.dsymutil(any)).thenAnswer((_) => Future<RunResult>.value(fakeRunResult));
|
||||
|
||||
final BuildResult result = await buildSystem.build(const AotAssemblyProfile(), iosEnvironment);
|
||||
|
||||
expect(result.success, true);
|
||||
verify(mockXcode.cc(argThat(contains('-fembed-bitcode')))).called(1);
|
||||
verify(mockXcode.clang(argThat(contains('-fembed-bitcode')))).called(1);
|
||||
verify(mockXcode.dsymutil(any)).called(1);
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Xcode: () => mockXcode,
|
||||
|
@ -276,12 +278,14 @@ flutter_tools:lib/''');
|
|||
|
||||
when(mockXcode.cc(any)).thenAnswer((_) => Future<RunResult>.value(fakeRunResult));
|
||||
when(mockXcode.clang(any)).thenAnswer((_) => Future<RunResult>.value(fakeRunResult));
|
||||
when(mockXcode.dsymutil(any)).thenAnswer((_) => Future<RunResult>.value(fakeRunResult));
|
||||
|
||||
final BuildResult result = await buildSystem.build(const AotAssemblyProfile(), iosEnvironment);
|
||||
|
||||
expect(result.success, true);
|
||||
verify(mockXcode.cc(argThat(contains('-fembed-bitcode')))).called(2);
|
||||
verify(mockXcode.clang(argThat(contains('-fembed-bitcode')))).called(2);
|
||||
verify(mockXcode.dsymutil(any)).called(2);
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Xcode: () => mockXcode,
|
||||
|
|
|
@ -179,6 +179,9 @@ void main() {
|
|||
when(xcode.clang(any)).thenAnswer((Invocation invocation) {
|
||||
return Future<RunResult>.value(RunResult(FakeProcessResult()..exitCode = 0, <String>['test']));
|
||||
});
|
||||
when(xcode.dsymutil(any)).thenAnswer((Invocation invocation) {
|
||||
return Future<RunResult>.value(RunResult(FakeProcessResult()..exitCode = 0, <String>['test']));
|
||||
});
|
||||
environment.buildDir.childFile('app.dill').createSync(recursive: true);
|
||||
fs.file('.packages')
|
||||
..createSync()
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:file/memory.dart';
|
|||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/process.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/commands/build_aot.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/ios/plist_parser.dart';
|
||||
|
@ -33,9 +32,16 @@ void main() {
|
|||
mockPlistUtils = MockPlistUtils();
|
||||
});
|
||||
|
||||
testUsingContext('build aot validates building with bitcode requires a local engine', () async {
|
||||
await expectToolExitLater(
|
||||
validateBitcode(),
|
||||
equals('Bitcode is only supported with a local engine built with --bitcode.'),
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('build aot validates existence of Flutter.framework in engine', () async {
|
||||
await expectToolExitLater(
|
||||
validateBitcode(BuildMode.release, TargetPlatform.ios),
|
||||
validateBitcode(),
|
||||
equals('Flutter.framework not found at ios_profile/Flutter.framework'),
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
|
@ -43,21 +49,48 @@ void main() {
|
|||
FileSystem: () => memoryFileSystem,
|
||||
});
|
||||
|
||||
testUsingContext('build aot validates Flutter.framework/Flutter contains bitcode', () async {
|
||||
final Directory flutterFramework = memoryFileSystem.directory('ios_profile/Flutter.framework')
|
||||
..createSync(recursive: true);
|
||||
flutterFramework.childFile('Flutter').createSync();
|
||||
flutterFramework.childFile('Info.plist').createSync();
|
||||
|
||||
final RunResult otoolResult = RunResult(
|
||||
FakeProcessResult(stdout: '', stderr: ''),
|
||||
const <String>['foo'],
|
||||
);
|
||||
when(mockXcode.otool(any)).thenAnswer((_) => Future<RunResult>.value(otoolResult));
|
||||
await expectToolExitLater(
|
||||
validateBitcode(),
|
||||
equals('The Flutter.framework at ios_profile/Flutter.framework does not contain bitcode.'),
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
Artifacts: () => LocalEngineArtifacts('/engine', 'ios_profile', 'host_profile'),
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Xcode: () => mockXcode,
|
||||
});
|
||||
|
||||
testUsingContext('build aot validates Flutter.framework/Flutter was built with same toolchain', () async {
|
||||
final Directory flutterFramework = memoryFileSystem.directory('ios_profile/Flutter.framework')
|
||||
..createSync(recursive: true);
|
||||
flutterFramework.childFile('Flutter').createSync();
|
||||
final File infoPlist = flutterFramework.childFile('Info.plist')..createSync();
|
||||
|
||||
final RunResult otoolResult = RunResult(
|
||||
FakeProcessResult(stdout: '__LLVM', stderr: ''),
|
||||
const <String>['foo'],
|
||||
);
|
||||
final RunResult clangResult = RunResult(
|
||||
FakeProcessResult(stdout: 'Apple LLVM version 10.0.0 (clang-4567.1.1.1)\nBlahBlah\n', stderr: ''),
|
||||
const <String>['foo'],
|
||||
);
|
||||
when(mockXcode.otool(any)).thenAnswer((_) => Future<RunResult>.value(otoolResult));
|
||||
when(mockXcode.clang(any)).thenAnswer((_) => Future<RunResult>.value(clangResult));
|
||||
when(mockPlistUtils.getValueFromFile(infoPlist.path, 'ClangVersion')).thenReturn('Apple LLVM version 10.0.1 (clang-1234.1.12.1)');
|
||||
|
||||
await expectToolExitLater(
|
||||
validateBitcode(BuildMode.release, TargetPlatform.ios),
|
||||
validateBitcode(),
|
||||
equals('The Flutter.framework at ios_profile/Flutter.framework was built with "Apple LLVM version 10.0.1 '
|
||||
'(clang-1234.1.12.1)", but the current version of clang is "Apple LLVM version 10.0.0 (clang-4567.1.1.1)". '
|
||||
'This will result in failures when trying toarchive an IPA. To resolve this issue, update your version '
|
||||
|
@ -78,14 +111,19 @@ void main() {
|
|||
flutterFramework.childFile('Flutter').createSync();
|
||||
final File infoPlist = flutterFramework.childFile('Info.plist')..createSync();
|
||||
|
||||
final RunResult otoolResult = RunResult(
|
||||
FakeProcessResult(stdout: '__LLVM', stderr: ''),
|
||||
const <String>['foo'],
|
||||
);
|
||||
final RunResult clangResult = RunResult(
|
||||
FakeProcessResult(stdout: 'Apple LLVM version 10.0.1 (clang-1234.1.12.1)\nBlahBlah\n', stderr: ''),
|
||||
const <String>['foo'],
|
||||
);
|
||||
when(mockXcode.otool(any)).thenAnswer((_) => Future<RunResult>.value(otoolResult));
|
||||
when(mockXcode.clang(any)).thenAnswer((_) => Future<RunResult>.value(clangResult));
|
||||
when(mockPlistUtils.getValueFromFile(infoPlist.path, 'ClangVersion')).thenReturn('Apple LLVM version 10.0.1 (clang-1234.1.12.1)');
|
||||
|
||||
await validateBitcode(BuildMode.release, TargetPlatform.ios);
|
||||
await validateBitcode();
|
||||
|
||||
expect(bufferLogger.statusText, '');
|
||||
}, overrides: <Type, Generator>{
|
||||
|
@ -103,14 +141,19 @@ void main() {
|
|||
flutterFramework.childFile('Flutter').createSync();
|
||||
final File infoPlist = flutterFramework.childFile('Info.plist')..createSync();
|
||||
|
||||
final RunResult otoolResult = RunResult(
|
||||
FakeProcessResult(stdout: '__LLVM', stderr: ''),
|
||||
const <String>['foo'],
|
||||
);
|
||||
final RunResult clangResult = RunResult(
|
||||
FakeProcessResult(stdout: 'Apple LLVM version 11.0.1 (clang-1234.1.12.1)\nBlahBlah\n', stderr: ''),
|
||||
const <String>['foo'],
|
||||
);
|
||||
when(mockXcode.otool(any)).thenAnswer((_) => Future<RunResult>.value(otoolResult));
|
||||
when(mockXcode.clang(any)).thenAnswer((_) => Future<RunResult>.value(clangResult));
|
||||
when(mockPlistUtils.getValueFromFile(infoPlist.path, 'ClangVersion')).thenReturn('Apple LLVM version 10.0.1 (clang-1234.1.12.1)');
|
||||
|
||||
await validateBitcode(BuildMode.release, TargetPlatform.ios);
|
||||
await validateBitcode();
|
||||
|
||||
expect(bufferLogger.statusText, '');
|
||||
}, overrides: <Type, Generator>{
|
||||
|
|
Loading…
Reference in a new issue