Browse Source

Reimplement `-build-mode:static`/`-build-mode:lib`

gingerBill 1 year ago
parent
commit
e71cd871c4
4 changed files with 42 additions and 8 deletions
  1. 7 1
      src/build_settings.cpp
  2. 1 0
      src/checker.cpp
  3. 24 7
      src/linker.cpp
  4. 10 0
      src/main.cpp

+ 7 - 1
src/build_settings.cpp

@@ -646,6 +646,7 @@ struct QueryDataSetSettings {
 enum BuildModeKind {
 enum BuildModeKind {
 	BuildMode_Executable,
 	BuildMode_Executable,
 	BuildMode_DynamicLibrary,
 	BuildMode_DynamicLibrary,
+	BuildMode_StaticLibrary,
 	BuildMode_Object,
 	BuildMode_Object,
 	BuildMode_Assembly,
 	BuildMode_Assembly,
 	BuildMode_LLVM_IR,
 	BuildMode_LLVM_IR,
@@ -2284,7 +2285,12 @@ gb_internal bool init_build_paths(String init_filename) {
 		} else if (build_context.metrics.os == TargetOs_darwin) {
 		} else if (build_context.metrics.os == TargetOs_darwin) {
 			output_extension = STR_LIT("dylib");
 			output_extension = STR_LIT("dylib");
 		}
 		}
-	} else if (build_context.build_mode == BuildMode_Object) {
+	} else if (build_context.build_mode == BuildMode_StaticLibrary) {
+		output_extension = STR_LIT("a");
+		if (build_context.metrics.os == TargetOs_windows) {
+			output_extension = STR_LIT("lib");
+		}
+	}else if (build_context.build_mode == BuildMode_Object) {
 		// By default use a .o object extension.
 		// By default use a .o object extension.
 		output_extension = STR_LIT("o");
 		output_extension = STR_LIT("o");
 
 

+ 1 - 0
src/checker.cpp

@@ -1044,6 +1044,7 @@ gb_internal void init_universal(void) {
 		GlobalEnumValue values[BuildMode_COUNT] = {
 		GlobalEnumValue values[BuildMode_COUNT] = {
 			{"Executable", BuildMode_Executable},
 			{"Executable", BuildMode_Executable},
 			{"Dynamic",    BuildMode_DynamicLibrary},
 			{"Dynamic",    BuildMode_DynamicLibrary},
+			{"Static",     BuildMode_StaticLibrary},
 			{"Object",     BuildMode_Object},
 			{"Object",     BuildMode_Object},
 			{"Assembly",   BuildMode_Assembly},
 			{"Assembly",   BuildMode_Assembly},
 			{"LLVM_IR",    BuildMode_LLVM_IR},
 			{"LLVM_IR",    BuildMode_LLVM_IR},

+ 24 - 7
src/linker.cpp

@@ -212,10 +212,12 @@ gb_internal i32 linker_stage(LinkerData *gen) {
 				link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(pdb_path));
 				link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(pdb_path));
 			}
 			}
 
 
-			if (build_context.no_crt) {
-				link_settings = gb_string_append_fmt(link_settings, " /nodefaultlib");
-			} else {
-				link_settings = gb_string_append_fmt(link_settings, " /defaultlib:libcmt");
+			if (build_context.build_mode != BuildMode_StaticLibrary) {
+				if (build_context.no_crt) {
+					link_settings = gb_string_append_fmt(link_settings, " /nodefaultlib");
+				} else {
+					link_settings = gb_string_append_fmt(link_settings, " /defaultlib:libcmt");
+				}
 			}
 			}
 
 
 			if (build_context.ODIN_DEBUG) {
 			if (build_context.ODIN_DEBUG) {
@@ -257,20 +259,31 @@ gb_internal i32 linker_stage(LinkerData *gen) {
 					}
 					}
 				}
 				}
 
 
+				String linker_name = str_lit("link.exe");
 				switch (build_context.build_mode) {
 				switch (build_context.build_mode) {
 				case BuildMode_Executable:
 				case BuildMode_Executable:
 					link_settings = gb_string_append_fmt(link_settings, " /NOIMPLIB /NOEXP");
 					link_settings = gb_string_append_fmt(link_settings, " /NOIMPLIB /NOEXP");
 					break;
 					break;
 				}
 				}
 
 
+				switch (build_context.build_mode) {
+				case BuildMode_StaticLibrary:
+					linker_name = str_lit("lib.exe");
+					break;
+				default:
+					link_settings = gb_string_append_fmt(link_settings, " /incremental:no /opt:ref");
+					break;
+				}
+
+
 				result = system_exec_command_line_app("msvc-link",
 				result = system_exec_command_line_app("msvc-link",
-					"\"%.*slink.exe\" %s %.*s -OUT:\"%.*s\" %s "
-					"/nologo /incremental:no /opt:ref /subsystem:%.*s "
+					"\"%.*s%.*s\" %s %.*s -OUT:\"%.*s\" %s "
+					"/nologo /subsystem:%.*s "
 					"%.*s "
 					"%.*s "
 					"%.*s "
 					"%.*s "
 					"%s "
 					"%s "
 					"",
 					"",
-					LIT(vs_exe_path), object_files, LIT(res_path), LIT(output_filename),
+					LIT(vs_exe_path), LIT(linker_name), object_files, LIT(res_path), LIT(output_filename),
 					link_settings,
 					link_settings,
 					LIT(build_context.ODIN_WINDOWS_SUBSYSTEM),
 					LIT(build_context.ODIN_WINDOWS_SUBSYSTEM),
 					LIT(build_context.link_flags),
 					LIT(build_context.link_flags),
@@ -458,6 +471,10 @@ gb_internal i32 linker_stage(LinkerData *gen) {
 				link_settings = gb_string_append_fmt(link_settings, "-nostdlib ");
 				link_settings = gb_string_append_fmt(link_settings, "-nostdlib ");
 			}
 			}
 
 
+			if (build_context.build_mode == BuildMode_StaticLibrary) {
+				compiler_error("TODO(bill): -build-mode:static on non-windows targets");
+			}
+
 			// NOTE(dweiler): We use clang as a frontend for the linker as there are
 			// 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
 			// other runtime and compiler support libraries that need to be linked in
 			// very specific orders such as libgcc_s, ld-linux-so, unwind, etc.
 			// very specific orders such as libgcc_s, ld-linux-so, unwind, etc.

+ 10 - 0
src/main.cpp

@@ -989,6 +989,8 @@ gb_internal bool parse_build_flags(Array<String> args) {
 								build_context.build_mode = BuildMode_DynamicLibrary;
 								build_context.build_mode = BuildMode_DynamicLibrary;
 							} else if (str == "obj" || str == "object") {
 							} else if (str == "obj" || str == "object") {
 								build_context.build_mode = BuildMode_Object;
 								build_context.build_mode = BuildMode_Object;
+							} else if (str == "static" || str == "lib") {
+								build_context.build_mode = BuildMode_StaticLibrary;
 							} else if (str == "exe") {
 							} else if (str == "exe") {
 								build_context.build_mode = BuildMode_Executable;
 								build_context.build_mode = BuildMode_Executable;
 							} else if (str == "asm" || str == "assembly" || str == "assembler") {
 							} else if (str == "asm" || str == "assembly" || str == "assembler") {
@@ -999,6 +1001,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
 								gb_printf_err("Unknown build mode '%.*s'\n", LIT(str));
 								gb_printf_err("Unknown build mode '%.*s'\n", LIT(str));
 								gb_printf_err("Valid build modes:\n");
 								gb_printf_err("Valid build modes:\n");
 								gb_printf_err("\tdll, shared, dynamic\n");
 								gb_printf_err("\tdll, shared, dynamic\n");
+								gb_printf_err("\tlib, static\n");
 								gb_printf_err("\tobj, object\n");
 								gb_printf_err("\tobj, object\n");
 								gb_printf_err("\texe\n");
 								gb_printf_err("\texe\n");
 								gb_printf_err("\tasm, assembly, assembler\n");
 								gb_printf_err("\tasm, assembly, assembler\n");
@@ -1637,6 +1640,7 @@ gb_internal void remove_temp_files(lbGenerator *gen) {
 
 
 	switch (build_context.build_mode) {
 	switch (build_context.build_mode) {
 	case BuildMode_Executable:
 	case BuildMode_Executable:
+	case BuildMode_StaticLibrary:
 	case BuildMode_DynamicLibrary:
 	case BuildMode_DynamicLibrary:
 		break;
 		break;
 
 
@@ -1655,6 +1659,7 @@ gb_internal void remove_temp_files(lbGenerator *gen) {
 	if (!build_context.keep_object_files) {
 	if (!build_context.keep_object_files) {
 		switch (build_context.build_mode) {
 		switch (build_context.build_mode) {
 		case BuildMode_Executable:
 		case BuildMode_Executable:
+		case BuildMode_StaticLibrary:
 		case BuildMode_DynamicLibrary:
 		case BuildMode_DynamicLibrary:
 			for (String const &path : gen->output_object_paths) {
 			for (String const &path : gen->output_object_paths) {
 				gb_file_remove(cast(char const *)path.text);
 				gb_file_remove(cast(char const *)path.text);
@@ -1833,6 +1838,9 @@ gb_internal void print_show_help(String const arg0, String const &command) {
 		print_usage_line(3, "-build-mode:exe         Builds as an executable.");
 		print_usage_line(3, "-build-mode:exe         Builds as an executable.");
 		print_usage_line(3, "-build-mode:dll         Builds as a dynamically linked library.");
 		print_usage_line(3, "-build-mode:dll         Builds as a dynamically linked library.");
 		print_usage_line(3, "-build-mode:shared      Builds as a dynamically linked library.");
 		print_usage_line(3, "-build-mode:shared      Builds as a dynamically linked library.");
+		print_usage_line(3, "-build-mode:lib         Builds as a statically linked library.");
+		print_usage_line(3, "-build-mode:static      Builds as a statically linked library.");
+		print_usage_line(3, "-build-mode:lib         Builds as an static library.");
 		print_usage_line(3, "-build-mode:obj         Builds as an object file.");
 		print_usage_line(3, "-build-mode:obj         Builds as an object file.");
 		print_usage_line(3, "-build-mode:object      Builds as an object file.");
 		print_usage_line(3, "-build-mode:object      Builds as an object file.");
 		print_usage_line(3, "-build-mode:assembly    Builds as an assembly file.");
 		print_usage_line(3, "-build-mode:assembly    Builds as an assembly file.");
@@ -2866,6 +2874,7 @@ int main(int arg_count, char const **arg_ptr) {
 
 
 		switch (build_context.build_mode) {
 		switch (build_context.build_mode) {
 		case BuildMode_Executable:
 		case BuildMode_Executable:
+		case BuildMode_StaticLibrary:
 		case BuildMode_DynamicLibrary:
 		case BuildMode_DynamicLibrary:
 			i32 result = linker_stage(&linker_data);
 			i32 result = linker_stage(&linker_data);
 			if (result) {
 			if (result) {
@@ -2887,6 +2896,7 @@ int main(int arg_count, char const **arg_ptr) {
 		if (lb_generate_code(gen)) {
 		if (lb_generate_code(gen)) {
 			switch (build_context.build_mode) {
 			switch (build_context.build_mode) {
 			case BuildMode_Executable:
 			case BuildMode_Executable:
+			case BuildMode_StaticLibrary:
 			case BuildMode_DynamicLibrary:
 			case BuildMode_DynamicLibrary:
 				i32 result = linker_stage(gen);
 				i32 result = linker_stage(gen);
 				if (result) {
 				if (result) {