Skip to content

Conversation

@abdelaziz-mahdy
Copy link
Contributor

@abdelaziz-mahdy abdelaziz-mahdy commented Oct 13, 2025

Passes EXCLUDED_ARCHS from Xcode project build settings to the xcodebuild command, fixing macOS builds when
dependencies don't support all architectures.

Problem

Release builds for macOS create universal binaries (arm64 + x86_64) by default. This causes build failures when
using native dependencies that only provide binaries for a single architecture. While developers can set
EXCLUDED_ARCHS in their Xcode project's xcconfig files, Swift Package Manager dependencies don't respect this
project-level setting.

Fixes: #176605

Solution

Instead of adding a CLI flag, pass EXCLUDED_ARCHS from the Xcode project's build settings directly to xcodebuild. This ensures Swift Package Manager dependencies respect architecture exclusions set in the project configuration.

How it works:
When macos/Runner/Configs/Release.xcconfig contains:

EXCLUDED_ARCHS = x86_64

The build command now includes EXCLUDED_ARCHS=x86_64, creating an arm64-only binary.

Usage

1. Edit your xcconfig file (e.g., macos/Runner/Configs/Release.xcconfig):

#include "../../Flutter/Flutter-Release.xcconfig"
#include "Warnings.xcconfig"

// Exclude x86_64 for dependencies that only support Apple Silicon
EXCLUDED_ARCHS = x86_64

2. Build normally:

flutter build macos --release

Without exclusions (default behavior):

# Creates universal binary (arm64 + x86_64)
flutter build macos --release

Implementation

  • Modified buildMacOS() to retrieve EXCLUDED_ARCHS from Xcode project build settings
  • Pass EXCLUDED_ARCHS to xcodebuild command when set and non-empty
  • Removed unused activeArch parameter
  • Added inline documentation explaining the SPM compatibility fix

Testing

Manual verification:

  • ✅ Built ExecuTorch Flutter example with EXCLUDED_ARCHS = x86_64: arm64-only binary (518.6MB)
  • ✅ Built without exclusions: universal binary (existing behavior)
  • ✅ Verified architecture with lipo -info: arm64-only when excluded

Unit tests:

  • ✅ Added test: "Passes EXCLUDED_ARCHS from Xcode project to xcodebuild command"
  • ✅ Added test: "Does not pass EXCLUDED_ARCHS when not set in Xcode project"
  • ✅ All 25 macOS build tests passing

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@abdelaziz-mahdy abdelaziz-mahdy requested a review from a team as a code owner October 13, 2025 18:56
@github-actions github-actions bot added tool Affects the "flutter" command-line tool. See also t: labels. a: desktop Running on desktop team-ios Owned by iOS platform team labels Oct 13, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a --macos-arch flag to the flutter build macos command, allowing developers to specify a target architecture (arm64 or x86_64) for macOS builds. This is implemented by adding a new command-line option, parsing it, and passing the corresponding architecture information to xcodebuild via the -destination and ARCHS build settings. The changes also include new tests to verify this functionality. The implementation looks solid, but I have a suggestion to improve the test coverage and maintainability.

@vashworth
Copy link
Contributor

If we can avoid adding any new flags, that would be preferred. Did you try setting the destination to platform=macOS to see if that fixed it?

@abdelaziz-mahdy
Copy link
Contributor Author

If we can avoid adding any new flags, that would be preferred. Did you try setting the destination to platform=macOS to see if that fixed it?

I tested platform=macOS,arch=$arch as suggested. It works, but breaks backward compatibility by forcing all release builds to single-architecture only.

The problem:

  • Disables universal binary creation by default
  • Users wanting both architectures must build separately on Intel and Apple Silicon, then manually combine with lipo
  • No way to opt-out for projects without architecture constraints

Why the flag is better:

  • Preserves current behavior (universal binaries by default)
  • Provides explicit opt-in for architecture-limited dependencies: --macos-arch=arm64
  • Clear, documentable solution: "Use --macos-arch if your dependencies don't support both architectures"

The flag solves the edge case without breaking the common case.

@vashworth
Copy link
Contributor

I tested platform=macOS,arch=$arch as suggested.

Try without an arch, just platform=macOS

@abdelaziz-mahdy
Copy link
Contributor Author

I tested platform=macOS,arch=$arch as suggested.

Try without an arch, just platform=macOS

I tested just platform=macOS (without arch) as suggested. It still fails with the same error because xcodebuild
treats platform=macOS as ambiguous and attempts to build for both architectures.

The warning shows:
xcodebuild: WARNING: Using the first of multiple matching destinations:
{ platform:macOS, arch:arm64, id:00006020-001820E60A33C01E, name:My Mac }
{ platform:macOS, arch:x86_64, id:00006020-001820E60A33C01E, name:My Mac }

Despite picking arm64 first, xcodebuild still tries to compile for x86_64, causing the build to fail. The
destination alone isn't sufficient—we must also specify ARCHS build settings to explicitly control which
architectures to build.

The --macos-arch flag approach works because it sets both the destination (platform=macOS,arch=arm64) and the
build settings (ARCHS=arm64, ONLY_ACTIVE_ARCH=YES), giving explicit control without breaking the default universal
binary behavior.

@vashworth
Copy link
Contributor

I tested platform=macOS,arch=$arch as suggested.

Try without an arch, just platform=macOS

I tested just platform=macOS (without arch) as suggested. It still fails with the same error because xcodebuild treats platform=macOS as ambiguous and attempts to build for both architectures.

The warning shows: xcodebuild: WARNING: Using the first of multiple matching destinations: { platform:macOS, arch:arm64, id:00006020-001820E60A33C01E, name:My Mac } { platform:macOS, arch:x86_64, id:00006020-001820E60A33C01E, name:My Mac }

Despite picking arm64 first, xcodebuild still tries to compile for x86_64, causing the build to fail. The destination alone isn't sufficient—we must also specify ARCHS build settings to explicitly control which architectures to build.

The --macos-arch flag approach works because it sets both the destination (platform=macOS,arch=arm64) and the build settings (ARCHS=arm64, ONLY_ACTIVE_ARCH=YES), giving explicit control without breaking the default universal binary behavior.

Okay thank you for trying! I see now that it's not that the app binary is still compiling x86_64. It's SwiftPM and its dependencies

if (activeArch != null) ...<String>[
'ONLY_ACTIVE_ARCH=${onlyActiveArch ? 'YES' : 'NO'}',
'ARCHS=${activeArch.name}',
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay so I played with this a little bit and I think a cleaner solution would be to pass EXCLUDED_ARCHS to the xcodebuild command so that developers can exclude the arch through Xcode. It seems like Swift Package Manager doesn't respect the EXCLUDED_ARCHS in the project unless it's sent with the command directly.

+ final String? excludedArches = buildSettings['EXCLUDED_ARCHS'];

  try {
    result = await globals.processUtils.stream(
      <String>[
        '/usr/bin/env',
        'xcrun',
        'xcodebuild',
        '-workspace',
        xcodeWorkspace.path,
        '-configuration',
        configuration,
        '-scheme',
        scheme,
        '-derivedDataPath',
        flutterBuildDir.absolute.path,
        '-destination',
        destination,
        'OBJROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Intermediates.noindex')}',
        'SYMROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Products')}',
        if (verboseLogging) 'VERBOSE_SCRIPT_LOGGING=YES' else '-quiet',
        'COMPILER_INDEX_STORE_ENABLE=NO',
        if (disabledSandboxEntitlementFile != null)
          'CODE_SIGN_ENTITLEMENTS=${disabledSandboxEntitlementFile.path}',
+        if (excludedArches != null && excludedArches.trim().isNotEmpty)
+          'EXCLUDED_ARCHS=$excludedArches',
        ...environmentVariablesAsXcodeBuildSettings(globals.platform),
      ],

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can give it a try, but why this instead of the command line arg? isnt that going to be a commandline arg too?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can give it a try, but why this instead of the command line arg? isnt that going to be a commandline arg too?

No it wouldn't be a command line arg, the buildSettings['EXCLUDED_ARCHS'] would come from the Xcode project's build settings. No flag would be passed into the CLI

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, fixes my issue, updated PR title and description.

@abdelaziz-mahdy abdelaziz-mahdy changed the title Add macOS architecture option to build command and update tests Pass EXCLUDED_ARCHS from Xcode project to xcodebuild for macOS builds Nov 15, 2025
Copy link
Contributor

@vashworth vashworth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you for the changes!

@vashworth vashworth requested a review from bkonyi November 19, 2025 16:45
@vashworth
Copy link
Contributor

@bkonyi Can you do a second review?

Copy link
Contributor

@bkonyi bkonyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bkonyi bkonyi added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 19, 2025
@auto-submit auto-submit bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 19, 2025
@auto-submit
Copy link
Contributor

auto-submit bot commented Nov 19, 2025

autosubmit label was removed for flutter/flutter/176948, because - The status or check suite Linux analyze has failed. Please fix the issues identified (or deflake) before re-applying this label.

@vashworth
Copy link
Contributor

Test Linux analyze is failing due to build_macos_test.dart needs to be formatted:

 Found 1 Dart file which was formatted incorrectly.
 To fix, run `dart format packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart` or:
 git apply <<DONE
 diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart
 index 22e12e5f036..00000000000 100644
 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart
 +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart
 @@ -42,9 +42,7 @@ class FakeXcodeProjectInterpreterWithProfile extends FakeXcodeProjectInterpreter
  }
  
  class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInterpreter {
 -  FakeXcodeProjectInterpreterWithBuildSettings({
 -    this.overrides = const <String, String>{},
 -  });
 +  FakeXcodeProjectInterpreterWithBuildSettings({this.overrides = const <String, String>{}});
  
    final Map<String, String> overrides;
  
 @@ -61,10 +59,7 @@ class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInter
      XcodeProjectBuildContext? buildContext,
      Duration timeout = const Duration(minutes: 1),
    }) async {
 -    return <String, String>{
 -      ...overrides,
 -      'PRODUCT_BUNDLE_IDENTIFIER': 'com.example.test',
 -    };
 +    return <String, String>{...overrides, 'PRODUCT_BUNDLE_IDENTIFIER': 'com.example.test'};
    }
  }
  
 @@ -1066,9 +1061,9 @@ STDERR STUFF
          osUtils: FakeOperatingSystemUtils(),
        );
  
 -      await createTestCommandRunner(command).run(
 -        <String>['build', 'macos', '--release', '--no-pub'],
 -      );
 +      await createTestCommandRunner(
 +        command,
 +      ).run(<String>['build', 'macos', '--release', '--no-pub']);
  
        expect(fakeProcessManager, hasNoRemainingExpectations);
      },
 @@ -1110,9 +1105,9 @@ STDERR STUFF
          osUtils: FakeOperatingSystemUtils(),
        );
  
 -      await createTestCommandRunner(command).run(
 -        <String>['build', 'macos', '--release', '--no-pub'],
 -      );
 +      await createTestCommandRunner(
 +        command,
 +      ).run(<String>['build', 'macos', '--release', '--no-pub']);
  
        expect(fakeProcessManager, hasNoRemainingExpectations);
      },
 @@ -1129,3 +1124,4 @@ STDERR STUFF
      },
    );
  }
 DONE

@abdelaziz-mahdy
Copy link
Contributor Author

I kept trying to find what was the issue and couldn't, can you show me how to figure it so I know in the future, and will fix it as soon I have access to the computer

@vashworth
Copy link
Contributor

I kept trying to find what was the issue and couldn't, can you show me how to figure it so I know in the future, and will fix it as soon I have access to the computer

  1. First click on the failing test, Linux analyze in this case

  2. Click on "View more details on flutter-dashboard" at the bottom

Screenshot 2025-11-21 at 2 26 30 PM
  1. Select the stdout of the step that failed
Screenshot 2025-11-21 at 2 28 35 PM
  1. Scan the logs for failures

In this case, it says you need to run dart format packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart

@abdelaziz-mahdy
Copy link
Contributor Author

I kept trying to find what was the issue and couldn't, can you show me how to figure it so I know in the future, and will fix it as soon I have access to the computer

  1. First click on the failing test, Linux analyze in this case
  2. Click on "View more details on flutter-dashboard" at the bottom
Screenshot 2025-11-21 at 2 26 30 PM 3. Select the `stdout` of the step that failed Screenshot 2025-11-21 at 2 28 35 PM 4. Scan the logs for failures

In this case, it says you need to run dart format packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart

thank you, reformatted, now I can figure the ci/cd easily

@vashworth vashworth added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 24, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Nov 24, 2025
Merged via the queue into flutter:master with commit 1b93620 Nov 24, 2025
141 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 24, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 26, 2025
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Nov 26, 2025
flutter/flutter@3f553f6...7b98d50

2025-11-26 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Fix for win32 embedder failing to send all alt key downs to the flutter app (#179097)" (flutter/flutter#179136)
2025-11-26 [email protected] Fix for win32 embedder failing to send all alt key downs to the flutter app (flutter/flutter#179097)
2025-11-26 [email protected] Modernize framework lints (flutter/flutter#179089)
2025-11-25 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Add framework-side hitTestBehavior support to Semantics (#178817)" (flutter/flutter#179100)
2025-11-25 [email protected] Add framework-side hitTestBehavior support to Semantics (flutter/flutter#178817)
2025-11-25 [email protected] Roll Packages from e019cf9 to cc3dca6 (1 revision) (flutter/flutter#179081)
2025-11-25 [email protected] Add tooltip windows to the windowing API alongside the window positioning logic (flutter/flutter#177404)
2025-11-25 [email protected] FlutterWindowsView::SendWindowMetrics now reliably sends the display_id (flutter/flutter#179053)
2025-11-25 [email protected] Remove semantics geometry shortcircuit (flutter/flutter#178680)
2025-11-25 [email protected] Add an assert message when OverlayEntry.remove is called twice (flutter/flutter#178163)
2025-11-25 [email protected] Roll Fuchsia Linux SDK from pOO9Jl9HTLsEmks6y... to nzuAxCJGeJbkZCTkr... (flutter/flutter#179066)
2025-11-25 [email protected] Dynamically set MinimumOSVersion in App.framework (flutter/flutter#178253)
2025-11-25 [email protected] Roll Skia from d83c30b090f4 to 925c311f4b37 (2 revisions) (flutter/flutter#179060)
2025-11-25 [email protected] Marks Linux build_android_host_app_with_module_aar to be unflaky (flutter/flutter#174864)
2025-11-25 [email protected] Marks Linux_mokey complex_layout__start_up to be unflaky (flutter/flutter#174865)
2025-11-25 [email protected] Manual Dart SDK roll to 3.11.0-169.0.dev (flutter/flutter#179054)
2025-11-25 [email protected] Bump Dart to 3.9 (flutter/flutter#179041)
2025-11-25 [email protected] Roll Skia from e298c2f93ebf to d83c30b090f4 (2 revisions) (flutter/flutter#179058)
2025-11-24 [email protected] updated licenses_cpp readme (flutter/flutter#178874)
2025-11-24 [email protected] Roll Skia from 43d2020be565 to e298c2f93ebf (5 revisions) (flutter/flutter#179046)
2025-11-24 [email protected] Refactor `_isLabel` method in `stepper.dart` to use `any` for better readablity (flutter/flutter#178909)
2025-11-24 49699333+dependabot[bot]@users.noreply.github.com Bump actions/checkout from 5 to 6 in the all-github-actions group (flutter/flutter#179049)
2025-11-24 [email protected] Disposes test restoration manager when accessed by bindings (flutter/flutter#176519)
2025-11-24 [email protected] [ Widget Preview ] Always generate scaffold under `$TMP` (flutter/flutter#179039)
2025-11-24 [email protected] Roll Packages from e67b6be to e019cf9 (9 revisions) (flutter/flutter#179035)
2025-11-24 [email protected] Update CHANGELOG.md for Flutter 3.38.3 (flutter/flutter#178935)
2025-11-24 [email protected] Remove unnecessary `String.valueOf` in `SettingsChannel.java‎` (flutter/flutter#178590)
2025-11-24 [email protected] Roll pub manually, pick up flutter_lints in examples/api (flutter/flutter#179030)
2025-11-24 [email protected] Roll Dart SDK from 24cc9a740bd3 to afca43095efa (1 revision) (flutter/flutter#179019)
2025-11-24 [email protected] Pass EXCLUDED_ARCHS from Xcode project to xcodebuild for macOS builds (flutter/flutter#176948)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
mboetger pushed a commit to mboetger/flutter that referenced this pull request Dec 2, 2025
…flutter#176948)

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->


Passes `EXCLUDED_ARCHS` from Xcode project build settings to the
xcodebuild command, fixing macOS builds when
  dependencies don't support all architectures.

  ### Problem
Release builds for macOS create universal binaries (arm64 + x86_64) by
default. This causes build failures when
using native dependencies that only provide binaries for a single
architecture. While developers can set
`EXCLUDED_ARCHS` in their Xcode project's xcconfig files, Swift Package
Manager dependencies don't respect this
  project-level setting.
  
  **Fixes**: flutter#176605

  ## Solution

Instead of adding a CLI flag, pass `EXCLUDED_ARCHS` from the Xcode
project's build settings directly to xcodebuild. This ensures Swift
Package Manager dependencies respect architecture exclusions set in the
project configuration.

**How it works:**
When `macos/Runner/Configs/Release.xcconfig` contains:
```xcconfig
EXCLUDED_ARCHS = x86_64
```

The build command now includes `EXCLUDED_ARCHS=x86_64`, creating an
arm64-only binary.

## Usage

**1. Edit your xcconfig file** (e.g.,
`macos/Runner/Configs/Release.xcconfig`):
```xcconfig
#include "../../Flutter/Flutter-Release.xcconfig"
#include "Warnings.xcconfig"

// Exclude x86_64 for dependencies that only support Apple Silicon
EXCLUDED_ARCHS = x86_64
```

**2. Build normally:**
```bash
flutter build macos --release
```

**Without exclusions (default behavior):**
```bash
# Creates universal binary (arm64 + x86_64)
flutter build macos --release
```

## Implementation

- Modified `buildMacOS()` to retrieve `EXCLUDED_ARCHS` from Xcode
project build settings
- Pass `EXCLUDED_ARCHS` to xcodebuild command when set and non-empty
- Removed unused `activeArch` parameter
- Added inline documentation explaining the SPM compatibility fix

## Testing

**Manual verification:**
- ✅ Built ExecuTorch Flutter example with `EXCLUDED_ARCHS = x86_64`:
arm64-only binary (518.6MB)
- ✅ Built without exclusions: universal binary (existing behavior)
- ✅ Verified architecture with `lipo -info`: arm64-only when excluded

**Unit tests:**
- ✅ Added test: "Passes EXCLUDED_ARCHS from Xcode project to xcodebuild
command"
- ✅ Added test: "Does not pass EXCLUDED_ARCHS when not set in Xcode
project"
- ✅ All 25 macOS build tests passing


*If you had to change anything in the [flutter/tests] repo, include a
link to the migration guide as per the [breaking change policy].*

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md

---------

Co-authored-by: Victoria Ashworth <[email protected]>
reidbaker pushed a commit to AbdeMohlbi/flutter that referenced this pull request Dec 10, 2025
…flutter#176948)

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->


Passes `EXCLUDED_ARCHS` from Xcode project build settings to the
xcodebuild command, fixing macOS builds when
  dependencies don't support all architectures.

  ### Problem
Release builds for macOS create universal binaries (arm64 + x86_64) by
default. This causes build failures when
using native dependencies that only provide binaries for a single
architecture. While developers can set
`EXCLUDED_ARCHS` in their Xcode project's xcconfig files, Swift Package
Manager dependencies don't respect this
  project-level setting.
  
  **Fixes**: flutter#176605

  ## Solution

Instead of adding a CLI flag, pass `EXCLUDED_ARCHS` from the Xcode
project's build settings directly to xcodebuild. This ensures Swift
Package Manager dependencies respect architecture exclusions set in the
project configuration.

**How it works:**
When `macos/Runner/Configs/Release.xcconfig` contains:
```xcconfig
EXCLUDED_ARCHS = x86_64
```

The build command now includes `EXCLUDED_ARCHS=x86_64`, creating an
arm64-only binary.

## Usage

**1. Edit your xcconfig file** (e.g.,
`macos/Runner/Configs/Release.xcconfig`):
```xcconfig
#include "../../Flutter/Flutter-Release.xcconfig"
#include "Warnings.xcconfig"

// Exclude x86_64 for dependencies that only support Apple Silicon
EXCLUDED_ARCHS = x86_64
```

**2. Build normally:**
```bash
flutter build macos --release
```

**Without exclusions (default behavior):**
```bash
# Creates universal binary (arm64 + x86_64)
flutter build macos --release
```

## Implementation

- Modified `buildMacOS()` to retrieve `EXCLUDED_ARCHS` from Xcode
project build settings
- Pass `EXCLUDED_ARCHS` to xcodebuild command when set and non-empty
- Removed unused `activeArch` parameter
- Added inline documentation explaining the SPM compatibility fix

## Testing

**Manual verification:**
- ✅ Built ExecuTorch Flutter example with `EXCLUDED_ARCHS = x86_64`:
arm64-only binary (518.6MB)
- ✅ Built without exclusions: universal binary (existing behavior)
- ✅ Verified architecture with `lipo -info`: arm64-only when excluded

**Unit tests:**
- ✅ Added test: "Passes EXCLUDED_ARCHS from Xcode project to xcodebuild
command"
- ✅ Added test: "Does not pass EXCLUDED_ARCHS when not set in Xcode
project"
- ✅ All 25 macOS build tests passing


*If you had to change anything in the [flutter/tests] repo, include a
link to the migration guide as per the [breaking change policy].*

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md

---------

Co-authored-by: Victoria Ashworth <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop team-ios Owned by iOS platform team tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants