auto merge of : alexcrichton/rust/no-crate-map, r=brson

This can be done now that logging has been moved out and libnative is the default (not libgreen)
This commit is contained in:
bors 2014-03-26 01:41:57 -07:00
commit de85948ac0
30 changed files with 116 additions and 338 deletions
src
compiletest
doc
libgreen
librustc
librustuv
libstd
test
run-make
bootstrap-from-c-with-green
bootstrap-from-c-with-native
c-link-to-rust-staticlib
c-set-crate-map-manually
lto-smoke-c
run-pass

@ -43,7 +43,9 @@ pub mod common;
pub mod errors;
#[start]
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, rustuv::event_loop, main)
}
pub fn main() {
let args = os::args();

@ -223,27 +223,49 @@ Having a default decision made in the compiler is done out of necessity and
convenience. The compiler's decision of runtime to link to is *not* an
endorsement of one over the other. As always, this decision can be overridden.
For example, this program will be linked to "the default runtime"
For example, this program will be linked to "the default runtime". The current
default runtime is to use libnative.
~~~{.rust}
fn main() {}
~~~
Whereas this program explicitly opts into using a particular runtime
### Force booting with libgreen
In this example, the `main` function will be booted with I/O support powered by
libuv. This is done by linking to the `rustuv` crate and specifying the
`rustuv::event_loop` function as the event loop factory.
To create a pool of green tasks which have no I/O support, you may shed the
`rustuv` dependency and use the `green::basic::event_loop` function instead of
`rustuv::event_loop`. All tasks will have no I/O support, but they will still be
able to deschedule/reschedule (use channels, locks, etc).
~~~{.rust}
extern crate green;
extern crate rustuv;
#[start]
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, main)
green::start(argc, argv, rustuv::event_loop, main)
}
fn main() {}
~~~
Both libgreen/libnative provide a top-level `start` function which is used to
boot an initial Rust task in that specified runtime.
### Force booting with libnative
This program's `main` function will always be booted with libnative, running
inside of an OS thread.
~~~{.rust}
extern crate native;
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }
fn main() {}
~~~
# Finding the runtime

