Skip to content

Conversation

@benjivos
Copy link
Contributor

On macOS, this change ensures that when DEVELOPER_DIR environment variable is used, it will be propagated to /usr/bin/xcrun to query the SDKROOT. This takes precedence over the --xcode_version flag when selecting the Xcode installation. This aligns with the intended use as documented in man xcrun:

The tool xcode-select(1) is used to set a system default for the active developer directory, and may be overridden by the DEVELOPER_DIR environment variable (see ENVIRONMENT).

To leverage this, developers must propagate the DEVELOPER_DIR environment variable to Bazel actions using --action_env=DEVELOPER_DIR.

@github-actions github-actions bot added the awaiting-review PR is awaiting review from an assigned reviewer label Mar 21, 2025
@keith
Copy link
Member

keith commented Mar 21, 2025

what's the motivation here to take precedence over xcode_version? in today's world the intent of the logic is that bazel does a lookup once to discover the current Xcode version (and that could take DEVELOPER_DIR into account) and then after that all invocations use that discover. The weird part about this is that separate actions could technically use different Xcode versions, for example in your example --action_env wouldn't be enough you'd also need --host_action_env

@iancha1992 iancha1992 added the team-Rules-ObjC Issues for Objective-C maintainers label Mar 21, 2025
@benjivos
Copy link
Contributor Author

benjivos commented Mar 22, 2025

The motivation is to ensure that when DEVELOPER_DIR is explicitly passed to actions via --action_env or --host_action_env, those actions consistently use the specified Xcode. While the current implementation attempts to respect DEVELOPER_DIR, it can lead to inconsistencies where a single action uses paths from different Xcode installations. This is because the SDKROOT is derived from the xcode-select -p, and other paths from the DEVELOPER_DIR environment variable.

My understanding is that the intent should be that if a user explicitly provides DEVELOPER_DIR for an action, that action should use that Xcode. The current implementation doesn't guarantee this.

To illustrate the problem, consider this scenario:

  • The system default Xcode is set to /Applications/Xcode.app (using xcode-select -s /Applications/Xcode.app).
  • We want to run a Bazel action using /Applications/Xcode2.app.
  • We pass DEVELOPER_DIR=/Applications/Xcode2.app using --action_env and --host_action_env.

The current implementation can result in an action that uses paths from both Xcode installations. Here's a concrete example, runnable with the attached example.zip file:

DEVELOPER_DIR=/Applications/Xcode2.app  bazel run -s --action_env=__WRAPPED_CLANG_LOG_ONLY=1 --action_env=DEVELOPER_DIR --host_action_env=DEVELOPER_DIR //:hello

This command will print the clang invocation, which includes both /Applications/Xcode.app and /Applications/Xcode2.app:

/usr/bin/xcrun clang -D_FORTIFY_SOURCE=1 -fstack-protector -fcolor-diagnostics -Wall -Wthread-safety -Wself-assign -fno-omit-frame-pointer -O0 -DDEBUG -fdebug-prefix-map=/private/tmp/bazel-sandbox.6cafcf99323a62b5375265dd657c2b4578a1b7be1607e50d8be25dad19416f92/darwin-sandbox/7/execroot/_main=. -fdebug-prefix-map=/Applications/Xcode2.app=/PLACEHOLDER_DEVELOPER_DIR -iquote . -iquote bazel-out/darwin_arm64-fastbuild/bin -iquote external/bazel_tools -iquote bazel-out/darwin_arm64-fastbuild/bin/external/bazel_tools -MD -MF bazel-out/darwin_arm64-fastbuild/bin/_objs/hello/hello.d -frandom-seed=bazel-out/darwin_arm64-fastbuild/bin/_objs/hello/hello.o -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.1.sdk -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.1.sdk/System/Library/Frameworks -F/Applications/Xcode2.app/Platforms/MacOSX.platform/Developer/Library/Frameworks -no-canonical-prefixes -pthread -no-canonical-prefixes -Wno-builtin-macro-redefined -D__DATE__="redacted" -D__TIMESTAMP__="redacted" -D__TIME__="redacted" -target arm64-apple-macosx15.1 -c hello.c -o bazel-out/darwin_arm64-fastbuild/bin/_objs/hello/hello.o

My change ensures that, in this scenario, only /Applications/Xcode2.app will be used for the entire action, providing the expected behavior when DEVELOPER_DIR is explicitly specified. The xcode_version setting would still be used if DEVELOPER_DIR isn't explicitly passed via --action_env or --host_action_env.

