Skip to content

Commit 6796bd4

Browse files
committed
rustpkg: Support arbitrary dependencies in the install API
api::install_pkg now accepts an argument that's a list of (kind, path) dependency pairs. This allows custom package scripts to declare C dependencies, as is demonstrated in rustpkg::tests::test_c_dependency_ok. Closes rust-lang#6403
1 parent cf7b9eb commit 6796bd4

File tree

16 files changed

+470
-91
lines changed

16 files changed

+470
-91
lines changed

mk/tests.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ $(3)/stage$(1)/test/rustpkgtest-$(2)$$(X_$(2)): \
370370
$$(SREQ$(1)_T_$(2)_H_$(3)) \
371371
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \
372372
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) \
373+
$$(HBIN$(1)_H_$(3))/rustpkg$$(X_$(2)) \
373374
$$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$$(X_$(2)) \
374375
$$(TBIN$(1)_T_$(2)_H_$(3))/rustc$$(X_$(2))
375376
@$$(call E, compile_and_link: $$@)

src/librustpkg/api.rs

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,25 @@ use context::*;
1212
use crate::*;
1313
use package_id::*;
1414
use package_source::*;
15+
use path_util::{platform_library_name, target_build_dir};
1516
use target::*;
1617
use version::Version;
18+
use workspace::pkg_parent_workspaces;
1719
use workcache_support::*;
20+
pub use path_util::default_workspace;
1821

1922
pub use source_control::{safe_git_clone, git_clone_url};
2023

21-
use std::os;
24+
use std::{os, run};
2225
use extra::arc::{Arc,RWArc};
2326
use extra::workcache;
2427
use extra::workcache::{Database, Logger, FreshnessMap};
2528
use extra::treemap::TreeMap;
2629

