Skip to content

Commit c979575

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 #6403
1 parent 22a5ebd commit c979575

File tree

16 files changed

+514
-104
lines changed

16 files changed

+514
-104
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: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,35 @@ 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

30+
// A little sad -- duplicated from rustc::back::*
31+
#[cfg(target_arch = "arm")]
32+
fn cc_args() -> ~[~str] { ~[~"-marm"] }
33+
#[cfg(target_arch = "mips")]
34+
fn cc_args() -> ~[~str] { ~[] }
35+
#[cfg(target_arch = "x86")]
36+
fn cc_args() -> ~[~str] { ~[~"-m32"] }
37+
#[cfg(target_arch = "x86_64")]
38+
fn cc_args() -> ~[~str] { ~[~"-m64"] }
39+
2740
/// Convenience functions intended for calling from pkg.rs
2841
/// 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)
42+
pub fn default_context(sysroot: Path, p: Path) -> BuildContext {
43+
new_default_context(new_workcache_context(&p), sysroot)
3144
}
3245

3346
pub fn new_default_context(c: workcache::Context, p: Path) -> BuildContext {
@@ -68,7 +81,7 @@ pub fn new_workcache_context(p: &Path) -> workcache::Context {
6881

6982
pub fn build_lib(sysroot: Path, root: Path, name: ~str, version: Version,
7083
lib: Path) {
71-
let cx = default_context(sysroot);
84+
let cx = default_context(sysroot, root.clone());
7285
let pkg_src = PkgSrc {
7386
source_workspace: root.clone(),
7487
build_in_destination: false,
@@ -81,12 +94,12 @@ pub fn build_lib(sysroot: Path, root: Path, name: ~str, version: Version,
8194
tests: ~[],
8295
benchs: ~[]
8396
};
84-
pkg_src.build(&cx, ~[]);
97+
pkg_src.build(&cx, ~[], []);
8598
}
8699

87100
pub fn build_exe(sysroot: Path, root: Path, name: ~str, version: Version,
88101
main: Path) {
89-
let cx = default_context(sysroot);
102+
let cx = default_context(sysroot, root.clone());
90103
let pkg_src = PkgSrc {
91104
source_workspace: root.clone(),
92105
build_in_destination: false,
@@ -100,13 +113,76 @@ pub fn build_exe(sysroot: Path, root: Path, name: ~str, version: Version,
100113
benchs: ~[]
101114
};
102115

103-
pkg_src.build(&cx, ~[]);
116+
pkg_src.build(&cx, ~[], []);
104117
}
105118

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

112188
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+
debug!("Adding library path: {}", p.display());
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: 43 additions & 9 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
debug!("build_crates: compiling {}", path.display());
@@ -408,7 +409,19 @@ 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)|
413+
(k.clone(), p.as_str().unwrap().to_owned()));
411414
do prep.exec |exec| {
415+
for &(ref kind, ref p) in inputs.iter() {
416+
let pth = Path::new(p.clone());
417+
exec.discover_input(*kind, *p, if *kind == ~"file" {
418+
digest_file_with_date(&pth)
419+
} else if *kind == ~"binary" {
420+
digest_only_date(&Path::new(p.clone()))
421+
} else {
422+
fail!("Bad kind in build_crates")
423+
});
424+
}
412425
let result = compile_crate(&subcx,
413426
exec,
414427
&id,
@@ -452,22 +465,43 @@ impl PkgSrc {
452465
build_context: &BuildContext,
453466
// DepMap is a map from str (crate name) to (kind, name) --
454467
// it tracks discovered dependencies per-crate
455-
cfgs: ~[~str]) -> DepMap {
468+
cfgs: ~[~str],
469+
inputs_to_discover: &[(~str, Path)]) -> DepMap {
456470
let mut deps = TreeMap::new();
457-
458471
let libs = self.libs.clone();
459472
let mains = self.mains.clone();
460473
let tests = self.tests.clone();
461474
let benchs = self.benchs.clone();
462475
debug!("Building libs in {}, destination = {}",
463-
self.source_workspace.display(), self.build_workspace().display());
464-
self.build_crates(build_context, &mut deps, libs, cfgs, Lib);
476+
self.destination_workspace.display(),
477+
self.destination_workspace.display());
478+
self.build_crates(build_context,
479+
&mut deps,
480+
libs,
481+
cfgs,
482+
Lib,
483+
inputs_to_discover);
465484
debug!("Building mains");
466-
self.build_crates(build_context, &mut deps, mains, cfgs, Main);
485+
self.build_crates(build_context,
486+
&mut deps,
487+
mains,
488+
cfgs,
489+
Main,
490+
inputs_to_discover);
467491
debug!("Building tests");
468-
self.build_crates(build_context, &mut deps, tests, cfgs, Test);
492+
self.build_crates(build_context,
493+
&mut deps,
494+
tests,
495+
cfgs,
496+
Test,
497+
inputs_to_discover);
469498
debug!("Building benches");
470-
self.build_crates(build_context, &mut deps, benchs, cfgs, Bench);
499+
self.build_crates(build_context,
500+
&mut deps,
501+
benchs,
502+
cfgs,
503+
Bench,
504+
inputs_to_discover);
471505
deps
472506
}
473507

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)