diff --git a/README.md b/README.md index 8fb01b711c..8eaeab7b95 100644 --- a/README.md +++ b/README.md @@ -64,8 +64,40 @@ For more options, tips, and troubleshooting, please see the [Building Zig From Source](https://github.com/ziglang/zig/wiki/Building-Zig-From-Source) page on the wiki. +## Building from Source without LLVM + +In this case, the only system dependency is a C compiler. + +``` +cc -o bootstrap bootstrap.c +./bootstrap build +``` + +You can pass any options to this that you would pass to `zig build` (see +`--help` for options). + +[Without LLVM extensions](https://github.com/ziglang/zig/issues/16270), a Zig +compiler is missing these features: +- Release mode optimizations +- aarch64 machine code backend +- `@cImport` / `zig translate-c` +- Ability to compile C files +- Ability to compile assembly files +- [Some ELF linking features](https://github.com/ziglang/zig/issues/17749) +- [Most COFF/PE linking features](https://github.com/ziglang/zig/issues/17751) +- [Some WebAssembly linking features](https://github.com/ziglang/zig/issues/17750) +- [COFF linking](https://github.com/ziglang/zig/issues/17751) +- [Ability to output LLVM bitcode](https://github.com/ziglang/zig/issues/13265) +- [Windows resource file compilation](https://github.com/ziglang/zig/issues/17752) +- [Ability to create import libs from def files](https://github.com/ziglang/zig/issues/17807) +- [Automatic importlib file generation for Windows DLLs](https://github.com/ziglang/zig/issues/17753) +- [Ability to create static archives from object files](https://github.com/ziglang/zig/issues/9828) +- Ability to compile C++, Objective-C, and Objective-C++ files + ## Contributing +[Donate monthly](https://ziglang.org/zsf/). + Zig is Free and Open Source Software. We welcome bug reports and patches from everyone. However, keep in mind that Zig governance is BDFN (Benevolent Dictator For Now) which means that Andrew Kelley has final say on the design diff --git a/bootstrap.c b/bootstrap.c new file mode 100644 index 0000000000..35ad33d266 --- /dev/null +++ b/bootstrap.c @@ -0,0 +1,194 @@ +#include +#include +#include +#include + +static const char *get_c_compiler(void) { + const char *cc = getenv("CC"); + return (cc == NULL) ? "cc" : cc; +} + +static void panic(const char *reason) { + fprintf(stderr, "%s\n", reason); + abort(); +} + +#if defined(__WIN32__) +#error TODO write the functionality for executing child process into this build script +#else + +#include +#include +#include + +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); + } + + // parent + + int status; + waitpid(pid, &status, 0); + + if (!WIFEXITED(status)) + panic("child process crashed"); + + if (WEXITSTATUS(status) != 0) + panic("child process failed"); +} + +static void run_execv(char **argv) { + if (execv(argv[0], argv) == -1 && errno == ENOENT) return; + perror("execv failed"); +} +#endif + +static void print_and_run(const char **argv) { + fprintf(stderr, "%s", argv[0]); + for (const char **arg = argv + 1; *arg; arg += 1) { + fprintf(stderr, " %s", *arg); + } + fprintf(stderr, "\n"); + run((char **)argv); +} + +static const char *get_host_os(void) { +#if defined(__WIN32__) + return "windows"; +#elif defined(__APPLE__) + return "macos"; +#elif defined(__linux__) + return "linux"; +#else +#error TODO implement get_host_os in this build script for this target +#endif +} + +static const char *get_host_arch(void) { +#if defined(__x86_64__ ) + return "x86_64"; +#elif defined(__aarch64__) + return "aarch64"; +#else +#error TODO implement get_host_arch in this build script for this target +#endif +} + +static const char *get_host_triple(void) { + static char global_buffer[100]; + sprintf(global_buffer, "%s-%s", get_host_arch(), get_host_os()); + return global_buffer; +} + +int main(int argc, char **argv) { + argv[0] = "./zig2"; + run_execv(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); + } + { + FILE *f = fopen("config.zig", "wb"); + if (f == NULL) + panic("unable to open config.zig for writing"); + + const char *zig_version = "0.12.0-dev.bootstrap"; + + int written = fprintf(f, + "pub const have_llvm = false;\n" + "pub const llvm_has_m68k = false;\n" + "pub const llvm_has_csky = false;\n" + "pub const llvm_has_arc = false;\n" + "pub const llvm_has_xtensa = false;\n" + "pub const version: [:0]const u8 = \"%s\";\n" + "pub const semver = @import(\"std\").SemanticVersion.parse(version) catch unreachable;\n" + "pub const enable_logging: bool = false;\n" + "pub const enable_link_snapshots: bool = false;\n" + "pub const enable_tracy = false;\n" + "pub const value_tracing = false;\n" + "pub const skip_non_native = false;\n" + "pub const only_c = false;\n" + "pub const force_gpa = false;\n" + "pub const only_core_functionality = true;\n" + "pub const only_reduce = false;\n" + , zig_version); + if (written < 100) + panic("unable to write to config.zig file"); + if (fclose(f) != 0) + panic("unable to finish writing to config.zig file"); + } + + { + const char *child_argv[] = { + "./zig1", "lib", "build-exe", "src/main.zig", + "-ofmt=c", "-lc", "-OReleaseSmall", + "--name", "zig2", "-femit-bin=zig2.c", + "--mod", "build_options::config.zig", + "--mod", "Builtins/Builtin.def::src/stubs/aro_builtins.zig", + "--mod", "Attribute/names.def::src/stubs/aro_names.zig", + "--mod", "aro:Builtins/Builtin.def,Attribute/names.def:deps/aro/lib.zig", + "--deps", "build_options,aro", + "-target", host_triple, + NULL, + }; + print_and_run(child_argv); + } + + { + const char *child_argv[] = { + "./zig1", "lib", "build-obj", "lib/compiler_rt.zig", + "-ofmt=c", "-OReleaseSmall", + "--name", "compiler_rt", "-femit-bin=compiler_rt.c", + "--mod", "build_options::config.zig", + "--deps", "build_options", + "-target", host_triple, + NULL, + }; + print_and_run(child_argv); + } + + { + const char *child_argv[] = { + cc, "-o", "zig2", "zig2.c", "compiler_rt.c", + "-std=c99", "-O2", "-fno-stack-protector", + "-Istage1", +#if defined(__APPLE__) + "-Wl,-stack_size,0x10000000", +#else + "-Wl,-z,stack-size=0x10000000", +#endif +#if defined(__GNUC__) + "-pthread", +#endif + NULL, + }; + print_and_run(child_argv); + } + + run_execv(argv); + panic("build script failed to create valid zig2 executable"); +} diff --git a/ci/x86_64-linux-debug.sh b/ci/x86_64-linux-debug.sh index 69cd569879..bbab0c564d 100755 --- a/ci/x86_64-linux-debug.sh +++ b/ci/x86_64-linux-debug.sh @@ -20,6 +20,14 @@ git config core.abbrev 9 git fetch --unshallow || true git fetch --tags +# Test building from source without LLVM. +git clean -fd +rm -rf zig-out +cc -o bootstrap bootstrap.c +./bootstrap build -Dno-lib +# In order to run these behavior tests we need to move the `@cImport` ones to somewhere else. +# ./zig-out/bin/zig test test/behavior.zig + export CC="$ZIG cc -target $TARGET -mcpu=$MCPU" export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU" diff --git a/ci/x86_64-linux-release.sh b/ci/x86_64-linux-release.sh index 421fb89ba7..61320ce0f9 100755 --- a/ci/x86_64-linux-release.sh +++ b/ci/x86_64-linux-release.sh @@ -20,6 +20,14 @@ git config core.abbrev 9 git fetch --unshallow || true git fetch --tags +# Test building from source without LLVM. +git clean -fd +rm -rf zig-out +cc -o bootstrap bootstrap.c +./bootstrap build -Dno-lib +# In order to run these behavior tests we need to move the `@cImport` ones to somewhere else. +# ./zig-out/bin/zig test test/behavior.zig + export CC="$ZIG cc -target $TARGET -mcpu=$MCPU" export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU" diff --git a/lib/zig.h b/lib/zig.h index 233c2961cb..acd7b1d700 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -61,6 +61,12 @@ typedef char bool; #define zig_gnuc #endif +#if defined(zig_gnuc) && (defined(__i386__) || defined(__x86_64__)) +#define zig_f128_has_miscompilations 1 +#else +#define zig_f128_has_miscompilations 0 +#endif + #if _MSC_VER #define zig_const_arr #define zig_callconv(c) __##c @@ -3155,22 +3161,22 @@ typedef zig_u128 zig_f80; #define zig_has_f128 1 #define zig_libc_name_f128(name) name##q #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) -#if FLT_MANT_DIG == 113 +#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f -#elif DBL_MANT_DIG == 113 +#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 typedef double zig_f128; #define zig_make_f128(fp, repr) fp -#elif LDBL_MANT_DIG == 113 +#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113 typedef long double zig_f128; #define zig_make_f128(fp, repr) fp##l -#elif FLT128_MANT_DIG == 113 +#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113 typedef _Float128 zig_f128; #define zig_make_f128(fp, repr) fp##f128 -#elif FLT64X_MANT_DIG == 113 +#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113 typedef _Float64x zig_f128; #define zig_make_f128(fp, repr) fp##f64x -#elif defined(__SIZEOF_FLOAT128__) +#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__) typedef __float128 zig_f128; #define zig_make_f128(fp, repr) fp##q #undef zig_make_special_f128 diff --git a/stage1/zig.h b/stage1/zig.h index 233c2961cb..acd7b1d700 100644 --- a/stage1/zig.h +++ b/stage1/zig.h @@ -61,6 +61,12 @@ typedef char bool; #define zig_gnuc #endif +#if defined(zig_gnuc) && (defined(__i386__) || defined(__x86_64__)) +#define zig_f128_has_miscompilations 1 +#else +#define zig_f128_has_miscompilations 0 +#endif + #if _MSC_VER #define zig_const_arr #define zig_callconv(c) __##c @@ -3155,22 +3161,22 @@ typedef zig_u128 zig_f80; #define zig_has_f128 1 #define zig_libc_name_f128(name) name##q #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) -#if FLT_MANT_DIG == 113 +#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f -#elif DBL_MANT_DIG == 113 +#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 typedef double zig_f128; #define zig_make_f128(fp, repr) fp -#elif LDBL_MANT_DIG == 113 +#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113 typedef long double zig_f128; #define zig_make_f128(fp, repr) fp##l -#elif FLT128_MANT_DIG == 113 +#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113 typedef _Float128 zig_f128; #define zig_make_f128(fp, repr) fp##f128 -#elif FLT64X_MANT_DIG == 113 +#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113 typedef _Float64x zig_f128; #define zig_make_f128(fp, repr) fp##f64x -#elif defined(__SIZEOF_FLOAT128__) +#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__) typedef __float128 zig_f128; #define zig_make_f128(fp, repr) fp##q #undef zig_make_special_f128