mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
Add more instructions and handling for first time iOS run (#10521)
* Before tests * Add the part to trust the cert on the device * flip the error checks since some are more specific and are more actionable * add tests * review
This commit is contained in:
parent
96b9d6473e
commit
c2b0a30c57
|
@ -45,7 +45,7 @@ class BuildIOSCommand extends BuildSubCommand {
|
|||
if (getCurrentHostPlatform() != HostPlatform.darwin_x64)
|
||||
throwToolExit('Building for iOS is only supported on the Mac.');
|
||||
|
||||
final IOSApp app = applicationPackages.getPackageForPlatform(TargetPlatform.ios);
|
||||
final BuildableIOSApp app = applicationPackages.getPackageForPlatform(TargetPlatform.ios);
|
||||
|
||||
if (app == null)
|
||||
throwToolExit('Application not configured for iOS');
|
||||
|
@ -73,7 +73,7 @@ class BuildIOSCommand extends BuildSubCommand {
|
|||
);
|
||||
|
||||
if (!result.success) {
|
||||
await diagnoseXcodeBuildFailure(result);
|
||||
await diagnoseXcodeBuildFailure(result, app);
|
||||
throwToolExit('Encountered error while building for $logTarget.');
|
||||
}
|
||||
|
||||
|
|
|
@ -14,34 +14,60 @@ import '../base/process.dart';
|
|||
import '../base/terminal.dart';
|
||||
import '../globals.dart';
|
||||
|
||||
/// User message when no development certificates are found in the keychain.
|
||||
///
|
||||
/// The user likely never did any iOS development.
|
||||
const String noCertificatesInstruction = '''
|
||||
═══════════════════════════════════════════════════════════════════════════════════
|
||||
No valid code signing certificates were found
|
||||
Please ensure that you have a valid Development Team with valid iOS Development Certificates
|
||||
associated with your Apple ID by:
|
||||
1- Opening the Xcode application
|
||||
2- Go to Xcode->Preferences->Accounts
|
||||
3- Make sure that you're signed in with your Apple ID via the '+' button on the bottom left
|
||||
4- Make sure that you have development certificates available by signing up to Apple
|
||||
Developer Program and/or downloading available profiles as needed.
|
||||
You can connect to your Apple Developer account by signing in with your Apple ID in Xcode
|
||||
and create an iOS Development Certificate as well as a Provisioning Profile for your project by:
|
||||
$fixWithDevelopmentTeamInstruction
|
||||
5- Trust your newly created Development Certificate on your iOS device
|
||||
via Settings > General > Device Management > [your new certificate] > Trust
|
||||
|
||||
For more information, please visit:
|
||||
https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingCertificates/MaintainingCertificates.html
|
||||
|
||||
Or run on an iOS simulator without code signing
|
||||
═══════════════════════════════════════════════════════════════════════════════════''';
|
||||
/// User message when there are no provisioning profile for the current app bundle identifier.
|
||||
///
|
||||
/// The user did iOS development but never on this project and/or device.
|
||||
const String noProvisioningProfileInstruction = '''
|
||||
═══════════════════════════════════════════════════════════════════════════════════
|
||||
No Provisioning Profile was found for your project's Bundle Identifier or your device.
|
||||
You can create a new Provisioning Profile for your project in Xcode for your
|
||||
team by:
|
||||
$fixWithDevelopmentTeamInstruction
|
||||
|
||||
For more information, please visit:
|
||||
https://flutter.io/setup/#deploy-to-ios-devices
|
||||
|
||||
Or run on an iOS simulator without code signing
|
||||
═══════════════════════════════════════════════════════════════════════════════════''';
|
||||
/// Fallback error message for signing issues.
|
||||
///
|
||||
/// Couldn't auto sign the app but can likely solved by retracing the signing flow in Xcode.
|
||||
const String noDevelopmentTeamInstruction = '''
|
||||
═══════════════════════════════════════════════════════════════════════════════════
|
||||
Building a deployable iOS app requires a selected Development Team with a Provisioning Profile
|
||||
Please ensure that a Development Team is selected by:
|
||||
1- Opening the Flutter project's Xcode target with
|
||||
$fixWithDevelopmentTeamInstruction
|
||||
|
||||
For more information, please visit:
|
||||
https://flutter.io/setup/#deploy-to-ios-devices
|
||||
|
||||
Or run on an iOS simulator without code signing
|
||||
═══════════════════════════════════════════════════════════════════════════════════''';
|
||||
const String fixWithDevelopmentTeamInstruction = '''
|
||||
1- Open the Flutter project's Xcode target with
|
||||
open ios/Runner.xcworkspace
|
||||
2- Select the 'Runner' project in the navigator then the 'Runner' target
|
||||
in the project settings
|
||||
3- In the 'General' tab, make sure a 'Development Team' is selected\n
|
||||
For more information, please visit:
|
||||
https://flutter.io/setup/#deploy-to-ios-devices\n
|
||||
Or run on an iOS simulator
|
||||
═══════════════════════════════════════════════════════════════════════════════════''';
|
||||
3- In the 'General' tab, make sure a 'Development Team' is selected. You may need to add
|
||||
your Apple ID first.
|
||||
4- Build or run your project again''';
|
||||
|
||||
final RegExp _securityFindIdentityDeveloperIdentityExtractionPattern =
|
||||
new RegExp(r'^\s*\d+\).+"(.+Developer.+)"$');
|
||||
|
|
|
@ -208,7 +208,7 @@ class IOSDevice extends Device {
|
|||
final XcodeBuildResult buildResult = await buildXcodeProject(app: app, mode: mode, target: mainPath, buildForDevice: true);
|
||||
if (!buildResult.success) {
|
||||
printError('Could not build the precompiled application for the device.');
|
||||
await diagnoseXcodeBuildFailure(buildResult);
|
||||
await diagnoseXcodeBuildFailure(buildResult, app);
|
||||
printError('');
|
||||
return new LaunchResult.failed();
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
|||
}
|
||||
|
||||
String developmentTeam;
|
||||
if (codesign && mode != BuildMode.release && buildForDevice)
|
||||
if (codesign && buildForDevice)
|
||||
developmentTeam = await getCodeSigningIdentityDevelopmentTeam(app);
|
||||
|
||||
// Before the build, all service definitions must be updated and the dylibs
|
||||
|
@ -246,51 +246,40 @@ Future<XcodeBuildResult> buildXcodeProject({
|
|||
}
|
||||
}
|
||||
|
||||
Future<Null> diagnoseXcodeBuildFailure(XcodeBuildResult result) async {
|
||||
final File plistFile = fs.file('ios/Runner/Info.plist');
|
||||
if (plistFile.existsSync()) {
|
||||
final String plistContent = plistFile.readAsStringSync();
|
||||
if (plistContent.contains('com.yourcompany')) {
|
||||
printError('');
|
||||
printError('It appears that your application still contains the default signing identifier.');
|
||||
printError("Try replacing 'com.yourcompany' with your signing id");
|
||||
printError('in ${plistFile.absolute.path}');
|
||||
return;
|
||||
}
|
||||
Future<Null> diagnoseXcodeBuildFailure(XcodeBuildResult result, BuildableIOSApp app) async {
|
||||
if (result.xcodeBuildExecution != null &&
|
||||
result.xcodeBuildExecution.buildForPhysicalDevice &&
|
||||
result.stdout?.contains('BCEROR') == true &&
|
||||
// May need updating if Xcode changes its outputs.
|
||||
result.stdout?.contains('Xcode couldn\'t find a provisioning profile matching') == true) {
|
||||
printError(noProvisioningProfileInstruction, emphasis: true);
|
||||
return;
|
||||
}
|
||||
if (result.xcodeBuildExecution != null &&
|
||||
result.xcodeBuildExecution.buildForPhysicalDevice &&
|
||||
// Make sure the user has specified at least the DEVELOPMENT_TEAM (for automatic Xcode 8)
|
||||
// signing or the PROVISIONING_PROFILE (for manual signing or Xcode 7).
|
||||
!(app.buildSettings?.containsKey('DEVELOPMENT_TEAM')) == true || app.buildSettings?.containsKey('PROVISIONING_PROFILE') == true) {
|
||||
printError(noDevelopmentTeamInstruction, emphasis: true);
|
||||
return;
|
||||
}
|
||||
if (app.id?.contains('com.yourcompany') ?? false) {
|
||||
printError('');
|
||||
printError('It appears that your application still contains the default signing identifier.');
|
||||
printError("Try replacing 'com.yourcompany' with your signing id in Xcode:");
|
||||
printError(' open ios/Runner.xcworkspace');
|
||||
return;
|
||||
}
|
||||
if (result.stdout?.contains('Code Sign error') == true) {
|
||||
printError('');
|
||||
printError('It appears that there was a problem signing your application prior to installation on the device.');
|
||||
printError('');
|
||||
if (plistFile.existsSync()) {
|
||||
printError('Verify that the CFBundleIdentifier in the Info.plist file is your signing id');
|
||||
printError(' ${plistFile.absolute.path}');
|
||||
printError('');
|
||||
}
|
||||
printError("Try launching Xcode and selecting 'Product > Build' to fix the problem:");
|
||||
printError(" open ios/Runner.xcworkspace");
|
||||
printError('Verify that the Bundle Identifier in your project is your signing id in Xcode');
|
||||
printError(' open ios/Runner.xcworkspace');
|
||||
printError('');
|
||||
printError("Also try selecting 'Product > Build' to fix the problem:");
|
||||
return;
|
||||
}
|
||||
if (result.xcodeBuildExecution != null) {
|
||||
assert(result.xcodeBuildExecution.buildForPhysicalDevice != null);
|
||||
assert(result.xcodeBuildExecution.buildCommands != null);
|
||||
assert(result.xcodeBuildExecution.appDirectory != null);
|
||||
if (result.xcodeBuildExecution.buildForPhysicalDevice &&
|
||||
result.xcodeBuildExecution.buildCommands.contains('build')) {
|
||||
final RunResult checkBuildSettings = await runAsync(
|
||||
result.xcodeBuildExecution.buildCommands..add('-showBuildSettings'),
|
||||
workingDirectory: result.xcodeBuildExecution.appDirectory,
|
||||
allowReentrantFlutter: true
|
||||
);
|
||||
// Make sure the user has specified at least the DEVELOPMENT_TEAM (for automatic Xcode 8)
|
||||
// signing or the PROVISIONING_PROFILE (for manual signing or Xcode 7).
|
||||
if (checkBuildSettings.exitCode == 0 &&
|
||||
!checkBuildSettings.stdout?.contains(new RegExp(r'\bDEVELOPMENT_TEAM\b')) == true &&
|
||||
!checkBuildSettings.stdout?.contains(new RegExp(r'\bPROVISIONING_PROFILE\b')) == true) {
|
||||
printError(noDevelopmentTeamInstruction, emphasis: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class XcodeBuildResult {
|
||||
|
|
176
packages/flutter_tools/test/ios/mac_test.dart
Normal file
176
packages/flutter_tools/test/ios/mac_test.dart
Normal file
|
@ -0,0 +1,176 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter_tools/src/application_package.dart';
|
||||
import 'package:flutter_tools/src/ios/mac.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../src/context.dart';
|
||||
|
||||
void main() {
|
||||
group('Diagnose Xcode build failure', () {
|
||||
BuildableIOSApp app;
|
||||
|
||||
setUp(() {
|
||||
app = new BuildableIOSApp(
|
||||
projectBundleId: 'test.app',
|
||||
buildSettings: <String, String>{
|
||||
'For our purposes': 'a non-empty build settings map is valid',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('No provisioning profile shows message', () async {
|
||||
final XcodeBuildResult buildResult = new XcodeBuildResult(
|
||||
success: false,
|
||||
stdout: '''
|
||||
Launching lib/main.dart on iPhone in debug mode...
|
||||
Signing iOS app for device deployment using developer identity: "iPhone Developer: test@flutter.io (1122334455)"
|
||||
Running Xcode build... 1.3s
|
||||
Failed to build iOS app
|
||||
Error output from Xcode build:
|
||||
↳
|
||||
** BUILD FAILED **
|
||||
|
||||
|
||||
The following build commands failed:
|
||||
Check dependencies
|
||||
(1 failure)
|
||||
Xcode's output:
|
||||
↳
|
||||
Build settings from command line:
|
||||
ARCHS = arm64
|
||||
BUILD_DIR = /Users/blah/blah
|
||||
DEVELOPMENT_TEAM = AABBCCDDEE
|
||||
ONLY_ACTIVE_ARCH = YES
|
||||
SDKROOT = iphoneos10.3
|
||||
|
||||
=== CLEAN TARGET Runner OF PROJECT Runner WITH CONFIGURATION Release ===
|
||||
|
||||
Check dependencies
|
||||
[BCEROR]No profiles for 'com.yourcompany.test' were found: Xcode couldn't find a provisioning profile matching 'com.yourcompany.test'.
|
||||
[BCEROR]Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
[BCEROR]Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
[BCEROR]Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
|
||||
Create product structure
|
||||
/bin/mkdir -p /Users/blah/Runner.app
|
||||
|
||||
Clean.Remove clean /Users/blah/Runner.app.dSYM
|
||||
builtin-rm -rf /Users/blah/Runner.app.dSYM
|
||||
|
||||
Clean.Remove clean /Users/blah/Runner.app
|
||||
builtin-rm -rf /Users/blah/Runner.app
|
||||
|
||||
Clean.Remove clean /Users/blah/Runner-dfvicjniknvzghgwsthwtgcjhtsk/Build/Intermediates/Runner.build/Release-iphoneos/Runner.build
|
||||
builtin-rm -rf /Users/blah/Runner-dfvicjniknvzghgwsthwtgcjhtsk/Build/Intermediates/Runner.build/Release-iphoneos/Runner.build
|
||||
|
||||
** CLEAN SUCCEEDED **
|
||||
|
||||
=== BUILD TARGET Runner OF PROJECT Runner WITH CONFIGURATION Release ===
|
||||
|
||||
Check dependencies
|
||||
No profiles for 'com.yourcompany.test' were found: Xcode couldn't find a provisioning profile matching 'com.yourcompany.test'.
|
||||
Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
|
||||
Could not build the precompiled application for the device.
|
||||
|
||||
Error launching application on iPhone.''',
|
||||
xcodeBuildExecution: new XcodeBuildExecution(
|
||||
<String>['xcrun', 'xcodebuild', 'blah'],
|
||||
'/blah/blah',
|
||||
buildForPhysicalDevice: true
|
||||
),
|
||||
);
|
||||
|
||||
await diagnoseXcodeBuildFailure(buildResult, app);
|
||||
expect(
|
||||
testLogger.errorText,
|
||||
contains('No Provisioning Profile was found for your project\'s Bundle Identifier or your device.'),
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('No development team shows message', () async {
|
||||
final XcodeBuildResult buildResult = new XcodeBuildResult(
|
||||
success: false,
|
||||
stdout: '''
|
||||
Running "flutter packages get" in flutter_gallery... 0.6s
|
||||
Launching lib/main.dart on x in release mode...
|
||||
Running pod install... 1.2s
|
||||
Running Xcode build... 1.4s
|
||||
Failed to build iOS app
|
||||
Error output from Xcode build:
|
||||
↳
|
||||
** BUILD FAILED **
|
||||
|
||||
|
||||
The following build commands failed:
|
||||
Check dependencies
|
||||
(1 failure)
|
||||
Xcode's output:
|
||||
↳
|
||||
blah
|
||||
|
||||
=== CLEAN TARGET url_launcher OF PROJECT Pods WITH CONFIGURATION Release ===
|
||||
|
||||
Check dependencies
|
||||
|
||||
blah
|
||||
|
||||
=== CLEAN TARGET Pods-Runner OF PROJECT Pods WITH CONFIGURATION Release ===
|
||||
|
||||
Check dependencies
|
||||
|
||||
blah
|
||||
|
||||
=== CLEAN TARGET Runner OF PROJECT Runner WITH CONFIGURATION Release ===
|
||||
|
||||
Check dependencies
|
||||
[BCEROR]Signing for "Runner" requires a development team. Select a development team in the project editor.
|
||||
[BCEROR]Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
[BCEROR]Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
[BCEROR]Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
|
||||
blah
|
||||
|
||||
** CLEAN SUCCEEDED **
|
||||
|
||||
=== BUILD TARGET url_launcher OF PROJECT Pods WITH CONFIGURATION Release ===
|
||||
|
||||
Check dependencies
|
||||
|
||||
blah
|
||||
|
||||
=== BUILD TARGET Pods-Runner OF PROJECT Pods WITH CONFIGURATION Release ===
|
||||
|
||||
Check dependencies
|
||||
|
||||
blah
|
||||
|
||||
=== BUILD TARGET Runner OF PROJECT Runner WITH CONFIGURATION Release ===
|
||||
|
||||
Check dependencies
|
||||
Signing for "Runner" requires a development team. Select a development team in the project editor.
|
||||
Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
Code signing is required for product type 'Application' in SDK 'iOS 10.3'
|
||||
|
||||
Could not build the precompiled application for the device.''',
|
||||
xcodeBuildExecution: new XcodeBuildExecution(
|
||||
<String>['xcrun', 'xcodebuild', 'blah'],
|
||||
'/blah/blah',
|
||||
buildForPhysicalDevice: true
|
||||
),
|
||||
);
|
||||
|
||||
await diagnoseXcodeBuildFailure(buildResult, app);
|
||||
expect(
|
||||
testLogger.errorText,
|
||||
contains('Building a deployable iOS app requires a selected Development Team with a Provisioning Profile'),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue