`xls/common/subprocess.cc` does not compile on macOS: uses `<linux/memfd.h>`, `memfd_create()` and `/proc/self/fd`
- Dominant language
- C++
- Stars
- 1.9k
- Forks
- 283
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 135
Description
## Summary
`xls/common/subprocess.cc` unconditionally depends on three Linux-only facilities, so it cannot compile on macOS:
```
xls/common/subprocess.cc:18:10: fatal error: 'linux/memfd.h' file not found
18 | #include
| ^~~~~~~~~~~~~~~
```
Beyond the header, the same code path also uses:
- `memfd_create()` / `MFD_CLOEXEC` — a Linux syscall with no macOS equivalent
- the `/proc/self/fd/` path handed to `posix_spawnp()` — macOS has no `/proc` filesystem
So this is not just a missing include guard; the mechanism for exec'ing the embedded `subprocess_helper` out of an anonymous in-memory file descriptor does not exist on macOS.
The file still carries an `#if defined(__APPLE__)` block for `environ`, which suggests macOS support was intended. The Linux-only path came in with 2c355ce53 ("Embed subprocess_helper in subprocess.cc", 2026-04-30).
## Impact
Blocks `//xls/tools:codegen_main` on macOS, plus anything else depending on `//xls/common:subprocess`. Notably it does **not** block `interpreter_main`, `ir_converter_main` or `opt_main` — none of those depend on `subprocess` — but since Bazel aborts on the first error, a plain `bazel build` of all four appears to fail entirely.
This is one of the reasons `Nightly MacOS` is red (see also the llvm-project checksum issue).
## Reproduction
On macOS arm64, after working around the llvm-project checksum problem:
```
bazel build -c opt -- //xls/tools:codegen_main
```
## Suggested fix
Introduce a `GetSubprocessHelperPath()` that encapsulates producing an exec'able path for the embedded helper:
- **Linux**: unchanged — write the helper to a memfd, return `/proc/self/fd/`, hold the descriptor open for the lifetime of the process.
- **Apple**: materialize the helper into a temporary file with `mkstemp()` and mark it executable with `fchmod(0700)`, unlinking it via `std::atexit()` (and on the error paths).
The temporary file is unavoidable on macOS: unlike a Linux memfd it has a name and is not reclaimed automatically, it cannot be unlinked up front because exec resolves it by path, exec'ing an unlinked file through `/dev/fd/` is rejected with `EACCES`, and there is no `fexecve()`. A process killed by a signal will still leave one behind.
I have this working locally; `//xls/common:subprocess_test` (12 tests, covering non-zero exits, crashing children, large stdout/stderr, and environment variable propagation) passes on macOS arm64. Happy to send it as a PR.
Note that running that test on macOS also requires the `xls_cc_embed_data` shared-library fix filed separately.
## Related
#1434 (tracking issue: OS X aarch64 build/test status).
One note in that issue appears to be out of date: it states that the hermetic
LLVM toolchain does not work on OS X. I did not need to disable it -- building
with the hermetic toolchain on macOS arm64 worked, once the problem above and
the `xls_cc_embed_data` shared-library problem were addressed.
Also #1363 (macosx nightly builds are failing), which reports the symptom; this issue is one of the concrete causes.
## Environment
- macOS 26.6.2, arm64 (Apple Silicon)
- Bazel 8.7.0, XLS at `fc572666a`
Contributor guide
Research direction
Start in xls/common/subprocess.cc, focusing on the embedded subprocess_helper path, Linux-only facilities, and the existing __APPLE__ handling. Run //xls/common:subprocess_test and bazel build -c opt -- //xls/tools:codegen_main on macOS; done means the target compiles and the 12 subprocess tests pass there.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, macos
- Domain
- build-system, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100