Skip to content

Commit 6f6dce7

Browse files
committed
auto merge of #8176 : catamorphism/rust/rustpkg-extern-mod, r=catamorphism
r? @graydon Also, notably, make rustpkgtest depend on the rustpkg executable (otherwise, tests that shell out to rustpgk might run when rustpkg doesn't exist).
2 parents 1de201c + 37fd8f0 commit 6f6dce7

30 files changed

+919
-794
lines changed

doc/rust.md

+22-8
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ There are several kinds of view item:
744744
##### Extern mod declarations
745745

746746
~~~~~~~~ {.ebnf .gram}
747-
extern_mod_decl : "extern" "mod" ident [ '(' link_attrs ')' ] ? ;
747+
extern_mod_decl : "extern" "mod" ident [ '(' link_attrs ')' ] ? [ '=' string_lit ] ? ;
748748
link_attrs : link_attr [ ',' link_attrs ] + ;
749749
link_attr : ident '=' literal ;
750750
~~~~~~~~
@@ -755,20 +755,34 @@ as the `ident` provided in the `extern_mod_decl`.
755755

756756
The external crate is resolved to a specific `soname` at compile time,
757757
and a runtime linkage requirement to that `soname` is passed to the linker for
758-
loading at runtime. The `soname` is resolved at compile time by scanning the
759-
compiler's library path and matching the `link_attrs` provided in the
760-
`use_decl` against any `#link` attributes that were declared on the external
761-
crate when it was compiled. If no `link_attrs` are provided, a default `name`
762-
attribute is assumed, equal to the `ident` given in the `use_decl`.
763-
764-
Three examples of `extern mod` declarations:
758+
loading at runtime.
759+
The `soname` is resolved at compile time by scanning the compiler's library path
760+
and matching the `link_attrs` provided in the `use_decl` against any `#link` attributes that
761+
were declared on the external crate when it was compiled.
762+
If no `link_attrs` are provided,
763+
a default `name` attribute is assumed,
764+
equal to the `ident` given in the `use_decl`.
765+
766+
Optionally, an identifier in an `extern mod` declaration may be followed by an equals sign,
767+
then a string literal denoting a relative path on the filesystem.
768+
This path should exist in one of the directories in the Rust path,
769+
which by default contains the `.rust` subdirectory of the current directory and each of its parents,
770+
as well as any directories in the colon-separated (or semicolon-separated on Windows)
771+
list of paths that is the `RUST_PATH` environment variable.
772+
The meaning of `extern mod a = "b/c/d";`, supposing that `/a` is in the RUST_PATH,
773+
is that the name `a` should be taken as a reference to the crate whose absolute location is
774+
`/a/b/c/d`.
775+
776+
Four examples of `extern mod` declarations:
765777

766778
~~~~~~~~{.xfail-test}
767779
extern mod pcre (uuid = "54aba0f8-a7b1-4beb-92f1-4cf625264841");
768780
769781
extern mod extra; // equivalent to: extern mod extra ( name = "extra" );
770782
771783
extern mod rustextra (name = "extra"); // linking to 'extra' under another name
784+
785+
extern mod complicated_mod = "some-file/in/the-rust/path";
772786
~~~~~~~~
773787

774788
##### Use declarations

mk/tests.mk

+3-1
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,9 @@ $(3)/stage$(1)/test/rustpkgtest-$(2)$$(X_$(2)): \
348348
$$(RUSTPKG_LIB) $$(RUSTPKG_INPUTS) \
349349
$$(SREQ$(1)_T_$(2)_H_$(3)) \
350350
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \
351-
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2))
351+
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) \
352+
$$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$$(X_$(2)) \
353+
$$(TBIN$(1)_T_$(2)_H_$(3))/rustc$$(X_$(2))
352354
@$$(call E, compile_and_link: $$@)
353355
$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
354356

