aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2023-10-15 12:53:32 +0200
committerGitHub <noreply@github.com>2023-10-15 12:53:32 +0200
commita62039882e85d58894a4ae74ea88a2bda4bb2023 (patch)
treefd188bbcc15d286e6103d4d5c090b1d74d52ff8c /src
parent45d08ea9928be172e5c437507e79e9ac70c7c867 (diff)
parenta2a05e40e6cb57e0fe4c5d8c86815551044559d3 (diff)
Merge pull request #2867 from flysand7/linux-asm
Implement foreign asm (x86) imports for linux and osx
Diffstat (limited to 'src')
-rw-r--r--src/checker.cpp3
-rw-r--r--src/linker.cpp127
2 files changed, 88 insertions, 42 deletions
diff --git a/src/checker.cpp b/src/checker.cpp
index 51cef9e2c..29f22bd9c 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -4733,8 +4733,7 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
}
if (has_asm_extension(fullpath)) {
- if (build_context.metrics.arch != TargetArch_amd64 ||
- build_context.metrics.os != TargetOs_windows) {
+ if (build_context.metrics.arch != TargetArch_amd64) {
error(decl, "Assembly files are not yet supported on this platform: %.*s_%.*s",
LIT(target_os_names[build_context.metrics.os]), LIT(target_arch_names[build_context.metrics.arch]));
}
diff --git a/src/linker.cpp b/src/linker.cpp
index c0fbf596f..eb3687ae2 100644
--- a/src/linker.cpp
+++ b/src/linker.cpp
@@ -149,14 +149,20 @@ gb_internal i32 linker_stage(LinkerData *gen) {
if (!string_set_update(&asm_files, lib)) {
String asm_file = asm_files.entries[i].value;
String obj_file = concatenate_strings(permanent_allocator(), asm_file, str_lit(".obj"));
-
+ String obj_format;
+#if defined(GB_ARCH_64_BIT)
+ obj_format = str_lit("win64");
+#elif defined(GB_ARCH_32_BIT)
+ obj_format = str_lit("win32");
+#endif // GB_ARCH_*_BIT
result = system_exec_command_line_app("nasm",
"\"%.*s\\bin\\nasm\\windows\\nasm.exe\" \"%.*s\" "
- "-f win64 "
+ "-f \"%.*s\" "
"-o \"%.*s\" "
"%.*s "
"",
LIT(build_context.ODIN_ROOT), LIT(asm_file),
+ LIT(obj_format),
LIT(obj_file),
LIT(build_context.extra_assembler_flags)
);
@@ -295,11 +301,15 @@ gb_internal i32 linker_stage(LinkerData *gen) {
// files can be passed with -l:
gbString lib_str = gb_string_make(heap_allocator(), "-L/");
defer (gb_string_free(lib_str));
-
+
+ StringSet asm_files = {};
+ string_set_init(&asm_files, 64);
+ defer (string_set_destroy(&asm_files));
+
StringSet libs = {};
string_set_init(&libs, 64);
defer (string_set_destroy(&libs));
-
+
for (Entity *e : gen->foreign_libraries) {
GB_ASSERT(e->kind == Entity_LibraryName);
for (String lib : e->LibraryName.paths) {
@@ -307,46 +317,83 @@ gb_internal i32 linker_stage(LinkerData *gen) {
if (lib.len == 0) {
continue;
}
- if (string_set_update(&libs, lib)) {
- continue;
- }
-
- // NOTE(zangent): Sometimes, you have to use -framework on MacOS.
- // This allows you to specify '-f' in a #foreign_system_library,
- // without having to implement any new syntax specifically for MacOS.
- if (build_context.metrics.os == TargetOs_darwin) {
- if (string_ends_with(lib, str_lit(".framework"))) {
- // framework thingie
- String lib_name = lib;
- lib_name = remove_extension_from_path(lib_name);
- lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", LIT(lib_name));
- } else if (string_ends_with(lib, str_lit(".a")) || string_ends_with(lib, str_lit(".o")) || string_ends_with(lib, str_lit(".dylib"))) {
- // For:
- // object
- // dynamic lib
- // static libs, absolute full path relative to the file in which the lib was imported from
- lib_str = gb_string_append_fmt(lib_str, " %.*s ", LIT(lib));
+ if (has_asm_extension(lib)) {
+ if (string_set_update(&asm_files, lib)) {
+ continue; // already handled
+ }
+ String asm_file = lib;
+ String obj_file = concatenate_strings(permanent_allocator(), asm_file, str_lit(".o"));
+ String obj_format;
+#if defined(GB_ARCH_64_BIT)
+ if (is_osx) {
+ obj_format = str_lit("macho64");
+ } else {
+ obj_format = str_lit("elf64");
+ }
+#elif defined(GB_ARCH_32_BIT)
+ if (is_osx) {
+ obj_format = str_lit("macho32");
} 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));
+ obj_format = str_lit("elf32");
}
+#endif // GB_ARCH_*_BIT
+ // Note(bumbread): I'm assuming nasm is installed on the host machine.
+ // Shipping binaries on unix-likes gets into the weird territorry of
+ // "which version of glibc" is it linked with.
+ result = system_exec_command_line_app("nasm",
+ "nasm \"%.*s\" "
+ "-f \"%.*s\" "
+ "-o \"%.*s\" "
+ "%.*s "
+ "",
+ LIT(asm_file),
+ LIT(obj_format),
+ LIT(obj_file),
+ LIT(build_context.extra_assembler_flags)
+ );
+ array_add(&gen->output_object_paths, obj_file);
} else {
- // NOTE(vassvik): static libraries (.a files) in linux can be linked to directly using the full path,
- // since those are statically linked to at link time. shared libraries (.so) has to be
- // 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
- lib_str = gb_string_append_fmt(lib_str, " -l:\"%.*s\" ", LIT(lib));
- } else if (string_ends_with(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));
+ if (string_set_update(&libs, lib)) {
+ continue;
+ }
+
+ // NOTE(zangent): Sometimes, you have to use -framework on MacOS.
+ // This allows you to specify '-f' in a #foreign_system_library,
+ // without having to implement any new syntax specifically for MacOS.
+ if (build_context.metrics.os == TargetOs_darwin) {
+ if (string_ends_with(lib, str_lit(".framework"))) {
+ // framework thingie
+ String lib_name = lib;
+ lib_name = remove_extension_from_path(lib_name);
+ lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", LIT(lib_name));
+ } else if (string_ends_with(lib, str_lit(".a")) || string_ends_with(lib, str_lit(".o")) || string_ends_with(lib, str_lit(".dylib"))) {
+ // For:
+ // object
+ // dynamic lib
+ // static libs, absolute full path relative to the file in which the lib was imported from
+ lib_str = gb_string_append_fmt(lib_str, " %.*s ", 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));
+ }
} 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));
+ // NOTE(vassvik): static libraries (.a files) in linux can be linked to directly using the full path,
+ // since those are statically linked to at link time. shared libraries (.so) has to be
+ // 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
+ lib_str = gb_string_append_fmt(lib_str, " -l:\"%.*s\" ", LIT(lib));
+ } else if (string_ends_with(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));
+ }
}
}
}