Skip to content

Commit

Permalink
bootstrap.c: Port to Windows.
Browse files Browse the repository at this point in the history
  • Loading branch information
alexrp committed Nov 23, 2024
1 parent 7ab2602 commit f1210a8
Showing 1 changed file with 202 additions and 96 deletions.
298 changes: 202 additions & 96 deletions bootstrap.c
Original file line number Diff line number Diff line change
@@ -1,62 +1,128 @@
// Bootstrap the self-hosted Zig compiler using a C compiler.
//
// Some ways to run this program:
//
// $ tcc -run bootstrap.c
// $ cc bootstrap.c -o bootstrap && ./bootstrap
// $ cl.exe bootstrap.c /link /out:bootstrap.exe && .\bootstrap.exe
//
// This program will try its best to invoke the same C compiler that it was
// built with. To override this behavior, set the CC environment variable.
//
// The following environment variables can be set to override the target
// triple detection for the system this program runs on (the host):
//
// * ZIG_HOST_TARGET_ARCH
// * ZIG_HOST_TARGET_OS
// * ZIG_HOST_TARGET_ABI
// * ZIG_HOST_TARGET_TRIPLE (overrides all of the above)

#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#if defined(_WIN32)
#include <process.h>
#else
#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>
#endif

static const char *get_c_compiler(void) {
const char *cc = getenv("CC");
return (cc == NULL) ? "cc" : cc;
if (cc != NULL) return cc;
#if defined(_MSC_VER)
return "cl";
#else
return "cc";
#endif
}

