Skip to content

Commit

Permalink
rustpkg: Pass command-line arguments to rustc
Browse files Browse the repository at this point in the history
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 rust-lang#8522
  • Loading branch information
catamorphism committed Sep 10, 2013
1 parent a9ac272 commit ad43613
Show file tree
Hide file tree
Showing 6 changed files with 704 additions and 65 deletions.
3 changes: 2 additions & 1 deletion src/librustpkg/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub fn default_context(p: Path) -> BuildContext {
pub fn new_default_context(c: workcache::Context, p: Path) -> BuildContext {
BuildContext {
context: Context {
cfgs: ~[],
rustc_flags: RustcFlags::default(),
use_rust_path_hack: false,
sysroot: p
},
Expand All @@ -44,7 +46,6 @@ fn binary_is_fresh(path: &str, in_hash: &str) -> bool {
in_hash == digest_only_date(&Path(path))
}


pub fn new_workcache_context(p: &Path) -> workcache::Context {
let db_file = p.push("rustpkg_db.json"); // ??? probably wrong
debug!("Workcache database file: %s", db_file.to_str());
Expand Down
225 changes: 222 additions & 3 deletions src/librustpkg/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@

// Context data structure used by rustpkg

use std::os;
use std::{io, os};
use extra::workcache;
use rustc::driver::session::{OptLevel, No};

#[deriving(Clone)]
pub struct Context {
// Config strings that the user passed in with --cfg
cfgs: ~[~str],
// Flags to pass to rustc
rustc_flags: RustcFlags,
// If use_rust_path_hack is true, rustpkg searches for sources
// in *package* directories that are in the RUST_PATH (for example,
// FOO/src/bar-0.1 instead of FOO). The flag doesn't affect where
Expand All @@ -40,15 +45,82 @@ impl BuildContext {
pub fn sysroot_to_use(&self) -> Path {
self.context.sysroot_to_use()
}

/// Returns the flags to pass to rustc, as a vector of strings
pub fn flag_strs(&self) -> ~[~str] {
self.context.flag_strs()
}

pub fn compile_upto(&self) -> StopBefore {
self.context.compile_upto()
}
}

/*
Deliberately unsupported rustc flags:
--bin, --lib inferred from crate file names
-L inferred from extern mods
--out-dir inferred from RUST_PATH
--test use `rustpkg test`
-v -h --ls don't make sense with rustpkg
-W -A -D -F - use pragmas instead
rustc flags that aren't implemented yet:
--passes
--llvm-arg
--target-feature
--android-cross-path
*/
pub struct RustcFlags {
compile_upto: StopBefore,
// Linker to use with the --linker flag
linker: Option<~str>,
// Extra arguments to pass to rustc with the --link-args flag
link_args: Option<~str>,
// Optimization level. 0 = default. -O = 2.
optimization_level: OptLevel,
// True if the user passed in --save-temps
save_temps: bool,
// Target (defaults to rustc's default target)
target: Option<~str>,
// Target CPU (defaults to rustc's default target CPU)
target_cpu: Option<~str>,
// Any -Z features
experimental_features: Option<~[~str]>
}

impl Clone for RustcFlags {
fn clone(&self) -> RustcFlags {
RustcFlags {
compile_upto: self.compile_upto,
linker: self.linker.clone(),
link_args: self.link_args.clone(),
optimization_level: self.optimization_level,
save_temps: self.save_temps,
target: self.target.clone(),
target_cpu: self.target_cpu.clone(),
experimental_features: self.experimental_features.clone()
}
}
}

#[deriving(Eq)]
pub enum StopBefore {
Nothing, // compile everything
Link, // --no-link
LLVMCompileBitcode, // --emit-llvm without -S
LLVMAssemble, // -S --emit-llvm
Assemble, // -S without --emit-llvm
Trans, // --no-trans
Pretty, // --pretty
Analysis, // --parse-only
}

impl Context {
pub fn sysroot(&self) -> Path {
self.sysroot.clone()
}
}

impl Context {
/// Debugging
pub fn sysroot_str(&self) -> ~str {
self.sysroot.to_str()
Expand All @@ -63,6 +135,15 @@ impl Context {
self.sysroot.pop().pop().pop()
}
}

/// Returns the flags to pass to rustc, as a vector of strings
pub fn flag_strs(&self) -> ~[~str] {
self.rustc_flags.flag_strs()
}

pub fn compile_upto(&self) -> StopBefore {
self.rustc_flags.compile_upto
}
}

/// We assume that if ../../rustc exists, then we're running
Expand All @@ -72,3 +153,141 @@ pub fn in_target(sysroot: &Path) -> bool {
debug!("Checking whether %s is in target", sysroot.to_str());
os::path_is_dir(&sysroot.pop().pop().push("rustc"))
}

impl RustcFlags {
fn flag_strs(&self) -> ~[~str] {
let linker_flag = match self.linker {
Some(ref l) => ~[~"--linker", l.clone()],
None => ~[]
};
let link_args_flag = match self.link_args {
Some(ref l) => ~[~"--link-args", l.clone()],
None => ~[]
};
let save_temps_flag = if self.save_temps { ~[~"--save-temps"] } else { ~[] };
let target_flag = match self.target {
Some(ref l) => ~[~"--target", l.clone()],
None => ~[]
};
let target_cpu_flag = match self.target_cpu {
Some(ref l) => ~[~"--target-cpu", l.clone()],
None => ~[]
};
let z_flags = match self.experimental_features {
Some(ref ls) => ls.flat_map(|s| ~[~"-Z", s.clone()]),
None => ~[]
};
linker_flag
+ link_args_flag
+ save_temps_flag
+ target_flag
+ target_cpu_flag
+ z_flags + (match self.compile_upto {
LLVMCompileBitcode => ~[~"--emit-llvm"],
LLVMAssemble => ~[~"--emit-llvm", ~"-S"],
Link => ~[~"-c"],
Trans => ~[~"--no-trans"],
Assemble => ~[~"-S"],
// n.b. Doesn't support all flavors of --pretty (yet)
Pretty => ~[~"--pretty"],
Analysis => ~[~"--parse-only"],
Nothing => ~[]
})
}

pub fn default() -> RustcFlags {
RustcFlags {
linker: None,
link_args: None,
compile_upto: Nothing,
optimization_level: No,
save_temps: false,
target: None,
target_cpu: None,
experimental_features: None
}
}
}

/// Returns true if any of the flags given are incompatible with the cmd
pub fn flags_ok_for_cmd(flags: &RustcFlags,
cfgs: &[~str],
cmd: &str, user_supplied_opt_level: bool) -> bool {
let complain = |s| {
io::println(fmt!("The %s option can only be used with the build command:
rustpkg [options..] build %s [package-ID]", s, s));
};

if flags.linker.is_some() && cmd != "build" && cmd != "install" {
io::println("The --linker option can only be used with the build or install commands.");
return true;
}
if flags.link_args.is_some() && cmd != "build" && cmd != "install" {
io::println("The --link-args option can only be used with the build or install commands.");
return true;
}

if !cfgs.is_empty() && cmd != "build" && cmd != "install" {
io::println("The --cfg option can only be used with the build or install commands.");
return true;
}

if user_supplied_opt_level && cmd != "build" && cmd != "install" {
io::println("The -O and --opt-level options can only be used with the build \
or install commands.");
return true;
}

if flags.save_temps && cmd != "build" && cmd != "install" {
io::println("The --save-temps option can only be used with the build \
or install commands.");
return true;
}

if flags.target.is_some() && cmd != "build" && cmd != "install" {
io::println("The --target option can only be used with the build \
or install commands.");
return true;
}
if flags.target_cpu.is_some() && cmd != "build" && cmd != "install" {
io::println("The --target-cpu option can only be used with the build \
or install commands.");
return true;
}
if flags.experimental_features.is_some() && cmd != "build" && cmd != "install" {
io::println("The -Z option can only be used with the build or install commands.");
return true;
}

match flags.compile_upto {
Link if cmd != "build" => {
complain("--no-link");
true
}
Trans if cmd != "build" => {
complain("--no-trans");
true
}
Assemble if cmd != "build" => {
complain("-S");
true
}
Pretty if cmd != "build" => {
complain("--pretty");
true
}
Analysis if cmd != "build" => {
complain("--parse-only");
true
}
LLVMCompileBitcode if cmd != "build" => {
complain("--emit-llvm");
true
}
LLVMAssemble if cmd != "build" => {
complain("--emit-llvm");
true
}
_ => false
}
}
Loading

0 comments on commit ad43613

Please sign in to comment.