@keith
Copy link
Member

keith commented Mar 26, 2025

Right the intent in bazel instead today is that you never pass DEVELOPER_DIR to actions, and instead bazel handles passing that itself, which it does by determining the DEVELOPER_DIR when it starts to discover xcode versions (if that part isn't working we should fix that)

the issue with changing this is that theoretically those could mismatch, and then things could end up with 2 values in other ways.

put another way we could make bazel reject ever setting DEVELOPER_DIR / SDKROOT in action_env, since that should be a bazel implementation detail.

Copy link
Member

@keith keith left a comment

Choose a reason for hiding this comment

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

I was missing a piece in order to fully understand this. The key is that if you have 2 different copies of the same Xcode version, and xcode-locator cannot differentiate.

I think we should land but clearly not recommend for folks, since most workflows should go through the normal discovery paths and then get DEVLEOPER_DIR set automatically.

the alternative to this would be to make xcode_autoconf take the DEVELOPER_DIR more literally, where today it only uses it to get the version and then look that up based on xcode-locator, but I think that path probably isn't worth it for this edge case.

@benjivos
Copy link
Contributor Author

benjivos commented Apr 2, 2025

@allevato would you be able to have a look at this PR? Thank you!

@allevato
Copy link
Member

allevato commented Apr 2, 2025

The key is that if you have 2 different copies of the same Xcode version, and xcode-locator cannot differentiate.

This doesn't seem like a compelling case to support. Why do you intentionally have two copies of the same version? Or is the issue that you somehow have a duplicate and it's not getting distinguished? If the latter, that's an argument to improve xcode-locator.

Otherwise, I'm very much against leaking external state (even intentionally via --action_env-like flags) into the Xcode selection process. There's already too much complexity there and this adds to it.

Copy link
Member

@allevato allevato left a comment

Choose a reason for hiding this comment

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

(I'm not actually requesting changes here, I just want to have signal that I don't think we should do this)

@allevato
Copy link
Member

allevato commented Apr 2, 2025

Here's a direction to explore that might be viable (I haven't thought it all the way through, though).

There shouldn't be a lot of places in Bazel's Java core where the --xcode_version flag is required to be a dotted version number. XcodeLocalEnvProvider.java converts it to one, but then it turns around and converts it right back to a string to pass it to xcode-locator.

So what if you could just pass the developer dir of the Xcode you want to use as that flag? --xcode_version=/Applications/Xcode2.app/Contents/Developer. That way, if the value passed in that flag isn't a valid version number, we just assume it's the desired developer dir verbatim and don't even call xcode-locator to find it. That makes the choice very explicit instead of relying on propagation of an external environment variable.

I don't know if this would have any knock-on effects downstream, like with the xcode_config rules (either the built-in ones or the new ones in apple_support). But that's the direction I would prefer to explore.

@benjivos
Copy link
Contributor Author

benjivos commented Apr 3, 2025

This doesn't seem like a compelling case to support. Why do you intentionally have two copies of the same version? Or is the issue that you somehow have a duplicate and it's not getting distinguished? If the latter, that's an argument to improve xcode-locator.

We actually have multiple copies installed of the same Xcode version with different local changes potentially, requiring us to unambiguously set DEVELOPER_DIR.

So what if you could just pass the developer dir of the Xcode you want to use as that flag? --xcode_version=/Applications/Xcode2.app/Contents/Developer. That way, if the value passed in that flag isn't a valid version number, we just assume it's the desired developer dir verbatim and don't even call xcode-locator to find it. That makes the choice very explicit instead of relying on propagation of an external environment variable.

Thanks for your direction, I also like the explicit nature of it more than my initial patch. I will try to update my change with your suggestions.

On macOS, this change allows --xcode_version to accept a path to an Xcode developer directory (e.g. /Applications/Xcode2.app/Contents/Developer).
If the value is not a valid version number, it is treated as the desired DEVELOPER_DIR and used verbatim, bypassing xcode-locator.
This makes Xcode selection more explicit and avoids relying on environment variables or auto-detection.
@benjivos benjivos force-pushed the feat/respect-developer-dir branch from bab0d03 to 5c77256 Compare April 4, 2025 09:42
@benjivos benjivos requested a review from allevato April 4, 2025 10:40
Copy link
Member

@allevato allevato left a comment

Choose a reason for hiding this comment

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

@susinmotion This seems fine to me but I'd appreciate a second pair of eyes on it.

Copy link
Member

@allevato allevato left a comment

