2013-02-28 13:15:32 +00:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2013-01-14 20:55:47 +10:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-04-12 16:15:40 -07:00
|
|
|
// rustpkg - a package manager and build system for Rust
|
2013-01-14 20:55:47 +10:00
|
|
|
|
2014-01-09 22:47:26 -08:00
|
|
|
#[crate_id = "rustpkg#0.10-pre"];
|
2013-03-01 08:41:31 -08:00
|
|
|
#[license = "MIT/ASL2"];
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 14:03:29 -08:00
|
|
|
#[crate_type = "dylib"];
|
2013-01-14 20:55:47 +10:00
|
|
|
|
2013-10-22 23:56:46 -04:00
|
|
|
#[feature(globs, managed_boxes)];
|
2013-10-02 18:10:16 -07:00
|
|
|
|
2013-06-28 18:32:26 -04:00
|
|
|
extern mod extra;
|
2013-05-19 00:21:41 -04:00
|
|
|
extern mod rustc;
|
|
|
|
extern mod syntax;
|
2013-01-14 20:55:47 +10:00
|
|
|
|
2014-01-05 11:23:39 +01:00
|
|
|
use std::{os, run, str, task};
|
2013-11-10 22:46:32 -08:00
|
|
|
use std::io::process;
|
|
|
|
use std::io;
|
|
|
|
use std::io::fs;
|
2013-06-28 18:32:26 -04:00
|
|
|
pub use std::path::Path;
|
|
|
|
|
2013-09-06 20:29:16 -07:00
|
|
|
use extra::workcache;
|
2013-01-18 18:31:43 +10:00
|
|
|
use rustc::driver::{driver, session};
|
2013-12-25 11:10:33 -07:00
|
|
|
use rustc::metadata::creader::Loader;
|
2013-03-01 10:44:43 -08:00
|
|
|
use rustc::metadata::filesearch;
|
2013-07-31 13:47:32 -07:00
|
|
|
use rustc::metadata::filesearch::rust_path;
|
2013-12-09 14:56:53 -07:00
|
|
|
use rustc::util::sha2;
|
2013-03-26 16:38:07 -04:00
|
|
|
use syntax::{ast, diagnostic};
|
2014-01-11 00:22:06 +09:00
|
|
|
use syntax::crateid::CrateId;
|
2013-09-10 23:25:31 -07:00
|
|
|
use messages::{error, warn, note};
|
2014-01-05 11:23:39 +01:00
|
|
|
use parse_args::{ParseResult, parse_args};
|
2013-09-26 16:04:49 -07:00
|
|
|
use path_util::{build_pkg_id_in_workspace, built_test_in_workspace};
|
2013-10-25 17:04:37 -07:00
|
|
|
use path_util::in_rust_path;
|
2013-07-09 18:28:00 -07:00
|
|
|
use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace};
|
2013-10-05 22:14:10 -04:00
|
|
|
use path_util::{target_executable_in_workspace, target_library_in_workspace, dir_has_crate_file};
|
2013-10-05 16:40:01 -04:00
|
|
|
use source_control::{CheckedOutSources, is_git_dir, make_read_only};
|
2013-08-22 19:18:38 -07:00
|
|
|
use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces, cwd_to_workspace};
|
2013-10-05 16:40:01 -04:00
|
|
|
use workspace::determine_destination;
|
2014-01-05 11:23:39 +01:00
|
|
|
use context::{BuildContext, Trans, Nothing, Pretty, Analysis,
|
|
|
|
LLVMAssemble, LLVMCompileBitcode};
|
2014-01-11 00:34:09 -05:00
|
|
|
use context::{Command, BuildCmd, CleanCmd, DoCmd, HelpCmd, InfoCmd, InstallCmd, ListCmd,
|
2014-01-05 10:17:51 +01:00
|
|
|
PreferCmd, TestCmd, InitCmd, UninstallCmd, UnpreferCmd};
|
2013-06-01 15:59:12 -07:00
|
|
|
use package_source::PkgSrc;
|
2013-09-30 22:39:50 -07:00
|
|
|
use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench};
|
2013-12-09 14:56:53 -07:00
|
|
|
use target::{Main, Tests, MaybeCustom, Inferred, JustOne};
|
2013-09-16 19:27:09 -07:00
|
|
|
use workcache_support::digest_only_date;
|
2014-01-05 11:23:39 +01:00
|
|
|
use exit_codes::{COPY_FAILED_CODE};
|
2013-01-14 20:55:47 +10:00
|
|
|
|
2013-06-25 22:26:22 -07:00
|
|
|
pub mod api;
|
2013-04-12 16:15:40 -07:00
|
|
|
mod conditions;
|
2013-09-30 22:39:50 -07:00
|
|
|
pub mod context;
|
2013-06-01 15:59:12 -07:00
|
|
|
mod crate;
|
2013-09-30 22:39:50 -07:00
|
|
|
pub mod exit_codes;
|
2013-07-11 18:20:31 -07:00
|
|
|
mod installed_packages;
|
2013-06-14 18:16:24 -07:00
|
|
|
mod messages;
|
2013-12-08 02:55:28 -05:00
|
|
|
pub mod package_source;
|
2014-01-05 11:23:39 +01:00
|
|
|
mod parse_args;
|
2013-04-12 16:15:40 -07:00
|
|
|
mod path_util;
|
2013-07-09 18:28:00 -07:00
|
|
|
mod source_control;
|
2013-05-27 17:45:16 -07:00
|
|
|
mod target;
|
2013-11-14 10:19:25 +09:00
|
|
|
#[cfg(not(windows), test)] // FIXME test failure on windows: #10471
|
2013-04-24 17:37:59 -07:00
|
|
|
mod tests;
|
2013-01-15 23:57:03 +10:00
|
|
|
mod util;
|
2013-09-30 22:39:50 -07:00
|
|
|
pub mod version;
|
2013-09-06 20:29:16 -07:00
|
|
|
pub mod workcache_support;
|
2013-04-24 17:37:59 -07:00
|
|
|
mod workspace;
|
2013-01-15 23:57:03 +10:00
|
|
|
|
2013-05-12 17:48:01 -04:00
|
|
|
pub mod usage;
|
|
|
|
|
2013-04-11 17:43:02 -07:00
|
|
|
/// A PkgScript represents user-supplied custom logic for
|
|
|
|
/// special build hooks. This only exists for packages with
|
|
|
|
/// an explicit package script.
|
2013-12-09 23:16:18 -08:00
|
|
|
struct PkgScript<'a> {
|
2013-04-11 17:43:02 -07:00
|
|
|
/// Uniquely identifies this package
|
2013-12-28 15:24:15 -05:00
|
|
|
id: &'a CrateId,
|
2013-09-06 20:29:16 -07:00
|
|
|
/// File path for the package script
|
|
|
|
input: Path,
|
2013-04-11 17:43:02 -07:00
|
|
|
/// The session to use *only* for compiling the custom
|
|
|
|
/// build script
|
2013-01-23 11:19:13 +10:00
|
|
|
sess: session::Session,
|
2013-04-11 17:43:02 -07:00
|
|
|
/// The config for compiling the custom build script
|
2013-07-19 07:38:55 +02:00
|
|
|
cfg: ast::CrateConfig,
|
2014-01-06 14:00:46 +02:00
|
|
|
/// The crate and ast_map for the custom build script
|
2014-01-09 22:25:09 +02:00
|
|
|
crate_and_map: Option<(ast::Crate, syntax::ast_map::Map)>,
|
2013-04-11 17:43:02 -07:00
|
|
|
/// Directory in which to store build output
|
|
|
|
build_dir: Path
|
2013-01-16 21:59:37 +10:00
|
|
|
}
|
|
|
|
|
2013-12-09 23:16:18 -08:00
|
|
|
impl<'a> PkgScript<'a> {
|
2013-04-11 17:43:02 -07:00
|
|
|
/// Given the path name for a package script
|
|
|
|
/// and a package ID, parse the package script into
|
|
|
|
/// a PkgScript that we can then execute
|
2013-09-30 22:39:50 -07:00
|
|
|
fn parse<'a>(sysroot: Path,
|
2013-08-15 18:36:39 -07:00
|
|
|
script: Path,
|
|
|
|
workspace: &Path,
|
2013-12-28 15:24:15 -05:00
|
|
|
id: &'a CrateId) -> PkgScript<'a> {
|
2013-04-11 17:43:02 -07:00
|
|
|
// Get the executable name that was invoked
|
2014-01-11 00:22:06 +09:00
|
|
|
let binary = os::args()[0];
|
2013-04-11 17:43:02 -07:00
|
|
|
// Build the rustc session data structures to pass
|
|
|
|
// to the compiler
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("pkgscript parse: {}", sysroot.display());
|
2014-01-14 01:31:05 +09:00
|
|
|
let options = @session::Options {
|
2013-05-11 22:45:13 -04:00
|
|
|
binary: binary,
|
2013-09-30 22:39:50 -07:00
|
|
|
maybe_sysroot: Some(@sysroot),
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 14:03:29 -08:00
|
|
|
outputs: ~[session::OutputExecutable],
|
2013-07-02 12:47:32 -07:00
|
|
|
.. (*session::basic_options()).clone()
|
2013-01-23 11:19:13 +10:00
|
|
|
};
|
2014-01-14 01:31:05 +09:00
|
|
|
let input = driver::FileInput(script.clone());
|
2013-08-30 10:55:24 -07:00
|
|
|
let sess = driver::build_session(options,
|
|
|
|
@diagnostic::DefaultEmitter as
|
|
|
|
@diagnostic::Emitter);
|
2013-08-13 17:06:27 -07:00
|
|
|
let cfg = driver::build_configuration(sess);
|
2013-07-26 23:49:38 -07:00
|
|
|
let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
|
2013-12-25 11:10:33 -07:00
|
|
|
let loader = &mut Loader::new(sess);
|
|
|
|
let crate_and_map = driver::phase_2_configure_and_expand(sess,
|
|
|
|
cfg.clone(),
|
|
|
|
loader,
|
|
|
|
crate);
|
2013-04-22 17:54:54 -07:00
|
|
|
let work_dir = build_pkg_id_in_workspace(id, workspace);
|
2013-01-16 21:59:37 +10:00
|
|
|
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Returning package script with id {}", id.to_str());
|
2013-01-16 21:59:37 +10:00
|
|
|
|
2013-04-11 17:43:02 -07:00
|
|
|
PkgScript {
|
2013-01-16 21:59:37 +10:00
|
|
|
id: id,
|
2013-09-06 20:29:16 -07:00
|
|
|
input: script,
|
2013-01-23 11:19:13 +10:00
|
|
|
sess: sess,
|
|
|
|
cfg: cfg,
|
2014-01-06 14:00:46 +02:00
|
|
|
crate_and_map: Some(crate_and_map),
|
2013-04-11 17:43:02 -07:00
|
|
|
build_dir: work_dir
|
|
|
|
}
|
2013-01-16 21:59:37 +10:00
|
|
|
}
|
|
|
|
|
2013-09-30 22:39:50 -07:00
|
|
|
fn build_custom(&mut self, exec: &mut workcache::Exec) -> ~str {
|
2013-01-23 11:19:13 +10:00
|
|
|
let sess = self.sess;
|
2013-04-11 17:43:02 -07:00
|
|
|
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Working directory = {}", self.build_dir.display());
|
2013-04-11 17:43:02 -07:00
|
|
|
// Collect together any user-defined commands in the package script
|
2014-01-06 14:00:46 +02:00
|
|
|
let (crate, ast_map) = self.crate_and_map.take_unwrap();
|
|
|
|
let crate = util::ready_crate(sess, crate);
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Building output filenames with script name {}",
|
2014-01-14 01:31:05 +09:00
|
|
|
driver::source_name(&driver::FileInput(self.input.clone())));
|
2013-10-05 19:49:32 -07:00
|
|
|
let exe = self.build_dir.join("pkg" + util::exe_suffix());
|
2013-07-31 13:47:32 -07:00
|
|
|
util::compile_crate_from_input(&self.input,
|
2013-09-06 20:29:16 -07:00
|
|
|
exec,
|
2013-09-10 11:41:05 -07:00
|
|
|
Nothing,
|
2013-07-31 13:47:32 -07:00
|
|
|
&self.build_dir,
|
|
|
|
sess,
|
2013-12-09 14:56:53 -07:00
|
|
|
crate,
|
2014-01-06 14:00:46 +02:00
|
|
|
ast_map,
|
2013-12-09 14:56:53 -07:00
|
|
|
Main);
|
2013-09-06 20:29:16 -07:00
|
|
|
// Discover the output
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2013-09-30 22:39:50 -07:00
|
|
|
// 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 <what>
|
|
|
|
/// is the command to pass to it (e.g., "build", "clean", "install")
|
|
|
|
/// Returns a pair of an exit code and list of configs (obtained by
|
2013-12-12 09:07:43 -05:00
|
|
|
/// 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)> {
|
2013-09-30 22:39:50 -07:00
|
|
|
debug!("Running program: {} {} {}", exe.as_str().unwrap().to_owned(),
|
|
|
|
sysroot.display(), "install");
|
2013-07-31 13:47:32 -07:00
|
|
|
// FIXME #7401 should support commands besides `install`
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2013-12-12 09:07:43 -05:00
|
|
|
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
|
2013-12-23 17:30:49 +01:00
|
|
|
let cfgs = str::from_utf8(output.output).unwrap().words()
|
2013-12-12 09:07:43 -05:00
|
|
|
.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
|
|
|
|
}
|
2013-04-11 17:43:02 -07:00
|
|
|
}
|
2013-01-23 11:19:13 +10:00
|
|
|
}
|
2013-01-16 21:59:37 +10:00
|
|
|
}
|
|
|
|
|
2013-06-14 18:21:47 -07:00
|
|
|
pub trait CtxMethods {
|
2014-01-05 10:17:51 +01:00
|
|
|
fn run(&self, cmd: Command, args: ~[~str]);
|
2013-06-14 18:21:47 -07:00
|
|
|
fn do_cmd(&self, _cmd: &str, _pkgname: &str);
|
2013-09-26 16:04:49 -07:00
|
|
|
/// Returns a pair of the selected package ID, and the destination workspace
|
2013-12-28 15:24:15 -05:00
|
|
|
fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)>;
|
2013-08-28 14:52:37 -07:00
|
|
|
/// Returns the destination workspace
|
2013-10-05 16:40:01 -04:00
|
|
|
fn build(&self, pkg_src: &mut PkgSrc, what: &WhatToBuild);
|
2013-12-28 15:24:15 -05:00
|
|
|
fn clean(&self, workspace: &Path, id: &CrateId);
|
2013-06-14 18:21:47 -07:00
|
|
|
fn info(&self);
|
2013-09-08 22:00:49 -07:00
|
|
|
/// Returns a pair. First component is a list of installed paths,
|
|
|
|
/// second is a list of declared and discovered inputs
|
2013-09-16 19:27:09 -07:00
|
|
|
fn install(&self, src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]);
|
2013-09-06 20:29:16 -07:00
|
|
|
/// Returns a list of installed files
|
2013-09-12 16:13:30 -07:00
|
|
|
fn install_no_build(&self,
|
2013-09-26 12:15:54 -07:00
|
|
|
build_workspace: &Path,
|
|
|
|
build_inputs: &[Path],
|
2013-09-12 16:13:30 -07:00
|
|
|
target_workspace: &Path,
|
2013-12-28 15:24:15 -05:00
|
|
|
id: &CrateId) -> ~[~str];
|
2013-06-14 18:21:47 -07:00
|
|
|
fn prefer(&self, _id: &str, _vers: Option<~str>);
|
2013-12-28 15:24:15 -05:00
|
|
|
fn test(&self, id: &CrateId, workspace: &Path);
|
2013-06-14 18:21:47 -07:00
|
|
|
fn uninstall(&self, _id: &str, _vers: Option<~str>);
|
|
|
|
fn unprefer(&self, _id: &str, _vers: Option<~str>);
|
2013-09-16 14:59:34 -07:00
|
|
|
fn init(&self);
|
2013-06-14 18:21:47 -07:00
|
|
|
}
|
|
|
|
|
2013-09-08 22:00:49 -07:00
|
|
|
impl CtxMethods for BuildContext {
|
2013-12-28 15:24:15 -05:00
|
|
|
fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)> {
|
2013-10-05 22:14:10 -04:00
|
|
|
let cwd = os::getcwd();
|
|
|
|
|
2013-09-26 16:04:49 -07:00
|
|
|
if args.len() < 1 {
|
|
|
|
match cwd_to_workspace() {
|
2014-01-08 14:09:48 +09:00
|
|
|
None if dir_has_crate_file(&cwd) => {
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-01-11 00:22:06 +09:00
|
|
|
let crateid = from_str(cwd.filename_str().unwrap()).expect("valid crate id");
|
2013-12-28 15:24:15 -05:00
|
|
|
let mut pkg_src = PkgSrc::new(cwd, default_workspace(), true, crateid);
|
2013-10-05 16:40:01 -04:00
|
|
|
self.build(&mut pkg_src, what);
|
|
|
|
match pkg_src {
|
|
|
|
PkgSrc { destination_workspace: ws,
|
2013-11-28 12:22:53 -08:00
|
|
|
id: id, .. } => {
|
2013-10-05 16:40:01 -04:00
|
|
|
Some((id, ws))
|
|
|
|
}
|
|
|
|
}
|
2013-09-26 16:04:49 -07:00
|
|
|
}
|
|
|
|
None => { usage::build(); None }
|
2013-12-28 15:24:15 -05:00
|
|
|
Some((ws, crateid)) => {
|
|
|
|
let mut pkg_src = PkgSrc::new(ws.clone(), ws, false, crateid);
|
2013-10-05 16:40:01 -04:00
|
|
|
self.build(&mut pkg_src, what);
|
|
|
|
match pkg_src {
|
|
|
|
PkgSrc { destination_workspace: ws,
|
2013-11-28 12:22:53 -08:00
|
|
|
id: id, .. } => {
|
2013-10-05 16:40:01 -04:00
|
|
|
Some((id, ws))
|
|
|
|
}
|
|
|
|
}
|
2013-09-26 16:04:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// The package id is presumed to be the first command-line
|
|
|
|
// argument
|
2014-01-11 00:22:06 +09:00
|
|
|
let crateid = from_str(args[0]).expect("valid crate id");
|
2013-10-05 16:40:01 -04:00
|
|
|
let mut dest_ws = default_workspace();
|
2013-12-28 15:24:15 -05:00
|
|
|
each_pkg_parent_workspace(&self.context, &crateid, |workspace| {
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("found pkg {} in workspace {}, trying to build",
|
2013-12-28 15:24:15 -05:00
|
|
|
crateid.to_str(), workspace.display());
|
2013-10-05 16:40:01 -04:00
|
|
|
dest_ws = determine_destination(os::getcwd(),
|
|
|
|
self.context.use_rust_path_hack,
|
|
|
|
workspace);
|
2013-10-15 23:32:14 -07:00
|
|
|
let mut pkg_src = PkgSrc::new(workspace.clone(), dest_ws.clone(),
|
2013-12-28 15:24:15 -05:00
|
|
|
false, crateid.clone());
|
2013-10-15 23:32:14 -07:00
|
|
|
self.build(&mut pkg_src, what);
|
2013-09-26 16:04:49 -07:00
|
|
|
true
|
2013-11-21 15:42:55 -08:00
|
|
|
});
|
2013-09-26 16:04:49 -07:00
|
|
|
// 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
|
2013-12-28 15:24:15 -05:00
|
|
|
Some((crateid, dest_ws))
|
2013-09-26 16:04:49 -07:00
|
|
|
}
|
|
|
|
}
|
2014-01-08 14:09:48 +09:00
|
|
|
|
2014-01-05 10:17:51 +01:00
|
|
|
fn run(&self, cmd: Command, args: ~[~str]) {
|
2013-10-05 22:14:10 -04:00
|
|
|
let cwd = os::getcwd();
|
2013-01-17 19:05:19 +10:00
|
|
|
match cmd {
|
2014-01-05 10:17:51 +01:00
|
|
|
BuildCmd => {
|
2013-09-30 22:39:50 -07:00
|
|
|
self.build_args(args, &WhatToBuild::new(MaybeCustom, Everything));
|
2013-01-23 11:19:13 +10:00
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
CleanCmd => {
|
2013-04-17 15:47:24 -07:00
|
|
|
if args.len() < 1 {
|
2013-08-22 19:18:38 -07:00
|
|
|
match cwd_to_workspace() {
|
|
|
|
None => { usage::clean(); return }
|
|
|
|
// tjc: Maybe clean should clean all the packages in the
|
|
|
|
// current workspace, though?
|
2013-12-28 15:24:15 -05:00
|
|
|
Some((ws, crateid)) => self.clean(&ws, &crateid)
|
2013-06-26 17:42:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// The package id is presumed to be the first command-line
|
|
|
|
// argument
|
2014-01-11 00:22:06 +09:00
|
|
|
let crateid = from_str(args[0]).expect("valid crate id");
|
2013-12-28 15:24:15 -05:00
|
|
|
self.clean(&cwd, &crateid); // tjc: should use workspace, not cwd
|
2013-04-17 15:47:24 -07:00
|
|
|
}
|
2013-01-23 11:19:13 +10:00
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
DoCmd => {
|
2013-04-11 17:43:02 -07:00
|
|
|
if args.len() < 2 {
|
2013-01-23 12:41:11 +10:00
|
|
|
return usage::do_cmd();
|
|
|
|
}
|
|
|
|
|
2013-07-02 12:47:32 -07:00
|
|
|
self.do_cmd(args[0].clone(), args[1].clone());
|
2013-01-23 12:41:11 +10:00
|
|
|
}
|
2014-01-11 00:34:09 -05:00
|
|
|
HelpCmd => {
|
|
|
|
if args.len() != 1 {
|
|
|
|
return usage::general();
|
|
|
|
}
|
|
|
|
match FromStr::from_str(args[0]) {
|
|
|
|
Some(help_cmd) => usage::usage_for_command(help_cmd),
|
|
|
|
None => {
|
|
|
|
usage::general();
|
|
|
|
error(format!("{} is not a recognized command", args[0]))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
InfoCmd => {
|
2013-01-26 18:35:10 +10:00
|
|
|
self.info();
|
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
InstallCmd => {
|
2013-09-06 20:29:16 -07:00
|
|
|
if args.len() < 1 {
|
2013-08-22 19:18:38 -07:00
|
|
|
match cwd_to_workspace() {
|
2013-10-05 22:14:10 -04:00
|
|
|
None if dir_has_crate_file(&cwd) => {
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2013-10-05 22:14:10 -04:00
|
|
|
|
2013-12-28 15:24:15 -05:00
|
|
|
let inferred_crateid =
|
2014-01-11 00:22:06 +09:00
|
|
|
from_str(cwd.filename_str().unwrap()).expect("valid crate id");
|
2013-10-05 16:40:01 -04:00
|
|
|
self.install(PkgSrc::new(cwd, default_workspace(),
|
2013-12-28 15:24:15 -05:00
|
|
|
true, inferred_crateid),
|
2013-09-30 22:39:50 -07:00
|
|
|
&WhatToBuild::new(MaybeCustom, Everything));
|
2013-08-28 14:52:37 -07:00
|
|
|
}
|
|
|
|
None => { usage::install(); return; }
|
2013-12-28 15:24:15 -05:00
|
|
|
Some((ws, crateid)) => {
|
|
|
|
let pkg_src = PkgSrc::new(ws.clone(), ws.clone(), false, crateid);
|
2013-09-30 22:39:50 -07:00
|
|
|
self.install(pkg_src, &WhatToBuild::new(MaybeCustom,
|
|
|
|
Everything));
|
2013-09-06 20:29:16 -07:00
|
|
|
}
|
|
|
|
}
|
2013-06-14 18:16:24 -07:00
|
|
|
}
|
|
|
|
else {
|
2013-06-26 17:42:24 -07:00
|
|
|
// The package id is presumed to be the first command-line
|
|
|
|
// argument
|
2014-01-11 00:22:06 +09:00
|
|
|
let crateid = from_str(args[0]).expect("valid crate id");
|
2013-12-28 15:24:15 -05:00
|
|
|
let workspaces = pkg_parent_workspaces(&self.context, &crateid);
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("package ID = {}, found it in {:?} workspaces",
|
2013-12-28 15:24:15 -05:00
|
|
|
crateid.to_str(), workspaces.len());
|
2013-06-26 17:42:24 -07:00
|
|
|
if workspaces.is_empty() {
|
2013-10-05 16:40:01 -04:00
|
|
|
let d = default_workspace();
|
2013-12-28 15:24:15 -05:00
|
|
|
let src = PkgSrc::new(d.clone(), d, false, crateid.clone());
|
2013-09-30 22:39:50 -07:00
|
|
|
self.install(src, &WhatToBuild::new(MaybeCustom, Everything));
|
2013-06-26 17:42:24 -07:00
|
|
|
}
|
|
|
|
else {
|
2013-09-06 20:29:16 -07:00
|
|
|
for workspace in workspaces.iter() {
|
2013-10-05 16:40:01 -04:00
|
|
|
let dest = determine_destination(os::getcwd(),
|
|
|
|
self.context.use_rust_path_hack,
|
|
|
|
workspace);
|
2013-09-06 20:29:16 -07:00
|
|
|
let src = PkgSrc::new(workspace.clone(),
|
2013-10-05 16:40:01 -04:00
|
|
|
dest,
|
2013-09-08 22:00:49 -07:00
|
|
|
self.context.use_rust_path_hack,
|
2013-12-28 15:24:15 -05:00
|
|
|
crateid.clone());
|
2013-09-30 22:39:50 -07:00
|
|
|
self.install(src, &WhatToBuild::new(MaybeCustom, Everything));
|
2013-08-02 02:17:20 -04:00
|
|
|
};
|
2013-06-14 18:16:24 -07:00
|
|
|
}
|
2013-04-24 17:37:59 -07:00
|
|
|
}
|
2013-01-18 18:31:43 +10:00
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
ListCmd => {
|
2014-01-09 21:06:55 +11:00
|
|
|
println!("Installed packages:");
|
2013-11-21 15:42:55 -08:00
|
|
|
installed_packages::list_installed_packages(|pkg_id| {
|
2014-01-11 00:22:06 +09:00
|
|
|
println!("{}", pkg_id.path);
|
2013-08-02 02:17:20 -04:00
|
|
|
true
|
2013-11-21 15:42:55 -08:00
|
|
|
});
|
2013-07-11 18:20:31 -07:00
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
PreferCmd => {
|
2013-01-18 18:31:43 +10:00
|
|
|
if args.len() < 1 {
|
2014-01-11 11:48:54 -05:00
|
|
|
return usage::prefer();
|
2013-01-18 18:31:43 +10:00
|
|
|
}
|
|
|
|
|
2013-05-14 17:46:52 -07:00
|
|
|
self.prefer(args[0], None);
|
2013-01-23 11:19:13 +10:00
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
TestCmd => {
|
2013-09-26 16:04:49 -07:00
|
|
|
// Build the test executable
|
2013-09-30 22:39:50 -07:00
|
|
|
let maybe_id_and_workspace = self.build_args(args,
|
|
|
|
&WhatToBuild::new(MaybeCustom, Tests));
|
2013-09-26 16:04:49 -07:00
|
|
|
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.");
|
|
|
|
}
|
|
|
|
}
|
2013-01-18 18:31:43 +10:00
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
InitCmd => {
|
2013-09-16 14:59:34 -07:00
|
|
|
if args.len() != 0 {
|
|
|
|
return usage::init();
|
|
|
|
} else {
|
|
|
|
self.init();
|
|
|
|
}
|
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
UninstallCmd => {
|
2013-01-18 18:31:43 +10:00
|
|
|
if args.len() < 1 {
|
|
|
|
return usage::uninstall();
|
|
|
|
}
|
|
|
|
|
2014-01-11 00:22:06 +09:00
|
|
|
let crateid = from_str(args[0]).expect("valid crate id");
|
2013-12-28 15:24:15 -05:00
|
|
|
if !installed_packages::package_is_installed(&crateid) {
|
2013-09-27 23:37:25 -07:00
|
|
|
warn(format!("Package {} doesn't seem to be installed! \
|
|
|
|
Doing nothing.", args[0]));
|
2013-07-11 18:20:31 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let rp = rust_path();
|
|
|
|
assert!(!rp.is_empty());
|
2013-12-28 15:24:15 -05:00
|
|
|
each_pkg_parent_workspace(&self.context, &crateid, |workspace| {
|
|
|
|
path_util::uninstall_package_from(workspace, &crateid);
|
2013-09-27 23:37:25 -07:00
|
|
|
note(format!("Uninstalled package {} (was installed in {})",
|
2013-12-28 15:24:15 -05:00
|
|
|
crateid.to_str(), workspace.display()));
|
2013-08-02 02:17:20 -04:00
|
|
|
true
|
2013-11-21 15:42:55 -08:00
|
|
|
});
|
2013-07-11 18:20:31 -07:00
|
|
|
}
|
2013-01-18 18:31:43 +10:00
|
|
|
}
|
2014-01-05 10:17:51 +01:00
|
|
|
UnpreferCmd => {
|
2013-01-18 18:31:43 +10:00
|
|
|
if args.len() < 1 {
|
2013-07-11 18:20:31 -07:00
|
|
|
return usage::unprefer();
|
2013-01-18 18:31:43 +10:00
|
|
|
}
|
|
|
|
|
2013-05-14 17:46:52 -07:00
|
|
|
self.unprefer(args[0], None);
|
2013-01-18 18:31:43 +10:00
|
|
|
}
|
2013-01-23 11:19:13 +10:00
|
|
|
}
|
2013-01-16 21:59:37 +10:00
|
|
|
}
|
|
|
|
|
2013-05-11 22:45:13 -04:00
|
|
|
fn do_cmd(&self, _cmd: &str, _pkgname: &str) {
|
2013-04-22 17:54:54 -07:00
|
|
|
// stub
|
2013-10-21 13:08:31 -07:00
|
|
|
fail!("`do` not yet implemented");
|
2013-01-16 21:59:37 +10:00
|
|
|
}
|
|
|
|
|
2013-10-05 16:40:01 -04:00
|
|
|
fn build(&self, pkg_src: &mut PkgSrc, what_to_build: &WhatToBuild) {
|
|
|
|
use conditions::git_checkout_failed::cond;
|
|
|
|
|
|
|
|
let workspace = pkg_src.source_workspace.clone();
|
2013-12-28 15:24:15 -05:00
|
|
|
let crateid = pkg_src.id.clone();
|
2013-09-06 20:29:16 -07:00
|
|
|
|
2014-01-11 00:22:06 +09:00
|
|
|
let path = crateid.path.as_slice();
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \
|
2013-12-28 15:24:15 -05:00
|
|
|
crateid = {} pkgsrc start_dir = {}", workspace.display(),
|
2014-01-11 00:22:06 +09:00
|
|
|
in_rust_path(&workspace), is_git_dir(&workspace.join(path)),
|
2013-12-28 15:24:15 -05:00
|
|
|
crateid.to_str(), pkg_src.start_dir.display());
|
2013-09-30 22:39:50 -07:00
|
|
|
debug!("build: what to build = {:?}", what_to_build);
|
2013-05-02 13:09:28 -07:00
|
|
|
|
2013-07-09 18:28:00 -07:00
|
|
|
// 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
|
2014-01-11 00:22:06 +09:00
|
|
|
if !in_rust_path(&workspace) && is_git_dir(&workspace.join(path)) {
|
2013-10-05 19:49:32 -07:00
|
|
|
let mut out_dir = default_workspace().join("src");
|
2014-01-11 00:22:06 +09:00
|
|
|
out_dir.push(path);
|
|
|
|
let git_result = source_control::safe_git_clone(&workspace.join(path),
|
2013-12-28 15:24:15 -05:00
|
|
|
&crateid.version,
|
2013-10-05 16:40:01 -04:00
|
|
|
&out_dir);
|
|
|
|
match git_result {
|
|
|
|
CheckedOutSources => make_read_only(&out_dir),
|
2014-01-11 00:22:06 +09:00
|
|
|
_ => cond.raise((path.to_owned(), out_dir.clone()))
|
2013-10-05 16:40:01 -04:00
|
|
|
};
|
2013-07-09 18:28:00 -07:00
|
|
|
let default_ws = default_workspace();
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Calling build recursively with {:?} and {:?}", default_ws.display(),
|
2013-12-28 15:24:15 -05:00
|
|
|
crateid.to_str());
|
2013-10-05 16:40:01 -04:00
|
|
|
return self.build(&mut PkgSrc::new(default_ws.clone(),
|
|
|
|
default_ws,
|
|
|
|
false,
|
2013-12-28 15:24:15 -05:00
|
|
|
crateid.clone()), what_to_build);
|
2013-07-09 18:28:00 -07:00
|
|
|
}
|
|
|
|
|
2013-05-02 13:09:28 -07:00
|
|
|
// Is there custom build logic? If so, use it
|
|
|
|
let mut custom = false;
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Package source directory = {}", pkg_src.to_str());
|
2013-09-06 20:29:16 -07:00
|
|
|
let opt = pkg_src.package_script_option();
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Calling pkg_script_option on {:?}", opt);
|
2013-09-30 22:39:50 -07:00
|
|
|
let cfgs = match (pkg_src.package_script_option(), what_to_build.build_type) {
|
|
|
|
(Some(package_script_path), MaybeCustom) => {
|
2013-09-06 20:29:16 -07:00
|
|
|
let sysroot = self.sysroot_to_use();
|
2013-09-30 22:39:50 -07:00
|
|
|
// Build the package script if needed
|
|
|
|
let script_build = format!("build_package_script({})",
|
|
|
|
package_script_path.display());
|
2013-11-21 15:42:55 -08:00
|
|
|
let pkg_exe = self.workcache_context.with_prep(script_build, |prep| {
|
2013-09-30 22:39:50 -07:00
|
|
|
let subsysroot = sysroot.clone();
|
|
|
|
let psp = package_script_path.clone();
|
|
|
|
let ws = workspace.clone();
|
2013-12-28 15:24:15 -05:00
|
|
|
let pid = crateid.clone();
|
2013-11-21 23:36:52 -08:00
|
|
|
prep.exec(proc(exec) {
|
2013-09-30 22:39:50 -07:00
|
|
|
let mut pscript = PkgScript::parse(subsysroot.clone(),
|
|
|
|
psp.clone(),
|
|
|
|
&ws,
|
|
|
|
&pid);
|
|
|
|
pscript.build_custom(exec)
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
|
|
|
});
|
2013-09-30 22:39:50 -07:00
|
|
|
// We always *run* the package script
|
2013-12-12 09:07:43 -05:00
|
|
|
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")
|
|
|
|
}
|
2013-05-02 13:09:28 -07:00
|
|
|
}
|
|
|
|
}
|
2013-09-30 22:39:50 -07:00
|
|
|
(Some(_), Inferred) => {
|
|
|
|
debug!("There is a package script, but we're ignoring it");
|
|
|
|
~[]
|
|
|
|
}
|
|
|
|
(None, _) => {
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("No package script, continuing");
|
2013-05-02 13:09:28 -07:00
|
|
|
~[]
|
|
|
|
}
|
2013-09-10 11:41:05 -07:00
|
|
|
} + self.context.cfgs;
|
2013-05-02 13:09:28 -07:00
|
|
|
|
|
|
|
// If there was a package script, it should have finished
|
|
|
|
// the build already. Otherwise...
|
|
|
|
if !custom {
|
2013-09-30 22:39:50 -07:00
|
|
|
match what_to_build.sources {
|
2013-09-16 19:27:09 -07:00
|
|
|
// Find crates inside the workspace
|
2013-09-30 22:39:50 -07:00
|
|
|
Everything => pkg_src.find_crates(),
|
2013-09-26 16:04:49 -07:00
|
|
|
// Find only tests
|
2013-12-03 19:15:12 -08:00
|
|
|
Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::new(s)) }),
|
2013-09-16 19:27:09 -07:00
|
|
|
// Don't infer any crates -- just build the one that was requested
|
2013-09-30 22:39:50 -07:00
|
|
|
JustOne(ref p) => {
|
2013-09-16 19:27:09 -07:00
|
|
|
// We expect that p is relative to the package source's start directory,
|
|
|
|
// so check that assumption
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("JustOne: p = {}", p.display());
|
2013-10-25 17:04:37 -07:00
|
|
|
assert!(pkg_src.start_dir.join(p).exists());
|
2013-09-16 19:27:09 -07:00
|
|
|
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 {
|
2013-09-26 17:21:59 -07:00
|
|
|
warn(format!("Not building any crates for dependency {}", p.display()));
|
2013-10-05 16:40:01 -04:00
|
|
|
return;
|
2013-09-16 19:27:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-05-02 13:09:28 -07:00
|
|
|
// Build it!
|
2013-09-30 22:39:50 -07:00
|
|
|
pkg_src.build(self, cfgs, []);
|
2013-05-02 13:09:28 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-28 15:24:15 -05:00
|
|
|
fn clean(&self, workspace: &Path, id: &CrateId) {
|
2013-04-17 15:47:24 -07:00
|
|
|
// Could also support a custom build hook in the pkg
|
|
|
|
// script for cleaning files rustpkg doesn't know about.
|
|
|
|
// Do something reasonable for now
|
|
|
|
|
2013-04-22 17:54:54 -07:00
|
|
|
let dir = build_pkg_id_in_workspace(id, workspace);
|
2013-09-27 23:37:25 -07:00
|
|
|
note(format!("Cleaning package {} (removing directory {})",
|
2013-09-26 17:21:59 -07:00
|
|
|
id.to_str(), dir.display()));
|
2013-10-25 17:04:37 -07:00
|
|
|
if dir.exists() {
|
2013-10-31 15:15:30 -07:00
|
|
|
fs::rmdir_recursive(&dir);
|
2013-09-26 17:21:59 -07:00
|
|
|
note(format!("Removed directory {}", dir.display()));
|
2013-04-17 15:47:24 -07:00
|
|
|
}
|
|
|
|
|
2013-09-27 23:37:25 -07:00
|
|
|
note(format!("Cleaned package {}", id.to_str()));
|
2013-01-16 21:59:37 +10:00
|
|
|
}
|
|
|
|
|
2013-02-04 17:12:31 -08:00
|
|
|
fn info(&self) {
|
2013-04-11 17:43:02 -07:00
|
|
|
// stub
|
2013-10-21 13:08:31 -07:00
|
|
|
fail!("info not yet implemented");
|
2013-01-26 18:35:10 +10:00
|
|
|
}
|
|
|
|
|
2013-09-16 19:27:09 -07:00
|
|
|
fn install(&self, mut pkg_src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]) {
|
|
|
|
|
|
|
|
let id = pkg_src.id.clone();
|
|
|
|
|
|
|
|
let mut installed_files = ~[];
|
2013-10-05 16:40:01 -04:00
|
|
|
let mut inputs = ~[];
|
2013-09-26 12:15:54 -07:00
|
|
|
let mut build_inputs = ~[];
|
2013-10-05 16:40:01 -04:00
|
|
|
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Installing package source: {}", pkg_src.to_str());
|
2013-09-16 19:27:09 -07:00
|
|
|
|
|
|
|
// workcache only knows about *crates*. Building a package
|
|
|
|
// just means inferring all the crates in it, then building each one.
|
2013-10-05 16:40:01 -04:00
|
|
|
self.build(&mut pkg_src, what);
|
2013-09-16 19:27:09 -07:00
|
|
|
|
2013-09-30 22:39:50 -07:00
|
|
|
debug!("Done building package source {}", pkg_src.to_str());
|
|
|
|
|
2013-09-16 19:27:09 -07:00
|
|
|
let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(),
|
|
|
|
pkg_src.tests.clone(), pkg_src.benchs.clone()];
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("In declare inputs for {}", id.to_str());
|
2013-09-16 19:27:09 -07:00
|
|
|
for cs in to_do.iter() {
|
|
|
|
for c in cs.iter() {
|
2013-10-02 18:17:46 -07:00
|
|
|
let path = pkg_src.start_dir.join(&c.file);
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Recording input: {}", path.display());
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
|
|
|
inputs.push((~"file", path.as_str().unwrap().to_owned()));
|
2013-09-26 12:15:54 -07:00
|
|
|
build_inputs.push(path);
|
2013-09-06 20:29:16 -07:00
|
|
|
}
|
2013-09-16 19:27:09 -07:00
|
|
|
}
|
2013-10-05 16:40:01 -04:00
|
|
|
|
|
|
|
let result = self.install_no_build(pkg_src.build_workspace(),
|
2013-09-26 12:15:54 -07:00
|
|
|
build_inputs,
|
2013-10-05 16:40:01 -04:00
|
|
|
&pkg_src.destination_workspace,
|
2013-12-03 19:15:12 -08:00
|
|
|
&id).map(|s| Path::new(s.as_slice()));
|
2013-09-16 19:27:09 -07:00
|
|
|
installed_files = installed_files + result;
|
2013-10-05 16:40:01 -04:00
|
|
|
note(format!("Installed package {} to {}",
|
|
|
|
id.to_str(),
|
2013-09-26 17:21:59 -07:00
|
|
|
pkg_src.destination_workspace.display()));
|
2013-09-16 19:27:09 -07:00
|
|
|
(installed_files, inputs)
|
2013-06-25 22:26:22 -07:00
|
|
|
}
|
|
|
|
|
2013-09-16 19:27:09 -07:00
|
|
|
// again, working around lack of Encodable for Path
|
2013-09-12 16:13:30 -07:00
|
|
|
fn install_no_build(&self,
|
2013-10-05 16:40:01 -04:00
|
|
|
build_workspace: &Path,
|
2013-09-26 12:15:54 -07:00
|
|
|
build_inputs: &[Path],
|
2013-09-12 16:13:30 -07:00
|
|
|
target_workspace: &Path,
|
2013-12-28 15:24:15 -05:00
|
|
|
id: &CrateId) -> ~[~str] {
|
2013-05-02 13:09:28 -07:00
|
|
|
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("install_no_build: assuming {} comes from {} with target {}",
|
2013-10-15 23:32:14 -07:00
|
|
|
id.to_str(), build_workspace.display(), target_workspace.display());
|
2013-10-05 16:40:01 -04:00
|
|
|
|
2013-05-02 13:09:28 -07:00
|
|
|
// Now copy stuff into the install dirs
|
2013-10-05 16:40:01 -04:00
|
|
|
let maybe_executable = built_executable_in_workspace(id, build_workspace);
|
|
|
|
let maybe_library = built_library_in_workspace(id, build_workspace);
|
2013-09-12 16:13:30 -07:00
|
|
|
let target_exec = target_executable_in_workspace(id, target_workspace);
|
2013-09-20 02:08:47 -04:00
|
|
|
let target_lib = maybe_library.as_ref()
|
|
|
|
.map(|_| target_library_in_workspace(id, target_workspace));
|
2013-05-02 13:09:28 -07:00
|
|
|
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("target_exec = {} target_lib = {:?} \
|
2013-09-27 23:37:25 -07:00
|
|
|
maybe_executable = {:?} maybe_library = {:?}",
|
2013-09-26 17:21:59 -07:00
|
|
|
target_exec.display(), target_lib,
|
2013-05-10 19:00:51 -07:00
|
|
|
maybe_executable, maybe_library);
|
|
|
|
|
2014-01-11 00:22:06 +09:00
|
|
|
let install_tag = format!("install({}-{})", id.path, id.version_or_default());
|
|
|
|
self.workcache_context.with_prep(install_tag, |prep| {
|
2013-09-16 19:27:09 -07:00
|
|
|
for ee in maybe_executable.iter() {
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2013-09-16 19:27:09 -07:00
|
|
|
prep.declare_input("binary",
|
2013-09-26 17:21:59 -07:00
|
|
|
ee.as_str().unwrap(),
|
2013-09-16 19:27:09 -07:00
|
|
|
workcache_support::digest_only_date(ee));
|
2013-05-02 13:09:28 -07:00
|
|
|
}
|
2013-09-16 19:27:09 -07:00
|
|
|
for ll in maybe_library.iter() {
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2013-09-16 19:27:09 -07:00
|
|
|
prep.declare_input("binary",
|
2013-09-26 17:21:59 -07:00
|
|
|
ll.as_str().unwrap(),
|
2013-09-16 19:27:09 -07:00
|
|
|
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();
|
2013-09-26 12:15:54 -07:00
|
|
|
let sub_build_inputs = build_inputs.to_owned();
|
2013-11-21 23:36:52 -08:00
|
|
|
prep.exec(proc(exe_thing) {
|
2013-09-16 19:27:09 -07:00
|
|
|
let mut outputs = ~[];
|
2013-09-26 12:15:54 -07:00
|
|
|
// Declare all the *inputs* to the declared input too, as inputs
|
|
|
|
for executable in subex.iter() {
|
|
|
|
exe_thing.discover_input("binary",
|
2013-10-02 18:17:46 -07:00
|
|
|
executable.as_str().unwrap().to_owned(),
|
2013-09-26 12:15:54 -07:00
|
|
|
workcache_support::digest_only_date(executable));
|
|
|
|
}
|
|
|
|
for library in sublib.iter() {
|
|
|
|
exe_thing.discover_input("binary",
|
2013-10-02 18:17:46 -07:00
|
|
|
library.as_str().unwrap().to_owned(),
|
2013-09-26 12:15:54 -07:00
|
|
|
workcache_support::digest_only_date(library));
|
|
|
|
}
|
|
|
|
|
|
|
|
for transitive_dependency in sub_build_inputs.iter() {
|
|
|
|
exe_thing.discover_input(
|
|
|
|
"file",
|
2013-10-02 18:17:46 -07:00
|
|
|
transitive_dependency.as_str().unwrap().to_owned(),
|
2013-09-26 12:15:54 -07:00
|
|
|
workcache_support::digest_file_with_date(transitive_dependency));
|
|
|
|
}
|
|
|
|
|
2013-09-16 19:27:09 -07:00
|
|
|
|
|
|
|
for exec in subex.iter() {
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display());
|
2013-10-31 15:15:30 -07:00
|
|
|
fs::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX);
|
|
|
|
fs::copy(exec, &sub_target_ex);
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2013-09-16 19:27:09 -07:00
|
|
|
exe_thing.discover_output("binary",
|
2013-09-26 17:21:59 -07:00
|
|
|
sub_target_ex.as_str().unwrap(),
|
2013-09-16 19:27:09 -07:00
|
|
|
workcache_support::digest_only_date(&sub_target_ex));
|
2013-09-26 17:21:59 -07:00
|
|
|
outputs.push(sub_target_ex.as_str().unwrap().to_owned());
|
2013-09-16 19:27:09 -07:00
|
|
|
}
|
|
|
|
for lib in sublib.iter() {
|
2013-09-26 17:21:59 -07:00
|
|
|
let mut target_lib = sub_target_lib
|
2013-09-27 23:37:25 -07:00
|
|
|
.clone().expect(format!("I built {} but apparently \
|
2013-09-26 17:21:59 -07:00
|
|
|
didn't install it!", lib.display()));
|
2013-10-15 23:32:14 -07:00
|
|
|
target_lib.set_filename(lib.filename().expect("weird target lib"));
|
2013-10-31 15:15:30 -07:00
|
|
|
fs::mkdir_recursive(&target_lib.dir_path(), io::UserRWX);
|
|
|
|
fs::copy(lib, &target_lib);
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("3. discovering output {}", target_lib.display());
|
2013-09-16 19:27:09 -07:00
|
|
|
exe_thing.discover_output("binary",
|
2013-09-26 17:21:59 -07:00
|
|
|
target_lib.as_str().unwrap(),
|
2013-09-16 19:27:09 -07:00
|
|
|
workcache_support::digest_only_date(&target_lib));
|
2013-09-26 17:21:59 -07:00
|
|
|
outputs.push(target_lib.as_str().unwrap().to_owned());
|
2013-09-16 19:27:09 -07:00
|
|
|
}
|
|
|
|
outputs
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
|
|
|
})
|
2013-01-16 21:59:37 +10:00
|
|
|
}
|
|
|
|
|
2013-05-14 17:46:52 -07:00
|
|
|
fn prefer(&self, _id: &str, _vers: Option<~str>) {
|
2013-10-21 13:08:31 -07:00
|
|
|
fail!("prefer not yet implemented");
|
2013-01-17 19:05:19 +10:00
|
|
|
}
|
2013-01-16 21:59:37 +10:00
|
|
|
|
2013-12-28 15:24:15 -05:00
|
|
|
fn test(&self, crateid: &CrateId, workspace: &Path) {
|
|
|
|
match built_test_in_workspace(crateid, workspace) {
|
2013-09-26 16:04:49 -07:00
|
|
|
Some(test_exec) => {
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("test: test_exec = {}", test_exec.display());
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2013-12-12 09:07:43 -05:00
|
|
|
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())
|
2013-11-03 15:23:34 -08:00
|
|
|
}
|
2013-09-26 16:04:49 -07:00
|
|
|
}
|
|
|
|
None => {
|
2013-09-27 23:37:25 -07:00
|
|
|
error(format!("Internal error: test executable for package ID {} in workspace {} \
|
2013-09-26 16:04:49 -07:00
|
|
|
wasn't built! Please report this as a bug.",
|
2013-12-28 15:24:15 -05:00
|
|
|
crateid.to_str(), workspace.display()));
|
2013-09-26 16:04:49 -07:00
|
|
|
}
|
|
|
|
}
|
2013-01-16 21:59:37 +10:00
|
|
|
}
|
|
|
|
|
2013-09-16 14:59:34 -07:00
|
|
|
fn init(&self) {
|
2013-12-03 19:15:12 -08:00
|
|
|
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);
|
2013-09-16 14:59:34 -07:00
|
|
|
}
|
|
|
|
|
2013-05-14 17:46:52 -07:00
|
|
|
fn uninstall(&self, _id: &str, _vers: Option<~str>) {
|
2013-10-21 13:08:31 -07:00
|
|
|
fail!("uninstall not yet implemented");
|
2013-01-17 19:05:19 +10:00
|
|
|
}
|
2013-01-16 21:59:37 +10:00
|
|
|
|
2013-05-14 17:46:52 -07:00
|
|
|
fn unprefer(&self, _id: &str, _vers: Option<~str>) {
|
2013-10-21 13:08:31 -07:00
|
|
|
fail!("unprefer not yet implemented");
|
2013-01-16 21:59:37 +10:00
|
|
|
}
|
|
|
|
}
|
2013-01-15 23:57:03 +10:00
|
|
|
|
2013-01-14 20:55:47 +10:00
|
|
|
pub fn main() {
|
2014-01-09 21:06:55 +11:00
|
|
|
println!("WARNING: The Rust package manager is experimental and may be unstable");
|
2013-09-24 16:34:23 -07:00
|
|
|
os::set_exit_status(main_args(os::args()));
|
2013-08-22 17:41:33 +08:00
|
|
|
}
|
|
|
|
|
2013-09-24 16:34:23 -07:00
|
|
|
pub fn main_args(args: &[~str]) -> int {
|
2013-08-26 15:34:34 -07:00
|
|
|
|
2014-01-05 11:23:39 +01:00
|
|
|
let (command, args, context, supplied_sysroot) = match parse_args(args) {
|
|
|
|
Ok(ParseResult {
|
|
|
|
command: cmd,
|
|
|
|
args: args,
|
|
|
|
context: ctx,
|
|
|
|
sysroot: sroot}) => (cmd, args, ctx, sroot),
|
|
|
|
Err(error_code) => {
|
|
|
|
debug!("Parsing failed. Returning error code {}", error_code);
|
|
|
|
return error_code
|
2013-09-10 11:41:05 -07:00
|
|
|
}
|
|
|
|
};
|
2014-01-05 11:23:39 +01:00
|
|
|
debug!("Finished parsing commandline args {:?}", args);
|
|
|
|
debug!(" Using command: {:?}", command);
|
|
|
|
debug!(" Using args {:?}", args);
|
|
|
|
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);
|
|
|
|
|
|
|
|
let sysroot = match supplied_sysroot {
|
2013-12-03 19:15:12 -08:00
|
|
|
Some(s) => Path::new(s),
|
2013-09-10 11:41:05 -07:00
|
|
|
_ => filesearch::get_or_default_sysroot()
|
|
|
|
};
|
|
|
|
|
2014-01-05 11:23:39 +01:00
|
|
|
debug!("Using sysroot: {}", sysroot.display());
|
2013-09-26 17:21:59 -07:00
|
|
|
let ws = default_workspace();
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("Will store workcache in {}", ws.display());
|
2013-09-16 19:27:09 -07:00
|
|
|
|
|
|
|
// Wrap the rest in task::try in case of a condition failure in a task
|
|
|
|
let result = do task::try {
|
|
|
|
BuildContext {
|
2014-01-05 11:23:39 +01:00
|
|
|
context: context,
|
|
|
|
sysroot: sysroot.clone(), // Currently, only tests override this
|
|
|
|
workcache_context: api::default_context(sysroot.clone(),
|
2013-09-30 22:39:50 -07:00
|
|
|
default_workspace()).workcache_context
|
2014-01-05 11:23:39 +01:00
|
|
|
}.run(command, args.clone())
|
2013-09-16 19:27:09 -07:00
|
|
|
};
|
|
|
|
// FIXME #9262: This is using the same error code for all errors,
|
2013-09-17 18:23:34 -07:00
|
|
|
// and at least one test case succeeds if rustpkg returns COPY_FAILED_CODE,
|
2013-09-16 19:27:09 -07:00
|
|
|
// when actually, it might set the exit code for that even if a different
|
|
|
|
// unhandled condition got raised.
|
2013-09-24 16:34:23 -07:00
|
|
|
if result.is_err() { return COPY_FAILED_CODE; }
|
|
|
|
return 0;
|
2013-01-14 20:55:47 +10:00
|
|
|
}
|