diff --git a/doc/tutorial/ffi.md b/doc/tutorial/ffi.md index 7b90f64a6ba56..248da6edef488 100644 --- a/doc/tutorial/ffi.md +++ b/doc/tutorial/ffi.md @@ -189,7 +189,7 @@ microsecond-resolution timer. use std; type timeval = {mutable tv_sec: u32, mutable tv_usec: u32}; - #[link_name = ""] + #[nolink] native mod libc { fn gettimeofday(tv: *timeval, tz: *()) -> i32; } @@ -199,7 +199,7 @@ microsecond-resolution timer. ret (x.tv_sec as u64) * 1000_000_u64 + (x.tv_usec as u64); } -The `#[link_name = ""]` sets the name of the native module to the +The `#[nolink]` sets the name of the native module to the empty string to prevent the rust compiler from trying to link it. The standard C library is already linked with Rust programs. diff --git a/src/comp/metadata/creader.rs b/src/comp/metadata/creader.rs index 34da777a86435..9f74f7afece11 100644 --- a/src/comp/metadata/creader.rs +++ b/src/comp/metadata/creader.rs @@ -57,18 +57,31 @@ fn visit_item(e: env, i: @ast::item) { } either::left(msg) { e.sess.span_fatal(i.span, msg); } } + let cstore = e.sess.get_cstore(); let native_name = i.ident; - alt attr::get_meta_item_value_str_by_name(i.attrs, "link_name") { - some(nn) { native_name = nn; } - none. { } + let already_added = false; + if vec::len(attr::find_attrs_by_name(i.attrs, "nolink")) == 0u { + alt attr::get_meta_item_value_str_by_name(i.attrs, "link_name") { + some(nn) { native_name = nn; } + none. { } + } + if native_name == "" { + e.sess.span_fatal(i.span, + "empty #[link_name] not allowed; use #[nolink]."); + } + already_added = !cstore::add_used_library(cstore, native_name); } - if !cstore::add_used_library(cstore, native_name) { ret; } - for a: ast::attribute in - attr::find_attrs_by_name(i.attrs, "link_args") { - + let link_args = attr::find_attrs_by_name(i.attrs, "link_args"); + if vec::len(link_args) > 0u && already_added { + e.sess.span_fatal(i.span, "library '" + native_name + + "' already added: can't specify link_args."); + } + for a: ast::attribute in link_args { alt attr::get_meta_item_value_str(attr::attr_meta(a)) { - some(linkarg) { cstore::add_used_link_args(cstore, linkarg); } + some(linkarg) { + cstore::add_used_link_args(cstore, linkarg); + } none. {/* fallthrough */ } } } diff --git a/src/comp/metadata/cstore.rs b/src/comp/metadata/cstore.rs index de74591c814ee..e0c0d49348df4 100644 --- a/src/comp/metadata/cstore.rs +++ b/src/comp/metadata/cstore.rs @@ -90,10 +90,9 @@ fn get_used_crate_files(cstore: cstore) -> [str] { } fn add_used_library(cstore: cstore, lib: str) -> bool { - if lib == "" { ret false; } + assert lib != ""; if vec::member(lib, p(cstore).used_libraries) { ret false; } - p(cstore).used_libraries += [lib]; ret true; } diff --git a/src/libstd/linux_os.rs b/src/libstd/linux_os.rs index 8528057ed98f7..e5b13a7cfc2a6 100644 --- a/src/libstd/linux_os.rs +++ b/src/libstd/linux_os.rs @@ -24,7 +24,8 @@ export fsync_fd; // FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult // by https://github.com/graydon/rust/issues#issue/268 -#[link_name = ""] +#[link_name = ""] // FIXME remove after #[nolink] is snapshotted +#[nolink] #[abi = "cdecl"] native mod libc { fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t; diff --git a/src/libstd/macos_os.rs b/src/libstd/macos_os.rs index 72afcc234b3cb..37a7d0ff95f2f 100644 --- a/src/libstd/macos_os.rs +++ b/src/libstd/macos_os.rs @@ -18,7 +18,7 @@ export fsync_fd; // FIXME Refactor into unix_os module or some such. Doesn't // seem to work right now. -#[link_name = ""] +#[nolink] #[abi = "cdecl"] native mod libc { fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t; @@ -118,7 +118,8 @@ native mod rustrt { fn getcwd() -> str { ret rustrt::rust_getcwd(); } -#[link_name = ""] +#[link_name = ""] // FIXME remove after #[nolink] is snapshotted +#[nolink] #[abi = "cdecl"] native mod mac_libc { fn _NSGetExecutablePath(buf: str::sbuf, diff --git a/src/libstd/win32_os.rs b/src/libstd/win32_os.rs index 439a79ec7acd5..825f4ffa0ebd2 100644 --- a/src/libstd/win32_os.rs +++ b/src/libstd/win32_os.rs @@ -2,7 +2,8 @@ import core::option; import ctypes::*; #[abi = "cdecl"] -#[link_name = ""] +#[link_name = ""] // FIXME remove after #[nolink] is snapshotted +#[nolink] native mod libc { fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t; fn write(fd: fd_t, buf: *u8, count: size_t) -> ssize_t; diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index a560e6e1d7a9f..cf4daa6b2ec0d 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -2,7 +2,7 @@ // http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod llvm { fn sqrt(n: float) -> float; } diff --git a/src/test/compile-fail/empty-linkname.rs b/src/test/compile-fail/empty-linkname.rs new file mode 100644 index 0000000000000..1e04913884bf0 --- /dev/null +++ b/src/test/compile-fail/empty-linkname.rs @@ -0,0 +1,5 @@ +// error-pattern:empty #[link_name] not allowed; use #[nolink]. + +#[link_name = ""] +native mod foo { +} diff --git a/src/test/compile-fail/nolink-with-link-args.rs b/src/test/compile-fail/nolink-with-link-args.rs new file mode 100644 index 0000000000000..07efff7571c33 --- /dev/null +++ b/src/test/compile-fail/nolink-with-link-args.rs @@ -0,0 +1,11 @@ +// error-pattern:aFdEfSeVEE + +/* We're testing that link_args are indeed passed when nolink is specified. +So we try to compile with junk link_args and make sure they are visible in +the compiler output. */ + +#[link_args = "aFdEfSeVEEE"] +#[nolink] +native mod m1 { } + +fn main() { } \ No newline at end of file diff --git a/src/test/compile-fail/redundant-link-args.rs b/src/test/compile-fail/redundant-link-args.rs new file mode 100644 index 0000000000000..ca06125880e3d --- /dev/null +++ b/src/test/compile-fail/redundant-link-args.rs @@ -0,0 +1,17 @@ +// error-pattern:library 'm' already added: can't specify link_args. + +/* I think it should undefined to have multiple modules that link in the same + library, but provide different link arguments. Unfortunately we don't track + link_args by module -- they are just appended as discovered into the crate + store -- but for now, it should be an error to provide link_args on a module + that's already been included (with or without link_args). */ + +#[link_name= "m"] +#[link_args="-foo"] // this could have been elided. +native mod m1 { +} + +#[link_name= "m"] +#[link_args="-bar"] // this is the actual error trigger. +native mod m2 { +} diff --git a/src/test/run-pass/bind-native-fn.rs b/src/test/run-pass/bind-native-fn.rs index aab3ba2dc7564..2984f97813b66 100644 --- a/src/test/run-pass/bind-native-fn.rs +++ b/src/test/run-pass/bind-native-fn.rs @@ -5,7 +5,7 @@ use std; import str; import ctypes::*; -#[link_name = ""] +#[nolink] native mod libc { fn write(fd: c_int, buf: *u8, nbyte: size_t); } diff --git a/src/test/run-pass/binops.rs b/src/test/run-pass/binops.rs index 3eedf7f48ca34..56469dbb17262 100644 --- a/src/test/run-pass/binops.rs +++ b/src/test/run-pass/binops.rs @@ -118,7 +118,7 @@ fn test_fn() { } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod test { fn do_gc(); fn unsupervise(); diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index 879db89b71357..66c79290e4726 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -2,7 +2,7 @@ use std; import str; #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod libc { fn atol(x: str::sbuf) -> int; fn atoll(x: str::sbuf) -> i64; diff --git a/src/test/run-pass/import-glob-1.rs b/src/test/run-pass/import-glob-1.rs index e40d6cbb9cc23..24a15e284d4e9 100644 --- a/src/test/run-pass/import-glob-1.rs +++ b/src/test/run-pass/import-glob-1.rs @@ -21,7 +21,7 @@ mod a1 { mod a2 { // | | | #[abi = "cdecl"] - #[link_name = ""] + #[nolink] native mod b1 { // | | | import a1::b2::*; diff --git a/src/test/run-pass/native-fn-linkname.rs b/src/test/run-pass/native-fn-linkname.rs index 98f429f8cb0dc..72d0ab01f9661 100644 --- a/src/test/run-pass/native-fn-linkname.rs +++ b/src/test/run-pass/native-fn-linkname.rs @@ -3,7 +3,7 @@ use std; import vec; import str; -#[link_name = ""] +#[nolink] #[abi = "cdecl"] native mod libc { #[link_name = "strlen"] diff --git a/src/test/run-pass/native-opaque-type.rs b/src/test/run-pass/native-opaque-type.rs index e8df623d1b870..e91b4e684b763 100644 --- a/src/test/run-pass/native-opaque-type.rs +++ b/src/test/run-pass/native-opaque-type.rs @@ -1,7 +1,7 @@ #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod libc { type file_handle; } diff --git a/src/test/run-pass/native2.rs b/src/test/run-pass/native2.rs index 07cb455cf0fe0..359ce18090f39 100644 --- a/src/test/run-pass/native2.rs +++ b/src/test/run-pass/native2.rs @@ -6,21 +6,21 @@ native mod rustrt { } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod bar { } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod zed { } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod libc { fn write(fd: int, buf: *u8, count: uint) -> int; } #[abi = "cdecl"] -#[link_name = ""] +#[nolink] native mod baz { } fn main(args: [str]) { } diff --git a/src/test/stdtest/c_vec.rs b/src/test/stdtest/c_vec.rs index d196a7baa3b29..65a6fc9c0bee1 100644 --- a/src/test/stdtest/c_vec.rs +++ b/src/test/stdtest/c_vec.rs @@ -5,7 +5,7 @@ use std; import std::c_vec::*; import ctypes::*; -#[link_name = ""] +#[nolink] #[abi = "cdecl"] native mod libc { fn malloc(n: size_t) -> *mutable u8;