2018-01-16 17:30:57 -06:00
|
|
|
// 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() {
|
2018-02-22 17:37:44 -06:00
|
|
|
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();
|
|
|
|
}
|
2018-01-16 17:30:57 -06:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2018-02-22 17:37:44 -06:00
|
|
|
let mut contents = Vec::new();
|
|
|
|
File::open(&ok).unwrap().read_to_end(&mut contents).unwrap();
|
2018-01-16 17:30:57 -06:00
|
|
|
|
|
|
|
for j in 0..i {
|
2018-02-22 17:37:44 -06:00
|
|
|
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[..]));
|
2018-01-16 17:30:57 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|