Skip to content

Commit 9e1fce1

Browse files
authored
Disable broken Make jobserver support on OSX to fix parallel builds (#229)
Disable legacy Make jobserver support on OSX On OSX, CMake (via libuv) spawns child processes, including make, via the Apple-specific `posix_spawn` attribute `POSIX_SPAWN_CLOEXEC_DEFAULT`. This blocks make from accessing all non-stdio file descriptors from the parent process, including those of the jobserver. Because make was getting passed jobserver information via MAKEFLAGS but was unable to access the jobserver, it prints an error like the following and proceeds to run a single-threaded build: ``` make: warning: jobserver unavailable: using -j1. Add '+' to parent make rule. ``` As a workaround, disable jobserver support on OSX so that cmake-rs instead passes `--parallel $NUM_JOBS` to CMake, allowing for a faster multi-threaded build. However, there is an exception made if the available jobserver is based on a named pipe. Since access to this pipe does not rely on the inheritance of file descriptors, the underlying build will be able to access the jobserver in this case.
1 parent 94da9de commit 9e1fce1

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed

src/lib.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -837,16 +837,22 @@ impl Config {
837837
let mut use_jobserver = false;
838838
if fs::metadata(build.join("Makefile")).is_ok() {
839839
match env::var_os("CARGO_MAKEFLAGS") {
840-
// Only do this on non-windows and non-bsd
841-
// On Windows, we could be invoking make instead of
842-
// mingw32-make which doesn't work with our jobserver
843-
// bsdmake also does not work with our job server
840+
// Only do this on non-windows, non-bsd, and non-macos (unless a named pipe
841+
// jobserver is available)
842+
// * On Windows, we could be invoking make instead of
843+
// mingw32-make which doesn't work with our jobserver
844+
// * bsdmake also does not work with our job server
845+
// * On macOS, CMake blocks propagation of the jobserver's file descriptors to make
846+
// However, if the jobserver is based on a named pipe, this will be available to
847+
// the build.
844848
Some(ref makeflags)
845849
if !(cfg!(windows)
846850
|| cfg!(target_os = "openbsd")
847851
|| cfg!(target_os = "netbsd")
848852
|| cfg!(target_os = "freebsd")
849-
|| cfg!(target_os = "dragonfly")) =>
853+
|| cfg!(target_os = "dragonfly")
854+
|| (cfg!(target_os = "macos")
855+
&& !uses_named_pipe_jobserver(makeflags))) =>
850856
{
851857
use_jobserver = true;
852858
cmd.env("MAKEFLAGS", makeflags);
@@ -1115,8 +1121,19 @@ fn fail(s: &str) -> ! {
11151121
panic!("\n{}\n\nbuild script failed, must exit now", s)
11161122
}
11171123

1124+
/// Returns whether the given MAKEFLAGS indicate that there is an available
1125+
/// jobserver that uses a named pipe (fifo)
1126+
fn uses_named_pipe_jobserver(makeflags: &OsStr) -> bool {
1127+
makeflags
1128+
.to_string_lossy()
1129+
// auth option as defined in
1130+
// https://www.gnu.org/software/make/manual/html_node/POSIX-Jobserver.html#POSIX-Jobserver
1131+
.contains("--jobserver-auth=fifo:")
1132+
}
1133+
11181134
#[cfg(test)]
11191135
mod tests {
1136+
use super::uses_named_pipe_jobserver;
11201137
use super::Version;
11211138

11221139
#[test]
@@ -1132,4 +1149,14 @@ CMake suite maintained and supported by Kitware (kitware.com/cmake).
11321149

11331150
let _v = Version::from_command("cmake".as_ref()).unwrap();
11341151
}
1152+
1153+
#[test]
1154+
fn test_uses_fifo_jobserver() {
1155+
assert!(uses_named_pipe_jobserver(
1156+
"-j --jobserver-auth=fifo:/foo".as_ref()
1157+
));
1158+
assert!(!uses_named_pipe_jobserver(
1159+
"-j --jobserver-auth=8:9".as_ref()
1160+
));
1161+
}
11351162
}

0 commit comments

Comments
 (0)