瀏覽代碼

Merge pull request #3900 from Kelimion/winres

 Allow precompiled resources with `-resource:foo.res`
gingerBill 1 年之前
父節點
當前提交
fc7c7cd8ab
共有 5 個文件被更改,包括 48 次插入26 次删除
  1. 5 4
      src/build_settings.cpp
  2. 12 0
      src/cached.cpp
  3. 20 20
      src/linker.cpp
  4. 4 2
      src/main.cpp
  5. 7 0
      src/path.cpp

+ 5 - 4
src/build_settings.cpp

@@ -1805,10 +1805,11 @@ gb_internal bool init_build_paths(String init_filename) {
 	#if defined(GB_SYSTEM_WINDOWS)
 	if (bc->metrics.os == TargetOs_windows) {
 		if (bc->resource_filepath.len > 0) {
-			bc->build_paths[BuildPath_RC]      = path_from_string(ha, bc->resource_filepath);
-			bc->build_paths[BuildPath_RES]     = path_from_string(ha, bc->resource_filepath);
-			bc->build_paths[BuildPath_RC].ext  = copy_string(ha, STR_LIT("rc"));
-			bc->build_paths[BuildPath_RES].ext = copy_string(ha, STR_LIT("res"));
+			bc->build_paths[BuildPath_RES] = path_from_string(ha, bc->resource_filepath);
+			if (!string_ends_with(bc->resource_filepath, str_lit(".res"))) {
+				bc->build_paths[BuildPath_RC]      = path_from_string(ha, bc->resource_filepath);
+				bc->build_paths[BuildPath_RC].ext  = copy_string(ha, STR_LIT("rc"));
+			}
 		}
 
 		if (bc->pdb_filepath.len > 0) {

+ 12 - 0
src/cached.cpp

@@ -200,6 +200,18 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
 		}
 	}
 
+	#if defined(GB_SYSTEM_WINDOWS)
+		if (build_context.has_resource) {
+			String res_path = {};
+			if (build_context.build_paths[BuildPath_RC].basename == "")  {
+				res_path = path_to_string(permanent_allocator(), build_context.build_paths[BuildPath_RES]);
+			} else {
+				res_path = path_to_string(permanent_allocator(), build_context.build_paths[BuildPath_RC]);
+			}
+			array_add(&files, res_path);
+		}
+	#endif
+
 	for (auto const &entry : c->info.load_file_cache) {
 		auto *cache = entry.value;
 		if (!cache || !cache->exists) {

+ 20 - 20
src/linker.cpp

@@ -305,30 +305,30 @@ gb_internal i32 linker_stage(LinkerData *gen) {
 			defer (gb_free(heap_allocator(), windows_sdk_bin_path.text));
 
 			if (!build_context.use_lld) { // msvc
-				String res_path = {};
+				String res_path = quote_path(heap_allocator(), build_context.build_paths[BuildPath_RES]);
+				String rc_path  = quote_path(heap_allocator(), build_context.build_paths[BuildPath_RC]);
 				defer (gb_free(heap_allocator(), res_path.text));
+				defer (gb_free(heap_allocator(), rc_path.text));
 
-				// TODO(Jeroen): Add ability to reuse .res file instead of recompiling, if `-resource:file.res` is given.
 				if (build_context.has_resource) {
-					String temp_res_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RES]);
-					res_path = concatenate3_strings(heap_allocator(), str_lit("\""), temp_res_path, str_lit("\""));
-					gb_free(heap_allocator(), temp_res_path.text);
-
-					String temp_rc_path  = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RC]);
-					String rc_path = concatenate3_strings(heap_allocator(), str_lit("\""), temp_rc_path, str_lit("\""));
-					gb_free(heap_allocator(), temp_rc_path.text);
-					defer (gb_free(heap_allocator(), rc_path.text));
-
-					result = system_exec_command_line_app("msvc-link",
-						"\"%.*src.exe\" /nologo /fo %.*s %.*s",
-						LIT(windows_sdk_bin_path),
-						LIT(res_path),
-						LIT(rc_path)
-					);
-
-					if (result) {
-						return result;
+					if (build_context.build_paths[BuildPath_RC].basename == "")  {
+						debugf("Using precompiled resource %.*s\n", LIT(res_path));
+					} else {
+						debugf("Compiling resource %.*s\n", LIT(res_path));
+
+						result = system_exec_command_line_app("msvc-link",
+							"\"%.*src.exe\" /nologo /fo %.*s %.*s",
+							LIT(windows_sdk_bin_path),
+							LIT(res_path),
+							LIT(rc_path)
+						);
+
+						if (result) {
+							return result;
+						}
 					}
+				} else {
+					res_path = {};
 				}
 
 				String linker_name = str_lit("link.exe");

+ 4 - 2
src/main.cpp

@@ -1452,8 +1452,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
 							String path = value.value_string;
 							path = string_trim_whitespace(path);
 							if (is_build_flag_path_valid(path)) {
-								if(!string_ends_with(path, str_lit(".rc"))) {
-									gb_printf_err("Invalid -resource path %.*s, missing .rc\n", LIT(path));
+								bool is_resource = string_ends_with(path, str_lit(".rc")) || string_ends_with(path, str_lit(".res"));
+								if(!is_resource) {
+									gb_printf_err("Invalid -resource path %.*s, missing .rc or .res file\n", LIT(path));
 									bad_flags = true;
 									break;
 								} else if (!gb_file_exists((const char *)path.text)) {
@@ -2552,6 +2553,7 @@ gb_internal void print_show_help(String const arg0, String const &command) {
 		print_usage_line(2, "[Windows only]");
 		print_usage_line(2, "Defines the resource file for the executable.");
 		print_usage_line(2, "Example: -resource:path/to/file.rc");
+		print_usage_line(2, "or:      -resource:path/to/file.res for a precompiled one.");
 		print_usage_line(0, "");
 
 		print_usage_line(1, "-pdb-name:<filepath>");

+ 7 - 0
src/path.cpp

@@ -152,6 +152,13 @@ gb_internal String path_to_string(gbAllocator a, Path path) {
 	return res;
 }
 
+gb_internal String quote_path(gbAllocator a, Path path) {
+	String temp   = path_to_string(a, path);
+	String quoted = concatenate3_strings(a, str_lit("\""), temp, str_lit("\""));
+	gb_free(a, temp.text);
+	return quoted;
+}
+
 // NOTE(Jeroen): Naively turns a Path into a string, then normalizes it using `path_to_full_path`.
 gb_internal String path_to_full_path(gbAllocator a, Path path) {
 	String temp = path_to_string(heap_allocator(), path);