diff --git a/.gitignore b/.gitignore index c12ab5b..238dac0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build -test.o \ No newline at end of file +test.o +test \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5371c46..17356fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,8 +22,8 @@ void llvm_hello_world(); -std::string read_file(std::string& filepath) { - std::ifstream input{ filepath }; +std::string read_file(std::string_view filepath) { + std::ifstream input{ std::string{filepath} }; if (!input) { std::cerr << "Failed to read " << filepath << std::endl; return {}; @@ -41,8 +41,8 @@ std::string read_file(std::string& filepath) { return out; } -int write_file(std::string& filepath, std::string& content) { - std::ofstream output{ filepath }; +int write_file(std::string_view filepath, std::string& content) { + std::ofstream output{ std::string{filepath} }; if (!output) { std::cerr << "Failed to open " << filepath << " for reading" << std::endl; return 1; @@ -57,12 +57,12 @@ struct CompileOutput { std::string obj_string; }; -std::optional compile(std::string& in_filename) { +std::optional compile(std::string_view in_filename) { std::string out{ read_file(in_filename) }; std::cout << out << std::endl; - auto tokens = token::tokenize(out, in_filename); + auto tokens = token::tokenize(out, std::string{ in_filename }); for (token::Token token : tokens) { std::cout << token << std::endl; } @@ -154,15 +154,59 @@ std::optional compile(std::string& in_filename) { }; } +std::string exec(const char* cmd) { + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(cmd, "r"), pclose); + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + while (fgets(buffer.data(), static_cast(buffer.size()), pipe.get()) != nullptr) { + result += buffer.data(); + } + return result; +} + +/// @brief Discovers the path of a given library using POSIX-util "whereis" +/// @param libname +/// @return path to the library, empty string if nothing was found +std::string find_lib(std::string libname) { + std::string cmd = "whereis " + libname; + auto output = exec(cmd.c_str()); + output.erase(0, libname.size() + 2); + auto path = output.substr(0, output.find('\n')); + path = path.substr(0, path.find(' ')); + + return path; +} + int main() { std::string in_filename{ "test.c" }; std::string out_filename{ "test.o" }; + std::string exec_filename{ "test" }; auto out = compile(in_filename); if (out) { + // Print LLVM IR, produce Obj-file std::cout << out->llvm_ir_string << std::endl; write_file(out_filename, out->obj_string); + + // Find necessary libraries + + std::string command = "ld"; + auto linker = find_lib("ld-linux-x86-64.so.2"); + auto crt1 = find_lib("crt1.o"); + auto crti = find_lib("crti.o"); + auto crtn = find_lib("crtn.o"); + + + // Link everything together and produce a file with exec_filename + std::string cmd = command + " -dynamic-linker " + linker + " -lc " + + crt1 + " " + crti + " " + crtn + " " + + out_filename + " -o " + exec_filename; + std::cout << cmd << std::endl; + std::cout << exec(cmd.c_str()) << std::endl; } return 0;