Detect ARM ffi CocoaPods error, suggest gem install (#70801)
This commit is contained in:
parent
ef4741540b
commit
37f4f1f281
@ -135,6 +135,7 @@ Future<T> runInContext<T>(
|
|||||||
platform: globals.platform,
|
platform: globals.platform,
|
||||||
xcodeProjectInterpreter: globals.xcodeProjectInterpreter,
|
xcodeProjectInterpreter: globals.xcodeProjectInterpreter,
|
||||||
artifacts: globals.artifacts,
|
artifacts: globals.artifacts,
|
||||||
|
usage: globals.flutterUsage,
|
||||||
),
|
),
|
||||||
CocoaPodsValidator: () => CocoaPodsValidator(
|
CocoaPodsValidator: () => CocoaPodsValidator(
|
||||||
globals.cocoaPods,
|
globals.cocoaPods,
|
||||||
|
@ -12,6 +12,7 @@ import '../base/error_handling_io.dart';
|
|||||||
import '../base/file_system.dart';
|
import '../base/file_system.dart';
|
||||||
import '../base/io.dart';
|
import '../base/io.dart';
|
||||||
import '../base/logger.dart';
|
import '../base/logger.dart';
|
||||||
|
import '../base/os.dart';
|
||||||
import '../base/platform.dart';
|
import '../base/platform.dart';
|
||||||
import '../base/process.dart';
|
import '../base/process.dart';
|
||||||
import '../base/version.dart';
|
import '../base/version.dart';
|
||||||
@ -19,6 +20,7 @@ import '../build_info.dart';
|
|||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
import '../ios/xcodeproj.dart';
|
import '../ios/xcodeproj.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
|
import '../reporting/reporting.dart';
|
||||||
|
|
||||||
const String noCocoaPodsConsequence = '''
|
const String noCocoaPodsConsequence = '''
|
||||||
CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
|
CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
|
||||||
@ -82,23 +84,33 @@ class CocoaPods {
|
|||||||
@required Logger logger,
|
@required Logger logger,
|
||||||
@required Platform platform,
|
@required Platform platform,
|
||||||
@required Artifacts artifacts,
|
@required Artifacts artifacts,
|
||||||
|
@required Usage usage,
|
||||||
}) : _fileSystem = fileSystem,
|
}) : _fileSystem = fileSystem,
|
||||||
_processManager = processManager,
|
_processManager = processManager,
|
||||||
_xcodeProjectInterpreter = xcodeProjectInterpreter,
|
_xcodeProjectInterpreter = xcodeProjectInterpreter,
|
||||||
_logger = logger,
|
_logger = logger,
|
||||||
_platform = platform,
|
_platform = platform,
|
||||||
_artifacts = artifacts,
|
_artifacts = artifacts,
|
||||||
|
_usage = usage,
|
||||||
_processUtils = ProcessUtils(processManager: processManager, logger: logger),
|
_processUtils = ProcessUtils(processManager: processManager, logger: logger),
|
||||||
_fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform);
|
_fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform),
|
||||||
|
_operatingSystemUtils = OperatingSystemUtils(
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
platform: platform,
|
||||||
|
processManager: processManager,
|
||||||
|
);
|
||||||
|
|
||||||
final FileSystem _fileSystem;
|
final FileSystem _fileSystem;
|
||||||
final ProcessManager _processManager;
|
final ProcessManager _processManager;
|
||||||
final FileSystemUtils _fileSystemUtils;
|
final FileSystemUtils _fileSystemUtils;
|
||||||
final ProcessUtils _processUtils;
|
final ProcessUtils _processUtils;
|
||||||
|
final OperatingSystemUtils _operatingSystemUtils;
|
||||||
final XcodeProjectInterpreter _xcodeProjectInterpreter;
|
final XcodeProjectInterpreter _xcodeProjectInterpreter;
|
||||||
final Logger _logger;
|
final Logger _logger;
|
||||||
final Platform _platform;
|
final Platform _platform;
|
||||||
final Artifacts _artifacts;
|
final Artifacts _artifacts;
|
||||||
|
final Usage _usage;
|
||||||
|
|
||||||
Future<String> _versionText;
|
Future<String> _versionText;
|
||||||
|
|
||||||
@ -370,14 +382,31 @@ class CocoaPods {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _diagnosePodInstallFailure(ProcessResult result) {
|
void _diagnosePodInstallFailure(ProcessResult result) {
|
||||||
final dynamic stdout = result.stdout;
|
if (result.stdout is! String) {
|
||||||
if (stdout is String && stdout.contains('out-of-date source repos')) {
|
return;
|
||||||
|
}
|
||||||
|
final String stdout = result.stdout as String;
|
||||||
|
if (stdout.contains('out-of-date source repos')) {
|
||||||
_logger.printError(
|
_logger.printError(
|
||||||
"Error: CocoaPods's specs repository is too out-of-date to satisfy dependencies.\n"
|
"Error: CocoaPods's specs repository is too out-of-date to satisfy dependencies.\n"
|
||||||
'To update the CocoaPods specs, run:\n'
|
'To update the CocoaPods specs, run:\n'
|
||||||
' pod repo update\n',
|
' pod repo update\n',
|
||||||
emphasis: true,
|
emphasis: true,
|
||||||
);
|
);
|
||||||
|
} else if (stdout.contains('Init_ffi_c') &&
|
||||||
|
stdout.contains('symbol not found') &&
|
||||||
|
_operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm) {
|
||||||
|
// https://github.com/flutter/flutter/issues/70796
|
||||||
|
UsageEvent(
|
||||||
|
'pod-install-failure',
|
||||||
|
'arm-ffi',
|
||||||
|
flutterUsage: _usage,
|
||||||
|
).send();
|
||||||
|
_logger.printError(
|
||||||
|
'Error: To set up CocoaPods for ARM macOS, run:\n'
|
||||||
|
' arch -x86_64 sudo gem install ffi\n',
|
||||||
|
emphasis: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
|||||||
import 'package:flutter_tools/src/macos/cocoapods.dart';
|
import 'package:flutter_tools/src/macos/cocoapods.dart';
|
||||||
import 'package:flutter_tools/src/plugins.dart';
|
import 'package:flutter_tools/src/plugins.dart';
|
||||||
import 'package:flutter_tools/src/project.dart';
|
import 'package:flutter_tools/src/project.dart';
|
||||||
|
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
import 'package:process/process.dart';
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ void main() {
|
|||||||
CocoaPods cocoaPodsUnderTest;
|
CocoaPods cocoaPodsUnderTest;
|
||||||
InvokeProcess resultOfPodVersion;
|
InvokeProcess resultOfPodVersion;
|
||||||
BufferLogger logger;
|
BufferLogger logger;
|
||||||
|
Usage usage;
|
||||||
|
|
||||||
void pretendPodVersionFails() {
|
void pretendPodVersionFails() {
|
||||||
resultOfPodVersion = () async => exitsWithError();
|
resultOfPodVersion = () async => exitsWithError();
|
||||||
@ -68,15 +70,17 @@ void main() {
|
|||||||
projectUnderTest = FlutterProject.fromDirectory(fileSystem.directory('project'));
|
projectUnderTest = FlutterProject.fromDirectory(fileSystem.directory('project'));
|
||||||
projectUnderTest.ios.xcodeProject.createSync(recursive: true);
|
projectUnderTest.ios.xcodeProject.createSync(recursive: true);
|
||||||
projectUnderTest.macos.xcodeProject.createSync(recursive: true);
|
projectUnderTest.macos.xcodeProject.createSync(recursive: true);
|
||||||
|
usage = Usage.test();
|
||||||
cocoaPodsUnderTest = CocoaPods(
|
cocoaPodsUnderTest = CocoaPods(
|
||||||
fileSystem: fileSystem,
|
fileSystem: fileSystem,
|
||||||
processManager: mockProcessManager,
|
processManager: mockProcessManager,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
platform: FakePlatform(),
|
platform: FakePlatform(operatingSystem: 'macos'),
|
||||||
artifacts: Artifacts.test(),
|
artifacts: Artifacts.test(),
|
||||||
xcodeProjectInterpreter: mockXcodeProjectInterpreter,
|
xcodeProjectInterpreter: mockXcodeProjectInterpreter,
|
||||||
|
usage: usage,
|
||||||
);
|
);
|
||||||
pretendPodVersionIs('1.8.0');
|
pretendPodVersionIs('1.9.0');
|
||||||
fileSystem.file(fileSystem.path.join(
|
fileSystem.file(fileSystem.path.join(
|
||||||
Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-ios-objc',
|
Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-ios-objc',
|
||||||
))
|
))
|
||||||
@ -450,6 +454,79 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWithoutContext('ffi failure on ARM macOS prompts gem install', () async {
|
||||||
|
pretendPodIsInstalled();
|
||||||
|
fileSystem.file(fileSystem.path.join('project', 'ios', 'Podfile'))
|
||||||
|
..createSync()
|
||||||
|
..writeAsStringSync('Existing Podfile');
|
||||||
|
|
||||||
|
when(mockProcessManager.runSync(<String>['sysctl', 'hw.optional.arm64']))
|
||||||
|
.thenReturn(ProcessResult(0, 0, 'hw.optional.arm64: 1', ''));
|
||||||
|
|
||||||
|
when(mockProcessManager.run(
|
||||||
|
<String>['pod', 'install', '--verbose'],
|
||||||
|
workingDirectory: 'project/ios',
|
||||||
|
environment: <String, String>{
|
||||||
|
'COCOAPODS_DISABLE_STATS': 'true',
|
||||||
|
'LANG': 'en_US.UTF-8',
|
||||||
|
},
|
||||||
|
)).thenAnswer((_) async => exitsWithError(
|
||||||
|
'LoadError - dlsym(0x7fbbeb6837d0, Init_ffi_c): symbol not found - /Library/Ruby/Gems/2.6.0/gems/ffi-1.13.1/lib/ffi_c.bundle',
|
||||||
|
));
|
||||||
|
|
||||||
|
// Capture Usage.test() events.
|
||||||
|
final StringBuffer buffer =
|
||||||
|
await capturedConsolePrint(() => expectToolExitLater(
|
||||||
|
cocoaPodsUnderTest.processPods(
|
||||||
|
xcodeProject: projectUnderTest.ios,
|
||||||
|
buildMode: BuildMode.debug,
|
||||||
|
),
|
||||||
|
equals('Error running pod install'),
|
||||||
|
));
|
||||||
|
expect(
|
||||||
|
logger.errorText,
|
||||||
|
contains('set up CocoaPods for ARM macOS'),
|
||||||
|
);
|
||||||
|
expect(buffer.toString(),
|
||||||
|
contains('event {category: pod-install-failure, action: arm-ffi'));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWithoutContext('ffi failure on x86 macOS does not prompt gem install', () async {
|
||||||
|
pretendPodIsInstalled();
|
||||||
|
fileSystem.file(fileSystem.path.join('project', 'ios', 'Podfile'))
|
||||||
|
..createSync()
|
||||||
|
..writeAsStringSync('Existing Podfile');
|
||||||
|
|
||||||
|
when(mockProcessManager.runSync(<String>['sysctl', 'hw.optional.arm64']))
|
||||||
|
.thenReturn(ProcessResult(0, 1, '', ''));
|
||||||
|
|
||||||
|
when(mockProcessManager.run(
|
||||||
|
<String>['pod', 'install', '--verbose'],
|
||||||
|
workingDirectory: 'project/ios',
|
||||||
|
environment: <String, String>{
|
||||||
|
'COCOAPODS_DISABLE_STATS': 'true',
|
||||||
|
'LANG': 'en_US.UTF-8',
|
||||||
|
},
|
||||||
|
)).thenAnswer((_) async => exitsWithError(
|
||||||
|
'LoadError - dlsym(0x7fbbeb6837d0, Init_ffi_c): symbol not found - /Library/Ruby/Gems/2.6.0/gems/ffi-1.13.1/lib/ffi_c.bundle',
|
||||||
|
));
|
||||||
|
|
||||||
|
// Capture Usage.test() events.
|
||||||
|
final StringBuffer buffer =
|
||||||
|
await capturedConsolePrint(() => expectToolExitLater(
|
||||||
|
cocoaPodsUnderTest.processPods(
|
||||||
|
xcodeProject: projectUnderTest.ios,
|
||||||
|
buildMode: BuildMode.debug,
|
||||||
|
),
|
||||||
|
equals('Error running pod install'),
|
||||||
|
));
|
||||||
|
expect(
|
||||||
|
logger.errorText,
|
||||||
|
isNot(contains('ARM macOS')),
|
||||||
|
);
|
||||||
|
expect(buffer.isEmpty, true);
|
||||||
|
});
|
||||||
|
|
||||||
testWithoutContext('run pod install, if Podfile.lock is missing', () async {
|
testWithoutContext('run pod install, if Podfile.lock is missing', () async {
|
||||||
pretendPodIsInstalled();
|
pretendPodIsInstalled();
|
||||||
projectUnderTest.ios.podfile
|
projectUnderTest.ios.podfile
|
||||||
|
Loading…
x
Reference in New Issue
Block a user