fix: CreateProcess 替代 system() 调 ld.lld,消除 shell 转义问题

This commit is contained in:
2026-06-05 22:07:53 +08:00
parent 39d8bad022
commit de91886712
+51 -17
View File
@@ -20,7 +20,9 @@
static void get_exe_dir(char* buf, size_t size) { static void get_exe_dir(char* buf, size_t size) {
#ifdef _WIN32 #ifdef _WIN32
GetModuleFileNameA(NULL, buf, (DWORD)size); GetModuleFileNameA(NULL, buf, (DWORD)size);
char* last = strrchr(buf, '\\'); // 反斜杠 → 正斜杠(兼容 MSYS2 和 cmd.exe
for (char* p = buf; *p; p++) if (*p == '\\') *p = '/';
char* last = strrchr(buf, '/');
if (last) *last = '\0'; if (last) *last = '\0';
#else #else
buf[0] = '.'; buf[1] = '\0'; buf[0] = '.'; buf[1] = '\0';
@@ -152,29 +154,61 @@ int main(int argc, char** argv) {
return 1; return 1;
} }
// 链接:优先安装包自带的 ld.lld + MinGW 库,fallback clang/gcc // 链接:优先安装包自带的 ld.lld + MinGW 库,fallback gcc
char cmd[2048];
int ret = -1; int ret = -1;
char exe_dir[512]; char exe_dir[512];
get_exe_dir(exe_dir, sizeof(exe_dir)); get_exe_dir(exe_dir, sizeof(exe_dir));
// 1) 优先: 安装包自带的 ld.lld + 自带 MinGW 库(完全自包含 // 1) 优先: 安装包自带的 ld.lld + MinGW 库(CreateProcess 避免 shell 转义
snprintf(cmd, sizeof(cmd), {
"\"%s/ld.lld.exe\" -m i386pep " char ld_path[512], crt2[512], crtbegin[512], crtend[512];
"\"%s/mingw_lib/crt2.o\" \"%s/mingw_lib/crtbegin.o\" " char lib_dir[512], out_path[512];
"\"%s\" " snprintf(ld_path, sizeof(ld_path), "%s/ld.lld.exe", exe_dir);
"-L \"%s/mingw_lib\" " snprintf(crt2, sizeof(crt2), "%s/mingw_lib/crt2.o", exe_dir);
"-lmingw32 -lmcfgthread -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt " snprintf(crtbegin, sizeof(crtbegin), "%s/mingw_lib/crtbegin.o", exe_dir);
"-ladvapi32 -lshell32 -luser32 -lkernel32 -lntdll " snprintf(crtend, sizeof(crtend), "%s/mingw_lib/crtend.o", exe_dir);
"\"%s/mingw_lib/crtend.o\" " snprintf(lib_dir, sizeof(lib_dir), "-L%s/mingw_lib", exe_dir);
"-o \"%s\"", snprintf(out_path, sizeof(out_path), "-o%s", output);
exe_dir, exe_dir, exe_dir,
obj_path, exe_dir, const char* ld_args[] = {
exe_dir, output); ld_path, "-m", "i386pep",
ret = system(cmd); crt2, crtbegin, obj_path,
lib_dir,
"-lmingw32", "-lmcfgthread", "-lgcc", "-lgcc_eh",
"-lmoldname", "-lmingwex", "-lmsvcrt",
"-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lntdll",
crtend, out_path, NULL
};
int nargs = sizeof(ld_args) / sizeof(ld_args[0]) - 1;
// 拼成命令行(CreateProcess 需要)
char cmd_line[4096] = {0};
char* p = cmd_line;
for (int i = 0; i < nargs; i++) {
if (i > 0) *p++ = ' ';
// 路径含空格则加引号
bool has_space = strchr(ld_args[i], ' ') != NULL;
if (has_space) *p++ = '"';
p += strlen(strcpy(p, ld_args[i]));
if (has_space) *p++ = '"';
}
STARTUPINFOA si = { sizeof(si) };
PROCESS_INFORMATION pi = {0};
if (CreateProcessA(NULL, cmd_line, NULL, NULL, FALSE,
CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exit_code;
GetExitCodeProcess(pi.hProcess, &exit_code);
ret = (int)exit_code;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
// 2) 最后 fallback: gcc(开发机有 MinGW 时) // 2) 最后 fallback: gcc(开发机有 MinGW 时)
if (ret != 0) { if (ret != 0) {
char cmd[1024];
snprintf(cmd, sizeof(cmd), snprintf(cmd, sizeof(cmd),
"gcc \"%s\" -o \"%s\"", "gcc \"%s\" -o \"%s\"",
obj_path, output); obj_path, output);