Skip to content

Commit ad43613

Browse files
committed
rustpkg: Pass command-line arguments to rustc
rustpkg now accepts most of rustc's command-line arguments and passes them along to rustc when building or installing. A few rarely-used arguments aren't implemented yet. rustpkg doesn't support flags that don't make sense with rustpkg (for example, --bin and --lib, which get inferred from crate file names). Closes #8522
1 parent a9ac272 commit ad43613

File tree

6 files changed

+704
-65
lines changed

6 files changed

+704
-65
lines changed

src/librustpkg/api.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub fn default_context(p: Path) -> BuildContext {
2929
pub fn new_default_context(c: workcache::Context, p: Path) -> BuildContext {
3030
BuildContext {
3131
context: Context {
32+
cfgs: ~[],
33+
rustc_flags: RustcFlags::default(),
3234
use_rust_path_hack: false,
3335
sysroot: p
3436
},
@@ -44,7 +46,6 @@ fn binary_is_fresh(path: &str, in_hash: &str) -> bool {
4446
in_hash == digest_only_date(&Path(path))
4547
}
4648

47-
4849
pub fn new_workcache_context(p: &Path) -> workcache::Context {
4950
let db_file = p.push("rustpkg_db.json"); // ??? probably wrong
5051
debug!("Workcache database file: %s", db_file.to_str());

src/librustpkg/context.rs

+222-3
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@
1010

1111
// Context data structure used by rustpkg
1212

13-
use std::os;
13+
use std::{io, os};
1414
use extra::workcache;
15+
use rustc::driver::session::{OptLevel, No};
1516

1617
#[deriving(Clone)]
1718
pub struct Context {
19+
// Config strings that the user passed in with --cfg
20+
cfgs: ~[~str],
21+
// Flags to pass to rustc
22+
rustc_flags: RustcFlags,
1823
// If use_rust_path_hack is true, rustpkg searches for sources
1924
// in *package* directories that are in the RUST_PATH (for example,
2025
// FOO/src/bar-0.1 instead of FOO). The flag doesn't affect where
@@ -40,15 +45,82 @@ impl BuildContext {
4045
pub fn sysroot_to_use(&self) -> Path {
4146
self.context.sysroot_to_use()
4247
}
48+
49+
/// Returns the flags to pass to rustc, as a vector of strings
50+
pub fn flag_strs(&self) -> ~[~str] {
51+
self.context.flag_strs()
52+
}
53+
54+
pub fn compile_upto(&self) -> StopBefore {
55+
self.context.compile_upto()
56+
}
57+
}
58+
59+
/*
60+
Deliberately unsupported rustc flags:
61+
--bin, --lib inferred from crate file names
62+
-L inferred from extern mods
63+
--out-dir inferred from RUST_PATH
64+
--test use `rustpkg test`
65+
-v -h --ls don't make sense with rustpkg
66+
-W -A -D -F - use pragmas instead
67+
68+
rustc flags that aren't implemented yet:
69+
--passes
70+
--llvm-arg
71+
--target-feature
72+
--android-cross-path
73+
*/
74+
pub struct RustcFlags {
75+
compile_upto: StopBefore,
76+
// Linker to use with the --linker flag
77+
linker: Option<~str>,
78+
// Extra arguments to pass to rustc with the --link-args flag
79+
link_args: Option<~str>,
80+
// Optimization level. 0 = default. -O = 2.
81+
optimization_level: OptLevel,
82+
// True if the user passed in --save-temps
83+
save_temps: bool,
84+
// Target (defaults to rustc's default target)
85+
target: Option<~str>,
86+
// Target CPU (defaults to rustc's default target CPU)
87+
target_cpu: Option<~str>,
88+
// Any -Z features
89+
experimental_features: Option<~[~str]>
90+
}
91+
92+
impl Clone for RustcFlags {
93+
fn clone(&self) -> RustcFlags {
94+
RustcFlags {
95+
compile_upto: self.compile_upto,
96+
linker: self.linker.clone(),
97+
link_args: self.link_args.clone(),
98+
optimization_level: self.optimization_level,
99+
save_temps: self.save_temps,
100+
target: self.target.clone(),
101+
target_cpu: self.target_cpu.clone(),
102+
experimental_features: self.experimental_features.clone()
103+
}
104+
}
105+
}
106+
107+
#[deriving(Eq)]
108+
pub enum StopBefore {
109+
Nothing, // compile everything
110+
Link, // --no-link
111+
LLVMCompileBitcode, // --emit-llvm without -S
112+
LLVMAssemble, // -S --emit-llvm
113+
Assemble, // -S without --emit-llvm
114+
Trans, // --no-trans
115+
Pretty, // --pretty
116+
Analysis, // --parse-only
43117
}
44118

45119
impl Context {
46120
pub fn sysroot(&self) -> Path {
47121
self.sysroot.clone()
48122
}
49-
}
50123

51-
impl Context {
52124
/// Debugging
53125
pub fn sysroot_str(&self) -> ~str {
54126
self.sysroot.to_str()
@@ -63,6 +135,15 @@ impl Context {
63135
self.sysroot.pop().pop().pop()
64136
}
65137
}
138+
139+
/// Returns the flags to pass to rustc, as a vector of strings
140+
pub fn flag_strs(&self) -> ~[~str] {
141+
self.rustc_flags.flag_strs()
142+
}
143+
144+
pub fn compile_upto(&self) -> StopBefore {
145+
self.rustc_flags.compile_upto
146+
}
66147
}
67148

68149
/// We assume that if ../../rustc exists, then we're running
@@ -72,3 +153,141 @@ pub fn in_target(sysroot: &Path) -> bool {
72153
debug!("Checking whether %s is in target", sysroot.to_str());
73154
os::path_is_dir(&sysroot.pop().pop().push("rustc"))
74155
}
156+
157+
impl RustcFlags {
158+
fn flag_strs(&self) -> ~[~str] {
159+
let linker_flag = match self.linker {
160+
Some(ref l) => ~[~"--linker", l.clone()],
161+
None => ~[]
162+
};
163+
let link_args_flag = match self.link_args {
164+
Some(ref l) => ~[~"--link-args", l.clone()],
165+
None => ~[]
166+
};
167+
let save_temps_flag = if self.save_temps { ~[~"--save-temps"] } else { ~[] };
168+
let target_flag = match self.target {
169+
Some(ref l) => ~[~"--target", l.clone()],
170+
None => ~[]
171+
};
172+
let target_cpu_flag = match self.target_cpu {
173+
Some(ref l) => ~[~"--target-cpu", l.clone()],
174+
None => ~[]
175+
};
176+
let z_flags = match self.experimental_features {
177+
Some(ref ls) => ls.flat_map(|s| ~[~"-Z", s.clone()]),
178+
None => ~[]
179+
};
180+
linker_flag
181+
+ link_args_flag
182+
+ save_temps_flag
183+
+ target_flag
184+
+ target_cpu_flag
185+
+ z_flags + (match self.compile_upto {
186+
LLVMCompileBitcode => ~[~"--emit-llvm"],
187+
LLVMAssemble => ~[~"--emit-llvm", ~"-S"],
188+
Link => ~[~"-c"],
189+
Trans => ~[~"--no-trans"],
190+
Assemble => ~[~"-S"],
191+
// n.b. Doesn't support all flavors of --pretty (yet)
192+
Pretty => ~[~"--pretty"],
193+
Analysis => ~[~"--parse-only"],
194+
Nothing => ~[]
195+
})
196+
}
197+
198+
pub fn default() -> RustcFlags {
199+
RustcFlags {
200+
linker: None,
201+
link_args: None,
202+
compile_upto: Nothing,
203+
optimization_level: No,
204+
save_temps: false,
205+
target: None,
206+
target_cpu: None,
207+
experimental_features: None
208+
}
209+
}
210+
}
211+
212+
/// Returns true if any of the flags given are incompatible with the cmd
213+
pub fn flags_ok_for_cmd(flags: &RustcFlags,
214+
cfgs: &[~str],
215+
cmd: &str, user_supplied_opt_level: bool) -> bool {
216+
let complain = |s| {
217+
io::println(fmt!("The %s option can only be used with the build command:
218+
rustpkg [options..] build %s [package-ID]", s, s));
219+
};
220+
221+
if flags.linker.is_some() && cmd != "build" && cmd != "install" {
222+
io::println("The --linker option can only be used with the build or install commands.");
223+
return true;
224+
}
225+
if flags.link_args.is_some() && cmd != "build" && cmd != "install" {
226+
io::println("The --link-args option can only be used with the build or install commands.");
227+
return true;
228+
}
229+
230+
if !cfgs.is_empty() && cmd != "build" && cmd != "install" {
231+
io::println("The --cfg option can only be used with the build or install commands.");
232+
return true;
233+
}
234+
235+
if user_supplied_opt_level && cmd != "build" && cmd != "install" {
236+
io::println("The -O and --opt-level options can only be used with the build \
237+
or install commands.");
238+
return true;
239+
}
240+
241+
if flags.save_temps && cmd != "build" && cmd != "install" {
242+
io::println("The --save-temps option can only be used with the build \
243+
or install commands.");
244+
return true;
245+
}
246+
247+
if flags.target.is_some() && cmd != "build" && cmd != "install" {
248+
io::println("The --target option can only be used with the build \
249+
or install commands.");
250+
return true;
251+
}
252+
if flags.target_cpu.is_some() && cmd != "build" && cmd != "install" {
253+
io::println("The --target-cpu option can only be used with the build \
254+
or install commands.");
255+
return true;
256+
}
257+
if flags.experimental_features.is_some() && cmd != "build" && cmd != "install" {
258+
io::println("The -Z option can only be used with the build or install commands.");
259+
return true;
260+
}
261+
262+
match flags.compile_upto {
263+
Link if cmd != "build" => {
264+
complain("--no-link");
265+
true
266+
}
267+
Trans if cmd != "build" => {
268+
complain("--no-trans");
269+
true
270+
}
271+
Assemble if cmd != "build" => {
272+
complain("-S");
273+
true
274+
}
275+
Pretty if cmd != "build" => {
276+
complain("--pretty");
277+
true
278+
}
279+
Analysis if cmd != "build" => {
280+
complain("--parse-only");
281+
true
282+
}
283+
LLVMCompileBitcode if cmd != "build" => {
284+
complain("--emit-llvm");
285+
true
286+
}
287+
LLVMAssemble if cmd != "build" => {
288+
complain("--emit-llvm");
289+
true
290+
}
291+
_ => false
292+
}
293+
}

0 commit comments

Comments
 (0)