diff options
| author | bors <bors@rust-lang.org> | 2013-04-12 12:57:58 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-04-12 12:57:58 -0700 |
| commit | 5bb2e8f62c5666f61db0b670f80f64ca673d22d6 (patch) | |
| tree | 79272465bc9cedcf90dd0ce396cd2f14e7b81ec7 /src | |
| parent | 2cb69748563f7b9ab94160943eea6ec787b27a4d (diff) | |
| parent | 74fee15bc1b6c3c558bab72a644b2600c91d0d2d (diff) | |
| download | rust-5bb2e8f62c5666f61db0b670f80f64ca673d22d6.tar.gz rust-5bb2e8f62c5666f61db0b670f80f64ca673d22d6.zip | |
auto merge of #5847 : catamorphism/rust/rustpkg, r=catamorphism
r? @graydon This is preliminary work on bringing rustpkg up to conformance with #5679 and related issues. This change makes rustpkg infer a package ID from its containing directory, instead of requiring name and vers attributes in the code. Many aspects of it are incomplete; I've only tested one package (see README.txt) and one command, "build". So far it only works for local packages. I also removed code for several of the package commands other than "build", replacing them with stubs that fail, since they used package IDs in ways that didn't jibe well with the new scheme. I will re-implement the commands one at a time.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustpkg/README.txt | 4 | ||||
| -rw-r--r-- | src/librustpkg/rustpkg.rc | 995 | ||||
| -rw-r--r-- | src/librustpkg/util.rs | 589 |
3 files changed, 636 insertions, 952 deletions
diff --git a/src/librustpkg/README.txt b/src/librustpkg/README.txt new file mode 100644 index 00000000000..eacf07e01ea --- /dev/null +++ b/src/librustpkg/README.txt @@ -0,0 +1,4 @@ +Right now (2013-04-11), only one package works, the branch of rust-sdl at: +https://github.com/catamorphism/rust-sdl/tree/new-rustpkg + +and only one command works, "build". diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index c0d77f60d69..83f5c78af43 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -27,42 +27,51 @@ extern mod rustc(vers = "0.7-pre"); extern mod syntax(vers = "0.7-pre"); use core::*; +pub use core::path::Path; use core::container::Map; use core::hashmap::HashMap; use core::io::WriterUtil; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; use std::net::url; -use std::{json, semver, getopts}; -use syntax::codemap::spanned; +use std::{getopts}; use syntax::{ast, diagnostic}; -use util::Package; +use util::{ExitCode, Pkg, PkgId}; mod usage; mod util; -struct PackageScript { - id: ~str, - name: ~str, - vers: semver::Version, - crates: ~[~str], - deps: ~[(~str, Option<~str>)], +/// A PkgScript represents user-supplied custom logic for +/// special build hooks. This only exists for packages with +/// an explicit package script. +struct PkgScript { + /// Uniquely identifies this package + id: PkgId, + // Used to have this field: deps: ~[(~str, Option<~str>)] + // but I think it shouldn't be stored here + /// The contents of the package script: either a file path, + /// or a string containing the text of the input input: driver::input, + /// The session to use *only* for compiling the custom + /// build script sess: session::Session, + /// The config for compiling the custom build script cfg: ast::crate_cfg, + /// The crate for the custom build script crate: @ast::crate, - custom: bool + /// Directory in which to store build output + build_dir: Path } -impl PackageScript { - fn parse(parent: &Path) -> Result<PackageScript, ~str> { - let script = parent.push(~"pkg.rs"); - - if !os::path_exists(&script) { - return result::Err(~"no pkg.rs file"); - } - +impl PkgScript { + /// Given the path name for a package script + /// and a package ID, parse the package script into + /// a PkgScript that we can then execute + fn parse(script: Path, id: PkgId) -> PkgScript { + // Get the executable name that was invoked let binary = os::args()[0]; + // Build the rustc session data structures to pass + // to the compiler let options = @session::options { binary: binary, crate_type: session::bin_crate, @@ -73,190 +82,121 @@ impl PackageScript { let cfg = driver::build_configuration(sess, binary, input); let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, None); - let mut id = None; - let mut vers = None; - let mut crates = ~[]; - let mut deps = ~[]; - - fn load_pkg_attr(mis: ~[@ast::meta_item]) -> (Option<~str>, - Option<~str>) { - let mut id = None; - let mut vers = None; - - for mis.each |a| { - match a.node { - ast::meta_name_value(v, spanned { - node: ast::lit_str(s), - span: _}) => { - match *v { - ~"id" => id = Some(*s), - ~"vers" => vers = Some(*s), - _ => () - } - } - _ => {} - } - } - - (id, vers) - } - - fn load_pkg_dep_attr(mis: ~[@ast::meta_item]) -> (Option<~str>, - Option<~str>) { - let mut url = None; - let mut target = None; - - for mis.each |a| { - match a.node { - ast::meta_name_value(v, spanned { - node: ast::lit_str(s), - span: _}) => { - match *v { - ~"url" => url = Some(*s), - ~"target" => target = Some(*s), - _ => () - } - } - _ => {} - } - } - - (url, target) - } - - fn load_pkg_crate_attr(mis: ~[@ast::meta_item]) -> Option<~str> { - let mut file = None; - - for mis.each |a| { - match a.node { - ast::meta_name_value(v, spanned { - node: ast::lit_str(s), - span: _}) => { - match *v { - ~"file" => file = Some(*s), - _ => () - } - } - _ => {} - } - } - - file - } - - for crate.node.attrs.each |a| { - match a.node.value.node { - ast::meta_list(v, mis) => { - match *v { - ~"pkg" => { - let (i, v) = load_pkg_attr(mis); - - id = i; - vers = v; - } - ~"pkg_dep" => { - let (u, t) = load_pkg_dep_attr(mis); - - if u.is_none() { - fail!(~"pkg_dep attr without a url value"); - } - - deps.push((u.get(), t)); - } - ~"pkg_crate" => { - let f = load_pkg_crate_attr(mis); - - if f.is_none() { - fail!(~"pkg_file attr without a file value"); - } - - crates.push(f.get()); - } - _ => {} - } - } - _ => {} - } - } - - let mut custom = false; - - // If we hit a function, we assume they want to use - // the build API. - for crate.node.module.items.each |i| { - match i.node { - ast::item_fn(*) => { - custom = true; - - break; - } - _ => {} - } - } - - if id.is_none() || vers.is_none() { - return result::Err(~"pkg attr without (id, vers) values"); - } + let work_dir = dest_dir(id); - let id = id.get(); - let name = match util::parse_name(id) { - result::Ok(name) => name, - result::Err(err) => return result::Err(err) - }; - let vers = match util::parse_vers(vers.get()) { - result::Ok(vers) => vers, - result::Err(err) => return result::Err(err) - }; + debug!("Returning package script with id %?", id); - result::Ok(PackageScript { + PkgScript { id: id, - name: name, - vers: vers, - crates: crates, - deps: deps, input: input, sess: sess, cfg: cfg, crate: crate, - custom: custom - }) + build_dir: work_dir + } } - // Build the bootstrap and run a command + /// Run the contents of this package script, where <what> + /// is the command to pass to it (e.g., "build", "clean", "install") + /// Returns a pair of an exit code and list of configs (obtained by + /// calling the package script's configs() function if it exists // FIXME (#4432): Use workcache to only compile the script when changed - fn run(&self, cmd: ~str, test: bool) -> int { - let work_dir = self.work_dir(); - let input = self.input; + fn run_custom(&self, what: ~str) -> (~[~str], ExitCode) { + debug!("run_custom: %s", what); let sess = self.sess; - let cfg = self.cfg; + + debug!("Working directory = %s", self.build_dir.to_str()); + // Collect together any user-defined commands in the package script let crate = util::ready_crate(sess, self.crate); - let outputs = driver::build_output_filenames(input, &Some(work_dir), - &None, sess); - let exe = work_dir.push(~"pkg" + util::exe_suffix()); - let root = filesearch::get_rustpkg_sysroot().get().pop().pop(); - - driver::compile_rest(sess, cfg, driver::cu_parse, - Some(outputs), Some(crate)); - run::run_program(exe.to_str(), ~[root.to_str(), cmd, test.to_str()]) + debug!("Building output filenames with script name %s", + driver::source_name(self.input)); + match filesearch::get_rustpkg_sysroot() { + Ok(r) => { + let root = r.pop().pop().pop().pop(); // :-\ + debug!("Root is %s, calling compile_rest", root.to_str()); + util::compile_crate_from_input(self.input, Some(self.build_dir), + sess, Some(crate), os::args()[0]); + let exe = self.build_dir.push(~"pkg" + util::exe_suffix()); + debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what); + let status = run::run_program(exe.to_str(), ~[root.to_str(), what]); + if status != 0 { + return (~[], status); + } + else { + debug!("Running program (configs): %s %s %s", + exe.to_str(), root.to_str(), ~"configs"); + let output = run::program_output(exe.to_str(), ~[root.to_str(), ~"configs"]); + // Run the configs() function to get the configs + let mut cfgs = ~[]; + for str::each_word(output.out) |w| { + cfgs.push(w.to_owned()); + } + (cfgs, output.status) + } + } + Err(e) => { + fail!(fmt!("Running package script, couldn't find rustpkg sysroot (%s)", + e)) + } + } } fn hash(&self) -> ~str { - fmt!("%s-%s-%s", self.name, util::hash(self.id + self.vers.to_str()), - self.vers.to_str()) + self.id.hash() } - fn work_dir(&self) -> Path { - util::root().push(~"work").push(self.hash()) - } } struct Ctx { - cfgs: ~[~str], + // I'm not sure what this is for json: bool, - dep_cache: @mut HashMap<~str, bool> + // Cache of hashes of things already installed + // though I'm not sure why the value is a bool + dep_cache: @mut HashMap<~str, bool>, +} + + +/// Returns the output directory to use. +/// Right now is always the default, should +/// support changing it. +fn dest_dir(pkgid: PkgId) -> Path { + default_dest_dir(&pkgid.path).expect( + ~"couldn't make default dir?!") +} + +/// Returns the default output directory for compilation. +/// Creates that directory if it doesn't exist. +fn default_dest_dir(pkg_dir: &Path) -> Option<Path> { + use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; + + // For now: assumes that pkg_dir exists and is relative + // to the CWD. Change this later when we do path searching. + let rslt = pkg_dir.push("build"); + let is_dir = os::path_is_dir(&rslt); + if os::path_exists(&rslt) { + if is_dir { + Some(rslt) + } + else { + util::error(fmt!("%s is not a directory", rslt.to_str())); + None + } + } + else { + // Create it + if os::make_dir(&rslt, (S_IRUSR | S_IWUSR | S_IXUSR) as i32) { + Some(rslt) + } + else { + util::error(fmt!("Could not create directory %s", + rslt.to_str())); + None // ??? should probably use conditions + } + } } impl Ctx { + fn run(&self, cmd: ~str, args: ~[~str]) { let root = util::root(); @@ -281,17 +221,64 @@ impl Ctx { match cmd { ~"build" => { - self.build(&os::getcwd(), true, false, false); + if args.len() < 1 { + return usage::build(); + } + // The package id is presumed to be the first command-line + // argument + let pkgid = PkgId::new(args[0]); + // Should allow the build directory to be configured. + // Right now it's always the "build" subdirectory in + // the package directory + let dst_dir = dest_dir(pkgid); + debug!("Destination dir = %s", dst_dir.to_str()); + // Right now, we assume the pkgid path is a valid dir + // relative to the CWD. In the future, we should search + // paths + let cwd = os::getcwd().normalize(); + debug!("Current working directory = %?", cwd); + + // Find crates inside the workspace + let mut src = PkgSrc::new(&cwd, &dst_dir, &pkgid); + debug!("Package src = %?", src); + src.find_crates(); + + // Is there custom build logic? If so, use it + let pkg_src_dir = cwd.push_rel(&pkgid.path); + debug!("Package source directory = %s", pkg_src_dir.to_str()); + let cfgs = match src.package_script_option(&pkg_src_dir) { + Some(package_script_path) => { + let pscript = PkgScript::parse(package_script_path, + pkgid); + // Limited right now -- we're only running the post_build + // hook and probably fail otherwise + // also post_build should be called pre_build + let (cfgs, hook_result) = pscript.run_custom(~"post_build"); + debug!("Command return code = %?", hook_result); + if hook_result != 0 { + fail!(fmt!("Error running custom build command")) + } + // otherwise, the package script succeeded + cfgs + } + None => { + debug!("No package script, continuing"); + ~[] + } + }; + src.build(&dst_dir, cfgs); } ~"clean" => { self.clean(); } ~"do" => { - if args.len() < 1 { + if args.len() < 2 { return usage::do_cmd(); } - self.do_cmd(args[0]); + if !self.do_cmd(args[0], args[1]) { + fail!(~"a command failed!"); + } } ~"info" => { self.info(); @@ -336,7 +323,7 @@ impl Ctx { } } - fn do_cmd(&self, cmd: ~str) -> bool { + fn do_cmd(&self, cmd: ~str, pkgname: ~str) -> bool { match cmd { ~"build" | ~"test" => { util::error(~"that command cannot be manually called"); @@ -347,230 +334,85 @@ impl Ctx { } let cwd = &os::getcwd(); - let script = match PackageScript::parse(cwd) { - result::Ok(script) => script, - result::Err(err) => { - util::error(err); - - return false; - } - }; - let status = script.run(cmd, false); - - if status == 42 { - util::error(~"no fns are listening for that cmd"); - - return false; - } - - status == 0 - } - - fn build(&self, dir: &Path, verbose: bool, opt: bool, - test: bool) -> Option<PackageScript> { - let cwd = &os::getcwd(); - let script = match PackageScript::parse(dir) { - result::Ok(script) => script, - result::Err(err) => { - util::error(err); - - return None; - } - }; - let work_dir = script.work_dir(); - let mut success = true; - - util::need_dir(&work_dir); - - if script.deps.len() >= 1 { - util::note(~"installing dependencies"); - - for script.deps.each |&dep| { - let (url, target) = dep; - - success = self.install(Some(url), target, true); - - if !success { break; } - } - - - if !success { - util::error( - fmt!("building %s v%s failed: a dep wasn't installed", - script.name, script.vers.to_str())); - - return None; + let pkgid = PkgId::new(pkgname); + // Always use the "build" subdirectory of the package dir, + // but we should allow this to be configured + let dst_dir = dest_dir(pkgid); + + let mut src = PkgSrc::new(cwd, &dst_dir, &pkgid); + match src.package_script_option(cwd) { + Some(script_path) => { + let script = PkgScript::parse(script_path, pkgid); + let (_, status) = script.run_custom(cmd); // Ignore cfgs? + if status == 42 { // ??? + util::error(~"no fns are listening for that cmd"); + return false; + } + status == 0 } - - util::note(~"installed dependencies"); - } - - // Build imperative crates - os::change_dir(dir); - - if script.custom { - let status = script.run(~"build", test); - - if status != 0 && status != 42 { - util::error( - fmt!("building %s v%s failed: custom logic failed (%d)", - script.name, script.vers.to_str(), status)); - - return None; + None => { + util::error(fmt!("invoked `do`, but there is no package script in %s", + cwd.to_str())); + false } } + } - os::change_dir(cwd); - - for script.crates.each |&crate| { - let crate = &dir.push_rel(&Path(crate)).normalize(); - - util::note(fmt!("compiling %s", crate.to_str())); - - success = self.compile(crate, &work_dir, ~[], - ~[], opt, test); - - if !success { break; } - } - - if !success { - util::error( - fmt!("building %s v%s failed: a crate failed to compile", - script.name, script.vers.to_str())); - - return None; - } - - if verbose { - util::note(fmt!("built %s v%s", script.name, - script.vers.to_str())); - } - - Some(script) + fn build(&self, _dir: &Path, _verbose: bool, _opt: bool, + _test: bool) -> Option<PkgScript> { + // either not needed anymore, + // or needed only when we don't have a package script. Not sure which one. + fail!(); } - fn compile(&self, crate: &Path, dir: &Path, flags: ~[~str], - cfgs: ~[~str], opt: bool, test: bool) -> bool { - util::compile_crate(None, crate, dir, flags, cfgs, opt, test) + fn compile(&self, _crate: &Path, _dir: &Path, _flags: ~[~str], + _cfgs: ~[~str], _opt: bool, _test: bool) -> bool { + // What's the difference between build and compile? + fail!(~"compile not yet implemented"); } fn clean(&self) -> bool { - let script = match PackageScript::parse(&os::getcwd()) { - result::Ok(script) => script, - result::Err(err) => { - util::error(err); - - return false; - } - }; - let dir = script.work_dir(); - - util::note(fmt!("cleaning %s v%s (%s)", script.name, - script.vers.to_str(), script.id)); - - if os::path_exists(&dir) { - util::remove_dir_r(&dir); - util::note(fmt!("removed %s", dir.to_str())); - } - - util::note(fmt!("cleaned %s v%s", script.name, - script.vers.to_str())); - - true + // stub + fail!(); } fn info(&self) { - if self.json { - match PackageScript::parse(&os::getcwd()) { - result::Ok(script) => { - let mut map = ~HashMap::new(); - - map.insert(~"id", json::String(script.id)); - map.insert(~"name", json::String(script.name)); - map.insert(~"vers", json::String(script.vers.to_str())); - map.insert(~"deps", json::List(do script.deps.map |&dep| { - let (url, target) = dep; - let mut inner = ~HashMap::new(); - - inner.insert(~"url", json::String(url)); - - if !target.is_none() { - inner.insert(~"target", - json::String(target.get())); - } - - json::Object(inner) - })); - - io::println(json::to_pretty_str(&json::Object(map))); - } - result::Err(_) => io::println(~"{}") - } - } else { - let script = match PackageScript::parse(&os::getcwd()) { - result::Ok(script) => script, - result::Err(err) => { - util::error(err); - - return; - } - }; - - util::note(fmt!("id: %s", script.id)); - util::note(fmt!("name: %s", script.name)); - util::note(fmt!("vers: %s", script.vers.to_str())); - util::note(fmt!("deps: %s", - if script.deps.len() > 0 { - ~"" - } else { - ~"none" - })); - - for script.deps.each |&dep| { - let (url, target) = dep; - - util::note(fmt!(" <%s> (%s)", url, match target { - Some(target) => target, - None => ~"" - })); - } - } + // stub + fail!(); } fn install(&self, url: Option<~str>, target: Option<~str>, cache: bool) -> bool { - let mut success; - let mut dir; - - if url.is_none() { - util::note(~"installing from the cwd"); - - dir = os::getcwd(); - } else { - let url = url.get(); - let hash = util::hash(if !target.is_none() { url + target.get() } - else { url }); - - if self.dep_cache.contains_key(&hash) { - util::warn(~"already installed dep this run"); - - return true; + let dir = match url { + None => { + util::note(~"installing from the cwd"); + os::getcwd() } + Some(url) => { + let hash = util::hash(if !target.is_none() { + url + target.get() + } + else { url }); - self.dep_cache.insert(hash, true); + if self.dep_cache.contains_key(&hash) { + util::warn(~"already installed dep this run"); + return true; + } - dir = util::root().push(~"tmp").push(hash); + self.dep_cache.insert(hash, true); - if cache && os::path_exists(&dir) { - return true; - } + let dir = util::root().push(~"tmp").push(hash); - success = self.fetch(&dir, url, target); + if cache && os::path_exists(&dir) { + return true; + } - if !success { - return false; + if !self.fetch(&dir, url, target) { + return false; + } + dir } - } + }; let script = match self.build(&dir, false, true, false) { Some(script) => script, @@ -578,7 +420,7 @@ impl Ctx { return false; } }; - let work_dir = script.work_dir(); + let work_dir = script.build_dir; let from_bin_dir = work_dir.push(~"bin"); let from_lib_dir = work_dir.push(~"lib"); let to_bin_dir = util::root().push(~"bin"); @@ -600,15 +442,13 @@ impl Ctx { libs.push(to.to_str()); } - let package = Package { + let package = Pkg { id: script.id, - vers: script.vers, bins: bins, libs: libs }; - util::note(fmt!("installed %s v%s", script.name, - script.vers.to_str())); + util::note(fmt!("installed %s", script.id.to_str())); util::add_pkg(&package); true @@ -713,17 +553,9 @@ impl Ctx { return false; } }; - let name = match util::parse_name(package.id) { - result::Ok(name) => name, - result::Err(err) => { - util::error(err); - - return false; - } - }; + let name = package.id.path.to_str(); // ??? - util::note(fmt!("preferring %s v%s (%s)", name, package.vers.to_str(), - package.id)); + util::note(fmt!("preferring %s v%s", name, package.id.version.to_str())); let bin_dir = util::root().push(~"bin"); @@ -740,7 +572,7 @@ impl Ctx { util::note(fmt!("linked %s", out.to_str())); } - util::note(fmt!("preferred %s v%s", name, package.vers.to_str())); + util::note(fmt!("preferred %s v%s", name, package.id.version.to_str())); true } @@ -752,126 +584,24 @@ impl Ctx { return false; } }; - let work_dir = script.work_dir(); - let test_dir = work_dir.push(~"test"); - - for os::walk_dir(&test_dir) |test| { - util::note(fmt!("running %s", test.to_str())); - - let status = run::run_program(test.to_str(), ~[]); - - if status != 0 { - os::set_exit_status(status); - } - } - - // Run custom test listener - if script.custom { - let status = script.run(~"test", false); - - if status != 0 && status != 42 { - util::error( - fmt!("testing %s v%s failed: custom logic failed (%d)", - script.name, script.vers.to_str(), status)); - os::set_exit_status(status); - } - } - - util::note(fmt!("tested %s v%s", script.name, script.vers.to_str())); - - true + // To do + util::note(fmt!("Would test %s, but this is a dry run", + script.id.to_str())); + false } - fn uninstall(&self, id: ~str, vers: Option<~str>) -> bool { - let package = match util::get_pkg(id, vers) { - result::Ok(package) => package, - result::Err(err) => { - util::error(err); - - return false; - } - }; - let name = match util::parse_name(package.id) { - result::Ok(name) => name, - result::Err(err) => { - util::error(err); - - return false; - } - }; - - util::note(fmt!("uninstalling %s v%s (%s)", name, - package.vers.to_str(), package.id)); - - for vec::append(package.bins, package.libs).each |&file| { - let path = Path(file); - - if os::path_exists(&path) { - if os::remove_file(&path) { - util::note(fmt!("removed %s", path.to_str())); - } else { - util::error(fmt!("could not remove %s", path.to_str())); - } - } - } - - util::note(fmt!("uninstalled %s v%s", name, package.vers.to_str())); - util::remove_pkg(&package); - - true + fn uninstall(&self, _id: ~str, _vers: Option<~str>) -> bool { + fail!(~"uninstall not yet implemented"); } - fn unprefer(&self, id: ~str, vers: Option<~str>) -> bool { - let package = match util::get_pkg(id, vers) { - result::Ok(package) => package, - result::Err(err) => { - util::error(err); - - return false; - } - }; - let name = match util::parse_name(package.id) { - result::Ok(name) => name, - result::Err(err) => { - util::error(err); - - return false; - } - }; - - util::note(fmt!("unpreferring %s v%s (%s)", name, - package.vers.to_str(), package.id)); - - let bin_dir = util::root().push(~"bin"); - - for package.bins.each |&bin| { - let path = Path(bin); - let mut name = None; - for str::each_split_char(path.file_path().to_str(), '-') |s| { - name = Some(s.to_owned()); - break; - } - let out = bin_dir.push(name.unwrap()); - - if os::path_exists(&out) { - if os::remove_file(&out) { - util::note(fmt!("unlinked %s", out.to_str())); - } else { - util::error(fmt!("could not unlink %s", out.to_str())); - } - } - } - - util::note(fmt!("unpreferred %s v%s", name, package.vers.to_str())); - - true + fn unprefer(&self, _id: ~str, _vers: Option<~str>) -> bool { + fail!(~"unprefer not yet implemented"); } } pub fn main() { - io::println("WARNING: The Rust package manager is experimental and may"); - io::println("be unstable."); + io::println("WARNING: The Rust package manager is experimental and may be unstable"); let args = os::args(); let opts = ~[getopts::optflag(~"h"), getopts::optflag(~"help"), @@ -889,8 +619,6 @@ pub fn main() { getopts::opt_present(matches, ~"help"); let json = getopts::opt_present(matches, ~"j") || getopts::opt_present(matches, ~"json"); - let cfgs = vec::append(getopts::opt_strs(matches, ~"cfg"), - getopts::opt_strs(matches, ~"c")); let mut args = copy matches.free; args.shift(); @@ -919,7 +647,6 @@ pub fn main() { } Ctx { - cfgs: cfgs, json: json, dep_cache: @mut HashMap::new() }.run(cmd, args); @@ -927,7 +654,7 @@ pub fn main() { /// A crate is a unit of Rust code to be compiled into a binary or library pub struct Crate { - file: ~str, + file: Path, flags: ~[~str], cfgs: ~[~str] } @@ -959,28 +686,37 @@ pub fn run(listeners: ~[Listener]) { } pub impl Crate { - pub fn flag(&self, flag: ~str) -> Crate { + + fn new(p: &Path) -> Crate { + Crate { + file: copy *p, + flags: ~[], + cfgs: ~[] + } + } + + fn flag(&self, flag: ~str) -> Crate { Crate { flags: vec::append(copy self.flags, ~[flag]), .. copy *self } } - pub fn flags(&self, flags: ~[~str]) -> Crate { + fn flags(&self, flags: ~[~str]) -> Crate { Crate { flags: vec::append(copy self.flags, flags), .. copy *self } } - pub fn cfg(&self, cfg: ~str) -> Crate { + fn cfg(&self, cfg: ~str) -> Crate { Crate { cfgs: vec::append(copy self.cfgs, ~[cfg]), .. copy *self } } - pub fn cfgs(&self, cfgs: ~[~str]) -> Crate { + fn cfgs(&self, cfgs: ~[~str]) -> Crate { Crate { cfgs: vec::append(copy self.cfgs, cfgs), .. copy *self @@ -988,15 +724,6 @@ pub impl Crate { } } -/// Create a crate target from a source file -pub fn Crate(file: ~str) -> Crate { - Crate { - file: file, - flags: ~[], - cfgs: ~[] - } -} - /** * Get the working directory of the package script. * Assumes that the package script has been compiled @@ -1016,30 +743,208 @@ pub fn src_dir() -> Path { os::getcwd() } -/// Build a set of crates, should be called once -pub fn build(crates: ~[Crate]) -> bool { - let args = os::args(); - let dir = src_dir(); - let work_dir = work_dir(); - let mut success = true; - let sysroot = Path(args[1]); - let test = args[3] == ~"true"; +condition! { + bad_pkg_id: (super::Path, ~str) -> ::util::PkgId; +} - for crates.each |&crate| { - let path = &dir.push_rel(&Path(crate.file)).normalize(); +// An enumeration of the unpacked source of a package workspace. +// This contains a list of files found in the source workspace. +pub struct PkgSrc { + root: Path, // root of where the package source code lives + dst_dir: Path, // directory where we will put the compiled output + id: PkgId, + libs: ~[Crate], + mains: ~[Crate], + tests: ~[Crate], + benchs: ~[Crate], +} - util::note(fmt!("compiling %s", path.to_str())); +condition! { + bad_path: (super::Path, ~str) -> super::Path; +} - success = util::compile_crate(Some(sysroot), path, &work_dir, - crate.flags, crate.cfgs, - false, test); +condition! { + build_err: (~str) -> (); +} - if !success { break; } +impl PkgSrc { + + + fn new(src_dir: &Path, dst_dir: &Path, + id: &PkgId) -> PkgSrc { + PkgSrc { + root: copy *src_dir, + dst_dir: copy *dst_dir, + id: copy *id, + libs: ~[], + mains: ~[], + tests: ~[], + benchs: ~[] + } } - if !success { - os::set_exit_status(101); + + fn check_dir(&self) -> Path { + use bad_path::cond; + + debug!("Pushing onto root: %s | %s", self.id.path.to_str(), + self.root.to_str()); + + let dir = self.root.push_rel(&self.id.path).normalize(); + + debug!("Checking dir: %s", dir.to_str()); + + if !os::path_exists(&dir) { + return cond.raise((dir, ~"missing package dir")); + } + + if !os::path_is_dir(&dir) { + return cond.raise((dir, ~"supplied path for package dir is a \ + non-directory")); + } + + dir + } + + + fn has_pkg_file(&self) -> bool { + let dir = self.check_dir(); + dir.push("pkg.rs").exists() } - success + // If a file named "pkg.rs" in the current directory exists, + // return the path for it. Otherwise, None + fn package_script_option(&self, cwd: &Path) -> Option<Path> { + let maybe_path = cwd.push("pkg.rs"); + if os::path_exists(&maybe_path) { + Some(maybe_path) + } + else { + None + } + } + + /// True if the given path's stem is self's pkg ID's stem + /// or if the pkg ID's stem is <rust-foo> and the given path's + /// stem is foo + fn stem_matches(&self, p: &Path) -> bool { + let self_id = self.id.path.filestem(); + if self_id == p.filestem() { + return true; + } + else { + for self_id.each |pth| { + if pth.starts_with("rust-") + && match p.filestem() { + Some(s) => str::eq_slice(s, pth.slice(5, pth.len())), + None => false + } { return true; } + } + } + false + } + + fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) { + assert!(p.components.len() > prefix); + let mut sub = Path(""); + for vec::slice(p.components, prefix, + p.components.len()).each |c| { + sub = sub.push(*c); + } + debug!("found crate %s", sub.to_str()); + cs.push(Crate::new(&sub)); + } + + fn find_crates(&mut self) { + use PkgSrc::push_crate; + + let dir = self.check_dir(); + let prefix = dir.components.len(); + // This is ugly, but can go away once we get rid + // of .rc files + let mut saw_rs = false; + let mut saw_rc = false; + debug!("Matching against %?", + self.id.path.filestem()); + for os::walk_dir(&dir) |pth| { + match pth.filename() { + Some(~"lib.rs") => push_crate(&mut self.libs, + prefix, pth), + Some(~"main.rs") => push_crate(&mut self.mains, + prefix, pth), + Some(~"test.rs") => push_crate(&mut self.tests, + prefix, pth), + Some(~"bench.rs") => push_crate(&mut self.benchs, + prefix, pth), + _ => { + // If the file stem is the same as the + // package ID, with an .rs or .rc extension, + // consider it to be a crate + let ext = pth.filetype(); + let matches = |p: &Path| { + self.stem_matches(p) && (ext == Some(~".rc") + || ext == Some(~".rs")) + }; + debug!("Checking %? which %s and ext = %? %? %?", pth.filestem(), + if matches(pth) { "matches" } else { "does not match" }, + ext, saw_rs, saw_rc); + if matches(pth) && + // Avoid pushing foo.rc *and* foo.rs + !((ext == Some(~".rc") && saw_rs) || + (ext == Some(~".rs") && saw_rc)) { + push_crate(&mut self.libs, // ???? + prefix, pth); + if ext == Some(~".rc") { + saw_rc = true; + } + else if ext == Some(~".rs") { + saw_rs = true; + } + } + } + } + } + debug!("found %u libs, %u mains, %u tests, %u benchs", + self.libs.len(), + self.mains.len(), + self.tests.len(), + self.benchs.len()) + } + + fn build_crates(dst_dir: &Path, + src_dir: &Path, + crates: &[Crate], + cfgs: ~[~str], + test: bool) { + + for crates.each |&crate| { + let path = &src_dir.push_rel(&crate.file).normalize(); + util::note(fmt!("build_crates: compiling %s", path.to_str())); + util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str())); + + let result = util::compile_crate(None, path, + dst_dir, + crate.flags, + crate.cfgs + cfgs, + false, test); + if !result { + build_err::cond.raise(fmt!("build failure on %s", + path.to_str())); + } + debug!("Result of compiling %s was %?", + path.to_str(), result); + } + } + + fn build(&self, dst_dir: &Path, cfgs: ~[~str]) { + let dir = self.check_dir(); + debug!("Building libs"); + PkgSrc::build_crates(dst_dir, &dir, self.libs, cfgs, false); + debug!("Building mains"); + PkgSrc::build_crates(dst_dir, &dir, self.mains, cfgs, false); + debug!("Building tests"); + PkgSrc::build_crates(dst_dir, &dir, self.tests, cfgs, true); + debug!("Building benches"); + PkgSrc::build_crates(dst_dir, &dir, self.benchs, cfgs, true); + } } diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 0d858afbb84..f7916329e48 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -9,26 +9,125 @@ // except according to those terms. use core::*; +use core::cmp::Ord; use core::hash::Streaming; -use core::hashmap::HashMap; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; use std::getopts::groups::getopts; use std::semver; -use std::{json, term, sort, getopts}; +use std::{json, term, getopts}; use syntax::ast_util::*; -use syntax::codemap::{dummy_sp, spanned}; +use syntax::codemap::{dummy_sp}; use syntax::ext::base::{mk_ctxt, ext_ctxt}; use syntax::ext::build; use syntax::{ast, attr, codemap, diagnostic, fold}; +use rustc::back::link::output_type_exe; -pub struct Package { - id: ~str, - vers: semver::Version, +pub type ExitCode = int; // For now + +/// A version is either an exact revision, +/// or a semantic version +pub enum Version { + ExactRevision(float), + SemVersion(semver::Version) +} + +impl Ord for Version { + fn lt(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 < f2, + (&SemVersion(v1), &SemVersion(v2)) => v1 < v2, + _ => false // incomparable, really + } + } + fn le(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 <= f2, + (&SemVersion(v1), &SemVersion(v2)) => v1 <= v2, + _ => false // incomparable, really + } + } + fn ge(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 > f2, + (&SemVersion(v1), &SemVersion(v2)) => v1 > v2, + _ => false // incomparable, really + } + } + fn gt(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 >= f2, + (&SemVersion(v1), &SemVersion(v2)) => v1 >= v2, + _ => false // incomparable, really + } + } + +} + +impl ToStr for Version { + fn to_str(&self) -> ~str { + match *self { + ExactRevision(n) => n.to_str(), + SemVersion(v) => v.to_str() + } + } +} + +/// Placeholder +fn default_version() -> Version { ExactRevision(0.1) } + +// Path-fragment identifier of a package such as +// 'github.com/graydon/test'; path must be a relative +// path with >=1 component. +pub struct PkgId { + path: Path, + version: Version +} + +pub impl PkgId { + fn new(s: &str) -> PkgId { + use bad_pkg_id::cond; + + let p = Path(s); + if p.is_absolute { + return cond.raise((p, ~"absolute pkgid")); + } + if p.components.len() < 1 { + return cond.raise((p, ~"0-length pkgid")); + } + PkgId { + path: p, + version: default_version() + } + } + + fn hash(&self) -> ~str { + fmt!("%s-%s-%s", self.path.to_str(), + hash(self.path.to_str() + self.version.to_str()), + self.version.to_str()) + } + +} + +impl ToStr for PkgId { + fn to_str(&self) -> ~str { + // should probably use the filestem and not the whole path + fmt!("%s-v%s", self.path.to_str(), self.version.to_str()) + } +} + +pub struct Pkg { + id: PkgId, bins: ~[~str], libs: ~[~str], } +impl ToStr for Pkg { + fn to_str(&self) -> ~str { + self.id.to_str() + } +} + pub fn root() -> Path { match filesearch::get_rustpkg_root() { result::Ok(path) => path, @@ -309,306 +408,65 @@ pub fn wait_for_lock(path: &Path) { } } -fn _add_pkg(packages: ~[json::Json], pkg: &Package) -> ~[json::Json] { - for packages.each |&package| { - match &package { - &json::Object(ref map) => { - let mut has_id = false; - - match map.get(&~"id") { - &json::String(ref str) => { - if pkg.id == *str { - has_id = true; - } - } - _ => {} - } - - match map.get(&~"vers") { - &json::String(ref str) => { - if has_id && pkg.vers.to_str() == *str { - return copy packages; - } - } - _ => {} - } - } - _ => {} - } - } - - let mut map = ~HashMap::new(); - - map.insert(~"id", json::String(pkg.id)); - map.insert(~"vers", json::String(pkg.vers.to_str())); - map.insert(~"bins", json::List(do pkg.bins.map |&bin| { - json::String(bin) - })); - map.insert(~"libs", json::List(do pkg.libs.map |&lib| { - json::String(lib) - })); - - vec::append(packages, ~[json::Object(map)]) -} - -fn _rm_pkg(packages: ~[json::Json], pkg: &Package) -> ~[json::Json] { - do packages.filter_mapped |&package| { - match &package { - &json::Object(ref map) => { - let mut has_id = false; - - match map.get(&~"id") { - &json::String(str) => { - if pkg.id == str { - has_id = true; - } - } - _ => {} - } - - match map.get(&~"vers") { - &json::String(ref str) => { - if has_id && pkg.vers.to_str() == *str { - None - } else { - Some(copy package) - } - } - _ => { Some(copy package) } - } - } - _ => { Some(copy package) } - } - } -} - pub fn load_pkgs() -> result::Result<~[json::Json], ~str> { - let root = root(); - let db = root.push(~"db.json"); - let db_lock = root.push(~"db.json.lck"); - - wait_for_lock(&db_lock); - touch(&db_lock); - - let packages = if os::path_exists(&db) { - match io::read_whole_file_str(&db) { - result::Ok(str) => { - match json::from_str(str) { - result::Ok(json) => { - match json { - json::List(list) => list, - _ => { - os::remove_file(&db_lock); - - return result::Err( - ~"package db's json is not a list"); - } - } - } - result::Err(err) => { - os::remove_file(&db_lock); - - return result::Err( - fmt!("failed to parse package db: %s", - err.to_str())); - } - } - } - result::Err(err) => { - os::remove_file(&db_lock); - - return result::Err(fmt!("failed to read package db: %s", - err)); - } - } - } else { ~[] }; - - os::remove_file(&db_lock); - - result::Ok(packages) + fail!(~"load_pkg not implemented"); } -pub fn get_pkg(id: ~str, - vers: Option<~str>) -> result::Result<Package, ~str> { - let name = match parse_name(id) { - result::Ok(name) => name, - result::Err(err) => return result::Err(err) - }; - let packages = match load_pkgs() { - result::Ok(packages) => packages, - result::Err(err) => return result::Err(err) - }; - let mut sel = None; - let mut possibs = ~[]; - let mut err = None; - - for packages.each |&package| { - match package { - json::Object(map) => { - let pid = match map.get(&~"id") { - &json::String(str) => str, - _ => loop - }; - let pname = match parse_name(pid) { - result::Ok(pname) => pname, - result::Err(perr) => { - err = Some(perr); - - break; - } - }; - let pvers = match map.get(&~"vers") { - &json::String(str) => str, - _ => loop - }; - if pid == id || pname == name { - let bins = match map.get(&~"bins") { - &json::List(ref list) => { - do list.map |&bin| { - match bin { - json::String(str) => str, - _ => ~"" - } - } - } - _ => ~[] - }; - let libs = match map.get(&~"libs") { - &json::List(ref list) => { - do list.map |&lib| { - match lib { - json::String(str) => str, - _ => ~"" - } - } - } - _ => ~[] - }; - let package = Package { - id: pid, - vers: match parse_vers(pvers) { - result::Ok(vers) => vers, - result::Err(verr) => { - err = Some(verr); - - break; - } - }, - bins: bins, - libs: libs - }; - - if !vers.is_none() && vers.get() == pvers { - sel = Some(package); - } - else { - possibs.push(package); - } - } - } - _ => {} - } - } - - if !err.is_none() { - return result::Err(err.get()); - } - if !sel.is_none() { - return result::Ok(sel.get()); - } - if !vers.is_none() || possibs.len() < 1 { - return result::Err(~"package not found"); - } - - let possibs = sort::merge_sort(possibs, |v1, v2| { - v1.vers <= v2.vers - }); - - result::Ok(copy *possibs.last()) +pub fn get_pkg(_id: ~str, + _vers: Option<~str>) -> result::Result<Pkg, ~str> { + fail!(~"get_pkg not implemented"); } -pub fn add_pkg(pkg: &Package) -> bool { - let root = root(); - let db = root.push(~"db.json"); - let db_lock = root.push(~"db.json.lck"); - let packages = match load_pkgs() { - result::Ok(packages) => packages, - result::Err(err) => { - error(err); - - return false; - } - }; - - wait_for_lock(&db_lock); - touch(&db_lock); - os::remove_file(&db); - - match io::mk_file_writer(&db, ~[io::Create]) { - result::Ok(writer) => { - writer.write_line(json::to_pretty_str(&json::List( - _add_pkg(packages, pkg)))); - } - result::Err(err) => { - error(fmt!("failed to dump package db: %s", err)); - os::remove_file(&db_lock); - - return false; - } - } - - os::remove_file(&db_lock); - - true +pub fn add_pkg(pkg: &Pkg) -> bool { + note(fmt!("Would be adding package, but add_pkg is not yet implemented %s", + pkg.to_str())); + false } -pub fn remove_pkg(pkg: &Package) -> bool { - let root = root(); - let db = root.push(~"db.json"); - let db_lock = root.push(~"db.json.lck"); - let packages = match load_pkgs() { - result::Ok(packages) => packages, - result::Err(err) => { - error(err); - - return false; - } - }; - - wait_for_lock(&db_lock); - touch(&db_lock); - os::remove_file(&db); +// FIXME (#4432): Use workcache to only compile when needed +pub fn compile_input(sysroot: Option<Path>, + in_file: &Path, + out_dir: &Path, + flags: ~[~str], + cfgs: ~[~str], + opt: bool, + test: bool) -> bool { - match io::mk_file_writer(&db, ~[io::Create]) { - result::Ok(writer) => { - writer.write_line(json::to_pretty_str(&json::List( - _rm_pkg(packages, pkg)))); - } - result::Err(err) => { - error(fmt!("failed to dump package db: %s", err)); - os::remove_file(&db_lock); + assert!(in_file.components.len() > 1); + let input = driver::file_input(copy *in_file); + debug!("compile_input: %s", in_file.to_str()); + // tjc: by default, use the package ID name as the link name + // not sure if we should support anything else + let short_name = in_file.filestem().expect("Can't compile a directory!"); + debug!("short_name = %s", short_name.to_str()); - return false; - } - } - - os::remove_file(&db_lock); +// Right now we're always assuming that we're building a library. +// What we should do is parse the crate and infer whether it's a library +// from the absence or presence of a main fn + let out_file = out_dir.push(os::dll_filename(short_name)); + let building_library = true; - true -} + debug!("compiling %s into %s", + in_file.to_str(), + out_file.to_str()); -pub fn compile_input(sysroot: Option<Path>, input: driver::input, dir: &Path, - flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool { - let lib_dir = dir.push(~"lib"); - let bin_dir = dir.push(~"bin"); - let test_dir = dir.push(~"test"); let binary = os::args()[0]; - let matches = getopts(flags, driver::optgroups()).get(); + + debug!("flags: %s", str::connect(flags, ~" ")); + debug!("cfgs: %s", str::connect(cfgs, ~" ")); +// Again, we assume we're building a library + let matches = getopts(~[~"-Z", ~"time-passes"] + + if building_library { ~[~"--lib"] } else { ~[] } + + flags + + cfgs.flat_map(|&c| { ~[~"--cfg", c] }), + driver::optgroups()).get(); let options = @session::options { - crate_type: session::unknown_crate, + crate_type: if building_library { session::lib_crate } + else { session::bin_crate }, optimize: if opt { session::Aggressive } else { session::No }, test: test, maybe_sysroot: sysroot, + addl_lib_search_paths: ~[copy *out_dir], .. *driver::build_session_options(binary, &matches, diagnostic::emit) }; let mut crate_cfg = options.cfg; @@ -619,124 +477,42 @@ pub fn compile_input(sysroot: Option<Path>, input: driver::input, dir: &Path, let options = @session::options { cfg: vec::append(options.cfg, crate_cfg), + // output_type should be conditional + output_type: output_type_exe, // Use this to get a library? That's weird .. *options }; let sess = driver::build_session(options, diagnostic::emit); - let cfg = driver::build_configuration(sess, binary, input); - let mut outputs = driver::build_output_filenames(input, &None, &None, - sess); - let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, - Some(outputs)); - - let mut name = None; - let mut vers = None; - let mut uuid = None; - let mut crate_type = None; - - fn load_link_attr(mis: ~[@ast::meta_item]) -> (Option<~str>, - Option<~str>, - Option<~str>) { - let mut name = None; - let mut vers = None; - let mut uuid = None; - - for mis.each |a| { - match a.node { - ast::meta_name_value(v, spanned {node: ast::lit_str(s), - span: _}) => { - match *v { - ~"name" => name = Some(*s), - ~"vers" => vers = Some(*s), - ~"uuid" => uuid = Some(*s), - _ => { } - } - } - _ => {} - } - } - - (name, vers, uuid) - } - - for crate.node.attrs.each |a| { - match a.node.value.node { - ast::meta_name_value(v, spanned {node: ast::lit_str(s), - span: _}) => { - match *v { - ~"crate_type" => crate_type = Some(*s), - _ => {} - } - } - ast::meta_list(v, mis) => { - match *v { - ~"link" => { - let (n, v, u) = load_link_attr(mis); - - name = n; - vers = v; - uuid = u; - } - _ => {} - } - } - _ => {} - } - } - - if name.is_none() || vers.is_none() || uuid.is_none() { - error(~"link attr without (name, vers, uuid) values"); - - return false; - } - let name = name.get(); - let vers = vers.get(); - let uuid = uuid.get(); - - let is_bin = match crate_type { - Some(crate_type) => { - match crate_type { - ~"bin" => true, - ~"lib" => false, - _ => { - warn(~"unknown crate_type, falling back to lib"); + debug!("calling compile_crate_from_input, out_dir = %s, + building_library = %?", out_dir.to_str(), sess.building_library); + compile_crate_from_input(input, Some(*out_dir), sess, None, binary); + true +} - false - } - } +// Should use workcache to avoid recompiling when not necessary +// Should also rename this to something better +// If crate_opt is present, then finish compilation. If it's None, then +// call compile_upto and return the crate +pub fn compile_crate_from_input(input: driver::input, build_dir_opt: Option<Path>, + sess: session::Session, crate_opt: Option<@ast::crate>, + binary: ~str) -> @ast::crate { + debug!("Calling build_output_filenames with %?", build_dir_opt); + let outputs = driver::build_output_filenames(input, &build_dir_opt, &None, sess); + debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type); + let cfg = driver::build_configuration(sess, binary, input); + match crate_opt { + Some(c) => { + debug!("Calling compile_rest, outputs = %?", outputs); + driver::compile_rest(sess, cfg, driver::cu_everything, Some(outputs), Some(c)); + c } None => { - warn(~"missing crate_type attr, assuming lib"); - - false + debug!("Calling compile_upto, outputs = %?", outputs); + let (crate, _) = driver::compile_upto(sess, cfg, input, driver::cu_parse, + Some(outputs)); + crate } - }; - - if test { - need_dir(&test_dir); - - outputs = driver::build_output_filenames(input, &Some(test_dir), - &None, sess) } - else if is_bin { - need_dir(&bin_dir); - - let path = bin_dir.push(fmt!("%s-%s-%s%s", name, - hash(name + uuid + vers), - vers, exe_suffix())); - outputs = driver::build_output_filenames(input, &None, &Some(path), - sess); - } else { - need_dir(&lib_dir); - - outputs = driver::build_output_filenames(input, &Some(lib_dir), - &None, sess) - } - - driver::compile_rest(sess, cfg, driver::cu_everything, - Some(outputs), Some(crate)); - - true } #[cfg(windows)] @@ -749,20 +525,19 @@ pub fn exe_suffix() -> ~str { ~".exe" } pub fn exe_suffix() -> ~str { ~"" } +// Called by build_crates // FIXME (#4432): Use workcache to only compile when needed pub fn compile_crate(sysroot: Option<Path>, crate: &Path, dir: &Path, flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool { - compile_input(sysroot, driver::file_input(*crate), dir, flags, cfgs, - opt, test) + debug!("compile_crate: crate=%s, dir=%s", crate.to_str(), dir.to_str()); + debug!("compile_crate: flags =..."); + for flags.each |&fl| { + debug!("+++ %s", fl); + } + compile_input(sysroot, crate, dir, flags, cfgs, opt, test) } -pub fn compile_str(sysroot: Option<Path>, code: ~str, dir: &Path, - flags: ~[~str], cfgs: ~[~str], opt: bool, - test: bool) -> bool { - compile_input(sysroot, driver::str_input(code), dir, flags, cfgs, - opt, test) -} #[cfg(windows)] pub fn link_exe(_src: &Path, _dest: &Path) -> bool { |
