auto merge of #6124 : catamorphism/rust/rustpkg, r=catamorphism
r? @graydon
This commit is contained in:
commit
7d9c638226
@ -772,6 +772,28 @@ pub fn list_dir_path(p: &Path) -> ~[~Path] {
|
||||
list_dir(p).map(|f| ~p.push(*f))
|
||||
}
|
||||
|
||||
/// Removes a directory at the specified path, after removing
|
||||
/// all its contents. Use carefully!
|
||||
pub fn remove_dir_recursive(p: &Path) -> bool {
|
||||
let mut error_happened = false;
|
||||
for walk_dir(p) |inner| {
|
||||
if !error_happened {
|
||||
if path_is_dir(inner) {
|
||||
if !remove_dir_recursive(inner) {
|
||||
error_happened = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if !remove_file(inner) {
|
||||
error_happened = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// Directory should now be empty
|
||||
!error_happened && remove_dir(p)
|
||||
}
|
||||
|
||||
/// Removes a directory at the specified path
|
||||
pub fn remove_dir(p: &Path) -> bool {
|
||||
return rmdir(p);
|
||||
@ -877,6 +899,10 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
|
||||
if istream as uint == 0u {
|
||||
return false;
|
||||
}
|
||||
// Preserve permissions
|
||||
let from_mode = from.get_mode().expect("copy_file: couldn't get permissions \
|
||||
for source file");
|
||||
|
||||
let ostream = do as_c_charp(to.to_str()) |top| {
|
||||
do as_c_charp("w+b") |modebuf| {
|
||||
libc::fopen(top, modebuf)
|
||||
@ -908,6 +934,15 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
|
||||
}
|
||||
fclose(istream);
|
||||
fclose(ostream);
|
||||
|
||||
// Give the new file the old file's permissions
|
||||
unsafe {
|
||||
if do str::as_c_str(to.to_str()) |to_buf| {
|
||||
libc::chmod(to_buf, from_mode as mode_t)
|
||||
} != 0 {
|
||||
return false; // should be a condition...
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
@ -1594,6 +1629,7 @@ mod tests {
|
||||
== buf.len() as size_t))
|
||||
}
|
||||
assert!((libc::fclose(ostream) == (0u as c_int)));
|
||||
let in_mode = in.get_mode();
|
||||
let rs = os::copy_file(&in, &out);
|
||||
if (!os::path_exists(&in)) {
|
||||
fail!(fmt!("%s doesn't exist", in.to_str()));
|
||||
@ -1601,6 +1637,7 @@ mod tests {
|
||||
assert!((rs));
|
||||
let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]);
|
||||
assert!((rslt == 0));
|
||||
assert!(out.get_mode() == in_mode);
|
||||
assert!((remove_file(&in)));
|
||||
assert!((remove_file(&out)));
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &Path)
|
||||
// where rustrt is and we know every rust program needs it
|
||||
let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess));
|
||||
|
||||
let rpaths = get_rpaths(os, &sysroot, output, libs,
|
||||
let rpaths = get_rpaths(os, sysroot, output, libs,
|
||||
sess.opts.target_triple);
|
||||
rpaths_to_flags(rpaths)
|
||||
}
|
||||
|
@ -603,7 +603,7 @@ pub fn build_session_options(binary: @~str,
|
||||
link::output_type_bitcode
|
||||
} else { link::output_type_exe };
|
||||
let sysroot_opt = getopts::opt_maybe_str(matches, ~"sysroot");
|
||||
let sysroot_opt = sysroot_opt.map(|m| Path(*m));
|
||||
let sysroot_opt = sysroot_opt.map(|m| @Path(*m));
|
||||
let target_opt = getopts::opt_maybe_str(matches, ~"target");
|
||||
let target_feature_opt = getopts::opt_maybe_str(matches, ~"target-feature");
|
||||
let save_temps = getopts::opt_present(matches, ~"save-temps");
|
||||
|
@ -125,7 +125,7 @@ pub struct options {
|
||||
output_type: back::link::output_type,
|
||||
addl_lib_search_paths: ~[Path],
|
||||
linker_args: ~[~str],
|
||||
maybe_sysroot: Option<Path>,
|
||||
maybe_sysroot: Option<@Path>,
|
||||
target_triple: ~str,
|
||||
target_feature: ~str,
|
||||
// User-specified cfg meta items. The compiler itself will add additional
|
||||
|
@ -20,41 +20,48 @@ pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
|
||||
}
|
||||
|
||||
pub trait FileSearch {
|
||||
fn sysroot(&self) -> Path;
|
||||
fn lib_search_paths(&self) -> ~[Path];
|
||||
fn sysroot(&self) -> @Path;
|
||||
fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool);
|
||||
fn get_target_lib_path(&self) -> Path;
|
||||
fn get_target_lib_file_path(&self, file: &Path) -> Path;
|
||||
}
|
||||
|
||||
pub fn mk_filesearch(maybe_sysroot: &Option<Path>,
|
||||
pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
|
||||
target_triple: &str,
|
||||
addl_lib_search_paths: ~[Path])
|
||||
-> @FileSearch {
|
||||
struct FileSearchImpl {
|
||||
sysroot: Path,
|
||||
sysroot: @Path,
|
||||
addl_lib_search_paths: ~[Path],
|
||||
target_triple: ~str
|
||||
}
|
||||
impl FileSearch for FileSearchImpl {
|
||||
fn sysroot(&self) -> Path { /*bad*/copy self.sysroot }
|
||||
fn lib_search_paths(&self) -> ~[Path] {
|
||||
let mut paths = /*bad*/copy self.addl_lib_search_paths;
|
||||
fn sysroot(&self) -> @Path { self.sysroot }
|
||||
fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) {
|
||||
debug!("filesearch: searching additional lib search paths");
|
||||
// a little weird
|
||||
self.addl_lib_search_paths.each(f);
|
||||
|
||||
paths.push(
|
||||
make_target_lib_path(&self.sysroot,
|
||||
self.target_triple));
|
||||
match get_rustpkg_lib_path_nearest() {
|
||||
result::Ok(ref p) => paths.push((/*bad*/copy *p)),
|
||||
result::Err(_) => ()
|
||||
debug!("filesearch: searching target lib path");
|
||||
if !f(&make_target_lib_path(self.sysroot,
|
||||
self.target_triple)) {
|
||||
return;
|
||||
}
|
||||
match get_rustpkg_lib_path() {
|
||||
result::Ok(ref p) => paths.push((/*bad*/copy *p)),
|
||||
result::Err(_) => ()
|
||||
}
|
||||
paths
|
||||
debug!("filesearch: searching rustpkg lib path nearest");
|
||||
if match get_rustpkg_lib_path_nearest() {
|
||||
result::Ok(ref p) => f(p),
|
||||
result::Err(_) => true
|
||||
} {
|
||||
return;
|
||||
}
|
||||
debug!("filesearch: searching rustpkg lib path");
|
||||
match get_rustpkg_lib_path() {
|
||||
result::Ok(ref p) => f(p),
|
||||
result::Err(_) => true
|
||||
};
|
||||
}
|
||||
fn get_target_lib_path(&self) -> Path {
|
||||
make_target_lib_path(&self.sysroot, self.target_triple)
|
||||
make_target_lib_path(self.sysroot, self.target_triple)
|
||||
}
|
||||
fn get_target_lib_file_path(&self, file: &Path) -> Path {
|
||||
self.get_target_lib_path().push_rel(file)
|
||||
@ -72,7 +79,7 @@ pub fn mk_filesearch(maybe_sysroot: &Option<Path>,
|
||||
|
||||
pub fn search<T:Copy>(filesearch: @FileSearch, pick: pick<T>) -> Option<T> {
|
||||
let mut rslt = None;
|
||||
for filesearch.lib_search_paths().each |lib_search_path| {
|
||||
for filesearch.for_each_lib_search_path() |lib_search_path| {
|
||||
debug!("searching %s", lib_search_path.to_str());
|
||||
for os::list_dir_path(lib_search_path).each |path| {
|
||||
debug!("testing %s", path.to_str());
|
||||
@ -108,10 +115,10 @@ fn get_or_default_sysroot() -> Path {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_sysroot(maybe_sysroot: &Option<Path>) -> Path {
|
||||
fn get_sysroot(maybe_sysroot: &Option<@Path>) -> @Path {
|
||||
match *maybe_sysroot {
|
||||
option::Some(ref sr) => (/*bad*/copy *sr),
|
||||
option::None => get_or_default_sysroot()
|
||||
option::Some(sr) => sr,
|
||||
option::None => @get_or_default_sysroot()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,5 +18,13 @@ condition! {
|
||||
}
|
||||
|
||||
condition! {
|
||||
nonexistent_package: (super::PkgId, ~str) -> super::Path;
|
||||
nonexistent_package: (super::PkgId, ~str) -> ();
|
||||
}
|
||||
|
||||
condition! {
|
||||
copy_failed: (super::Path, super::Path) -> ();
|
||||
}
|
||||
|
||||
condition! {
|
||||
missing_pkg_files: (super::PkgId) -> ();
|
||||
}
|
||||
|
@ -13,6 +13,9 @@
|
||||
use core::hashmap::HashMap;
|
||||
|
||||
pub struct Ctx {
|
||||
// Sysroot -- if this is None, uses rustc filesearch's
|
||||
// idea of the default
|
||||
sysroot_opt: Option<@Path>,
|
||||
// I'm not sure what this is for
|
||||
json: bool,
|
||||
// Cache of hashes of things already installed
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
use util::PkgId;
|
||||
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
|
||||
use core::os::mkdir_recursive;
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub enum OutputType { Main, Lib, Bench, Test }
|
||||
@ -23,16 +24,12 @@ pub fn rust_path() -> ~[Path] {
|
||||
~[Path(".")]
|
||||
}
|
||||
|
||||
static u_rwx: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
|
||||
pub static u_rwx: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
|
||||
|
||||
/// Creates a directory that is readable, writeable,
|
||||
/// and executable by the user. Returns true iff creation
|
||||
/// succeeded.
|
||||
pub fn make_dir_rwx(p: &Path) -> bool {
|
||||
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
|
||||
|
||||
os::make_dir(p, u_rwx)
|
||||
}
|
||||
pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, u_rwx) }
|
||||
|
||||
/// Replace all occurrences of '-' in the stem part of path with '_'
|
||||
/// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux
|
||||
@ -70,34 +67,137 @@ pub fn pkgid_src_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
|
||||
result.push(pkgid.path.to_str())
|
||||
}
|
||||
|
||||
/// Figure out what the executable name for <pkgid> in <workspace>'s build
|
||||
/// directory is, and if the file exists, return it.
|
||||
pub fn built_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Option<Path> {
|
||||
let mut result = workspace.push("build");
|
||||
result = result.push_rel(&pkgid.path);
|
||||
// should use a target-specific subdirectory
|
||||
result = mk_output_path(Main, fmt!("%s-%s", pkgid.path.to_str(), pkgid.version.to_str()),
|
||||
result);
|
||||
debug!("built_executable_in_workspace: checking whether %s exists",
|
||||
result.to_str());
|
||||
if os::path_exists(&result) {
|
||||
Some(result)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Figure out what the library name for <pkgid> in <workspace>'s build
|
||||
/// directory is, and if the file exists, return it.
|
||||
pub fn built_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Option<Path> {
|
||||
let mut result = workspace.push("build");
|
||||
result = result.push_rel(&pkgid.path);
|
||||
// should use a target-specific subdirectory
|
||||
result = mk_output_path(Lib, pkgid.path.to_str(), result);
|
||||
debug!("built_library_in_workspace: checking whether %s exists",
|
||||
result.to_str());
|
||||
|
||||
// We don't know what the hash is, so we have to search through the directory
|
||||
// contents
|
||||
let dir_contents = os::list_dir(&result.pop());
|
||||
debug!("dir has %? entries", dir_contents.len());
|
||||
|
||||
// n.b. This code assumes the pkgid's path only has one element
|
||||
let lib_prefix = fmt!("%s%s", os::consts::DLL_PREFIX, pkgid.path.to_str());
|
||||
let lib_filetype = fmt!("%s%s", pkgid.version.to_str(), os::consts::DLL_SUFFIX);
|
||||
|
||||
debug!("lib_prefix = %s and lib_filetype = %s", lib_prefix, lib_filetype);
|
||||
|
||||
let mut result_filename = None;
|
||||
for dir_contents.each |&p| {
|
||||
let mut which = 0;
|
||||
let mut hash = None;
|
||||
// Find a filename that matches the pattern: (lib_prefix)-hash-(version)(lib_suffix)
|
||||
// and remember what the hash was
|
||||
for p.each_split_char('-') |piece| {
|
||||
debug!("a piece = %s", piece);
|
||||
if which == 0 && piece != lib_prefix {
|
||||
break;
|
||||
}
|
||||
else if which == 0 {
|
||||
which += 1;
|
||||
}
|
||||
else if which == 1 {
|
||||
hash = Some(piece.to_owned());
|
||||
which += 1;
|
||||
}
|
||||
else if which == 2 && piece != lib_filetype {
|
||||
hash = None;
|
||||
break;
|
||||
}
|
||||
else if which == 2 {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// something went wrong
|
||||
hash = None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if hash.is_some() {
|
||||
result_filename = Some(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the filename that matches, which we now know exists
|
||||
// (if result_filename != None)
|
||||
debug!("result_filename = %?", result_filename);
|
||||
match result_filename {
|
||||
None => None,
|
||||
Some(result_filename) => {
|
||||
let result_filename = result.with_filename(result_filename);
|
||||
debug!("result_filename = %s", result_filename.to_str());
|
||||
Some(result_filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the executable that would be installed for <pkgid>
|
||||
/// in <workspace>
|
||||
/// As a side effect, creates the bin-dir if it doesn't exist
|
||||
pub fn target_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
|
||||
let result = workspace.push("bin");
|
||||
// should use a target-specific subdirectory
|
||||
mk_output_path(Main, pkgid.path.to_str(), result)
|
||||
target_file_in_workspace(pkgid, workspace, Main)
|
||||
}
|
||||
|
||||
|
||||
/// Returns the executable that would be installed for <pkgid>
|
||||
/// in <workspace>
|
||||
/// As a side effect, creates the bin-dir if it doesn't exist
|
||||
pub fn target_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
|
||||
let result = workspace.push("lib");
|
||||
mk_output_path(Lib, pkgid.path.to_str(), result)
|
||||
target_file_in_workspace(pkgid, workspace, Lib)
|
||||
}
|
||||
|
||||
/// Returns the test executable that would be installed for <pkgid>
|
||||
/// in <workspace>
|
||||
pub fn target_test_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
|
||||
let result = workspace.push("build");
|
||||
mk_output_path(Test, pkgid.path.to_str(), result)
|
||||
target_file_in_workspace(pkgid, workspace, Test)
|
||||
}
|
||||
|
||||
/// Returns the bench executable that would be installed for <pkgid>
|
||||
/// in <workspace>
|
||||
pub fn target_bench_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
|
||||
let result = workspace.push("build");
|
||||
mk_output_path(Bench, pkgid.path.to_str(), result)
|
||||
target_file_in_workspace(pkgid, workspace, Bench)
|
||||
}
|
||||
|
||||
fn target_file_in_workspace(pkgid: PkgId, workspace: &Path,
|
||||
what: OutputType) -> Path {
|
||||
use conditions::bad_path::cond;
|
||||
|
||||
let (subdir, create_dir) = match what {
|
||||
Main => ("bin", true), Lib => ("lib", true), Test | Bench => ("build", false)
|
||||
};
|
||||
let result = workspace.push(subdir);
|
||||
if create_dir {
|
||||
if !os::path_exists(&result) && !mkdir_recursive(&result, u_rwx) {
|
||||
cond.raise((result, fmt!("I couldn't create the %s dir", subdir)));
|
||||
}
|
||||
}
|
||||
mk_output_path(what, pkgid.path.to_str(), result)
|
||||
|
||||
}
|
||||
|
||||
/// Return the directory for <pkgid>'s build artifacts in <workspace>.
|
||||
@ -123,7 +223,11 @@ pub fn mk_output_path(what: OutputType, short_name: ~str, dir: Path) -> Path {
|
||||
match what {
|
||||
Lib => dir.push(os::dll_filename(short_name)),
|
||||
_ => dir.push(fmt!("%s%s%s", short_name,
|
||||
if what == Test { ~"test" } else { ~"" },
|
||||
match what {
|
||||
Test => "test",
|
||||
Bench => "bench",
|
||||
_ => ""
|
||||
}
|
||||
os::EXE_SUFFIX))
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ use syntax::{ast, diagnostic};
|
||||
use util::*;
|
||||
use path_util::normalize;
|
||||
use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace};
|
||||
use path_util::{built_executable_in_workspace, built_library_in_workspace};
|
||||
use path_util::{target_executable_in_workspace, target_library_in_workspace};
|
||||
use workspace::pkg_parent_workspaces;
|
||||
use rustc::driver::session::{lib_crate, bin_crate, crate_type};
|
||||
use context::Ctx;
|
||||
@ -188,49 +190,7 @@ impl Ctx {
|
||||
// argument
|
||||
let pkgid = PkgId::new(args[0]);
|
||||
for pkg_parent_workspaces(pkgid) |workspace| {
|
||||
let src_dir = pkgid_src_in_workspace(pkgid, workspace);
|
||||
let build_dir = build_pkg_id_in_workspace(pkgid, workspace);
|
||||
debug!("Destination dir = %s", build_dir.to_str());
|
||||
|
||||
// Create the package source
|
||||
let mut src = PkgSrc::new(&workspace.push("src"), &build_dir, &pkgid);
|
||||
debug!("Package src = %?", src);
|
||||
|
||||
// Is there custom build logic? If so, use it
|
||||
let pkg_src_dir = src_dir;
|
||||
let mut custom = false;
|
||||
debug!("Package source directory = %s", pkg_src_dir.to_str());
|
||||
let cfgs = match src.package_script_option(&pkg_src_dir) {
|
||||
Some(package_script_path) => {
|
||||
let pscript = PkgScript::parse(package_script_path,
|
||||
workspace,
|
||||
pkgid);
|
||||
// Limited right now -- we're only running the post_build
|
||||
// hook and probably fail otherwise
|
||||
// also post_build should be called pre_build
|
||||
let (cfgs, hook_result) = pscript.run_custom(~"post_build");
|
||||
debug!("Command return code = %?", hook_result);
|
||||
if hook_result != 0 {
|
||||
fail!(fmt!("Error running custom build command"))
|
||||
}
|
||||
custom = true;
|
||||
// otherwise, the package script succeeded
|
||||
cfgs
|
||||
}
|
||||
None => {
|
||||
debug!("No package script, continuing");
|
||||
~[]
|
||||
}
|
||||
};
|
||||
|
||||
// If there was a package script, it should have finished
|
||||
// the build already. Otherwise...
|
||||
if !custom {
|
||||
// Find crates inside the workspace
|
||||
src.find_crates();
|
||||
// Build it!
|
||||
src.build(&build_dir, cfgs);
|
||||
}
|
||||
self.build(workspace, pkgid);
|
||||
}
|
||||
}
|
||||
~"clean" => {
|
||||
@ -304,6 +264,53 @@ impl Ctx {
|
||||
fail!(~"`do` not yet implemented");
|
||||
}
|
||||
|
||||
fn build(&self, workspace: &Path, pkgid: PkgId) {
|
||||
let src_dir = pkgid_src_in_workspace(pkgid, workspace);
|
||||
let build_dir = build_pkg_id_in_workspace(pkgid, workspace);
|
||||
debug!("Destination dir = %s", build_dir.to_str());
|
||||
|
||||
// Create the package source
|
||||
let mut src = PkgSrc::new(&workspace.push("src"), &build_dir, &pkgid);
|
||||
debug!("Package src = %?", src);
|
||||
|
||||
// Is there custom build logic? If so, use it
|
||||
let pkg_src_dir = src_dir;
|
||||
let mut custom = false;
|
||||
debug!("Package source directory = %s", pkg_src_dir.to_str());
|
||||
let cfgs = match src.package_script_option(&pkg_src_dir) {
|
||||
Some(package_script_path) => {
|
||||
let pscript = PkgScript::parse(package_script_path,
|
||||
workspace,
|
||||
pkgid);
|
||||
// Limited right now -- we're only running the post_build
|
||||
// hook and probably fail otherwise
|
||||
// also post_build should be called pre_build
|
||||
let (cfgs, hook_result) = pscript.run_custom(~"post_build");
|
||||
debug!("Command return code = %?", hook_result);
|
||||
if hook_result != 0 {
|
||||
fail!(fmt!("Error running custom build command"))
|
||||
}
|
||||
custom = true;
|
||||
// otherwise, the package script succeeded
|
||||
cfgs
|
||||
}
|
||||
None => {
|
||||
debug!("No package script, continuing");
|
||||
~[]
|
||||
}
|
||||
};
|
||||
|
||||
// If there was a package script, it should have finished
|
||||
// the build already. Otherwise...
|
||||
if !custom {
|
||||
// Find crates inside the workspace
|
||||
src.find_crates();
|
||||
// Build it!
|
||||
src.build(&build_dir, cfgs, self.sysroot_opt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn clean(&self, workspace: &Path, id: PkgId) {
|
||||
// Could also support a custom build hook in the pkg
|
||||
// script for cleaning files rustpkg doesn't know about.
|
||||
@ -325,9 +332,31 @@ impl Ctx {
|
||||
fail!(~"info not yet implemented");
|
||||
}
|
||||
|
||||
fn install(&self, _workspace: &Path, _id: PkgId) {
|
||||
// stub
|
||||
fail!(~"install not yet implemented");
|
||||
fn install(&self, workspace: &Path, id: PkgId) {
|
||||
use conditions::copy_failed::cond;
|
||||
|
||||
// Should use RUST_PATH in the future.
|
||||
// Also should use workcache to not build if not necessary.
|
||||
self.build(workspace, id);
|
||||
|
||||
// Now copy stuff into the install dirs
|
||||
let maybe_executable = built_executable_in_workspace(id, workspace);
|
||||
let maybe_library = built_library_in_workspace(id, workspace);
|
||||
let target_exec = target_executable_in_workspace(id, workspace);
|
||||
let target_lib = target_library_in_workspace(id, workspace);
|
||||
|
||||
for maybe_executable.each |exec| {
|
||||
debug!("Copying: %s -> %s", exec.to_str(), target_exec.to_str());
|
||||
if !os::copy_file(exec, &target_exec) {
|
||||
cond.raise((*exec, target_exec));
|
||||
}
|
||||
}
|
||||
for maybe_library.each |lib| {
|
||||
debug!("Copying: %s -> %s", lib.to_str(), target_lib.to_str());
|
||||
if !os::copy_file(lib, &target_lib) {
|
||||
cond.raise((*lib, target_lib));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch(&self, _dir: &Path, _url: ~str, _target: Option<~str>) {
|
||||
@ -477,6 +506,7 @@ pub fn main() {
|
||||
}
|
||||
|
||||
Ctx {
|
||||
sysroot_opt: None, // Currently, only tests override this
|
||||
json: json,
|
||||
dep_cache: @mut HashMap::new()
|
||||
}.run(cmd, args);
|
||||
@ -610,7 +640,7 @@ impl PkgSrc {
|
||||
|
||||
|
||||
fn check_dir(&self) -> Path {
|
||||
use conditions::bad_path::cond;
|
||||
use conditions::nonexistent_package::cond;
|
||||
|
||||
debug!("Pushing onto root: %s | %s", self.id.path.to_str(),
|
||||
self.root.to_str());
|
||||
@ -619,13 +649,15 @@ impl PkgSrc {
|
||||
|
||||
debug!("Checking dir: %s", dir.to_str());
|
||||
|
||||
// tjc: Rather than erroring out, need to try downloading the
|
||||
// contents of the path to a local directory (#5679)
|
||||
if !os::path_exists(&dir) {
|
||||
return cond.raise((dir, ~"missing package dir"));
|
||||
cond.raise((self.id, ~"missing package dir"));
|
||||
}
|
||||
|
||||
if !os::path_is_dir(&dir) {
|
||||
return cond.raise((dir, ~"supplied path for package dir is a \
|
||||
non-directory"));
|
||||
cond.raise((self.id, ~"supplied path for package dir is a \
|
||||
non-directory"));
|
||||
}
|
||||
|
||||
dir
|
||||
@ -680,6 +712,7 @@ impl PkgSrc {
|
||||
/// is no custom build logic
|
||||
fn find_crates(&mut self) {
|
||||
use PkgSrc::push_crate;
|
||||
use conditions::missing_pkg_files::cond;
|
||||
|
||||
let dir = self.check_dir();
|
||||
let prefix = dir.components.len();
|
||||
@ -704,7 +737,7 @@ impl PkgSrc {
|
||||
util::note(~"Couldn't infer any crates to build.\n\
|
||||
Try naming a crate `main.rs`, `lib.rs`, \
|
||||
`test.rs`, or `bench.rs`.");
|
||||
fail!(~"Failed to infer crates to build");
|
||||
cond.raise(self.id);
|
||||
}
|
||||
|
||||
debug!("found %u libs, %u mains, %u tests, %u benchs",
|
||||
@ -714,18 +747,20 @@ impl PkgSrc {
|
||||
self.benchs.len())
|
||||
}
|
||||
|
||||
fn build_crates(&self, dst_dir: &Path,
|
||||
src_dir: &Path,
|
||||
crates: &[Crate],
|
||||
cfgs: ~[~str],
|
||||
test: bool, crate_type: crate_type) {
|
||||
fn build_crates(&self,
|
||||
maybe_sysroot: Option<@Path>,
|
||||
dst_dir: &Path,
|
||||
src_dir: &Path,
|
||||
crates: &[Crate],
|
||||
cfgs: ~[~str],
|
||||
test: bool, crate_type: crate_type) {
|
||||
|
||||
for crates.each |&crate| {
|
||||
let path = &src_dir.push_rel(&crate.file).normalize();
|
||||
util::note(fmt!("build_crates: compiling %s", path.to_str()));
|
||||
util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str()));
|
||||
|
||||
let result = util::compile_crate(None, self.id, path,
|
||||
let result = util::compile_crate(maybe_sysroot, self.id, path,
|
||||
dst_dir,
|
||||
crate.flags,
|
||||
crate.cfgs + cfgs,
|
||||
@ -739,15 +774,15 @@ impl PkgSrc {
|
||||
}
|
||||
}
|
||||
|
||||
fn build(&self, dst_dir: &Path, cfgs: ~[~str]) {
|
||||
fn build(&self, dst_dir: &Path, cfgs: ~[~str], maybe_sysroot: Option<@Path>) {
|
||||
let dir = self.check_dir();
|
||||
debug!("Building libs");
|
||||
self.build_crates(dst_dir, &dir, self.libs, cfgs, false, lib_crate);
|
||||
self.build_crates(maybe_sysroot, dst_dir, &dir, self.libs, cfgs, false, lib_crate);
|
||||
debug!("Building mains");
|
||||
self.build_crates(dst_dir, &dir, self.mains, cfgs, false, bin_crate);
|
||||
self.build_crates(maybe_sysroot, dst_dir, &dir, self.mains, cfgs, false, bin_crate);
|
||||
debug!("Building tests");
|
||||
self.build_crates(dst_dir, &dir, self.tests, cfgs, true, bin_crate);
|
||||
self.build_crates(maybe_sysroot, dst_dir, &dir, self.tests, cfgs, true, bin_crate);
|
||||
debug!("Building benches");
|
||||
self.build_crates(dst_dir, &dir, self.benchs, cfgs, true, bin_crate);
|
||||
self.build_crates(maybe_sysroot, dst_dir, &dir, self.benchs, cfgs, true, bin_crate);
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,12 @@ use std::tempfile::mkdtemp;
|
||||
use util::{PkgId, default_version};
|
||||
use path_util::{target_executable_in_workspace, target_library_in_workspace,
|
||||
target_test_in_workspace, target_bench_in_workspace,
|
||||
make_dir_rwx};
|
||||
make_dir_rwx, u_rwx};
|
||||
use core::os::mkdir_recursive;
|
||||
|
||||
fn fake_ctxt() -> Ctx {
|
||||
fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
|
||||
Ctx {
|
||||
sysroot_opt: sysroot_opt,
|
||||
json: false,
|
||||
dep_cache: @mut HashMap::new()
|
||||
}
|
||||
@ -33,8 +35,34 @@ fn fake_pkg() -> PkgId {
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_temp_workspace() -> Path {
|
||||
mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir")
|
||||
fn remote_pkg() -> PkgId {
|
||||
PkgId {
|
||||
path: Path(~"github.com/catamorphism/test-pkg"),
|
||||
version: default_version()
|
||||
}
|
||||
}
|
||||
|
||||
fn writeFile(file_path: &Path, contents: ~str) {
|
||||
let out: @io::Writer =
|
||||
result::get(&io::file_writer(file_path,
|
||||
~[io::Create, io::Truncate]));
|
||||
out.write_line(contents);
|
||||
}
|
||||
|
||||
fn mk_temp_workspace(short_name: &Path) -> Path {
|
||||
let workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
|
||||
let package_dir = workspace.push(~"src").push_rel(short_name);
|
||||
assert!(mkdir_recursive(&package_dir, u_rwx));
|
||||
// Create main, lib, test, and bench files
|
||||
writeFile(&package_dir.push(~"main.rs"),
|
||||
~"fn main() { let _x = (); }");
|
||||
writeFile(&package_dir.push(~"lib.rs"),
|
||||
~"pub fn f() { let _x = (); }");
|
||||
writeFile(&package_dir.push(~"test.rs"),
|
||||
~"#[test] pub fn f() { (); }");
|
||||
writeFile(&package_dir.push(~"bench.rs"),
|
||||
~"#[bench] pub fn f() { (); }");
|
||||
workspace
|
||||
}
|
||||
|
||||
fn is_rwx(p: &Path) -> bool {
|
||||
@ -42,60 +70,104 @@ fn is_rwx(p: &Path) -> bool {
|
||||
|
||||
match p.get_mode() {
|
||||
None => return false,
|
||||
Some(m) => {
|
||||
Some(m) =>
|
||||
((m & S_IRUSR as uint) == S_IRUSR as uint
|
||||
&& (m & S_IWUSR as uint) == S_IWUSR as uint
|
||||
&& (m & S_IXUSR as uint) == S_IXUSR as uint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn test_sysroot() -> Path {
|
||||
// Totally gross hack but it's just for test cases.
|
||||
// Infer the sysroot from the exe name and tack "stage2"
|
||||
// onto it. (Did I mention it was a gross hack?)
|
||||
let self_path = os::self_exe_path().expect("Couldn't get self_exe path");
|
||||
self_path.pop().push("stage2")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_make_dir_rwx() {
|
||||
let temp = &os::tmpdir();
|
||||
let dir = temp.push(~"quux");
|
||||
let _ = os::remove_dir(&dir);
|
||||
assert!(!os::path_exists(&dir) ||
|
||||
os::remove_dir_recursive(&dir));
|
||||
debug!("Trying to make %s", dir.to_str());
|
||||
assert!(make_dir_rwx(&dir));
|
||||
assert!(os::path_is_dir(&dir));
|
||||
assert!(is_rwx(&dir));
|
||||
assert!(os::remove_dir(&dir));
|
||||
assert!(os::remove_dir_recursive(&dir));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore(reason = "install not yet implemented")]
|
||||
fn test_install_valid() {
|
||||
let ctxt = fake_ctxt();
|
||||
let sysroot = test_sysroot();
|
||||
debug!("sysroot = %s", sysroot.to_str());
|
||||
let ctxt = fake_ctxt(Some(@sysroot));
|
||||
let temp_pkg_id = fake_pkg();
|
||||
let temp_workspace = mk_temp_workspace();
|
||||
let temp_workspace = mk_temp_workspace(&temp_pkg_id.path);
|
||||
// should have test, bench, lib, and main
|
||||
ctxt.install(&temp_workspace, temp_pkg_id);
|
||||
// Check that all files exist
|
||||
let exec = target_executable_in_workspace(temp_pkg_id, &temp_workspace);
|
||||
debug!("exec = %s", exec.to_str());
|
||||
assert!(os::path_exists(&exec));
|
||||
assert!(is_rwx(&exec));
|
||||
let lib = target_library_in_workspace(temp_pkg_id, &temp_workspace);
|
||||
debug!("lib = %s", lib.to_str());
|
||||
assert!(os::path_exists(&lib));
|
||||
assert!(is_rwx(&lib));
|
||||
// And that the test and bench executables aren't installed
|
||||
assert!(!os::path_exists(&target_test_in_workspace(temp_pkg_id, &temp_workspace)));
|
||||
assert!(!os::path_exists(&target_bench_in_workspace(temp_pkg_id, &temp_workspace)));
|
||||
let bench = target_bench_in_workspace(temp_pkg_id, &temp_workspace);
|
||||
debug!("bench = %s", bench.to_str());
|
||||
assert!(!os::path_exists(&bench));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore(reason = "install not yet implemented")]
|
||||
fn test_install_invalid() {
|
||||
use conditions::nonexistent_package::cond;
|
||||
use cond1 = conditions::missing_pkg_files::cond;
|
||||
|
||||
let ctxt = fake_ctxt();
|
||||
let ctxt = fake_ctxt(None);
|
||||
let pkgid = fake_pkg();
|
||||
let temp_workspace = mk_temp_workspace();
|
||||
let expected_path = Path(~"quux");
|
||||
let substituted: Path = do cond.trap(|_| {
|
||||
expected_path
|
||||
let temp_workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
|
||||
let mut error_occurred = false;
|
||||
let mut error1_occurred = false;
|
||||
do cond1.trap(|_| {
|
||||
error1_occurred = true;
|
||||
}).in {
|
||||
ctxt.install(&temp_workspace, pkgid);
|
||||
// ok
|
||||
fail!(~"test_install_invalid failed, should have raised a condition");
|
||||
};
|
||||
assert!(substituted == expected_path);
|
||||
do cond.trap(|_| {
|
||||
error_occurred = true;
|
||||
}).in {
|
||||
ctxt.install(&temp_workspace, pkgid);
|
||||
}
|
||||
}
|
||||
assert!(error_occurred && error1_occurred);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore(reason = "install from URL-fragment not yet implemented")]
|
||||
fn test_install_url() {
|
||||
let sysroot = test_sysroot();
|
||||
debug!("sysroot = %s", sysroot.to_str());
|
||||
let ctxt = fake_ctxt(Some(@sysroot));
|
||||
let temp_pkg_id = remote_pkg();
|
||||
let temp_workspace = mk_temp_workspace(&temp_pkg_id.path);
|
||||
// should have test, bench, lib, and main
|
||||
ctxt.install(&temp_workspace, temp_pkg_id);
|
||||
// Check that all files exist
|
||||
let exec = target_executable_in_workspace(temp_pkg_id, &temp_workspace);
|
||||
debug!("exec = %s", exec.to_str());
|
||||
assert!(os::path_exists(&exec));
|
||||
assert!(is_rwx(&exec));
|
||||
let lib = target_library_in_workspace(temp_pkg_id, &temp_workspace);
|
||||
debug!("lib = %s", lib.to_str());
|
||||
assert!(os::path_exists(&lib));
|
||||
assert!(is_rwx(&lib));
|
||||
// And that the test and bench executables aren't installed
|
||||
assert!(!os::path_exists(&target_test_in_workspace(temp_pkg_id, &temp_workspace)));
|
||||
let bench = target_bench_in_workspace(temp_pkg_id, &temp_workspace);
|
||||
debug!("bench = %s", bench.to_str());
|
||||
assert!(!os::path_exists(&bench));
|
||||
}
|
@ -435,7 +435,7 @@ pub fn add_pkg(pkg: &Pkg) -> bool {
|
||||
}
|
||||
|
||||
// FIXME (#4432): Use workcache to only compile when needed
|
||||
pub fn compile_input(sysroot: Option<Path>,
|
||||
pub fn compile_input(sysroot: Option<@Path>,
|
||||
pkg_id: PkgId,
|
||||
in_file: &Path,
|
||||
out_dir: &Path,
|
||||
@ -474,9 +474,12 @@ pub fn compile_input(sysroot: Option<Path>,
|
||||
out_file.to_str());
|
||||
debug!("flags: %s", str::connect(flags, ~" "));
|
||||
debug!("cfgs: %s", str::connect(cfgs, ~" "));
|
||||
debug!("compile_input's sysroot = %?", sysroot);
|
||||
|
||||
let matches = getopts(~[~"-Z", ~"time-passes"]
|
||||
+ if building_library { ~[~"--lib"] }
|
||||
else if test { ~[~"--test"] }
|
||||
// bench?
|
||||
else { ~[] }
|
||||
+ flags
|
||||
+ cfgs.flat_map(|&c| { ~[~"--cfg", c] }),
|
||||
@ -540,9 +543,13 @@ pub fn compile_crate_from_input(input: driver::input,
|
||||
let (crate, _) = driver::compile_upto(sess, cfg, &input,
|
||||
driver::cu_parse, Some(outputs));
|
||||
|
||||
debug!("About to inject link_meta info...");
|
||||
// Inject the inferred link_meta info if it's not already there
|
||||
// (assumes that name and vers are the only linkage metas)
|
||||
let mut crate_to_use = crate;
|
||||
|
||||
debug!("How many attrs? %?", attr::find_linkage_metas(crate.node.attrs).len());
|
||||
|
||||
if attr::find_linkage_metas(crate.node.attrs).is_empty() {
|
||||
crate_to_use = add_attrs(*crate, ~[mk_attr(@dummy_spanned(meta_list(@~"link",
|
||||
// change PkgId to have a <shortname> field?
|
||||
@ -552,7 +559,6 @@ pub fn compile_crate_from_input(input: driver::input,
|
||||
mk_string_lit(@pkg_id.version.to_str())))])))]);
|
||||
}
|
||||
|
||||
|
||||
driver::compile_rest(sess, cfg, what, Some(outputs), Some(crate_to_use));
|
||||
crate_to_use
|
||||
}
|
||||
@ -582,7 +588,7 @@ fn add_attrs(c: ast::crate, new_attrs: ~[attribute]) -> @ast::crate {
|
||||
|
||||
// Called by build_crates
|
||||
// FIXME (#4432): Use workcache to only compile when needed
|
||||
pub fn compile_crate(sysroot: Option<Path>, pkg_id: PkgId,
|
||||
pub fn compile_crate(sysroot: Option<@Path>, pkg_id: PkgId,
|
||||
crate: &Path, dir: &Path,
|
||||
flags: ~[~str], cfgs: ~[~str], opt: bool,
|
||||
test: bool, crate_type: crate_type) -> bool {
|
||||
|
@ -27,6 +27,7 @@ pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option<Path> {
|
||||
mod tests {
|
||||
use tempfile::mkdtemp;
|
||||
use tempfile;
|
||||
use core::os;
|
||||
|
||||
#[test]
|
||||
fn test_mkdtemp() {
|
||||
@ -89,4 +90,27 @@ mod tests {
|
||||
assert!(os::path_is_dir(&path2.pop()));
|
||||
});
|
||||
}
|
||||
|
||||
// Ideally this would be in core, but needs mkdtemp
|
||||
#[test]
|
||||
pub fn test_rmdir_recursive_ok() {
|
||||
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
|
||||
use core::os;
|
||||
|
||||
let rwx = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
|
||||
|
||||
let tmpdir = mkdtemp(&os::tmpdir(), "test").expect("test_rmdir_recursive_ok: \
|
||||
couldn't create temp dir");
|
||||
let root = tmpdir.push("foo");
|
||||
|
||||
debug!("making %s", root.to_str());
|
||||
assert!(os::make_dir(&root, rwx));
|
||||
assert!(os::make_dir(&root.push("foo"), rwx));
|
||||
assert!(os::make_dir(&root.push("foo").push("bar"), rwx));
|
||||
assert!(os::make_dir(&root.push("foo").push("bar").push("blat"), rwx));
|
||||
assert!(os::remove_dir_recursive(&root));
|
||||
assert!(!os::path_exists(&root));
|
||||
assert!(!os::path_exists(&root.push("bar")));
|
||||
assert!(!os::path_exists(&root.push("bar").push("blat")));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user