Skip to content

rustpkg: Pass command-line arguments to rustc #9107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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