Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc/rustpkg: Use a target-specific subdirectory in build/ and lib/ #9151

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions doc/rustpkg.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,11 @@ A valid workspace must contain each of the following subdirectories:
rustpkg will install libraries for bar to `foo/lib/x86_64-apple-darwin/`.
The libraries will have names of the form `foo/lib/x86_64-apple-darwin/libbar-[hash].dylib`,
where [hash] is a hash of the package ID.
* 'bin/': `rustpkg install` installs executable binaries into a target-specific subdirectory of this directory.
* 'bin/': `rustpkg install` installs executable binaries into this directory.

For example, on a 64-bit machine running Mac OS X,
if `foo` is a workspace, containing the package `bar`,
rustpkg will install executables for `bar` to
`foo/bin/x86_64-apple-darwin/`.
The executables will have names of the form `foo/bin/x86_64-apple-darwin/bar`.
For example, rustpkg will install executables for `bar` to
`foo/bin`.
The executables will have names of the form `foo/bin/bar`.
* 'build/': `rustpkg build` stores temporary build artifacts in a target-specific subdirectory of this directory.

For example, on a 64-bit machine running Mac OS X,
Expand All @@ -85,6 +83,12 @@ rustpkg also interprets any dependencies on such a package ID literally
Thus, `github.com/mozilla/rust#5c4cd30f80` is also a valid package ID,
since git can deduce that 5c4cd30f80 refers to a revision of the desired repository.

A package identifier can name a subdirectory of another package.
For example, if `foo` is a workspace, and `foo/src/bar/lib.rs` exists,
as well as `foo/src/bar/extras/baz/lib.rs`,
then both `bar` and `bar/extras/baz` are valid package identifiers
in the workspace `foo`.

## Source files

rustpkg searches for four different fixed filenames in order to determine the crates to build:
Expand Down Expand Up @@ -140,9 +144,11 @@ but not in their `lib` or `bin` directories.

## install

`rustpkg install foo` builds the libraries and/or executables that are targets for `foo`,
and then installs them either into `foo`'s `lib` and `bin` directories,
or into the `lib` and `bin` subdirectories of the first entry in `RUST_PATH`.
`rustpkg install foo` builds the libraries and/or executables that are targets for `foo`.
If `RUST_PATH` is declared as an environment variable, then rustpkg installs the
libraries and executables into the `lib` and `bin` subdirectories
of the first entry in `RUST_PATH`.
Otherwise, it installs them into `foo`'s `lib` and `bin` directories.

## test

