Skip to content

Commit 19ba9b4

Browse files
committed
Begin work on rpath
1 parent e963cfd commit 19ba9b4

File tree

4 files changed

+218
-2
lines changed

4 files changed

+218
-2
lines changed

src/comp/back/link.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import metadata::{encoder, cstore};
77
import middle::trans_common::crate_ctxt;
88
import std::str;
99
import std::fs;
10+
import std::os;
1011
import std::vec;
1112
import std::option;
1213
import std::run;
@@ -573,6 +574,8 @@ fn link_binary(sess: session::session,
573574

574575
gcc_args += ["-Lrt", "-lrustrt"];
575576

577+
gcc_args += rpath::get_rpath_flags(sess, saved_out_filename);
578+
576579
// We run 'gcc' here
577580
let err_code = run::run_program(prog, gcc_args);
578581
if 0 != err_code {

src/comp/back/rpath.rs

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
import std::os;
2+
import std::fs;
3+
import std::vec;
4+
import metadata::cstore;
5+
import driver::session;
6+
import util::filesearch;
7+
import std::map;
8+
9+
export get_rpath_flags, test;
10+
11+
#[cfg(target_os="linux")]
12+
#[cfg(target_os="macos")]
13+
fn get_rpath_flags(_sess: session::session, _out_filename: str) -> [str] {
14+
log "preparing the RPATH!";
15+
16+
// FIXME
17+
/*
18+
let cwd = os::getcwd();
19+
let sysroot = sess.filesearch().sysroot();
20+
let output = out_filename;
21+
let libs = cstore::get_used_crate_files(sess.get_cstore());
22+
let target_triple = sess.get_opts().target_triple;
23+
let rpaths = get_rpaths(cwd, sysroot, output, libs, target_triple);
24+
*/
25+
let rpaths = [];
26+
rpaths_to_flags(rpaths)
27+
}
28+
29+
#[cfg(target_os="win32")]
30+
fn get_rpath_flags(_sess: session::session, _out_filename: str) -> [str] {
31+
[]
32+
}
33+
34+
fn rpaths_to_flags(rpaths: [str]) -> [str] {
35+
vec::map({ |rpath| #fmt("-Wl,-rpath,%s",rpath)}, rpaths)
36+
}
37+
38+
fn get_rpaths(cwd: fs::path, sysroot: fs::path,
39+
output: fs::path, libs: [fs::path],
40+
target_triple: str) -> [str] {
41+
log #fmt("cwd: %s", cwd);
42+
log #fmt("sysroot: %s", sysroot);
43+
log #fmt("output: %s", output);
44+
log #fmt("libs:");
45+
for libpath in libs {
46+
log #fmt(" %s", libpath);
47+
}
48+
log #fmt("target_triple: %s", target_triple);
49+
50+
// Use relative paths to the libraries. Binaries can be moved
51+
// as long as they maintain the relative relationship to the
52+
// crates they depend on.
53+
let rpaths = get_rpaths_relative_to_output(cwd, output, libs);
54+
55+
// Make backup absolute paths to the libraries. Binaries can
56+
// be moved as long as the crates they link against don't move.
57+
rpaths += get_absolute_rpaths(cwd, libs);
58+
59+
// And a final backup rpath to the global library location.
60+
rpaths += [get_install_prefix_rpath(target_triple)];
61+
62+
// Remove duplicates
63+
let rpaths = minimize_rpaths(rpaths);
64+
ret rpaths;
65+
}
66+
67+
fn get_rpaths_relative_to_output(cwd: fs::path,
68+
output: fs::path,
69+
libs: [fs::path]) -> [str] {
70+
vec::map(bind get_rpath_relative_to_output(cwd, output, _), libs)
71+
}
72+
73+
fn get_rpath_relative_to_output(_cwd: fs::path,
74+
_output: fs::path,
75+
_lib: fs::path) -> str {
76+
fail;
77+
/*get_relative_to(
78+
get_absolute(cwd, output),
79+
get_absolute(cwd, lib))*/
80+
}
81+
82+
// Find the relative path from one file to another
83+
fn get_relative_to(_abs1: fs::path, _abs2: fs::path) -> fs::path {
84+
fail;
85+
}
86+
87+
fn get_absolute_rpaths(cwd: fs::path, libs: [fs::path]) -> [str] {
88+
vec::map(bind get_absolute_rpath(cwd, _), libs)
89+
}
90+
91+
fn get_absolute_rpath(cwd: fs::path, lib: fs::path) -> str {
92+
get_absolute(cwd, lib)
93+
}
94+
95+
fn get_absolute(cwd: fs::path, lib: fs::path) -> fs::path {
96+
if fs::path_is_absolute(lib) {
97+
lib
98+
} else {
99+
fs::connect(cwd, lib)
100+
}
101+
}
102+
103+
fn get_install_prefix_rpath(target_triple: str) -> str {
104+
let install_prefix = #env("CFG_PREFIX");
105+
106+
if install_prefix == "" {
107+
fail "rustc compiled without CFG_PREFIX environment variable";
108+
}
109+
110+
let path = [install_prefix]
111+
+ filesearch::relative_target_lib_path(target_triple);
112+
check vec::is_not_empty(path);
113+
fs::connect_many(path)
114+
}
115+
116+
fn minimize_rpaths(rpaths: [str]) -> [str] {
117+
let set = map::new_str_hash::<()>();
118+
for rpath in rpaths { set.insert(rpath, ()); }
119+
let minimized = [];
120+
for each rpath in set.keys() { minimized += [rpath]; }
121+
ret minimized;
122+
}
123+
124+
#[cfg(target_os = "linux")]
125+
#[cfg(target_os = "macos")]
126+
mod test {
127+
#[test]
128+
fn test_rpaths_to_flags() {
129+
let flags = rpaths_to_flags(["path1", "path2"]);
130+
assert flags == ["-Wl,-rpath,path1", "-Wl,-rpath,path2"];
131+
}
132+
133+
#[test]
134+
fn test_get_absolute1() {
135+
let cwd = "/dir";
136+
let lib = "some/path/lib";
137+
let res = get_absolute(cwd, lib);
138+
assert res == "/dir/some/path/lib";
139+
}
140+
141+
#[test]
142+
fn test_get_absolute2() {
143+
let cwd = "/dir";
144+
let lib = "/some/path/lib";
145+
let res = get_absolute(cwd, lib);
146+
assert res == "/some/path/lib";
147+
}
148+
149+
#[test]
150+
fn test_prefix_rpath() {
151+
let res = get_install_prefix_rpath("triple");
152+
assert res == #env("CFG_PREFIX") + "/lib/rustc/triple/lib";
153+
}
154+
155+
#[test]
156+
fn test_minimize() {
157+
let res = minimize_rpaths(["rpath1", "rpath2", "rpath1"]);
158+
assert res == ["rpath1", "rpath2"];
159+
}
160+
161+
#[test]
162+
#[ignore]
163+
fn test_relative_to1() {
164+
let p1 = "/usr/bin/rustc";
165+
let p2 = "/usr/lib/mylib";
166+
let res = get_relative_to(p1, p2);
167+
assert res == "../lib";
168+
}
169+
170+
#[test]
171+
#[ignore]
172+
fn test_relative_to2() {
173+
let p1 = "/usr/bin/rustc";
174+
let p2 = "/usr/bin/../lib/mylib";
175+
let res = get_relative_to(p1, p2);
176+
assert res == "../lib";
177+
}
178+
179+
#[test]
180+
#[ignore]
181+
fn test_relative_to3() {
182+
let p1 = "/usr/bin/whatever/rustc";
183+
let p2 = "/usr/lib/whatever/mylib";
184+
let res = get_relative_to(p1, p2);
185+
assert res == "../../lib/whatever";
186+
}
187+
188+
#[test]
189+
#[ignore]
190+
fn test_relative_to4() {
191+
let p1 = "/usr/bin/whatever/../rustc";
192+
let p2 = "/usr/lib/whatever/mylib";
193+
let res = get_relative_to(p1, p2);
194+
assert res == "../lib/whatever";
195+
}
196+
197+
#[test]
198+
#[ignore]
199+
fn test_relative_to5() {
200+
let p1 = "/usr/bin/whatever/../rustc";
201+
let p2 = "/usr/lib/whatever/../mylib";
202+
let res = get_relative_to(p1, p2);
203+
assert res == "../lib/whatever";
204+
}
205+
}

src/comp/rustc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ mod back {
9191
mod abi;
9292
mod upcall;
9393
mod x86;
94+
mod rpath;
9495
}
9596

9697
mod metadata {

src/comp/util/filesearch.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// A module for searching for libraries
2+
// FIXME: I'm not happy how this module turned out. Should probably
3+
// just be folded into cstore.
24

35
import std::option;
46
import std::fs;
@@ -12,6 +14,7 @@ export mk_filesearch;
1214
export pick;
1315
export pick_file;
1416
export search;
17+
export relative_target_lib_path;
1518

1619
type pick<@T> = block(path: fs::path) -> option::t<T>;
1720

@@ -71,17 +74,21 @@ fn search<@T>(filesearch: filesearch, pick: pick<T>) -> option::t<T> {
7174
ret option::none;
7275
}
7376

77+
fn relative_target_lib_path(target_triple: str) -> [fs::path] {
78+
["lib", "rustc", target_triple, "lib"]
79+
}
80+
7481
fn make_target_lib_path(sysroot: fs::path,
7582
target_triple: str) -> fs::path {
76-
let path = [sysroot, "lib/rustc", target_triple, "lib"];
83+
let path = [sysroot] + relative_target_lib_path(target_triple);
7784
check vec::is_not_empty(path);
7885
let path = fs::connect_many(path);
7986
ret path;
8087
}
8188

8289
fn get_default_sysroot() -> fs::path {
8390
alt os::get_exe_path() {
84-
option::some(p) { fs::connect(p, "../") }
91+
option::some(p) { fs::connect(p, "..") }
8592
option::none. {
8693
fail "can't determine value for sysroot";
8794
}

0 commit comments

Comments
 (0)