[Bug]: .cargo/config.toml pins DEVELOPER_DIR to Xcode, so a Command Line Tools-only machine cannot build the workspace at all
- Dominant language
- Rust
- Stars
- 21k
- Forks
- 675
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 172
Description
### Pre-flight checklist
- [x] I searched [existing issues](https://github.com/AprilNEA/OpenLogi/issues?q=is%3Aissue) and this is not a duplicate.
- [x] I am on the [latest release](https://github.com/AprilNEA/OpenLogi/releases/latest) or a recent `master` build.
- [x] I quit **Logi Options+** before running OpenLogi (the two apps fight over HID++ access and only one can own a receiver at a time).
### Which part of OpenLogi?
Both
### OpenLogi version
v0.8.1 (`411c927`). The `.cargo/config.toml` block below is unchanged on current `master` (`62fd576`) as of 2026-08-27.
### Operating system
macOS
### OS version & architecture
macOS 15.7.3 (Sequoia), Apple Silicon (aarch64). **Xcode is not installed**; only the Command Line Tools are.
### Device model
N/A. No device is involved: this is a build failure that happens before anything can talk to hardware.
### How is the device connected?
Other / not sure
### Affected area(s)
- [ ] Device discovery / detection
- [ ] Button remapping
- [ ] DPI control
- [ ] SmartShift
- [ ] Per-application profiles
- [ ] Battery status
- [ ] Settings / configuration (TOML)
- [ ] Auto-update
- [ ] Menu bar / tray
- [x] Other
### What happened?
On a macOS machine with the Command Line Tools installed and Xcode absent, any `cargo build` fails before compiling a single crate of the workspace. The build scripts of third-party dependencies fail to link:
```
error: linking with `/usr/bin/cc` failed: exit status: 1
= note: xcrun: error: missing DEVELOPER_DIR path: /Applications/Xcode.app/Contents/Developer
error: could not compile `libc` (build script) due to 1 previous error
error: could not compile `proc-macro2` (build script) due to 1 previous error
error: could not compile `serde` (build script) due to 1 previous error
error: could not compile `crossbeam-utils` (build script) due to 1 previous error
```
I expected a plain `cargo build` to work, because `AGENTS.md` says this setup is supported:
> Nix/devenv is optional — rustup + `rust-toolchain.toml` is enough. If devenv is installed, direnv loads it; otherwise `.envrc` prints a notice and leaves PATH alone so system `cargo` works.
**Cause.** `.cargo/config.toml` sets `DEVELOPER_DIR` unconditionally:
```toml
# Belt-and-suspenders DEVELOPER_DIR for contributors who run cargo outside
# the devenv shell and have xcode-select pointing at the Command Line Tools
# only (no Metal toolchain). `force = false` means a real DEVELOPER_DIR
# already exported in the shell (devenv users, CI runners) wins.
[env]
DEVELOPER_DIR = { value = "/Applications/Xcode.app/Contents/Developer", force = false }
```
`force = false` only yields to a `DEVELOPER_DIR` that is *already exported*. An unset variable is not "already exported", so cargo's value wins and overrides an `xcode-select` configuration that is already correct:
```console
$ xcode-select -p
/Library/Developer/CommandLineTools
$ ls -d /Applications/Xcode.app
ls: /Applications/Xcode.app: No such file or directory
$ echo "${DEVELOPER_DIR:-unset}"
unset
```
*(Notes on the form itself: the "Which part of OpenLogi?" dropdown and the "Affected area(s)" list have no build/tooling option; I picked "Both" and "Other" because the failure is in the build itself: it happens inside third-party build scripts, so no crate of this workspace starts compiling at all. The repo's `type: build` label looks like the right home for this. Pre-flight: Logi Options+ is not installed on this machine.)*
### Steps to reproduce
On a macOS machine with the Command Line Tools installed and Xcode absent:
1. `git clone https://github.com/AprilNEA/OpenLogi && cd OpenLogi`
2. `rustup update stable`, so the toolchain satisfies `rust-version = "1.98"`. (Worth stating because an older stable stops earlier, with an MSRV error, before it can reach the failure this issue is about.)
3. Any cargo invocation, for example `cargo build -p openlogi-hid` or `cargo check -p openlogi-core`.
4. The build fails as above, inside dependency build scripts.
**Workaround:**
```console
$ DEVELOPER_DIR=/Library/Developer/CommandLineTools cargo build -p openlogi-hid
```
With that, `openlogi-hid` and its whole dependency tree build cleanly, and nothing else about this environment is missing.
**Scope of what I verified.** I built `openlogi-hid` (and an example of it), not the workspace as a whole. In particular I did not build `openlogi-desktop`, and I would not expect it to build here: the Command Line Tools ship no Metal compiler, so the shader step has nothing to run either way.
```console
$ DEVELOPER_DIR=/Library/Developer/CommandLineTools xcrun -sdk macosx --find metal
xcrun: error: unable to find utility "metal", not a developer tool or in PATH
```
So the ask here is not "make the GUI build without Xcode", which is not possible. It is that the crates which do not need Metal, the CLI, the libraries and the tests, should not be blocked by a setting the GUI needs.
---
### Notes on fixing
I have deliberately not sent a PR, because the trade-off looks like yours to make rather than mine.
The block does serve a real case, the one its comment describes: a contributor who *has* Xcode installed but whose `xcode-select` points at the Command Line Tools. Without it, their GUI build fails on GPUI's Metal shaders, which `AGENTS.md` calls out:
> The macOS GUI build needs full Xcode for GPUI's Metal shaders; devenv sets the env when present.
So the bug is not that the fallback exists, but that it does not degrade when Xcode is absent, and `[env]` in `.cargo/config.toml` is static, with no way to test whether the path exists.
**One constraint worth stating**, since it rules out the obvious fix: the Metal requirement does not come from this workspace. It comes from `gpui_macos`'s build script in the zed tree (`crates/gpui_macos/build.rs` as of zed `cc053a4`, the rev this workspace's `Cargo.lock` pins), which shells out to `xcrun` to produce `shaders.metallib`:
```rust
Command::new("xcrun").args(["-sdk", "macosx", "metal", ...])
Command::new("xcrun").args(["-sdk", "macosx", "metallib"])
```
A dependency's build script runs before anything in the depending crate, so `openlogi-desktop` cannot set `DEVELOPER_DIR` for it from its own `build.rs`, and cargo has no per-package form of `[env]`. Whatever needs Xcode has to have `DEVELOPER_DIR` in the environment **before cargo starts**, which is why the setting ended up workspace-wide in the first place.
Options I can see:
1. **Set it outside cargo, and drop the blanket `[env]`.** Since it has to be in the environment before cargo starts, the natural owners are the things that already wrap the build: devenv sets it when present, and `xtask/src/support/xcode.rs` already resolves `OPENLOGI_DEVELOPER_DIR`. Routing the GUI build through those, and leaving a plain `cargo build` alone, keeps the CLI, the libraries and the tests buildable without Xcode. Anyone building the GUI still needs Xcode, which is unavoidable, but they would get a Metal error that says so instead of `libc` failing to link.
2. **Drop the block and treat the case it covers as a misconfiguration.** A contributor who has Xcode but whose `xcode-select` points at the Command Line Tools can fix that once, globally, with `sudo xcode-select -s /Applications/Xcode.app`. Papering over it in the repo config is what costs correctly-configured machines a total build failure, and the error they get if the block is gone (a missing Metal SDK) points at the real problem far better than the current one, which names `libc`.
3. **Move the fallback to `.envrc`**, which is a shell script and can test that the path exists before exporting. That fixes the "does not degrade" part, but only for people who have direnv, and `AGENTS.md` presents devenv and direnv as optional, so it would miss exactly the rustup-only contributors the block is aimed at.
4. **Keep it and document it**: a line in the build section of `AGENTS.md` saying that machines without Xcode need `DEVELOPER_DIR=/Library/Developer/CommandLineTools`. Cheapest, but it leaves the default broken for the setup `AGENTS.md` currently advertises as sufficient, so that sentence would probably need adjusting too.
1 and 2 are complementary rather than alternatives: dropping the workspace-wide value is what unblocks non-Xcode machines, and making sure the GUI path still gets `DEVELOPER_DIR` from its wrapper is what keeps Metal working for everyone who needs it.
Happy to send a PR for whichever you prefer.
### Impact
A contributor without Xcode hits this on their very first `cargo build`, and the error names `libc` and `xcrun` rather than `.cargo/config.toml`, so the cause is hard to find: `xcode-select -p` reports the correct path, which makes it look like the environment is fine.
### Diagnostics report
```markdown
N/A. The CLI cannot be built on this machine without the workaround above.
```
### `openlogi list` output
```text
N/A. No device involved.
```
### Logs
```shell
N/A. The failure is at build time, and the output is quoted in full above.
```
### macOS permissions (if applicable)
- [ ] OpenLogi has **Accessibility** permission (needed to remap buttons via the event tap).
- [ ] OpenLogi has **Input Monitoring** permission (needed for Bluetooth-direct devices and capture).
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with .cargo/config.toml and AGENTS.md, then inspect .envrc, devenv configuration, and xtask/src/support/xcode.rs to understand how DEVELOPER_DIR is selected before Cargo starts. Reproduce with a Command Line Tools-only machine using cargo build -p openlogi-hid, and verify that non-GUI crates build without Xcode while the GUI path still clearly reports its Metal/Xcode requirement.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, rust
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100