Fix race condition between simultaneous build scripts creating symlinks
diff --git a/gen/build/src/out.rs b/gen/build/src/out.rs
index e275049..5fe957c 100644
--- a/gen/build/src/out.rs
+++ b/gen/build/src/out.rs
@@ -1,6 +1,7 @@
use crate::error::{Error, Result};
use crate::gen::fs;
use crate::paths;
+use std::io;
use std::path::Path;
pub(crate) fn write(path: impl AsRef<Path>, content: &[u8]) -> Result<()> {
@@ -43,8 +44,22 @@
match paths::symlink_or_copy(original, link) {
// As long as symlink_or_copy succeeded, ignore any create_dir_all error.
Ok(()) => Ok(()),
- // If create_dir_all and symlink_or_copy both failed, prefer the first error.
- Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))),
+ Err(err) => {
+ if err.kind() == io::ErrorKind::AlreadyExists {
+ // This is fine, a different simultaneous build script already
+ // created the same link or copy. The cxx_build target directory
+ // is laid out such that the same path never refers to two
+ // different targets during the same multi-crate build, so if
+ // some other build script already created the same path then we
+ // know it refers to the identical target that the current build
+ // script was trying to create.
+ Ok(())
+ } else {
+ // If create_dir_all and symlink_or_copy both failed, prefer the
+ // first error.
+ Err(Error::Fs(create_dir_error.unwrap_or(err)))
+ }
+ }
}
}
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index 7053cc4..bfda582 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -13,6 +13,15 @@
message: String,
}
+impl Error {
+ pub fn kind(&self) -> io::ErrorKind {
+ match &self.source {
+ Some(io_error) => io_error.kind(),
+ None => io::ErrorKind::Other,
+ }
+ }
+}
+
impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(&self.message)