Try to detect symlinking disabled on Windows
diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
index 4f2eb8e..f6ec026 100644
--- a/tools/cargo/build.rs
+++ b/tools/cargo/build.rs
@@ -1,8 +1,12 @@
use std::io::{self, Write};
+#[cfg(windows)]
+use std::os::windows::fs as windows;
use std::path::Path;
use std::process;
+#[cfg(windows)]
+use std::{env, fs};
-const NOSYMLINK: &str = "
+const MISSING: &str = "
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When building `cxx` from a git clone, git's symlink support needs
to be enabled on platforms that have it off by default (Windows).
@@ -23,9 +27,46 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
";
+#[cfg(windows)]
+const DENIED: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone on Windows we need Developer
+Mode enabled for symlink support.
+
+To enable Developer Mode: go under Settings to Update & Security,
+then 'For developers', and turn on the toggle for Developer Mode.
+
+For more explanation of symlinks in Windows, see these resources:
+> https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/
+> https://docs.microsoft.com/windows/uwp/get-started/enable-your-device-for-development
+
+Symlinks are only required when compiling locally from a clone of
+the git repository---they are NOT required when building `cxx` as
+a Cargo-managed (possibly transitive) build dependency downloaded
+through crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
fn main() {
- if !Path::new("src/syntax/mod.rs").exists() {
- let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
- process::exit(1);
+ if Path::new("src/syntax/mod.rs").exists() {
+ return;
}
+
+ #[allow(unused_mut)]
+ let mut message = MISSING;
+
+ #[cfg(windows)]
+ if let Some(out_dir) = env::var_os("OUT_DIR") {
+ let parent_dir = Path::new(&out_dir).join("symlink");
+ let from_dir = parent_dir.join("from");
+ let to_dir = parent_dir.join("to");
+ if fs::create_dir_all(&from_dir).is_ok()
+ && windows::symlink_dir(&from_dir, &to_dir).is_err()
+ {
+ message = DENIED;
+ }
+ }
+
+ let _ = io::stderr().write_all(message.as_bytes());
+ process::exit(1);
}