From 8f91e9307c6ea7a243001efb2ecb135d37587301 Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Mon, 10 Jan 2022 17:57:33 -0500 Subject: [PATCH] shared library fixes --- src/llvm_backend.cpp | 8 ++++++- src/main.cpp | 51 ++++++++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 5acd2a80f..1a657e47b 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1238,12 +1238,18 @@ void lb_generate_code(lbGenerator *gen) { // NOTE(bill, 2021-05-04): Target machines must be unique to each module because they are not thread safe auto target_machines = array_make(permanent_allocator(), gen->modules.entries.count); + // NOTE(dweiler): Dynamic libraries require position-independent code. + LLVMRelocMode reloc_mode = LLVMRelocDefault; + if (build_context.build_mode == BuildMode_DynamicLibrary) { + reloc_mode = LLVMRelocPIC; + } + for_array(i, gen->modules.entries) { target_machines[i] = LLVMCreateTargetMachine( target, target_triple, llvm_cpu, llvm_features, code_gen_level, - LLVMRelocDefault, + reloc_mode, code_mode); LLVMSetModuleDataLayout(gen->modules.entries[i].value->mod, LLVMCreateTargetDataLayout(target_machines[i])); } diff --git a/src/main.cpp b/src/main.cpp index 36b30112f..0e8894ed0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -432,40 +432,39 @@ i32 linker_stage(lbGenerator *gen) { // typically executable files on *NIX systems don't have extensions. String output_ext = {}; gbString link_settings = gb_string_make_reserve(heap_allocator(), 32); - char const *linker; + + // NOTE(dweiler): We use clang as a frontend for the linker as there are + // other runtime and compiler support libraries that need to be linked in + // very specific orders such as libgcc_s, ld-linux-so, unwind, etc. + // These are not always typically inside /lib, /lib64, or /usr versions + // of that, e.g libgcc.a is in /usr/lib/gcc/{version}, and can vary on + // the distribution of Linux even. The gcc or clang specs is the only + // reliable way to query this information to call ld directly. if (build_context.build_mode == BuildMode_DynamicLibrary) { - // NOTE(tetra, 2020-11-06): __$startup_runtime must be called at DLL load time. - // Clang, for some reason, won't let us pass the '-init' flag that lets us do this, - // so use ld instead. - // :UseLDForShared - linker = "ld"; + // NOTE(dweiler): Let the frontend know we're building a shared library + // so it doesn't generate symbols which cannot be relocated. + link_settings = gb_string_appendc(link_settings, "-shared "); + + // NOTE(dweiler): __$startup_runtime must be called at initialization + // time of the shared object, we can pass -init to the linker by using + // a comma separated list of arguments to -Wl. + // + // This previously used ld but ld cannot actually build a shared library + // correctly this way since all the other dependencies provided implicitly + // by the compiler frontend are still needed and most of the command + // line arguments prepared previously are incompatible with ld. + // // Shared libraries are .dylib on MacOS and .so on Linux. #if defined(GB_SYSTEM_OSX) output_ext = STR_LIT(".dylib"); - link_settings = gb_string_appendc(link_settings, "-init '___$startup_runtime' "); - link_settings = gb_string_appendc(link_settings, "-dylib -dynamic "); + link_settings = gb_string_appendc(link_settings, "-Wl,-init,'___$startup_runtime' "); #else output_ext = STR_LIT(".so"); - link_settings = gb_string_appendc(link_settings, "-init '__$startup_runtime' "); - link_settings = gb_string_appendc(link_settings, "-shared "); + link_settings = gb_string_appendc(link_settings, "-Wl,-init,'__$startup_runtime' "); #endif } else { - #if defined(GB_SYSTEM_OSX) - linker = "ld"; - #else - // TODO(zangent): Figure out how to make ld work on Linux. - // It probably has to do with including the entire CRT, but - // that's quite a complicated issue to solve while remaining distro-agnostic. - // Clang can figure out linker flags for us, and that's good enough _for now_. - linker = "clang -Wno-unused-command-line-argument"; - #endif - } - - if (build_context.metrics.os == TargetOs_linux) { link_settings = gb_string_appendc(link_settings, "-no-pie "); } - - if (build_context.out_filepath.len > 0) { //NOTE(thebirk): We have a custom -out arguments, so we should use the extension from that isize pos = string_extension_position(build_context.out_filepath); @@ -475,7 +474,7 @@ i32 linker_stage(lbGenerator *gen) { } result = system_exec_command_line_app("ld-link", - "%s %s -o \"%.*s%.*s\" %s " + "clang -Wunused-command-line-argument %s -o \"%.*s%.*s\" %s " " %s " " %.*s " " %.*s " @@ -492,7 +491,7 @@ i32 linker_stage(lbGenerator *gen) { // This points the linker to where the entry point is " -e _main " #endif - , linker, object_files, LIT(output_base), LIT(output_ext), + , object_files, LIT(output_base), LIT(output_ext), #if defined(GB_SYSTEM_OSX) "-lSystem -lm -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -L/usr/local/lib", #else