Expand Down
17 changes: 11 additions & 6 deletions src/librustc/metadata/filesearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
if !found {
let rustpath = rust_path();
for path in rustpath.iter() {
debug!("is %s in visited_dirs? %?",
path.push("lib").to_str(),
visited_dirs.contains(&path.push("lib").to_str()));
let tlib_path = make_rustpkg_target_lib_path(path, self.target_triple);
debug!("is %s in visited_dirs? %?", tlib_path.to_str(),
visited_dirs.contains(&tlib_path.to_str()));

if !visited_dirs.contains(&path.push("lib").to_str()) {
visited_dirs.insert(path.push("lib").to_str());
if !visited_dirs.contains(&tlib_path.to_str()) {
visited_dirs.insert(tlib_path.to_str());
// Don't keep searching the RUST_PATH if one match turns up --
// if we did, we'd get a "multiple matching crates" error
match f(&path.push("lib")) {
match f(&tlib_path) {
FileMatches => {
break;
}
Expand Down Expand Up @@ -145,6 +145,11 @@ fn make_target_lib_path(sysroot: &Path,
sysroot.push_rel(&relative_target_lib_path(target_triple))
}

fn make_rustpkg_target_lib_path(dir: &Path,
target_triple: &str) -> Path {
dir.push_rel(&Path(libdir()).push(target_triple.to_owned()))
}

fn get_or_default_sysroot() -> Path {
match os::self_exe_path() {
option::Some(ref p) => (*p).pop(),
Expand Down
53 changes: 42 additions & 11 deletions src/librustpkg/path_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub use package_id::PkgId;
pub use target::{OutputType, Main, Lib, Test, Bench, Target, Build, Install};
pub use version::{Version, NoVersion, split_version_general, try_parsing_version};
pub use rustc::metadata::filesearch::rust_path;
use rustc::driver::driver::host_triple;

use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
use std::os::mkdir_recursive;
Expand Down Expand Up @@ -94,10 +95,29 @@ pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
found
}

/// Return the target-specific build subdirectory, pushed onto `base`;
/// doesn't check that it exists or create it
pub fn target_build_dir(workspace: &Path) -> Path {
workspace.push("build").push(host_triple())
}

/// Return the target-specific lib subdirectory, pushed onto `base`;
/// doesn't check that it exists or create it
fn target_lib_dir(workspace: &Path) -> Path {
workspace.push("lib").push(host_triple())
}

/// Return the bin subdirectory, pushed onto `base`;
/// doesn't check that it exists or create it
/// note: this isn't target-specific
fn target_bin_dir(workspace: &Path) -> Path {
workspace.push("bin")
}

/// 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");
let mut result = target_build_dir(workspace);
// should use a target-specific subdirectory
result = mk_output_path(Main, Build, pkgid, result);
debug!("built_executable_in_workspace: checking whether %s exists",
Expand All @@ -124,7 +144,7 @@ pub fn built_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path>
}

fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Option<Path> {
let mut result = workspace.push("build");
let mut result = target_build_dir(workspace);
// should use a target-specific subdirectory
result = mk_output_path(what, Build, pkgid, result);
debug!("output_in_workspace: checking whether %s exists",
Expand Down Expand Up @@ -172,11 +192,21 @@ pub fn library_in_workspace(path: &Path, short_name: &str, where: Target,
prefix = %s", short_name, where, workspace.to_str(), prefix);

let dir_to_search = match where {
Build => workspace.push(prefix).push_rel(path),
Install => workspace.push(prefix)
Build => target_build_dir(workspace).push_rel(path),
Install => target_lib_dir(workspace)
};

library_in(short_name, version, &dir_to_search)
}

// rustc doesn't use target-specific subdirectories
pub fn system_library(sysroot: &Path, lib_name: &str) -> Option<Path> {
library_in(lib_name, &NoVersion, &sysroot.push("lib"))
}

fn library_in(short_name: &str, version: &Version, dir_to_search: &Path) -> Option<Path> {
debug!("Listing directory %s", dir_to_search.to_str());
let dir_contents = os::list_dir(&dir_to_search);
let dir_contents = os::list_dir(dir_to_search);
debug!("dir has %? entries", dir_contents.len());

let lib_prefix = fmt!("%s%s", os::consts::DLL_PREFIX, short_name);
Expand Down Expand Up @@ -298,9 +328,10 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
};
// Artifacts in the build directory live in a package-ID-specific subdirectory,
// but installed ones don't.
let result = match where {
Build => workspace.push(subdir).push_rel(&pkgid.path),
_ => workspace.push(subdir)
let result = match (where, what) {
(Build, _) => target_build_dir(workspace).push_rel(&pkgid.path),
(Install, Lib) => target_lib_dir(workspace),
(Install, _) => target_bin_dir(workspace)
};
if !os::path_exists(&result) && !mkdir_recursive(&result, U_RWX) {
cond.raise((result.clone(), fmt!("target_file_in_workspace couldn't \
Expand All @@ -315,10 +346,10 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
pub fn build_pkg_id_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
use conditions::bad_path::cond;

let mut result = workspace.push("build");
// n.b. Should actually use a target-specific
// subdirectory of build/
let mut result = target_build_dir(workspace);
result = result.push_rel(&pkgid.path);
debug!("Creating build dir %s for package id %s", result.to_str(),
pkgid.to_str());
if os::path_exists(&result) || os::mkdir_recursive(&result, U_RWX) {
result
}
Expand Down
48 changes: 37 additions & 11 deletions src/librustpkg/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use path_util::{target_executable_in_workspace, target_test_in_workspace,
target_bench_in_workspace, make_dir_rwx, U_RWX,
library_in_workspace, installed_library_in_workspace,
built_bench_in_workspace, built_test_in_workspace,
built_library_in_workspace, built_executable_in_workspace};
built_library_in_workspace, built_executable_in_workspace, target_build_dir};
use rustc::back::link::get_cc_prog;
use rustc::metadata::filesearch::rust_path;
use rustc::driver::driver::{build_session, build_session_options, host_triple, optgroups};
Expand Down Expand Up @@ -382,7 +382,7 @@ fn llvm_bitcode_file_exists(repo: &Path, short_name: &str) -> bool {
}

fn file_exists(repo: &Path, short_name: &str, extension: &str) -> bool {
os::path_exists(&repo.push_many([~"build", short_name.to_owned(),
os::path_exists(&target_build_dir(repo).push_many([short_name.to_owned(),
fmt!("%s.%s", short_name, extension)]))
}

Expand Down Expand Up @@ -433,7 +433,7 @@ fn lib_output_file_name(workspace: &Path, parent: &str, short_name: &str) -> Pat
}

fn output_file_name(workspace: &Path, short_name: &str) -> Path {
workspace.push("build").push(short_name).push(fmt!("%s%s", short_name, os::EXE_SUFFIX))
target_build_dir(workspace).push(short_name).push(fmt!("%s%s", short_name, os::EXE_SUFFIX))
}

fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
Expand Down Expand Up @@ -657,11 +657,10 @@ fn test_package_version() {
None => false
});
assert!(built_executable_in_workspace(&temp_pkg_id, &ws)
== Some(ws.push("build").
push("mockgithub.com").
push("catamorphism").
push("test_pkg_version").
push("test_pkg_version")));
== Some(target_build_dir(&ws).push_many([~"mockgithub.com",
~"catamorphism",
~"test_pkg_version",
~"test_pkg_version"])));
}

#[test]
Expand Down Expand Up @@ -755,7 +754,7 @@ fn package_script_with_default_build() {
}
command_line_test([~"install", ~"fancy-lib"], &dir);
assert_lib_exists(&dir, &Path("fancy-lib"), NoVersion);
assert!(os::path_exists(&dir.push("build").push("fancy-lib").push("generated.rs")));
assert!(os::path_exists(&target_build_dir(&dir).push_many([~"fancy-lib", ~"generated.rs"])));
}

#[test]
Expand Down Expand Up @@ -1121,7 +1120,7 @@ fn test_import_rustpkg() {
"extern mod rustpkg; fn main() {}");
command_line_test([~"build", ~"foo"], &workspace);
debug!("workspace = %s", workspace.to_str());
assert!(os::path_exists(&workspace.push("build").push("foo").push(fmt!("pkg%s",
assert!(os::path_exists(&target_build_dir(&workspace).push("foo").push(fmt!("pkg%s",
os::EXE_SUFFIX))));
}

Expand All @@ -1133,7 +1132,7 @@ fn test_macro_pkg_script() {
"extern mod rustpkg; fn main() { debug!(\"Hi\"); }");
command_line_test([~"build", ~"foo"], &workspace);
debug!("workspace = %s", workspace.to_str());
assert!(os::path_exists(&workspace.push("build").push("foo").push(fmt!("pkg%s",
assert!(os::path_exists(&target_build_dir(&workspace).push("foo").push(fmt!("pkg%s",
os::EXE_SUFFIX))));
}

Expand Down Expand Up @@ -1622,6 +1621,33 @@ fn test_install_to_rust_path() {
assert!(!executable_exists(&second_workspace, "foo"));
}

fn test_target_specific_build_dir() {
let p_id = PkgId::new("foo");
let workspace = create_local_package(&p_id);
command_line_test([test_sysroot().to_str(),
~"build",
~"foo"],
&workspace);
assert!(os::path_is_dir(&target_build_dir(&workspace)));
assert!(built_executable_exists(&workspace, "foo"));
assert!(os::list_dir(&workspace.push("build")).len() == 1);
}

#[test]
fn test_target_specific_install_dir() {
let p_id = PkgId::new("foo");
let workspace = create_local_package(&p_id);
command_line_test([test_sysroot().to_str(),
~"install",
~"foo"],
&workspace);
assert!(os::path_is_dir(&workspace.push("lib").push(host_triple())));
assert_lib_exists(&workspace, &Path("foo"), NoVersion);
assert!(os::list_dir(&workspace.push("lib")).len() == 1);
assert!(os::path_is_dir(&workspace.push("bin")));
assert_executable_exists(&workspace, "foo");
}

/// Returns true if p exists and is executable
fn is_executable(p: &Path) -> bool {
use std::libc::consts::os::posix88::{S_IXUSR};
Expand Down
7 changes: 4 additions & 3 deletions src/librustpkg/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use context::{in_target, StopBefore, Link, Assemble, BuildContext};
use package_id::PkgId;
use package_source::PkgSrc;
use workspace::pkg_parent_workspaces;
use path_util::{installed_library_in_workspace, U_RWX, rust_path};
use path_util::{installed_library_in_workspace, U_RWX, rust_path, system_library, target_build_dir};
use messages::error;

pub use target::{OutputType, Main, Lib, Bench, Test};
Expand Down Expand Up @@ -170,7 +170,7 @@ pub fn compile_input(context: &BuildContext,
// tjc: by default, use the package ID name as the link name
// not sure if we should support anything else

let out_dir = workspace.push("build").push_rel(&pkg_id.path);
let out_dir = target_build_dir(workspace).push_rel(&pkg_id.path);

let binary = os::args()[0].to_managed();

Expand Down Expand Up @@ -381,7 +381,8 @@ pub fn find_and_install_dependencies(context: &BuildContext,
None => sess.str_of(lib_ident)
};
debug!("Finding and installing... %s", lib_name);
match installed_library_in_workspace(&Path(lib_name), &context.sysroot()) {
// Check standard Rust library path first
match system_library(&context.sysroot(), lib_name) {
Some(ref installed_path) => {
debug!("It exists: %s", installed_path.to_str());
// Say that [path for c] has a discovered dependency on
Expand Down