build: finish cross-platform release tooling

This commit is contained in:
WHC
2026-10-10 16:21:00 +08:00
parent 9bf7707912
commit 50abcf1a91
29 changed files with 973 additions and 230 deletions
+71 -12
View File
@@ -13,6 +13,7 @@
#include "os_internal.h"
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -503,19 +504,74 @@ int os_resolve_shell(char *out, size_t out_sz) {
#endif
}
/* Per thread: parallel tool runs and sub-agents each watch their own flag. */
static _Thread_local volatile int *g_run_cancel;
static _Thread_local int g_run_timeout_s;
/* Per thread: parallel tool runs and sub-agents each watch their own flag.
* Thread keys rather than _Thread_local, which tcc does not implement; each
* value fits in the key's pointer slot, so nothing is allocated. */
#ifdef _WIN32
static INIT_ONCE g_run_once = INIT_ONCE_STATIC_INIT;
static DWORD g_key_cancel = TLS_OUT_OF_INDEXES, g_key_timeout = TLS_OUT_OF_INDEXES;
static BOOL CALLBACK run_keys_init(PINIT_ONCE once, PVOID param, PVOID *ctx) {
(void)once;
(void)param;
(void)ctx;
g_key_cancel = TlsAlloc();
g_key_timeout = TlsAlloc();
return TRUE;
}
static void *run_key_get(DWORD *key) {
InitOnceExecuteOnce(&g_run_once, run_keys_init, NULL, NULL);
if (*key == TLS_OUT_OF_INDEXES)
return NULL;
DWORD err = GetLastError(); /* TlsGetValue clears it */
void *v = TlsGetValue(*key);
SetLastError(err);
return v;
}
static void run_key_set(DWORD *key, void *v) {
InitOnceExecuteOnce(&g_run_once, run_keys_init, NULL, NULL);
if (*key != TLS_OUT_OF_INDEXES)
TlsSetValue(*key, v);
}
#else
static pthread_once_t g_run_once = PTHREAD_ONCE_INIT;
static pthread_key_t g_key_cancel, g_key_timeout;
static int g_run_keys_ok;
static void run_keys_init(void) {
g_run_keys_ok = pthread_key_create(&g_key_cancel, NULL) == 0 &&
pthread_key_create(&g_key_timeout, NULL) == 0;
}
static void *run_key_get(pthread_key_t *key) {
pthread_once(&g_run_once, run_keys_init);
return g_run_keys_ok ? pthread_getspecific(*key) : NULL;
}
static void run_key_set(pthread_key_t *key, void *v) {
pthread_once(&g_run_once, run_keys_init);
if (g_run_keys_ok)
pthread_setspecific(*key, v);
}
#endif
void os_set_cancel_flag(volatile int *flag) { g_run_cancel = flag; }
static volatile int *run_cancel(void) {
return (volatile int *)run_key_get(&g_key_cancel);
}
static int run_timeout(void) {
return (int)(intptr_t)run_key_get(&g_key_timeout);
}
void os_set_run_timeout(int seconds) { g_run_timeout_s = seconds; }
void os_set_cancel_flag(volatile int *flag) {
run_key_set(&g_key_cancel, (void *)(uintptr_t)flag);
}
int os_get_run_timeout(void) { return g_run_timeout_s; }
void os_set_run_timeout(int seconds) {
run_key_set(&g_key_timeout, (void *)(intptr_t)seconds);
}
int os_get_run_timeout(void) { return run_timeout(); }
int os_run_timeout_effective(void) {
if (g_run_timeout_s > 0)
return g_run_timeout_s;
int t = run_timeout();
if (t > 0)
return t;
const char *e = getenv("CST_SHELL_TIMEOUT");
if (e && atoi(e) > 0)
return atoi(e);
@@ -693,8 +749,8 @@ int os_run_capture_ex(const char *cwd, const char *const argv[],
}
/* Checked on every pass, so a chatty command still stops promptly. */
if (!reaped && !killed &&
((g_run_cancel && *g_run_cancel) || (deadline > 0 && now > deadline))) {
killed = (g_run_cancel && *g_run_cancel) ? 2 : 1;
(os_cancel_requested() || (deadline > 0 && now > deadline))) {
killed = os_cancel_requested() ? 2 : 1;
killed_at = now;
kill(-pid, SIGTERM);
}
@@ -900,9 +956,12 @@ void os_run_parallel(os_task_fn fn, void *const args[], int n) {
free(tasks);
}
int os_cancel_requested(void) { return g_run_cancel && *g_run_cancel; }
int os_cancel_requested(void) {
volatile int *c = run_cancel();
return c && *c;
}
volatile int *os_get_cancel_flag(void) { return g_run_cancel; }
volatile int *os_get_cancel_flag(void) { return run_cancel(); }
#ifndef _WIN32
int os_proc_spawn(const char *cwd, const char *const argv[],