src/librustc/back/link.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use lib::llvm::llvm;
1616
use lib::llvm::ModuleRef;
1717
use lib;
1818
use metadata::common::LinkMeta;
19-
use metadata::{encoder, csearch, cstore};
19+
use metadata::{encoder, csearch, cstore, filesearch};
2020
use middle::trans::context::CrateContext;
2121
use middle::trans::common::gensym_name;
2222
use middle::ty;
@@ -497,35 +497,40 @@ pub fn build_link_meta(sess: Session,
497497
struct ProvidedMetas {
498498
name: Option<@str>,
499499
vers: Option<@str>,
500+
pkg_id: Option<@str>,
500501
cmh_items: ~[@ast::MetaItem]
501502
}
502503

503504
fn provided_link_metas(sess: Session, c: &ast::Crate) ->
504505
ProvidedMetas {
505506
let mut name = None;
506507
let mut vers = None;
508+
let mut pkg_id = None;
507509
let mut cmh_items = ~[];
508510
let linkage_metas = attr::find_linkage_metas(c.attrs);
509511
attr::require_unique_names(sess.diagnostic(), linkage_metas);
510512
for meta in linkage_metas.iter() {
511513
match meta.name_str_pair() {
512514
Some((n, value)) if "name" == n => name = Some(value),
513515
Some((n, value)) if "vers" == n => vers = Some(value),
516+
Some((n, value)) if "package_id" == n => pkg_id = Some(value),
514517
_ => cmh_items.push(*meta)
515518
}
516519
}
517520

518521
ProvidedMetas {
519522
name: name,
520523
vers: vers,
524+
pkg_id: pkg_id,
521525
cmh_items: cmh_items
522526
}
523527
}
524528

525529
// This calculates CMH as defined above
526530
fn crate_meta_extras_hash(symbol_hasher: &mut hash::State,
527531
cmh_items: ~[@ast::MetaItem],
528-
dep_hashes: ~[@str]) -> @str {
532+
dep_hashes: ~[@str],
533+
pkg_id: Option<@str>) -> @str {
529534
fn len_and_str(s: &str) -> ~str {
530535
fmt!("%u_%s", s.len(), s)
531536
}
@@ -563,7 +568,10 @@ pub fn build_link_meta(sess: Session,
563568
write_string(symbol_hasher, len_and_str(*dh));
564569
}
565570

566-
// tjc: allocation is unfortunate; need to change std::hash
571+
for p in pkg_id.iter() {
572+
write_string(symbol_hasher, len_and_str(*p));
573+
}
574+
567575
return truncated_hash_result(symbol_hasher).to_managed();
568576
}
569577

@@ -605,18 +613,20 @@ pub fn build_link_meta(sess: Session,
605613
let ProvidedMetas {
606614
name: opt_name,
607615
vers: opt_vers,
616+
pkg_id: opt_pkg_id,
608617
cmh_items: cmh_items
609618
} = provided_link_metas(sess, c);
610619
let name = crate_meta_name(sess, output, opt_name);
611620
let vers = crate_meta_vers(sess, opt_vers);
612621
let dep_hashes = cstore::get_dep_hashes(sess.cstore);
613622
let extras_hash =
614623
crate_meta_extras_hash(symbol_hasher, cmh_items,
615-
dep_hashes);
624+
dep_hashes, opt_pkg_id);
616625

617626
LinkMeta {
618627
name: name,
619628
vers: vers,
629+
package_id: opt_pkg_id,
620630
extras_hash: extras_hash
621631
}
622632
}
@@ -939,6 +949,11 @@ pub fn link_args(sess: Session,
939949
args.push(~"-L" + path.to_str());
940950
}
941951

952+
let rustpath = filesearch::rust_path();
953+
for path in rustpath.iter() {
954+
args.push(~"-L" + path.to_str());
955+
}
956+
942957
// The names of the extern libraries
943958
let used_libs = cstore::get_used_libraries(cstore);
944959
for l in used_libs.iter() { args.push(~"-l" + *l); }

src/librustc/back/rpath.rs

+4-113
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ use metadata::cstore;
1414
use metadata::filesearch;
1515

1616
use std::hashmap::HashSet;
17-
use std::num;
18-
use std::os;
19-
use std::util;
20-
use std::vec;
17+
use std::{num, os, path, uint, util, vec};
2118

2219
fn not_win32(os: session::os) -> bool {
2320
os != session::os_win32
@@ -122,42 +119,7 @@ pub fn get_rpath_relative_to_output(os: session::os,
122119
session::os_win32 => util::unreachable()
123120
};
124121

125-
Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output),
126-
&os::make_absolute(lib)))
127-
}
128-
129-
// Find the relative path from one file to another
130-
pub fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
131-
assert!(abs1.is_absolute);
132-
assert!(abs2.is_absolute);
133-
let abs1 = abs1.normalize();
134-
let abs2 = abs2.normalize();
135-
debug!("finding relative path from %s to %s",
136-
abs1.to_str(), abs2.to_str());
137-
let split1: &[~str] = abs1.components;
138-
let split2: &[~str] = abs2.components;
139-
let len1 = split1.len();
140-
let len2 = split2.len();
141-
assert!(len1 > 0);
142-
assert!(len2 > 0);
143-
144-
let max_common_path = num::min(len1, len2) - 1;
145-
let mut start_idx = 0;
146-
while start_idx < max_common_path
147-
&& split1[start_idx] == split2[start_idx] {
148-
start_idx += 1;
149-
}
150-
151-
let mut path = ~[];
152-
for _ in range(start_idx, len1 - 1) { path.push(~".."); };
153-
154-
path.push_all(split2.slice(start_idx, len2 - 1));
155-
156-
return if !path.is_empty() {
157-
Path("").push_many(path)
158-
} else {
159-
Path(".")
160-
}
122+
Path(prefix).push_rel(&os::make_absolute(output).get_relative_to(&os::make_absolute(lib)))
161123
}
162124

