|
| 1 | +# Jobserver |
| 2 | + |
| 3 | +Internally, `rustc` may take advantage of parallelism. `rustc` will coordinate |
| 4 | +with the build system calling it if a [GNU Make jobserver] is passed in the |
| 5 | +`MAKEFLAGS` environment variable. Other flags may have an effect as well, such |
| 6 | +as [`CARGO_MAKEFLAGS`]. |
| 7 | + |
| 8 | +Starting with Rust 1.76.0, `rustc` will warn if a jobserver appears to be |
| 9 | +available but is not accessible, e.g.: |
| 10 | + |
| 11 | +```console |
| 12 | +$ echo 'fn main() {}' | MAKEFLAGS=--jobserver-auth=3,4 rustc - |
| 13 | +warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,4"`: cannot open file descriptor 3 from the jobserver environment variable value: Bad file descriptor (os error 9) |
| 14 | + | |
| 15 | + = note: the build environment is likely misconfigured |
| 16 | +``` |
| 17 | + |
| 18 | +## Integration with build systems |
| 19 | + |
| 20 | +The following subsections contain recommendations on how to integrate `rustc` |
| 21 | +with build systems so that the jobserver is handled appropriately. |
| 22 | + |
| 23 | +### GNU Make |
| 24 | + |
| 25 | +When calling `rustc` from GNU Make, it is recommended that all `rustc` |
| 26 | +invocations are marked as recursive in the `Makefile` (by prefixing the command |
| 27 | +line with the `+` indicator), so that GNU Make enables the jobserver for them. |
| 28 | +For instance: |
| 29 | + |
| 30 | +<!-- ignore-tidy-tab --> |
| 31 | + |
| 32 | +```make |
| 33 | +x: |
| 34 | + +@echo 'fn main() {}' | rustc - |
| 35 | +``` |
| 36 | + |
| 37 | +In particular, GNU Make 4.3 (a widely used version as of 2024) passes a simple |
| 38 | +pipe jobserver in `MAKEFLAGS` even when it was not made available for the child |
| 39 | +process, which in turn means `rustc` will warn about it. For instance, if the |
| 40 | +`+` indicator is removed from the example above and GNU Make is called with e.g. |
| 41 | +`make -j2`, then the aforementioned warning will trigger. |
| 42 | + |
| 43 | +For calls to `rustc` inside `$(shell ...)` inside a recursive Make, one can |
| 44 | +disable the jobserver manually by clearing the `MAKEFLAGS` variable, e.g.: |
| 45 | + |
| 46 | +```make |
| 47 | +S := $(shell MAKEFLAGS= rustc --print sysroot) |
| 48 | + |
| 49 | +x: |
| 50 | + @$(MAKE) y |
| 51 | + |
| 52 | +y: |
| 53 | + @echo $(S) |
| 54 | +``` |
| 55 | + |
| 56 | +### CMake |
| 57 | + |
| 58 | +CMake 3.28 supports the `JOB_SERVER_AWARE` option in its [`add_custom_target`] |
| 59 | +command, e.g.: |
| 60 | + |
| 61 | +```cmake |
| 62 | +cmake_minimum_required(VERSION 3.28) |
| 63 | +project(x) |
| 64 | +add_custom_target(x |
| 65 | + JOB_SERVER_AWARE TRUE |
| 66 | + COMMAND echo 'fn main() {}' | rustc - |
| 67 | +) |
| 68 | +``` |
| 69 | + |
| 70 | +For earlier versions, when using CMake with the Makefile generator, one |
| 71 | +workaround is to have [`$(MAKE)`] somewhere in the command so that GNU Make |
| 72 | +treats it as a recursive Make call, e.g.: |
| 73 | + |
| 74 | +```cmake |
| 75 | +cmake_minimum_required(VERSION 3.22) |
| 76 | +project(x) |
| 77 | +add_custom_target(x |
| 78 | + COMMAND DUMMY_VARIABLE=$(MAKE) echo 'fn main() {}' | rustc - |
| 79 | +) |
| 80 | +``` |
| 81 | + |
| 82 | +[GNU Make jobserver]: https://www.gnu.org/software/make/manual/html_node/POSIX-Jobserver.html |
| 83 | +[`CARGO_MAKEFLAGS`]: https://doc.rust-lang.org/cargo/reference/environment-variables.html |
| 84 | +[`add_custom_target`]: https://cmake.org/cmake/help/latest/command/add_custom_target.html |
| 85 | +[`$(MAKE)`]: https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html |
0 commit comments