auto merge of #7403 : catamorphism/rust/package-scripts, r=brson

r? @brson (or @graydon if available) rustpkg/api.rs provides functions intended for package scripts to call.
It will probably need more functionality added to it later, but this is
a start.

Added a test case checking that a package script can use the API.

Closes #6401
This commit is contained in:
bors 2013-06-27 06:01:30 -07:00
commit c440743dcc
7 changed files with 166 additions and 22 deletions

View File

@ -161,7 +161,7 @@ pub struct compile_upto {
#[deriving(Eq)]
pub enum compile_phase {
cu_parse,
cu_expand,
cu_expand, // means "it's already expanded"
cu_typeck,
cu_no_trans,
cu_everything,

92
src/librustpkg/api.rs Normal file
View File

@ -0,0 +1,92 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.
use context::*;
use crate::*;
use package_id::*;
use package_source::*;
use version::Version;
use core::option::*;
use core::os;
use core::hashmap::*;
use core::path::*;
/// Convenience functions intended for calling from pkg.rs
fn default_ctxt(p: @Path) -> Ctx {
Ctx { sysroot_opt: Some(p), json: false, dep_cache: @mut HashMap::new() }
}
pub fn build_lib(sysroot: @Path, root: Path, dest: Path, name: ~str, version: Version,
lib: Path) {
let pkg_src = PkgSrc {
root: root,
dst_dir: dest,
id: PkgId{ version: version, ..PkgId::new(name)},
libs: ~[mk_crate(lib)],
mains: ~[],
tests: ~[],
benchs: ~[]
};
pkg_src.build(&default_ctxt(sysroot), pkg_src.dst_dir, ~[]);
}
pub fn build_exe(sysroot: @Path, root: Path, dest: Path, name: ~str, version: Version,
main: Path) {
let pkg_src = PkgSrc {
root: root,
dst_dir: dest,
id: PkgId{ version: version, ..PkgId::new(name)},
libs: ~[],
mains: ~[mk_crate(main)],
tests: ~[],
benchs: ~[]
};
pkg_src.build(&default_ctxt(sysroot), pkg_src.dst_dir, ~[]);
}
pub fn install_lib(sysroot: @Path,
workspace: Path,
name: ~str,
lib_path: Path,
version: Version) {
debug!("self_exe: %?", os::self_exe_path());
debug!("sysroot = %s", sysroot.to_str());
debug!("workspace = %s", workspace.to_str());
// make a PkgSrc
let pkg_id = PkgId{ version: version, ..PkgId::new(name)};
let build_dir = workspace.push("build");
let dst_dir = build_dir.push_rel(&*pkg_id.local_path);
let pkg_src = PkgSrc {
root: copy workspace,
dst_dir: copy dst_dir,
id: copy pkg_id,
libs: ~[mk_crate(lib_path)],
mains: ~[],
tests: ~[],
benchs: ~[]
};
let cx = default_ctxt(sysroot);
pkg_src.build(&cx, dst_dir, ~[]);
cx.install_no_build(&workspace, &pkg_id);
}
pub fn install_exe(sysroot: @Path, workspace: Path, name: ~str, version: Version) {
default_ctxt(sysroot).install(&workspace, &PkgId{ version: version,
..PkgId::new(name)});
}
fn mk_crate(p: Path) -> Crate {
Crate { file: p, flags: ~[], cfgs: ~[] }
}

View File

@ -46,6 +46,7 @@
use package_id::PkgId;
use package_source::PkgSrc;
pub mod api;
mod conditions;
mod context;
mod crate;
@ -104,8 +105,10 @@ fn parse<'a>(script: Path, workspace: &Path, id: &'a PkgId) -> PkgScript<'a> {
let binary = os::args()[0].to_managed();
// Build the rustc session data structures to pass
// to the compiler
debug!("pkgscript parse: %?", os::self_exe_path());
let options = @session::options {
binary: binary,
maybe_sysroot: Some(@os::self_exe_path().get().pop()),
crate_type: session::bin_crate,
.. copy *session::basic_options()
};
@ -132,8 +135,7 @@ fn parse<'a>(script: Path, workspace: &Path, id: &'a PkgId) -> PkgScript<'a> {
/// Returns a pair of an exit code and list of configs (obtained by
/// calling the package script's configs() function if it exists
// FIXME (#4432): Use workcache to only compile the script when changed
fn run_custom(&self, what: ~str) -> (~[~str], ExitCode) {
debug!("run_custom: %s", what);
fn run_custom(&self, sysroot: @Path) -> (~[~str], ExitCode) {
let sess = self.sess;
debug!("Working directory = %s", self.build_dir.to_str());
@ -152,9 +154,12 @@ fn run_custom(&self, what: ~str) -> (~[~str], ExitCode) {
sess,
crate,
driver::build_configuration(sess,
binary, &self.input));
debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what);
let status = run::process_status(exe.to_str(), [root.to_str(), what]);
binary, &self.input),
driver::cu_parse);
debug!("Running program: %s %s %s %s", exe.to_str(),
sysroot.to_str(), root.to_str(), "install");
// FIXME #7401 should support commands besides `install`
let status = run::process_status(exe.to_str(), [sysroot.to_str(), ~"install"]);
if status != 0 {
return (~[], status);
}
@ -291,10 +296,8 @@ fn build(&self, workspace: &Path, pkgid: &PkgId) {
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");
let sysroot = self.sysroot_opt.expect("custom build needs a sysroot");
let (cfgs, hook_result) = pscript.run_custom(sysroot);
debug!("Command return code = %?", hook_result);
if hook_result != 0 {
fail!("Error running custom build command")
@ -341,13 +344,17 @@ fn info(&self) {
}
fn install(&self, workspace: &Path, id: &PkgId) {
use conditions::copy_failed::cond;
// Should use RUST_PATH in the future.
// FIXME #7402: Use RUST_PATH to determine target dir
// Also should use workcache to not build if not necessary.
self.build(workspace, id);
debug!("install: workspace = %s, id = %s", workspace.to_str(),
id.to_str());
self.install_no_build(workspace, id);
}
fn install_no_build(&self, workspace: &Path, id: &PkgId) {
use conditions::copy_failed::cond;
// Now copy stuff into the install dirs
let maybe_executable = built_executable_in_workspace(id, workspace);

View File

@ -545,6 +545,22 @@ fn rustpkg_local_pkg() {
assert_executable_exists(&dir, "foo");
}
#[test]
fn package_script_with_default_build() {
let dir = create_local_package(&PkgId::new("fancy-lib"));
debug!("dir = %s", dir.to_str());
let source = test_sysroot().pop().pop().pop().push("src").push("librustpkg").
push("testsuite").push("pass").push("src").push("fancy-lib").push("pkg.rs");
debug!("package_script_with_default_build: %s", source.to_str());
if !os::copy_file(&source,
& dir.push("src").push("fancy_lib-0.1").push("pkg.rs")) {
fail!("Couldn't copy file");
}
command_line_test([~"install", ~"fancy-lib"], &dir);
assert_lib_exists(&dir, "fancy-lib");
assert!(os::path_exists(&dir.push("build").push("fancy_lib").push("generated.rs")));
}
#[test]
#[ignore (reason = "RUST_PATH not yet implemented -- #5682")]
fn rust_path_test() {

View File

@ -8,12 +8,37 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::run;
extern mod rustpkg;
extern mod rustc;
use std::{io, os};
use rustpkg::api;
use rustpkg::version::NoVersion;
use rustc::metadata::filesearch;
pub fn main() {
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
let args = os::args();
let out_path = Path(~"build/fancy_lib");
// by convention, first arg is sysroot
if args.len() < 2 {
fail!("Package script requires a directory where rustc libraries live as the first \
argument");
}
let sysroot_arg = copy args[1];
let sysroot = Path(sysroot_arg);
if !os::path_exists(&sysroot) {
fail!("Package script requires a sysroot that exists; %s doesn't", sysroot.to_str());
}
if args[2] != ~"install" {
io::println(fmt!("Warning: I don't know how to %s", args[2]));
return;
}
let out_path = Path("build/fancy_lib");
if !os::path_exists(&out_path) {
assert!(os::make_dir(&out_path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
}
@ -22,7 +47,10 @@ pub fn main() {
[io::Create]).get();
file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }");
// now compile the crate itself
run::process_status("rustc", [~"src/fancy-lib/fancy-lib.rs", ~"--lib", ~"-o",
out_path.push(~"fancy_lib").to_str()]);
debug!("api_____install_____lib, my sysroot:");
debug!(sysroot.to_str());
api::install_lib(@sysroot, os::getcwd(), ~"fancy-lib", Path("lib.rs"),
NoVersion);
}

View File

@ -257,7 +257,7 @@ pub fn compile_input(ctxt: &Ctx,
debug!("calling compile_crate_from_input, out_dir = %s,
building_library = %?", out_dir.to_str(), sess.building_library);
compile_crate_from_input(&input, out_dir, sess, crate, copy cfg);
compile_crate_from_input(&input, out_dir, sess, crate, copy cfg, driver::cu_expand);
true
}
@ -270,7 +270,8 @@ pub fn compile_crate_from_input(input: &driver::input,
build_dir: &Path,
sess: session::Session,
crate: @ast::crate,
cfg: ast::crate_cfg) {
cfg: ast::crate_cfg,
compile_from: driver::compile_phase) {
debug!("Calling build_output_filenames with %s, building library? %?",
build_dir.to_str(), sess.building_library);
@ -287,7 +288,7 @@ pub fn compile_crate_from_input(input: &driver::input,
driver::compile_rest(sess,
cfg,
compile_upto {
from: driver::cu_expand,
from: compile_from,
to: driver::cu_everything
},
Some(outputs),