163125
fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] {
@@ -208,8 +170,7 @@ mod test {
208170
#[cfg(test)]
209171
#[cfg(test)]
210172
use back::rpath::{get_absolute_rpath, get_install_prefix_rpath};
211-
use back::rpath::{get_relative_to, get_rpath_relative_to_output};
212-
use back::rpath::{minimize_rpaths, rpaths_to_flags};
173+
use back::rpath::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output};
213174
use driver::session;
214175

215176
#[test]
@@ -253,78 +214,9 @@ mod test {
253214
assert_eq!(res, ~[Path("1a"), Path("2"), Path("4a"), Path("3")]);
254215
}
255216
256-
#[test]
257-
fn test_relative_to1() {
258-
let p1 = Path("/usr/bin/rustc");
259-
let p2 = Path("/usr/lib/mylib");
260-
let res = get_relative_to(&p1, &p2);
261-
assert_eq!(res, Path("../lib"));
262-
}
263-
264-
#[test]
265-
fn test_relative_to2() {
266-
let p1 = Path("/usr/bin/rustc");
267-
let p2 = Path("/usr/bin/../lib/mylib");
268-
let res = get_relative_to(&p1, &p2);
269-
assert_eq!(res, Path("../lib"));
270-
}
271-
272-
#[test]
273-
fn test_relative_to3() {
274-
let p1 = Path("/usr/bin/whatever/rustc");
275-
let p2 = Path("/usr/lib/whatever/mylib");
276-
let res = get_relative_to(&p1, &p2);
277-
assert_eq!(res, Path("../../lib/whatever"));
278-
}
279-
280-
#[test]
281-
fn test_relative_to4() {
282-
let p1 = Path("/usr/bin/whatever/../rustc");
283-
let p2 = Path("/usr/lib/whatever/mylib");
284-
let res = get_relative_to(&p1, &p2);
285-
assert_eq!(res, Path("../lib/whatever"));
286-
}
287-
288-
#[test]
289-
fn test_relative_to5() {
290-
let p1 = Path("/usr/bin/whatever/../rustc");
291-
let p2 = Path("/usr/lib/whatever/../mylib");
292-
let res = get_relative_to(&p1, &p2);
293-
assert_eq!(res, Path("../lib"));
294-
}
295-
296-
#[test]
297-
fn test_relative_to6() {
298-
let p1 = Path("/1");
299-
let p2 = Path("/2/3");
300-
let res = get_relative_to(&p1, &p2);
301-
assert_eq!(res, Path("2"));
302-
}
303-
304-
#[test]
305-
fn test_relative_to7() {
306-
let p1 = Path("/1/2");
307-
let p2 = Path("/3");
308-
let res = get_relative_to(&p1, &p2);
309-
assert_eq!(res, Path(".."));
310-
}
311-
312-
#[test]
313-
fn test_relative_to8() {
314-
let p1 = Path("/home/brian/Dev/rust/build/").push_rel(
315-
&Path("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
316-
let p2 = Path("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
317-
&Path("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
318-
let res = get_relative_to(&p1, &p2);
319-
debug!("test_relative_tu8: %s vs. %s",
320-
res.to_str(),
321-
Path(".").to_str());
322-
assert_eq!(res, Path("."));
323-
}
324-
325217
#[test]
326218
#[cfg(target_os = "linux")]
327-
#[cfg(target_os = "andorid")]
219+
#[cfg(target_os = "android")]
328220
fn test_rpath_relative() {
329221
let o = session::os_linux;
330222
let res = get_rpath_relative_to_output(o,
@@ -344,7 +236,6 @@ mod test {
344236
#[test]
345237
#[cfg(target_os = "macos")]
346238
fn test_rpath_relative() {
347-
// this is why refinements would be nice
348239
let o = session::os_macos;
349240
let res = get_rpath_relative_to_output(o,
350241
&Path("bin/rustc"),

src/librustc/front/std_inject.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
4747
let n1 = sess.next_node_id();
4848
let vi1 = ast::view_item {
4949
node: ast::view_item_extern_mod(
50-
sess.ident_of("std"), ~[], n1),
50+
sess.ident_of("std"), None, ~[], n1),
5151
attrs: ~[
5252
attr::mk_attr(
5353
attr::mk_name_value_item_str(@"vers", STD_VERSION.to_managed()))

src/librustc/front/test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ fn mk_std(cx: &TestCtxt) -> ast::view_item {
282282
cx.sess.next_node_id()))])
283283
} else {
284284
let mi = attr::mk_name_value_item_str(@"vers", @"0.8-pre");
285-
ast::view_item_extern_mod(id_extra, ~[mi], cx.sess.next_node_id())
285+
ast::view_item_extern_mod(id_extra, None, ~[mi], cx.sess.next_node_id())
286286
};
287287
ast::view_item {
288288
node: vi,

src/librustc/metadata/common.rs

+2
Original file line numberDiff line numberDiff line change
@@ -185,5 +185,7 @@ pub static tag_item_impl_vtables: uint = 0x82;
185185
pub struct LinkMeta {
186186
name: @str,
187187
vers: @str,
188+
// Optional package ID
189+
package_id: Option<@str>, // non-None if this was a URL-like package ID
188190
extras_hash: @str
189191
}

0 commit comments

Comments
 (0)