diff options
Diffstat (limited to 'tests/run-make/long-linker-command-lines-cmd-exe')
3 files changed, 109 insertions, 0 deletions
diff --git a/tests/run-make/long-linker-command-lines-cmd-exe/Makefile b/tests/run-make/long-linker-command-lines-cmd-exe/Makefile new file mode 100644 index 000000000..e43aab7f8 --- /dev/null +++ b/tests/run-make/long-linker-command-lines-cmd-exe/Makefile @@ -0,0 +1,7 @@ +# ignore-cross-compile +include ../tools.mk + +all: + $(RUSTC) foo.rs -g + cp foo.bat $(TMPDIR)/ + OUT_DIR="$(TMPDIR)" RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo) diff --git a/tests/run-make/long-linker-command-lines-cmd-exe/foo.bat b/tests/run-make/long-linker-command-lines-cmd-exe/foo.bat new file mode 100644 index 000000000..a9350f12b --- /dev/null +++ b/tests/run-make/long-linker-command-lines-cmd-exe/foo.bat @@ -0,0 +1 @@ +%MY_LINKER% %* diff --git a/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs b/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs new file mode 100644 index 000000000..74d7b9b07 --- /dev/null +++ b/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs @@ -0,0 +1,101 @@ +// Like the `long-linker-command-lines` test this test attempts to blow +// a command line limit for running the linker. Unlike that test, however, +// this test is testing `cmd.exe` specifically rather than the OS. +// +// Unfortunately `cmd.exe` has a 8192 limit which is relatively small +// in the grand scheme of things and anyone sripting rustc's linker +// is probably using a `*.bat` script and is likely to hit this limit. +// +// This test uses a `foo.bat` script as the linker which just simply +// delegates back to this program. The compiler should use a lower +// limit for arguments before passing everything via `@`, which +// means that everything should still succeed here. + +use std::env; +use std::fs::{self, File}; +use std::io::{BufWriter, Write, Read}; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + if !cfg!(windows) { + return + } + + let tmpdir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let ok = tmpdir.join("ok"); + let not_ok = tmpdir.join("not_ok"); + if env::var("YOU_ARE_A_LINKER").is_ok() { + match env::args_os().find(|a| a.to_string_lossy().contains("@")) { + Some(file) => { + let file = file.to_str().unwrap(); + fs::copy(&file[1..], &ok).unwrap(); + } + None => { File::create(¬_ok).unwrap(); } + } + return + } + + let rustc = env::var_os("RUSTC").unwrap_or("rustc".into()); + let me = env::current_exe().unwrap(); + let bat = me.parent() + .unwrap() + .join("foo.bat"); + let bat_linker = format!("linker={}", bat.display()); + for i in (1..).map(|i| i * 10) { + println!("attempt: {}", i); + + let file = tmpdir.join("bar.rs"); + let mut f = BufWriter::new(File::create(&file).unwrap()); + let mut lib_name = String::new(); + for _ in 0..i { + lib_name.push_str("foo"); + } + for j in 0..i { + writeln!(f, "#[link(name = \"{}{}\")]", lib_name, j).unwrap(); + } + writeln!(f, "extern {{}}\nfn main() {{}}").unwrap(); + f.into_inner().unwrap(); + + drop(fs::remove_file(&ok)); + drop(fs::remove_file(¬_ok)); + let status = Command::new(&rustc) + .arg(&file) + .arg("-C").arg(&bat_linker) + .arg("--out-dir").arg(&tmpdir) + .env("YOU_ARE_A_LINKER", "1") + .env("MY_LINKER", &me) + .status() + .unwrap(); + + if !status.success() { + panic!("rustc didn't succeed: {}", status); + } + + if !ok.exists() { + assert!(not_ok.exists()); + continue + } + + let mut contents = Vec::new(); + File::open(&ok).unwrap().read_to_end(&mut contents).unwrap(); + + for j in 0..i { + let exp = format!("{}{}", lib_name, j); + let exp = if cfg!(target_env = "msvc") { + let mut out = Vec::with_capacity(exp.len() * 2); + for c in exp.encode_utf16() { + // encode in little endian + out.push(c as u8); + out.push((c >> 8) as u8); + } + out + } else { + exp.into_bytes() + }; + assert!(contents.windows(exp.len()).any(|w| w == &exp[..])); + } + + break + } +} |