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'; ...@@ -11,6 +11,7 @@ import '../base/context.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../base/version.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../dart/package_map.dart'; import '../dart/package_map.dart';
import '../globals.dart'; import '../globals.dart';
...@@ -225,13 +226,35 @@ Future<void> validateBitcode() async { ...@@ -225,13 +226,35 @@ Future<void> validateBitcode() async {
fs.path.join(flutterFrameworkPath, 'Info.plist'), fs.path.join(flutterFrameworkPath, 'Info.plist'),
'ClangVersion', 'ClangVersion',
); );
if (clangVersion != engineClangVersion) { final Version engineClangSemVer = _parseVersionFromClang(engineClangVersion);
printStatus( final Version clangSemVer = _parseVersionFromClang(clangVersion);
if (engineClangSemVer > clangSemVer) {
throwToolExit(
'The Flutter.framework at $flutterFrameworkPath was built ' 'The Flutter.framework at $flutterFrameworkPath was built '
'with "${engineClangVersion ?? 'unknown'}", but the current version ' 'with "${engineClangVersion ?? 'unknown'}", but the current version '
'of clang is "$clangVersion". This may result in failures when ' 'of clang is "$clangVersion". This will result in failures when trying to'
'archiving your application in Xcode.', 'archive an IPA. To resolve this issue, update your version of Xcode to '
emphasis: true, '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() { ...@@ -82,19 +82,50 @@ void main() {
const <String>['foo'], const <String>['foo'],
); );
final RunResult clangResult = RunResult( 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'], const <String>['foo'],
); );
when(mockXcode.otool(any)).thenAnswer((_) => Future<RunResult>.value(otoolResult)); when(mockXcode.otool(any)).thenAnswer((_) => Future<RunResult>.value(otoolResult));
when(mockXcode.clang(any)).thenAnswer((_) => Future<RunResult>.value(clangResult)); 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( testUsingContext('build aot validates and succeeds - same version of Xcode', () async {
bufferLogger.statusText, final Directory flutterFramework = memoryFileSystem.directory('ios_profile/Flutter.framework')
startsWith('The Flutter.framework at ${flutterFramework.path} was built with "Apple LLVM Version 10.0.1'), ..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>{ }, overrides: <Type, Generator>{
Artifacts: () => LocalEngineArtifacts('/engine', 'ios_profile', 'host_profile'), Artifacts: () => LocalEngineArtifacts('/engine', 'ios_profile', 'host_profile'),
FileSystem: () => memoryFileSystem, FileSystem: () => memoryFileSystem,
...@@ -104,7 +135,7 @@ void main() { ...@@ -104,7 +135,7 @@ void main() {
IOSWorkflow: () => mockIOSWorkflow, 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') final Directory flutterFramework = memoryFileSystem.directory('ios_profile/Flutter.framework')
..createSync(recursive: true); ..createSync(recursive: true);
flutterFramework.childFile('Flutter').createSync(); flutterFramework.childFile('Flutter').createSync();
...@@ -115,12 +146,12 @@ void main() { ...@@ -115,12 +146,12 @@ void main() {
const <String>['foo'], const <String>['foo'],
); );
final RunResult clangResult = RunResult( 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'], const <String>['foo'],
); );
when(mockXcode.otool(any)).thenAnswer((_) => Future<RunResult>.value(otoolResult)); when(mockXcode.otool(any)).thenAnswer((_) => Future<RunResult>.value(otoolResult));
when(mockXcode.clang(any)).thenAnswer((_) => Future<RunResult>.value(clangResult)); 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 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