]> git.proxmox.com Git - rustc.git/blob - vendor/cc/tests/support/mod.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / vendor / cc / tests / support / mod.rs
1 #![allow(dead_code)]
2
3 use std::env;
4 use std::ffi::{OsStr, OsString};
5 use std::fs::{self, File};
6 use std::io;
7 use std::io::prelude::*;
8 use std::path::{Path, PathBuf};
9
10 use cc;
11 use tempdir::TempDir;
12
13 pub struct Test {
14 pub td: TempDir,
15 pub gcc: PathBuf,
16 pub msvc: bool,
17 }
18
19 pub struct Execution {
20 args: Vec<String>,
21 }
22
23 impl Test {
24 pub fn new() -> Test {
25 let mut gcc = PathBuf::from(env::current_exe().unwrap());
26 gcc.pop();
27 if gcc.ends_with("deps") {
28 gcc.pop();
29 }
30 let td = TempDir::new_in(&gcc, "gcc-test").unwrap();
31 gcc.push(format!("gcc-shim{}", env::consts::EXE_SUFFIX));
32 Test {
33 td: td,
34 gcc: gcc,
35 msvc: false,
36 }
37 }
38
39 pub fn gnu() -> Test {
40 let t = Test::new();
41 t.shim("cc").shim("c++").shim("ar");
42 t
43 }
44
45 pub fn msvc() -> Test {
46 let mut t = Test::new();
47 t.shim("cl").shim("lib.exe");
48 t.msvc = true;
49 t
50 }
51
52 pub fn shim(&self, name: &str) -> &Test {
53 link_or_copy(
54 &self.gcc,
55 self.td
56 .path()
57 .join(&format!("{}{}", name, env::consts::EXE_SUFFIX)),
58 )
59 .unwrap();
60 self
61 }
62
63 pub fn gcc(&self) -> cc::Build {
64 let mut cfg = cc::Build::new();
65 let target = if self.msvc {
66 "x86_64-pc-windows-msvc"
67 } else {
68 "x86_64-unknown-linux-gnu"
69 };
70
71 cfg.target(target)
72 .host(target)
73 .opt_level(2)
74 .debug(false)
75 .out_dir(self.td.path())
76 .__set_env("PATH", self.path())
77 .__set_env("GCCTEST_OUT_DIR", self.td.path());
78 if self.msvc {
79 cfg.compiler(self.td.path().join("cl"));
80 cfg.archiver(self.td.path().join("lib.exe"));
81 }
82 cfg
83 }
84
85 fn path(&self) -> OsString {
86 let mut path = env::split_paths(&env::var_os("PATH").unwrap()).collect::<Vec<_>>();
87 path.insert(0, self.td.path().to_owned());
88 env::join_paths(path).unwrap()
89 }
90
91 pub fn cmd(&self, i: u32) -> Execution {
92 let mut s = String::new();
93 File::open(self.td.path().join(format!("out{}", i)))
94 .unwrap()
95 .read_to_string(&mut s)
96 .unwrap();
97 Execution {
98 args: s.lines().map(|s| s.to_string()).collect(),
99 }
100 }
101 }
102
103 impl Execution {
104 pub fn must_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
105 if !self.has(p.as_ref()) {
106 panic!("didn't find {:?} in {:?}", p.as_ref(), self.args);
107 } else {
108 self
109 }
110 }
111
112 pub fn must_not_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
113 if self.has(p.as_ref()) {
114 panic!("found {:?}", p.as_ref());
115 } else {
116 self
117 }
118 }
119
120 pub fn has(&self, p: &OsStr) -> bool {
121 self.args.iter().any(|arg| OsStr::new(arg) == p)
122 }
123
124 pub fn must_have_in_order(&self, before: &str, after: &str) -> &Execution {
125 let before_position = self
126 .args
127 .iter()
128 .rposition(|x| OsStr::new(x) == OsStr::new(before));
129 let after_position = self
130 .args
131 .iter()
132 .rposition(|x| OsStr::new(x) == OsStr::new(after));
133 match (before_position, after_position) {
134 (Some(b), Some(a)) if b < a => {}
135 (b, a) => panic!(
136 "{:?} (last position: {:?}) did not appear before {:?} (last position: {:?})",
137 before, b, after, a
138 ),
139 };
140 self
141 }
142 }
143
144 /// Hard link an executable or copy it if that fails.
145 ///
146 /// We first try to hard link an executable to save space. If that fails (as on Windows with
147 /// different mount points, issue #60), we copy.
148 #[cfg(not(target_os = "macos"))]
149 fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
150 let from = from.as_ref();
151 let to = to.as_ref();
152 fs::hard_link(from, to).or_else(|_| fs::copy(from, to).map(|_| ()))
153 }
154
155 /// Copy an executable.
156 ///
157 /// On macOS, hard linking the executable leads to strange failures (issue #419), so we just copy.
158 #[cfg(target_os = "macos")]
159 fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
160 fs::copy(from, to).map(|_| ())
161 }