diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index d3789ec5adfd8..7155233cd372e 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -55,6 +55,10 @@ pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool { pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path, // Returns the directory it was actually found in workspace_to_src_dir: &fn(&Path) -> Path) -> Option { + if !os::path_is_dir(workspace) { + return None; + } + let src_dir = workspace_to_src_dir(workspace); let mut found = None; diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs index 03eb4e938424e..8212e3e279977 100644 --- a/src/librustpkg/rustpkg.rs +++ b/src/librustpkg/rustpkg.rs @@ -33,7 +33,7 @@ use rustc::metadata::filesearch::rust_path; use extra::{getopts}; use syntax::{ast, diagnostic}; use util::*; -use messages::*; +use messages::{error, warn, note}; use path_util::build_pkg_id_in_workspace; use path_util::{U_RWX, in_rust_path}; use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace}; diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index cef422be77a89..bf80dc14166fe 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -1581,6 +1581,28 @@ fn pkgid_pointing_to_subdir() { assert_executable_exists(&workspace, "testpkg"); } +fn test_recursive_deps() { + let a_id = PkgId::new("a"); + let b_id = PkgId::new("b"); + let c_id = PkgId::new("c"); + let b_workspace = create_local_package_with_dep(&b_id, &c_id); + writeFile(&b_workspace.push("src").push("c-0.1").push("lib.rs"), + "pub fn g() {}"); + let a_workspace = create_local_package(&a_id); + writeFile(&a_workspace.push("src").push("a-0.1").push("main.rs"), + "extern mod b; use b::f; fn main() { f(); }"); + writeFile(&b_workspace.push("src").push("b-0.1").push("lib.rs"), + "extern mod c; use c::g; pub fn f() { g(); }"); + let environment = Some(~[(~"RUST_PATH", b_workspace.to_str())]); + debug!("RUST_PATH=%s", b_workspace.to_str()); + command_line_test_with_env([~"install", ~"a"], + &a_workspace, + environment); + assert_lib_exists(&a_workspace, &Path("a"), NoVersion); + assert_lib_exists(&b_workspace, &Path("b"), NoVersion); + assert_lib_exists(&b_workspace, &Path("c"), NoVersion); +} + /// Returns true if p exists and is executable fn is_executable(p: &Path) -> bool { use std::libc::consts::os::posix88::{S_IXUSR}; diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 15fc7d376217b..708d50bb53794 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -22,7 +22,9 @@ use rustc::driver::session::{lib_crate, bin_crate}; use context::{in_target, StopBefore, Link, Assemble, BuildContext}; use package_id::PkgId; use package_source::PkgSrc; -use path_util::{installed_library_in_workspace, U_RWX}; +use workspace::pkg_parent_workspaces; +use path_util::{installed_library_in_workspace, U_RWX, rust_path}; +use messages::error; pub use target::{OutputType, Main, Lib, Bench, Test}; use workcache_support::{digest_file_with_date, digest_only_date}; @@ -243,9 +245,7 @@ pub fn compile_input(context: &BuildContext, let mut crate = driver::phase_1_parse_input(sess, cfg.clone(), &input); crate = driver::phase_2_configure_and_expand(sess, cfg.clone(), crate); - // Not really right. Should search other workspaces too, and the installed - // database (which doesn't exist yet) - find_and_install_dependencies(context, sess, exec, workspace, crate, + find_and_install_dependencies(context, pkg_id, sess, exec, crate, |p| { debug!("a dependency: %s", p.to_str()); // Pass the directory containing a dependency @@ -362,13 +362,15 @@ pub fn compile_crate(ctxt: &BuildContext, /// Collect all `extern mod` directives in `c`, then /// try to install their targets, failing if any target /// can't be found. -pub fn find_and_install_dependencies(ctxt: &BuildContext, +pub fn find_and_install_dependencies(context: &BuildContext, + parent: &PkgId, sess: session::Session, exec: &mut workcache::Exec, - workspace: &Path, c: &ast::Crate, save: @fn(Path) ) { + use conditions::nonexistent_package::cond; + do c.each_view_item() |vi: &ast::view_item| { debug!("A view item!"); match vi.node { @@ -379,7 +381,7 @@ pub fn find_and_install_dependencies(ctxt: &BuildContext, None => sess.str_of(lib_ident) }; debug!("Finding and installing... %s", lib_name); - match installed_library_in_workspace(&Path(lib_name), &ctxt.sysroot()) { + match installed_library_in_workspace(&Path(lib_name), &context.sysroot()) { Some(ref installed_path) => { debug!("It exists: %s", installed_path.to_str()); // Say that [path for c] has a discovered dependency on @@ -397,8 +399,18 @@ pub fn find_and_install_dependencies(ctxt: &BuildContext, lib_name.to_str()); // Try to install it let pkg_id = PkgId::new(lib_name); + let workspaces = pkg_parent_workspaces(&context.context, &pkg_id); + let dep_workspace = if workspaces.is_empty() { + error(fmt!("Couldn't find package %s, which is needed by %s, \ + in any of the workspaces in the RUST_PATH (%?)", + lib_name, parent.to_str(), rust_path())); + cond.raise((pkg_id.clone(), ~"Dependency not found")) + } + else { + workspaces[0] + }; let (outputs_disc, inputs_disc) = - ctxt.install(PkgSrc::new(workspace.clone(), false, pkg_id)); + context.install(PkgSrc::new(dep_workspace.clone(), false, pkg_id)); debug!("Installed %s, returned %? dependencies and \ %? transitive dependencies", lib_name, outputs_disc.len(), inputs_disc.len()); @@ -423,7 +435,7 @@ pub fn find_and_install_dependencies(ctxt: &BuildContext, // Also, add an additional search path debug!("Adding additional search path: %s", lib_name); let installed_library = - installed_library_in_workspace(&Path(lib_name), workspace) + installed_library_in_workspace(&Path(lib_name), &dep_workspace) .expect( fmt!("rustpkg failed to install dependency %s", lib_name)); let install_dir = installed_library.pop();