2730
/// Convenience functions intended for calling from pkg.rs
2831
/// p is where to put the cache file for dependencies
29-
pub fn default_context(p: Path) -> BuildContext {
30-
new_default_context(new_workcache_context(&p), p)
32+
pub fn default_context(sysroot: Path, p: Path) -> BuildContext {
33+
new_default_context(new_workcache_context(&p), sysroot)
3134
}
3235

3336
pub fn new_default_context(c: workcache::Context, p: Path) -> BuildContext {
@@ -68,7 +71,7 @@ pub fn new_workcache_context(p: &Path) -> workcache::Context {
6871

6972
pub fn build_lib(sysroot: Path, root: Path, name: ~str, version: Version,
7073
lib: Path) {
71-
let cx = default_context(sysroot);
74+
let cx = default_context(sysroot, root.clone());
7275
let pkg_src = PkgSrc {
7376
source_workspace: root.clone(),
7477
build_in_destination: false,
@@ -81,12 +84,12 @@ pub fn build_lib(sysroot: Path, root: Path, name: ~str, version: Version,
8184
tests: ~[],
8285
benchs: ~[]
8386
};
84-
pkg_src.build(&cx, ~[]);
87+
pkg_src.build(&cx, ~[], []);
8588
}
8689

8790
pub fn build_exe(sysroot: Path, root: Path, name: ~str, version: Version,
8891
main: Path) {
89-
let cx = default_context(sysroot);
92+
let cx = default_context(sysroot, root.clone());
9093
let pkg_src = PkgSrc {
9194
source_workspace: root.clone(),
9295
build_in_destination: false,
@@ -100,13 +103,65 @@ pub fn build_exe(sysroot: Path, root: Path, name: ~str, version: Version,
100103
benchs: ~[]
101104
};
102105

103-
pkg_src.build(&cx, ~[]);
106+
pkg_src.build(&cx, ~[], []);
104107
}
105108

106-
pub fn install_pkg(sysroot: Path, workspace: Path, name: ~str, version: Version) {
107-
let cx = default_context(sysroot);
109+
pub fn install_pkg(cx: &BuildContext,
110+
workspace: Path,
111+
name: ~str,
112+
version: Version,
113+
// For now, these inputs are assumed to be inputs to each of the crates
114+
more_inputs: ~[(~str, Path)]) { // pairs of Kind and Path
108115
let pkgid = PkgId{ version: version, ..PkgId::new(name)};
109-
cx.install(PkgSrc::new(workspace.clone(), workspace, false, pkgid), &Everything);
116+
cx.install(PkgSrc::new(workspace.clone(), workspace, false, pkgid),
117+
&WhatToBuild{ build_type: Inferred,
118+
inputs_to_discover: more_inputs,
119+
sources: Everything });
120+
}
121+
122+
/// Builds an arbitrary library whose short name is `output`,
123+
/// by invoking `tool` with arguments `args` plus "-o %s", where %s
124+
/// is the platform-specific library name for `output`.
125+
/// Returns that platform-specific name.
126+
pub fn build_library_in_workspace(exec: &mut workcache::Exec,
127+
context: &mut Context,
128+
package_name: &str,
129+
tool: &str,
130+
flags: &[~str],
131+
paths: &[~str],
132+
output: &str) -> ~str {
133+
use command_failed = conditions::command_failed::cond;
134+
135+
let workspace = my_workspace(context, package_name);
136+
let workspace_build_dir = target_build_dir(&workspace);
137+
let out_name = workspace_build_dir.push_many([package_name.to_str(),
138+
platform_library_name(output)]);
139+
// make paths absolute
140+
let pkgid = PkgId::new(package_name);
141+
let absolute_paths = paths.map(|s|
142+
workspace.push_many([~"src", pkgid.to_str(), s.to_owned()]).to_str());
143+
let all_args = flags + absolute_paths + ~[~"-o", out_name.to_str()];
144+
let exit_code = run::process_status(tool, all_args);
145+
if exit_code != 0 {
146+
command_failed.raise((tool.to_owned(), all_args, exit_code))
147+
}
148+
else {
149+
exec.discover_output("binary", out_name.to_str(), digest_only_date(&out_name));
150+
context.add_library_path(out_name.dir_path());
151+
out_name.to_str()
152+
}
153+
}
154+
155+
pub fn my_workspace(context: &Context, package_name: &str) -> Path {
156+
use bad_pkg_id = conditions::bad_pkg_id::cond;
157+
158+
// (this assumes no particular version is requested)
159+
let pkgid = PkgId::new(package_name);
160+
let workspaces = pkg_parent_workspaces(context, &pkgid);
161+
if workspaces.is_empty() {
162+
bad_pkg_id.raise((Path(package_name), package_name.to_owned()));
163+
}
164+
workspaces[0]
110165
}
111166

112167
fn mk_crate(p: Path) -> Crate {

src/librustpkg/conditions.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,9 @@ condition! {
5454
condition! {
5555
pub git_checkout_failed: (~str, Path) -> ();
5656
}
57+
58+
condition! {
59+
// str is output of applying the command (first component)
60+
// to the args (second component)
61+
pub command_failed: (~str, ~[~str], int) -> ~str;
62+
}

src/librustpkg/context.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ impl BuildContext {
5454
pub fn compile_upto(&self) -> StopBefore {
5555
self.context.compile_upto()
5656
}
57+
58+
pub fn add_library_path(&mut self, p: Path) {
59+
debug2!("Adding library path: {}", p.to_str());
60+
self.context.add_library_path(p);
61+
}
62+
63+
pub fn additional_library_paths(&self) -> ~[Path] {
64+
self.context.rustc_flags.additional_library_paths.clone()
65+
}
5766
}
5867

5968
/*
@@ -85,6 +94,9 @@ pub struct RustcFlags {
8594
target: Option<~str>,
8695
// Target CPU (defaults to rustc's default target CPU)
8796
target_cpu: Option<~str>,
97+
// Additional library directories, which get passed with the -L flag
98+
// This can't be set with a rustpkg flag, only from package scripts
99+
additional_library_paths: ~[Path],
88100
// Any -Z features
89101
experimental_features: Option<~[~str]>
90102
}
@@ -99,6 +111,7 @@ impl Clone for RustcFlags {
99111
save_temps: self.save_temps,
100112
target: self.target.clone(),
101113
target_cpu: self.target_cpu.clone(),
114+
additional_library_paths: self.additional_library_paths.clone(),
102115
experimental_features: self.experimental_features.clone()
103116
}
104117
}
@@ -148,6 +161,10 @@ impl Context {
148161
pub fn compile_upto(&self) -> StopBefore {
149162
self.rustc_flags.compile_upto
150163
}
164+
165+
pub fn add_library_path(&mut self, p: Path) {
166+
self.rustc_flags.additional_library_paths.push(p);
167+
}
151168
}
152169

153170
/// We assume that if ../../rustc exists, then we're running
@@ -210,6 +227,7 @@ impl RustcFlags {
210227
save_temps: false,
211228
target: None,
212229
target_cpu: None,
230+
additional_library_paths: ~[],
213231
experimental_features: None
214232
}
215233
}

src/librustpkg/package_source.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use path_util::{find_dir_using_rust_path_hack, make_dir_rwx_recursive, default_w
2323
use path_util::{target_build_dir, versionize, dir_has_crate_file};
2424
use util::{compile_crate, DepMap};
2525
use workcache_support;
26-
use workcache_support::crate_tag;
26+
use workcache_support::{digest_only_date, digest_file_with_date, crate_tag};
2727
use extra::workcache;
2828
use extra::treemap::TreeMap;
2929

@@ -390,7 +390,8 @@ impl PkgSrc {
390390
deps: &mut DepMap,
391391
crates: &[Crate],
392392
cfgs: &[~str],
393-
what: OutputType) {
393+
what: OutputType,
394+
inputs_to_discover: &[(~str, Path)]) {
394395
for crate in crates.iter() {
395396
let path = self.start_dir.join(&crate.file);
396397
debug2!("build_crates: compiling {}", path.display());
@@ -408,7 +409,18 @@ impl PkgSrc {
408409
let sub_dir = self.build_workspace().clone();
409410
let sub_flags = crate.flags.clone();
410411
let sub_deps = deps.clone();
412+
let inputs = inputs_to_discover.map(|&(ref k, ref p)| (k.clone(), p.to_str()));
411413
do prep.exec |exec| {
414+
for &(ref kind, ref p) in inputs.iter() {
415+
let pth = Path(*p);
416+
exec.discover_input(*kind, *p, if *kind == ~"file" {
417+
digest_file_with_date(&pth)
418+
} else if *kind == ~"binary" {
419+
digest_only_date(&Path(*p))
420+
} else {
421+
fail2!("Bad kind in build_crates")
422+
});
423+
}
412424
let result = compile_crate(&subcx,
413425
exec,
414426
&id,
@@ -452,23 +464,43 @@ impl PkgSrc {
452464
build_context: &BuildContext,
453465
// DepMap is a map from str (crate name) to (kind, name) --
454466
// it tracks discovered dependencies per-crate
455-
cfgs: ~[~str]) -> DepMap {
467+
cfgs: ~[~str]){
468+
inputs_to_discover: &[(~str, Path)]) -> DepMap {
456469
let mut deps = TreeMap::new();
457-
458470
let libs = self.libs.clone();
459471
let mains = self.mains.clone();
460472
let tests = self.tests.clone();
461473
let benchs = self.benchs.clone();
462474
debug2!("Building libs in {}, destination = {}",
463-
self.source_workspace.display(), self.build_workspace().display());
464-
self.build_crates(build_context, &mut deps, libs, cfgs, Lib);
475+
self.destination_workspace.to_str(),
476+
self.destination_workspace.to_str());
477+
self.build_crates(build_context,
478+
&mut deps,
479+
libs,
480+
cfgs,
481+
Lib,
482+
inputs_to_discover);
465483
debug2!("Building mains");
466-
self.build_crates(build_context, &mut deps, mains, cfgs, Main);
484+
self.build_crates(build_context,
485+
&mut deps,
486+
mains,
487+
cfgs,
488+
Main,
489+
inputs_to_discover);
467490
debug2!("Building tests");
468-
self.build_crates(build_context, &mut deps, tests, cfgs, Test);
491+
self.build_crates(build_context,
492+
&mut deps,
493+
tests,
494+
cfgs,
495+
Test,
496+
inputs_to_discover);
469497
debug2!("Building benches");
470-
self.build_crates(build_context, &mut deps, benchs, cfgs, Bench);
471-
deps
498+
self.build_crates(build_context,
499+
&mut deps,
500+
benchs,
501+
cfgs,
502+
Bench,
503+
inputs_to_discover);
472504
}
473505

474506
/// Return the workspace to put temporary files in. See the comment on `PkgSrc`

src/librustpkg/path_util.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,6 @@ pub fn versionize(p: &Path, v: &Version) -> Path {
461461
p.with_filename(q)
462462
}
463463

464-
465464
#[cfg(target_os = "win32")]
466465
pub fn chmod_read_only(p: &Path) -> bool {
467466
#[fixed_stack_segment];
@@ -483,3 +482,6 @@ pub fn chmod_read_only(p: &Path) -> bool {
483482
}
484483
}
485484

485+
pub fn platform_library_name(s: &str) -> ~str {
486+
format!("{}{}{}", os::consts::DLL_PREFIX, s, os::consts::DLL_SUFFIX)
487+
}

0 commit comments

Comments
 (0)