Skip to content

Commit 0983ebe

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 a7e8957 commit 0983ebe

File tree

16 files changed

+465
-104
lines changed

16 files changed

+465
-104
lines changed

mk/tests.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ $(3)/stage$(1)/test/rustpkgtest-$(2)$$(X_$(2)): \
374374
$$(SREQ$(1)_T_$(2)_H_$(3)) \
375375
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \
376376
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) \
377+
$$(HBIN$(1)_H_$(3))/rustpkg$$(X_$(2)) \
377378
$$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$$(X_$(2)) \
378379
$$(TBIN$(1)_T_$(2)_H_$(3))/rustc$$(X_$(2))
379380
@$$(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
}
@@ -144,6 +157,10 @@ impl Context {
144157
pub fn compile_upto(&self) -> StopBefore {
145158
self.rustc_flags.compile_upto
146159
}
160+
161+
pub fn add_library_path(&mut self, p: Path) {
162+
self.rustc_flags.additional_library_paths.push(p);
163+
}
147164
}
148165

149166
/// We assume that if ../../rustc exists, then we're running
@@ -204,6 +221,7 @@ impl RustcFlags {
204221
save_temps: false,
205222
target: None,
206223
target_cpu: None,
224+
additional_library_paths: ~[],
207225
experimental_features: None
208226
}
209227
}

src/librustpkg/package_source.rs

Lines changed: 38 additions & 8 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};
2323
use path_util::{target_build_dir, versionize};
2424
use util::compile_crate;
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

2929
// An enumeration of the unpacked source of a package workspace.
@@ -360,7 +360,8 @@ impl PkgSrc {
360360
ctx: &BuildContext,
361361
crates: &[Crate],
362362
cfgs: &[~str],
363-
what: OutputType) {
363+
what: OutputType,
364+
inputs_to_discover: &[(~str, Path)]) {
364365
for crate in crates.iter() {
365366
let path = self.start_dir.push_rel(&crate.file).normalize();
366367
debug2!("build_crates: compiling {}", path.to_str());
@@ -378,7 +379,18 @@ impl PkgSrc {
378379
let id = self.id.clone();
379380
let sub_dir = self.build_workspace().clone();
380381
let sub_flags = crate.flags.clone();
382+
let inputs = inputs_to_discover.map(|&(ref k, ref p)| (k.clone(), p.to_str()));
381383
do prep.exec |exec| {
384+
for &(ref kind, ref p) in inputs.iter() {
385+
let pth = Path(*p);
386+
exec.discover_input(*kind, *p, if *kind == ~"file" {
387+
digest_file_with_date(&pth)
388+
} else if *kind == ~"binary" {
389+
digest_only_date(&Path(*p))
390+
} else {
391+
fail2!("Bad kind in build_crates")
392+
});
393+
}
382394
let result = compile_crate(&subcx,
383395
exec,
384396
&id,
@@ -416,20 +428,38 @@ impl PkgSrc {
416428
// Encodable.
417429
pub fn build(&self,
418430
build_context: &BuildContext,
419-
cfgs: ~[~str]) {
431+
cfgs: ~[~str],
432+
inputs_to_discover: &[(~str, Path)]) {
420433
let libs = self.libs.clone();
421434
let mains = self.mains.clone();
422435
let tests = self.tests.clone();
423436
let benchs = self.benchs.clone();
424437
debug2!("Building libs in {}, destination = {}",
425-
self.source_workspace.to_str(), self.build_workspace().to_str());
426-
self.build_crates(build_context, libs, cfgs, Lib);
438+
self.destination_workspace.to_str(),
439+
self.destination_workspace.to_str());
440+
self.build_crates(build_context,
441+
libs,
442+
cfgs,
443+
Lib,
444+
inputs_to_discover);
427445
debug2!("Building mains");
428-
self.build_crates(build_context, mains, cfgs, Main);
446+
self.build_crates(build_context,
447+
mains,
448+
cfgs,
449+
Main,
450+
inputs_to_discover);
429451
debug2!("Building tests");
430-
self.build_crates(build_context, tests, cfgs, Test);
452+
self.build_crates(build_context,
453+
tests,
454+
cfgs,
455+
Test,
456+
inputs_to_discover);
431457
debug2!("Building benches");
432-
self.build_crates(build_context, benchs, cfgs, Bench);
458+
self.build_crates(build_context,
459+
benchs,
460+
cfgs,
461+
Bench,
462+
inputs_to_discover);
433463
}
434464

435465
/// 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
@@ -453,7 +453,6 @@ pub fn versionize(p: &Path, v: &Version) -> Path {
453453
p.with_filename(format!("{}-{}", q, v.to_str()))
454454
}
455455

456-
457456
#[cfg(target_os = "win32")]
458457
pub fn chmod_read_only(p: &Path) -> bool {
459458
#[fixed_stack_segment];
@@ -475,3 +474,6 @@ pub fn chmod_read_only(p: &Path) -> bool {
475474
}
476475
}
477476

477+
pub fn platform_library_name(s: &str) -> ~str {
478+
format!("{}{}{}", os::consts::DLL_PREFIX, s, os::consts::DLL_SUFFIX)
479+
}

0 commit comments

Comments
 (0)