Bladeren bron

Cache files, env, and args

gingerBill 1 jaar geleden
bovenliggende
commit
886ee66e7f
5 gewijzigde bestanden met toevoegingen van 175 en 29 verwijderingen
  1. 6 1
      src/build_settings.cpp
  2. 145 25
      src/cached.cpp
  3. 10 3
      src/main.cpp
  4. 10 0
      src/parser.cpp
  5. 4 0
      src/parser.hpp

+ 6 - 1
src/build_settings.cpp

@@ -329,7 +329,12 @@ enum SanitizerFlags : u32 {
 struct BuildCacheData {
 	u64 crc;
 	String cache_dir;
-	String manifest_path;
+
+	// manifests
+	String files_path;
+	String args_path;
+	String env_path;
+
 	bool copy_already_done;
 };
 

+ 145 - 25
src/cached.cpp

@@ -1,4 +1,4 @@
-gb_internal GB_COMPARE_PROC(cached_file_cmp) {
+gb_internal GB_COMPARE_PROC(string_cmp) {
 	String const &x = *(String *)a;
 	String const &y = *(String *)b;
 	return string_compare(x, y);
@@ -182,7 +182,9 @@ bool try_copy_executable_from_cache(void) {
 
 
 // returns false if different, true if it is the same
-bool try_cached_build(Checker *c) {
+bool try_cached_build(Checker *c, Array<String> const &args) {
+	TEMPORARY_ALLOCATOR_GUARD();
+
 	Parser *p = c->parser;
 
 	auto files = array_make<String>(heap_allocator());
@@ -200,7 +202,7 @@ bool try_cached_build(Checker *c) {
 		array_add(&files, cache->path);
 	}
 
-	array_sort(files, cached_file_cmp);
+	array_sort(files, string_cmp);
 
 	u64 crc = 0;
 	for (String const &path : files) {
@@ -213,28 +215,58 @@ bool try_cached_build(Checker *c) {
 
 	gbString crc_str = gb_string_make_reserve(permanent_allocator(), 16);
 	crc_str = gb_string_append_fmt(crc_str, "%016llx", crc);
-	String cache_dir = concatenate3_strings(permanent_allocator(), base_cache_dir, str_lit("/"), make_string_c(crc_str));
-	String manifest_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("odin.manifest"));
+	String cache_dir  = concatenate3_strings(permanent_allocator(), base_cache_dir, str_lit("/"), make_string_c(crc_str));
+	String files_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("files.manifest"));
+	String args_path  = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("args.manifest"));
+	String env_path   = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("env.manifest"));
 
 	build_context.build_cache_data.cache_dir = cache_dir;
-	build_context.build_cache_data.manifest_path = manifest_path;
+	build_context.build_cache_data.files_path = files_path;
+	build_context.build_cache_data.args_path = args_path;
+	build_context.build_cache_data.env_path = env_path;
+
+	auto envs = array_make<String>(heap_allocator());
+	defer (array_free(&envs));
+	{
+	#if defined(GB_SYSTEM_WINDOWS)
+		wchar_t *strings = GetEnvironmentStringsW();
+		defer (FreeEnvironmentStringsW(strings));
+
+		wchar_t *curr_string = strings;
+		while (curr_string && *curr_string) {
+			String16 wstr = make_string16_c(curr_string);
+			curr_string += wstr.len+1;
+			String str = string16_to_string(temporary_allocator(), wstr);
+			array_add(&envs, str);
+		}
+	#endif
+	}
+	array_sort(envs, string_cmp);
 
 	if (check_if_exists_directory_otherwise_create(cache_dir)) {
-		goto do_write_file;
+		goto write_cache;
 	}
 
-	if (check_if_exists_file_otherwise_create(manifest_path)) {
-		goto do_write_file;
-	} else {
+	if (check_if_exists_file_otherwise_create(files_path)) {
+		goto write_cache;
+	}
+	if (check_if_exists_file_otherwise_create(args_path)) {
+		goto write_cache;
+	}
+	if (check_if_exists_file_otherwise_create(env_path)) {
+		goto write_cache;
+	}
+
+	{
 		// exists already
 		LoadedFile loaded_file = {};
 
 		LoadedFileError file_err = load_file_32(
-			alloc_cstring(temporary_allocator(), manifest_path),
+			alloc_cstring(temporary_allocator(), files_path),
 			&loaded_file,
 			false
 		);
-		if (file_err) {
+		if (file_err > LoadedFile_Empty) {
 			return false;
 		}
 
@@ -250,7 +282,7 @@ bool try_cached_build(Checker *c) {
 			}
 			isize sep = string_index_byte(line, ' ');
 			if (sep < 0) {
-				goto do_write_file;
+				goto write_cache;
 			}
 
 			String timestamp_str = substring(line, 0, sep);
@@ -260,43 +292,131 @@ bool try_cached_build(Checker *c) {
 			path_str = string_trim_whitespace(path_str);
 
 			if (file_count >= files.count) {
-				goto do_write_file;
+				goto write_cache;
 			}
 			if (files[file_count] != path_str) {
-				goto do_write_file;
+				goto write_cache;
 			}
 
 			u64 timestamp = exact_value_to_u64(exact_value_integer_from_string(timestamp_str));
 			gbFileTime last_write_time = gb_file_last_write_time(alloc_cstring(temporary_allocator(), path_str));
 			if (last_write_time != timestamp) {
-				goto do_write_file;
+				goto write_cache;
 			}
 		}
 
 		if (file_count != files.count) {
-			goto do_write_file;
+			goto write_cache;
 		}
+	}
+	{
+		LoadedFile loaded_file = {};
 
-		goto try_copy_executable;
+		LoadedFileError file_err = load_file_32(
+			alloc_cstring(temporary_allocator(), args_path),
+			&loaded_file,
+			false
+		);
+		if (file_err > LoadedFile_Empty) {
+			return false;
+		}
+
+		String data = {cast(u8 *)loaded_file.data, loaded_file.size};
+		String_Iterator it = {data, 0};
+
+		isize args_count = 0;
+
+		for (; it.pos < data.len; args_count++) {
+			String line = string_split_iterator(&it, '\n');
+			line = string_trim_whitespace(line);
+			if (line.len == 0) {
+				break;
+			}
+			if (args_count >= args.count) {
+				goto write_cache;
+			}
+
+			if (line != args[args_count]) {
+				goto write_cache;
+			}
+		}
 	}
+	{
+		LoadedFile loaded_file = {};
 
-do_write_file:;
+		LoadedFileError file_err = load_file_32(
+			alloc_cstring(temporary_allocator(), env_path),
+			&loaded_file,
+			false
+		);
+		if (file_err > LoadedFile_Empty) {
+			return false;
+		}
+
+		String data = {cast(u8 *)loaded_file.data, loaded_file.size};
+		String_Iterator it = {data, 0};
+
+		isize env_count = 0;
+
+		for (; it.pos < data.len; env_count++) {
+			String line = string_split_iterator(&it, '\n');
+			line = string_trim_whitespace(line);
+			if (line.len == 0) {
+				break;
+			}
+			if (env_count >= envs.count) {
+				goto write_cache;
+			}
+
+			if (line != envs[env_count]) {
+				goto write_cache;
+			}
+		}
+	}
+
+	return try_copy_executable_from_cache();
+
+write_cache:;
 	{
-		char const *manifest_path_c = alloc_cstring(temporary_allocator(), manifest_path);
-		gb_file_remove(manifest_path_c);
+		char const *path_c = alloc_cstring(temporary_allocator(), files_path);
+		gb_file_remove(path_c);
 
 		gbFile f = {};
 		defer (gb_file_close(&f));
-		gb_file_open_mode(&f, gbFileMode_Write, manifest_path_c);
+		gb_file_open_mode(&f, gbFileMode_Write, path_c);
 
 		for (String const &path : files) {
 			gbFileTime ft = gb_file_last_write_time(alloc_cstring(temporary_allocator(), path));
 			gb_fprintf(&f, "%llu %.*s\n", cast(unsigned long long)ft, LIT(path));
 		}
-		return false;
 	}
+	{
+		char const *path_c = alloc_cstring(temporary_allocator(), args_path);
+		gb_file_remove(path_c);
 
-try_copy_executable:;
-	return try_copy_executable_from_cache();
+		gbFile f = {};
+		defer (gb_file_close(&f));
+		gb_file_open_mode(&f, gbFileMode_Write, path_c);
+
+		for (String const &arg : args) {
+			String targ = string_trim_whitespace(arg);
+			gb_fprintf(&f, "%.*s\n", LIT(targ));
+		}
+	}
+	{
+		char const *path_c = alloc_cstring(temporary_allocator(), env_path);
+		gb_file_remove(path_c);
+
+		gbFile f = {};
+		defer (gb_file_close(&f));
+		gb_file_open_mode(&f, gbFileMode_Write, path_c);
+
+		for (String const &env : envs) {
+			gb_fprintf(&f, "%.*s\n", LIT(env));
+		}
+	}
+
+
+	return false;
 }
 

+ 10 - 3
src/main.cpp

@@ -3271,12 +3271,19 @@ int main(int arg_count, char const **arg_ptr) {
 		print_all_errors();
 	}
 
-	MAIN_TIME_SECTION("type check");
 
 	checker->parser = parser;
 	init_checker(checker);
-	defer (destroy_checker(checker));
+	defer (destroy_checker(checker)); // this is here because of a `goto`
+
+	if (build_context.cached && parser->total_seen_load_directive_count.load() == 0) {
+		MAIN_TIME_SECTION("check cached build (pre-semantic check)");
+		if (try_cached_build(checker, args)) {
+			goto end_of_code_gen;
+		}
+	}
 
+	MAIN_TIME_SECTION("type check");
 	check_parsed_files(checker);
 	check_defines(&build_context, checker);
 	if (any_errors()) {
@@ -3331,7 +3338,7 @@ int main(int arg_count, char const **arg_ptr) {
 
 	if (build_context.cached) {
 		MAIN_TIME_SECTION("check cached build");
-		if (try_cached_build(checker)) {
+		if (try_cached_build(checker, args)) {
 			goto end_of_code_gen;
 		}
 	}

+ 10 - 0
src/parser.cpp

@@ -787,6 +787,9 @@ gb_internal Ast *ast_basic_directive(AstFile *f, Token token, Token name) {
 	Ast *result = alloc_ast_node(f, Ast_BasicDirective);
 	result->BasicDirective.token = token;
 	result->BasicDirective.name = name;
+	if (string_starts_with(name.string, str_lit("load"))) {
+		f->seen_load_directive_count++;
+	}
 	return result;
 }
 
@@ -6576,6 +6579,13 @@ gb_internal ParseFileError parse_packages(Parser *p, String init_filename) {
 			}
 		}
 	}
+
+	for (AstPackage *pkg : p->packages) {
+		for (AstFile *file : pkg->files) {
+			p->total_seen_load_directive_count += file->seen_load_directive_count;
+		}
+	}
+
 	return ParseFile_None;
 }
 

+ 4 - 0
src/parser.hpp

@@ -140,6 +140,8 @@ struct AstFile {
 	// This is effectively a queue but does not require any multi-threading capabilities
 	Array<Ast *> delayed_decls_queues[AstDelayQueue_COUNT];
 
+	std::atomic<isize> seen_load_directive_count;
+
 #define PARSER_MAX_FIX_COUNT 6
 	isize    fix_count;
 	TokenPos fix_prev_pos;
@@ -210,6 +212,8 @@ struct Parser {
 	std::atomic<isize>     total_token_count;
 	std::atomic<isize>     total_line_count;
 
+	std::atomic<isize>     total_seen_load_directive_count;
+
 	// TODO(bill): What should this mutex be per?
 	//  * Parser
 	//  * Package