Pass environment variables through to xcodebuild (#43553)
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart index e29c1df..d872f19 100644 --- a/packages/flutter_tools/lib/src/ios/mac.dart +++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -464,6 +464,7 @@ // e.g. `flutter build bundle`. buildCommands.add('FLUTTER_SUPPRESS_ANALYTICS=true'); buildCommands.add('COMPILER_INDEX_STORE_ENABLE=NO'); + buildCommands.addAll(environmentVariablesAsXcodeBuildSettings()); final Stopwatch sw = Stopwatch()..start(); initialBuildStatus = logger.startProgress('Running Xcode build...', timeout: timeoutConfiguration.fastOperation);
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart index 9244719..40bdd7d 100644 --- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart +++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -293,9 +293,10 @@ '-target', target, '-showBuildSettings', + ...environmentVariablesAsXcodeBuildSettings() ]; try { - // showBuildSettings is reported to ocassionally timeout. Here, we give it + // showBuildSettings is reported to occasionally timeout. Here, we give it // a lot of wiggle room (locally on Flutter Gallery, this takes ~1s). // When there is a timeout, we retry once. final RunResult result = await processUtils.run( @@ -329,6 +330,7 @@ scheme, '-quiet', 'clean', + ...environmentVariablesAsXcodeBuildSettings() ], workingDirectory: fs.currentDirectory.path); } @@ -354,6 +356,21 @@ } } +/// Environment variables prefixed by FLUTTER_XCODE_ will be passed as build configurations to xcodebuild. +/// This allows developers to pass arbitrary build settings in without the tool needing to make a flag +/// for or be aware of each one. This could be used to set code signing build settings in a CI +/// environment without requiring settings changes in the Xcode project. +List<String> environmentVariablesAsXcodeBuildSettings() { + const String xcodeBuildSettingPrefix = 'FLUTTER_XCODE_'; + return platform.environment.entries.where((MapEntry<String, String> mapEntry) { + return mapEntry.key.startsWith(xcodeBuildSettingPrefix); + }).expand<String>((MapEntry<String, String> mapEntry) { + // Remove FLUTTER_XCODE_ prefix from the environment variable to get the build setting. + final String trimmedBuildSettingKey = mapEntry.key.substring(xcodeBuildSettingPrefix.length); + return <String>['$trimmedBuildSettingKey=${mapEntry.value}']; + }).toList(); +} + Map<String, String> parseXcodeBuildSettings(String showBuildSettingsOutput) { final Map<String, String> settings = <String, String>{}; for (Match match in showBuildSettingsOutput.split('\n').map<Match>(_settingExpr.firstMatch)) {
diff --git a/packages/flutter_tools/lib/src/macos/build_macos.dart b/packages/flutter_tools/lib/src/macos/build_macos.dart index 69571bc..d9b16f3 100644 --- a/packages/flutter_tools/lib/src/macos/build_macos.dart +++ b/packages/flutter_tools/lib/src/macos/build_macos.dart
@@ -79,6 +79,7 @@ 'OBJROOT=${fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Intermediates.noindex')}', 'SYMROOT=${fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Products')}', 'COMPILER_INDEX_STORE_ENABLE=NO', + ...environmentVariablesAsXcodeBuildSettings() ], trace: true); } finally { status.cancel();