@ -237,7 +237,7 @@ mod test {
fn pool() -> SchedPool {
SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: Some(basic::event_loop),
event_loop_factory: basic::event_loop,
})
}
@ -267,7 +267,7 @@ mod test {
fn multi_thread() {
let mut pool = SchedPool::new(PoolConfig {
threads: 2,
event_loop_factory: Some(basic::event_loop),
event_loop_factory: basic::event_loop,
});
for _ in range(0, 20) {

@ -116,13 +116,34 @@
//! extern crate green;
//!
//! #[start]
//! fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }
//! fn start(argc: int, argv: **u8) -> int {
//! green::start(argc, argv, green::basic::event_loop, main)
//! }
//!
//! fn main() {
//! // this code is running in a pool of schedulers
//! }
//! ```
//!
//! > **Note**: This `main` funciton in this example does *not* have I/O
//! > support. The basic event loop does not provide any support
//!
//! # Starting with I/O support in libgreen
//!
//! ```rust
//! extern crate green;
//! extern crate rustuv;
//!
//! #[start]
//! fn start(argc: int, argv: **u8) -> int {
//! green::start(argc, argv, rustuv::event_loop, main)
//! }
//!
//! fn main() {
//! // this code is running in a pool of schedulers all powered by libuv
//! }
//! ```
//!
//! # Using a scheduler pool
//!
//! ```rust
@ -176,11 +197,11 @@
#[allow(visible_private_types)];
#[cfg(test)] #[phase(syntax, link)] extern crate log;
#[cfg(test)] extern crate rustuv;
extern crate rand;
use std::mem::replace;
use std::os;
use std::rt::crate_map;
use std::rt::rtio;
use std::rt::thread::Thread;
use std::rt;
@ -225,12 +246,14 @@ pub mod task;
///
/// The return value is used as the process return code. 0 on success, 101 on
/// error.
pub fn start(argc: int, argv: **u8, main: proc()) -> int {
pub fn start(argc: int, argv: **u8,
event_loop_factory: fn() -> ~rtio::EventLoop,
main: proc()) -> int {
rt::init(argc, argv);
let mut main = Some(main);
let mut ret = None;
simple::task().run(|| {
ret = Some(run(main.take_unwrap()));
ret = Some(run(event_loop_factory, main.take_unwrap()));
});
// unsafe is ok b/c we're sure that the runtime is gone
unsafe { rt::cleanup() }
@ -245,10 +268,12 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
///
/// This function will not return until all schedulers in the associated pool
/// have returned.
pub fn run(main: proc()) -> int {
pub fn run(event_loop_factory: fn() -> ~rtio::EventLoop, main: proc()) -> int {
// Create a scheduler pool and spawn the main task into this pool. We will
// get notified over a channel when the main task exits.
let mut pool = SchedPool::new(PoolConfig::new());
let mut cfg = PoolConfig::new();
cfg.event_loop_factory = event_loop_factory;
let mut pool = SchedPool::new(cfg);
let (tx, rx) = channel();
let mut opts = TaskOpts::new();
opts.notify_chan = Some(tx);
@ -273,7 +298,7 @@ pub struct PoolConfig {
threads: uint,
/// A factory function used to create new event loops. If this is not
/// specified then the default event loop factory is used.
event_loop_factory: Option<fn() -> ~rtio::EventLoop>,
event_loop_factory: fn() -> ~rtio::EventLoop,
}
impl PoolConfig {
@ -282,7 +307,7 @@ impl PoolConfig {
pub fn new() -> PoolConfig {
PoolConfig {
threads: rt::default_sched_threads(),
event_loop_factory: None,
event_loop_factory: basic::event_loop,
}
}
}
@ -324,7 +349,6 @@ impl SchedPool {
threads: nscheds,
event_loop_factory: factory
} = config;
let factory = factory.unwrap_or(default_event_loop_factory());
assert!(nscheds > 0);
// The pool of schedulers that will be returned from this function
@ -493,20 +517,3 @@ impl Drop for SchedPool {
}
}
}
fn default_event_loop_factory() -> fn() -> ~rtio::EventLoop {
match crate_map::get_crate_map() {
None => {}
Some(map) => {
match map.event_loop_factory {
None => {}
Some(factory) => return factory
}
}
}
// If the crate map didn't specify a factory to create an event loop, then
// instead just use a basic event loop missing all I/O services to at least
// get the scheduler running.
return basic::event_loop;
}

@ -1003,6 +1003,8 @@ fn new_sched_rng() -> XorShiftRng {
#[cfg(test)]
mod test {
use rustuv;
use std::comm;
use std::task::TaskOpts;
use std::rt::Runtime;
@ -1017,7 +1019,7 @@ mod test {
fn pool() -> SchedPool {
SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: Some(basic::event_loop),
event_loop_factory: basic::event_loop,
})
}
@ -1262,7 +1264,7 @@ mod test {
let mut pool = SchedPool::new(PoolConfig {
threads: 2,
event_loop_factory: None,
event_loop_factory: rustuv::event_loop,
});
// This is a regression test that when there are no schedulable tasks in
@ -1413,7 +1415,7 @@ mod test {
fn dont_starve_1() {
let mut pool = SchedPool::new(PoolConfig {
threads: 2, // this must be > 1
event_loop_factory: Some(basic::event_loop),
event_loop_factory: basic::event_loop,
});
pool.spawn(TaskOpts::new(), proc() {
let (tx, rx) = channel();

@ -494,7 +494,7 @@ mod tests {
fn spawn_opts(opts: TaskOpts, f: proc()) {
let mut pool = SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: None,
event_loop_factory: ::rustuv::event_loop,
});
pool.spawn(opts, f);
pool.shutdown();

@ -451,8 +451,6 @@ cgoptions!(
"don't run LLVM's SLP vectorization pass"),
soft_float: bool = (false, parse_bool,
"generate software floating point library calls"),
gen_crate_map: bool = (false, parse_bool,
"force generation of a toplevel crate map"),
prefer_dynamic: bool = (false, parse_bool,
"prefer dynamic linking to static linking"),
no_integrated_as: bool = (false, parse_bool,

@ -254,8 +254,6 @@ lets_do_this! {
TyVisitorTraitLangItem, "ty_visitor", ty_visitor;
OpaqueStructLangItem, "opaque", opaque;
EventLoopFactoryLangItem, "event_loop_factory", event_loop_factory;
TypeIdLangItem, "type_id", type_id;
EhPersonalityLangItem, "eh_personality", eh_personality_fn;

@ -980,7 +980,7 @@ static other_attrs: &'static [&'static str] = &[
"thread_local", // for statics
"allow", "deny", "forbid", "warn", // lint options
"deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability
"crate_map", "cfg", "doc", "export_name", "link_section",
"cfg", "doc", "export_name", "link_section",
"no_mangle", "static_assert", "unsafe_no_drop_flag", "packed",
"simd", "repr", "deriving", "unsafe_destructor", "link", "phase",
"macro_export", "must_use", "automatically_derived",

@ -76,7 +76,7 @@ use std::c_str::ToCStr;
use std::cell::{Cell, RefCell};
use std::libc::c_uint;
use std::local_data;
use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic, OsWin32};
use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic};
use syntax::ast_map::PathName;
use syntax::ast_util::{local_def, is_local};
use syntax::attr::AttrMetaMethods;
@ -2316,65 +2316,6 @@ pub fn symname(name: &str, hash: &str, vers: &str) -> ~str {
link::exported_name(ast_map::Values(path.iter()).chain(None), hash, vers)
}
pub fn decl_crate_map(ccx: &mut CrateContext) {
let mut n_subcrates = 1;
while ccx.sess().cstore.have_crate_data(n_subcrates) {
n_subcrates += 1;
}
let is_top = !ccx.sess().building_library.get() || ccx.sess().opts.cg.gen_crate_map;
let sym_name = if is_top {
~"_rust_crate_map_toplevel"
} else {
symname("_rust_crate_map_" + ccx.link_meta.crateid.name,
ccx.link_meta.crate_hash.as_str(),
ccx.link_meta.crateid.version_or_default())
};
let maptype = Type::struct_(ccx, [
Type::i32(ccx), // version
ccx.int_type.ptr_to(), // event loop factory
], false);
let map = sym_name.with_c_str(|buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
}
});
lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage);
// On windows we'd like to export the toplevel cratemap
// such that we can find it from libstd.
if ccx.sess().targ_cfg.os == OsWin32 && is_top {
unsafe { llvm::LLVMRustSetDLLExportStorageClass(map) }
}
ccx.crate_map_name = sym_name;
ccx.crate_map = map;
}
pub fn fill_crate_map(ccx: &CrateContext, map: ValueRef) {
let event_loop_factory = match ccx.tcx.lang_items.event_loop_factory() {
Some(did) => unsafe {
if is_local(did) {
llvm::LLVMConstPointerCast(get_item_val(ccx, did.node),
ccx.int_type.ptr_to().to_ref())
} else {
let name = csearch::get_symbol(&ccx.sess().cstore, did);
let global = name.with_c_str(|buf| {
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
});
global
}
},
None => C_null(ccx.int_type.ptr_to())
};
unsafe {
llvm::LLVMSetInitializer(map, C_struct(ccx,
[C_i32(ccx, 2),
event_loop_factory,
], false));
}
}
pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeInlinedItem<'r>)
-> encoder::EncodeParams<'r> {
@ -2467,26 +2408,6 @@ pub fn trans_crate(krate: ast::Crate,
trans_mod(&ccx, &krate.module);
}
fill_crate_map(&ccx, ccx.crate_map);
// win32: wart with exporting crate_map symbol
// We set the crate map (_rust_crate_map_toplevel) to use dll_export
// linkage but that ends up causing the linker to look for a
// __rust_crate_map_toplevel symbol (extra underscore) which it will
// subsequently fail to find. So to mitigate that we just introduce
// an alias from the symbol it expects to the one that actually exists.
if ccx.sess().targ_cfg.os == OsWin32 && !ccx.sess().building_library.get() {
let maptype = val_ty(ccx.crate_map).to_ref();
"__rust_crate_map_toplevel".with_c_str(|buf| {
unsafe {
llvm::LLVMAddAlias(ccx.llmod, maptype,
ccx.crate_map, buf);
}
})
}
glue::emit_tydescs(&ccx);
if ccx.sess().opts.debuginfo != NoDebugInfo {
debuginfo::finalize(&ccx);
@ -2537,7 +2458,6 @@ pub fn trans_crate(krate: ast::Crate,
// symbol. This symbol is required for use by the libmorestack library that
// we link in, so we must ensure that this symbol is not internalized (if
// defined in the crate).
reachable.push(ccx.crate_map_name.to_owned());
reachable.push(~"main");
reachable.push(~"rust_stack_exhausted");
reachable.push(~"rust_eh_personality"); // referenced from .eh_frame section on some platforms

@ -22,7 +22,6 @@ use middle::trans::base;
use middle::trans::builder::Builder;
use middle::trans::common::{C_i32, C_null};
use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
use middle::trans::base::{decl_crate_map};
use middle::trans::debuginfo;
use middle::trans::type_::Type;
use middle::ty;
@ -105,8 +104,6 @@ pub struct CrateContext {
int_type: Type,
opaque_vec_type: Type,
builder: BuilderRef_res,
crate_map: ValueRef,
crate_map_name: ~str,
// Set when at least one function uses GC. Needed so that
// decl_gc_metadata knows whether to link to the module metadata, which
// is not emitted by LLVM's GC pass when no functions use GC.
@ -200,8 +197,6 @@ impl CrateContext {
int_type: Type::from_ref(ptr::null()),
opaque_vec_type: Type::from_ref(ptr::null()),
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
crate_map: ptr::null(),
crate_map_name: ~"",
uses_gc: false,
dbg_cx: dbg_cx,
};
@ -215,8 +210,6 @@ impl CrateContext {
str_slice_ty.set_struct_body([Type::i8p(&ccx), ccx.int_type], false);
ccx.tn.associate_type("str_slice", &str_slice_ty);
decl_crate_map(&mut ccx);
base::declare_intrinsics(&mut ccx);
if ccx.sess().count_llvm_insns() {

@ -134,28 +134,6 @@ pub fn register_static(ccx: &CrateContext,
let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
let llty = type_of::type_of(ccx, ty);
// Treat the crate map static specially in order to
// a weak-linkage-like functionality where it's
// dynamically resolved at runtime. If we're
// building a library, then we declare the static
// with weak linkage, but if we're building a
// library then we've already declared the crate map
// so use that instead.
if attr::contains_name(foreign_item.attrs.as_slice(), "crate_map") {
return if ccx.sess().building_library.get() {
let s = "_rust_crate_map_toplevel";
let g = unsafe {
s.with_c_str(|buf| {
llvm::LLVMAddGlobal(ccx.llmod, llty.to_ref(), buf)
})
};
lib::llvm::SetLinkage(g, lib::llvm::ExternalWeakLinkage);
g
} else {
ccx.crate_map
}
}
let ident = link_name(foreign_item);
match attr::first_attr_value_str_by_name(foreign_item.attrs.as_slice(),
"linkage") {

@ -167,7 +167,7 @@ mod test {
let (tx, rx) = channel();
let mut pool = SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: None,
event_loop_factory: ::event_loop,
});
pool.spawn(TaskOpts::new(), proc() {
@ -188,7 +188,7 @@ mod test {
let (tx, rx) = channel();
let mut pool = SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: None,
event_loop_factory: ::event_loop,
});
pool.spawn(TaskOpts::new(), proc() {

@ -54,6 +54,7 @@ use std::libc::{c_int, c_void};
use std::ptr::null;
use std::ptr;
use std::rt::local::Local;
use std::rt::rtio;
use std::rt::task::{BlockedTask, Task};
use std::str::raw::from_c_str;
use std::str;
@ -76,7 +77,7 @@ pub use self::tty::TtyWatcher;
// '__test' module.
#[cfg(test)] #[start]
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, __test::main)
green::start(argc, argv, event_loop, __test::main)
}
mod macros;
@ -104,6 +105,31 @@ pub mod tty;
pub mod signal;
pub mod stream;
/// Creates a new event loop which is powered by libuv
///
/// This function is used in tandem with libgreen's `PoolConfig` type as a value
/// for the `event_loop_factory` field. Using this function as the event loop
/// factory will power programs with libuv and enable green threading.
///
/// # Example
///
/// ```
/// extern crate rustuv;
/// extern crate green;
///
/// #[start]
/// fn start(argc: int, argv: **u8) -> int {
/// green::start(argc, argv, rustuv::event_loop, main)
/// }
///
/// fn main() {
/// // this code is running inside of a green task powered by libuv
/// }
/// ```
pub fn event_loop() -> ~rtio::EventLoop {
~uvio::UvEventLoop::new() as ~rtio::EventLoop
}
/// A type that wraps a uv handle
pub trait UvHandle<T> {
fn uv_handle(&self) -> *T;

@ -105,12 +105,6 @@ impl rtio::EventLoop for UvEventLoop {
}
}
#[cfg(not(test))]
#[lang = "event_loop_factory"]
pub fn new_loop() -> ~rtio::EventLoop {
~UvEventLoop::new() as ~rtio::EventLoop
}
#[test]
fn test_callback_run_once() {
use std::rt::rtio::EventLoop;

@ -84,7 +84,7 @@
// '__test' module.
#[cfg(test)] #[start]
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, __test::main)
green::start(argc, argv, rustuv::event_loop, __test::main)
}
pub mod macros;

@ -1,104 +0,0 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use cast;
use option::{Some, None, Option};
use ptr::RawPtr;
use rt::rtio::EventLoop;
// Need to tell the linker on OS X to not barf on undefined symbols
// and instead look them up at runtime, which we need to resolve
// the crate_map properly.
#[cfg(target_os = "macos")]
#[link_args = "-Wl,-U,__rust_crate_map_toplevel"]
extern {}
pub struct CrateMap<'a> {
version: i32,
event_loop_factory: Option<fn() -> ~EventLoop>,
}
// When working on android, apparently weak symbols don't work so well for
// finding the crate map, and neither does dlopen + dlsym. This is mainly a
// problem when integrating a shared library with an existing application.
// Standalone binaries do not appear to have this problem. The reasons are a
// little mysterious, and more information can be found in #11731.
//
// For now we provide a way to tell libstd about the crate map manually that's
// checked before the normal weak symbol/dlopen paths. In theory this is useful
// on other platforms where our dlopen/weak linkage strategy mysteriously fails
// but the crate map can be specified manually.
static mut MANUALLY_PROVIDED_CRATE_MAP: *CrateMap<'static> =
0 as *CrateMap<'static>;
#[no_mangle]
#[cfg(not(test))]
pub extern fn rust_set_crate_map(map: *CrateMap<'static>) {
unsafe { MANUALLY_PROVIDED_CRATE_MAP = map; }
}
fn manual_crate_map() -> Option<&'static CrateMap<'static>> {
unsafe {
if MANUALLY_PROVIDED_CRATE_MAP.is_null() {
None
} else {
Some(cast::transmute(MANUALLY_PROVIDED_CRATE_MAP))
}
}
}
#[cfg(not(windows))]
pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
extern {
#[crate_map]
static CRATE_MAP: CrateMap<'static>;
}
manual_crate_map().or_else(|| {
let ptr: (*CrateMap) = &'static CRATE_MAP;
if ptr.is_null() {
None
} else {
Some(&'static CRATE_MAP)
}
})
}
#[cfg(windows)]
pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
use c_str::ToCStr;
use unstable::dynamic_lib::dl;
match manual_crate_map() {
Some(cm) => return Some(cm),
None => {}
}
let sym = unsafe {
let module = dl::open_internal();
let rust_crate_map_toplevel = if cfg!(target_arch = "x86") {
"__rust_crate_map_toplevel"
} else {
"_rust_crate_map_toplevel"
};
let sym = rust_crate_map_toplevel.with_c_str(|buf| {
dl::symbol(module, buf)
});
dl::close(module);
sym
};
let ptr: (*CrateMap) = sym as *CrateMap;
if ptr.is_null() {
return None;
} else {
unsafe {
return Some(cast::transmute(sym));
}
}
}

@ -104,9 +104,6 @@ pub mod env;
/// The local, managed heap
pub mod local_heap;
/// Crate map
pub mod crate_map;
/// The runtime needs to be able to put a pointer into thread-local storage.
mod local_ptr;

@ -1,7 +1,7 @@
-include ../tools.mk
all:
$(RUSTC) lib.rs -C gen-crate-map
$(RUSTC) lib.rs
ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot)
$(CC) main.c -o $(call RUN,main) -lboot
$(call RUN,main)

@ -16,7 +16,7 @@ extern crate green;
#[no_mangle] // this needs to get called from C
pub extern "C" fn foo(argc: int, argv: **u8) -> int {
green::start(argc, argv, proc() {
green::start(argc, argv, rustuv::event_loop, proc() {
spawn(proc() {
println!("hello");
});

@ -1,7 +1,7 @@
-include ../tools.mk
all:
$(RUSTC) lib.rs -C gen-crate-map
$(RUSTC) lib.rs
ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot)
$(CC) main.c -o $(call RUN,main) -lboot
$(call RUN,main)

@ -5,7 +5,7 @@ ifneq ($(shell uname),Darwin)
endif
all:
$(RUSTC) foo.rs -C gen-crate-map
$(RUSTC) foo.rs
ln -s $(call STATICLIB,foo-*) $(call STATICLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN,bar) $(EXTRAFLAGS) -lstdc++
$(call RUN,bar)

@ -1,7 +0,0 @@
-include ../tools.mk
all:
$(RUSTC) lib.rs -C gen-crate-map
ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot)
$(CC) main.c -o $(call RUN,main) -lboot -Wl,-rpath,$(TMPDIR)
RUST_LOG=boot $(call RUN,main)

@ -1,32 +0,0 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[crate_id="boot#0.1"];
#[crate_type="dylib"];
#[no_uv];
#[feature(phase)];
extern crate rustuv;
extern crate green;
#[phase(syntax, link)] extern crate log;
use std::rt::crate_map::{CrateMap, rust_set_crate_map};
// pull in this symbol from libstd into this crate (for convenience)
#[no_mangle]
pub static set_crate_map: extern "C" fn(*CrateMap<'static>) = rust_set_crate_map;
#[no_mangle] // this needs to get called from C
pub extern "C" fn foo(argc: int, argv: **u8) -> int {
green::start(argc, argv, proc() {
if log_enabled!(log::DEBUG) { return }
fail!()
})
}

@ -1,20 +0,0 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// this is the rust entry point that we're going to call.
int foo(int argc, char *argv[]);
extern void (*set_crate_map)(void *map);
extern int _rust_crate_map_toplevel;
int main(int argc, char *argv[]) {
set_crate_map(&_rust_crate_map_toplevel);
return foo(argc, argv);
}

@ -5,7 +5,7 @@ ifneq ($(shell uname),Darwin)
endif
all:
$(RUSTC) foo.rs -C gen-crate-map -Z lto
$(RUSTC) foo.rs -Z lto
ln -s $(call STATICLIB,foo-*) $(call STATICLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN,bar) $(EXTRAFLAGS) -lstdc++
$(call RUN,bar)

@ -49,7 +49,7 @@ macro_rules! iotest (
#[cfg(test)] #[start]
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, __test::main)
green::start(argc, argv, rustuv::event_loop, __test::main)
}
iotest!(fn test_destroy_once() {

@ -15,7 +15,9 @@ extern crate green;
extern crate rustuv;
#[start]
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, rustuv::event_loop, main)
}
fn main() {
native::task::spawn(proc() customtask());

@ -18,7 +18,7 @@ static mut DROP_T: int = 0i;
#[start]
fn start(argc: int, argv: **u8) -> int {
let ret = green::start(argc, argv, main);
let ret = green::start(argc, argv, green::basic::event_loop, main);
unsafe {
assert_eq!(2, DROP);
assert_eq!(1, DROP_S);

@ -28,7 +28,9 @@ use std::io::process;
use std::io::signal::{Listener, Interrupt};
#[start]
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, rustuv::event_loop, main)
}
fn main() {
unsafe { libc::setsid(); }