From 87ac68fcf2b5fcaa02118929b820e61bbd8c10c4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 8 Jul 2024 23:39:14 +0100 Subject: Add `-internal-cached` --- src/cached.cpp | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/cached.cpp (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp new file mode 100644 index 000000000..89158ccbb --- /dev/null +++ b/src/cached.cpp @@ -0,0 +1,213 @@ +gb_internal GB_COMPARE_PROC(cached_file_cmp) { + String const &x = *(String *)a; + String const &y = *(String *)b; + return string_compare(x, y); +} + + +u64 crc64_with_seed(void const *data, isize len, u64 seed) { + isize remaining; + u64 result = ~seed; + u8 const *c = cast(u8 const *)data; + for (remaining = len; remaining--; c++) { + result = (result >> 8) ^ (GB__CRC64_TABLE[(result ^ *c) & 0xff]); + } + return ~result; +} + +bool check_if_exists_file_otherwise_create(String const &str) { + char const *str_c = alloc_cstring(permanent_allocator(), str); + if (!gb_file_exists(str_c)) { + gbFile f = {}; + gb_file_create(&f, str_c); + gb_file_close(&f); + return true; + } + return false; +} + + +bool check_if_exists_directory_otherwise_create(String const &str) { +#if defined(GB_SYSTEM_WINDOWS) + String16 wstr = string_to_string16(permanent_allocator(), str); + wchar_t *wstr_c = alloc_wstring(permanent_allocator(), wstr); + return CreateDirectoryW(wstr_c, nullptr); +#else + char const *str_c = alloc_cstring(permanent_allocator(), str); + if (!gb_file_exists(str_c)) { + return false; + } + return false; +#endif +} +bool try_copy_executable_cache_internal(bool to_cache) { + String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); + defer (gb_free(heap_allocator(), exe_name.text)); + + gbString cache_name = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(cache_name)); + + String cache_dir = build_context.build_cache_data.cache_dir; + + cache_name = gb_string_append_length(cache_name, cache_dir.text, cache_dir.len); + cache_name = gb_string_appendc(cache_name, "/"); + + cache_name = gb_string_appendc(cache_name, "cached-exe"); + if (selected_target_metrics) { + cache_name = gb_string_appendc(cache_name, "-"); + cache_name = gb_string_append_length(cache_name, selected_target_metrics->name.text, selected_target_metrics->name.len); + } + cache_name = gb_string_appendc(cache_name, ".bin"); + + if (to_cache) { + return gb_file_copy( + alloc_cstring(temporary_allocator(), exe_name), + cache_name, + false + ); + } else { + return gb_file_copy( + cache_name, + alloc_cstring(temporary_allocator(), exe_name), + false + ); + } +} + + + +bool try_copy_executable_to_cache(void) { + if (try_copy_executable_cache_internal(true)) { + build_context.build_cache_data.copy_already_done = true; + return true; + } + return false; +} + +bool try_copy_executable_from_cache(void) { + if (try_copy_executable_cache_internal(false)) { + build_context.build_cache_data.copy_already_done = true; + return true; + } + return false; +} + + + + +// returns false if different, true if it is the same +bool try_cached_build(Checker *c) { + Parser *p = c->parser; + + auto files = array_make(heap_allocator()); + for (AstPackage *pkg : p->packages) { + for (AstFile *f : pkg->files) { + array_add(&files, f->fullpath); + } + } + + for (auto const &entry : c->info.load_file_cache) { + auto *cache = entry.value; + if (!cache || !cache->exists) { + continue; + } + array_add(&files, cache->path); + } + + array_sort(files, cached_file_cmp); + + u64 crc = 0; + for (String const &path : files) { + crc = crc64_with_seed(path.text, path.len, crc); + } + + String base_cache_dir = build_context.build_paths[BuildPath_Output].basename; + base_cache_dir = concatenate_strings(permanent_allocator(), base_cache_dir, str_lit("/.odin-cache")); + (void)check_if_exists_directory_otherwise_create(base_cache_dir); + + 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")); + + build_context.build_cache_data.cache_dir = cache_dir; + build_context.build_cache_data.manifest_path = manifest_path; + + if (check_if_exists_directory_otherwise_create(cache_dir)) { + goto do_write_file; + } + + if (check_if_exists_file_otherwise_create(manifest_path)) { + goto do_write_file; + } else { + // exists already + LoadedFile loaded_file = {}; + + LoadedFileError file_err = load_file_32( + alloc_cstring(temporary_allocator(), manifest_path), + &loaded_file, + false + ); + if (file_err) { + return false; + } + + String data = {cast(u8 *)loaded_file.data, loaded_file.size}; + String_Iterator it = {data, 0}; + + isize file_count = 0; + + for (; it.pos < data.len; file_count++) { + String line = string_split_iterator(&it, '\n'); + if (line.len == 0) { + break; + } + isize sep = string_index_byte(line, ' '); + if (sep < 0) { + goto do_write_file; + } + + String timestamp_str = substring(line, 0, sep); + String path_str = substring(line, sep+1, line.len); + + timestamp_str = string_trim_whitespace(timestamp_str); + path_str = string_trim_whitespace(path_str); + + if (files[file_count] != path_str) { + goto do_write_file; + } + + 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; + } + } + + if (file_count != files.count) { + goto do_write_file; + } + + goto try_copy_executable; + } + +do_write_file:; + { + char const *manifest_path_c = alloc_cstring(temporary_allocator(), manifest_path); + gb_file_remove(manifest_path_c); + + gbFile f = {}; + defer (gb_file_close(&f)); + gb_file_open_mode(&f, gbFileMode_Write, manifest_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; + } + +try_copy_executable:; + return try_copy_executable_from_cache(); +} + -- cgit v1.2.3 From 45bf1808478ca5059dce582182cdf84582dd5a9a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 8 Jul 2024 23:55:01 +0100 Subject: Add subtarget to cached executable --- src/cached.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 89158ccbb..62c7641e5 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -57,6 +57,11 @@ bool try_copy_executable_cache_internal(bool to_cache) { cache_name = gb_string_appendc(cache_name, "-"); cache_name = gb_string_append_length(cache_name, selected_target_metrics->name.text, selected_target_metrics->name.len); } + if (selected_subtarget) { + String st = subtarget_strings[selected_subtarget]; + cache_name = gb_string_appendc(cache_name, "-"); + cache_name = gb_string_append_length(cache_name, st.text, st.len); + } cache_name = gb_string_appendc(cache_name, ".bin"); if (to_cache) { -- cgit v1.2.3 From ccdad8b8dd3af934ef12e833b79c239c8a04895e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 13:31:54 +0100 Subject: Add `odin clear-cache` --- src/cached.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 2 ++ 2 files changed, 83 insertions(+) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 62c7641e5..83950c82b 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -4,6 +4,87 @@ gb_internal GB_COMPARE_PROC(cached_file_cmp) { return string_compare(x, y); } +bool recursively_delete_directory(wchar_t *wpath_c) { +#if defined(GB_SYSTEM_WINDOWS) + auto const is_dots_w = [](wchar_t const *str) -> bool { + if (!str) { + return false; + } + return wcscmp(str, L".") == 0 || wcscmp(str, L"..") == 0; + }; + + TEMPORARY_ALLOCATOR_GUARD(); + + wchar_t dir_path[MAX_PATH] = {}; + wchar_t filename[MAX_PATH] = {}; + wcscpy(dir_path, wpath_c); + wcscat(dir_path, L"\\*"); + + wcscpy(filename, wpath_c); + wcscat(filename, L"\\"); + + + WIN32_FIND_DATAW find_file_data = {}; + HANDLE hfind = FindFirstFileW(dir_path, &find_file_data); + if (hfind == INVALID_HANDLE_VALUE) { + return false; + } + defer (FindClose(hfind)); + + wcscpy(dir_path, filename); + + for (;;) { + if (FindNextFileW(hfind, &find_file_data)) { + if (is_dots_w(find_file_data.cFileName)) { + continue; + } + wcscat(filename, find_file_data.cFileName); + + if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (!recursively_delete_directory(filename)) { + return false; + } + RemoveDirectoryW(filename); + wcscpy(filename, dir_path); + } else { + if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + _wchmod(filename, _S_IWRITE); + } + if (!DeleteFileW(filename)) { + return false; + } + wcscpy(filename, dir_path); + } + } else { + if (GetLastError() == ERROR_NO_MORE_FILES) { + break; + } + return false; + } + } + + + return RemoveDirectoryW(wpath_c); +#else + return false; +#endif +} + +bool recursively_delete_directory(String const &path) { +#if defined(GB_SYSTEM_WINDOWS) + String16 wpath = string_to_string16(permanent_allocator(), path); + wchar_t *wpath_c = alloc_wstring(permanent_allocator(), wpath); + return recursively_delete_directory(wpath_c); +#else + return false; +#endif +} + +int try_clear_cache(void) { + bool ok = recursively_delete_directory(str_lit(".odin-cache")); + return ok ? 0 : 1; +} + u64 crc64_with_seed(void const *data, isize len, u64 seed) { isize remaining; diff --git a/src/main.cpp b/src/main.cpp index 006a7ddbc..49c34014b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3057,6 +3057,8 @@ int main(int arg_count, char const **arg_ptr) { } else if (command == "root") { gb_printf("%.*s", LIT(odin_root_dir())); return 0; + } else if (command == "clear-cache") { + return try_clear_cache(); } else { String argv1 = {}; if (args.count > 1) { -- cgit v1.2.3 From 68b70a21831b3128828357e8af366a377283fa80 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 13:35:52 +0100 Subject: Check for bounds check error --- src/cached.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 83950c82b..ab6d99848 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -259,6 +259,9 @@ bool try_cached_build(Checker *c) { timestamp_str = string_trim_whitespace(timestamp_str); path_str = string_trim_whitespace(path_str); + if (file_count >= files.count) { + goto do_write_file; + } if (files[file_count] != path_str) { goto do_write_file; } -- cgit v1.2.3 From 886ee66e7fcabbd09c20fd55d98051e3854dfd76 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 14:16:56 +0100 Subject: Cache files, env, and args --- src/build_settings.cpp | 7 +- src/cached.cpp | 170 +++++++++++++++++++++++++++++++++++++++++-------- src/main.cpp | 13 +++- src/parser.cpp | 10 +++ src/parser.hpp | 4 ++ 5 files changed, 175 insertions(+), 29 deletions(-) (limited to 'src/cached.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index be896f6fa..28ca0f088 100644 --- a/src/build_settings.cpp +++ b/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; }; diff --git a/src/cached.cpp b/src/cached.cpp index ab6d99848..da72e9989 100644 --- a/src/cached.cpp +++ b/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 const &args) { + TEMPORARY_ALLOCATOR_GUARD(); + Parser *p = c->parser; auto files = array_make(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(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; } diff --git a/src/main.cpp b/src/main.cpp index 49c34014b..f2312f248 100644 --- a/src/main.cpp +++ b/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; } } diff --git a/src/parser.cpp b/src/parser.cpp index 548e46cbe..eb012e980 100644 --- a/src/parser.cpp +++ b/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; } diff --git a/src/parser.hpp b/src/parser.hpp index 521fd7a37..86b3393af 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -140,6 +140,8 @@ struct AstFile { // This is effectively a queue but does not require any multi-threading capabilities Array delayed_decls_queues[AstDelayQueue_COUNT]; + std::atomic 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 total_token_count; std::atomic total_line_count; + std::atomic total_seen_load_directive_count; + // TODO(bill): What should this mutex be per? // * Parser // * Package -- cgit v1.2.3 From 952fb998e6fca880aa579754da5969295ccd9344 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 14:20:55 +0100 Subject: Check for `CURR_DATE_TIME` --- src/cached.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index da72e9989..4b6d82d45 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -237,6 +237,9 @@ bool try_cached_build(Checker *c, Array const &args) { String16 wstr = make_string16_c(curr_string); curr_string += wstr.len+1; String str = string16_to_string(temporary_allocator(), wstr); + if (string_starts_with(str, str_lit("CURR_DATE_TIME="))) { + continue; + } array_add(&envs, str); } #endif -- cgit v1.2.3 From 330d0e7a2a41201eeb0bd844057f46ef42a7e404 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 14:30:38 +0100 Subject: Add `debugf` calls --- src/cached.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 4b6d82d45..59c68c6ee 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -163,6 +163,8 @@ bool try_copy_executable_cache_internal(bool to_cache) { bool try_copy_executable_to_cache(void) { + debugf("Cache: try_copy_executable_to_cache\n"); + if (try_copy_executable_cache_internal(true)) { build_context.build_cache_data.copy_already_done = true; return true; @@ -171,6 +173,8 @@ bool try_copy_executable_to_cache(void) { } bool try_copy_executable_from_cache(void) { + debugf("Cache: try_copy_executable_from_cache\n"); + if (try_copy_executable_cache_internal(false)) { build_context.build_cache_data.copy_already_done = true; return true; @@ -220,10 +224,10 @@ bool try_cached_build(Checker *c, Array const &args) { 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.cache_dir = cache_dir; 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; + build_context.build_cache_data.args_path = args_path; + build_context.build_cache_data.env_path = env_path; auto envs = array_make(heap_allocator()); defer (array_free(&envs)); @@ -384,6 +388,8 @@ write_cache:; char const *path_c = alloc_cstring(temporary_allocator(), files_path); gb_file_remove(path_c); + debugf("Cache: updating %s\n", path_c); + gbFile f = {}; defer (gb_file_close(&f)); gb_file_open_mode(&f, gbFileMode_Write, path_c); @@ -397,6 +403,8 @@ write_cache:; char const *path_c = alloc_cstring(temporary_allocator(), args_path); gb_file_remove(path_c); + debugf("Cache: updating %s\n", path_c); + gbFile f = {}; defer (gb_file_close(&f)); gb_file_open_mode(&f, gbFileMode_Write, path_c); @@ -410,6 +418,8 @@ write_cache:; char const *path_c = alloc_cstring(temporary_allocator(), env_path); gb_file_remove(path_c); + debugf("Cache: updating %s\n", path_c); + gbFile f = {}; defer (gb_file_close(&f)); gb_file_open_mode(&f, gbFileMode_Write, path_c); -- cgit v1.2.3 From 14dc3598b4ef4b32e4fd1bcbf3f6f3ce3e40a9cf Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 14:33:01 +0100 Subject: Add `gb_internal` to procedures --- src/cached.cpp | 23 +++++++++++------------ src/main.cpp | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 59c68c6ee..0cf9dcf5f 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -4,7 +4,7 @@ gb_internal GB_COMPARE_PROC(string_cmp) { return string_compare(x, y); } -bool recursively_delete_directory(wchar_t *wpath_c) { +gb_internal bool recursively_delete_directory(wchar_t *wpath_c) { #if defined(GB_SYSTEM_WINDOWS) auto const is_dots_w = [](wchar_t const *str) -> bool { if (!str) { @@ -70,7 +70,7 @@ bool recursively_delete_directory(wchar_t *wpath_c) { #endif } -bool recursively_delete_directory(String const &path) { +gb_internal bool recursively_delete_directory(String const &path) { #if defined(GB_SYSTEM_WINDOWS) String16 wpath = string_to_string16(permanent_allocator(), path); wchar_t *wpath_c = alloc_wstring(permanent_allocator(), wpath); @@ -80,13 +80,12 @@ bool recursively_delete_directory(String const &path) { #endif } -int try_clear_cache(void) { - bool ok = recursively_delete_directory(str_lit(".odin-cache")); - return ok ? 0 : 1; +gb_internal bool try_clear_cache(void) { + return recursively_delete_directory(str_lit(".odin-cache")); } -u64 crc64_with_seed(void const *data, isize len, u64 seed) { +gb_internal u64 crc64_with_seed(void const *data, isize len, u64 seed) { isize remaining; u64 result = ~seed; u8 const *c = cast(u8 const *)data; @@ -96,7 +95,7 @@ u64 crc64_with_seed(void const *data, isize len, u64 seed) { return ~result; } -bool check_if_exists_file_otherwise_create(String const &str) { +gb_internal bool check_if_exists_file_otherwise_create(String const &str) { char const *str_c = alloc_cstring(permanent_allocator(), str); if (!gb_file_exists(str_c)) { gbFile f = {}; @@ -108,7 +107,7 @@ bool check_if_exists_file_otherwise_create(String const &str) { } -bool check_if_exists_directory_otherwise_create(String const &str) { +gb_internal bool check_if_exists_directory_otherwise_create(String const &str) { #if defined(GB_SYSTEM_WINDOWS) String16 wstr = string_to_string16(permanent_allocator(), str); wchar_t *wstr_c = alloc_wstring(permanent_allocator(), wstr); @@ -121,7 +120,7 @@ bool check_if_exists_directory_otherwise_create(String const &str) { return false; #endif } -bool try_copy_executable_cache_internal(bool to_cache) { +gb_internal bool try_copy_executable_cache_internal(bool to_cache) { String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); defer (gb_free(heap_allocator(), exe_name.text)); @@ -162,7 +161,7 @@ bool try_copy_executable_cache_internal(bool to_cache) { -bool try_copy_executable_to_cache(void) { +gb_internal bool try_copy_executable_to_cache(void) { debugf("Cache: try_copy_executable_to_cache\n"); if (try_copy_executable_cache_internal(true)) { @@ -172,7 +171,7 @@ bool try_copy_executable_to_cache(void) { return false; } -bool try_copy_executable_from_cache(void) { +gb_internal bool try_copy_executable_from_cache(void) { debugf("Cache: try_copy_executable_from_cache\n"); if (try_copy_executable_cache_internal(false)) { @@ -186,7 +185,7 @@ bool try_copy_executable_from_cache(void) { // returns false if different, true if it is the same -bool try_cached_build(Checker *c, Array const &args) { +gb_internal bool try_cached_build(Checker *c, Array const &args) { TEMPORARY_ALLOCATOR_GUARD(); Parser *p = c->parser; diff --git a/src/main.cpp b/src/main.cpp index f2312f248..7763ccd23 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3058,7 +3058,7 @@ int main(int arg_count, char const **arg_ptr) { gb_printf("%.*s", LIT(odin_root_dir())); return 0; } else if (command == "clear-cache") { - return try_clear_cache(); + return try_clear_cache() ? 0 : 1; } else { String argv1 = {}; if (args.count > 1) { -- cgit v1.2.3 From 666703f4301353a8bd435ae88fb698a350ac8e00 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 14:47:22 +0100 Subject: Mock out \*nix stuff for cached.cpp --- src/cached.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 0cf9dcf5f..553ac039f 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -115,7 +115,8 @@ gb_internal bool check_if_exists_directory_otherwise_create(String const &str) { #else char const *str_c = alloc_cstring(permanent_allocator(), str); if (!gb_file_exists(str_c)) { - return false; + int status = mkdir(str_c, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + return status == 0; } return false; #endif @@ -245,6 +246,11 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { } array_add(&envs, str); } + #else + char **curr_env = environ; + while (curr_env && *curr_env) { + array_add(&envs, make_string_c(*curr_env++)); + } #endif } array_sort(envs, string_cmp); -- cgit v1.2.3 From 4c1754b1dc3e13b0c1bb66c3859c4f7b2012b8cd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 14:56:03 +0100 Subject: `environ` is only for Linux --- src/cached.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 553ac039f..2e5f838ef 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -246,11 +246,13 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { } array_add(&envs, str); } - #else + #elif defined(GB_SYSTEM_LINUX) char **curr_env = environ; while (curr_env && *curr_env) { array_add(&envs, make_string_c(*curr_env++)); } + #else + // TODO(bill): environment variables on all other platforms #endif } array_sort(envs, string_cmp); -- cgit v1.2.3 From d7016422939b3c4f0eeec4fb45796667655489cf Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 15:15:23 +0100 Subject: Check for `PROMPT` --- src/cached.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 2e5f838ef..37eac6924 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -183,7 +183,9 @@ gb_internal bool try_copy_executable_from_cache(void) { } - +#if !defined(GB_SYSTEM_WINDOWS) +extern char **environ; +#endif // returns false if different, true if it is the same gb_internal bool try_cached_build(Checker *c, Array const &args) { @@ -244,15 +246,20 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { if (string_starts_with(str, str_lit("CURR_DATE_TIME="))) { continue; } + if (string_starts_with(str, str_lit("PROMPT="))) { + continue; + } array_add(&envs, str); } - #elif defined(GB_SYSTEM_LINUX) + #else char **curr_env = environ; while (curr_env && *curr_env) { - array_add(&envs, make_string_c(*curr_env++)); + String str = make_string_c(*curr_env++); + if (string_starts_with(str, str_lit("PROMPT="))) { + continue; + } + array_add(&envs, str); } - #else - // TODO(bill): environment variables on all other platforms #endif } array_sort(envs, string_cmp); -- cgit v1.2.3 From 5627af582a7882c640f0f4c5b285bafb6377fce1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 15:18:15 +0100 Subject: Add `RPROMPT` to blacklist --- src/cached.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 37eac6924..02cb1ae96 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -246,9 +246,6 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { if (string_starts_with(str, str_lit("CURR_DATE_TIME="))) { continue; } - if (string_starts_with(str, str_lit("PROMPT="))) { - continue; - } array_add(&envs, str); } #else @@ -258,6 +255,9 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { if (string_starts_with(str, str_lit("PROMPT="))) { continue; } + if (string_starts_with(str, str_lit("RPROMPT="))) { + continue; + } array_add(&envs, str); } #endif -- cgit v1.2.3 From cc73e06a46cbefd2afa4caa7ef95ba6d9ab64eb9 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Wed, 10 Jul 2024 15:09:13 +0200 Subject: Allow precompiled resources with -resource:foo.res And add them to the magic new feature. --- src/cached.cpp | 11 +++++++++++ src/linker.cpp | 11 +++-------- src/path.cpp | 7 +++++++ 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 02cb1ae96..36927496d 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -200,6 +200,17 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { } } + // Add Windows resource file to file list, if applicable + if (build_context.has_resource) { + String res_path = {}; + if (build_context.build_paths[BuildPath_RC].basename == "") { + res_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RES]); + } else { + res_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RC]); + } + array_add(&files, res_path); + } + for (auto const &entry : c->info.load_file_cache) { auto *cache = entry.value; if (!cache || !cache->exists) { diff --git a/src/linker.cpp b/src/linker.cpp index ac3e32851..046e72d0e 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -305,18 +305,13 @@ gb_internal i32 linker_stage(LinkerData *gen) { defer (gb_free(heap_allocator(), windows_sdk_bin_path.text)); if (!build_context.use_lld) { // msvc - String temp_res_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RES]); - String temp_rc_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RC]); - defer (gb_free(heap_allocator(), temp_res_path.text)); - defer (gb_free(heap_allocator(), temp_rc_path.text)); - - String res_path = concatenate3_strings(heap_allocator(), str_lit("\""), temp_res_path, str_lit("\"")); - String rc_path = concatenate3_strings(heap_allocator(), str_lit("\""), temp_rc_path, str_lit("\"")); + 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)); if (build_context.has_resource) { - if (temp_rc_path == "") { + 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)); diff --git a/src/path.cpp b/src/path.cpp index 26ccb7cbf..2c08ddd98 100644 --- a/src/path.cpp +++ b/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); -- cgit v1.2.3 From 4148c6d6c749eac62b7d1a978f820b82de7d3bea Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Wed, 10 Jul 2024 15:25:49 +0200 Subject: #if WINDOWS --- src/cached.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 36927496d..7f213ba21 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -200,16 +200,17 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { } } - // Add Windows resource file to file list, if applicable - if (build_context.has_resource) { - String res_path = {}; - if (build_context.build_paths[BuildPath_RC].basename == "") { - res_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RES]); - } else { - res_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RC]); + #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); } - array_add(&files, res_path); - } + #endif for (auto const &entry : c->info.load_file_cache) { auto *cache = entry.value; -- cgit v1.2.3 From 3311ea1c7667364af9cd3f233d1a774e50879e3c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 00:38:10 +0100 Subject: Keep MSVC happy with secure versions of C calls --- src/cached.cpp | 16 ++++++++-------- src/checker.cpp | 4 ++++ src/common.cpp | 2 ++ src/main.cpp | 10 ---------- 4 files changed, 14 insertions(+), 18 deletions(-) (limited to 'src/cached.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 7f213ba21..4ad65ee9e 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -17,11 +17,11 @@ gb_internal bool recursively_delete_directory(wchar_t *wpath_c) { wchar_t dir_path[MAX_PATH] = {}; wchar_t filename[MAX_PATH] = {}; - wcscpy(dir_path, wpath_c); - wcscat(dir_path, L"\\*"); + wcscpy_s(dir_path, wpath_c); + wcscat_s(dir_path, L"\\*"); - wcscpy(filename, wpath_c); - wcscat(filename, L"\\"); + wcscpy_s(filename, wpath_c); + wcscat_s(filename, L"\\"); WIN32_FIND_DATAW find_file_data = {}; @@ -31,21 +31,21 @@ gb_internal bool recursively_delete_directory(wchar_t *wpath_c) { } defer (FindClose(hfind)); - wcscpy(dir_path, filename); + wcscpy_s(dir_path, filename); for (;;) { if (FindNextFileW(hfind, &find_file_data)) { if (is_dots_w(find_file_data.cFileName)) { continue; } - wcscat(filename, find_file_data.cFileName); + wcscat_s(filename, find_file_data.cFileName); if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (!recursively_delete_directory(filename)) { return false; } RemoveDirectoryW(filename); - wcscpy(filename, dir_path); + wcscpy_s(filename, dir_path); } else { if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { _wchmod(filename, _S_IWRITE); @@ -53,7 +53,7 @@ gb_internal bool recursively_delete_directory(wchar_t *wpath_c) { if (!DeleteFileW(filename)) { return false; } - wcscpy(filename, dir_path); + wcscpy_s(filename, dir_path); } } else { if (GetLastError() == ERROR_NO_MORE_FILES) { diff --git a/src/checker.cpp b/src/checker.cpp index 0a671cc2d..0e65af211 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1117,7 +1117,11 @@ gb_internal void init_universal(void) { int minimum_os_version = 0; if (build_context.minimum_os_version_string != "") { int major, minor, revision = 0; + #if defined(GB_SYSTEM_WINDOWS) + sscanf_s(cast(const char *)(build_context.minimum_os_version_string.text), "%d.%d.%d", &major, &minor, &revision); + #else sscanf(cast(const char *)(build_context.minimum_os_version_string.text), "%d.%d.%d", &major, &minor, &revision); + #endif minimum_os_version = (major*10000)+(minor*100)+revision; } add_global_constant("ODIN_MINIMUM_OS_VERSION", t_untyped_integer, exact_value_i64(minimum_os_version)); diff --git a/src/common.cpp b/src/common.cpp index 69426e2a6..0ef39bd10 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -14,6 +14,8 @@ #undef NOMINMAX #endif +#include + #define GB_WINDOWS_H_INCLUDED #define GB_IMPLEMENTATION #include "gb/gb.h" diff --git a/src/main.cpp b/src/main.cpp index 388184be9..ef9cad873 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -399,8 +399,6 @@ enum BuildFlagKind { BuildFlag_Sanitize, - BuildFlag_FastBuild, - #if defined(GB_SYSTEM_WINDOWS) BuildFlag_IgnoreVsSearch, BuildFlag_ResourceFile, @@ -607,8 +605,6 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Sanitize, str_lit("sanitize"), BuildFlagParam_String, Command__does_build, true); - add_flag(&build_flags, BuildFlag_FastBuild, str_lit("fast-build"), BuildFlagParam_None, Command__does_build); - #if defined(GB_SYSTEM_WINDOWS) add_flag(&build_flags, BuildFlag_IgnoreVsSearch, str_lit("ignore-vs-search"), BuildFlagParam_None, Command__does_build); @@ -1447,12 +1443,6 @@ gb_internal bool parse_build_flags(Array args) { break; - case BuildFlag_FastBuild: - build_context.custom_optimization_level = true; - build_context.optimization_level = -1; - build_context.use_separate_modules = true; - break; - #if defined(GB_SYSTEM_WINDOWS) case BuildFlag_IgnoreVsSearch: { GB_ASSERT(value.kind == ExactValue_Invalid); -- cgit v1.2.3 From 28b26043fb1b036e94ff741b7409b1ef94587a09 Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Tue, 22 Oct 2024 17:58:54 +1100 Subject: cached.cpp: Improve internal cached robustness Do not memory map files; Windows cannot write to a file that is memory mapped. Write cache after llvm building. This ensures the cache won't have a false positive if llvm fails. --- odin.rdi | Bin 0 -> 6593532 bytes src/cached.cpp | 109 ++++++++++++++++++++++++++++++++------------------------- src/main.cpp | 21 +++++++---- 3 files changed, 75 insertions(+), 55 deletions(-) create mode 100644 odin.rdi (limited to 'src/cached.cpp') diff --git a/odin.rdi b/odin.rdi new file mode 100644 index 000000000..851ee3578 Binary files /dev/null and b/odin.rdi differ diff --git a/src/cached.cpp b/src/cached.cpp index 4ad65ee9e..efdadce7b 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -187,10 +187,7 @@ gb_internal bool try_copy_executable_from_cache(void) { extern char **environ; #endif -// returns false if different, true if it is the same -gb_internal bool try_cached_build(Checker *c, Array const &args) { - TEMPORARY_ALLOCATOR_GUARD(); - +Array cache_gather_files(Checker *c) { Parser *p = c->parser; auto files = array_make(heap_allocator()); @@ -222,29 +219,11 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { array_sort(files, string_cmp); - u64 crc = 0; - for (String const &path : files) { - crc = crc64_with_seed(path.text, path.len, crc); - } - - String base_cache_dir = build_context.build_paths[BuildPath_Output].basename; - base_cache_dir = concatenate_strings(permanent_allocator(), base_cache_dir, str_lit("/.odin-cache")); - (void)check_if_exists_directory_otherwise_create(base_cache_dir); - - 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 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.files_path = files_path; - build_context.build_cache_data.args_path = args_path; - build_context.build_cache_data.env_path = env_path; + return files; +} +Array cache_gather_envs() { auto envs = array_make(heap_allocator()); - defer (array_free(&envs)); { #if defined(GB_SYSTEM_WINDOWS) wchar_t *strings = GetEnvironmentStringsW(); @@ -275,19 +254,50 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { #endif } array_sort(envs, string_cmp); + return envs; +} + +// returns false if different, true if it is the same +gb_internal bool try_cached_build(Checker *c, Array const &args) { + TEMPORARY_ALLOCATOR_GUARD(); + + auto files = cache_gather_files(c); + auto envs = cache_gather_envs(); + defer (array_free(&envs)); + + u64 crc = 0; + for (String const &path : files) { + crc = crc64_with_seed(path.text, path.len, crc); + } + + String base_cache_dir = build_context.build_paths[BuildPath_Output].basename; + base_cache_dir = concatenate_strings(permanent_allocator(), base_cache_dir, str_lit("/.odin-cache")); + (void)check_if_exists_directory_otherwise_create(base_cache_dir); + + 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 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.files_path = files_path; + build_context.build_cache_data.args_path = args_path; + build_context.build_cache_data.env_path = env_path; if (check_if_exists_directory_otherwise_create(cache_dir)) { - goto write_cache; + return false; } if (check_if_exists_file_otherwise_create(files_path)) { - goto write_cache; + return false; } if (check_if_exists_file_otherwise_create(args_path)) { - goto write_cache; + return false; } if (check_if_exists_file_otherwise_create(env_path)) { - goto write_cache; + return false; } { @@ -297,7 +307,7 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { LoadedFileError file_err = load_file_32( alloc_cstring(temporary_allocator(), files_path), &loaded_file, - false + true ); if (file_err > LoadedFile_Empty) { return false; @@ -315,7 +325,7 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { } isize sep = string_index_byte(line, ' '); if (sep < 0) { - goto write_cache; + return false; } String timestamp_str = substring(line, 0, sep); @@ -325,21 +335,21 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { path_str = string_trim_whitespace(path_str); if (file_count >= files.count) { - goto write_cache; + return false; } if (files[file_count] != path_str) { - goto write_cache; + return false; } 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 write_cache; + return false; } } if (file_count != files.count) { - goto write_cache; + return false; } } { @@ -348,7 +358,7 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { LoadedFileError file_err = load_file_32( alloc_cstring(temporary_allocator(), args_path), &loaded_file, - false + true ); if (file_err > LoadedFile_Empty) { return false; @@ -366,11 +376,11 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { break; } if (args_count >= args.count) { - goto write_cache; + return false; } if (line != args[args_count]) { - goto write_cache; + return false; } } } @@ -380,7 +390,7 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { LoadedFileError file_err = load_file_32( alloc_cstring(temporary_allocator(), env_path), &loaded_file, - false + true ); if (file_err > LoadedFile_Empty) { return false; @@ -398,20 +408,26 @@ gb_internal bool try_cached_build(Checker *c, Array const &args) { break; } if (env_count >= envs.count) { - goto write_cache; + return false; } if (line != envs[env_count]) { - goto write_cache; + return false; } } } return try_copy_executable_from_cache(); +} + +void write_cached_build(Checker *c, Array const &args) { + auto files = cache_gather_files(c); + defer (array_free(&files)); + auto envs = cache_gather_envs(); + defer (array_free(&envs)); -write_cache:; { - char const *path_c = alloc_cstring(temporary_allocator(), files_path); + char const *path_c = alloc_cstring(temporary_allocator(), build_context.build_cache_data.files_path); gb_file_remove(path_c); debugf("Cache: updating %s\n", path_c); @@ -426,7 +442,7 @@ write_cache:; } } { - char const *path_c = alloc_cstring(temporary_allocator(), args_path); + char const *path_c = alloc_cstring(temporary_allocator(), build_context.build_cache_data.args_path); gb_file_remove(path_c); debugf("Cache: updating %s\n", path_c); @@ -441,7 +457,7 @@ write_cache:; } } { - char const *path_c = alloc_cstring(temporary_allocator(), env_path); + char const *path_c = alloc_cstring(temporary_allocator(), build_context.build_cache_data.env_path); gb_file_remove(path_c); debugf("Cache: updating %s\n", path_c); @@ -454,8 +470,5 @@ write_cache:; gb_fprintf(&f, "%.*s\n", LIT(env)); } } - - - return false; } diff --git a/src/main.cpp b/src/main.cpp index 04d3bdf52..1574ac544 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3391,6 +3391,7 @@ int main(int arg_count, char const **arg_ptr) { Parser *parser = gb_alloc_item(permanent_allocator(), Parser); Checker *checker = gb_alloc_item(permanent_allocator(), Checker); + bool failed_to_cache_parsing = false; MAIN_TIME_SECTION("parse files"); @@ -3480,6 +3481,7 @@ int main(int arg_count, char const **arg_ptr) { if (try_cached_build(checker, args)) { goto end_of_code_gen; } + failed_to_cache_parsing = true; } #if ALLOW_TILDE @@ -3545,18 +3547,23 @@ int main(int arg_count, char const **arg_ptr) { end_of_code_gen:; - if (build_context.show_timings) { - show_timings(checker, &global_timings); - } - if (build_context.export_dependencies_format != DependenciesExportUnspecified) { export_dependencies(checker); } + if (build_context.cached) { + MAIN_TIME_SECTION("write cached build"); + if (!build_context.build_cache_data.copy_already_done) { + try_copy_executable_to_cache(); + } - if (!build_context.build_cache_data.copy_already_done && - build_context.cached) { - try_copy_executable_to_cache(); + if (failed_to_cache_parsing) { + write_cached_build(checker, args); + } + } + + if (build_context.show_timings) { + show_timings(checker, &global_timings); } if (run_output) { -- cgit v1.2.3