Explorar el Código

Merge pull request #2867 from flysand7/linux-asm

Implement foreign asm (x86) imports for linux and osx
Jeroen van Rijn hace 1 año
padre
commit
a62039882e
Se han modificado 2 ficheros con 88 adiciones y 42 borrados
  1. 1 2
      src/checker.cpp
  2. 87 40
      src/linker.cpp

+ 1 - 2
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]));
 		}

+ 87 - 40
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));
+							}
 						}
 					}
 				}