Merge pull request #7485 from Yawning/fix/linker-system

src: Use `posix_spawnp` instead of `system()` when invoking the linker
This commit is contained in:
Jeroen van Rijn
2026-09-01 03:02:46 -07:00
committed by GitHub
3 changed files with 91 additions and 4 deletions

View File

@@ -739,6 +739,75 @@ gb_internal wchar_t **command_line_to_wargv(wchar_t *cmd_line, int *_argc, isize
return argv;
}
#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
gb_internal char **command_line_to_spawn_argv(const char *cmd_line, int *_argc) {
u32 i, j;
u32 len = cast(u32)strlen(cmd_line);
i = len*gb_size_of(void *) + gb_size_of(void *);
char **argv = cast(char **)gb_alloc(gb_heap_allocator(), i + (len+1));
char *_argv = (cast(char *)argv)+i;
u32 argc = 0;
argv[argc] = _argv;
bool in_quote = false;
bool in_text = false;
bool in_space = true;
i = 0;
j = 0;
for (;;) {
char a = cmd_line[i];
if (a == 0) {
break;
}
if (in_quote) {
if (a == '\"') {
in_quote = false;
} else {
_argv[j++] = a;
}
} else {
switch (a) {
case '\"':
in_quote = true;
in_text = true;
if (in_space) {
// check_double_dash();
argv[argc++] = _argv + j;
}
in_space = false;
break;
case ' ':
case '\t':
case '\n':
case '\r':
if (in_text) _argv[j++] = '\0';
in_text = false;
in_space = true;
break;
default:
in_text = true;
if (in_space) {
// check_double_dash();
argv[argc++] = _argv + j;
}
_argv[j++] = a;
in_space = false;
break;
}
}
i++;
}
_argv[j] = '\0';
argv[argc] = nullptr;
if (_argc) *_argc = argc;
return argv;
}
#endif
#include "path.cpp"

View File

@@ -810,6 +810,7 @@ try_cross_linking:;
}
} else if (build_context.build_mode != BuildMode_DynamicLibrary) {
if (build_context.metrics.os != TargetOs_openbsd
&& build_context.metrics.os != TargetOs_darwin
&& build_context.metrics.arch != TargetArch_riscv64
&& !is_android
) {
@@ -961,7 +962,7 @@ try_cross_linking:;
if (is_android) {
// ignore
} else {
link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,\\$ORIGIN ");
link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,$ORIGIN ");
}
}
}

View File

@@ -83,6 +83,10 @@ gb_global Timings global_timings = {0};
#include "bug_report.cpp"
#if defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
int run_subprocess(const char *name, const char **args, bool honor_path = false);
#endif
// NOTE(bill): 'name' is used in debugging and profiling modes
gb_internal i32 system_exec_command_line_app_internal(bool exit_on_err, char const *name, char const *fmt, va_list va) {
isize const cmd_cap = 64<<20; // 64 MiB should be more than enough
@@ -154,7 +158,11 @@ gb_internal i32 system_exec_command_line_app_internal(bool exit_on_err, char con
gb_printf_err("[SYSTEM CALL] %s\n", name);
gb_printf_err("%s\n\n", cmd_line);
}
exit_code = system(cmd_line);
int argc;
char **argv = command_line_to_spawn_argv(cmd_line, &argc);
exit_code = run_subprocess(argv[0], cast(const char**)(argv), true);
if (exit_on_err && WIFSIGNALED(exit_code)) {
struct rlimit limit = { 0, 0, };
setrlimit(RLIMIT_CORE, &limit);
@@ -236,10 +244,19 @@ int run_subprocess(String const &exe_name, wchar_t *after_double_dash_raw) {
return exit_code;
}
#else
int run_subprocess(const char *name, const char **args) {
int run_subprocess(const char *name, const char **args, bool honor_path) {
pid_t pid;
int status;
status = posix_spawn(&pid, name, NULL, NULL, (char *const *)args, environ);
String exec_name = make_string_c(args[0]);
exec_name = last_path_element(exec_name);
args[0] = alloc_cstring(gb_heap_allocator(), exec_name);
if (!honor_path) {
status = posix_spawn(&pid, name, NULL, NULL, (char *const *)args, environ);
} else {
status = posix_spawnp(&pid, name, NULL, NULL, (char *const *)args, environ);
}
if (status != 0) {
gb_printf_err("Could not spawn subprocess: %s\n", strerror(errno));
return -1;