mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-29 01:14:40 +00:00
Merge pull request #4206 from laytan/improve-linking-shared-libraries
Improve linking shared libraries
This commit is contained in:
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@@ -257,16 +257,16 @@ jobs:
|
||||
run: sudo apt-get install -y qemu-user qemu-user-static gcc-12-riscv64-linux-gnu libc6-riscv64-cross
|
||||
|
||||
- name: Odin run
|
||||
run: ./odin run examples/demo -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin run examples/demo -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
- name: Odin run -debug
|
||||
run: ./odin run examples/demo -debug -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin run examples/demo -debug -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
- name: Normal Core library tests
|
||||
run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
- name: Optimized Core library tests
|
||||
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
- name: Internals tests
|
||||
run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
@@ -411,6 +411,7 @@ struct BuildContext {
|
||||
bool no_dynamic_literals;
|
||||
bool no_output_files;
|
||||
bool no_crt;
|
||||
bool no_rpath;
|
||||
bool no_entry_point;
|
||||
bool no_thread_local;
|
||||
bool use_lld;
|
||||
|
||||
@@ -548,14 +548,8 @@ gb_internal i32 linker_stage(LinkerData *gen) {
|
||||
// available at runtime wherever the executable is run, so we make require those to be
|
||||
// local to the executable (unless the system collection is used, in which case we search
|
||||
// the system library paths for the library file).
|
||||
if (string_ends_with(lib, str_lit(".a")) || string_ends_with(lib, str_lit(".o"))) {
|
||||
// static libs and object files, absolute full path relative to the file in which the lib was imported from
|
||||
if (string_ends_with(lib, str_lit(".a")) || string_ends_with(lib, str_lit(".o")) || string_ends_with(lib, str_lit(".so")) || string_contains_string(lib, str_lit(".so."))) {
|
||||
lib_str = gb_string_append_fmt(lib_str, " -l:\"%.*s\" ", LIT(lib));
|
||||
} else if (string_ends_with(lib, str_lit(".so")) || string_contains_string(lib, str_lit(".so."))) {
|
||||
// dynamic lib, relative path to executable
|
||||
// NOTE(vassvik): it is the user's responsibility to make sure the shared library files are visible
|
||||
// at runtime to the executable
|
||||
lib_str = gb_string_append_fmt(lib_str, " -l:\"%s/%.*s\" ", cwd, LIT(lib));
|
||||
} else {
|
||||
// dynamic or static system lib, just link regularly searching system library paths
|
||||
lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib));
|
||||
@@ -643,6 +637,16 @@ gb_internal i32 linker_stage(LinkerData *gen) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!build_context.no_rpath) {
|
||||
// Set the rpath to the $ORIGIN/@loader_path (the path of the executable),
|
||||
// so that dynamic libraries are looked for at that path.
|
||||
if (build_context.metrics.os == TargetOs_darwin) {
|
||||
link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,@loader_path ");
|
||||
} else {
|
||||
link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,\\$ORIGIN ");
|
||||
}
|
||||
}
|
||||
|
||||
if (!build_context.no_crt) {
|
||||
platform_lib_str = gb_string_appendc(platform_lib_str, "-lm ");
|
||||
if (build_context.metrics.os == TargetOs_darwin) {
|
||||
|
||||
@@ -325,6 +325,7 @@ enum BuildFlagKind {
|
||||
BuildFlag_NoTypeAssert,
|
||||
BuildFlag_NoDynamicLiterals,
|
||||
BuildFlag_NoCRT,
|
||||
BuildFlag_NoRPath,
|
||||
BuildFlag_NoEntryPoint,
|
||||
BuildFlag_UseLLD,
|
||||
BuildFlag_UseSeparateModules,
|
||||
@@ -533,6 +534,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
add_flag(&build_flags, BuildFlag_NoThreadLocal, str_lit("no-thread-local"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_NoDynamicLiterals, str_lit("no-dynamic-literals"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None, Command__does_build);
|
||||
add_flag(&build_flags, BuildFlag_NoRPath, str_lit("no-rpath"), BuildFlagParam_None, Command__does_build);
|
||||
add_flag(&build_flags, BuildFlag_NoEntryPoint, str_lit("no-entry-point"), BuildFlagParam_None, Command__does_check &~ Command_test);
|
||||
add_flag(&build_flags, BuildFlag_UseLLD, str_lit("lld"), BuildFlagParam_None, Command__does_build);
|
||||
add_flag(&build_flags, BuildFlag_UseSeparateModules, str_lit("use-separate-modules"), BuildFlagParam_None, Command__does_build);
|
||||
@@ -1183,6 +1185,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
case BuildFlag_NoCRT:
|
||||
build_context.no_crt = true;
|
||||
break;
|
||||
case BuildFlag_NoRPath:
|
||||
build_context.no_rpath = true;
|
||||
break;
|
||||
case BuildFlag_NoEntryPoint:
|
||||
build_context.no_entry_point = true;
|
||||
break;
|
||||
@@ -2315,6 +2320,10 @@ gb_internal void print_show_help(String const arg0, String const &command) {
|
||||
print_usage_line(2, "Disables automatic linking with the C Run Time.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-no-rpath");
|
||||
print_usage_line(2, "Disables automatic addition of an rpath linked to the executable directory.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-no-thread-local");
|
||||
print_usage_line(2, "Ignores @thread_local attribute, effectively treating the program as if it is single-threaded.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
@@ -5932,20 +5932,6 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node
|
||||
do_error(node, "Unknown library collection: '%.*s'", LIT(collection_name));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
#if !defined(GB_SYSTEM_WINDOWS)
|
||||
// @NOTE(vassvik): foreign imports of shared libraries that are not in the system collection on
|
||||
// linux/mac have to be local to the executable for consistency with shared libraries.
|
||||
// Unix does not have a concept of "import library" for shared/dynamic libraries,
|
||||
// so we need to pass the relative path to the linker, and add the current
|
||||
// working directory of the exe to the library search paths.
|
||||
// Static libraries can be linked directly with the full pathname
|
||||
//
|
||||
if (node->kind == Ast_ForeignImportDecl && (string_ends_with(file_str, str_lit(".so")) || string_contains_string(file_str, str_lit(".so.")))) {
|
||||
*path = file_str;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (is_package_name_reserved(file_str)) {
|
||||
|
||||
Reference in New Issue
Block a user