stage1 实现ir2vm 修复nob test命令的构建问题
This commit is contained in:
1 parent
87d9b7ea34
commit
a64a96f9a4
11 files changed
+1565
-195
No files matched your search
+105
-14
@@ -15,34 +15,125 @@ typedef struct {
|
||||
int count;
|
||||
} Nob_Files;
|
||||
|
||||
// 运行命令,捕获 stdout 和退出码(不支持 stdin 和 stderr)
|
||||
// 运行命令,捕获 stdout(Windows 下会合并 stderr)和真实退出码。
|
||||
// 返回 true 仅表示命令成功启动并完成,不代表 exit_code == 0。
|
||||
bool nob_cmd_capture_popen(const char *tname, Nob_Cmd_Result *res) {
|
||||
memset(res, 0, sizeof(*res));
|
||||
|
||||
#ifdef _WIN32
|
||||
FILE *fp = _popen(tname, "r");
|
||||
#else
|
||||
FILE *fp = popen(tname, "r");
|
||||
#endif
|
||||
// ---------- Windows: CreateProcessA + 匿名管道 ----------
|
||||
SECURITY_ATTRIBUTES sa = {0};
|
||||
sa.nLength = sizeof(sa);
|
||||
sa.bInheritHandle = TRUE;
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
|
||||
HANDLE hRead = NULL;
|
||||
HANDLE hWrite = NULL;
|
||||
if (!CreatePipe(&hRead, &hWrite, &sa, 0)) {
|
||||
nob_log(NOB_ERROR, "CreatePipe failed: %s", nob_win32_error_message(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 读端不能被继承,否则父进程 ReadFile 永远等不到 EOF
|
||||
if (!SetHandleInformation(hRead, HANDLE_FLAG_INHERIT, 0)) {
|
||||
nob_log(NOB_ERROR, "SetHandleInformation failed: %s",
|
||||
nob_win32_error_message(GetLastError()));
|
||||
CloseHandle(hRead);
|
||||
CloseHandle(hWrite);
|
||||
return false;
|
||||
}
|
||||
|
||||
STARTUPINFOA si = {0};
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
si.hStdOutput = hWrite;
|
||||
si.hStdError = hWrite; // 把 stderr 也并入 out,需要分离的话另开一条管道
|
||||
|
||||
PROCESS_INFORMATION pi = {0};
|
||||
|
||||
// CreateProcessA 会就地修改 lpCommandLine,必须传可写缓冲
|
||||
char *cmdline = NULL;
|
||||
{
|
||||
size_t n = strlen(tname) + 1;
|
||||
cmdline = (char *)malloc(n);
|
||||
if (!cmdline) {
|
||||
CloseHandle(hRead);
|
||||
CloseHandle(hWrite);
|
||||
nob_log(NOB_ERROR, "malloc failed");
|
||||
return false;
|
||||
}
|
||||
memcpy(cmdline, tname, n);
|
||||
}
|
||||
|
||||
BOOL ok = CreateProcessA(NULL, // lpApplicationName: 让系统从 lpCommandLine 里解析
|
||||
cmdline, // lpCommandLine
|
||||
NULL, // lpProcessAttributes
|
||||
NULL, // lpThreadAttributes
|
||||
TRUE, // bInheritHandles: 必须为 TRUE,才能继承管道写端
|
||||
CREATE_NO_WINDOW, // 不弹黑窗;想弹就传 0
|
||||
NULL, // lpEnvironment
|
||||
NULL, // lpCurrentDirectory
|
||||
&si, &pi);
|
||||
|
||||
free(cmdline);
|
||||
|
||||
// 无论成功与否,父进程都不再需要写端(子进程已持有自己的副本)
|
||||
CloseHandle(hWrite);
|
||||
|
||||
if (!ok) {
|
||||
nob_log(NOB_ERROR, "CreateProcessA failed for \"%s\": %s", tname,
|
||||
nob_win32_error_message(GetLastError()));
|
||||
CloseHandle(hRead);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------- 读取 stdout ----------
|
||||
{
|
||||
char buffer[4096];
|
||||
DWORD n = 0;
|
||||
while (ReadFile(hRead, buffer, sizeof(buffer), &n, NULL) && n > 0) {
|
||||
nob_sb_append_buf(&res->out, buffer, (size_t)n);
|
||||
}
|
||||
}
|
||||
CloseHandle(hRead);
|
||||
|
||||
// ---------- 等待并取真实退出码 ----------
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
DWORD code = 0;
|
||||
if (!GetExitCodeProcess(pi.hProcess, &code)) {
|
||||
nob_log(NOB_ERROR, "GetExitCodeProcess failed: %s",
|
||||
nob_win32_error_message(GetLastError()));
|
||||
code = (DWORD)-1;
|
||||
}
|
||||
res->exit_code = (int)code;
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
#else
|
||||
// ---------- POSIX: popen ----------
|
||||
FILE *fp = popen(tname, "r");
|
||||
if (!fp) {
|
||||
nob_log(NOB_ERROR, "popen failed");
|
||||
nob_log(NOB_ERROR, "popen failed: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 读取输出到 String_Builder
|
||||
char buffer[4096];
|
||||
while (fgets(buffer, sizeof(buffer), fp)) {
|
||||
nob_sb_append_cstr(&res->out, buffer);
|
||||
}
|
||||
|
||||
// 获取退出码
|
||||
#ifdef _WIN32
|
||||
res->exit_code = _pclose(fp);
|
||||
#else
|
||||
res->exit_code = pclose(fp);
|
||||
if (WIFEXITED(res->exit_code))
|
||||
res->exit_code = WEXITSTATUS(res->exit_code);
|
||||
int status = pclose(fp);
|
||||
if (status == -1) {
|
||||
nob_log(NOB_ERROR, "pclose failed: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if (WIFEXITED(status))
|
||||
status = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
status = 128 + WTERMSIG(status);
|
||||
res->exit_code = status;
|
||||
#endif
|
||||
|
||||
res->ok = true;
|
||||
|
||||
Reference in new issue
Block a user