Use explicit ld invocation instead of ar

This commit is contained in:
Richard Feldman 2020-09-27 23:37:49 -04:00
parent 0ee61c79a9
commit fa288a1404
4 changed files with 39 additions and 27 deletions

View file

@ -136,8 +136,7 @@ fn build_file(
}; };
let loaded = let loaded =
roc_load::file::load(filename.clone(), &stdlib, src_dir.as_path(), subs_by_module)?; roc_load::file::load(filename.clone(), &stdlib, src_dir.as_path(), subs_by_module)?;
let dest_filename = filename.with_extension("o"); let dest_filename = filename.with_file_name("roc_app.o");
let buf = &mut String::with_capacity(1024); let buf = &mut String::with_capacity(1024);
for (module_id, module_timing) in loaded.timings.iter() { for (module_id, module_timing) in loaded.timings.iter() {
@ -180,36 +179,19 @@ fn build_file(
); );
let cwd = dest_filename.parent().unwrap(); let cwd = dest_filename.parent().unwrap();
let lib_path = dest_filename.with_file_name("libroc_app.a");
// Step 2: turn the .o file into a .a static library // Step 2: have rustc compile the host
Command::new("ar") // TODO on Windows, use `link` let host_output_path = cwd.join("libhost.a"); // TODO should be host.lib on Windows
.args(&[
"rcs",
lib_path.to_str().unwrap(),
dest_filename.to_str().unwrap(),
])
.spawn()
.map_err(|_| {
todo!("gracefully handle `ar` failing to spawn.");
})?
.wait()
.map_err(|_| {
todo!("gracefully handle error after `ar` spawned");
})?;
// Step 3: have rustc compile the host and link in the .a file
let binary_path = cwd.join("app");
Command::new("rustc") Command::new("rustc")
.args(&[ .args(&[
"-L", "-L",
".", ".",
"--crate-type", "--crate-type",
"bin", "staticlib",
"host.rs", "host.rs",
"-o", "-o",
binary_path.as_path().to_str().unwrap(), host_output_path.as_path().to_str().unwrap(),
// ensure we don't make a position-independent executable // ensure we don't make a position-independent executable
"-C", "-C",
"link-arg=-no-pie", "link-arg=-no-pie",
@ -227,5 +209,34 @@ fn build_file(
todo!("gracefully handle error after `rustc` spawned"); todo!("gracefully handle error after `rustc` spawned");
})?; })?;
// Step 3: link the compiled host and compiled app
let binary_path = cwd.join("app"); // TODO should be app.exe on Windows
let arch = "x86_64"; // TODO determine this based on target
// TODO do we need -lSystem on macOS? -lpthread? -lm? -lresolv? -lc++?
Command::new("ld") // TODO use lld
.args(&[
"-L",
".",
"-arch",
arch,
"-lc", // libc
"-lhost", // libhost.a
"-e",
"_main", // assume hosts use `main` as their entry points
"-o",
binary_path.as_path().to_str().unwrap(),
dest_filename.as_path().to_str().unwrap(), // roc_app.o
])
.current_dir(cwd)
.spawn()
.map_err(|_| {
todo!("gracefully handle `rustc` failing to spawn.");
})?
.wait()
.map_err(|_| {
todo!("gracefully handle error after `rustc` spawned");
})?;
Ok(binary_path) Ok(binary_path)
} }

View file

@ -1,13 +1,14 @@
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::c_char; use std::os::raw::c_char;
#[link(name = "roc_app", kind = "static")] #[link(name = "roc_app")]
extern "C" { extern "C" {
#[link_name = "main#1"] #[link_name = "main#1"]
fn str_from_roc() -> *const c_char; fn str_from_roc() -> *const c_char;
} }
pub fn main() { #[no_mangle]
pub extern "C" fn main() {
let c_str = unsafe { CStr::from_ptr(str_from_roc()) }; let c_str = unsafe { CStr::from_ptr(str_from_roc()) };
println!("Roc says: {}", c_str.to_str().unwrap()); println!("Roc says: {}", c_str.to_str().unwrap());

View file

@ -1,6 +1,6 @@
use std::time::SystemTime; use std::time::SystemTime;
#[link(name = "roc_app", kind = "static")] #[link(name = "roc_app")]
extern "C" { extern "C" {
#[allow(improper_ctypes)] #[allow(improper_ctypes)]
#[link_name = "quicksort#1"] #[link_name = "quicksort#1"]

View file

@ -1,6 +1,6 @@
use std::time::SystemTime; use std::time::SystemTime;
#[link(name = "roc_app", kind = "static")] #[link(name = "roc_app")]
extern "C" { extern "C" {
#[allow(improper_ctypes)] #[allow(improper_ctypes)]
#[link_name = "quicksort#1"] #[link_name = "quicksort#1"]