Skip to content

Commit f77784b

Browse files
committed
auto merge of #13857 : alexcrichton/rust/add-dylib-paths, r=brson
When a syntax extension is loaded by the compiler, the dylib that is opened may have other dylibs that it depends on. The dynamic linker must be able to find these libraries on the system or else the library will fail to load. Currently, unix gets by with the use of rpaths. This relies on the dylib not moving around too drastically relative to its dependencies. For windows, however, this is no rpath available, and in theory unix should work without rpaths as well. This modifies the compiler to add all -L search directories to the dynamic linker's set of load paths. This is currently managed through environment variables for each platform. Closes #13848
2 parents cbf1131 + 1a367c6 commit f77784b

File tree

7 files changed

+114
-3
lines changed

7 files changed

+114
-3
lines changed

src/liblibc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ pub use funcs::bsd43::{shutdown};
231231
#[cfg(windows)] pub use types::os::arch::extra::{HANDLE, BOOL, LPSECURITY_ATTRIBUTES};
232232
#[cfg(windows)] pub use types::os::arch::extra::{LPCSTR, WORD, DWORD, BYTE, FILETIME};
233233
#[cfg(windows)] pub use types::os::arch::extra::{LARGE_INTEGER, LPVOID, LONG};
234-
#[cfg(windows)] pub use types::os::arch::extra::{time64_t, OVERLAPPED};
234+
#[cfg(windows)] pub use types::os::arch::extra::{time64_t, OVERLAPPED, LPCWSTR};
235235
#[cfg(windows)] pub use types::os::arch::extra::{LPOVERLAPPED, SIZE_T, LPDWORD};
236236
#[cfg(windows)] pub use funcs::c95::string::{wcslen};
237237
#[cfg(windows)] pub use funcs::posix88::stat_::{wstat, wutime, wchmod, wrmdir};

src/librustc/driver/driver.rs

+8
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,14 @@ pub fn phase_2_configure_and_expand(sess: &Session,
232232
front::config::strip_unconfigured_items(krate));
233233

234234
krate = time(time_passes, "expansion", krate, |krate| {
235+
// Windows dlls do not have rpaths, so they don't know how to find their
236+
// dependencies. It's up to use to tell the system where to find all the
237+
// dependent dlls. Note that this uses cfg!(windows) as opposed to
238+
// targ_cfg because syntax extensions are always loaded for the host
239+
// compiler, not for the target.
240+
if cfg!(windows) {
241+
sess.host_filesearch().add_dylib_search_paths();
242+
}
235243
let cfg = syntax::ext::expand::ExpansionConfig {
236244
loader: loader,
237245
deriving_hash_type_parameter: sess.features.default_type_params.get(),

src/librustc/metadata/filesearch.rs

+8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use std::cell::RefCell;
1414
use std::os;
1515
use std::io::fs;
16+
use std::unstable::dynamic_lib::DynamicLibrary;
1617
use collections::HashSet;
1718

1819
use myfs = util::fs;
@@ -132,6 +133,13 @@ impl<'a> FileSearch<'a> {
132133
triple: triple,
133134
}
134135
}
136+
137+
pub fn add_dylib_search_paths(&self) {
138+
self.for_each_lib_search_path(|lib_search_path| {
139+
DynamicLibrary::add_search_path(lib_search_path);
140+
FileDoesntMatch
141+
})
142+
}
135143
}
136144

137145
pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> Path {

src/libstd/unstable/dynamic_lib.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ Dynamic library facilities.
1515
A simple wrapper over the platform's dynamic library facilities
1616
1717
*/
18+
1819
use c_str::ToCStr;
1920
use cast;
20-
use path;
2121
use ops::*;
2222
use option::*;
23+
use os;
24+
use path::GenericPath;
25+
use path;
2326
use result::*;
27+
use str;
2428

2529
pub struct DynamicLibrary { handle: *u8}
2630

@@ -59,6 +63,20 @@ impl DynamicLibrary {
5963
}
6064
}
6165

66+
/// Appends a path to the system search path for dynamic libraries
67+
pub fn add_search_path(path: &path::Path) {
68+
let (envvar, sep) = if cfg!(windows) {
69+
("PATH", ';' as u8)
70+
} else if cfg!(target_os = "macos") {
71+
("DYLD_LIBRARY_PATH", ':' as u8)
72+
} else {
73+
("LD_LIBRARY_PATH", ':' as u8)
74+
};
75+
let newenv = os::getenv_as_bytes(envvar).unwrap_or(~[]);
76+
let newenv = newenv + &[sep] + path.as_vec();
77+
os::setenv(envvar, str::from_utf8(newenv).unwrap());
78+
}
79+
6280
/// Access the value at the symbol of the dynamic library
6381
pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, ~str> {
6482
// This function should have a lifetime constraint of 'a on
@@ -237,7 +255,6 @@ pub mod dl {
237255
FreeLibrary(handle as *libc::c_void); ()
238256
}
239257

240-
#[link_name = "kernel32"]
241258
extern "system" {
242259
fn SetLastError(error: libc::size_t);
243260
fn LoadLibraryW(name: *libc::c_void) -> *libc::c_void;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2014 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+
// no-prefer-dynamic
12+
// force-host
13+
14+
#![crate_type = "dylib"]
15+
16+
pub fn the_answer() -> int {
17+
2
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2014 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+
// force-host
12+
// no-prefer-dynamic
13+
14+
#![crate_type = "dylib"]
15+
#![feature(macro_registrar, quote, globs)]
16+
17+
extern crate other = "syntax-extension-with-dll-deps-1";
18+
extern crate syntax;
19+
20+
use syntax::ast::{Name, TokenTree, Item, MetaItem};
21+
use syntax::codemap::Span;
22+
use syntax::ext::base::*;
23+
use syntax::parse::token;
24+
25+
#[macro_registrar]
26+
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
27+
register(token::intern("foo"),
28+
NormalTT(~BasicMacroExpander {
29+
expander: expand_foo,
30+
span: None,
31+
},
32+
None));
33+
}
34+
35+
fn expand_foo(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> ~MacResult {
36+
let answer = other::the_answer();
37+
MacExpr::new(quote_expr!(cx, $answer))
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2014 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+
// aux-build:syntax-extension-with-dll-deps-1.rs
12+
// aux-build:syntax-extension-with-dll-deps-2.rs
13+
// ignore-stage1
14+
15+
#![feature(phase)]
16+
17+
#[phase(syntax)]
18+
extern crate extension = "syntax-extension-with-dll-deps-2";
19+
20+
fn main() {
21+
foo!();
22+
}

0 commit comments

Comments
 (0)