From 47610725eaac53db557cdb8c4d5b9a71b3af48ea Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Sun, 23 Apr 2023 17:02:56 +0100 Subject: [PATCH 01/14] Change default executable extension Putting a program into your path on a UNIX system with a file extension means that you have to type the extension out for every invocation of the program. A better default is to have no extension at all since most people will end up removing it anyway. This change does not affect Windows since the .exe extension is set after the default extension if compiling on Windows. --- src/build_settings.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index ac033df71..7de9e558e 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1497,13 +1497,11 @@ gb_internal bool init_build_paths(String init_filename) { } else if (is_arch_wasm()) { output_extension = STR_LIT("wasm"); } else if (build_context.build_mode == BuildMode_Executable) { - // By default use a .bin executable extension. - output_extension = STR_LIT("bin"); + // By default use no executable extension. + output_extension = make_string(nullptr, 0); if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); - } else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { - output_extension = make_string(nullptr, 0); } } else if (build_context.build_mode == BuildMode_DynamicLibrary) { // By default use a .so shared library extension. From a6b93415933a9d8b27d6b37623d29788278bfc84 Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Sun, 23 Apr 2023 18:53:00 +0100 Subject: [PATCH 02/14] Add .bin extension the case of a collision The directory name is used to determine the executable name. In the case that the directory and output executable are in conflict, a .bin extension is added. --- src/build_settings.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 7de9e558e..a8ad9bd3e 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1502,6 +1502,10 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); + } else if (!str_eq(init_filename, str_lit(".")) && path_is_directory(init_filename)) { + // Add .bin extension to avoid collision + // with package directory name + output_extension = STR_LIT("bin"); } } else if (build_context.build_mode == BuildMode_DynamicLibrary) { // By default use a .so shared library extension. From 06e8d03fbaf01fd78c2729e140c59bf921e7cf6b Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Sun, 23 Apr 2023 21:15:08 +0100 Subject: [PATCH 03/14] Use last element for directory collision check --- src/build_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index a8ad9bd3e..d6b29709a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1502,7 +1502,7 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); - } else if (!str_eq(init_filename, str_lit(".")) && path_is_directory(init_filename)) { + } else if (!str_eq(init_filename, str_lit(".")) && path_is_directory(last_path_element(init_filename))) { // Add .bin extension to avoid collision // with package directory name output_extension = STR_LIT("bin"); From cbcf94669e138a1afcfc8d581257e81b138fbdb9 Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Mon, 24 Apr 2023 12:57:34 +0100 Subject: [PATCH 04/14] Add get_current_directory() --- src/path.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/path.cpp b/src/path.cpp index 49a2d4a4f..baae94670 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -1,6 +1,8 @@ /* Path handling utilities. */ +#include + gb_internal String remove_extension_from_path(String const &s) { if (s.len != 0 && s.text[s.len-1] == '.') { return s; @@ -25,6 +27,16 @@ gb_internal String remove_directory_from_path(String const &s) { return substring(s, s.len-len, s.len); } +// NOTE(Mark Naughton): getcwd as String +gb_internal String get_current_directory(void) { + gbAllocator a = heap_allocator(); + + char cwd[256]; + getcwd(cwd, 256); + + return make_string_c(cwd); +} + gb_internal bool path_is_directory(String path); gb_internal String directory_from_path(String const &s) { From 780375d8654363f7de1eb95278b979d80a9a9775 Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Mon, 24 Apr 2023 12:57:59 +0100 Subject: [PATCH 05/14] Add .bin extension in extra case --- src/build_settings.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index d6b29709a..1bef4b6ad 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1502,9 +1502,15 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); - } else if (!str_eq(init_filename, str_lit(".")) && path_is_directory(last_path_element(init_filename))) { - // Add .bin extension to avoid collision - // with package directory name + } else if (str_eq(init_filename, str_lit("."))) { + // Avoid conflict in edge case where directory to be compiled is + // the same as the current directory's name + if (path_is_directory(last_path_element(get_current_directory()))) { + // Add .bin extension to avoid collision + // with package directory name + output_extension = STR_LIT("bin"); + } + } else if (path_is_directory(last_path_element(init_filename))) { output_extension = STR_LIT("bin"); } } else if (build_context.build_mode == BuildMode_DynamicLibrary) { From 67b6a8ee89f5138f3e10d1d40111ac755ba34149 Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Mon, 24 Apr 2023 14:26:53 +0100 Subject: [PATCH 06/14] Add Windows equivalent of get_current_directory --- src/path.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/path.cpp b/src/path.cpp index baae94670..414a90c39 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -1,7 +1,9 @@ /* Path handling utilities. */ +#if !defined(GB_SYSTEM_WINDOWS) #include +#endif gb_internal String remove_extension_from_path(String const &s) { if (s.len != 0 && s.text[s.len-1] == '.') { @@ -27,7 +29,9 @@ gb_internal String remove_directory_from_path(String const &s) { return substring(s, s.len-len, s.len); } + // NOTE(Mark Naughton): getcwd as String +#if !defined(GB_SYSTEM_WINDOWS) gb_internal String get_current_directory(void) { gbAllocator a = heap_allocator(); @@ -37,6 +41,17 @@ gb_internal String get_current_directory(void) { return make_string_c(cwd); } +#else +gb_internal String get_current_directory(void) { + gbAllocator a = heap_allocator(); + + wchar_t cwd[256]; + GetCurrentDirectoryW(256, cwd); + + return make_string_c(cwd); +} +#endif + gb_internal bool path_is_directory(String path); gb_internal String directory_from_path(String const &s) { From 5151403aaa500fc7a60c5f234f53d46d0b446b03 Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Tue, 25 Apr 2023 12:08:15 +0100 Subject: [PATCH 07/14] Fix Windows version of get_current_directory --- src/path.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/path.cpp b/src/path.cpp index 414a90c39..7664380a4 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -33,8 +33,6 @@ gb_internal String remove_directory_from_path(String const &s) { // NOTE(Mark Naughton): getcwd as String #if !defined(GB_SYSTEM_WINDOWS) gb_internal String get_current_directory(void) { - gbAllocator a = heap_allocator(); - char cwd[256]; getcwd(cwd, 256); @@ -48,7 +46,9 @@ gb_internal String get_current_directory(void) { wchar_t cwd[256]; GetCurrentDirectoryW(256, cwd); - return make_string_c(cwd); + String16 wstr = make_string16_c(cwd); + + return string16_to_string(a, wstr); } #endif From 1a5ed4eb7f0fd88cf22992db8ebf1794464e7a1b Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Wed, 26 Apr 2023 14:10:22 +0100 Subject: [PATCH 08/14] Fix .bin not being applied for relative directory --- src/build_settings.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1bef4b6ad..198de5bc6 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1510,7 +1510,8 @@ gb_internal bool init_build_paths(String init_filename) { // with package directory name output_extension = STR_LIT("bin"); } - } else if (path_is_directory(last_path_element(init_filename))) { + // Path could be absolute or relative + } else if (path_is_directory(last_path_element(init_filename)) || path_is_directory(init_filename)) { output_extension = STR_LIT("bin"); } } else if (build_context.build_mode == BuildMode_DynamicLibrary) { From e84802468b61522b64e15a0eaa6cffe6029311e6 Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Wed, 26 Apr 2023 15:48:59 +0100 Subject: [PATCH 09/14] Use buildpath instead of init_filename --- src/build_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 198de5bc6..b7ecd15f2 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1511,7 +1511,7 @@ gb_internal bool init_build_paths(String init_filename) { output_extension = STR_LIT("bin"); } // Path could be absolute or relative - } else if (path_is_directory(last_path_element(init_filename)) || path_is_directory(init_filename)) { + } else if (path_is_directory(last_path_element(bc->build_paths[BuildPath_Main_Package].basename))) { output_extension = STR_LIT("bin"); } } else if (build_context.build_mode == BuildMode_DynamicLibrary) { From 4b4481ea274283489f39fe3ac3ae871d26a2b46d Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Wed, 26 Apr 2023 16:39:47 +0100 Subject: [PATCH 10/14] Simplify extension addition logic --- src/build_settings.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b7ecd15f2..b74207b85 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1502,16 +1502,9 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); - } else if (str_eq(init_filename, str_lit("."))) { - // Avoid conflict in edge case where directory to be compiled is - // the same as the current directory's name - if (path_is_directory(last_path_element(get_current_directory()))) { - // Add .bin extension to avoid collision - // with package directory name - output_extension = STR_LIT("bin"); - } - // Path could be absolute or relative } else if (path_is_directory(last_path_element(bc->build_paths[BuildPath_Main_Package].basename))) { + // Add .bin extension to avoid collision + // with package directory name output_extension = STR_LIT("bin"); } } else if (build_context.build_mode == BuildMode_DynamicLibrary) { From 413077a5d9ce55850bbb64747e1e7a813e356e5b Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Thu, 18 May 2023 13:23:17 +0100 Subject: [PATCH 11/14] Fix single-file package case --- src/build_settings.cpp | 7 +++++++ src/path.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b74207b85..e690b9ea2 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1499,13 +1499,20 @@ gb_internal bool init_build_paths(String init_filename) { } else if (build_context.build_mode == BuildMode_Executable) { // By default use no executable extension. output_extension = make_string(nullptr, 0); + String const single_file_extension = str_lit(".odin"); if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); + } else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { + output_extension = make_string(nullptr, 0); } else if (path_is_directory(last_path_element(bc->build_paths[BuildPath_Main_Package].basename))) { // Add .bin extension to avoid collision // with package directory name output_extension = STR_LIT("bin"); + } else if (string_ends_with(init_filename, single_file_extension) && path_is_directory(remove_extension_from_path(init_filename))) { + // Add bin extension if compiling single-file package + // with same output name as a directory + output_extension = STR_LIT("bin"); } } else if (build_context.build_mode == BuildMode_DynamicLibrary) { // By default use a .so shared library extension. diff --git a/src/path.cpp b/src/path.cpp index 7664380a4..3054e3b57 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -2,7 +2,7 @@ Path handling utilities. */ #if !defined(GB_SYSTEM_WINDOWS) -#include +#include #endif gb_internal String remove_extension_from_path(String const &s) { From 018904f0ec59244645187b72f01bedcf716ab40c Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Fri, 19 May 2023 18:37:55 +0100 Subject: [PATCH 12/14] Add write permissions check on output folder --- src/build_settings.cpp | 19 ++++++++++++++++++- src/path.cpp | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index e690b9ea2..018c3741a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1504,7 +1504,8 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); } else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { - output_extension = make_string(nullptr, 0); + // Do nothing: we don't want the .bin extension + // when cross compiling } else if (path_is_directory(last_path_element(bc->build_paths[BuildPath_Main_Package].basename))) { // Add .bin extension to avoid collision // with package directory name @@ -1624,6 +1625,22 @@ gb_internal bool init_build_paths(String init_filename) { return false; } + if (path_is_directory(bc->build_paths[BuildPath_Output])) { + String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]); + defer (gb_free(ha, output_file.text)); + gb_printf_err("Output path %.*s is a directory.\n", LIT(output_file)); + return false; + } + //nocheckin char const *pathname = (char *)bc->build_paths[BuildPath_Output].basename.text; + + if (!write_directory(bc->build_paths[BuildPath_Output].basename)) { + String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]); + defer (gb_free(ha, output_file.text)); + gb_printf_err("No write permissions for output path: %.*s\n", LIT(output_file)); + return false; + } + + if (bc->target_features_string.len != 0) { enable_target_feature({}, bc->target_features_string); } diff --git a/src/path.cpp b/src/path.cpp index 3054e3b57..c9887e9ca 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -419,7 +419,43 @@ gb_internal ReadDirectoryError read_directory(String path, Array *fi) return ReadDirectory_None; } + + #else #error Implement read_directory #endif +#if !defined(GB_SYSTEM_WINDOWS) +gb_internal bool write_directory(String path) { + char const *pathname = (char *) path.text; + + if (access(pathname, W_OK) < 0) { + return false; + } + + return true; +} +#else +gb_internal bool write_directory(String path) { + String16wstr = string_to_string16(heap_allocator(), path); + LPCWSTR wdirectory_name = wstr.text; + + HANDLE directory = CreateFileW(wdirectory_name, + GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if (directory == INVALID_HANDLE_VALUE) { + DWORD error_code = GetLastError(); + if (error_code == ERROR_ACCESS_DENIED) { + return false; + } + } + + CloseHandle(directory); + return true; +} +#endif From 775a488a3688a1ce3157366a368349de32279f8c Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Fri, 19 May 2023 18:53:43 +0100 Subject: [PATCH 13/14] Fix windows write_directory() --- src/path.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/path.cpp b/src/path.cpp index c9887e9ca..de80c9def 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -437,7 +437,7 @@ gb_internal bool write_directory(String path) { } #else gb_internal bool write_directory(String path) { - String16wstr = string_to_string16(heap_allocator(), path); + String16 wstr = string_to_string16(heap_allocator(), path); LPCWSTR wdirectory_name = wstr.text; HANDLE directory = CreateFileW(wdirectory_name, From fa1ce7d5d1dc96c7d02184c6c706533bfbf0796b Mon Sep 17 00:00:00 2001 From: Mark Naughton Date: Fri, 19 May 2023 18:56:35 +0100 Subject: [PATCH 14/14] Fix accidental check in --- src/build_settings.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 018c3741a..7c9531da1 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1625,14 +1625,6 @@ gb_internal bool init_build_paths(String init_filename) { return false; } - if (path_is_directory(bc->build_paths[BuildPath_Output])) { - String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]); - defer (gb_free(ha, output_file.text)); - gb_printf_err("Output path %.*s is a directory.\n", LIT(output_file)); - return false; - } - //nocheckin char const *pathname = (char *)bc->build_paths[BuildPath_Output].basename.text; - if (!write_directory(bc->build_paths[BuildPath_Output].basename)) { String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]); defer (gb_free(ha, output_file.text));