]> git.lizzy.rs Git - rust.git/blob - tests/run-make-fulldeps/long-linker-command-lines-cmd-exe/foo.rs
Rollup merge of #106144 - tgross35:patch-1, r=Mark-Simulacrum
[rust.git] / tests / run-make-fulldeps / long-linker-command-lines-cmd-exe / foo.rs
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(&not_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(&not_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 }