Support for app flavors in flutter tooling, #11676 retake (#11734)

diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 87c9f15..3885332 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -220,7 +220,7 @@
 
 Future<XcodeBuildResult> buildXcodeProject({
   BuildableIOSApp app,
-  BuildMode mode,
+  BuildInfo buildInfo,
   String target: flx.defaultMainPath,
   bool buildForDevice,
   bool codesign: true,
@@ -234,6 +234,35 @@
     return new XcodeBuildResult(success: false);
   }
 
+  final XcodeProjectInfo projectInfo = new XcodeProjectInfo.fromProjectSync(app.appDirectory);
+  if (!projectInfo.targets.contains('Runner')) {
+    printError('The Xcode project does not define target "Runner" which is needed by Flutter tooling.');
+    printError('Open Xcode to fix the problem:');
+    printError('  open ios/Runner.xcworkspace');
+    return new XcodeBuildResult(success: false);
+  }
+  final String scheme = projectInfo.schemeFor(buildInfo);
+  if (scheme == null) {
+    printError('');
+    if (projectInfo.definesCustomSchemes) {
+      printError('The Xcode project defines schemes: ${projectInfo.schemes.join(', ')}');
+      printError('You must specify a --flavor option to select one of them.');
+    } else {
+      printError('The Xcode project does not define custom schemes.');
+      printError('You cannot use the --flavor option.');
+    }
+    return new XcodeBuildResult(success: false);
+  }
+  final String configuration = projectInfo.buildConfigurationFor(buildInfo, scheme);
+  if (configuration == null) {
+    printError('');
+    printError('The Xcode project defines build configurations: ${projectInfo.buildConfigurations.join(', ')}');
+    printError('Flutter expects a build configuration named ${XcodeProjectInfo.expectedBuildConfigurationFor(buildInfo, scheme)} or similar.');
+    printError('Open Xcode to fix the problem:');
+    printError('  open ios/Runner.xcworkspace');
+    return new XcodeBuildResult(success: false);
+  }
+
   String developmentTeam;
   if (codesign && buildForDevice)
     developmentTeam = await getCodeSigningIdentityDevelopmentTeam(iosApp: app, usesTerminalUi: usesTerminalUi);
@@ -247,13 +276,13 @@
   if (hasFlutterPlugins)
     await cocoaPods.processPods(
       appIosDir: appDirectory,
-      iosEngineDir: flutterFrameworkDir(mode),
+      iosEngineDir: flutterFrameworkDir(buildInfo.mode),
       isSwift: app.isSwift,
     );
 
   updateXcodeGeneratedProperties(
     projectPath: fs.currentDirectory.path,
-    mode: mode,
+    buildInfo: buildInfo,
     target: target,
     hasPlugins: hasFlutterPlugins
   );
@@ -264,7 +293,8 @@
     'xcodebuild',
     'clean',
     'build',
-    '-configuration', 'Release',
+    '-configuration', configuration,
+    '-scheme', scheme,
     'ONLY_ACTIVE_ARCH=YES',
   ];
 
@@ -276,7 +306,6 @@
     if (fs.path.extension(entity.path) == '.xcworkspace') {
       commands.addAll(<String>[
         '-workspace', fs.path.basename(entity.path),
-        '-scheme', fs.path.basenameWithoutExtension(entity.path),
         "BUILD_DIR=${fs.path.absolute(getIosBuildDirectory())}",
       ]);
       break;
@@ -306,7 +335,6 @@
     allowReentrantFlutter: true
   );
   status.stop();
-
   if (result.exitCode != 0) {
     printStatus('Failed to build iOS app');
     if (result.stderr.isNotEmpty) {
@@ -328,13 +356,18 @@
       ),
     );
   } else {
-    // Look for 'clean build/Release-iphoneos/Runner.app'.
-    final RegExp regexp = new RegExp(r' clean (\S*\.app)$', multiLine: true);
+    // Look for 'clean build/<configuration>-<sdk>/Runner.app'.
+    final RegExp regexp = new RegExp(r' clean (.*\.app)$', multiLine: true);
     final Match match = regexp.firstMatch(result.stdout);
     String outputDir;
-    if (match != null)
-      outputDir = fs.path.join(app.appDirectory, match.group(1));
-    return new XcodeBuildResult(success:true, output: outputDir);
+    if (match != null) {
+      final String actualOutputDir = match.group(1).replaceAll('\\ ', ' ');
+      // Copy app folder to a place where other tools can find it without knowing
+      // the BuildInfo.
+      outputDir = actualOutputDir.replaceFirst('/$configuration-', '/');
+      copyDirectorySync(fs.directory(actualOutputDir), fs.directory(outputDir));
+    }
+    return new XcodeBuildResult(success: true, output: outputDir);
   }
 }
 
@@ -356,7 +389,9 @@
     printError(noDevelopmentTeamInstruction, emphasis: true);
     return;
   }
-  if (app.id?.contains('com.yourcompany') ?? false) {
+  if (result.xcodeBuildExecution != null &&
+      result.xcodeBuildExecution.buildForPhysicalDevice &&
+      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:");