From 678831d853e4c840721451e51b4427ebd4404e81 Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Mon, 6 Jan 2014 18:49:01 +0100 Subject: [PATCH 1/8] move PckSript to rust_packagescript.rs --- src/librustpkg/lib.rs | 143 +-------------------------- src/librustpkg/package_script.rs | 161 +++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 139 deletions(-) create mode 100644 src/librustpkg/package_script.rs diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index 99cf14f0d9624..ed20a1ad5f5a6 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -20,18 +20,14 @@ extern mod extra; extern mod rustc; extern mod syntax; -use std::{os, run, str, task}; -use std::io::process; +use std::{os, run, task}; use std::io; use std::io::fs; pub use std::path::Path; -use extra::workcache; -use rustc::driver::{driver, session}; use rustc::metadata::filesearch; use rustc::metadata::filesearch::rust_path; use rustc::util::sha2; -use syntax::{ast, diagnostic}; use messages::{error, warn, note}; use parse_args::{ParseResult, parse_args}; use path_util::{build_pkg_id_in_workspace, built_test_in_workspace}; @@ -46,9 +42,10 @@ use context::{BuildContext, Trans, Nothing, Pretty, Analysis, use context::{Command, BuildCmd, CleanCmd, DoCmd, InfoCmd, InstallCmd, ListCmd, PreferCmd, TestCmd, InitCmd, UninstallCmd, UnpreferCmd}; use crate_id::CrateId; +use package_script::PkgScript; use package_source::PkgSrc; use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench}; -use target::{Main, Tests, MaybeCustom, Inferred, JustOne}; +use target::{Tests, MaybeCustom, Inferred, JustOne}; use workcache_support::digest_only_date; use exit_codes::{COPY_FAILED_CODE}; @@ -60,6 +57,7 @@ pub mod exit_codes; mod installed_packages; mod messages; pub mod crate_id; +mod package_script; pub mod package_source; mod parse_args; mod path_util; @@ -74,139 +72,6 @@ mod workspace; pub mod usage; -/// A PkgScript represents user-supplied custom logic for -/// special build hooks. This only exists for packages with -/// an explicit package script. -struct PkgScript<'a> { - /// Uniquely identifies this package - id: &'a CrateId, - /// File path for the package script - input: Path, - /// The session to use *only* for compiling the custom - /// build script - sess: session::Session, - /// The config for compiling the custom build script - cfg: ast::CrateConfig, - /// The crate and ast_map for the custom build script - crate_and_map: Option<(ast::Crate, syntax::ast_map::map)>, - /// Directory in which to store build output - build_dir: Path -} - -impl<'a> PkgScript<'a> { - /// 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<'a>(sysroot: Path, - script: Path, - workspace: &Path, - id: &'a CrateId) -> PkgScript<'a> { - // Get the executable name that was invoked - let binary = os::args()[0].to_owned(); - // Build the rustc session data structures to pass - // to the compiler - debug!("pkgscript parse: {}", sysroot.display()); - let options = @session::options { - binary: binary, - maybe_sysroot: Some(@sysroot), - outputs: ~[session::OutputExecutable], - .. (*session::basic_options()).clone() - }; - let input = driver::file_input(script.clone()); - let sess = driver::build_session(options, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); - let cfg = driver::build_configuration(sess); - let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input); - let crate_and_map = driver::phase_2_configure_and_expand(sess, cfg.clone(), crate); - let work_dir = build_pkg_id_in_workspace(id, workspace); - - debug!("Returning package script with id {}", id.to_str()); - - PkgScript { - id: id, - input: script, - sess: sess, - cfg: cfg, - crate_and_map: Some(crate_and_map), - build_dir: work_dir - } - } - - fn build_custom(&mut self, exec: &mut workcache::Exec) -> ~str { - let sess = self.sess; - - debug!("Working directory = {}", self.build_dir.display()); - // Collect together any user-defined commands in the package script - let (crate, ast_map) = self.crate_and_map.take_unwrap(); - let crate = util::ready_crate(sess, crate); - debug!("Building output filenames with script name {}", - driver::source_name(&driver::file_input(self.input.clone()))); - let exe = self.build_dir.join("pkg" + util::exe_suffix()); - util::compile_crate_from_input(&self.input, - exec, - Nothing, - &self.build_dir, - sess, - crate, - ast_map, - Main); - // Discover the output - // FIXME (#9639): This needs to handle non-utf8 paths - // Discover the output - exec.discover_output("binary", exe.as_str().unwrap().to_owned(), digest_only_date(&exe)); - exe.as_str().unwrap().to_owned() - } - - - /// Run the contents of this package script, where - /// 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, or - /// None if `exe` could not be started. - fn run_custom(exe: &Path, sysroot: &Path) -> Option<(~[~str], process::ProcessExit)> { - debug!("Running program: {} {} {}", exe.as_str().unwrap().to_owned(), - sysroot.display(), "install"); - // FIXME #7401 should support commands besides `install` - // FIXME (#9639): This needs to handle non-utf8 paths - let opt_status = run::process_status(exe.as_str().unwrap(), - [sysroot.as_str().unwrap().to_owned(), ~"install"]); - match opt_status { - Some(status) => { - if !status.success() { - debug!("run_custom: first pkg command failed with {:?}", status); - Some((~[], status)) - } - else { - debug!("Running program (configs): {} {} {}", - exe.display(), sysroot.display(), "configs"); - // FIXME (#9639): This needs to handle non-utf8 paths - let opt_output = run::process_output(exe.as_str().unwrap(), - [sysroot.as_str().unwrap().to_owned(), - ~"configs"]); - match opt_output { - Some(output) => { - debug!("run_custom: second pkg command did {:?}", output.status); - // Run the configs() function to get the configs - let cfgs = str::from_utf8(output.output).words() - .map(|w| w.to_owned()).collect(); - Some((cfgs, output.status)) - }, - None => { - debug!("run_custom: second pkg command failed to start"); - Some((~[], status)) - } - } - } - }, - None => { - debug!("run_custom: first pkg command failed to start"); - None - } - } - } -} - pub trait CtxMethods { fn run(&self, cmd: Command, args: ~[~str]); fn do_cmd(&self, _cmd: &str, _pkgname: &str); diff --git a/src/librustpkg/package_script.rs b/src/librustpkg/package_script.rs new file mode 100644 index 0000000000000..15bce3421e318 --- /dev/null +++ b/src/librustpkg/package_script.rs @@ -0,0 +1,161 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern mod extra; +extern mod rustc; +extern mod syntax; + +use std::{os, run, str}; +use std::io::process; +pub use std::path::Path; + +use extra::workcache; +use rustc::driver::{driver, session}; +use syntax::{ast, diagnostic}; +use path_util::{build_pkg_id_in_workspace}; +use context::{Nothing}; +use crate_id::CrateId; +use target::{Main}; +use util; +use workcache_support::digest_only_date; + + +/// A PkgScript represents user-supplied custom logic for +/// special build hooks. This only exists for packages with +/// an explicit package script. +pub struct PkgScript<'a> { + /// Uniquely identifies this package + id: &'a CrateId, + /// File path for the package script + input: Path, + /// The session to use *only* for compiling the custom + /// build script + sess: session::Session, + /// The config for compiling the custom build script + cfg: ast::CrateConfig, + /// The crate and ast_map for the custom build script + crate_and_map: Option<(ast::Crate, syntax::ast_map::map)>, + /// Directory in which to store build output + build_dir: Path +} + +impl<'a> PkgScript<'a> { + /// Given the path name for a package script + /// and a package ID, parse the package script into + /// a PkgScript that we can then execute + pub fn parse<'a>(sysroot: Path, + script: Path, + workspace: &Path, + id: &'a CrateId) -> PkgScript<'a> { + // Get the executable name that was invoked + let binary = os::args()[0].to_owned(); + // Build the rustc session data structures to pass + // to the compiler + debug!("pkgscript parse: {}", sysroot.display()); + let options = @session::options { + binary: binary, + maybe_sysroot: Some(@sysroot), + outputs: ~[session::OutputExecutable], + .. (*session::basic_options()).clone() + }; + let input = driver::file_input(script.clone()); + let sess = driver::build_session(options, + @diagnostic::DefaultEmitter as + @diagnostic::Emitter); + let cfg = driver::build_configuration(sess); + let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input); + let crate_and_map = driver::phase_2_configure_and_expand(sess, cfg.clone(), crate); + let work_dir = build_pkg_id_in_workspace(id, workspace); + + debug!("Returning package script with id {}", id.to_str()); + + PkgScript { + id: id, + input: script, + sess: sess, + cfg: cfg, + crate_and_map: Some(crate_and_map), + build_dir: work_dir + } + } + + pub fn build_custom(&mut self, exec: &mut workcache::Exec) -> ~str { + let sess = self.sess; + + debug!("Working directory = {}", self.build_dir.display()); + // Collect together any user-defined commands in the package script + let (crate, ast_map) = self.crate_and_map.take_unwrap(); + let crate = util::ready_crate(sess, crate); + debug!("Building output filenames with script name {}", + driver::source_name(&driver::file_input(self.input.clone()))); + let exe = self.build_dir.join("pkg" + util::exe_suffix()); + util::compile_crate_from_input(&self.input, + exec, + Nothing, + &self.build_dir, + sess, + crate, + ast_map, + Main); + // Discover the output + // FIXME (#9639): This needs to handle non-utf8 paths + // Discover the output + exec.discover_output("binary", exe.as_str().unwrap().to_owned(), digest_only_date(&exe)); + exe.as_str().unwrap().to_owned() + } + + + /// Run the contents of this package script, where + /// 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, or + /// None if `exe` could not be started. + pub fn run_custom(exe: &Path, sysroot: &Path) -> Option<(~[~str], process::ProcessExit)> { + debug!("Running program: {} {} {}", exe.as_str().unwrap().to_owned(), + sysroot.display(), "install"); + // FIXME #7401 should support commands besides `install` + // FIXME (#9639): This needs to handle non-utf8 paths + let opt_status = run::process_status(exe.as_str().unwrap(), + [sysroot.as_str().unwrap().to_owned(), ~"install"]); + match opt_status { + Some(status) => { + if !status.success() { + debug!("run_custom: first pkg command failed with {:?}", status); + Some((~[], status)) + } + else { + debug!("Running program (configs): {} {} {}", + exe.display(), sysroot.display(), "configs"); + // FIXME (#9639): This needs to handle non-utf8 paths + let opt_output = run::process_output(exe.as_str().unwrap(), + [sysroot.as_str().unwrap().to_owned(), + ~"configs"]); + match opt_output { + Some(output) => { + debug!("run_custom: second pkg command did {:?}", output.status); + // Run the configs() function to get the configs + let cfgs = str::from_utf8(output.output).words() + .map(|w| w.to_owned()).collect(); + Some((cfgs, output.status)) + }, + None => { + debug!("run_custom: second pkg command failed to start"); + Some((~[], status)) + } + } + } + }, + None => { + debug!("run_custom: first pkg command failed to start"); + None + } + } + } +} From be08f63bc48380d292176810e8e9faf2e391139e Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Mon, 6 Jan 2014 20:03:16 +0100 Subject: [PATCH 2/8] Moved rustpkg::CtxMethods::run(cmd: Command ...) to rustpkg::run_cmd.rs --- src/librustpkg/lib.rs | 585 ++-------------------------- src/librustpkg/run_cmd.rs | 580 +++++++++++++++++++++++++++ src/librustpkg/workcache_support.rs | 2 +- 3 files changed, 603 insertions(+), 564 deletions(-) create mode 100644 src/librustpkg/run_cmd.rs diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index ed20a1ad5f5a6..e0a3ea0ae9a5b 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -20,33 +20,30 @@ extern mod extra; extern mod rustc; extern mod syntax; -use std::{os, run, task}; -use std::io; -use std::io::fs; pub use std::path::Path; +use context::{Trans, Nothing, Pretty, Analysis, LLVMAssemble}; +use context::{LLVMCompileBitcode, BuildCmd, CleanCmd, DoCmd, InfoCmd}; +use context::{InstallCmd, ListCmd, PreferCmd, TestCmd, InitCmd, UninstallCmd}; +use context::{UnpreferCmd}; +//use path_util::{build_pkg_id_in_workspace, built_test_in_workspace}; +//use path_util::{in_rust_path, built_executable_in_workspace}; +//use path_util::{built_library_in_workspace, default_workspace}; +//use path_util::{target_executable_in_workspace, target_library_in_workspace}; +//use path_util::{dir_has_crate_file}; +use run_cmd::{CtxMethods}; +//use source_control::{CheckedOutSources, is_git_dir, make_read_only}; +//use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench}; +//use target::{Tests, MaybeCustom, Inferred, JustOne}; +//use workcache_support::digest_only_date; +//use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces, cwd_to_workspace}; +//use workspace::{determine_destination}; + +use std::{os, task}; +use context::{BuildContext}; use rustc::metadata::filesearch; -use rustc::metadata::filesearch::rust_path; -use rustc::util::sha2; -use messages::{error, warn, note}; use parse_args::{ParseResult, parse_args}; -use path_util::{build_pkg_id_in_workspace, built_test_in_workspace}; -use path_util::in_rust_path; -use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace}; -use path_util::{target_executable_in_workspace, target_library_in_workspace, dir_has_crate_file}; -use source_control::{CheckedOutSources, is_git_dir, make_read_only}; -use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces, cwd_to_workspace}; -use workspace::determine_destination; -use context::{BuildContext, Trans, Nothing, Pretty, Analysis, - LLVMAssemble, LLVMCompileBitcode}; -use context::{Command, BuildCmd, CleanCmd, DoCmd, InfoCmd, InstallCmd, ListCmd, - PreferCmd, TestCmd, InitCmd, UninstallCmd, UnpreferCmd}; -use crate_id::CrateId; -use package_script::PkgScript; -use package_source::PkgSrc; -use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench}; -use target::{Tests, MaybeCustom, Inferred, JustOne}; -use workcache_support::digest_only_date; +use path_util::{default_workspace}; use exit_codes::{COPY_FAILED_CODE}; pub mod api; @@ -61,555 +58,17 @@ mod package_script; pub mod package_source; mod parse_args; mod path_util; +mod run_cmd; mod source_control; mod target; #[cfg(not(windows), test)] // FIXME test failure on windows: #10471 mod tests; +pub mod usage; mod util; pub mod version; pub mod workcache_support; mod workspace; -pub mod usage; - -pub trait CtxMethods { - fn run(&self, cmd: Command, args: ~[~str]); - fn do_cmd(&self, _cmd: &str, _pkgname: &str); - /// Returns a pair of the selected package ID, and the destination workspace - fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)>; - /// Returns the destination workspace - fn build(&self, pkg_src: &mut PkgSrc, what: &WhatToBuild); - fn clean(&self, workspace: &Path, id: &CrateId); - fn info(&self); - /// Returns a pair. First component is a list of installed paths, - /// second is a list of declared and discovered inputs - fn install(&self, src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]); - /// Returns a list of installed files - fn install_no_build(&self, - build_workspace: &Path, - build_inputs: &[Path], - target_workspace: &Path, - id: &CrateId) -> ~[~str]; - fn prefer(&self, _id: &str, _vers: Option<~str>); - fn test(&self, id: &CrateId, workspace: &Path); - fn uninstall(&self, _id: &str, _vers: Option<~str>); - fn unprefer(&self, _id: &str, _vers: Option<~str>); - fn init(&self); -} - -impl CtxMethods for BuildContext { - fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)> { - let cwd = os::getcwd(); - - if args.len() < 1 { - match cwd_to_workspace() { - None if dir_has_crate_file(&cwd) => { - // FIXME (#9639): This needs to handle non-utf8 paths - let crateid = CrateId::new(cwd.filename_str().unwrap()); - let mut pkg_src = PkgSrc::new(cwd, default_workspace(), true, crateid); - self.build(&mut pkg_src, what); - match pkg_src { - PkgSrc { destination_workspace: ws, - id: id, .. } => { - Some((id, ws)) - } - } - } - None => { usage::build(); None } - Some((ws, crateid)) => { - let mut pkg_src = PkgSrc::new(ws.clone(), ws, false, crateid); - self.build(&mut pkg_src, what); - match pkg_src { - PkgSrc { destination_workspace: ws, - id: id, .. } => { - Some((id, ws)) - } - } - } - } - } else { - // The package id is presumed to be the first command-line - // argument - let crateid = CrateId::new(args[0].clone()); - let mut dest_ws = default_workspace(); - each_pkg_parent_workspace(&self.context, &crateid, |workspace| { - debug!("found pkg {} in workspace {}, trying to build", - crateid.to_str(), workspace.display()); - dest_ws = determine_destination(os::getcwd(), - self.context.use_rust_path_hack, - workspace); - let mut pkg_src = PkgSrc::new(workspace.clone(), dest_ws.clone(), - false, crateid.clone()); - self.build(&mut pkg_src, what); - true - }); - // n.b. If this builds multiple packages, it only returns the workspace for - // the last one. The whole building-multiple-packages-with-the-same-ID is weird - // anyway and there are no tests for it, so maybe take it out - Some((crateid, dest_ws)) - } - } - fn run(&self, cmd: Command, args: ~[~str]) { - let cwd = os::getcwd(); - match cmd { - BuildCmd => { - self.build_args(args, &WhatToBuild::new(MaybeCustom, Everything)); - } - CleanCmd => { - if args.len() < 1 { - match cwd_to_workspace() { - None => { usage::clean(); return } - // tjc: Maybe clean should clean all the packages in the - // current workspace, though? - Some((ws, crateid)) => self.clean(&ws, &crateid) - } - - } - else { - // The package id is presumed to be the first command-line - // argument - let crateid = CrateId::new(args[0].clone()); - self.clean(&cwd, &crateid); // tjc: should use workspace, not cwd - } - } - DoCmd => { - if args.len() < 2 { - return usage::do_cmd(); - } - - self.do_cmd(args[0].clone(), args[1].clone()); - } - InfoCmd => { - self.info(); - } - InstallCmd => { - if args.len() < 1 { - match cwd_to_workspace() { - None if dir_has_crate_file(&cwd) => { - // FIXME (#9639): This needs to handle non-utf8 paths - - let inferred_crateid = - CrateId::new(cwd.filename_str().unwrap()); - self.install(PkgSrc::new(cwd, default_workspace(), - true, inferred_crateid), - &WhatToBuild::new(MaybeCustom, Everything)); - } - None => { usage::install(); return; } - Some((ws, crateid)) => { - let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, crateid); - self.install(pkg_src, &WhatToBuild::new(MaybeCustom, - Everything)); - } - } - } - else { - // The package id is presumed to be the first command-line - // argument - let crateid = CrateId::new(args[0]); - let workspaces = pkg_parent_workspaces(&self.context, &crateid); - debug!("package ID = {}, found it in {:?} workspaces", - crateid.to_str(), workspaces.len()); - if workspaces.is_empty() { - let d = default_workspace(); - let src = PkgSrc::new(d.clone(), d, false, crateid.clone()); - self.install(src, &WhatToBuild::new(MaybeCustom, Everything)); - } - else { - for workspace in workspaces.iter() { - let dest = determine_destination(os::getcwd(), - self.context.use_rust_path_hack, - workspace); - let src = PkgSrc::new(workspace.clone(), - dest, - self.context.use_rust_path_hack, - crateid.clone()); - self.install(src, &WhatToBuild::new(MaybeCustom, Everything)); - }; - } - } - } - ListCmd => { - println("Installed packages:"); - installed_packages::list_installed_packages(|pkg_id| { - pkg_id.path.display().with_str(|s| println(s)); - true - }); - } - PreferCmd => { - if args.len() < 1 { - return usage::uninstall(); - } - - self.prefer(args[0], None); - } - TestCmd => { - // Build the test executable - let maybe_id_and_workspace = self.build_args(args, - &WhatToBuild::new(MaybeCustom, Tests)); - match maybe_id_and_workspace { - Some((pkg_id, workspace)) => { - // Assuming it's built, run the tests - self.test(&pkg_id, &workspace); - } - None => { - error("Testing failed because building the specified package failed."); - } - } - } - InitCmd => { - if args.len() != 0 { - return usage::init(); - } else { - self.init(); - } - } - UninstallCmd => { - if args.len() < 1 { - return usage::uninstall(); - } - - let crateid = CrateId::new(args[0]); - if !installed_packages::package_is_installed(&crateid) { - warn(format!("Package {} doesn't seem to be installed! \ - Doing nothing.", args[0])); - return; - } - else { - let rp = rust_path(); - assert!(!rp.is_empty()); - each_pkg_parent_workspace(&self.context, &crateid, |workspace| { - path_util::uninstall_package_from(workspace, &crateid); - note(format!("Uninstalled package {} (was installed in {})", - crateid.to_str(), workspace.display())); - true - }); - } - } - UnpreferCmd => { - if args.len() < 1 { - return usage::unprefer(); - } - - self.unprefer(args[0], None); - } - } - } - - fn do_cmd(&self, _cmd: &str, _pkgname: &str) { - // stub - fail!("`do` not yet implemented"); - } - - fn build(&self, pkg_src: &mut PkgSrc, what_to_build: &WhatToBuild) { - use conditions::git_checkout_failed::cond; - - let workspace = pkg_src.source_workspace.clone(); - let crateid = pkg_src.id.clone(); - - debug!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \ - crateid = {} pkgsrc start_dir = {}", workspace.display(), - in_rust_path(&workspace), is_git_dir(&workspace.join(&crateid.path)), - crateid.to_str(), pkg_src.start_dir.display()); - debug!("build: what to build = {:?}", what_to_build); - - // If workspace isn't in the RUST_PATH, and it's a git repo, - // then clone it into the first entry in RUST_PATH, and repeat - if !in_rust_path(&workspace) && is_git_dir(&workspace.join(&crateid.path)) { - let mut out_dir = default_workspace().join("src"); - out_dir.push(&crateid.path); - let git_result = source_control::safe_git_clone(&workspace.join(&crateid.path), - &crateid.version, - &out_dir); - match git_result { - CheckedOutSources => make_read_only(&out_dir), - // FIXME (#9639): This needs to handle non-utf8 paths - _ => cond.raise((crateid.path.as_str().unwrap().to_owned(), out_dir.clone())) - }; - let default_ws = default_workspace(); - debug!("Calling build recursively with {:?} and {:?}", default_ws.display(), - crateid.to_str()); - return self.build(&mut PkgSrc::new(default_ws.clone(), - default_ws, - false, - crateid.clone()), what_to_build); - } - - // Is there custom build logic? If so, use it - let mut custom = false; - debug!("Package source directory = {}", pkg_src.to_str()); - let opt = pkg_src.package_script_option(); - debug!("Calling pkg_script_option on {:?}", opt); - let cfgs = match (pkg_src.package_script_option(), what_to_build.build_type) { - (Some(package_script_path), MaybeCustom) => { - let sysroot = self.sysroot_to_use(); - // Build the package script if needed - let script_build = format!("build_package_script({})", - package_script_path.display()); - let pkg_exe = self.workcache_context.with_prep(script_build, |prep| { - let subsysroot = sysroot.clone(); - let psp = package_script_path.clone(); - let ws = workspace.clone(); - let pid = crateid.clone(); - prep.exec(proc(exec) { - let mut pscript = PkgScript::parse(subsysroot.clone(), - psp.clone(), - &ws, - &pid); - pscript.build_custom(exec) - }) - }); - // We always *run* the package script - match PkgScript::run_custom(&Path::new(pkg_exe), &sysroot) { - Some((cfgs, hook_result)) => { - debug!("Command return code = {:?}", hook_result); - if !hook_result.success() { - fail!("Error running custom build command") - } - custom = true; - // otherwise, the package script succeeded - cfgs - }, - None => { - fail!("Error starting custom build command") - } - } - } - (Some(_), Inferred) => { - debug!("There is a package script, but we're ignoring it"); - ~[] - } - (None, _) => { - debug!("No package script, continuing"); - ~[] - } - } + self.context.cfgs; - - // If there was a package script, it should have finished - // the build already. Otherwise... - if !custom { - match what_to_build.sources { - // Find crates inside the workspace - Everything => pkg_src.find_crates(), - // Find only tests - Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }), - // Don't infer any crates -- just build the one that was requested - JustOne(ref p) => { - // We expect that p is relative to the package source's start directory, - // so check that assumption - debug!("JustOne: p = {}", p.display()); - assert!(pkg_src.start_dir.join(p).exists()); - if is_lib(p) { - PkgSrc::push_crate(&mut pkg_src.libs, 0, p); - } else if is_main(p) { - PkgSrc::push_crate(&mut pkg_src.mains, 0, p); - } else if is_test(p) { - PkgSrc::push_crate(&mut pkg_src.tests, 0, p); - } else if is_bench(p) { - PkgSrc::push_crate(&mut pkg_src.benchs, 0, p); - } else { - warn(format!("Not building any crates for dependency {}", p.display())); - return; - } - } - } - // Build it! - pkg_src.build(self, cfgs, []); - } - } - - fn clean(&self, workspace: &Path, id: &CrateId) { - // Could also support a custom build hook in the pkg - // script for cleaning files rustpkg doesn't know about. - // Do something reasonable for now - - let dir = build_pkg_id_in_workspace(id, workspace); - note(format!("Cleaning package {} (removing directory {})", - id.to_str(), dir.display())); - if dir.exists() { - fs::rmdir_recursive(&dir); - note(format!("Removed directory {}", dir.display())); - } - - note(format!("Cleaned package {}", id.to_str())); - } - - fn info(&self) { - // stub - fail!("info not yet implemented"); - } - - fn install(&self, mut pkg_src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]) { - - let id = pkg_src.id.clone(); - - let mut installed_files = ~[]; - let mut inputs = ~[]; - let mut build_inputs = ~[]; - - debug!("Installing package source: {}", pkg_src.to_str()); - - // workcache only knows about *crates*. Building a package - // just means inferring all the crates in it, then building each one. - self.build(&mut pkg_src, what); - - debug!("Done building package source {}", pkg_src.to_str()); - - let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(), - pkg_src.tests.clone(), pkg_src.benchs.clone()]; - debug!("In declare inputs for {}", id.to_str()); - for cs in to_do.iter() { - for c in cs.iter() { - let path = pkg_src.start_dir.join(&c.file); - debug!("Recording input: {}", path.display()); - // FIXME (#9639): This needs to handle non-utf8 paths - inputs.push((~"file", path.as_str().unwrap().to_owned())); - build_inputs.push(path); - } - } - - let result = self.install_no_build(pkg_src.build_workspace(), - build_inputs, - &pkg_src.destination_workspace, - &id).map(|s| Path::new(s.as_slice())); - installed_files = installed_files + result; - note(format!("Installed package {} to {}", - id.to_str(), - pkg_src.destination_workspace.display())); - (installed_files, inputs) - } - - // again, working around lack of Encodable for Path - fn install_no_build(&self, - build_workspace: &Path, - build_inputs: &[Path], - target_workspace: &Path, - id: &CrateId) -> ~[~str] { - - debug!("install_no_build: assuming {} comes from {} with target {}", - id.to_str(), build_workspace.display(), target_workspace.display()); - - // Now copy stuff into the install dirs - let maybe_executable = built_executable_in_workspace(id, build_workspace); - let maybe_library = built_library_in_workspace(id, build_workspace); - let target_exec = target_executable_in_workspace(id, target_workspace); - let target_lib = maybe_library.as_ref() - .map(|_| target_library_in_workspace(id, target_workspace)); - - debug!("target_exec = {} target_lib = {:?} \ - maybe_executable = {:?} maybe_library = {:?}", - target_exec.display(), target_lib, - maybe_executable, maybe_library); - - self.workcache_context.with_prep(id.install_tag(), |prep| { - for ee in maybe_executable.iter() { - // FIXME (#9639): This needs to handle non-utf8 paths - prep.declare_input("binary", - ee.as_str().unwrap(), - workcache_support::digest_only_date(ee)); - } - for ll in maybe_library.iter() { - // FIXME (#9639): This needs to handle non-utf8 paths - prep.declare_input("binary", - ll.as_str().unwrap(), - workcache_support::digest_only_date(ll)); - } - let subex = maybe_executable.clone(); - let sublib = maybe_library.clone(); - let sub_target_ex = target_exec.clone(); - let sub_target_lib = target_lib.clone(); - let sub_build_inputs = build_inputs.to_owned(); - prep.exec(proc(exe_thing) { - let mut outputs = ~[]; - // Declare all the *inputs* to the declared input too, as inputs - for executable in subex.iter() { - exe_thing.discover_input("binary", - executable.as_str().unwrap().to_owned(), - workcache_support::digest_only_date(executable)); - } - for library in sublib.iter() { - exe_thing.discover_input("binary", - library.as_str().unwrap().to_owned(), - workcache_support::digest_only_date(library)); - } - - for transitive_dependency in sub_build_inputs.iter() { - exe_thing.discover_input( - "file", - transitive_dependency.as_str().unwrap().to_owned(), - workcache_support::digest_file_with_date(transitive_dependency)); - } - - - for exec in subex.iter() { - debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display()); - fs::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX); - fs::copy(exec, &sub_target_ex); - // FIXME (#9639): This needs to handle non-utf8 paths - exe_thing.discover_output("binary", - sub_target_ex.as_str().unwrap(), - workcache_support::digest_only_date(&sub_target_ex)); - outputs.push(sub_target_ex.as_str().unwrap().to_owned()); - } - for lib in sublib.iter() { - let mut target_lib = sub_target_lib - .clone().expect(format!("I built {} but apparently \ - didn't install it!", lib.display())); - target_lib.set_filename(lib.filename().expect("weird target lib")); - fs::mkdir_recursive(&target_lib.dir_path(), io::UserRWX); - fs::copy(lib, &target_lib); - debug!("3. discovering output {}", target_lib.display()); - exe_thing.discover_output("binary", - target_lib.as_str().unwrap(), - workcache_support::digest_only_date(&target_lib)); - outputs.push(target_lib.as_str().unwrap().to_owned()); - } - outputs - }) - }) - } - - fn prefer(&self, _id: &str, _vers: Option<~str>) { - fail!("prefer not yet implemented"); - } - - fn test(&self, crateid: &CrateId, workspace: &Path) { - match built_test_in_workspace(crateid, workspace) { - Some(test_exec) => { - debug!("test: test_exec = {}", test_exec.display()); - // FIXME (#9639): This needs to handle non-utf8 paths - let opt_status = run::process_status(test_exec.as_str().unwrap(), [~"--test"]); - match opt_status { - Some(status) => { - if !status.success() { - fail!("Some tests failed"); - } - }, - None => fail!("Could not exec `{}`", test_exec.display()) - } - } - None => { - error(format!("Internal error: test executable for package ID {} in workspace {} \ - wasn't built! Please report this as a bug.", - crateid.to_str(), workspace.display())); - } - } - } - - fn init(&self) { - fs::mkdir_recursive(&Path::new("src"), io::UserRWX); - fs::mkdir_recursive(&Path::new("bin"), io::UserRWX); - fs::mkdir_recursive(&Path::new("lib"), io::UserRWX); - fs::mkdir_recursive(&Path::new("build"), io::UserRWX); - } - - fn uninstall(&self, _id: &str, _vers: Option<~str>) { - fail!("uninstall not yet implemented"); - } - - fn unprefer(&self, _id: &str, _vers: Option<~str>) { - fail!("unprefer not yet implemented"); - } -} pub fn main() { println("WARNING: The Rust package manager is experimental and may be unstable"); diff --git a/src/librustpkg/run_cmd.rs b/src/librustpkg/run_cmd.rs new file mode 100644 index 0000000000000..88aa88f69b700 --- /dev/null +++ b/src/librustpkg/run_cmd.rs @@ -0,0 +1,580 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::{io, os, run}; +use std::io::fs; +pub use std::path::Path; + +use context::{BuildContext}; +use context::{Command, BuildCmd, CleanCmd, DoCmd, InfoCmd}; +use context::{InstallCmd, ListCmd, PreferCmd, TestCmd, InitCmd, UninstallCmd}; +use context::{UnpreferCmd}; +use crate_id::{CrateId}; +use installed_packages; +use messages::{error, warn, note}; +use path_util::{build_pkg_id_in_workspace, built_test_in_workspace}; +use path_util::{in_rust_path, built_executable_in_workspace}; +use path_util::{built_library_in_workspace, default_workspace}; +use path_util::{target_executable_in_workspace, target_library_in_workspace}; +use path_util::{dir_has_crate_file}; +use package_script::PkgScript; +use package_source::PkgSrc; +use path_util; +use rustc::metadata::filesearch::rust_path; +use source_control; +use source_control::{CheckedOutSources, is_git_dir, make_read_only}; +use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench}; +use target::{Tests, MaybeCustom, Inferred, JustOne}; +use usage; +use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces, cwd_to_workspace}; +use workspace::determine_destination; +use workcache_support::digest_only_date; +use workcache_support; + +pub trait CtxMethods { + fn run(&self, cmd: Command, args: ~[~str]); + fn do_cmd(&self, _cmd: &str, _pkgname: &str); + /// Returns a pair of the selected package ID, and the destination workspace + fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)>; + /// Returns the destination workspace + fn build(&self, pkg_src: &mut PkgSrc, what: &WhatToBuild); + fn clean(&self, workspace: &Path, id: &CrateId); + fn info(&self); + /// Returns a pair. First component is a list of installed paths, + /// second is a list of declared and discovered inputs + fn install(&self, src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]); + /// Returns a list of installed files + fn install_no_build(&self, + build_workspace: &Path, + build_inputs: &[Path], + target_workspace: &Path, + id: &CrateId) -> ~[~str]; + fn prefer(&self, _id: &str, _vers: Option<~str>); + fn test(&self, id: &CrateId, workspace: &Path); + fn uninstall(&self, _id: &str, _vers: Option<~str>); + fn unprefer(&self, _id: &str, _vers: Option<~str>); + fn init(&self); +} + +impl CtxMethods for BuildContext { + fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)> { + let cwd = os::getcwd(); + + if args.len() < 1 { + match cwd_to_workspace() { + None if dir_has_crate_file(&cwd) => { + // FIXME (#9639): This needs to handle non-utf8 paths + let crateid = CrateId::new(cwd.filename_str().unwrap()); + let mut pkg_src = PkgSrc::new(cwd, default_workspace(), true, crateid); + self.build(&mut pkg_src, what); + match pkg_src { + PkgSrc { destination_workspace: ws, + id: id, .. } => { + Some((id, ws)) + } + } + } + None => { usage::build(); None } + Some((ws, crateid)) => { + let mut pkg_src = PkgSrc::new(ws.clone(), ws, false, crateid); + self.build(&mut pkg_src, what); + match pkg_src { + PkgSrc { destination_workspace: ws, + id: id, .. } => { + Some((id, ws)) + } + } + } + } + } else { + // The package id is presumed to be the first command-line + // argument + let crateid = CrateId::new(args[0].clone()); + let mut dest_ws = default_workspace(); + each_pkg_parent_workspace(&self.context, &crateid, |workspace| { + debug!("found pkg {} in workspace {}, trying to build", + crateid.to_str(), workspace.display()); + dest_ws = determine_destination(os::getcwd(), + self.context.use_rust_path_hack, + workspace); + let mut pkg_src = PkgSrc::new(workspace.clone(), dest_ws.clone(), + false, crateid.clone()); + self.build(&mut pkg_src, what); + true + }); + // n.b. If this builds multiple packages, it only returns the workspace for + // the last one. The whole building-multiple-packages-with-the-same-ID is weird + // anyway and there are no tests for it, so maybe take it out + Some((crateid, dest_ws)) + } + } + fn run(&self, cmd: Command, args: ~[~str]) { + let cwd = os::getcwd(); + match cmd { + BuildCmd => { + self.build_args(args, &WhatToBuild::new(MaybeCustom, Everything)); + } + CleanCmd => { + if args.len() < 1 { + match cwd_to_workspace() { + None => { usage::clean(); return } + // tjc: Maybe clean should clean all the packages in the + // current workspace, though? + Some((ws, crateid)) => self.clean(&ws, &crateid) + } + + } + else { + // The package id is presumed to be the first command-line + // argument + let crateid = CrateId::new(args[0].clone()); + self.clean(&cwd, &crateid); // tjc: should use workspace, not cwd + } + } + DoCmd => { + if args.len() < 2 { + return usage::do_cmd(); + } + + self.do_cmd(args[0].clone(), args[1].clone()); + } + InfoCmd => { + self.info(); + } + InstallCmd => { + if args.len() < 1 { + match cwd_to_workspace() { + None if dir_has_crate_file(&cwd) => { + // FIXME (#9639): This needs to handle non-utf8 paths + + let inferred_crateid = + CrateId::new(cwd.filename_str().unwrap()); + self.install(PkgSrc::new(cwd, default_workspace(), + true, inferred_crateid), + &WhatToBuild::new(MaybeCustom, Everything)); + } + None => { usage::install(); return; } + Some((ws, crateid)) => { + let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, crateid); + self.install(pkg_src, &WhatToBuild::new(MaybeCustom, + Everything)); + } + } + } + else { + // The package id is presumed to be the first command-line + // argument + let crateid = CrateId::new(args[0]); + let workspaces = pkg_parent_workspaces(&self.context, &crateid); + debug!("package ID = {}, found it in {:?} workspaces", + crateid.to_str(), workspaces.len()); + if workspaces.is_empty() { + let d = default_workspace(); + let src = PkgSrc::new(d.clone(), d, false, crateid.clone()); + self.install(src, &WhatToBuild::new(MaybeCustom, Everything)); + } + else { + for workspace in workspaces.iter() { + let dest = determine_destination(os::getcwd(), + self.context.use_rust_path_hack, + workspace); + let src = PkgSrc::new(workspace.clone(), + dest, + self.context.use_rust_path_hack, + crateid.clone()); + self.install(src, &WhatToBuild::new(MaybeCustom, Everything)); + }; + } + } + } + ListCmd => { + println("Installed packages:"); + installed_packages::list_installed_packages(|pkg_id| { + pkg_id.path.display().with_str(|s| println(s)); + true + }); + } + PreferCmd => { + if args.len() < 1 { + return usage::uninstall(); + } + + self.prefer(args[0], None); + } + TestCmd => { + // Build the test executable + let maybe_id_and_workspace = self.build_args(args, + &WhatToBuild::new(MaybeCustom, Tests)); + match maybe_id_and_workspace { + Some((pkg_id, workspace)) => { + // Assuming it's built, run the tests + self.test(&pkg_id, &workspace); + } + None => { + error("Testing failed because building the specified package failed."); + } + } + } + InitCmd => { + if args.len() != 0 { + return usage::init(); + } else { + self.init(); + } + } + UninstallCmd => { + if args.len() < 1 { + return usage::uninstall(); + } + + let crateid = CrateId::new(args[0]); + if !installed_packages::package_is_installed(&crateid) { + warn(format!("Package {} doesn't seem to be installed! \ + Doing nothing.", args[0])); + return; + } + else { + let rp = rust_path(); + assert!(!rp.is_empty()); + each_pkg_parent_workspace(&self.context, &crateid, |workspace| { + path_util::uninstall_package_from(workspace, &crateid); + note(format!("Uninstalled package {} (was installed in {})", + crateid.to_str(), workspace.display())); + true + }); + } + } + UnpreferCmd => { + if args.len() < 1 { + return usage::unprefer(); + } + + self.unprefer(args[0], None); + } + } + } + + fn do_cmd(&self, _cmd: &str, _pkgname: &str) { + // stub + fail!("`do` not yet implemented"); + } + + fn build(&self, pkg_src: &mut PkgSrc, what_to_build: &WhatToBuild) { + use conditions::git_checkout_failed::cond; + + let workspace = pkg_src.source_workspace.clone(); + let crateid = pkg_src.id.clone(); + + debug!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \ + crateid = {} pkgsrc start_dir = {}", workspace.display(), + in_rust_path(&workspace), is_git_dir(&workspace.join(&crateid.path)), + crateid.to_str(), pkg_src.start_dir.display()); + debug!("build: what to build = {:?}", what_to_build); + + // If workspace isn't in the RUST_PATH, and it's a git repo, + // then clone it into the first entry in RUST_PATH, and repeat + if !in_rust_path(&workspace) && is_git_dir(&workspace.join(&crateid.path)) { + let mut out_dir = default_workspace().join("src"); + out_dir.push(&crateid.path); + let git_result = source_control::safe_git_clone(&workspace.join(&crateid.path), + &crateid.version, + &out_dir); + match git_result { + CheckedOutSources => make_read_only(&out_dir), + // FIXME (#9639): This needs to handle non-utf8 paths + _ => cond.raise((crateid.path.as_str().unwrap().to_owned(), out_dir.clone())) + }; + let default_ws = default_workspace(); + debug!("Calling build recursively with {:?} and {:?}", default_ws.display(), + crateid.to_str()); + return self.build(&mut PkgSrc::new(default_ws.clone(), + default_ws, + false, + crateid.clone()), what_to_build); + } + + // Is there custom build logic? If so, use it + let mut custom = false; + debug!("Package source directory = {}", pkg_src.to_str()); + let opt = pkg_src.package_script_option(); + debug!("Calling pkg_script_option on {:?}", opt); + let cfgs = match (pkg_src.package_script_option(), what_to_build.build_type) { + (Some(package_script_path), MaybeCustom) => { + let sysroot = self.sysroot_to_use(); + // Build the package script if needed + let script_build = format!("build_package_script({})", + package_script_path.display()); + let pkg_exe = self.workcache_context.with_prep(script_build, |prep| { + let subsysroot = sysroot.clone(); + let psp = package_script_path.clone(); + let ws = workspace.clone(); + let pid = crateid.clone(); + prep.exec(proc(exec) { + let mut pscript = PkgScript::parse(subsysroot.clone(), + psp.clone(), + &ws, + &pid); + pscript.build_custom(exec) + }) + }); + // We always *run* the package script + match PkgScript::run_custom(&Path::new(pkg_exe), &sysroot) { + Some((cfgs, hook_result)) => { + debug!("Command return code = {:?}", hook_result); + if !hook_result.success() { + fail!("Error running custom build command") + } + custom = true; + // otherwise, the package script succeeded + cfgs + }, + None => { + fail!("Error starting custom build command") + } + } + } + (Some(_), Inferred) => { + debug!("There is a package script, but we're ignoring it"); + ~[] + } + (None, _) => { + debug!("No package script, continuing"); + ~[] + } + } + self.context.cfgs; + + // If there was a package script, it should have finished + // the build already. Otherwise... + if !custom { + match what_to_build.sources { + // Find crates inside the workspace + Everything => pkg_src.find_crates(), + // Find only tests + Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }), + // Don't infer any crates -- just build the one that was requested + JustOne(ref p) => { + // We expect that p is relative to the package source's start directory, + // so check that assumption + debug!("JustOne: p = {}", p.display()); + assert!(pkg_src.start_dir.join(p).exists()); + if is_lib(p) { + PkgSrc::push_crate(&mut pkg_src.libs, 0, p); + } else if is_main(p) { + PkgSrc::push_crate(&mut pkg_src.mains, 0, p); + } else if is_test(p) { + PkgSrc::push_crate(&mut pkg_src.tests, 0, p); + } else if is_bench(p) { + PkgSrc::push_crate(&mut pkg_src.benchs, 0, p); + } else { + warn(format!("Not building any crates for dependency {}", p.display())); + return; + } + } + } + // Build it! + pkg_src.build(self, cfgs, []); + } + } + + fn clean(&self, workspace: &Path, id: &CrateId) { + // Could also support a custom build hook in the pkg + // script for cleaning files rustpkg doesn't know about. + // Do something reasonable for now + + let dir = build_pkg_id_in_workspace(id, workspace); + note(format!("Cleaning package {} (removing directory {})", + id.to_str(), dir.display())); + if dir.exists() { + fs::rmdir_recursive(&dir); + note(format!("Removed directory {}", dir.display())); + } + + note(format!("Cleaned package {}", id.to_str())); + } + + fn info(&self) { + // stub + fail!("info not yet implemented"); + } + + fn install(&self, mut pkg_src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]) { + + let id = pkg_src.id.clone(); + + let mut installed_files = ~[]; + let mut inputs = ~[]; + let mut build_inputs = ~[]; + + debug!("Installing package source: {}", pkg_src.to_str()); + + // workcache only knows about *crates*. Building a package + // just means inferring all the crates in it, then building each one. + self.build(&mut pkg_src, what); + + debug!("Done building package source {}", pkg_src.to_str()); + + let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(), + pkg_src.tests.clone(), pkg_src.benchs.clone()]; + debug!("In declare inputs for {}", id.to_str()); + for cs in to_do.iter() { + for c in cs.iter() { + let path = pkg_src.start_dir.join(&c.file); + debug!("Recording input: {}", path.display()); + // FIXME (#9639): This needs to handle non-utf8 paths + inputs.push((~"file", path.as_str().unwrap().to_owned())); + build_inputs.push(path); + } + } + + let result = self.install_no_build(pkg_src.build_workspace(), + build_inputs, + &pkg_src.destination_workspace, + &id).map(|s| Path::new(s.as_slice())); + installed_files = installed_files + result; + note(format!("Installed package {} to {}", + id.to_str(), + pkg_src.destination_workspace.display())); + (installed_files, inputs) + } + + // again, working around lack of Encodable for Path + fn install_no_build(&self, + build_workspace: &Path, + build_inputs: &[Path], + target_workspace: &Path, + id: &CrateId) -> ~[~str] { + + debug!("install_no_build: assuming {} comes from {} with target {}", + id.to_str(), build_workspace.display(), target_workspace.display()); + + // Now copy stuff into the install dirs + let maybe_executable = built_executable_in_workspace(id, build_workspace); + let maybe_library = built_library_in_workspace(id, build_workspace); + let target_exec = target_executable_in_workspace(id, target_workspace); + let target_lib = maybe_library.as_ref() + .map(|_| target_library_in_workspace(id, target_workspace)); + + debug!("target_exec = {} target_lib = {:?} \ + maybe_executable = {:?} maybe_library = {:?}", + target_exec.display(), target_lib, + maybe_executable, maybe_library); + + self.workcache_context.with_prep(id.install_tag(), |prep| { + for ee in maybe_executable.iter() { + // FIXME (#9639): This needs to handle non-utf8 paths + prep.declare_input("binary", + ee.as_str().unwrap(), + workcache_support::digest_only_date(ee)); + } + for ll in maybe_library.iter() { + // FIXME (#9639): This needs to handle non-utf8 paths + prep.declare_input("binary", + ll.as_str().unwrap(), + workcache_support::digest_only_date(ll)); + } + let subex = maybe_executable.clone(); + let sublib = maybe_library.clone(); + let sub_target_ex = target_exec.clone(); + let sub_target_lib = target_lib.clone(); + let sub_build_inputs = build_inputs.to_owned(); + prep.exec(proc(exe_thing) { + let mut outputs = ~[]; + // Declare all the *inputs* to the declared input too, as inputs + for executable in subex.iter() { + exe_thing.discover_input("binary", + executable.as_str().unwrap().to_owned(), + workcache_support::digest_only_date(executable)); + } + for library in sublib.iter() { + exe_thing.discover_input("binary", + library.as_str().unwrap().to_owned(), + workcache_support::digest_only_date(library)); + } + + for transitive_dependency in sub_build_inputs.iter() { + exe_thing.discover_input( + "file", + transitive_dependency.as_str().unwrap().to_owned(), + workcache_support::digest_file_with_date(transitive_dependency)); + } + + + for exec in subex.iter() { + debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display()); + fs::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX); + fs::copy(exec, &sub_target_ex); + // FIXME (#9639): This needs to handle non-utf8 paths + exe_thing.discover_output("binary", + sub_target_ex.as_str().unwrap(), + workcache_support::digest_only_date(&sub_target_ex)); + outputs.push(sub_target_ex.as_str().unwrap().to_owned()); + } + for lib in sublib.iter() { + let mut target_lib = sub_target_lib + .clone().expect(format!("I built {} but apparently \ + didn't install it!", lib.display())); + target_lib.set_filename(lib.filename().expect("weird target lib")); + fs::mkdir_recursive(&target_lib.dir_path(), io::UserRWX); + fs::copy(lib, &target_lib); + debug!("3. discovering output {}", target_lib.display()); + exe_thing.discover_output("binary", + target_lib.as_str().unwrap(), + workcache_support::digest_only_date(&target_lib)); + outputs.push(target_lib.as_str().unwrap().to_owned()); + } + outputs + }) + }) + } + + fn prefer(&self, _id: &str, _vers: Option<~str>) { + fail!("prefer not yet implemented"); + } + + fn test(&self, crateid: &CrateId, workspace: &Path) { + match built_test_in_workspace(crateid, workspace) { + Some(test_exec) => { + debug!("test: test_exec = {}", test_exec.display()); + // FIXME (#9639): This needs to handle non-utf8 paths + let opt_status = run::process_status(test_exec.as_str().unwrap(), [~"--test"]); + match opt_status { + Some(status) => { + if !status.success() { + fail!("Some tests failed"); + } + }, + None => fail!("Could not exec `{}`", test_exec.display()) + } + } + None => { + error(format!("Internal error: test executable for package ID {} in workspace {} \ + wasn't built! Please report this as a bug.", + crateid.to_str(), workspace.display())); + } + } + } + + fn init(&self) { + fs::mkdir_recursive(&Path::new("src"), io::UserRWX); + fs::mkdir_recursive(&Path::new("bin"), io::UserRWX); + fs::mkdir_recursive(&Path::new("lib"), io::UserRWX); + fs::mkdir_recursive(&Path::new("build"), io::UserRWX); + } + + fn uninstall(&self, _id: &str, _vers: Option<~str>) { + fail!("uninstall not yet implemented"); + } + + fn unprefer(&self, _id: &str, _vers: Option<~str>) { + fail!("unprefer not yet implemented"); + } +} + + diff --git a/src/librustpkg/workcache_support.rs b/src/librustpkg/workcache_support.rs index 824ba5341d4f6..d7a0e8ac8fe2d 100644 --- a/src/librustpkg/workcache_support.rs +++ b/src/librustpkg/workcache_support.rs @@ -11,7 +11,7 @@ use std::io; use std::io::File; use extra::workcache; -use sha2::{Digest, Sha256}; +use rustc::util::sha2::{Digest, Sha256}; /// Hashes the file contents along with the last-modified time pub fn digest_file_with_date(path: &Path) -> ~str { From de5325a350467cf860de137cd221c4f5f7cd60db Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Mon, 6 Jan 2014 21:50:44 +0100 Subject: [PATCH 3/8] Rustpkg: Remove trait CtxMethods (convert all method to functions) --- src/librustpkg/api.rs | 8 +- src/librustpkg/lib.rs | 23 +- src/librustpkg/run_cmd.rs | 935 +++++++++++++++++++------------------- src/librustpkg/tests.rs | 5 +- src/librustpkg/util.rs | 8 +- 5 files changed, 478 insertions(+), 501 deletions(-) diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs index 45c37a93e3e1e..5cb42a5208a20 100644 --- a/src/librustpkg/api.rs +++ b/src/librustpkg/api.rs @@ -13,6 +13,7 @@ use crate::*; use crate_id::*; use package_source::*; use path_util::{platform_library_name, target_build_dir}; +use run_cmd::{run_install}; use target::*; use version::Version; use workspace::pkg_parent_workspaces; @@ -133,10 +134,11 @@ pub fn install_pkg(cx: &BuildContext, // For now, these inputs are assumed to be inputs to each of the crates more_inputs: ~[(~str, Path)]) { // pairs of Kind and Path let crateid = CrateId{ version: version, ..CrateId::new(name)}; - cx.install(PkgSrc::new(workspace.clone(), workspace, false, crateid), - &WhatToBuild{ build_type: Inferred, + let pkg_src = PkgSrc::new(workspace.clone(), workspace, false, crateid); + let what = WhatToBuild{ build_type: Inferred, inputs_to_discover: more_inputs, - sources: Everything }); + sources: Everything }; + run_install(pkg_src, &what, cx); } /// Builds an arbitrary library whose short name is `output`, diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index e0a3ea0ae9a5b..6ecbb10217fe5 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -20,28 +20,16 @@ extern mod extra; extern mod rustc; extern mod syntax; -pub use std::path::Path; +use std::path::Path; +use std::{os, task}; use context::{Trans, Nothing, Pretty, Analysis, LLVMAssemble}; use context::{LLVMCompileBitcode, BuildCmd, CleanCmd, DoCmd, InfoCmd}; use context::{InstallCmd, ListCmd, PreferCmd, TestCmd, InitCmd, UninstallCmd}; use context::{UnpreferCmd}; -//use path_util::{build_pkg_id_in_workspace, built_test_in_workspace}; -//use path_util::{in_rust_path, built_executable_in_workspace}; -//use path_util::{built_library_in_workspace, default_workspace}; -//use path_util::{target_executable_in_workspace, target_library_in_workspace}; -//use path_util::{dir_has_crate_file}; -use run_cmd::{CtxMethods}; -//use source_control::{CheckedOutSources, is_git_dir, make_read_only}; -//use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench}; -//use target::{Tests, MaybeCustom, Inferred, JustOne}; -//use workcache_support::digest_only_date; -//use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces, cwd_to_workspace}; -//use workspace::{determine_destination}; - -use std::{os, task}; use context::{BuildContext}; use rustc::metadata::filesearch; +use run_cmd::{run_cmd}; use parse_args::{ParseResult, parse_args}; use path_util::{default_workspace}; use exit_codes::{COPY_FAILED_CODE}; @@ -107,12 +95,13 @@ pub fn main_args(args: &[~str]) -> int { // Wrap the rest in task::try in case of a condition failure in a task let result = do task::try { - BuildContext { + let build_context = BuildContext { context: context, sysroot: sysroot.clone(), // Currently, only tests override this workcache_context: api::default_context(sysroot.clone(), default_workspace()).workcache_context - }.run(command, args.clone()) + }; + run_cmd(command, args.clone(), &build_context); }; // FIXME #9262: This is using the same error code for all errors, // and at least one test case succeeds if rustpkg returns COPY_FAILED_CODE, diff --git a/src/librustpkg/run_cmd.rs b/src/librustpkg/run_cmd.rs index 88aa88f69b700..863a6249ef611 100644 --- a/src/librustpkg/run_cmd.rs +++ b/src/librustpkg/run_cmd.rs @@ -38,543 +38,528 @@ use workspace::determine_destination; use workcache_support::digest_only_date; use workcache_support; -pub trait CtxMethods { - fn run(&self, cmd: Command, args: ~[~str]); - fn do_cmd(&self, _cmd: &str, _pkgname: &str); - /// Returns a pair of the selected package ID, and the destination workspace - fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)>; - /// Returns the destination workspace - fn build(&self, pkg_src: &mut PkgSrc, what: &WhatToBuild); - fn clean(&self, workspace: &Path, id: &CrateId); - fn info(&self); - /// Returns a pair. First component is a list of installed paths, - /// second is a list of declared and discovered inputs - fn install(&self, src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]); - /// Returns a list of installed files - fn install_no_build(&self, - build_workspace: &Path, - build_inputs: &[Path], - target_workspace: &Path, - id: &CrateId) -> ~[~str]; - fn prefer(&self, _id: &str, _vers: Option<~str>); - fn test(&self, id: &CrateId, workspace: &Path); - fn uninstall(&self, _id: &str, _vers: Option<~str>); - fn unprefer(&self, _id: &str, _vers: Option<~str>); - fn init(&self); -} +/// Perform actions based on parsed command line input +pub fn run_cmd(cmd: Command, + args: ~[~str], + build_context: &BuildContext ) { + let cwd = os::getcwd(); + match cmd { + BuildCmd => { + let what = WhatToBuild::new(MaybeCustom, Everything); + run_build(args, &what, build_context); + } + CleanCmd => { + if args.len() < 1 { + match cwd_to_workspace() { + None => { usage::clean(); return } + // tjc: Maybe clean should clean all the packages in the + // current workspace, though? + Some((ws, crateid)) => run_clean(&ws, &crateid) + } -impl CtxMethods for BuildContext { - fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)> { - let cwd = os::getcwd(); - - if args.len() < 1 { - match cwd_to_workspace() { - None if dir_has_crate_file(&cwd) => { - // FIXME (#9639): This needs to handle non-utf8 paths - let crateid = CrateId::new(cwd.filename_str().unwrap()); - let mut pkg_src = PkgSrc::new(cwd, default_workspace(), true, crateid); - self.build(&mut pkg_src, what); - match pkg_src { - PkgSrc { destination_workspace: ws, - id: id, .. } => { - Some((id, ws)) - } + } + else { + // The package id is presumed to be the first command-line + // argument + let crateid = CrateId::new(args[0].clone()); + run_clean(&cwd, &crateid); // tjc: should use workspace, not cwd + } + } + DoCmd => { + if args.len() < 2 { + return usage::do_cmd(); + } + run_do(args[0].clone(), args[1].clone()); + } + InfoCmd => { + run_info(); + } + InstallCmd => { + if args.len() < 1 { + match cwd_to_workspace() { + None if dir_has_crate_file(&cwd) => { + // FIXME (#9639): This needs to handle non-utf8 paths + + let inferred_crateid = + CrateId::new(cwd.filename_str().unwrap()); + let pkg_src = PkgSrc::new(cwd, default_workspace(), + true, inferred_crateid); + let what = WhatToBuild::new(MaybeCustom, Everything); + run_install(pkg_src, &what, build_context); } + None => { usage::install(); return; } + Some((ws, crateid)) => { + let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, crateid); + let what = WhatToBuild::new(MaybeCustom, Everything); + run_install(pkg_src, &what, build_context); + } + } + } + else { + // The package id is presumed to be the first command-line + // argument + let crateid = CrateId::new(args[0]); + let workspaces = pkg_parent_workspaces(&build_context.context, &crateid); + debug!("package ID = {}, found it in {:?} workspaces", + crateid.to_str(), workspaces.len()); + if workspaces.is_empty() { + let d = default_workspace(); + let pkg_src = PkgSrc::new(d.clone(), d, false, crateid.clone()); + let what = WhatToBuild::new(MaybeCustom, Everything); + run_install(pkg_src, &what, build_context); } - None => { usage::build(); None } - Some((ws, crateid)) => { - let mut pkg_src = PkgSrc::new(ws.clone(), ws, false, crateid); - self.build(&mut pkg_src, what); - match pkg_src { - PkgSrc { destination_workspace: ws, - id: id, .. } => { - Some((id, ws)) - } - } + else { + for workspace in workspaces.iter() { + let dest = determine_destination(os::getcwd(), + build_context.context.use_rust_path_hack, + workspace); + let pkg_src = PkgSrc::new(workspace.clone(), + dest, + build_context.context.use_rust_path_hack, + crateid.clone()); + let what = WhatToBuild::new(MaybeCustom, Everything); + run_install(pkg_src, &what, build_context); + }; } } - } else { - // The package id is presumed to be the first command-line - // argument - let crateid = CrateId::new(args[0].clone()); - let mut dest_ws = default_workspace(); - each_pkg_parent_workspace(&self.context, &crateid, |workspace| { - debug!("found pkg {} in workspace {}, trying to build", - crateid.to_str(), workspace.display()); - dest_ws = determine_destination(os::getcwd(), - self.context.use_rust_path_hack, - workspace); - let mut pkg_src = PkgSrc::new(workspace.clone(), dest_ws.clone(), - false, crateid.clone()); - self.build(&mut pkg_src, what); + } + ListCmd => { + println("Installed packages:"); + installed_packages::list_installed_packages(|pkg_id| { + pkg_id.path.display().with_str(|s| println(s)); true }); - // n.b. If this builds multiple packages, it only returns the workspace for - // the last one. The whole building-multiple-packages-with-the-same-ID is weird - // anyway and there are no tests for it, so maybe take it out - Some((crateid, dest_ws)) } - } - fn run(&self, cmd: Command, args: ~[~str]) { - let cwd = os::getcwd(); - match cmd { - BuildCmd => { - self.build_args(args, &WhatToBuild::new(MaybeCustom, Everything)); + PreferCmd => { + if args.len() < 1 { + return usage::uninstall(); } - CleanCmd => { - if args.len() < 1 { - match cwd_to_workspace() { - None => { usage::clean(); return } - // tjc: Maybe clean should clean all the packages in the - // current workspace, though? - Some((ws, crateid)) => self.clean(&ws, &crateid) - } - + run_prefer(args[0], None); + } + TestCmd => { + // Build the test executable + let what = WhatToBuild::new(MaybeCustom, Tests); + let maybe_id_and_workspace = run_build(args, &what, build_context); + match maybe_id_and_workspace { + Some((pkg_id, workspace)) => { + // Assuming it's built, run the tests + run_test(&pkg_id, &workspace); } - else { - // The package id is presumed to be the first command-line - // argument - let crateid = CrateId::new(args[0].clone()); - self.clean(&cwd, &crateid); // tjc: should use workspace, not cwd + None => { + error("Testing failed because building the specified package failed."); } } - DoCmd => { - if args.len() < 2 { - return usage::do_cmd(); - } - - self.do_cmd(args[0].clone(), args[1].clone()); + } + InitCmd => { + if args.len() != 0 { + return usage::init(); + } else { + run_init(); } - InfoCmd => { - self.info(); + } + UninstallCmd => { + if args.len() < 1 { + return usage::uninstall(); } - InstallCmd => { - if args.len() < 1 { - match cwd_to_workspace() { - None if dir_has_crate_file(&cwd) => { - // FIXME (#9639): This needs to handle non-utf8 paths - - let inferred_crateid = - CrateId::new(cwd.filename_str().unwrap()); - self.install(PkgSrc::new(cwd, default_workspace(), - true, inferred_crateid), - &WhatToBuild::new(MaybeCustom, Everything)); - } - None => { usage::install(); return; } - Some((ws, crateid)) => { - let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, crateid); - self.install(pkg_src, &WhatToBuild::new(MaybeCustom, - Everything)); - } - } - } - else { - // The package id is presumed to be the first command-line - // argument - let crateid = CrateId::new(args[0]); - let workspaces = pkg_parent_workspaces(&self.context, &crateid); - debug!("package ID = {}, found it in {:?} workspaces", - crateid.to_str(), workspaces.len()); - if workspaces.is_empty() { - let d = default_workspace(); - let src = PkgSrc::new(d.clone(), d, false, crateid.clone()); - self.install(src, &WhatToBuild::new(MaybeCustom, Everything)); - } - else { - for workspace in workspaces.iter() { - let dest = determine_destination(os::getcwd(), - self.context.use_rust_path_hack, - workspace); - let src = PkgSrc::new(workspace.clone(), - dest, - self.context.use_rust_path_hack, - crateid.clone()); - self.install(src, &WhatToBuild::new(MaybeCustom, Everything)); - }; - } - } + + let crateid = CrateId::new(args[0]); + if !installed_packages::package_is_installed(&crateid) { + warn(format!("Package {} doesn't seem to be installed! \ + Doing nothing.", args[0])); + return; } - ListCmd => { - println("Installed packages:"); - installed_packages::list_installed_packages(|pkg_id| { - pkg_id.path.display().with_str(|s| println(s)); + else { + let rp = rust_path(); + assert!(!rp.is_empty()); + each_pkg_parent_workspace(&build_context.context, &crateid, |workspace| { + path_util::uninstall_package_from(workspace, &crateid); + note(format!("Uninstalled package {} (was installed in {})", + crateid.to_str(), workspace.display())); true }); } - PreferCmd => { - if args.len() < 1 { - return usage::uninstall(); - } - - self.prefer(args[0], None); - } - TestCmd => { - // Build the test executable - let maybe_id_and_workspace = self.build_args(args, - &WhatToBuild::new(MaybeCustom, Tests)); - match maybe_id_and_workspace { - Some((pkg_id, workspace)) => { - // Assuming it's built, run the tests - self.test(&pkg_id, &workspace); - } - None => { - error("Testing failed because building the specified package failed."); - } - } - } - InitCmd => { - if args.len() != 0 { - return usage::init(); - } else { - self.init(); - } + } + UnpreferCmd => { + if args.len() < 1 { + return usage::unprefer(); } - UninstallCmd => { - if args.len() < 1 { - return usage::uninstall(); - } - let crateid = CrateId::new(args[0]); - if !installed_packages::package_is_installed(&crateid) { - warn(format!("Package {} doesn't seem to be installed! \ - Doing nothing.", args[0])); - return; - } - else { - let rp = rust_path(); - assert!(!rp.is_empty()); - each_pkg_parent_workspace(&self.context, &crateid, |workspace| { - path_util::uninstall_package_from(workspace, &crateid); - note(format!("Uninstalled package {} (was installed in {})", - crateid.to_str(), workspace.display())); - true - }); + run_unprefer(args[0], None); + } + } +} + +fn run_build(args: ~[~str], + what: &WhatToBuild, + build_context: &BuildContext) -> Option<(CrateId, Path)> { + let cwd = os::getcwd(); + + if args.len() < 1 { + match cwd_to_workspace() { + None if dir_has_crate_file(&cwd) => { + // FIXME (#9639): This needs to handle non-utf8 paths + let crateid = CrateId::new(cwd.filename_str().unwrap()); + let mut pkg_src = PkgSrc::new(cwd, default_workspace(), true, crateid); + build(&mut pkg_src, what, build_context); + match pkg_src { + PkgSrc { destination_workspace: ws, + id: id, .. } => { + Some((id, ws)) + } } } - UnpreferCmd => { - if args.len() < 1 { - return usage::unprefer(); + None => { usage::build(); None } + Some((ws, crateid)) => { + let mut pkg_src = PkgSrc::new(ws.clone(), ws, false, crateid); + build(&mut pkg_src, what, build_context); + match pkg_src { + PkgSrc { destination_workspace: ws, + id: id, .. } => { + Some((id, ws)) + } } - - self.unprefer(args[0], None); } } + } else { + // The package id is presumed to be the first command-line + // argument + let crateid = CrateId::new(args[0].clone()); + let mut dest_ws = default_workspace(); + each_pkg_parent_workspace(&build_context.context, &crateid, |workspace| { + debug!("found pkg {} in workspace {}, trying to build", + crateid.to_str(), workspace.display()); + dest_ws = determine_destination(os::getcwd(), + build_context.context.use_rust_path_hack, + workspace); + let mut pkg_src = PkgSrc::new(workspace.clone(), dest_ws.clone(), + false, crateid.clone()); + build(&mut pkg_src, what, build_context); + true + }); + // n.b. If this builds multiple packages, it only returns the workspace for + // the last one. The whole building-multiple-packages-with-the-same-ID is weird + // anyway and there are no tests for it, so maybe take it out + Some((crateid, dest_ws)) } +} - fn do_cmd(&self, _cmd: &str, _pkgname: &str) { - // stub - fail!("`do` not yet implemented"); - } - fn build(&self, pkg_src: &mut PkgSrc, what_to_build: &WhatToBuild) { - use conditions::git_checkout_failed::cond; - - let workspace = pkg_src.source_workspace.clone(); - let crateid = pkg_src.id.clone(); - - debug!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \ - crateid = {} pkgsrc start_dir = {}", workspace.display(), - in_rust_path(&workspace), is_git_dir(&workspace.join(&crateid.path)), - crateid.to_str(), pkg_src.start_dir.display()); - debug!("build: what to build = {:?}", what_to_build); - - // If workspace isn't in the RUST_PATH, and it's a git repo, - // then clone it into the first entry in RUST_PATH, and repeat - if !in_rust_path(&workspace) && is_git_dir(&workspace.join(&crateid.path)) { - let mut out_dir = default_workspace().join("src"); - out_dir.push(&crateid.path); - let git_result = source_control::safe_git_clone(&workspace.join(&crateid.path), - &crateid.version, - &out_dir); - match git_result { - CheckedOutSources => make_read_only(&out_dir), - // FIXME (#9639): This needs to handle non-utf8 paths - _ => cond.raise((crateid.path.as_str().unwrap().to_owned(), out_dir.clone())) - }; - let default_ws = default_workspace(); - debug!("Calling build recursively with {:?} and {:?}", default_ws.display(), - crateid.to_str()); - return self.build(&mut PkgSrc::new(default_ws.clone(), - default_ws, - false, - crateid.clone()), what_to_build); - } +fn run_do(_cmd: &str, _pkgname: &str) { + // stub + fail!("`do` not yet implemented"); +} - // Is there custom build logic? If so, use it - let mut custom = false; - debug!("Package source directory = {}", pkg_src.to_str()); - let opt = pkg_src.package_script_option(); - debug!("Calling pkg_script_option on {:?}", opt); - let cfgs = match (pkg_src.package_script_option(), what_to_build.build_type) { - (Some(package_script_path), MaybeCustom) => { - let sysroot = self.sysroot_to_use(); - // Build the package script if needed - let script_build = format!("build_package_script({})", - package_script_path.display()); - let pkg_exe = self.workcache_context.with_prep(script_build, |prep| { - let subsysroot = sysroot.clone(); - let psp = package_script_path.clone(); - let ws = workspace.clone(); - let pid = crateid.clone(); - prep.exec(proc(exec) { - let mut pscript = PkgScript::parse(subsysroot.clone(), - psp.clone(), - &ws, - &pid); - pscript.build_custom(exec) - }) - }); - // We always *run* the package script - match PkgScript::run_custom(&Path::new(pkg_exe), &sysroot) { - Some((cfgs, hook_result)) => { - debug!("Command return code = {:?}", hook_result); - if !hook_result.success() { - fail!("Error running custom build command") - } - custom = true; - // otherwise, the package script succeeded - cfgs - }, - None => { - fail!("Error starting custom build command") + +fn build(pkg_src: &mut PkgSrc, + what_to_build: &WhatToBuild, + build_context: &BuildContext) { + use conditions::git_checkout_failed::cond; + + let workspace = pkg_src.source_workspace.clone(); + let crateid = pkg_src.id.clone(); + + debug!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \ + crateid = {} pkgsrc start_dir = {}", workspace.display(), + in_rust_path(&workspace), is_git_dir(&workspace.join(&crateid.path)), + crateid.to_str(), pkg_src.start_dir.display()); + debug!("build: what to build = {:?}", what_to_build); + + // If workspace isn't in the RUST_PATH, and it's a git repo, + // then clone it into the first entry in RUST_PATH, and repeat + if !in_rust_path(&workspace) && is_git_dir(&workspace.join(&crateid.path)) { + let mut out_dir = default_workspace().join("src"); + out_dir.push(&crateid.path); + let git_result = source_control::safe_git_clone(&workspace.join(&crateid.path), + &crateid.version, + &out_dir); + match git_result { + CheckedOutSources => make_read_only(&out_dir), + // FIXME (#9639): This needs to handle non-utf8 paths + _ => cond.raise((crateid.path.as_str().unwrap().to_owned(), out_dir.clone())) + }; + let default_ws = default_workspace(); + debug!("Calling build recursively with {:?} and {:?}", default_ws.display(), + crateid.to_str()); + let pkg_src = &mut PkgSrc::new(default_ws.clone(), + default_ws, + false, + crateid.clone()); + return build(pkg_src, what_to_build, build_context); + } + + // Is there custom build logic? If so, use it + let mut custom = false; + debug!("Package source directory = {}", pkg_src.to_str()); + let opt = pkg_src.package_script_option(); + debug!("Calling pkg_script_option on {:?}", opt); + let cfgs = match (pkg_src.package_script_option(), what_to_build.build_type) { + (Some(package_script_path), MaybeCustom) => { + let sysroot = build_context.sysroot_to_use(); + // Build the package script if needed + let script_build = format!("build_package_script({})", + package_script_path.display()); + let pkg_exe = build_context.workcache_context.with_prep(script_build, |prep| { + let subsysroot = sysroot.clone(); + let psp = package_script_path.clone(); + let ws = workspace.clone(); + let pid = crateid.clone(); + prep.exec(proc(exec) { + let mut pscript = PkgScript::parse(subsysroot.clone(), + psp.clone(), + &ws, + &pid); + pscript.build_custom(exec) + }) + }); + // We always *run* the package script + match PkgScript::run_custom(&Path::new(pkg_exe), &sysroot) { + Some((cfgs, hook_result)) => { + debug!("Command return code = {:?}", hook_result); + if !hook_result.success() { + fail!("Error running custom build command") } + custom = true; + // otherwise, the package script succeeded + cfgs + }, + None => { + fail!("Error starting custom build command") } } - (Some(_), Inferred) => { - debug!("There is a package script, but we're ignoring it"); - ~[] - } - (None, _) => { - debug!("No package script, continuing"); - ~[] - } - } + self.context.cfgs; - - // If there was a package script, it should have finished - // the build already. Otherwise... - if !custom { - match what_to_build.sources { - // Find crates inside the workspace - Everything => pkg_src.find_crates(), - // Find only tests - Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }), - // Don't infer any crates -- just build the one that was requested - JustOne(ref p) => { - // We expect that p is relative to the package source's start directory, - // so check that assumption - debug!("JustOne: p = {}", p.display()); - assert!(pkg_src.start_dir.join(p).exists()); - if is_lib(p) { - PkgSrc::push_crate(&mut pkg_src.libs, 0, p); - } else if is_main(p) { - PkgSrc::push_crate(&mut pkg_src.mains, 0, p); - } else if is_test(p) { - PkgSrc::push_crate(&mut pkg_src.tests, 0, p); - } else if is_bench(p) { - PkgSrc::push_crate(&mut pkg_src.benchs, 0, p); - } else { - warn(format!("Not building any crates for dependency {}", p.display())); - return; - } + } + (Some(_), Inferred) => { + debug!("There is a package script, but we're ignoring it"); + ~[] + } + (None, _) => { + debug!("No package script, continuing"); + ~[] + } + } + build_context.context.cfgs; + + // If there was a package script, it should have finished + // the build already. Otherwise... + if !custom { + match what_to_build.sources { + // Find crates inside the workspace + Everything => pkg_src.find_crates(), + // Find only tests + Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }), + // Don't infer any crates -- just build the one that was requested + JustOne(ref p) => { + // We expect that p is relative to the package source's start directory, + // so check that assumption + debug!("JustOne: p = {}", p.display()); + assert!(pkg_src.start_dir.join(p).exists()); + if is_lib(p) { + PkgSrc::push_crate(&mut pkg_src.libs, 0, p); + } else if is_main(p) { + PkgSrc::push_crate(&mut pkg_src.mains, 0, p); + } else if is_test(p) { + PkgSrc::push_crate(&mut pkg_src.tests, 0, p); + } else if is_bench(p) { + PkgSrc::push_crate(&mut pkg_src.benchs, 0, p); + } else { + warn(format!("Not building any crates for dependency {}", p.display())); + return; } } - // Build it! - pkg_src.build(self, cfgs, []); } + // Build it! + pkg_src.build(build_context, cfgs, []); } +} - fn clean(&self, workspace: &Path, id: &CrateId) { - // Could also support a custom build hook in the pkg - // script for cleaning files rustpkg doesn't know about. - // Do something reasonable for now - - let dir = build_pkg_id_in_workspace(id, workspace); - note(format!("Cleaning package {} (removing directory {})", - id.to_str(), dir.display())); - if dir.exists() { - fs::rmdir_recursive(&dir); - note(format!("Removed directory {}", dir.display())); - } - - note(format!("Cleaned package {}", id.to_str())); +fn run_clean(workspace: &Path, id: &CrateId) { + // Could also support a custom build hook in the pkg + // script for cleaning files rustpkg doesn't know about. + // Do something reasonable for now + + let dir = build_pkg_id_in_workspace(id, workspace); + note(format!("Cleaning package {} (removing directory {})", + id.to_str(), dir.display())); + if dir.exists() { + fs::rmdir_recursive(&dir); + note(format!("Removed directory {}", dir.display())); } - fn info(&self) { - // stub - fail!("info not yet implemented"); - } + note(format!("Cleaned package {}", id.to_str())); +} - fn install(&self, mut pkg_src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]) { +fn run_info() { + // stub + fail!("info not yet implemented"); +} - let id = pkg_src.id.clone(); +pub fn run_install(mut pkg_src: PkgSrc, + what: &WhatToBuild, + build_context: &BuildContext) -> (~[Path], ~[(~str, ~str)]) { - let mut installed_files = ~[]; - let mut inputs = ~[]; - let mut build_inputs = ~[]; + let id = pkg_src.id.clone(); - debug!("Installing package source: {}", pkg_src.to_str()); + let mut installed_files = ~[]; + let mut inputs = ~[]; + let mut build_inputs = ~[]; - // workcache only knows about *crates*. Building a package - // just means inferring all the crates in it, then building each one. - self.build(&mut pkg_src, what); + debug!("Installing package source: {}", pkg_src.to_str()); - debug!("Done building package source {}", pkg_src.to_str()); + // workcache only knows about *crates*. Building a package + // just means inferring all the crates in it, then building each one. + build(&mut pkg_src, what, build_context); - let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(), - pkg_src.tests.clone(), pkg_src.benchs.clone()]; - debug!("In declare inputs for {}", id.to_str()); - for cs in to_do.iter() { - for c in cs.iter() { - let path = pkg_src.start_dir.join(&c.file); - debug!("Recording input: {}", path.display()); - // FIXME (#9639): This needs to handle non-utf8 paths - inputs.push((~"file", path.as_str().unwrap().to_owned())); - build_inputs.push(path); - } - } + debug!("Done building package source {}", pkg_src.to_str()); - let result = self.install_no_build(pkg_src.build_workspace(), - build_inputs, - &pkg_src.destination_workspace, - &id).map(|s| Path::new(s.as_slice())); - installed_files = installed_files + result; - note(format!("Installed package {} to {}", - id.to_str(), - pkg_src.destination_workspace.display())); - (installed_files, inputs) + let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(), + pkg_src.tests.clone(), pkg_src.benchs.clone()]; + debug!("In declare inputs for {}", id.to_str()); + for cs in to_do.iter() { + for c in cs.iter() { + let path = pkg_src.start_dir.join(&c.file); + debug!("Recording input: {}", path.display()); + // FIXME (#9639): This needs to handle non-utf8 paths + inputs.push((~"file", path.as_str().unwrap().to_owned())); + build_inputs.push(path); + } } - // again, working around lack of Encodable for Path - fn install_no_build(&self, - build_workspace: &Path, - build_inputs: &[Path], - target_workspace: &Path, - id: &CrateId) -> ~[~str] { - - debug!("install_no_build: assuming {} comes from {} with target {}", - id.to_str(), build_workspace.display(), target_workspace.display()); - - // Now copy stuff into the install dirs - let maybe_executable = built_executable_in_workspace(id, build_workspace); - let maybe_library = built_library_in_workspace(id, build_workspace); - let target_exec = target_executable_in_workspace(id, target_workspace); - let target_lib = maybe_library.as_ref() - .map(|_| target_library_in_workspace(id, target_workspace)); - - debug!("target_exec = {} target_lib = {:?} \ - maybe_executable = {:?} maybe_library = {:?}", - target_exec.display(), target_lib, - maybe_executable, maybe_library); - - self.workcache_context.with_prep(id.install_tag(), |prep| { - for ee in maybe_executable.iter() { - // FIXME (#9639): This needs to handle non-utf8 paths - prep.declare_input("binary", - ee.as_str().unwrap(), - workcache_support::digest_only_date(ee)); + let result = + install_no_build(pkg_src.build_workspace(), + build_inputs, + &pkg_src.destination_workspace, + &id, + build_context).map(|s| Path::new(s.as_slice())); +installed_files = installed_files + result; + note(format!("Installed package {} to {}", + id.to_str(), + pkg_src.destination_workspace.display())); + (installed_files, inputs) +} + +fn install_no_build(build_workspace: &Path, + build_inputs: &[Path], + target_workspace: &Path, + id: &CrateId, + build_context: &BuildContext) -> ~[~str] { + + debug!("install_no_build: assuming {} comes from {} with target {}", + id.to_str(), build_workspace.display(), target_workspace.display()); + + // Now copy stuff into the install dirs + let maybe_executable = built_executable_in_workspace(id, build_workspace); + let maybe_library = built_library_in_workspace(id, build_workspace); + let target_exec = target_executable_in_workspace(id, target_workspace); + let target_lib = maybe_library.as_ref() + .map(|_| target_library_in_workspace(id, target_workspace)); + + debug!("target_exec = {} target_lib = {:?} \ + maybe_executable = {:?} maybe_library = {:?}", + target_exec.display(), target_lib, + maybe_executable, maybe_library); + + build_context.workcache_context.with_prep(id.install_tag(), |prep| { + for ee in maybe_executable.iter() { + // FIXME (#9639): This needs to handle non-utf8 paths + prep.declare_input("binary", + ee.as_str().unwrap(), + workcache_support::digest_only_date(ee)); + } + for ll in maybe_library.iter() { + // FIXME (#9639): This needs to handle non-utf8 paths + prep.declare_input("binary", + ll.as_str().unwrap(), + workcache_support::digest_only_date(ll)); + } + let subex = maybe_executable.clone(); + let sublib = maybe_library.clone(); + let sub_target_ex = target_exec.clone(); + let sub_target_lib = target_lib.clone(); + let sub_build_inputs = build_inputs.to_owned(); + prep.exec(proc(exe_thing) { + let mut outputs = ~[]; + // Declare all the *inputs* to the declared input too, as inputs + for executable in subex.iter() { + exe_thing.discover_input("binary", + executable.as_str().unwrap().to_owned(), + workcache_support::digest_only_date(executable)); } - for ll in maybe_library.iter() { - // FIXME (#9639): This needs to handle non-utf8 paths - prep.declare_input("binary", - ll.as_str().unwrap(), - workcache_support::digest_only_date(ll)); + for library in sublib.iter() { + exe_thing.discover_input("binary", + library.as_str().unwrap().to_owned(), + workcache_support::digest_only_date(library)); } - let subex = maybe_executable.clone(); - let sublib = maybe_library.clone(); - let sub_target_ex = target_exec.clone(); - let sub_target_lib = target_lib.clone(); - let sub_build_inputs = build_inputs.to_owned(); - prep.exec(proc(exe_thing) { - let mut outputs = ~[]; - // Declare all the *inputs* to the declared input too, as inputs - for executable in subex.iter() { - exe_thing.discover_input("binary", - executable.as_str().unwrap().to_owned(), - workcache_support::digest_only_date(executable)); - } - for library in sublib.iter() { - exe_thing.discover_input("binary", - library.as_str().unwrap().to_owned(), - workcache_support::digest_only_date(library)); - } - for transitive_dependency in sub_build_inputs.iter() { - exe_thing.discover_input( - "file", - transitive_dependency.as_str().unwrap().to_owned(), - workcache_support::digest_file_with_date(transitive_dependency)); - } + for transitive_dependency in sub_build_inputs.iter() { + exe_thing.discover_input( + "file", + transitive_dependency.as_str().unwrap().to_owned(), + workcache_support::digest_file_with_date(transitive_dependency)); + } - for exec in subex.iter() { - debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display()); - fs::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX); - fs::copy(exec, &sub_target_ex); - // FIXME (#9639): This needs to handle non-utf8 paths - exe_thing.discover_output("binary", - sub_target_ex.as_str().unwrap(), - workcache_support::digest_only_date(&sub_target_ex)); - outputs.push(sub_target_ex.as_str().unwrap().to_owned()); - } - for lib in sublib.iter() { - let mut target_lib = sub_target_lib - .clone().expect(format!("I built {} but apparently \ - didn't install it!", lib.display())); - target_lib.set_filename(lib.filename().expect("weird target lib")); - fs::mkdir_recursive(&target_lib.dir_path(), io::UserRWX); - fs::copy(lib, &target_lib); - debug!("3. discovering output {}", target_lib.display()); - exe_thing.discover_output("binary", - target_lib.as_str().unwrap(), - workcache_support::digest_only_date(&target_lib)); - outputs.push(target_lib.as_str().unwrap().to_owned()); - } - outputs - }) + for exec in subex.iter() { + debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display()); + fs::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX); + fs::copy(exec, &sub_target_ex); + // FIXME (#9639): This needs to handle non-utf8 paths + exe_thing.discover_output("binary", + sub_target_ex.as_str().unwrap(), + workcache_support::digest_only_date(&sub_target_ex)); + outputs.push(sub_target_ex.as_str().unwrap().to_owned()); + } + for lib in sublib.iter() { + let mut target_lib = sub_target_lib + .clone().expect(format!("I built {} but apparently \ + didn't install it!", lib.display())); + target_lib.set_filename(lib.filename().expect("weird target lib")); + fs::mkdir_recursive(&target_lib.dir_path(), io::UserRWX); + fs::copy(lib, &target_lib); + debug!("3. discovering output {}", target_lib.display()); + exe_thing.discover_output("binary", + target_lib.as_str().unwrap(), + workcache_support::digest_only_date(&target_lib)); + outputs.push(target_lib.as_str().unwrap().to_owned()); + } + outputs }) - } + }) +} - fn prefer(&self, _id: &str, _vers: Option<~str>) { - fail!("prefer not yet implemented"); - } +fn run_prefer(_id: &str, _vers: Option<~str>) { + fail!("prefer not yet implemented"); +} - fn test(&self, crateid: &CrateId, workspace: &Path) { - match built_test_in_workspace(crateid, workspace) { - Some(test_exec) => { - debug!("test: test_exec = {}", test_exec.display()); - // FIXME (#9639): This needs to handle non-utf8 paths - let opt_status = run::process_status(test_exec.as_str().unwrap(), [~"--test"]); - match opt_status { - Some(status) => { - if !status.success() { - fail!("Some tests failed"); - } - }, - None => fail!("Could not exec `{}`", test_exec.display()) - } - } - None => { - error(format!("Internal error: test executable for package ID {} in workspace {} \ - wasn't built! Please report this as a bug.", - crateid.to_str(), workspace.display())); +fn run_test(crateid: &CrateId, workspace: &Path) { + match built_test_in_workspace(crateid, workspace) { + Some(test_exec) => { + debug!("test: test_exec = {}", test_exec.display()); + // FIXME (#9639): This needs to handle non-utf8 paths + let opt_status = run::process_status(test_exec.as_str().unwrap(), [~"--test"]); + match opt_status { + Some(status) => { + if !status.success() { + fail!("Some tests failed"); + } + }, + None => fail!("Could not exec `{}`", test_exec.display()) } } + None => { + error(format!("Internal error: test executable for package ID {} in workspace {} \ + wasn't built! Please report this as a bug.", + crateid.to_str(), workspace.display())); + } } +} - fn init(&self) { - fs::mkdir_recursive(&Path::new("src"), io::UserRWX); - fs::mkdir_recursive(&Path::new("bin"), io::UserRWX); - fs::mkdir_recursive(&Path::new("lib"), io::UserRWX); - fs::mkdir_recursive(&Path::new("build"), io::UserRWX); - } - - fn uninstall(&self, _id: &str, _vers: Option<~str>) { - fail!("uninstall not yet implemented"); - } +fn run_init() { + fs::mkdir_recursive(&Path::new("src"), io::UserRWX); + fs::mkdir_recursive(&Path::new("bin"), io::UserRWX); + fs::mkdir_recursive(&Path::new("lib"), io::UserRWX); + fs::mkdir_recursive(&Path::new("build"), io::UserRWX); +} - fn unprefer(&self, _id: &str, _vers: Option<~str>) { - fail!("unprefer not yet implemented"); - } +fn run_unprefer(_id: &str, _vers: Option<~str>) { + fail!("unprefer not yet implemented"); } diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index a9f3a87dfdc07..82ebd236a9180 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -22,6 +22,7 @@ use extra::workcache; use extra::workcache::{Database, Logger}; use extra::treemap::TreeMap; use extra::getopts::groups::getopts; +use run_cmd::{run_install}; use std::run::ProcessOutput; use installed_packages::list_installed_packages; use crate_id::{CrateId}; @@ -591,7 +592,7 @@ fn test_install_valid() { temp_workspace.clone(), false, temp_pkg_id.clone()); - ctxt.install(src, &WhatToBuild::new(MaybeCustom, Everything)); + run_install(src, &WhatToBuild::new(MaybeCustom, Everything), &ctxt); // Check that all files exist let exec = target_executable_in_workspace(&temp_pkg_id, temp_workspace); debug!("exec = {}", exec.display()); @@ -630,7 +631,7 @@ fn test_install_invalid() { temp_workspace.clone(), false, crateid.clone()); - ctxt.install(pkg_src, &WhatToBuild::new(MaybeCustom, Everything)); + run_install(pkg_src, &WhatToBuild::new(MaybeCustom, Everything),&ctxt); }; assert!(result.unwrap_err() .to_str().contains("supplied path for package dir does not exist")); diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 4c533860c5702..a3fe5ed184fe2 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -34,6 +34,7 @@ use package_source::PkgSrc; use workspace::pkg_parent_workspaces; use path_util::{system_library, target_build_dir}; use path_util::{default_workspace, built_library_in_workspace}; +use run_cmd::{run_install}; pub use target::{OutputType, Main, Lib, Bench, Test, JustOne, lib_name_of, lib_crate_filename}; pub use target::{Target, Build, Install}; use extra::treemap::TreeMap; @@ -524,11 +525,10 @@ impl<'a> Visitor<()> for ViewItemVisitor<'a> { self.context.context.use_rust_path_hack, pkg_id.clone()) }); + let what = WhatToBuild::new(Inferred, + JustOne(Path::new(lib_crate_filename))); let (outputs_disc, inputs_disc) = - self.context.install( - pkg_src, - &WhatToBuild::new(Inferred, - JustOne(Path::new(lib_crate_filename)))); + run_install(pkg_src, &what, self.context); debug!("Installed {}, returned {:?} dependencies and \ {:?} transitive dependencies", lib_name, outputs_disc.len(), inputs_disc.len()); From f883fc57903233f71ca7499b7f5dcff72d5df63a Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Tue, 7 Jan 2014 07:53:51 +0100 Subject: [PATCH 4/8] rustpkg: Move public methods build(..) and install(..) to perform.rs --- src/librustpkg/api.rs | 4 +- src/librustpkg/lib.rs | 1 + src/librustpkg/perform.rs | 290 ++++++++++++++++++++++++++++++++++++++ src/librustpkg/run_cmd.rs | 279 ++---------------------------------- src/librustpkg/tests.rs | 6 +- src/librustpkg/util.rs | 4 +- 6 files changed, 307 insertions(+), 277 deletions(-) create mode 100644 src/librustpkg/perform.rs diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs index 5cb42a5208a20..fbd499108f036 100644 --- a/src/librustpkg/api.rs +++ b/src/librustpkg/api.rs @@ -13,7 +13,7 @@ use crate::*; use crate_id::*; use package_source::*; use path_util::{platform_library_name, target_build_dir}; -use run_cmd::{run_install}; +use perform::{install}; use target::*; use version::Version; use workspace::pkg_parent_workspaces; @@ -138,7 +138,7 @@ pub fn install_pkg(cx: &BuildContext, let what = WhatToBuild{ build_type: Inferred, inputs_to_discover: more_inputs, sources: Everything }; - run_install(pkg_src, &what, cx); + install(pkg_src, &what, cx); } /// Builds an arbitrary library whose short name is `output`, diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index 6ecbb10217fe5..eba3aaa759b42 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -46,6 +46,7 @@ mod package_script; pub mod package_source; mod parse_args; mod path_util; +mod perform; mod run_cmd; mod source_control; mod target; diff --git a/src/librustpkg/perform.rs b/src/librustpkg/perform.rs new file mode 100644 index 0000000000000..5ddc6ba2683ad --- /dev/null +++ b/src/librustpkg/perform.rs @@ -0,0 +1,290 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This module contains methods such as build and install. They do the actual +// work of rustpkg + +use std::{io}; +use std::io::fs; +pub use std::path::Path; + +use context::{BuildContext}; +use crate_id::{CrateId}; +use messages::{warn, note}; +use path_util::{in_rust_path, built_executable_in_workspace}; +use path_util::{built_library_in_workspace, default_workspace}; +use path_util::{target_executable_in_workspace, target_library_in_workspace}; +use package_script::PkgScript; +use package_source::PkgSrc; +use source_control; +use source_control::{CheckedOutSources, is_git_dir, make_read_only}; +use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench}; +use target::{Tests, MaybeCustom, Inferred, JustOne}; +use workcache_support::digest_only_date; +use workcache_support; + + +/// Build a package +pub fn build(pkg_src: &mut PkgSrc, + what_to_build: &WhatToBuild, + build_context: &BuildContext) { + use conditions::git_checkout_failed::cond; + + let workspace = pkg_src.source_workspace.clone(); + let crateid = pkg_src.id.clone(); + + debug!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \ + crateid = {} pkgsrc start_dir = {}", workspace.display(), + in_rust_path(&workspace), is_git_dir(&workspace.join(&crateid.path)), + crateid.to_str(), pkg_src.start_dir.display()); + debug!("build: what to build = {:?}", what_to_build); + + // If workspace isn't in the RUST_PATH, and it's a git repo, + // then clone it into the first entry in RUST_PATH, and repeat + if !in_rust_path(&workspace) && is_git_dir(&workspace.join(&crateid.path)) { + let mut out_dir = default_workspace().join("src"); + out_dir.push(&crateid.path); + let git_result = source_control::safe_git_clone(&workspace.join(&crateid.path), + &crateid.version, + &out_dir); + match git_result { + CheckedOutSources => make_read_only(&out_dir), + // FIXME (#9639): This needs to handle non-utf8 paths + _ => cond.raise((crateid.path.as_str().unwrap().to_owned(), out_dir.clone())) + }; + let default_ws = default_workspace(); + debug!("Calling build recursively with {:?} and {:?}", default_ws.display(), + crateid.to_str()); + let pkg_src = &mut PkgSrc::new(default_ws.clone(), + default_ws, + false, + crateid.clone()); + return build(pkg_src, what_to_build, build_context); + } + + // Is there custom build logic? If so, use it + let mut custom = false; + debug!("Package source directory = {}", pkg_src.to_str()); + let opt = pkg_src.package_script_option(); + debug!("Calling pkg_script_option on {:?}", opt); + let cfgs = match (pkg_src.package_script_option(), what_to_build.build_type) { + (Some(package_script_path), MaybeCustom) => { + let sysroot = build_context.sysroot_to_use(); + // Build the package script if needed + let script_build = format!("build_package_script({})", + package_script_path.display()); + let pkg_exe = build_context.workcache_context.with_prep(script_build, |prep| { + let subsysroot = sysroot.clone(); + let psp = package_script_path.clone(); + let ws = workspace.clone(); + let pid = crateid.clone(); + prep.exec(proc(exec) { + let mut pscript = PkgScript::parse(subsysroot.clone(), + psp.clone(), + &ws, + &pid); + pscript.build_custom(exec) + }) + }); + // We always *run* the package script + match PkgScript::run_custom(&Path::new(pkg_exe), &sysroot) { + Some((cfgs, hook_result)) => { + debug!("Command return code = {:?}", hook_result); + if !hook_result.success() { + fail!("Error running custom build command") + } + custom = true; + // otherwise, the package script succeeded + cfgs + }, + None => { + fail!("Error starting custom build command") + } + } + } + (Some(_), Inferred) => { + debug!("There is a package script, but we're ignoring it"); + ~[] + } + (None, _) => { + debug!("No package script, continuing"); + ~[] + } + } + build_context.context.cfgs; + + // If there was a package script, it should have finished + // the build already. Otherwise... + if !custom { + match what_to_build.sources { + // Find crates inside the workspace + Everything => pkg_src.find_crates(), + // Find only tests + Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }), + // Don't infer any crates -- just build the one that was requested + JustOne(ref p) => { + // We expect that p is relative to the package source's start directory, + // so check that assumption + debug!("JustOne: p = {}", p.display()); + assert!(pkg_src.start_dir.join(p).exists()); + if is_lib(p) { + PkgSrc::push_crate(&mut pkg_src.libs, 0, p); + } else if is_main(p) { + PkgSrc::push_crate(&mut pkg_src.mains, 0, p); + } else if is_test(p) { + PkgSrc::push_crate(&mut pkg_src.tests, 0, p); + } else if is_bench(p) { + PkgSrc::push_crate(&mut pkg_src.benchs, 0, p); + } else { + warn(format!("Not building any crates for dependency {}", p.display())); + return; + } + } + } + // Build it! + pkg_src.build(build_context, cfgs, []); + } +} + +/// Install a package +pub fn install(mut pkg_src: PkgSrc, + what: &WhatToBuild, + build_context: &BuildContext) -> (~[Path], ~[(~str, ~str)]) { + + let id = pkg_src.id.clone(); + + let mut installed_files = ~[]; + let mut inputs = ~[]; + let mut build_inputs = ~[]; + + debug!("Installing package source: {}", pkg_src.to_str()); + + // workcache only knows about *crates*. Building a package + // just means inferring all the crates in it, then building each one. + build(&mut pkg_src, what, build_context); + + debug!("Done building package source {}", pkg_src.to_str()); + + let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(), + pkg_src.tests.clone(), pkg_src.benchs.clone()]; + debug!("In declare inputs for {}", id.to_str()); + for cs in to_do.iter() { + for c in cs.iter() { + let path = pkg_src.start_dir.join(&c.file); + debug!("Recording input: {}", path.display()); + // FIXME (#9639): This needs to handle non-utf8 paths + inputs.push((~"file", path.as_str().unwrap().to_owned())); + build_inputs.push(path); + } + } + + let result = + install_no_build(pkg_src.build_workspace(), + build_inputs, + &pkg_src.destination_workspace, + &id, + build_context).map(|s| Path::new(s.as_slice())); + installed_files = installed_files + result; + note(format!("Installed package {} to {}", + id.to_str(), + pkg_src.destination_workspace.display())); + (installed_files, inputs) +} + + +/// Installing a package without building +fn install_no_build(build_workspace: &Path, + build_inputs: &[Path], + target_workspace: &Path, + id: &CrateId, + build_context: &BuildContext) -> ~[~str] { + + debug!("install_no_build: assuming {} comes from {} with target {}", + id.to_str(), build_workspace.display(), target_workspace.display()); + + // Now copy stuff into the install dirs + let maybe_executable = built_executable_in_workspace(id, build_workspace); + let maybe_library = built_library_in_workspace(id, build_workspace); + let target_exec = target_executable_in_workspace(id, target_workspace); + let target_lib = maybe_library.as_ref() + .map(|_| target_library_in_workspace(id, target_workspace)); + + debug!("target_exec = {} target_lib = {:?} \ + maybe_executable = {:?} maybe_library = {:?}", + target_exec.display(), target_lib, + maybe_executable, maybe_library); + + build_context.workcache_context.with_prep(id.install_tag(), |prep| { + for ee in maybe_executable.iter() { + // FIXME (#9639): This needs to handle non-utf8 paths + prep.declare_input("binary", + ee.as_str().unwrap(), + workcache_support::digest_only_date(ee)); + } + for ll in maybe_library.iter() { + // FIXME (#9639): This needs to handle non-utf8 paths + prep.declare_input("binary", + ll.as_str().unwrap(), + workcache_support::digest_only_date(ll)); + } + let subex = maybe_executable.clone(); + let sublib = maybe_library.clone(); + let sub_target_ex = target_exec.clone(); + let sub_target_lib = target_lib.clone(); + let sub_build_inputs = build_inputs.to_owned(); + prep.exec(proc(exe_thing) { + let mut outputs = ~[]; + // Declare all the *inputs* to the declared input too, as inputs + for executable in subex.iter() { + exe_thing.discover_input("binary", + executable.as_str().unwrap().to_owned(), + workcache_support::digest_only_date(executable)); + } + for library in sublib.iter() { + exe_thing.discover_input("binary", + library.as_str().unwrap().to_owned(), + workcache_support::digest_only_date(library)); + } + + for transitive_dependency in sub_build_inputs.iter() { + exe_thing.discover_input( + "file", + transitive_dependency.as_str().unwrap().to_owned(), + workcache_support::digest_file_with_date(transitive_dependency)); + } + + + for exec in subex.iter() { + debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display()); + fs::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX); + fs::copy(exec, &sub_target_ex); + // FIXME (#9639): This needs to handle non-utf8 paths + exe_thing.discover_output("binary", + sub_target_ex.as_str().unwrap(), + workcache_support::digest_only_date(&sub_target_ex)); + outputs.push(sub_target_ex.as_str().unwrap().to_owned()); + } + for lib in sublib.iter() { + let mut target_lib = sub_target_lib + .clone().expect(format!("I built {} but apparently \ + didn't install it!", lib.display())); + target_lib.set_filename(lib.filename().expect("weird target lib")); + fs::mkdir_recursive(&target_lib.dir_path(), io::UserRWX); + fs::copy(lib, &target_lib); + debug!("3. discovering output {}", target_lib.display()); + exe_thing.discover_output("binary", + target_lib.as_str().unwrap(), + workcache_support::digest_only_date(&target_lib)); + outputs.push(target_lib.as_str().unwrap().to_owned()); + } + outputs + }) + }) +} + diff --git a/src/librustpkg/run_cmd.rs b/src/librustpkg/run_cmd.rs index 863a6249ef611..994359ca712ed 100644 --- a/src/librustpkg/run_cmd.rs +++ b/src/librustpkg/run_cmd.rs @@ -13,30 +13,22 @@ use std::io::fs; pub use std::path::Path; use context::{BuildContext}; -use context::{Command, BuildCmd, CleanCmd, DoCmd, InfoCmd}; -use context::{InstallCmd, ListCmd, PreferCmd, TestCmd, InitCmd, UninstallCmd}; +use context::{Command, BuildCmd, CleanCmd, DoCmd, InfoCmd, InstallCmd}; +use context::{ListCmd, PreferCmd, TestCmd, InitCmd, UninstallCmd}; use context::{UnpreferCmd}; use crate_id::{CrateId}; use installed_packages; use messages::{error, warn, note}; use path_util::{build_pkg_id_in_workspace, built_test_in_workspace}; -use path_util::{in_rust_path, built_executable_in_workspace}; -use path_util::{built_library_in_workspace, default_workspace}; -use path_util::{target_executable_in_workspace, target_library_in_workspace}; -use path_util::{dir_has_crate_file}; -use package_script::PkgScript; +use path_util::{default_workspace, dir_has_crate_file}; +use perform::{build, install}; use package_source::PkgSrc; use path_util; use rustc::metadata::filesearch::rust_path; -use source_control; -use source_control::{CheckedOutSources, is_git_dir, make_read_only}; -use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench}; -use target::{Tests, MaybeCustom, Inferred, JustOne}; +use target::{WhatToBuild, Everything, Tests, MaybeCustom}; use usage; use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces, cwd_to_workspace}; use workspace::determine_destination; -use workcache_support::digest_only_date; -use workcache_support; /// Perform actions based on parsed command line input pub fn run_cmd(cmd: Command, @@ -85,13 +77,13 @@ pub fn run_cmd(cmd: Command, let pkg_src = PkgSrc::new(cwd, default_workspace(), true, inferred_crateid); let what = WhatToBuild::new(MaybeCustom, Everything); - run_install(pkg_src, &what, build_context); + install(pkg_src, &what, build_context); } None => { usage::install(); return; } Some((ws, crateid)) => { let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, crateid); let what = WhatToBuild::new(MaybeCustom, Everything); - run_install(pkg_src, &what, build_context); + install(pkg_src, &what, build_context); } } } @@ -106,7 +98,7 @@ pub fn run_cmd(cmd: Command, let d = default_workspace(); let pkg_src = PkgSrc::new(d.clone(), d, false, crateid.clone()); let what = WhatToBuild::new(MaybeCustom, Everything); - run_install(pkg_src, &what, build_context); + install(pkg_src, &what, build_context); } else { for workspace in workspaces.iter() { @@ -118,7 +110,7 @@ pub fn run_cmd(cmd: Command, build_context.context.use_rust_path_hack, crateid.clone()); let what = WhatToBuild::new(MaybeCustom, Everything); - run_install(pkg_src, &what, build_context); + install(pkg_src, &what, build_context); }; } } @@ -250,126 +242,6 @@ fn run_do(_cmd: &str, _pkgname: &str) { } -fn build(pkg_src: &mut PkgSrc, - what_to_build: &WhatToBuild, - build_context: &BuildContext) { - use conditions::git_checkout_failed::cond; - - let workspace = pkg_src.source_workspace.clone(); - let crateid = pkg_src.id.clone(); - - debug!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \ - crateid = {} pkgsrc start_dir = {}", workspace.display(), - in_rust_path(&workspace), is_git_dir(&workspace.join(&crateid.path)), - crateid.to_str(), pkg_src.start_dir.display()); - debug!("build: what to build = {:?}", what_to_build); - - // If workspace isn't in the RUST_PATH, and it's a git repo, - // then clone it into the first entry in RUST_PATH, and repeat - if !in_rust_path(&workspace) && is_git_dir(&workspace.join(&crateid.path)) { - let mut out_dir = default_workspace().join("src"); - out_dir.push(&crateid.path); - let git_result = source_control::safe_git_clone(&workspace.join(&crateid.path), - &crateid.version, - &out_dir); - match git_result { - CheckedOutSources => make_read_only(&out_dir), - // FIXME (#9639): This needs to handle non-utf8 paths - _ => cond.raise((crateid.path.as_str().unwrap().to_owned(), out_dir.clone())) - }; - let default_ws = default_workspace(); - debug!("Calling build recursively with {:?} and {:?}", default_ws.display(), - crateid.to_str()); - let pkg_src = &mut PkgSrc::new(default_ws.clone(), - default_ws, - false, - crateid.clone()); - return build(pkg_src, what_to_build, build_context); - } - - // Is there custom build logic? If so, use it - let mut custom = false; - debug!("Package source directory = {}", pkg_src.to_str()); - let opt = pkg_src.package_script_option(); - debug!("Calling pkg_script_option on {:?}", opt); - let cfgs = match (pkg_src.package_script_option(), what_to_build.build_type) { - (Some(package_script_path), MaybeCustom) => { - let sysroot = build_context.sysroot_to_use(); - // Build the package script if needed - let script_build = format!("build_package_script({})", - package_script_path.display()); - let pkg_exe = build_context.workcache_context.with_prep(script_build, |prep| { - let subsysroot = sysroot.clone(); - let psp = package_script_path.clone(); - let ws = workspace.clone(); - let pid = crateid.clone(); - prep.exec(proc(exec) { - let mut pscript = PkgScript::parse(subsysroot.clone(), - psp.clone(), - &ws, - &pid); - pscript.build_custom(exec) - }) - }); - // We always *run* the package script - match PkgScript::run_custom(&Path::new(pkg_exe), &sysroot) { - Some((cfgs, hook_result)) => { - debug!("Command return code = {:?}", hook_result); - if !hook_result.success() { - fail!("Error running custom build command") - } - custom = true; - // otherwise, the package script succeeded - cfgs - }, - None => { - fail!("Error starting custom build command") - } - } - } - (Some(_), Inferred) => { - debug!("There is a package script, but we're ignoring it"); - ~[] - } - (None, _) => { - debug!("No package script, continuing"); - ~[] - } - } + build_context.context.cfgs; - - // If there was a package script, it should have finished - // the build already. Otherwise... - if !custom { - match what_to_build.sources { - // Find crates inside the workspace - Everything => pkg_src.find_crates(), - // Find only tests - Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }), - // Don't infer any crates -- just build the one that was requested - JustOne(ref p) => { - // We expect that p is relative to the package source's start directory, - // so check that assumption - debug!("JustOne: p = {}", p.display()); - assert!(pkg_src.start_dir.join(p).exists()); - if is_lib(p) { - PkgSrc::push_crate(&mut pkg_src.libs, 0, p); - } else if is_main(p) { - PkgSrc::push_crate(&mut pkg_src.mains, 0, p); - } else if is_test(p) { - PkgSrc::push_crate(&mut pkg_src.tests, 0, p); - } else if is_bench(p) { - PkgSrc::push_crate(&mut pkg_src.benchs, 0, p); - } else { - warn(format!("Not building any crates for dependency {}", p.display())); - return; - } - } - } - // Build it! - pkg_src.build(build_context, cfgs, []); - } -} - fn run_clean(workspace: &Path, id: &CrateId) { // Could also support a custom build hook in the pkg // script for cleaning files rustpkg doesn't know about. @@ -391,139 +263,6 @@ fn run_info() { fail!("info not yet implemented"); } -pub fn run_install(mut pkg_src: PkgSrc, - what: &WhatToBuild, - build_context: &BuildContext) -> (~[Path], ~[(~str, ~str)]) { - - let id = pkg_src.id.clone(); - - let mut installed_files = ~[]; - let mut inputs = ~[]; - let mut build_inputs = ~[]; - - debug!("Installing package source: {}", pkg_src.to_str()); - - // workcache only knows about *crates*. Building a package - // just means inferring all the crates in it, then building each one. - build(&mut pkg_src, what, build_context); - - debug!("Done building package source {}", pkg_src.to_str()); - - let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(), - pkg_src.tests.clone(), pkg_src.benchs.clone()]; - debug!("In declare inputs for {}", id.to_str()); - for cs in to_do.iter() { - for c in cs.iter() { - let path = pkg_src.start_dir.join(&c.file); - debug!("Recording input: {}", path.display()); - // FIXME (#9639): This needs to handle non-utf8 paths - inputs.push((~"file", path.as_str().unwrap().to_owned())); - build_inputs.push(path); - } - } - - let result = - install_no_build(pkg_src.build_workspace(), - build_inputs, - &pkg_src.destination_workspace, - &id, - build_context).map(|s| Path::new(s.as_slice())); -installed_files = installed_files + result; - note(format!("Installed package {} to {}", - id.to_str(), - pkg_src.destination_workspace.display())); - (installed_files, inputs) -} - -fn install_no_build(build_workspace: &Path, - build_inputs: &[Path], - target_workspace: &Path, - id: &CrateId, - build_context: &BuildContext) -> ~[~str] { - - debug!("install_no_build: assuming {} comes from {} with target {}", - id.to_str(), build_workspace.display(), target_workspace.display()); - - // Now copy stuff into the install dirs - let maybe_executable = built_executable_in_workspace(id, build_workspace); - let maybe_library = built_library_in_workspace(id, build_workspace); - let target_exec = target_executable_in_workspace(id, target_workspace); - let target_lib = maybe_library.as_ref() - .map(|_| target_library_in_workspace(id, target_workspace)); - - debug!("target_exec = {} target_lib = {:?} \ - maybe_executable = {:?} maybe_library = {:?}", - target_exec.display(), target_lib, - maybe_executable, maybe_library); - - build_context.workcache_context.with_prep(id.install_tag(), |prep| { - for ee in maybe_executable.iter() { - // FIXME (#9639): This needs to handle non-utf8 paths - prep.declare_input("binary", - ee.as_str().unwrap(), - workcache_support::digest_only_date(ee)); - } - for ll in maybe_library.iter() { - // FIXME (#9639): This needs to handle non-utf8 paths - prep.declare_input("binary", - ll.as_str().unwrap(), - workcache_support::digest_only_date(ll)); - } - let subex = maybe_executable.clone(); - let sublib = maybe_library.clone(); - let sub_target_ex = target_exec.clone(); - let sub_target_lib = target_lib.clone(); - let sub_build_inputs = build_inputs.to_owned(); - prep.exec(proc(exe_thing) { - let mut outputs = ~[]; - // Declare all the *inputs* to the declared input too, as inputs - for executable in subex.iter() { - exe_thing.discover_input("binary", - executable.as_str().unwrap().to_owned(), - workcache_support::digest_only_date(executable)); - } - for library in sublib.iter() { - exe_thing.discover_input("binary", - library.as_str().unwrap().to_owned(), - workcache_support::digest_only_date(library)); - } - - for transitive_dependency in sub_build_inputs.iter() { - exe_thing.discover_input( - "file", - transitive_dependency.as_str().unwrap().to_owned(), - workcache_support::digest_file_with_date(transitive_dependency)); - } - - - for exec in subex.iter() { - debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display()); - fs::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX); - fs::copy(exec, &sub_target_ex); - // FIXME (#9639): This needs to handle non-utf8 paths - exe_thing.discover_output("binary", - sub_target_ex.as_str().unwrap(), - workcache_support::digest_only_date(&sub_target_ex)); - outputs.push(sub_target_ex.as_str().unwrap().to_owned()); - } - for lib in sublib.iter() { - let mut target_lib = sub_target_lib - .clone().expect(format!("I built {} but apparently \ - didn't install it!", lib.display())); - target_lib.set_filename(lib.filename().expect("weird target lib")); - fs::mkdir_recursive(&target_lib.dir_path(), io::UserRWX); - fs::copy(lib, &target_lib); - debug!("3. discovering output {}", target_lib.display()); - exe_thing.discover_output("binary", - target_lib.as_str().unwrap(), - workcache_support::digest_only_date(&target_lib)); - outputs.push(target_lib.as_str().unwrap().to_owned()); - } - outputs - }) - }) -} - fn run_prefer(_id: &str, _vers: Option<~str>) { fail!("prefer not yet implemented"); } diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index 82ebd236a9180..4d288e0b43e1b 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -22,7 +22,7 @@ use extra::workcache; use extra::workcache::{Database, Logger}; use extra::treemap::TreeMap; use extra::getopts::groups::getopts; -use run_cmd::{run_install}; +use perform::{install}; use std::run::ProcessOutput; use installed_packages::list_installed_packages; use crate_id::{CrateId}; @@ -592,7 +592,7 @@ fn test_install_valid() { temp_workspace.clone(), false, temp_pkg_id.clone()); - run_install(src, &WhatToBuild::new(MaybeCustom, Everything), &ctxt); + install(src, &WhatToBuild::new(MaybeCustom, Everything), &ctxt); // Check that all files exist let exec = target_executable_in_workspace(&temp_pkg_id, temp_workspace); debug!("exec = {}", exec.display()); @@ -631,7 +631,7 @@ fn test_install_invalid() { temp_workspace.clone(), false, crateid.clone()); - run_install(pkg_src, &WhatToBuild::new(MaybeCustom, Everything),&ctxt); + install(pkg_src, &WhatToBuild::new(MaybeCustom, Everything),&ctxt); }; assert!(result.unwrap_err() .to_str().contains("supplied path for package dir does not exist")); diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index a3fe5ed184fe2..b941b9cf18a05 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -34,7 +34,7 @@ use package_source::PkgSrc; use workspace::pkg_parent_workspaces; use path_util::{system_library, target_build_dir}; use path_util::{default_workspace, built_library_in_workspace}; -use run_cmd::{run_install}; +use perform::{install}; pub use target::{OutputType, Main, Lib, Bench, Test, JustOne, lib_name_of, lib_crate_filename}; pub use target::{Target, Build, Install}; use extra::treemap::TreeMap; @@ -528,7 +528,7 @@ impl<'a> Visitor<()> for ViewItemVisitor<'a> { let what = WhatToBuild::new(Inferred, JustOne(Path::new(lib_crate_filename))); let (outputs_disc, inputs_disc) = - run_install(pkg_src, &what, self.context); + install(pkg_src, &what, self.context); debug!("Installed {}, returned {:?} dependencies and \ {:?} transitive dependencies", lib_name, outputs_disc.len(), inputs_disc.len()); From c517fcaad28afe2bcb1f9518be4d47ee34ed00a4 Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Tue, 7 Jan 2014 10:12:30 +0100 Subject: [PATCH 5/8] rustpkg: Add supplied_sysroot to context --- src/librustpkg/api.rs | 1 + src/librustpkg/context.rs | 2 ++ src/librustpkg/lib.rs | 11 +++++------ src/librustpkg/parse_args.rs | 6 ++---- src/librustpkg/tests.rs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs index fbd499108f036..f6d89a00377ab 100644 --- a/src/librustpkg/api.rs +++ b/src/librustpkg/api.rs @@ -50,6 +50,7 @@ pub fn new_default_context(c: workcache::Context, p: Path) -> BuildContext { cfgs: ~[], rustc_flags: RustcFlags::default(), use_rust_path_hack: false, + supplied_sysroot: None }, sysroot: p, workcache_context: c diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs index 681ae1dc80780..c73d9c477af7c 100644 --- a/src/librustpkg/context.rs +++ b/src/librustpkg/context.rs @@ -27,6 +27,8 @@ pub struct Context { // FOO/src/bar-0.1 instead of FOO). The flag doesn't affect where // rustpkg stores build artifacts. use_rust_path_hack: bool, + // The root directory containing the Rust standard libraries + supplied_sysroot: Option<~str> } #[deriving(Clone)] diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index eba3aaa759b42..133ded8603d71 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -66,12 +66,11 @@ pub fn main() { pub fn main_args(args: &[~str]) -> int { - let (command, args, context, supplied_sysroot) = match parse_args(args) { + let (command, args, context) = match parse_args(args) { Ok(ParseResult { command: cmd, args: args, - context: ctx, - sysroot: sroot}) => (cmd, args, ctx, sroot), + context: ctx}) => (cmd, args, ctx), Err(error_code) => { debug!("Parsing failed. Returning error code {}", error_code); return error_code @@ -83,10 +82,10 @@ pub fn main_args(args: &[~str]) -> int { debug!(" Using cflags: {:?}", context.rustc_flags); debug!(" Using rust_path_hack {:b}", context.use_rust_path_hack); debug!(" Using cfgs: {:?}", context.cfgs); - debug!(" Using supplied_sysroot: {:?}", supplied_sysroot); + debug!(" Using supplied_sysroot: {:?}", context.supplied_sysroot); - let sysroot = match supplied_sysroot { - Some(s) => Path::new(s), + let sysroot = match context.supplied_sysroot.clone() { + Some(ref s) => Path::new(s.clone()), _ => filesearch::get_or_default_sysroot() }; diff --git a/src/librustpkg/parse_args.rs b/src/librustpkg/parse_args.rs index 8f21c6d3bfa68..68cc09adad9d8 100644 --- a/src/librustpkg/parse_args.rs +++ b/src/librustpkg/parse_args.rs @@ -29,8 +29,6 @@ pub struct ParseResult { args: ~[~str], // Parsed command line flags context: Context, - // Path to system root - sysroot: Option<~str> } /// Parses command line arguments of rustpkg. @@ -179,12 +177,12 @@ pub fn parse_args(args: &[~str]) -> Result { rustc_flags: rustc_flags, cfgs: cfgs, use_rust_path_hack: use_rust_path_hack, + supplied_sysroot: supplied_sysroot }; Ok(ParseResult { command: command, args: remaining_args, - context: context, - sysroot: supplied_sysroot + context: context }) } diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index 4d288e0b43e1b..4710b69052ae1 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -53,8 +53,8 @@ fn fake_ctxt(sysroot: Path, workspace: &Path) -> BuildContext { context: Context { cfgs: ~[], rustc_flags: RustcFlags::default(), - use_rust_path_hack: false, + supplied_sysroot:None }, sysroot: sysroot } From fa5418f5aa326de2ac7f2ef43e7b4efd71622786 Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Tue, 7 Jan 2014 18:03:38 +0100 Subject: [PATCH 6/8] rustpkg Initialize build-context later in the build process --- src/librustpkg/context.rs | 22 ++++++++++++++++++++ src/librustpkg/lib.rs | 21 +------------------ src/librustpkg/run_cmd.rs | 43 +++++++++++++++++++++++---------------- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs index c73d9c477af7c..73d20813cfb8c 100644 --- a/src/librustpkg/context.rs +++ b/src/librustpkg/context.rs @@ -10,8 +10,11 @@ // Context data structure used by rustpkg +use api; use extra::workcache; +use path_util::{default_workspace}; use rustc::driver::session; +use rustc::metadata::filesearch; use rustc::metadata::filesearch::rustlibdir; use std::hashmap::HashSet; @@ -77,6 +80,25 @@ impl BuildContext { pub fn additional_library_paths(&self) -> HashSet { self.context.rustc_flags.additional_library_paths.clone() } + + pub fn from_context(context: &Context) -> BuildContext{ + + let sysroot = match context.supplied_sysroot.clone() { + Some(ref s) => Path::new(s.clone()), + _ => filesearch::get_or_default_sysroot() + }; + debug!("Using sysroot: {}", sysroot.display()); + + let ws = default_workspace(); + debug!("Will store workcache in {}", ws.display()); + + BuildContext { + context: context.clone(), + sysroot: sysroot.clone(), + workcache_context: api::default_context(sysroot.clone(), + default_workspace()).workcache_context + } + } } /* diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index 133ded8603d71..8c91c2d092bd7 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -20,18 +20,14 @@ extern mod extra; extern mod rustc; extern mod syntax; -use std::path::Path; use std::{os, task}; use context::{Trans, Nothing, Pretty, Analysis, LLVMAssemble}; use context::{LLVMCompileBitcode, BuildCmd, CleanCmd, DoCmd, InfoCmd}; use context::{InstallCmd, ListCmd, PreferCmd, TestCmd, InitCmd, UninstallCmd}; use context::{UnpreferCmd}; -use context::{BuildContext}; -use rustc::metadata::filesearch; use run_cmd::{run_cmd}; use parse_args::{ParseResult, parse_args}; -use path_util::{default_workspace}; use exit_codes::{COPY_FAILED_CODE}; pub mod api; @@ -84,24 +80,9 @@ pub fn main_args(args: &[~str]) -> int { debug!(" Using cfgs: {:?}", context.cfgs); debug!(" Using supplied_sysroot: {:?}", context.supplied_sysroot); - let sysroot = match context.supplied_sysroot.clone() { - Some(ref s) => Path::new(s.clone()), - _ => filesearch::get_or_default_sysroot() - }; - - debug!("Using sysroot: {}", sysroot.display()); - let ws = default_workspace(); - debug!("Will store workcache in {}", ws.display()); - // Wrap the rest in task::try in case of a condition failure in a task let result = do task::try { - let build_context = BuildContext { - context: context, - sysroot: sysroot.clone(), // Currently, only tests override this - workcache_context: api::default_context(sysroot.clone(), - default_workspace()).workcache_context - }; - run_cmd(command, args.clone(), &build_context); + run_cmd(command, args.clone(), &context); }; // FIXME #9262: This is using the same error code for all errors, // and at least one test case succeeds if rustpkg returns COPY_FAILED_CODE, diff --git a/src/librustpkg/run_cmd.rs b/src/librustpkg/run_cmd.rs index 994359ca712ed..5a920021c587a 100644 --- a/src/librustpkg/run_cmd.rs +++ b/src/librustpkg/run_cmd.rs @@ -12,7 +12,7 @@ use std::{io, os, run}; use std::io::fs; pub use std::path::Path; -use context::{BuildContext}; +use context::{Context, BuildContext}; use context::{Command, BuildCmd, CleanCmd, DoCmd, InfoCmd, InstallCmd}; use context::{ListCmd, PreferCmd, TestCmd, InitCmd, UninstallCmd}; use context::{UnpreferCmd}; @@ -33,12 +33,12 @@ use workspace::determine_destination; /// Perform actions based on parsed command line input pub fn run_cmd(cmd: Command, args: ~[~str], - build_context: &BuildContext ) { + context: &Context) { let cwd = os::getcwd(); match cmd { BuildCmd => { let what = WhatToBuild::new(MaybeCustom, Everything); - run_build(args, &what, build_context); + run_build(args, &what, context); } CleanCmd => { if args.len() < 1 { @@ -77,13 +77,15 @@ pub fn run_cmd(cmd: Command, let pkg_src = PkgSrc::new(cwd, default_workspace(), true, inferred_crateid); let what = WhatToBuild::new(MaybeCustom, Everything); - install(pkg_src, &what, build_context); + let build_context = BuildContext::from_context(context); + install(pkg_src, &what, &build_context); } None => { usage::install(); return; } Some((ws, crateid)) => { let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, crateid); let what = WhatToBuild::new(MaybeCustom, Everything); - install(pkg_src, &what, build_context); + let build_context = BuildContext::from_context(context); + install(pkg_src, &what, &build_context); } } } @@ -91,26 +93,28 @@ pub fn run_cmd(cmd: Command, // The package id is presumed to be the first command-line // argument let crateid = CrateId::new(args[0]); - let workspaces = pkg_parent_workspaces(&build_context.context, &crateid); + let workspaces = pkg_parent_workspaces(context, &crateid); debug!("package ID = {}, found it in {:?} workspaces", crateid.to_str(), workspaces.len()); if workspaces.is_empty() { let d = default_workspace(); let pkg_src = PkgSrc::new(d.clone(), d, false, crateid.clone()); let what = WhatToBuild::new(MaybeCustom, Everything); - install(pkg_src, &what, build_context); + let build_context = BuildContext::from_context(context); + install(pkg_src, &what, &build_context); } else { for workspace in workspaces.iter() { let dest = determine_destination(os::getcwd(), - build_context.context.use_rust_path_hack, + context.use_rust_path_hack, workspace); let pkg_src = PkgSrc::new(workspace.clone(), dest, - build_context.context.use_rust_path_hack, + context.use_rust_path_hack, crateid.clone()); let what = WhatToBuild::new(MaybeCustom, Everything); - install(pkg_src, &what, build_context); + let build_context = BuildContext::from_context(context); + install(pkg_src, &what, &build_context); }; } } @@ -131,7 +135,7 @@ pub fn run_cmd(cmd: Command, TestCmd => { // Build the test executable let what = WhatToBuild::new(MaybeCustom, Tests); - let maybe_id_and_workspace = run_build(args, &what, build_context); + let maybe_id_and_workspace = run_build(args, &what, context); match maybe_id_and_workspace { Some((pkg_id, workspace)) => { // Assuming it's built, run the tests @@ -163,7 +167,7 @@ pub fn run_cmd(cmd: Command, else { let rp = rust_path(); assert!(!rp.is_empty()); - each_pkg_parent_workspace(&build_context.context, &crateid, |workspace| { + each_pkg_parent_workspace(context, &crateid, |workspace| { path_util::uninstall_package_from(workspace, &crateid); note(format!("Uninstalled package {} (was installed in {})", crateid.to_str(), workspace.display())); @@ -183,7 +187,7 @@ pub fn run_cmd(cmd: Command, fn run_build(args: ~[~str], what: &WhatToBuild, - build_context: &BuildContext) -> Option<(CrateId, Path)> { + context: &Context) -> Option<(CrateId, Path)> { let cwd = os::getcwd(); if args.len() < 1 { @@ -192,7 +196,8 @@ fn run_build(args: ~[~str], // FIXME (#9639): This needs to handle non-utf8 paths let crateid = CrateId::new(cwd.filename_str().unwrap()); let mut pkg_src = PkgSrc::new(cwd, default_workspace(), true, crateid); - build(&mut pkg_src, what, build_context); + let build_context = BuildContext::from_context(context); + build(&mut pkg_src, what, &build_context); match pkg_src { PkgSrc { destination_workspace: ws, id: id, .. } => { @@ -203,7 +208,8 @@ fn run_build(args: ~[~str], None => { usage::build(); None } Some((ws, crateid)) => { let mut pkg_src = PkgSrc::new(ws.clone(), ws, false, crateid); - build(&mut pkg_src, what, build_context); + let build_context = BuildContext::from_context(context); + build(&mut pkg_src, what, &build_context); match pkg_src { PkgSrc { destination_workspace: ws, id: id, .. } => { @@ -217,15 +223,16 @@ fn run_build(args: ~[~str], // argument let crateid = CrateId::new(args[0].clone()); let mut dest_ws = default_workspace(); - each_pkg_parent_workspace(&build_context.context, &crateid, |workspace| { + each_pkg_parent_workspace(context, &crateid, |workspace| { debug!("found pkg {} in workspace {}, trying to build", crateid.to_str(), workspace.display()); dest_ws = determine_destination(os::getcwd(), - build_context.context.use_rust_path_hack, + context.use_rust_path_hack, workspace); let mut pkg_src = PkgSrc::new(workspace.clone(), dest_ws.clone(), false, crateid.clone()); - build(&mut pkg_src, what, build_context); + let build_context = BuildContext::from_context(context); + build(&mut pkg_src, what, &build_context); true }); // n.b. If this builds multiple packages, it only returns the workspace for From 6a27a22421c4e1e56f37e08b6361849f0cfa0e99 Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Tue, 7 Jan 2014 18:18:24 +0100 Subject: [PATCH 7/8] Remove some dead code --- src/librustpkg/tests.rs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index 4710b69052ae1..dfb2588014263 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -26,7 +26,7 @@ use perform::{install}; use std::run::ProcessOutput; use installed_packages::list_installed_packages; use crate_id::{CrateId}; -use version::{ExactRevision, NoVersion, Version, Tagged}; +use version::{ExactRevision, NoVersion, Version}; use path_util::{target_executable_in_workspace, target_test_in_workspace, target_bench_in_workspace, make_dir_rwx, library_in_workspace, installed_library_in_workspace, @@ -35,7 +35,6 @@ use path_util::{target_executable_in_workspace, target_test_in_workspace, chmod_read_only, platform_library_name}; use rustc::back::link::get_cc_prog; use rustc::metadata::filesearch::{rust_path, libdir, rustlibdir}; -use rustc::driver::session; use rustc::driver::driver::{build_session, build_session_options, host_triple, optgroups}; use syntax::diagnostic; use target::*; @@ -77,14 +76,6 @@ fn git_repo_pkg() -> CrateId { } } -fn git_repo_pkg_with_tag(a_tag: ~str) -> CrateId { - CrateId { - path: Path::new("mockgithub.com/catamorphism/test-pkg"), - short_name: ~"test-pkg", - version: Tagged(a_tag) - } -} - fn writeFile(file_path: &Path, contents: &str) { let mut out = File::create(file_path); out.write(contents.as_bytes()); @@ -488,12 +479,6 @@ fn lib_output_file_name(workspace: &Path, short_name: &str) -> Path { &NoVersion).expect("lib_output_file_name") } -fn output_file_name(workspace: &Path, short_name: ~str) -> Path { - target_build_dir(workspace).join(short_name.as_slice()) - .join(format!("{}{}", short_name, - os::consts::EXE_SUFFIX)) -} - #[cfg(target_os = "linux")] fn touch_source_file(workspace: &Path, crateid: &CrateId) { use conditions::bad_path::cond; From 037da20676b1c78c6e71261700543259004a677f Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Tue, 7 Jan 2014 19:27:27 +0100 Subject: [PATCH 8/8] rustpkg A few cleanups in run_cmd.rs --- src/librustpkg/run_cmd.rs | 152 ++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 72 deletions(-) diff --git a/src/librustpkg/run_cmd.rs b/src/librustpkg/run_cmd.rs index 5a920021c587a..e6a6a132145ad 100644 --- a/src/librustpkg/run_cmd.rs +++ b/src/librustpkg/run_cmd.rs @@ -10,7 +10,7 @@ use std::{io, os, run}; use std::io::fs; -pub use std::path::Path; +use std::path::Path; use context::{Context, BuildContext}; use context::{Command, BuildCmd, CleanCmd, DoCmd, InfoCmd, InstallCmd}; @@ -49,8 +49,7 @@ pub fn run_cmd(cmd: Command, Some((ws, crateid)) => run_clean(&ws, &crateid) } - } - else { + } else { // The package id is presumed to be the first command-line // argument let crateid = CrateId::new(args[0].clone()); @@ -67,56 +66,10 @@ pub fn run_cmd(cmd: Command, run_info(); } InstallCmd => { - if args.len() < 1 { - match cwd_to_workspace() { - None if dir_has_crate_file(&cwd) => { - // FIXME (#9639): This needs to handle non-utf8 paths - - let inferred_crateid = - CrateId::new(cwd.filename_str().unwrap()); - let pkg_src = PkgSrc::new(cwd, default_workspace(), - true, inferred_crateid); - let what = WhatToBuild::new(MaybeCustom, Everything); - let build_context = BuildContext::from_context(context); - install(pkg_src, &what, &build_context); - } - None => { usage::install(); return; } - Some((ws, crateid)) => { - let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, crateid); - let what = WhatToBuild::new(MaybeCustom, Everything); - let build_context = BuildContext::from_context(context); - install(pkg_src, &what, &build_context); - } - } - } - else { - // The package id is presumed to be the first command-line - // argument - let crateid = CrateId::new(args[0]); - let workspaces = pkg_parent_workspaces(context, &crateid); - debug!("package ID = {}, found it in {:?} workspaces", - crateid.to_str(), workspaces.len()); - if workspaces.is_empty() { - let d = default_workspace(); - let pkg_src = PkgSrc::new(d.clone(), d, false, crateid.clone()); - let what = WhatToBuild::new(MaybeCustom, Everything); - let build_context = BuildContext::from_context(context); - install(pkg_src, &what, &build_context); - } - else { - for workspace in workspaces.iter() { - let dest = determine_destination(os::getcwd(), - context.use_rust_path_hack, - workspace); - let pkg_src = PkgSrc::new(workspace.clone(), - dest, - context.use_rust_path_hack, - crateid.clone()); - let what = WhatToBuild::new(MaybeCustom, Everything); - let build_context = BuildContext::from_context(context); - install(pkg_src, &what, &build_context); - }; - } + if args.len() < 1 { + run_install(None, context); + } else { + run_install(Some(args[0]), context); } } ListCmd => { @@ -157,29 +110,12 @@ pub fn run_cmd(cmd: Command, if args.len() < 1 { return usage::uninstall(); } - - let crateid = CrateId::new(args[0]); - if !installed_packages::package_is_installed(&crateid) { - warn(format!("Package {} doesn't seem to be installed! \ - Doing nothing.", args[0])); - return; - } - else { - let rp = rust_path(); - assert!(!rp.is_empty()); - each_pkg_parent_workspace(context, &crateid, |workspace| { - path_util::uninstall_package_from(workspace, &crateid); - note(format!("Uninstalled package {} (was installed in {})", - crateid.to_str(), workspace.display())); - true - }); - } + run_uninstall(args[0], context); } UnpreferCmd => { if args.len() < 1 { return usage::unprefer(); - } - + }; run_unprefer(args[0], None); } } @@ -270,6 +206,56 @@ fn run_info() { fail!("info not yet implemented"); } + +fn run_install(maybe_crateid_str: Option<~str>, context: &Context){ + let pkg_src = match maybe_crateid_str { + None => match cwd_to_workspace() { + Some((ws, crateid)) => { + PkgSrc::new(ws.clone(), ws.clone(), false, crateid) + }, + None if dir_has_crate_file(&os::getcwd()) => { + // FIXME (#9639): This needs to handle non-utf8 paths + let cwd = os::getcwd(); + let crateid = CrateId::new(cwd.filename_str().unwrap()); + PkgSrc::new(cwd, default_workspace(),true, crateid) + } + None => { + usage::install(); + return; + } + }, + Some(crateid_str) => { + let crateid = CrateId::new(crateid_str); + let workspaces = pkg_parent_workspaces(context, &crateid); + debug!("package ID = {}, found it in {:?} workspaces", + crateid.to_str(), workspaces.len()); + if workspaces.is_empty() { + // Install default workspace + let d = default_workspace(); + PkgSrc::new(d.clone(), d, false, crateid.clone()) + } else { + // Install all parent workspaces, and then return early + let what = WhatToBuild::new(MaybeCustom, Everything); + let build_context = BuildContext::from_context(context); + for workspace in workspaces.iter() { + let dest = determine_destination(os::getcwd(), + context.use_rust_path_hack, + workspace); + let pkg_src = PkgSrc::new(workspace.clone(), + dest, + context.use_rust_path_hack, + crateid.clone()); + install(pkg_src, &what, &build_context); + } + return; + } + } + }; + let what = WhatToBuild::new(MaybeCustom, Everything); + let build_context = BuildContext::from_context(context); + install(pkg_src, &what, &build_context); +} + fn run_prefer(_id: &str, _vers: Option<~str>) { fail!("prefer not yet implemented"); } @@ -304,6 +290,28 @@ fn run_init() { fs::mkdir_recursive(&Path::new("build"), io::UserRWX); } +fn run_uninstall(crateid_str: &str, context: &Context) { + let crateid = CrateId::new(crateid_str); + if !installed_packages::package_is_installed(&crateid) { + warn(format!("Package {} doesn't seem to be installed! \ + Doing nothing.", crateid_str)); + return; + } else { + let rp = rust_path(); + assert!(!rp.is_empty()); + let workspaces = pkg_parent_workspaces(context, &crateid); + for workspace in workspaces.iter() { + path_util::uninstall_package_from(workspace, &crateid); + note(format!("Uninstalled package {} (was installed in {})", + crateid.to_str(), workspace.display())); + return + }; + warn!("Failed to find a parent workspace") + warn!("crateid_str: {}", crateid_str); + warn!("crate_id: {:?}", crateid); + } +} + fn run_unprefer(_id: &str, _vers: Option<~str>) { fail!("unprefer not yet implemented"); }