Remove Runner target check, prefer schemes (#56620)
diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart index 0b00d6b..3315e46 100644 --- a/packages/flutter_tools/lib/src/application_package.dart +++ b/packages/flutter_tools/lib/src/application_package.dart
@@ -31,6 +31,7 @@ Future<ApplicationPackage> getPackageForPlatform( TargetPlatform platform, { + BuildInfo buildInfo, File applicationBinary, }) async { switch (platform) { @@ -47,7 +48,7 @@ : AndroidApk.fromApk(applicationBinary); case TargetPlatform.ios: return applicationBinary == null - ? await IOSApp.fromIosProject(FlutterProject.current().ios) + ? await IOSApp.fromIosProject(FlutterProject.current().ios, buildInfo) : IOSApp.fromPrebuiltApp(applicationBinary); case TargetPlatform.tester: return FlutterTesterApp.fromCurrentDirectory(); @@ -327,7 +328,7 @@ ); } - static Future<IOSApp> fromIosProject(IosProject project) { + static Future<IOSApp> fromIosProject(IosProject project, BuildInfo buildInfo) { if (getCurrentHostPlatform() != HostPlatform.darwin_x64) { return null; } @@ -344,7 +345,7 @@ globals.printError('Expected ios/Runner.xcodeproj/project.pbxproj but this file is missing.'); return null; } - return BuildableIOSApp.fromProject(project); + return BuildableIOSApp.fromProject(project, buildInfo); } @override @@ -360,9 +361,9 @@ : _hostAppBundleName = hostAppBundleName, super(projectBundleId: projectBundleId); - static Future<BuildableIOSApp> fromProject(IosProject project) async { - final String projectBundleId = await project.productBundleIdentifier; - final String hostAppBundleName = await project.hostAppBundleName; + static Future<BuildableIOSApp> fromProject(IosProject project, BuildInfo buildInfo) async { + final String projectBundleId = await project.productBundleIdentifier(buildInfo); + final String hostAppBundleName = await project.hostAppBundleName(buildInfo); return BuildableIOSApp(project, projectBundleId, hostAppBundleName); } @@ -416,7 +417,10 @@ MacOSApp macOS; WindowsApp windows; - Future<ApplicationPackage> getPackageForPlatform(TargetPlatform platform) async { + Future<ApplicationPackage> getPackageForPlatform( + TargetPlatform platform, + BuildInfo buildInfo, + ) async { switch (platform) { case TargetPlatform.android: case TargetPlatform.android_arm: @@ -426,7 +430,7 @@ android ??= await AndroidApk.fromAndroidProject(FlutterProject.current().android); return android; case TargetPlatform.ios: - iOS ??= await IOSApp.fromIosProject(FlutterProject.current().ios); + iOS ??= await IOSApp.fromIosProject(FlutterProject.current().ios, buildInfo); return iOS; case TargetPlatform.fuchsia_arm64: case TargetPlatform.fuchsia_x64:
diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart index b3cb71d..b445ea1 100644 --- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
@@ -370,6 +370,7 @@ firstBuildTime = DateTime.now(); final ApplicationPackage package = await ApplicationPackageFactory.instance.getPackageForPlatform( TargetPlatform.web_javascript, + buildInfo: debuggingOptions.buildInfo, applicationBinary: null, ); if (package == null) {
diff --git a/packages/flutter_tools/lib/src/commands/build_ios.dart b/packages/flutter_tools/lib/src/commands/build_ios.dart index fb7a10b..5f5dee1 100644 --- a/packages/flutter_tools/lib/src/commands/build_ios.dart +++ b/packages/flutter_tools/lib/src/commands/build_ios.dart
@@ -64,7 +64,11 @@ throwToolExit('Building for iOS is only supported on the Mac.'); } - final BuildableIOSApp app = await applicationPackages.getPackageForPlatform(TargetPlatform.ios) as BuildableIOSApp; + final BuildInfo buildInfo = getBuildInfo(); + final BuildableIOSApp app = await applicationPackages.getPackageForPlatform( + TargetPlatform.ios, + buildInfo, + ) as BuildableIOSApp; if (app == null) { throwToolExit('Application not configured for iOS'); @@ -76,7 +80,6 @@ globals.printStatus('Warning: Building for device with codesigning disabled. You will ' 'have to manually codesign before deploying to device.'); } - final BuildInfo buildInfo = getBuildInfo(); if (forSimulator && !buildInfo.supportsSimulator) { throwToolExit('${toTitleCase(buildInfo.friendlyModeName)} mode is not supported for simulators.'); }
diff --git a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart index 479119b..5fa5942 100644 --- a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart +++ b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
@@ -181,8 +181,8 @@ final Directory outputDirectory = globals.fs.directory(globals.fs.path.absolute(globals.fs.path.normalize(outputArgument))); - final String productBundleIdentifier = await _project.ios.productBundleIdentifier; for (final BuildInfo buildInfo in buildInfos) { + final String productBundleIdentifier = await _project.ios.productBundleIdentifier(buildInfo); globals.printStatus('Building frameworks for $productBundleIdentifier in ${getNameForBuildMode(buildInfo.mode)} mode...'); final String xcodeBuildConfiguration = toTitleCase(getNameForBuildMode(buildInfo.mode)); final Directory modeDirectory = outputDirectory.childDirectory(xcodeBuildConfiguration);
diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart index b6bfdf2..9055483 100644 --- a/packages/flutter_tools/lib/src/commands/drive.dart +++ b/packages/flutter_tools/lib/src/commands/drive.dart
@@ -404,7 +404,7 @@ await appStopper(command); final ApplicationPackage package = await command.applicationPackages - .getPackageForPlatform(await command.device.targetPlatform); + .getPackageForPlatform(await command.device.targetPlatform, command.getBuildInfo()); if (command.shouldBuild) { globals.printTrace('Installing application package.'); @@ -497,7 +497,10 @@ Future<bool> _stopApp(DriveCommand command) async { globals.printTrace('Stopping application.'); - final ApplicationPackage package = await command.applicationPackages.getPackageForPlatform(await command.device.targetPlatform); + final ApplicationPackage package = await command.applicationPackages.getPackageForPlatform( + await command.device.targetPlatform, + command.getBuildInfo(), + ); final bool stopped = await command.device.stopApp(package); await command._deviceLogSubscription?.cancel(); return stopped;
diff --git a/packages/flutter_tools/lib/src/commands/install.dart b/packages/flutter_tools/lib/src/commands/install.dart index 2d2b69a..320552a 100644 --- a/packages/flutter_tools/lib/src/commands/install.dart +++ b/packages/flutter_tools/lib/src/commands/install.dart
@@ -43,7 +43,10 @@ @override Future<FlutterCommandResult> runCommand() async { - final ApplicationPackage package = await applicationPackages.getPackageForPlatform(await device.targetPlatform); + final ApplicationPackage package = await applicationPackages.getPackageForPlatform( + await device.targetPlatform, + null, // Build info isn't relevant for install, will use whatever bundle was built last. + ); Cache.releaseLockEarly();
diff --git a/packages/flutter_tools/lib/src/ios/code_signing.dart b/packages/flutter_tools/lib/src/ios/code_signing.dart index cce0ae4..ec99325 100644 --- a/packages/flutter_tools/lib/src/ios/code_signing.dart +++ b/packages/flutter_tools/lib/src/ios/code_signing.dart
@@ -13,6 +13,7 @@ import '../base/io.dart'; import '../base/logger.dart'; import '../base/process.dart'; +import '../build_info.dart'; import '../convert.dart' show utf8; import '../globals.dart' as globals; @@ -101,8 +102,9 @@ @required BuildableIOSApp iosApp, @required ProcessManager processManager, @required Logger logger, + @required BuildInfo buildInfo, }) async { - final Map<String, String> buildSettings = await iosApp.project.buildSettings; + final Map<String, String> buildSettings = await iosApp.project.buildSettingsForBuildInfo(buildInfo); if (buildSettings == null) { return null; }
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart index d3d6e92..f2f088d 100644 --- a/packages/flutter_tools/lib/src/ios/mac.dart +++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -111,12 +111,6 @@ await removeFinderExtendedAttributes(app.project.hostAppRoot, processUtils, globals.logger); final XcodeProjectInfo projectInfo = await globals.xcodeProjectInterpreter.getInfo(app.project.hostAppRoot.path); - if (!projectInfo.targets.contains('Runner')) { - globals.printError('The Xcode project does not define target "Runner" which is needed by Flutter tooling.'); - globals.printError('Open Xcode to fix the problem:'); - globals.printError(' open ios/Runner.xcworkspace'); - return XcodeBuildResult(success: false); - } final String scheme = projectInfo.schemeFor(buildInfo); if (scheme == null) { globals.printError(''); @@ -180,7 +174,8 @@ autoSigningConfigs = await getCodeSigningIdentityDevelopmentTeam( iosApp: app, processManager: globals.processManager, - logger: globals.logger + logger: globals.logger, + buildInfo: buildInfo, ); } @@ -229,7 +224,10 @@ } // Check if the project contains a watchOS companion app. - final bool hasWatchCompanion = await app.project.containsWatchCompanion(projectInfo.targets); + final bool hasWatchCompanion = await app.project.containsWatchCompanion( + projectInfo.targets, + buildInfo, + ); if (hasWatchCompanion) { // The -sdk argument has to be omitted if a watchOS companion app exists. // Otherwise the build will fail as WatchKit dependencies cannot be build using the iOS SDK.
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart index 1786508..b2fab77 100644 --- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart +++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -309,9 +309,12 @@ /// Asynchronously retrieve xcode build settings. This one is preferred for /// new call-sites. + /// + /// If [scheme] is null, xcodebuild will return build settings for the first discovered + /// target (by default this is Runner). Future<Map<String, String>> getBuildSettings( - String projectPath, - String target, { + String projectPath, { + String scheme, Duration timeout = const Duration(minutes: 1), }) async { final Status status = Status.withSpinner( @@ -324,8 +327,8 @@ _executable, '-project', _fileSystem.path.absolute(projectPath), - '-target', - target, + if (scheme != null) + ...<String>['-scheme', scheme], '-showBuildSettings', ...environmentVariablesAsXcodeBuildSettings(_platform) ]; @@ -465,7 +468,6 @@ final List<String> buildConfigurations; final List<String> schemes; - bool get definesCustomTargets => !(targets.contains('Runner') && targets.length == 1); bool get definesCustomSchemes => !(schemes.contains('Runner') && schemes.length == 1); bool get definesCustomBuildConfigurations { return !(buildConfigurations.contains('Debug') && @@ -475,7 +477,7 @@ /// The expected scheme for [buildInfo]. static String expectedSchemeFor(BuildInfo buildInfo) { - return toTitleCase(buildInfo.flavor ?? 'runner'); + return toTitleCase(buildInfo?.flavor ?? 'runner'); } /// The expected build configuration for [buildInfo] and [scheme].
diff --git a/packages/flutter_tools/lib/src/macos/cocoapods.dart b/packages/flutter_tools/lib/src/macos/cocoapods.dart index c46a096..2960019 100644 --- a/packages/flutter_tools/lib/src/macos/cocoapods.dart +++ b/packages/flutter_tools/lib/src/macos/cocoapods.dart
@@ -267,7 +267,6 @@ } else { final bool isSwift = (await _xcodeProjectInterpreter.getBuildSettings( runnerProject.path, - 'Runner', )).containsKey('SWIFT_VERSION'); podfileTemplateName = isSwift ? 'Podfile-ios-swift' : 'Podfile-ios-objc'; }
diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart index 77cd014..8ef4656 100644 --- a/packages/flutter_tools/lib/src/project.dart +++ b/packages/flutter_tools/lib/src/project.dart
@@ -102,11 +102,14 @@ /// Gradle group ID. Future<Set<String>> get organizationNames async { final List<String> candidates = <String>[ - await ios.productBundleIdentifier, + // Don't require iOS build info, this method is only + // used during create as best-effort, use the + // default target bundle identifier. + await ios.productBundleIdentifier(null), android.applicationId, android.group, example.android.applicationId, - await example.ios.productBundleIdentifier, + await example.ios.productBundleIdentifier(null), ]; return Set<String>.of(candidates .map<String>(_organizationNameFromPackageName) @@ -411,11 +414,11 @@ /// The product bundle identifier of the host app, or null if not set or if /// iOS tooling needed to read it is not installed. - Future<String> get productBundleIdentifier async => - _productBundleIdentifier ??= await _parseProductBundleIdentifier(); + Future<String> productBundleIdentifier(BuildInfo buildInfo) async => + _productBundleIdentifier ??= await _parseProductBundleIdentifier(buildInfo); String _productBundleIdentifier; - Future<String> _parseProductBundleIdentifier() async { + Future<String> _parseProductBundleIdentifier(BuildInfo buildInfo) async { String fromPlist; final File defaultInfoPlist = defaultHostInfoPlist; // Users can change the location of the Info.plist. @@ -434,7 +437,7 @@ return fromPlist; } } - final Map<String, String> allBuildSettings = await buildSettings; + final Map<String, String> allBuildSettings = await buildSettingsForBuildInfo(buildInfo); if (allBuildSettings != null) { if (fromPlist != null) { // Perform variable substitution using build settings. @@ -458,18 +461,18 @@ } /// The bundle name of the host app, `My App.app`. - Future<String> get hostAppBundleName async => - _hostAppBundleName ??= await _parseHostAppBundleName(); + Future<String> hostAppBundleName(BuildInfo buildInfo) async => + _hostAppBundleName ??= await _parseHostAppBundleName(buildInfo); String _hostAppBundleName; - Future<String> _parseHostAppBundleName() async { + Future<String> _parseHostAppBundleName(BuildInfo buildInfo) async { // The product name and bundle name are derived from the display name, which the user // is instructed to change in Xcode as part of deploying to the App Store. // https://flutter.dev/docs/deployment/ios#review-xcode-project-settings // The only source of truth for the name is Xcode's interpretation of the build settings. String productName; if (globals.xcodeProjectInterpreter.isInstalled) { - final Map<String, String> xcodeBuildSettings = await buildSettings; + final Map<String, String> xcodeBuildSettings = await buildSettingsForBuildInfo(buildInfo); if (xcodeBuildSettings != null) { productName = xcodeBuildSettings['FULL_PRODUCT_NAME']; } @@ -483,17 +486,20 @@ /// The build settings for the host app of this project, as a detached map. /// /// Returns null, if iOS tooling is unavailable. - Future<Map<String, String>> get buildSettings async => - _buildSettings ??= await _xcodeProjectBuildSettings(); - Map<String, String> _buildSettings; + Future<Map<String, String>> buildSettingsForBuildInfo(BuildInfo buildInfo) async { + _buildSettingsByScheme ??= <String, Map<String, String>>{}; + final String scheme = xcode.XcodeProjectInfo.expectedSchemeFor(buildInfo); + return _buildSettingsByScheme[scheme] ??= await _xcodeProjectBuildSettings(scheme); + } + Map<String, Map<String, String>> _buildSettingsByScheme; - Future<Map<String, String>> _xcodeProjectBuildSettings() async { + Future<Map<String, String>> _xcodeProjectBuildSettings(String scheme) async { if (!globals.xcodeProjectInterpreter.isInstalled) { return null; } final Map<String, String> buildSettings = await globals.xcodeProjectInterpreter.getBuildSettings( xcodeProject.path, - _hostAppProjectName, + scheme: scheme, ); if (buildSettings != null && buildSettings.isNotEmpty) { // No timeouts, flakes, or errors. @@ -511,8 +517,8 @@ } /// Check if one the [targets] of the project is a watchOS companion app target. - Future<bool> containsWatchCompanion(List<String> targets) async { - final String bundleIdentifier = await productBundleIdentifier; + Future<bool> containsWatchCompanion(List<String> targets, BuildInfo buildInfo) async { + final String bundleIdentifier = await productBundleIdentifier(buildInfo); // A bundle identifier is required for a companion app. if (bundleIdentifier == null) { return false;
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index d9d044d..40d6311 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -469,6 +469,7 @@ final TargetPlatform targetPlatform = await device.targetPlatform; package = await ApplicationPackageFactory.instance.getPackageForPlatform( targetPlatform, + buildInfo: hotRunner.debuggingOptions.buildInfo, applicationBinary: hotRunner.applicationBinary, ); @@ -524,6 +525,7 @@ final TargetPlatform targetPlatform = await device.targetPlatform; package = await ApplicationPackageFactory.instance.getPackageForPlatform( targetPlatform, + buildInfo: coldRunner.debuggingOptions.buildInfo, applicationBinary: coldRunner.applicationBinary, );