Unverified Commit 07f079a9 authored by Dan Field's avatar Dan Field Committed by GitHub

Improve bitcode check (#38587)

parent 2a6f1b73
......@@ -11,6 +11,7 @@ import '../base/context.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/process.dart';
import '../base/version.dart';
import '../build_info.dart';
import '../dart/package_map.dart';
import '../globals.dart';
......@@ -225,13 +226,35 @@ Future<void> validateBitcode() async {
fs.path.join(flutterFrameworkPath, 'Info.plist'),
'ClangVersion',
);
if (clangVersion != engineClangVersion) {
printStatus(
final Version engineClangSemVer = _parseVersionFromClang(engineClangVersion);
final Version clangSemVer = _parseVersionFromClang(clangVersion);
if (engineClangSemVer > clangSemVer) {
throwToolExit(
'The Flutter.framework at $flutterFrameworkPath was built '
'with "${engineClangVersion ?? 'unknown'}", but the current version '
'of clang is "$clangVersion". This may result in failures when '
'archiving your application in Xcode.',
emphasis: true,
'of clang is "$clangVersion". This will result in failures when trying to'
'archive an IPA. To resolve this issue, update your version of Xcode to '
'at least $engineClangSemVer.',
);
}
}
Version _parseVersionFromClang(String clangVersion) {
const String prefix = 'Apple LLVM version ';
void _invalid() {
throwToolExit('Unable to parse Clang version from "$clangVersion". '
'Expected a string like "$prefix #.#.# (clang-####.#.##.#)".');
}
if (clangVersion == null || clangVersion.length <= prefix.length || !clangVersion.startsWith(prefix)) {
_invalid();
}
final int lastSpace = clangVersion.lastIndexOf(' ');
if (lastSpace == -1) {
_invalid();
}
final Version version = Version.parse(clangVersion.substring(prefix.length, lastSpace));
if (version == null) {
_invalid();
}
return version;
}
......@@ -82,19 +82,50 @@ void main() {
const <String>['foo'],
);
final RunResult clangResult = RunResult(
FakeProcessResult(stdout: 'BadVersion\nBlahBlah\n', stderr: ''),
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(mockIOSWorkflow.getPlistValueFromFile(infoPlist.path, 'ClangVersion')).thenReturn('Apple LLVM Version 10.0.1');
when(mockIOSWorkflow.getPlistValueFromFile(infoPlist.path, 'ClangVersion')).thenReturn('Apple LLVM version 10.0.1 (clang-1234.1.12.1)');
await validateBitcode();
await expectToolExitLater(
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 '
'of Xcode to at least 10.0.1.'),
);
}, overrides: <Type, Generator>{
Artifacts: () => LocalEngineArtifacts('/engine', 'ios_profile', 'host_profile'),
FileSystem: () => memoryFileSystem,
ProcessManager: () => mockProcessManager,
Xcode: () => mockXcode,
Logger: () => bufferLogger,
IOSWorkflow: () => mockIOSWorkflow,
});
expect(
bufferLogger.statusText,
startsWith('The Flutter.framework at ${flutterFramework.path} was built with "Apple LLVM Version 10.0.1'),
testUsingContext('build aot validates and succeeds - same version of Xcode', () 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.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(mockIOSWorkflow.getPlistValueFromFile(infoPlist.path, 'ClangVersion')).thenReturn('Apple LLVM version 10.0.1 (clang-1234.1.12.1)');
await validateBitcode();
expect(bufferLogger.statusText, '');
}, overrides: <Type, Generator>{
Artifacts: () => LocalEngineArtifacts('/engine', 'ios_profile', 'host_profile'),
FileSystem: () => memoryFileSystem,
......@@ -104,7 +135,7 @@ void main() {
IOSWorkflow: () => mockIOSWorkflow,
});
testUsingContext('build aot validates and succeeds', () async {
testUsingContext('build aot validates and succeeds when user has newer version of Xcode', () async {
final Directory flutterFramework = memoryFileSystem.directory('ios_profile/Flutter.framework')
..createSync(recursive: true);
flutterFramework.childFile('Flutter').createSync();
......@@ -115,12 +146,12 @@ void main() {
const <String>['foo'],
);
final RunResult clangResult = RunResult(
FakeProcessResult(stdout: 'Apple LLVM Version 10.0.1\nBlahBlah\n', stderr: ''),
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(mockIOSWorkflow.getPlistValueFromFile(infoPlist.path, 'ClangVersion')).thenReturn('Apple LLVM Version 10.0.1');
when(mockIOSWorkflow.getPlistValueFromFile(infoPlist.path, 'ClangVersion')).thenReturn('Apple LLVM version 10.0.1 (clang-1234.1.12.1)');
await validateBitcode();
......
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