Skip to content

Commit 4e6c7f7

Browse files
authored
Unrolled build for rust-lang#123149
Rollup merge of rust-lang#123149 - jieyouxu:rmake-arguments-non-c-like-enum, r=Mark-Simulacrum Port argument-non-c-like-enum to Rust Part of rust-lang#121876.
2 parents 5958f5e + fad8213 commit 4e6c7f7

File tree

7 files changed

+328
-27
lines changed

7 files changed

+328
-27
lines changed

src/tools/compiletest/src/runtest.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -3926,11 +3926,17 @@ impl<'test> TestCx<'test> {
39263926
cmd.env("IS_MSVC", "1")
39273927
.env("IS_WINDOWS", "1")
39283928
.env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
3929-
.env("CC", format!("'{}' {}", self.config.cc, cflags))
3930-
.env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
3929+
// Note: we diverge from legacy run_make and don't lump `CC` the compiler and
3930+
// default flags together.
3931+
.env("CC_DEFAULT_FLAGS", &cflags)
3932+
.env("CC", &self.config.cc)
3933+
.env("CXX_DEFAULT_FLAGS", &cxxflags)
3934+
.env("CXX", &self.config.cxx);
39313935
} else {
3932-
cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
3933-
.env("CXX", format!("{} {}", self.config.cxx, self.config.cxxflags))
3936+
cmd.env("CC_DEFAULT_FLAGS", &self.config.cflags)
3937+
.env("CC", &self.config.cc)
3938+
.env("CXX_DEFAULT_FLAGS", &self.config.cxxflags)
3939+
.env("CXX", &self.config.cxx)
39343940
.env("AR", &self.config.ar);
39353941

39363942
if self.config.target.contains("windows") {

src/tools/run-make-support/src/cc.rs

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
use std::env;
2+
use std::path::Path;
3+
use std::process::{Command, Output};
4+
5+
use crate::{bin_name, cygpath_windows, handle_failed_output, is_msvc, is_windows, tmp_dir, uname};
6+
7+
/// Construct a new platform-specific C compiler invocation.
8+
///
9+
/// WARNING: This means that what flags are accepted by the underlying C compiler is
10+
/// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
11+
pub fn cc() -> Cc {
12+
Cc::new()
13+
}
14+
15+
/// A platform-specific C compiler invocation builder. The specific C compiler used is
16+
/// passed down from compiletest.
17+
#[derive(Debug)]
18+
pub struct Cc {
19+
cmd: Command,
20+
}
21+
22+
impl Cc {
23+
/// Construct a new platform-specific C compiler invocation.
24+
///
25+
/// WARNING: This means that what flags are accepted by the underlying C compile is
26+
/// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`.
27+
pub fn new() -> Self {
28+
let compiler = env::var("CC").unwrap();
29+
30+
let mut cmd = Command::new(compiler);
31+
32+
let default_cflags = env::var("CC_DEFAULT_FLAGS").unwrap();
33+
for flag in default_cflags.split(char::is_whitespace) {
34+
cmd.arg(flag);
35+
}
36+
37+
Self { cmd }
38+
}
39+
40+
/// Specify path of the input file.
41+
pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
42+
self.cmd.arg(path.as_ref());
43+
self
44+
}
45+
46+
/// Add a *platform-and-compiler-specific* argument. Please consult the docs for the various
47+
/// possible C compilers on the various platforms to check which arguments are legal for
48+
/// which compiler.
49+
pub fn arg(&mut self, flag: &str) -> &mut Self {
50+
self.cmd.arg(flag);
51+
self
52+
}
53+
54+
/// Add multiple *platform-and-compiler-specific* arguments. Please consult the docs for the
55+
/// various possible C compilers on the various platforms to check which arguments are legal
56+
/// for which compiler.
57+
pub fn args(&mut self, args: &[&str]) -> &mut Self {
58+
self.cmd.args(args);
59+
self
60+
}
61+
62+
/// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler. This assumes that the executable
63+
/// is under `$TMPDIR`.
64+
pub fn out_exe(&mut self, name: &str) -> &mut Self {
65+
// Ref: tools.mk (irrelevant lines omitted):
66+
//
67+
// ```makefile
68+
// ifdef IS_MSVC
69+
// OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
70+
// -Fo:`cygpath -w $(TMPDIR)/$(1).obj`
71+
// else
72+
// OUT_EXE=-o $(TMPDIR)/$(1)
73+
// endif
74+
// ```
75+
76+
if is_msvc() {
77+
let fe_path = cygpath_windows(tmp_dir().join(bin_name(name)));
78+
let fo_path = cygpath_windows(tmp_dir().join(format!("{name}.obj")));
79+
self.cmd.arg(format!("-Fe:{fe_path}"));
80+
self.cmd.arg(format!("-Fo:{fo_path}"));
81+
} else {
82+
self.cmd.arg("-o");
83+
self.cmd.arg(tmp_dir().join(name));
84+
}
85+
86+
self
87+
}
88+
89+
/// Run the constructed C invocation command and assert that it is successfully run.
90+
#[track_caller]
91+
pub fn run(&mut self) -> Output {
92+
let caller_location = std::panic::Location::caller();
93+
let caller_line_number = caller_location.line();
94+
95+
let output = self.cmd.output().unwrap();
96+
if !output.status.success() {
97+
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
98+
}
99+
output
100+
}
101+
102+
/// Inspect what the underlying [`Command`] is up to the current construction.
103+
pub fn inspect(&mut self, f: impl FnOnce(&Command)) -> &mut Self {
104+
f(&self.cmd);
105+
self
106+
}
107+
}
108+
109+
/// `EXTRACFLAGS`
110+
pub fn extra_c_flags() -> Vec<&'static str> {
111+
// Adapted from tools.mk (trimmed):
112+
//
113+
// ```makefile
114+
// ifdef IS_WINDOWS
115+
// ifdef IS_MSVC
116+
// EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib bcrypt.lib ntdll.lib synchronization.lib
117+
// else
118+
// EXTRACFLAGS := -lws2_32 -luserenv -lbcrypt -lntdll -lsynchronization
119+
// endif
120+
// else
121+
// ifeq ($(UNAME),Darwin)
122+
// EXTRACFLAGS := -lresolv
123+
// else
124+
// ifeq ($(UNAME),FreeBSD)
125+
// EXTRACFLAGS := -lm -lpthread -lgcc_s
126+
// else
127+
// ifeq ($(UNAME),SunOS)
128+
// EXTRACFLAGS := -lm -lpthread -lposix4 -lsocket -lresolv
129+
// else
130+
// ifeq ($(UNAME),OpenBSD)
131+
// EXTRACFLAGS := -lm -lpthread -lc++abi
132+
// else
133+
// EXTRACFLAGS := -lm -lrt -ldl -lpthread
134+
// endif
135+
// endif
136+
// endif
137+
// endif
138+
// endif
139+
// ```
140+
141+
if is_windows() {
142+
if is_msvc() {
143+
vec![
144+
"ws2_32.lib",
145+
"userenv.lib",
146+
"advapi32.lib",
147+
"bcrypt.lib",
148+
"ntdll.lib",
149+
"synchronization.lib",
150+
]
151+
} else {
152+
vec!["-lws2_32", "-luserenv", "-lbcrypt", "-lntdll", "-lsynchronization"]
153+
}
154+
} else {
155+
match uname() {
156+
n if n.contains("Darwin") => vec!["-lresolv"],
157+
n if n.contains("FreeBSD") => vec!["-lm", "-lpthread", "-lgcc_s"],
158+
n if n.contains("SunOS") => {
159+
vec!["-lm", "-lpthread", "-lposix4", "-lsocket", "-lresolv"]
160+
}
161+
n if n.contains("OpenBSD") => vec!["-lm", "-lpthread", "-lc++abi"],
162+
_ => vec!["-lm", "-lrt", "-ldl", "-lpthread"],
163+
}
164+
}
165+
}
166+
167+
/// `EXTRACXXFLAGS`
168+
pub fn extra_cxx_flags() -> Vec<&'static str> {
169+
// Adapted from tools.mk (trimmed):
170+
//
171+
// ```makefile
172+
// ifdef IS_WINDOWS
173+
// ifdef IS_MSVC
174+
// else
175+
// EXTRACXXFLAGS := -lstdc++
176+
// endif
177+
// else
178+
// ifeq ($(UNAME),Darwin)
179+
// EXTRACXXFLAGS := -lc++
180+
// else
181+
// ifeq ($(UNAME),FreeBSD)
182+
// else
183+
// ifeq ($(UNAME),SunOS)
184+
// else
185+
// ifeq ($(UNAME),OpenBSD)
186+
// else
187+
// EXTRACXXFLAGS := -lstdc++
188+
// endif
189+
// endif
190+
// endif
191+
// endif
192+
// endif
193+
// ```
194+
if is_windows() {
195+
if is_msvc() { vec![] } else { vec!["-lstdc++"] }
196+
} else {
197+
match uname() {
198+
n if n.contains("Darwin") => vec!["-lc++"],
199+
_ => vec!["-lstdc++"],
200+
}
201+
}
202+
}

