Skip to content

Commit 57e9a2f

Browse files
committed
Make -Z gen-crate-map usable for I/O
In #10422, I didn't actually test to make sure that the '-Z gen-crate-map' option was usable before I implemented it. The crate map was indeed generated when '-Z gen-crate-map' was specified, but the I/O factory slot was empty because of an extra check in trans about filling in that location. This commit both fixes that location, and checks in a "fancy test" which does lots of fun stuff. The test will use the rustc library to compile a rust crate, and then compile a C program to link against that crate and run the C program. To my knowledge this is the first test of its kind, so it's a little ad-hoc, but it seems to get the job done. We could perhaps generalize running tests like this, but for now I think it's fine to have this sort of functionality tucked away in a test.
1 parent c0b7972 commit 57e9a2f

File tree

4 files changed

+140
-10
lines changed

4 files changed

+140
-10
lines changed

src/librustc/middle/trans/base.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ use extra::time;
7777
use extra::sort;
7878
use syntax::ast::Name;
7979
use syntax::ast_map::{path, path_elt_to_str, path_name, path_pretty_name};
80-
use syntax::ast_util::{local_def};
80+
use syntax::ast_util::{local_def, is_local};
8181
use syntax::attr;
8282
use syntax::attr::AttrMetaMethods;
8383
use syntax::codemap::Span;
@@ -2979,7 +2979,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
29792979
return map;
29802980
}
29812981

2982-
pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
2982+
pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) {
29832983
let mut subcrates: ~[ValueRef] = ~[];
29842984
let mut i = 1;
29852985
let cstore = ccx.sess.cstore;
@@ -2997,19 +2997,20 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
29972997
subcrates.push(p2i(ccx, cr));
29982998
i += 1;
29992999
}
3000-
let event_loop_factory = if !*ccx.sess.building_library {
3001-
match ccx.tcx.lang_items.event_loop_factory() {
3002-
Some(did) => unsafe {
3000+
let event_loop_factory = match ccx.tcx.lang_items.event_loop_factory() {
3001+
Some(did) => unsafe {
3002+
if is_local(did) {
3003+
llvm::LLVMConstPointerCast(get_item_val(ccx, did.node),
3004+
ccx.int_type.ptr_to().to_ref())
3005+
} else {
30033006
let name = csearch::get_symbol(ccx.sess.cstore, did);
30043007
let global = do name.with_c_str |buf| {
30053008
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
30063009
};
30073010
global
3008-
},
3009-
None => C_null(ccx.int_type.ptr_to())
3010-
}
3011-
} else {
3012-
C_null(ccx.int_type.ptr_to())
3011+
}
3012+
},
3013+
None => C_null(ccx.int_type.ptr_to())
30133014
};
30143015
unsafe {
30153016
let maptype = Type::array(&ccx.int_type, subcrates.len() as u64);
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This test exercises bootstrapping the runtime from C to make sure that this
12+
// continues to work. The runtime is expected to have all local I/O services
13+
// that one would normally expect.
14+
15+
#[feature(managed_boxes)];
16+
17+
extern mod extra;
18+
extern mod rustc;
19+
extern mod syntax;
20+
21+
use extra::glob;
22+
use extra::tempfile::TempDir;
23+
use rustc::back::link;
24+
use rustc::driver::driver;
25+
use rustc::driver::session;
26+
use std::os;
27+
use std::rt::io::fs;
28+
use std::run;
29+
use std::str;
30+
use syntax::diagnostic;
31+
32+
fn main() {
33+
// Sketchily figure out where our sysroot is
34+
let mut sysroot = Path::new(os::self_exe_path().unwrap());
35+
sysroot.pop();
36+
sysroot.pop();
37+
sysroot.push("stage2");
38+
39+
// Give ourselves a little workspace
40+
let d = TempDir::new("mytest").unwrap();
41+
let d = d.path();
42+
43+
// Figure out where we are
44+
let mut me = Path::new(file!());
45+
me.pop();
46+
let srcfile = me.join("bootstrap-from-c/lib.rs");
47+
let cfile = me.join("bootstrap-from-c/main.c");
48+
49+
// Compile the rust crate
50+
let options = @session::options {
51+
maybe_sysroot: Some(@sysroot),
52+
debugging_opts: session::gen_crate_map,
53+
..(*session::basic_options()).clone()
54+
};
55+
let diagnostic = @diagnostic::DefaultEmitter as @diagnostic::Emitter;
56+
let session = driver::build_session(options, diagnostic);
57+
driver::compile_input(session, ~[], &driver::file_input(srcfile),
58+
&Some(d.clone()), &None);
59+
60+
// Copy the C source into place
61+
let cdst = d.join("main.c");
62+
let exe = d.join("out" + os::consts::EXE_SUFFIX);
63+
fs::copy(&cfile, &cdst);
64+
65+
// Figure out where we put the dynamic library
66+
let dll = os::dll_filename("boot-*");
67+
let dll = glob::glob(d.as_str().unwrap() + "/" + dll).next().unwrap();
68+
69+
// Compile the c program with all the appropriate arguments. We're compiling
70+
// the cfile and the library together, and may have to do some linker rpath
71+
// magic to make sure that the dll can get found when the executable is
72+
// running.
73+
let cc = link::get_cc_prog(session);
74+
let mut cc_args = session.targ_cfg.target_strs.cc_args.clone();
75+
cc_args.push_all([~"-o", exe.as_str().unwrap().to_owned()]);
76+
cc_args.push(cdst.as_str().unwrap().to_owned());
77+
cc_args.push(dll.as_str().unwrap().to_owned());
78+
if cfg!(target_os = "macos") {
79+
cc_args.push("-Wl,-rpath," + d.as_str().unwrap().to_owned());
80+
}
81+
let status = run::process_status(cc, cc_args);
82+
assert!(status.success());
83+
84+
// Finally, run the program and make sure that it tells us hello.
85+
let res = run::process_output(exe.as_str().unwrap().to_owned(), []);
86+
assert!(res.status.success());
87+
assert_eq!(str::from_utf8(res.output), ~"hello\n");
88+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[link(package_id = "boot", name = "boot", vers = "0.1")];
12+
13+
extern mod rustuv; // pull in uvio
14+
15+
use std::rt;
16+
use std::ptr;
17+
18+
#[no_mangle] // this needs to get called from C
19+
pub extern "C" fn foo(argc: int, argv: **u8) -> int {
20+
do rt::start(argc, argv) {
21+
do spawn {
22+
println!("hello");
23+
}
24+
}
25+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// this is the rust entry point that we're going to call.
12+
int foo(int argc, char *argv[]);
13+
14+
int main(int argc, char *argv[]) {
15+
return foo(argc, argv);
16+
}

0 commit comments

Comments
 (0)