static void panic(const char *reason) {
fprintf(stderr, "%s\n", reason);
static void panic(const char *format, ...) {
fputs("panic: ", stderr);
va_list vargs;
va_start(vargs, format);
vfprintf(stderr, format, vargs);
va_end(vargs);
fputs("\n", stderr);
abort();
}

#if defined(__WIN32__)
#error TODO write the functionality for executing child process into this build script
#else
static void error(const char *format, ...) {
fputs("error: ", stderr);
va_list vargs;
va_start(vargs, format);
vfprintf(stderr, format, vargs);
va_end(vargs);
fprintf(stderr, ": %s (%d)\n", strerror(errno), errno);
exit(1);
}

#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
static void fatal(const char *format, ...) {
fputs("fatal: ", stderr);
va_list vargs;
va_start(vargs, format);
vfprintf(stderr, format, vargs);
va_end(vargs);
fputs("\n", stderr);
exit(1);
}

static void run(char **argv) {
pid_t pid = fork();
if (pid == -1)
panic("fork failed");
if (pid == 0) {
// child
execvp(argv[0], argv);
exit(1);
}
static void usage(const char *message) {
fprintf(stderr, "%s\n", message);
exit(2);
}

// parent
static void run(const char *const *argv) {
#if defined(_WIN32)
intptr_t status = _spawnvp(_P_WAIT, argv[0], argv);
switch (status) {
case -1: error("_spawnv(%s, ...)", argv[0]); break;
case 0: break;
default: fatal("child process failed: %d", status); break;
}
#else
pid_t pid = fork();
switch (pid) {
case -1: error("fork()"); break;
case 0: {
// child
execvp(argv[0], (char *const *)argv);
panic("execve(%s, ...) returned", argv[0]);

int status;
waitpid(pid, &status, 0);
break;
}
default: {
// parent
int wstatus;
if (waitpid(pid, &wstatus, 0) == -1) error("waitpid(%d, ..., 0)", pid);
if (!WIFEXITED(wstatus)) fatal("child process crashed");

if (!WIFEXITED(status))
panic("child process crashed");
int status = WEXITSTATUS(wstatus);
if (status != 0) fatal("child process failed: %d", status);

if (WEXITSTATUS(status) != 0)
panic("child process failed");
}
break;
}
}
#endif
}

static void print_and_run(const char **argv) {
static void print_and_run(const char *const *argv) {
fprintf(stderr, "%s", argv[0]);
for (const char **arg = argv + 1; *arg; arg += 1) {
for (const char *const *arg = argv + 1; *arg; arg++) {
fprintf(stderr, " %s", *arg);
}
fprintf(stderr, "\n");
run((char **)argv);
run(argv);
}

static const char *get_host_os(void) {
const char *host_os = getenv("ZIG_HOST_TARGET_OS");
if (host_os != NULL) return host_os;
#if defined(__WIN32__)
#if defined(_WIN32)
return "windows";
#elif defined(__APPLE__)
return "macos";
Expand All @@ -67,25 +133,30 @@ static const char *get_host_os(void) {
#elif defined(__HAIKU__)
return "haiku";
#else
panic("unknown host os, specify with ZIG_HOST_TARGET_OS");
usage("unknown host OS; specify with environment variable ZIG_HOST_TARGET_OS");
#endif
}

static const char *get_host_arch(void) {
const char *host_arch = getenv("ZIG_HOST_TARGET_ARCH");
if (host_arch != NULL) return host_arch;
#if defined(__x86_64__ )
#if defined(__x86_64__) || defined(_M_X64)
return "x86_64";
#elif defined(__aarch64__)
#elif defined(__aarch64__) || defined(_M_ARM64)
return "aarch64";
#else
panic("unknown host arch, specify with ZIG_HOST_TARGET_ARCH");
usage("unknown host architecture; specify with environment variable ZIG_HOST_TARGET_ARCH");
#endif
}

static const char *get_host_abi(void) {
const char *host_abi = getenv("ZIG_HOST_TARGET_ABI");
return (host_abi == NULL) ? "" : host_abi;
if (host_abi != NULL) return host_abi;
#if defined(_MSC_VER)
return "-msvc";
#else
return "";
#endif
}

static const char *get_host_triple(void) {
Expand All @@ -100,28 +171,50 @@ int main(int argc, char **argv) {
const char *cc = get_c_compiler();
const char *host_triple = get_host_triple();

{
const char *child_argv[] = {
cc, "-o", "zig-wasm2c", "stage1/wasm2c.c", "-O2", "-std=c99", NULL,
};
print_and_run(child_argv);
}
{
const char *child_argv[] = {
"./zig-wasm2c", "stage1/zig1.wasm", "zig1.c", NULL,
};
print_and_run(child_argv);
}
{
const char *child_argv[] = {
cc, "-o", "zig1", "zig1.c", "stage1/wasi.c", "-std=c99", "-Os", "-lm", NULL,
};
print_and_run(child_argv);
}
print_and_run((const char *[]) {
cc,
#if defined(_MSC_VER)
"stage1/wasm2c.c",
"/O2",
"/link",
"/OUT:zig-wasm2c.exe",
#else
"stage1/wasm2c.c",
"-std=c99",
"-O2",
"-o", "zig-wasm2c",
#endif
NULL,
});

print_and_run((const char *[]) {
"./zig-wasm2c", "stage1/zig1.wasm", "zig1.c",
NULL,
});

print_and_run((const char *[]) {
cc,
#if defined(_MSC_VER)
"zig1.c",
"stage1/wasi.c",
"/O1",
"/link",
"/OUT:zig1.exe",
#else
"zig1.c",
"stage1/wasi.c",
"-std=c99",
"-Os",
"-lm",
"-o", "zig1",
#endif
NULL,
});

{
FILE *f = fopen("config.zig", "wb");
if (f == NULL)
panic("unable to open config.zig for writing");
error("fopen(\"config.zig\", \"wb\")");

const char *zig_version = "0.14.0-dev.bootstrap";

Expand All @@ -145,52 +238,65 @@ int main(int argc, char **argv) {
if (written < 100)
panic("unable to write to config.zig file");
if (fclose(f) != 0)
panic("unable to finish writing to config.zig file");
error("fclose(\"config.zig\")");
}

{
const char *child_argv[] = {
"./zig1", "lib", "build-exe",
"-ofmt=c", "-lc", "-OReleaseSmall",
"--name", "zig2", "-femit-bin=zig2.c",
"-target", host_triple,
"--dep", "build_options",
"--dep", "aro",
"-Mroot=src/main.zig",
"-Mbuild_options=config.zig",
"-Maro=lib/compiler/aro/aro.zig",
NULL,
};
print_and_run(child_argv);
}
print_and_run((const char *[]) {
"./zig1", "lib", "build-exe",
"-OReleaseSmall",
"-target", host_triple,
"-lc",
"-ofmt=c",
"-femit-bin=zig2.c",
"--name", "zig2",
"--dep", "build_options",
"--dep", "aro",
"-Mroot=src/main.zig",
"-Mbuild_options=config.zig",
"-Maro=lib/compiler/aro/aro.zig",
NULL,
});

{
const char *child_argv[] = {
"./zig1", "lib", "build-obj",
"-ofmt=c", "-OReleaseSmall",
"--name", "compiler_rt", "-femit-bin=compiler_rt.c",
"-target", host_triple,
"-Mroot=lib/compiler_rt.zig",
NULL,
};
print_and_run(child_argv);
}
print_and_run((const char *[]) {
"./zig1", "lib", "build-obj",
"-OReleaseSmall",
"-target", host_triple,
"-ofmt=c",
"-femit-bin=compiler_rt.c",
"--name", "compiler_rt",
"-Mroot=lib/compiler_rt.zig",
NULL,
});

{
const char *child_argv[] = {
cc, "-o", "zig2", "zig2.c", "compiler_rt.c",
"-std=c99", "-O2", "-fno-stack-protector",
"-Istage1",
print_and_run((const char *[]) {
cc,
#if defined(_MSC_VER)
"zig2.c",
"compiler_rt.c",
"/Istage1",
"/O2",
"/GS-",
"/Gs0x10000000",
"/link",
"/STACK:0x10000000,0x10000000",
"/OUT:zig2.exe",
#else
"zig2.c",
"compiler_rt.c",
"-Istage1",
"-std=c99",
#if defined(__GNUC__)
"-pthread",
#endif
"-O2",
"-fno-stack-protector",
#if defined(__APPLE__)
"-Wl,-stack_size,0x10000000",
"-Wl,-stack_size,0x10000000",
#else
"-Wl,-z,stack-size=0x10000000",
"-Wl,-z,stack-size=0x10000000",
#endif
#if defined(__GNUC__)
"-pthread",
"-o", "zig2",
#endif
NULL,
};
print_and_run(child_argv);
}
NULL,
});
}

0 comments on commit f1210a8

Please sign in to comment.