diff --git a/examples/ptr.reid b/examples/ptr.reid old mode 100644 new mode 100755 diff --git a/libtest.sh b/libtest.sh index 775bf55..b28750a 100755 --- a/libtest.sh +++ b/libtest.sh @@ -16,8 +16,9 @@ BINARY="$(echo $1 | cut -d'.' -f1)"".out" echo $1 -make clean SRC=$1 ; make SRC=$1 && echo "" - +cargo run --example cli $@ && \ +sleep 0.1 && \ +chmod +x $BINARY && \ $BINARY ; echo "Return value: ""$?" ## Command from: clang -v hello.o -o test diff --git a/reid/examples/cli.rs b/reid/examples/cli.rs index 2de0e71..1e7ad10 100644 --- a/reid/examples/cli.rs +++ b/reid/examples/cli.rs @@ -1,11 +1,18 @@ use std::{env, fs, path::PathBuf}; -use reid::{compile_simple, CustomIRs}; +use reid::{compile_simple, ld::LDRunner, CustomIRs}; use reid_lib::compile::CompileOutput; fn main() -> Result<(), std::io::Error> { let args: Vec = env::args().collect(); - if let Some(filename) = args.get(1) { + let mut iter = args.into_iter().skip(1); + if let Some(filename) = iter.next() { + let mut libraries = Vec::new(); + while let Some(libname) = iter.next() { + libraries.push(libname); + } + + dbg!(&filename); let path = PathBuf::from(filename).canonicalize().unwrap(); let parent = path.with_extension(""); let llvm_ir_path = parent.with_extension("ll"); @@ -46,6 +53,14 @@ fn main() -> Result<(), std::io::Error> { "Compilation took: {:.2}ms\n", (after.duration_since(before).unwrap().as_micros() as f32) / 1000. ); + + println!("Linking {:?}", &object_path); + let linker = option_env!("LD").unwrap_or("ld").to_owned(); + let mut linker = LDRunner::from_command(linker).with_library("c".to_owned()); + for library in libraries { + linker = linker.with_library(library); + } + linker.invoke(object_path); } Err(e) => panic!("{}", e), }; diff --git a/reid/src/ld.rs b/reid/src/ld.rs new file mode 100644 index 0000000..bf7edda --- /dev/null +++ b/reid/src/ld.rs @@ -0,0 +1,67 @@ +use std::{io::Read, path::PathBuf, process::Command}; + +pub struct LDRunner { + command: String, + dynamic_linker: String, + libraries: Vec, +} + +impl LDRunner { + pub fn from_command(command: String) -> LDRunner { + LDRunner { + command, + dynamic_linker: "ld-linux-x86-64.so.2".to_string(), + libraries: Default::default(), + } + } + + pub fn with_library(mut self, lib: String) -> LDRunner { + self.libraries.push(lib); + self + } + + pub fn invoke(&self, file: PathBuf) { + let filepath = file.canonicalize().unwrap(); + + let dyn_linker_path = find_objectfile(&self.dynamic_linker); + let crt1_path = find_objectfile("crt1.o"); + + println!("LDRunner: Using dynamic linker at: {:?}", dyn_linker_path); + + let mut ld = Command::new(&self.command); + ld.arg("-dynamic-linker") + .arg(dyn_linker_path) + .arg(crt1_path); + + for library in &self.libraries { + ld.arg(format!("-l{}", library)); + } + + ld.arg(filepath.to_str().unwrap()) + .arg("-o") + .arg(filepath.with_extension("out")); + + println!("LDRunner: Executing linker to objfile at {:?}", filepath); + dbg!(&ld); + + ld.spawn().expect("Unable to execute ld!"); + } +} + +fn find_objectfile(name: &str) -> String { + let whereis = Command::new("whereis") + .arg(&name) + .output() + .expect("Unable to execute whereis"); + let whereis_output = String::from_utf8(whereis.stdout).unwrap(); + + whereis_output + .split(" ") + .skip(1) + .next() + .expect(&format!("Unable to find {}: {}", name, whereis_output)) + .split("\n") + .next() + .unwrap() + .to_owned() +} diff --git a/reid/src/lib.rs b/reid/src/lib.rs index eec083f..58c30ec 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -55,6 +55,7 @@ use crate::{ast::TopLevelStatement, lexer::Token, token_stream::TokenStream}; mod ast; mod codegen; pub mod error_raporting; +pub mod ld; mod lexer; pub mod mir; mod pad_adapter; diff --git a/reid/tests/e2e.rs b/reid/tests/e2e.rs index 274a67d..c9257ee 100644 --- a/reid/tests/e2e.rs +++ b/reid/tests/e2e.rs @@ -19,7 +19,9 @@ fn test(source: &str, name: &str) { let context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION"))); - assert_err(mir_context.codegen(&context)); + let codegen = assert_err(mir_context.codegen(&context)); + + codegen.compile(); Ok::<(), ()>(()) })))