aboutsummaryrefslogtreecommitdiff
path: root/src/build_settings.cpp
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2022-09-04 19:01:32 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2022-09-04 19:01:32 +0200
commitcac72a942313996e2004f6122bfd64d621ee7a33 (patch)
treed021d8a0eeb0dbf08a0e0f9f06132b0f29da46ee /src/build_settings.cpp
parenteb5456f9c7bcf916fb7d12892f32f489a8b284d0 (diff)
Allow Odin to find itself if it's in PATH on OpenBSD, because reasons.
Diffstat (limited to 'src/build_settings.cpp')
-rw-r--r--src/build_settings.cpp69
1 files changed, 66 insertions, 3 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index 3f6be3c48..998c40208 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -830,10 +830,73 @@ String internal_odin_root_dir(void) {
gb_mfree(argv);
return make_string(nullptr, 0);
}
- // copy argv[0] to path_buf
+
+ // NOTE(Jeroen):
+ // On OpenBSD, if `odin` is on the path, `argv[0]` will contain just `odin`,
+ // even though that isn't then the relative path.
+ // When run from Odin's directory, it returns `./odin`.
+ // Check argv[0] for lack of / to see if it's a reference to PATH.
+ // If so, walk PATH to find the executable.
+
len = gb_strlen(argv[0]);
- if(len < path_buf.count) {
- gb_memmove(&path_buf[0], argv[0], len);
+
+ bool slash_found = false;
+ bool odin_found = false;
+
+ for (int i = 0; i < len; i += 1) {
+ if (argv[0][i] == '/') {
+ slash_found = true;
+ break;
+ }
+ }
+
+ if (slash_found) {
+ // copy argv[0] to path_buf
+ if(len < path_buf.count) {
+ gb_memmove(&path_buf[0], argv[0], len);
+ odin_found = true;
+ }
+ } else {
+ gbAllocator a = heap_allocator();
+ char const *path_env = gb_get_env("PATH", a);
+ defer (gb_free(a, cast(void *)path_env));
+
+ if (path_env) {
+ int path_len = gb_strlen(path_env);
+ int path_start = 0;
+ int path_end = 0;
+
+ for (; path_start < path_len; ) {
+ for (; path_end <= path_len; path_end++) {
+ if (path_env[path_end] == ':' || path_end == path_len) {
+ break;
+ }
+ }
+ String path_needle = (const String)make_string((const u8 *)(path_env + path_start), path_end - path_start);
+ String argv0 = (const String)make_string((const u8 *)argv[0], len);
+ String odin_candidate = concatenate3_strings(a, path_needle, STR_LIT("/"), argv0);
+ defer (gb_free(a, odin_candidate.text));
+
+ if (gb_file_exists((const char *)odin_candidate.text)) {
+ len = odin_candidate.len;
+ if(len < path_buf.count) {
+ gb_memmove(&path_buf[0], odin_candidate.text, len);
+ }
+ odin_found = true;
+ break;
+ }
+
+ path_start = path_end + 1;
+ path_end = path_start;
+ if (path_start > path_len) {
+ break;
+ }
+ }
+ }
+
+ if (!odin_found) {
+ gb_printf_err("Odin could not locate itself in PATH, and ODIN_ROOT wasn't set either.\n");
+ }
}
gb_mfree(argv);
#endif