Harden macOS build use of Xcode project getInfo (#40375)

- Makes build_macos.dart handle the case where there is only one Xcode
  project in the macos/ directory, but it's not called Runner.xcodeproj
- Makes getInfo throw a tool exit when trying to get project info and it
  can't find a project, since that is a configuration error by the user
  rather than a tool bug.
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index 181905f..8723faf 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -7,6 +7,7 @@
 import 'package:meta/meta.dart';
 
 import '../artifacts.dart';
+import '../base/common.dart';
 import '../base/context.dart';
 import '../base/file_system.dart';
 import '../base/io.dart';
@@ -331,6 +332,10 @@
   }
 
   Future<XcodeProjectInfo> getInfo(String projectPath, {String projectFilename}) async {
+    // The exit code returned by 'xcodebuild -list' when either:
+    // * -project is passed and the given project isn't there, or
+    // * no -project is passed and there isn't a project.
+    const int missingProjectExitCode = 66;
     final RunResult result = await processUtils.run(
       <String>[
         _executable,
@@ -338,8 +343,12 @@
         if (projectFilename != null) ...<String>['-project', projectFilename],
       ],
       throwOnError: true,
+      whiteListFailures: (int c) => c == missingProjectExitCode,
       workingDirectory: projectPath,
     );
+    if (result.exitCode == missingProjectExitCode) {
+      throwToolExit('Unable to get Xcode project information:\n ${result.stderr}');
+    }
     return XcodeProjectInfo.fromXcodeBuildOutput(result.toString());
   }
 }
diff --git a/packages/flutter_tools/lib/src/macos/build_macos.dart b/packages/flutter_tools/lib/src/macos/build_macos.dart
index 0aa94f5..678c14c 100644
--- a/packages/flutter_tools/lib/src/macos/build_macos.dart
+++ b/packages/flutter_tools/lib/src/macos/build_macos.dart
@@ -46,9 +46,13 @@
 
   final Directory xcodeProject = flutterProject.macos.xcodeProject;
 
+  // If the standard project exists, specify it to getInfo to handle the case where there are
+  // other Xcode projects in the macos/ directory. Otherwise pass no name, which will work
+  // regardless of the project name so long as there is exactly one project.
+  final String xcodeProjectName = xcodeProject.existsSync() ? xcodeProject.basename : null;
   final XcodeProjectInfo projectInfo = await xcodeProjectInterpreter.getInfo(
     xcodeProject.parent.path,
-    projectFilename: xcodeProject.basename,
+    projectFilename: xcodeProjectName,
   );
   final String scheme = projectInfo.schemeFor(buildInfo);
   if (scheme == null) {