]>
Commit | Line | Data |
---|---|---|
ff7c6d11 XL |
1 | // Like the `long-linker-command-lines` test this test attempts to blow |
2 | // a command line limit for running the linker. Unlike that test, however, | |
3 | // this test is testing `cmd.exe` specifically rather than the OS. | |
4 | // | |
5 | // Unfortunately `cmd.exe` has a 8192 limit which is relatively small | |
6 | // in the grand scheme of things and anyone sripting rustc's linker | |
7 | // is probably using a `*.bat` script and is likely to hit this limit. | |
8 | // | |
9 | // This test uses a `foo.bat` script as the linker which just simply | |
10 | // delegates back to this program. The compiler should use a lower | |
11 | // limit for arguments before passing everything via `@`, which | |
12 | // means that everything should still succeed here. | |
13 | ||
14 | use std::env; | |
15 | use std::fs::{self, File}; | |
16 | use std::io::{BufWriter, Write, Read}; | |
17 | use std::path::PathBuf; | |
18 | use std::process::Command; | |
19 | ||
20 | fn main() { | |
21 | if !cfg!(windows) { | |
22 | return | |
23 | } | |
24 | ||
25 | let tmpdir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); | |
26 | let ok = tmpdir.join("ok"); | |
27 | let not_ok = tmpdir.join("not_ok"); | |
28 | if env::var("YOU_ARE_A_LINKER").is_ok() { | |
29 | match env::args_os().find(|a| a.to_string_lossy().contains("@")) { | |
30 | Some(file) => { | |
31 | let file = file.to_str().unwrap(); | |
32 | fs::copy(&file[1..], &ok).unwrap(); | |
33 | } | |
34 | None => { File::create(¬_ok).unwrap(); } | |
35 | } | |
36 | return | |
37 | } | |
38 | ||
39 | let rustc = env::var_os("RUSTC").unwrap_or("rustc".into()); | |
40 | let me = env::current_exe().unwrap(); | |
41 | let bat = me.parent() | |
42 | .unwrap() | |
43 | .join("foo.bat"); | |
44 | let bat_linker = format!("linker={}", bat.display()); | |
45 | for i in (1..).map(|i| i * 10) { | |
46 | println!("attempt: {}", i); | |
47 | ||
48 | let file = tmpdir.join("bar.rs"); | |
49 | let mut f = BufWriter::new(File::create(&file).unwrap()); | |
50 | let mut lib_name = String::new(); | |
51 | for _ in 0..i { | |
52 | lib_name.push_str("foo"); | |
53 | } | |
54 | for j in 0..i { | |
55 | writeln!(f, "#[link(name = \"{}{}\")]", lib_name, j).unwrap(); | |
56 | } | |
57 | writeln!(f, "extern {{}}\nfn main() {{}}").unwrap(); | |
58 | f.into_inner().unwrap(); | |
59 | ||
60 | drop(fs::remove_file(&ok)); | |
61 | drop(fs::remove_file(¬_ok)); | |
62 | let status = Command::new(&rustc) | |
63 | .arg(&file) | |
64 | .arg("-C").arg(&bat_linker) | |
65 | .arg("--out-dir").arg(&tmpdir) | |
66 | .env("YOU_ARE_A_LINKER", "1") | |
67 | .env("MY_LINKER", &me) | |
68 | .status() | |
69 | .unwrap(); | |
70 | ||
71 | if !status.success() { | |
72 | panic!("rustc didn't succeed: {}", status); | |
73 | } | |
74 | ||
75 | if !ok.exists() { | |
76 | assert!(not_ok.exists()); | |
77 | continue | |
78 | } | |
79 | ||
80 | let mut contents = Vec::new(); | |
81 | File::open(&ok).unwrap().read_to_end(&mut contents).unwrap(); | |
82 | ||
83 | for j in 0..i { | |
84 | let exp = format!("{}{}", lib_name, j); | |
85 | let exp = if cfg!(target_env = "msvc") { | |
86 | let mut out = Vec::with_capacity(exp.len() * 2); | |
87 | for c in exp.encode_utf16() { | |
88 | // encode in little endian | |
89 | out.push(c as u8); | |
90 | out.push((c >> 8) as u8); | |
91 | } | |
92 | out | |
93 | } else { | |
94 | exp.into_bytes() | |
95 | }; | |
96 | assert!(contents.windows(exp.len()).any(|w| w == &exp[..])); | |
97 | } | |
98 | ||
99 | break | |
100 | } | |
101 | } |