src/tools/run-make-support/src/lib.rs

+87-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
pub mod cc;
12
pub mod run;
23
pub mod rustc;
34
pub mod rustdoc;
45

56
use std::env;
6-
use std::path::PathBuf;
7-
use std::process::Output;
7+
use std::path::{Path, PathBuf};
8+
use std::process::{Command, Output};
89

910
pub use object;
1011
pub use wasmparser;
1112

13+
pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
1214
pub use run::{run, run_fail};
1315
pub use rustc::{aux_build, rustc, Rustc};
1416
pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
@@ -18,6 +20,89 @@ pub fn tmp_dir() -> PathBuf {
1820
env::var_os("TMPDIR").unwrap().into()
1921
}
2022

23+
/// `TARGET`
24+
pub fn target() -> String {
25+
env::var("TARGET").unwrap()
26+
}
27+
28+
/// Check if target is windows-like.
29+
pub fn is_windows() -> bool {
30+
env::var_os("IS_WINDOWS").is_some()
31+
}
32+
33+
/// Check if target uses msvc.
34+
pub fn is_msvc() -> bool {
35+
env::var_os("IS_MSVC").is_some()
36+
}
37+
38+
/// Construct a path to a static library under `$TMPDIR` given the library name. This will return a
39+
/// path with `$TMPDIR` joined with platform-and-compiler-specific library name.
40+
pub fn static_lib(name: &str) -> PathBuf {
41+
tmp_dir().join(static_lib_name(name))
42+
}
43+
44+
/// Construct the static library name based on the platform.
45+
pub fn static_lib_name(name: &str) -> String {
46+
// See tools.mk (irrelevant lines omitted):
47+
//
48+
// ```makefile
49+
// ifeq ($(UNAME),Darwin)
50+
// STATICLIB = $(TMPDIR)/lib$(1).a
51+
// else
52+
// ifdef IS_WINDOWS
53+
// ifdef IS_MSVC
54+
// STATICLIB = $(TMPDIR)/$(1).lib
55+
// else
56+
// STATICLIB = $(TMPDIR)/lib$(1).a
57+
// endif
58+
// else
59+
// STATICLIB = $(TMPDIR)/lib$(1).a
60+
// endif
61+
// endif
62+
// ```
63+
assert!(!name.contains(char::is_whitespace), "name cannot contain whitespace");
64+
65+
if target().contains("msvc") { format!("{name}.lib") } else { format!("lib{name}.a") }
66+
}
67+
68+
/// Construct the binary name based on platform.
69+
pub fn bin_name(name: &str) -> String {
70+
if is_windows() { format!("{name}.exe") } else { name.to_string() }
71+
}
72+
73+
/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
74+
/// available on the platform!
75+
#[track_caller]
76+
pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
77+
let caller_location = std::panic::Location::caller();
78+
let caller_line_number = caller_location.line();
79+
80+
let mut cygpath = Command::new("cygpath");
81+
cygpath.arg("-w");
82+
cygpath.arg(path.as_ref());
83+
let output = cygpath.output().unwrap();
84+
if !output.status.success() {
85+
handle_failed_output(&format!("{:#?}", cygpath), output, caller_line_number);
86+
}
87+
let s = String::from_utf8(output.stdout).unwrap();
88+
// cygpath -w can attach a newline
89+
s.trim().to_string()
90+
}
91+
92+
/// Run `uname`. This assumes that `uname` is available on the platform!
93+
#[track_caller]
94+
pub fn uname() -> String {
95+
let caller_location = std::panic::Location::caller();
96+
let caller_line_number = caller_location.line();
97+
98+
let mut uname = Command::new("uname");
99+
let output = uname.output().unwrap();
100+
if !output.status.success() {
101+
handle_failed_output(&format!("{:#?}", uname), output, caller_line_number);
102+
}
103+
String::from_utf8(output.stdout).unwrap()
104+
}
105+
21106
fn handle_failed_output(cmd: &str, output: Output, caller_line_number: u32) -> ! {
22107
if output.status.success() {
23108
eprintln!("command incorrectly succeeded at line {caller_line_number}");

src/tools/run-make-support/src/run.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,14 @@ use std::env;
22
use std::path::{Path, PathBuf};
33
use std::process::{Command, Output};
44

5-
use super::handle_failed_output;
5+
use crate::is_windows;
66

7-
fn run_common(bin_name: &str) -> (Command, Output) {
8-
let target = env::var("TARGET").unwrap();
9-
10-
let bin_name =
11-
if target.contains("windows") { format!("{}.exe", bin_name) } else { bin_name.to_owned() };
7+
use super::{bin_name, handle_failed_output};
128

9+
fn run_common(name: &str) -> (Command, Output) {
1310
let mut bin_path = PathBuf::new();
1411
bin_path.push(env::var("TMPDIR").unwrap());
15-
bin_path.push(&bin_name);
12+
bin_path.push(&bin_name(name));
1613
let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap();
1714
let mut cmd = Command::new(bin_path);
1815
cmd.env(&ld_lib_path_envvar, {
@@ -27,7 +24,7 @@ fn run_common(bin_name: &str) -> (Command, Output) {
2724
env::join_paths(paths.iter()).unwrap()
2825
});
2926

30-
if target.contains("windows") {
27+
if is_windows() {
3128
let mut paths = vec![];
3229
for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) {
3330
paths.push(p.to_path_buf());
@@ -42,11 +39,11 @@ fn run_common(bin_name: &str) -> (Command, Output) {
4239

4340
/// Run a built binary and make sure it succeeds.
4441
#[track_caller]
45-
pub fn run(bin_name: &str) -> Output {
42+
pub fn run(name: &str) -> Output {
4643
let caller_location = std::panic::Location::caller();
4744
let caller_line_number = caller_location.line();
4845

49-
let (cmd, output) = run_common(bin_name);
46+
let (cmd, output) = run_common(name);
5047
if !output.status.success() {
5148
handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
5249
}
@@ -55,11 +52,11 @@ pub fn run(bin_name: &str) -> Output {
5552

5653
/// Run a built binary and make sure it fails.
5754
#[track_caller]
58-
pub fn run_fail(bin_name: &str) -> Output {
55+
pub fn run_fail(name: &str) -> Output {
5956
let caller_location = std::panic::Location::caller();
6057
let caller_line_number = caller_location.line();
6158

62-
let (cmd, output) = run_common(bin_name);
59+
let (cmd, output) = run_common(name);
6360
if output.status.success() {
6461
handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
6562
}

0 commit comments

Comments
 (0)