Choose a reason for hiding this comment

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

Yep! If @susinmotion is good, I'm good.

@allevato
Copy link
Member

I have no power to merge it, though.

@benjivos
Copy link
Contributor Author

@allevato who can help merging it? Thank you!

@benjivos
Copy link
Contributor Author

@iancha1992 could you help merging this change? Thank you!

@susinmotion susinmotion self-assigned this Apr 15, 2025
@susinmotion susinmotion added awaiting-PR-merge PR has been approved by a reviewer and is ready to be merge internally and removed awaiting-review PR is awaiting review from an assigned reviewer labels Apr 15, 2025
@github-actions github-actions bot removed the awaiting-PR-merge PR has been approved by a reviewer and is ready to be merge internally label Apr 16, 2025
@benjivos benjivos deleted the feat/respect-developer-dir branch April 17, 2025 11:14
benjivos added a commit to benjivos/bazel that referenced this pull request Apr 17, 2025
On macOS, this change ensures that when `DEVELOPER_DIR` environment variable is used, it will be propagated to `/usr/bin/xcrun` to query the SDKROOT. This takes precedence over the `--xcode_version` flag when selecting the Xcode installation. This aligns with the intended use as documented in `man xcrun`:

`The tool xcode-select(1) is used to set a system default for the active developer directory, and may be overridden by the DEVELOPER_DIR environment variable (see ENVIRONMENT).`

To leverage this, developers must propagate the `DEVELOPER_DIR` environment variable to Bazel actions using `--action_env=DEVELOPER_DIR`.

Closes bazelbuild#25657.

PiperOrigin-RevId: 748404233
Change-Id: I52181098658d33e2bd2ec992ad1cd38d64abb293
@iancha1992
Copy link
Member

@bazel-io fork 8.3.0

bazel-io pushed a commit to bazel-io/bazel that referenced this pull request Apr 17, 2025
On macOS, this change ensures that when `DEVELOPER_DIR` environment variable is used, it will be propagated to `/usr/bin/xcrun` to query the SDKROOT. This takes precedence over the `--xcode_version` flag when selecting the Xcode installation. This aligns with the intended use as documented in `man xcrun`:

`The tool xcode-select(1) is used to set a system default for the active developer directory, and may be overridden by the DEVELOPER_DIR environment variable (see ENVIRONMENT).`

To leverage this, developers must propagate the `DEVELOPER_DIR` environment variable to Bazel actions using `--action_env=DEVELOPER_DIR`.

Closes bazelbuild#25657.

PiperOrigin-RevId: 748404233
Change-Id: I52181098658d33e2bd2ec992ad1cd38d64abb293
github-merge-queue bot pushed a commit that referenced this pull request Apr 22, 2025
On macOS, this change ensures that when `DEVELOPER_DIR` environment
variable is used, it will be propagated to `/usr/bin/xcrun` to query the
SDKROOT. This takes precedence over the `--xcode_version` flag when
selecting the Xcode installation. This aligns with the intended use as
documented in `man xcrun`:

`The tool xcode-select(1) is used to set a system default for the active
developer directory, and may be overridden by the DEVELOPER_DIR
environment variable (see ENVIRONMENT).`

To leverage this, developers must propagate the `DEVELOPER_DIR`
environment variable to Bazel actions using
`--action_env=DEVELOPER_DIR`.

Closes #25657.

PiperOrigin-RevId: 748404233
Change-Id: I52181098658d33e2bd2ec992ad1cd38d64abb293

Commit
d2e8c82

Co-authored-by: Benji Vos <bvos@apple.com>
fmeum pushed a commit to fmeum/bazel that referenced this pull request Apr 25, 2025
On macOS, this change ensures that when `DEVELOPER_DIR` environment variable is used, it will be propagated to `/usr/bin/xcrun` to query the SDKROOT. This takes precedence over the `--xcode_version` flag when selecting the Xcode installation. This aligns with the intended use as documented in `man xcrun`:

`The tool xcode-select(1) is used to set a system default for the active developer directory, and may be overridden by the DEVELOPER_DIR environment variable (see ENVIRONMENT).`

To leverage this, developers must propagate the `DEVELOPER_DIR` environment variable to Bazel actions using `--action_env=DEVELOPER_DIR`.

Closes bazelbuild#25657.

PiperOrigin-RevId: 748404233
Change-Id: I52181098658d33e2bd2ec992ad1cd38d64abb293
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

team-Rules-ObjC Issues for Objective-C maintainers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants