Skip to content

[ios,macos] Update swiftc.py flags to match swiftc#189174

Merged
cbracken merged 1 commit into
flutter:masterfrom
cbracken:clean-up-swiftc-py
Jul 9, 2026
Merged

[ios,macos] Update swiftc.py flags to match swiftc#189174
cbracken merged 1 commit into
flutter:masterfrom
cbracken:clean-up-swiftc-py

Conversation

@cbracken

@cbracken cbracken commented Jul 9, 2026

Copy link
Copy Markdown
Member

This updates flag names in the swiftc.py build wrapper and GN rules to match underlying swiftc counterparts (-module-name, -import-objc-header, and -target). This eliminates the finer-grained custom flags we had been using for convenience.

This also deduplicates the LLVM target triple mapping and iOS simulator suffix rules into darwin_sdk.gni, so they're shared between default and test configurations.

This is pre-factoring that will simplify downstream compile_commands.json post-processing in an upcoming patch that adds SourceKit LSP support for Swift.

No test changes because the test is the build itself (as well as existing tests).

Issue: #185741

Pre-launch Checklist

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

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

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.

This updates flag names in the swiftc.py build wrapper and GN rules to
match underlying swiftc counterparts (-module-name, -import-objc-header,
and -target). This eliminates the finer-grained custom flags we had been
using for convenience.

This also deduplicates the LLVM target triple mapping and iOS simulator
suffix rules into darwin_sdk.gni, so they're shared between default and
test configurations.

This is pre-factoring that will simplify downstream
compile_commands.json post-processing in an upcoming patch that adds
SourceKit LSP support for Swift.

No test changes because the test is the build itself (as well as
existing tests).

Issue: flutter#185741
@cbracken
cbracken requested a review from a team as a code owner July 9, 2026 07:07
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jul 9, 2026
@flutter-dashboard

Copy link
Copy Markdown

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

@github-actions github-actions Bot added platform-ios iOS applications specifically engine flutter/engine related. See also e: labels. a: desktop Running on desktop team-ios Owned by iOS platform team team-macos Owned by the macOS platform team labels Jul 9, 2026

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

Copy link
Copy Markdown
Contributor

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 refactors the Darwin build configuration and Swift compiler toolchain to use the unified -target triple flag instead of separate --target-cpu, --target-os, --deployment-target, and --use-simulator flags. It also renames --module-name to -module-name and --bridge-header to -import-objc-header in the Swift compiler wrapper. There are no review comments, so I have no feedback to provide.

parser.add_argument('--module-name',
parser.add_argument('-module-name',
required=True,
help='name of the Swift module')

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It would be nice if Apple used double-dash flags like everyone else, but they don't :/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Our code simply relay this to swiftc?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yep!

@stuartmorgan-g

Copy link
Copy Markdown
Contributor

test-exempt: covered by build

#defines = [ "CR_XCODE_VERSION=$xcode_version" ]

_target_triple =
"$darwin_target_arch-$_triplet_os$_deployment_target$darwin_target_sim"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

interesting - this "triple" has 4 components? (the simulator part?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Target triples are these globally unique (but pretty inconsistent!) standard means of identifying target platforms. Ironically they're called target triples but are specified with an optional fourth component: the environment.

From the lldb page linked above:

ARCHITECTURE-VENDOR-OPERATING_SYSTEM
ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT

Makes sense since Xcode ships with separate SDKs for iOS arm64 and simulator arm64 targets.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Discussed offline - this is expected

parser.add_argument('--module-name',
parser.add_argument('-module-name',
required=True,
help='name of the Swift module')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Our code simply relay this to swiftc?

"--const-gather-protocols-file $_const_gather_protocols_file " +
"--depfile-path $depfile --src-dir $_src_dir --gen-dir $_gen_dir " +
"--bridge-header {{bridge_header}} {{include_dirs}} " +
"-import-objc-header {{bridge_header}} {{include_dirs}} " +

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hmmm, the mix usage of - and -- reads a bit ugly here. We may wanna add some comments here to reduce risk of future surprises.

I wonder if it's possible to still use -- and translate it in swiftc.py (replace all -- to -).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Discussed offline -

GN will create the compile command json file based on this command that invokes the swiftc.py, and then we further post-process it in tools/pkg/engine_build_configs/lib/src/build_config_runner.dart because it calls swiftc.py rather than swiftc (so the json would contain swiftc.py). The reason we want to use swiftc's official param name is to simplify the post process script.

default=False,
action='store_true',
help='targeting the simulator')
help='target triple (e.g. "arm64-apple-ios14.0")')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think i need some help understanding the rational behind the change that passes the triplet instead of 3 separate arguments: if we construct the triplets inside swiftc.py, then the triplet constructing logic would still be shared right? Is that better?

@cbracken cbracken Jul 9, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Triples are a standard compiler/toolchain concept. Compilers doesn't really deal in the separate elements ever. They're always concatenated together in this standard form.

Previously, this was the only place in our build toolchain where we were using them, but we also need them for SourceKit LSP pre-processing of compile_commands.json in a patch that depends on this one. That code is written in Dart (since that's where we do compile_commands processing today), and rewriting this in there is another ~50 lines of flags processing and construction logic.

More importantly though, swiftc.py is a super simple wrapper around swiftc, so the more we can make it look identical, the better.

For SourceKit processing, we query the ninja compilation db (ninja -t compdb) which dumps out a bunch of swift.py ... commands. SwiftKit doesn't understand those, so I've added a tweak to our compile_commands.json post-processor called from gn, that rewrites those from swiftc.py to swiftc with the correct swiftc arguments.

This patch is basically prep work to make that super easy rather than manually rewriting it all in Dart.

"--deployment-target",
_deployment_target,
"-target",
_target_triple,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

discussed offline, posting here for future reference: we revert back to passing the triple because we want to use this triple in other places than the swiftc.py.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: could you also revert some other changes I made in https://github.com/flutter/flutter/pull/185712/changes#diff-d57f937ed2d743b17635dd069689072eba124f649f307228915c25d55b19ed62 to let swiftc.py construct the target triple? For example invoke_swift_compiler should take one less argument since target is already in the args dictionary.

@cbracken cbracken Jul 9, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch! Since everyone's headed out the door, I've created a followup patch that does those cleanups internally in this script. Thanks for spotting!

Also thanks for landing #185712! I'm super excited to use more Swift Testing in our code!

@hellohuanlin hellohuanlin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM! Thanks for providing the context!

@cbracken
cbracken added this pull request to the merge queue Jul 9, 2026
Merged via the queue into flutter:master with commit dc2a870 Jul 9, 2026
199 of 200 checks passed
@cbracken
cbracken deleted the clean-up-swiftc-py branch July 9, 2026 23:28
cbracken added a commit to cbracken/flutter that referenced this pull request Jul 10, 2026
In flutter#189174, we migrated back to
using target triples in swiftc.py in order to more closely mirror the
commandline interface to `swiftc` itself.

This is a followup that cleans up some extra function parameters that
are no longer necessary now that we're getting the target triple in
args.

This cleans up a few remaining diffs from the reversion of the target
triple splitting from https://github.com/flutter/flutter/pull/185712/changes#diff-d57f937ed2d743b17635dd069689072eba124f649f307228915c25d55b19ed62.

Issue: flutter#185741
cbracken added a commit to cbracken/flutter that referenced this pull request Jul 10, 2026
In flutter#189174, we migrated back to
using target triples in swiftc.py in order to more closely mirror the
commandline interface to `swiftc` itself.

This is a followup that cleans up some extra function parameters that
are no longer necessary now that we're getting the target triple in
args.

This cleans up a few remaining diffs from the reversion of the target
triple splitting from https://github.com/flutter/flutter/pull/185712/changes#diff-d57f937ed2d743b17635dd069689072eba124f649f307228915c25d55b19ed62.

Issue: flutter#185741
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Jul 10, 2026
…12169)

Manual roll Flutter from 91939cc4db78 to dc2a8703e12b (50 revisions)

Manual roll requested by [email protected]

flutter/flutter@91939cc...dc2a870

2026-07-09 [email protected] [ios,macos] Update swiftc.py flags to match swiftc (flutter/flutter#189174)
2026-07-09 [email protected] [AGP 9] Update Warn Version to AGP 9+ (flutter/flutter#189109)
2026-07-09 [email protected] Sync CHANGELOG.md from stable (flutter/flutter#189203)
2026-07-09 [email protected] [web] Roll Chrome to 145 (framework) (flutter/flutter#182861)
2026-07-09 [email protected] Roll Packages from 52d84d6 to 20928d5 (6 revisions) (flutter/flutter#189194)
2026-07-09 [email protected] [web] Avoid absolute positioning for base CanvasKit canvas (flutter/flutter#188337)
2026-07-09 [email protected] Roll Dart SDK from cdb7217e65aa to a11fb7ed40a5 (6 revisions) (flutter/flutter#189195)
2026-07-09 [email protected] Fix dereference of nullptr in the moved-to-rect signal in the Linux embedder (flutter/flutter#189152)
2026-07-09 [email protected] Fix data for design packages (flutter/flutter#189140)
2026-07-09 [email protected] Roll Skia from 7b42d1251d54 to ab3a7b98c94d (2 revisions) (flutter/flutter#189181)
2026-07-09 [email protected] Roll Skia from 05d9d214e0b7 to 7b42d1251d54 (2 revisions) (flutter/flutter#189175)
2026-07-09 [email protected] Roll Skia from 542c8bdd7f4f to 05d9d214e0b7 (4 revisions) (flutter/flutter#189169)
2026-07-09 [email protected] UberSDF rect handling for thin (line-like) rectangles (flutter/flutter#188821)
2026-07-09 [email protected] Roll Skia from dd572c07f63c to 542c8bdd7f4f (4 revisions) (flutter/flutter#189160)
2026-07-09 [email protected] [flutter_tools] Fix hot restart for WASM web builds (flutter/flutter#187898)
2026-07-08 [email protected] Split FlViewRenderer into OpenGL and software backends (flutter/flutter#188824)
2026-07-08 [email protected] Promote android_hardware_smoke_tests out of bringup in CI (flutter/flutter#189081)
2026-07-08 [email protected] Roll Skia from 8df24be66531 to dd572c07f63c (4 revisions) (flutter/flutter#189150)
2026-07-08 [email protected] Expose LinuxWindowRegistrar on _window_linux.dart in order to better support out of tree LinuxWindowingOwners (flutter/flutter#188917)
2026-07-08 [email protected] Roll pub packages (flutter/flutter#189149)
2026-07-08 [email protected] fix(ci): harden some workflows (flutter/flutter#189087)
2026-07-08 [email protected] Roll Skia from 51a62da33da0 to 8df24be66531 (1 revision) (flutter/flutter#189139)
2026-07-08 [email protected] Roll Dart SDK to Dart 3.13 beta3 (flutter/flutter#189122)
2026-07-08 [email protected] [flutter_tools] Don't crash on non-UTF-8 plugin pubspec.yaml (flutter/flutter#188976)
2026-07-08 [email protected] [flutter_tools] Watch transitive #include headers for FragmentProgram hot reload (flutter/flutter#187945)
2026-07-08 [email protected] Roll Skia from 040d9f55de00 to 51a62da33da0 (1 revision) (flutter/flutter#189135)
2026-07-08 [email protected] Roll Packages from 92525f5 to 52d84d6 (7 revisions) (flutter/flutter#189134)
2026-07-08 [email protected] [flutter_tools] Forcefully kill hung subprocesses 5 seconds after timeout (flutter/flutter#187178)
2026-07-08 [email protected] Expose the app's build name and number as compile-time constants (flutter/flutter#187935)
2026-07-08 [email protected] Roll Skia from 1ff92f879815 to 040d9f55de00 (1 revision) (flutter/flutter#189131)
2026-07-08 [email protected] Roll Skia from 6137414bef5c to 1ff92f879815 (6 revisions) (flutter/flutter#189126)
2026-07-08 [email protected] [test cross imports] More test/rendering + flutter_test/test fixes (flutter/flutter#188954)
2026-07-08 [email protected] engine: explain why each candidate build was skipped in Flutter web loader (flutter/flutter#186254)
2026-07-08 [email protected] vscode: add missing unicode.h (flutter/flutter#189102)
2026-07-08 [email protected] Roll Fuchsia Linux SDK from 7RjQJBW3m-3Jl-7jr... to QcRFUtvCw2EobfJ8s... (flutter/flutter#189104)
2026-07-08 [email protected] Roll Skia from 075fbe4778d9 to 6137414bef5c (10 revisions) (flutter/flutter#189106)
2026-07-08 [email protected] engine: warn on WASM load failure when not crossOriginIsolated (flutter/flutter#186252)
2026-07-08 [email protected] Roll Dart SDK from c9bccc09e733 to db2155f56bf3 (2 revisions) (flutter/flutter#189105)
2026-07-08 [email protected] [flutter_tools] Prevent interactive device selection in machine mode (flutter/flutter#188267)
2026-07-08 [email protected] [flutter_tools] Fix wireless ADB device discovery when serial contains spaces (flutter/flutter#187943)
2026-07-07 [email protected] [web] Fix grouped autofill on iOS Chrome (flutter/flutter#187459)
2026-07-07 [email protected] Fix TextSelectionOverlay crash when layout is degenerate (flutter/flutter#188672)
2026-07-07 [email protected] [flutter_tools] Provision Android NDK in the main Gradle invocation (flutter/flutter#186337)
2026-07-07 [email protected] Android_hardware_smoke_test: Migrate to AGP 9 (flutter/flutter#189082)
...
pull Bot pushed a commit to Mu-L/flutter that referenced this pull request Jul 11, 2026
…9240)

In flutter#189174, we migrated back to
using target triples in swiftc.py in order to more closely mirror the
commandline interface to `swiftc` itself.

This is a followup that cleans up some extra function parameters that
are no longer necessary now that we're getting the target triple in
args.

This cleans up a few remaining diffs from the reversion of the target
triple splitting from
https://github.com/flutter/flutter/pull/185712/changes#diff-d57f937ed2d743b17635dd069689072eba124f649f307228915c25d55b19ed62.

No test changes since this is a refactor with no semantic change. The
test is the build (and transitively, all the tests it builds and runs).

Issue: flutter#185741


## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [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].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**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
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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
cbracken added a commit to cbracken/flutter that referenced this pull request Jul 18, 2026
GN's `--export-compile-commands` only understands its built-in
`cc`/`cxx`/`objc`/`objcxx` tool types, so the custom `swift` tool we use to
invoke `swiftc.py` never shows up in `compile_commands.json`. Swift code
under `flutter/shell/platform/darwin` was therefore invisible to any
tooling that reads that file, including SourceKit-LSP, which is what
drives Swift diagnostics/completion/go-to-definition in VS Code and other
editors.

This adds a post-processing step to `gn gen` that fixes this up. Since
GN's own compdb export omits the swift targets entirely, we now shell out
to `ninja -t compdb` to get the full compilation database instead (falling
back to the existing `compile_commands.json` on disk if that fails), then
rewrite the result in two passes:

* `stripCompilerWrappers` strips the `rewrapper`/`ccache` prefix off
  `clang`/`clang++` invocations, same as before, so `clangd` doesn't choke
  on RBE wrapper commands (flutter#147767).
* `expandSwiftcCommands` turns each `swiftc.py`-wrapped entry into one or
  more native `swiftc` invocations, one per compiled Swift file, with all
  relative paths resolved to absolute against the entry's `directory`.
  This mirrors the argument translation `swiftc.py` itself does
  (`-import-objc-header`, `-whole-module-optimization`,
  `-I`/`-isystem`/`-F`/`-Fsystem`/`-D` mirrored to `-Xcc`, etc.) so
  SourceKit-LSP sees the same flags the real build uses.

Also wires up `.sourcekit-lsp/config.json` and the
`swift.sourcekit-lsp.supported-languages` setting in
`engine.code-workspace`/`engine-workspace.yaml` so VS Code's Swift
extension picks up the generated compdb automatically.

Both regexes in `update_compdb.dart` scan the raw ninja output directly
rather than decoding the full `compile_commands.json`, which can run past
20MB and is slow to parse in Dart; we only `jsonDecode` the handful of
matched `swiftc.py` entries. While tightening this up I found the
`clang`/`clang++` wrapper-stripping regex could match a `clang` substring
anywhere later on the line -- e.g. an `-Xclang` flag, or a source file
whose name happens to contain "clang" -- rather than the actual compiler
token, silently truncating the command. Anchored the match to require
`clang`/`clang++` be preceded by `/` (or start-of-word) and followed by a
word boundary, and added regression tests for both cases.

Pre-factored in flutter#189174 and flutter#189240.
cbracken added a commit to cbracken/flutter that referenced this pull request Jul 18, 2026
GN's `--export-compile-commands` only understands its built-in
`cc`/`cxx`/`objc`/`objcxx` tool types, so the custom `swift` tool we use to
invoke `swiftc.py` never shows up in `compile_commands.json`. Swift code
under `flutter/shell/platform/darwin` was therefore invisible to any
tooling that reads that file, including SourceKit-LSP, which is what
drives Swift diagnostics/completion/go-to-definition in VS Code and other
editors.

This adds a post-processing step to `gn gen` that fixes this up. Since
GN's own compdb export omits the swift targets entirely, we now shell out
to `ninja -t compdb` to get the full compilation database instead (falling
back to the existing `compile_commands.json` on disk if that fails), then
rewrite the result in two passes:

* `stripCompilerWrappers` strips the `rewrapper`/`ccache` prefix off
  `clang`/`clang++` invocations, same as before, so `clangd` doesn't choke
  on RBE wrapper commands (flutter#147767).
* `expandSwiftcCommands` turns each `swiftc.py`-wrapped entry into one or
  more native `swiftc` invocations, one per compiled Swift file, with all
  relative paths resolved to absolute against the entry's `directory`.
  This mirrors the argument translation `swiftc.py` itself does
  (`-import-objc-header`, `-whole-module-optimization`,
  `-I`/`-isystem`/`-F`/`-Fsystem`/`-D` mirrored to `-Xcc`, etc.) so
  SourceKit-LSP sees the same flags the real build uses.

Also wires up `.sourcekit-lsp/config.json` and the
`swift.sourcekit-lsp.supported-languages` setting in
`engine.code-workspace`/`engine-workspace.yaml` so VS Code's Swift
extension picks up the generated compdb automatically.

Both regexes in `update_compdb.dart` scan the raw ninja output directly
rather than decoding the full `compile_commands.json`, which can run past
20MB and is slow to parse in Dart; we only `jsonDecode` the handful of
matched `swiftc.py` entries. While tightening this up I found the
`clang`/`clang++` wrapper-stripping regex could match a `clang` substring
anywhere later on the line -- e.g. an `-Xclang` flag, or a source file
whose name happens to contain "clang" -- rather than the actual compiler
token, silently truncating the command. Anchored the match to require
`clang`/`clang++` be preceded by `/` (or start-of-word) and followed by a
word boundary, and added regression tests for both cases.

A design pass on `update_compdb.dart` also cleaned up a few things:

* Dropped `update_compdb.dart` from the package's public barrel export
  (`engine_build_configs.dart`). Nothing needs it there -- `_postGn()`
  imports it directly as a sibling file, and the tests import
  `package:engine_build_configs/src/update_compdb.dart` rather than the
  barrel -- so exporting it only widened the package's public API for no
  reason.
* `swiftc.py` args now flow as `List<String>` end to end and get quoted
  into a shell command exactly once, at the very end, instead of being
  joined into a string and immediately re-split back into a list to
  resolve paths.
* Replaced the `CommandString` utility class (private constructor, only
  static members) with top-level functions `splitShellWords` and
  `quoteShellWord`.
* `expandSwiftEntry` no longer mutates the `entry` map it's given; it and
  its helpers (`_absolutizeEntryFile`, `_duplicateEntryPerSwiftFile`)
  build fresh maps via spread syntax instead.
* Collapsed `_SwiftCommand`/`_ParsedSwiftCommand`/`_CommandPathResolver`
  -- three classes, each with exactly one call site -- into two
  functions, `_translateSwiftcArgs` and `_resolveCommandPaths`, linked by
  a `_SwiftcTranslation` record typedef instead of a dedicated value
  class.

Pre-factored in flutter#189174 and flutter#189240.
cbracken added a commit to cbracken/flutter that referenced this pull request Jul 18, 2026
GN's `--export-compile-commands` only understands its built-in
`cc`/`cxx`/`objc`/`objcxx` tool types, so the custom `swift` tool we use to
invoke `swiftc.py` never shows up in `compile_commands.json`. Swift code
under `flutter/shell/platform/darwin` was therefore invisible to any
tooling that reads that file, including SourceKit-LSP, which is what
drives Swift diagnostics/completion/go-to-definition in VS Code and other
editors.

This adds a post-processing step to `gn gen` that fixes this up. Since
GN's own compdb export omits the swift targets entirely, we now shell out
to `ninja -t compdb` to get the full compilation database instead (falling
back to the existing `compile_commands.json` on disk if that fails), then
rewrite the result in two passes:

* `stripCompilerWrappers` strips the `rewrapper`/`ccache` prefix off
  `clang`/`clang++` invocations, same as before, so `clangd` doesn't choke
  on RBE wrapper commands (flutter#147767).
* `expandSwiftcCommands` turns each `swiftc.py`-wrapped entry into one or
  more native `swiftc` invocations, one per compiled Swift file, with all
  relative paths resolved to absolute against the entry's `directory`.
  This mirrors the argument translation `swiftc.py` itself does
  (`-import-objc-header`, `-whole-module-optimization`,
  `-I`/`-isystem`/`-F`/`-Fsystem`/`-D` mirrored to `-Xcc`, etc.) so
  SourceKit-LSP sees the same flags the real build uses.

Also wires up `.sourcekit-lsp/config.json` and the
`swift.sourcekit-lsp.supported-languages` setting in
`engine.code-workspace`/`engine-workspace.yaml` so VS Code's Swift
extension picks up the generated compdb automatically.

Both regexes in `update_compdb.dart` scan the raw ninja output directly
rather than decoding the full `compile_commands.json`, which can run past
20MB and is slow to parse in Dart; we only `jsonDecode` the handful of
matched `swiftc.py` entries. While tightening this up I found the
`clang`/`clang++` wrapper-stripping regex could match a `clang` substring
anywhere later on the line -- e.g. an `-Xclang` flag, or a source file
whose name happens to contain "clang" -- rather than the actual compiler
token, silently truncating the command. Anchored the match to require
`clang`/`clang++` be preceded by `/` (or start-of-word) and followed by a
word boundary, and added regression tests for both cases.

A design pass on `update_compdb.dart` also cleaned up a few things:

* Dropped `update_compdb.dart` from the package's public barrel export
  (`engine_build_configs.dart`). Nothing needs it there -- `_postGn()`
  imports it directly as a sibling file, and the tests import
  `package:engine_build_configs/src/update_compdb.dart` rather than the
  barrel -- so exporting it only widened the package's public API for no
  reason.
* `swiftc.py` args now flow as `List<String>` end to end and get quoted
  into a shell command exactly once, at the very end, instead of being
  joined into a string and immediately re-split back into a list to
  resolve paths.
* Replaced the `CommandString` utility class (private constructor, only
  static members) with top-level functions `splitShellWords` and
  `quoteShellWord`.
* `expandSwiftEntry` no longer mutates the `entry` map it's given; it and
  its helpers (`_absolutizeEntryFile`, `_duplicateEntryPerSwiftFile`)
  build fresh maps via spread syntax instead.
* Collapsed `_SwiftCommand`/`_ParsedSwiftCommand`/`_CommandPathResolver`
  -- three classes, each with exactly one call site -- into two
  functions, `_translateSwiftcArgs` and `_resolveCommandPaths`, linked by
  a `_SwiftcTranslation` record typedef instead of a dedicated value
  class.

A correctness pass traced the flag translation against `swiftc.py`'s
actual `ArgumentForwarder` logic (`build/toolchain/darwin/swiftc.py`) and
found two mismatches, both currently dormant since no target in this repo
wires `{{defines}}` or `{{system_include_dirs}}` into the swift tool's GN
command template today, but worth fixing for fidelity:

* `-isystem` was forwarded to `swiftc` itself as a bare flag in addition
  to the `-Xcc -isystem -Xcc <path>` mirror. `swiftc.py`'s
  `IncludeArgumentForwarder` excludes `-isystem` from the swift-side
  forward entirely (`to_swift=lambda _: arg_name != '-isystem'`) -- it's
  clang-only. Fixed in `_resolveCommandPaths` for both the attached and
  separated forms.
* `-D key=value` was forwarded to `swiftc`'s `-D`, which only accepts
  bare conditional-compilation flags. `swiftc.py`'s
  `DefineArgumentForwarder` only forwards to swift when the value has no
  `=`; value-defines go to clang only. Fixed in `_translateSwiftcArgs`.
  Bare flags like `-D FOO` are unaffected.

Also dropped a dead `--fix-module-imports` branch (not an actual
swiftc.py argparse flag -- only `--fix-generated-header` is; the name
only ever existed in a stale docstring), and fixed `splitShellWords` to
preserve an empty quoted argument (`""`/`''`) as an empty-string token
instead of dropping it, which had been silently swallowing the following
flag whenever `-import-objc-header ""` appeared on a real command line.

Pre-factored in flutter#189174 and flutter#189240.
cbracken added a commit to cbracken/flutter that referenced this pull request Jul 18, 2026
GN's `--export-compile-commands` only understands its built-in
`cc`/`cxx`/`objc`/`objcxx` tool types, so the custom `swift` tool we use to
invoke `swiftc.py` never shows up in `compile_commands.json`. Swift code
under `flutter/shell/platform/darwin` was therefore invisible to any
tooling that reads that file, including SourceKit-LSP, which is what
drives Swift diagnostics/completion/go-to-definition in VS Code and other
editors.

This adds a post-processing step to `gn gen` that fixes this up. Since
GN's own compdb export omits the swift targets entirely, we now shell out
to `ninja -t compdb` to get the full compilation database instead (falling
back to the existing `compile_commands.json` on disk if that fails), then
rewrite the result in two passes:

* `stripCompilerWrappers` strips the `rewrapper`/`ccache` prefix off
  `clang`/`clang++` invocations, same as before, so `clangd` doesn't choke
  on RBE wrapper commands (flutter#147767).
* `expandSwiftcCommands` turns each `swiftc.py`-wrapped entry into one or
  more native `swiftc` invocations, one per compiled Swift file, with all
  relative paths resolved to absolute against the entry's `directory`.
  This mirrors the argument translation `swiftc.py` itself does
  (`-import-objc-header`, `-whole-module-optimization`,
  `-I`/`-isystem`/`-F`/`-Fsystem`/`-D` mirrored to `-Xcc`, etc.) so
  SourceKit-LSP sees the same flags the real build uses.

Also wires up `.sourcekit-lsp/config.json` and the
`swift.sourcekit-lsp.supported-languages` setting in
`engine.code-workspace`/`engine-workspace.yaml` so VS Code's Swift
extension picks up the generated compdb automatically.

Both regexes in `update_compdb.dart` scan the raw ninja output directly
rather than decoding the full `compile_commands.json`, which can run past
20MB and is slow to parse in Dart; we only `jsonDecode` the handful of
matched `swiftc.py` entries. While tightening this up I found the
`clang`/`clang++` wrapper-stripping regex could match a `clang` substring
anywhere later on the line -- e.g. an `-Xclang` flag, or a source file
whose name happens to contain "clang" -- rather than the actual compiler
token, silently truncating the command. Anchored the match to require
`clang`/`clang++` be preceded by `/` (or start-of-word) and followed by a
word boundary, and added regression tests for both cases.

A design pass on `update_compdb.dart` also cleaned up a few things:

* Dropped `update_compdb.dart` from the package's public barrel export
  (`engine_build_configs.dart`). Nothing needs it there -- `_postGn()`
  imports it directly as a sibling file, and the tests import
  `package:engine_build_configs/src/update_compdb.dart` rather than the
  barrel -- so exporting it only widened the package's public API for no
  reason.
* `swiftc.py` args now flow as `List<String>` end to end and get quoted
  into a shell command exactly once, at the very end, instead of being
  joined into a string and immediately re-split back into a list to
  resolve paths.
* Replaced the `CommandString` utility class (private constructor, only
  static members) with top-level functions `splitShellWords` and
  `quoteShellWord`.
* `expandSwiftEntry` no longer mutates the `entry` map it's given; it and
  its helpers (`_absolutizeEntryFile`, `_duplicateEntryPerSwiftFile`)
  build fresh maps via spread syntax instead.
* Collapsed `_SwiftCommand`/`_ParsedSwiftCommand`/`_CommandPathResolver`
  -- three classes, each with exactly one call site -- into two
  functions, `_translateSwiftcArgs` and `_resolveCommandPaths`, linked by
  a `_SwiftcTranslation` record typedef instead of a dedicated value
  class.

A correctness pass traced the flag translation against `swiftc.py`'s
actual `ArgumentForwarder` logic (`build/toolchain/darwin/swiftc.py`) and
found two mismatches, both currently dormant since no target in this repo
wires `{{defines}}` or `{{system_include_dirs}}` into the swift tool's GN
command template today, but worth fixing for fidelity:

* `-isystem` was forwarded to `swiftc` itself as a bare flag in addition
  to the `-Xcc -isystem -Xcc <path>` mirror. `swiftc.py`'s
  `IncludeArgumentForwarder` excludes `-isystem` from the swift-side
  forward entirely (`to_swift=lambda _: arg_name != '-isystem'`) -- it's
  clang-only. Fixed in `_resolveCommandPaths` for both the attached and
  separated forms, and consolidated into a single named `isClangOnly()`
  check instead of three separate comparisons, so the same class of bug
  (a special case duplicated instead of centralized) can't creep back in.
* `-D key=value` was forwarded to `swiftc`'s `-D`, which only accepts
  bare conditional-compilation flags. `swiftc.py`'s
  `DefineArgumentForwarder` only forwards to swift when the value has no
  `=`; value-defines go to clang only. Fixed in `_translateSwiftcArgs`.
  Bare flags like `-D FOO` are unaffected.

Also dropped a dead `--fix-module-imports` branch (not an actual
swiftc.py argparse flag -- only `--fix-generated-header` is; the name
only ever existed in a stale docstring), and fixed `splitShellWords` to
preserve an empty quoted argument (`""`/`''`) as an empty-string token
instead of dropping it, which had been silently swallowing the following
flag whenever `-import-objc-header ""` appeared on a real command line.

Ran `dart format` for the first time (fixed a missing blank line between
import groups) and grouped the test file's 15 tests by the function they
exercise now that it's grown past being easy to scan as a flat list.

Pre-factored in flutter#189174 and flutter#189240.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-ios iOS applications specifically team-ios Owned by iOS platform team team-macos Owned by the macOS platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants