Commit 39c7bd24e4
Changed files (10)
src-self-hosted
src-self-hosted/llvm.zig
@@ -0,0 +1,13 @@
+const builtin = @import("builtin");
+const c = @import("c.zig");
+const assert = @import("std").debug.assert;
+
+pub const ValueRef = removeNullability(c.LLVMValueRef);
+pub const ModuleRef = removeNullability(c.LLVMModuleRef);
+pub const ContextRef = removeNullability(c.LLVMContextRef);
+pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
+
+fn removeNullability(comptime T: type) -> type {
+ comptime assert(@typeId(T) == builtin.TypeId.Nullable);
+ return T.Child;
+}
src-self-hosted/main.zig
@@ -4,71 +4,620 @@ const io = std.io;
const os = std.os;
const heap = std.heap;
const warn = std.debug.warn;
-const Tokenizer = @import("tokenizer.zig").Tokenizer;
-const Token = @import("tokenizer.zig").Token;
-const Parser = @import("parser.zig").Parser;
const assert = std.debug.assert;
const target = @import("target.zig");
+const Target = target.Target;
+const Module = @import("module.zig").Module;
+const ErrColor = Module.ErrColor;
+const Emit = Module.Emit;
+const builtin = @import("builtin");
+const ArrayList = std.ArrayList;
+
+error InvalidCommandLineArguments;
+error ZigLibDirNotFound;
+error ZigInstallationNotFound;
+
+const default_zig_cache_name = "zig-cache";
pub fn main() -> %void {
main2() %% |err| {
- warn("{}\n", @errorName(err));
+ if (err != error.InvalidCommandLineArguments) {
+ warn("{}\n", @errorName(err));
+ }
return err;
};
}
-pub fn main2() -> %void {
- var incrementing_allocator = %return heap.IncrementingAllocator.init(10 * 1024 * 1024);
- defer incrementing_allocator.deinit();
+const Cmd = enum {
+ None,
+ Build,
+ Test,
+ Version,
+ Zen,
+ TranslateC,
+ Targets,
+};
- const allocator = &incrementing_allocator.allocator;
+fn badArgs(comptime format: []const u8, args: ...) -> error {
+ var stderr = %return io.getStdErr();
+ var stderr_stream_adapter = io.FileOutStream.init(&stderr);
+ const stderr_stream = &stderr_stream_adapter.stream;
+ %return stderr_stream.print(format ++ "\n\n", args);
+ %return printUsage(&stderr_stream_adapter.stream);
+ return error.InvalidCommandLineArguments;
+}
+
+pub fn main2() -> %void {
+ const allocator = std.heap.c_allocator;
const args = %return os.argsAlloc(allocator);
defer os.argsFree(allocator, args);
- target.initializeAll();
+ var cmd = Cmd.None;
+ var build_kind: Module.Kind = undefined;
+ var build_mode: builtin.Mode = builtin.Mode.Debug;
+ var color = ErrColor.Auto;
+ var emit_file_type = Emit.Binary;
+
+ var strip = false;
+ var is_static = false;
+ var verbose_tokenize = false;
+ var verbose_ast_tree = false;
+ var verbose_ast_fmt = false;
+ var verbose_link = false;
+ var verbose_ir = false;
+ var verbose_llvm_ir = false;
+ var verbose_cimport = false;
+ var mwindows = false;
+ var mconsole = false;
+ var rdynamic = false;
+ var each_lib_rpath = false;
+ var timing_info = false;
+
+ var in_file_arg: ?[]u8 = null;
+ var out_file: ?[]u8 = null;
+ var out_file_h: ?[]u8 = null;
+ var out_name_arg: ?[]u8 = null;
+ var libc_lib_dir_arg: ?[]u8 = null;
+ var libc_static_lib_dir_arg: ?[]u8 = null;
+ var libc_include_dir_arg: ?[]u8 = null;
+ var msvc_lib_dir_arg: ?[]u8 = null;
+ var kernel32_lib_dir_arg: ?[]u8 = null;
+ var zig_install_prefix: ?[]u8 = null;
+ var dynamic_linker_arg: ?[]u8 = null;
+ var cache_dir_arg: ?[]const u8 = null;
+ var target_arch: ?[]u8 = null;
+ var target_os: ?[]u8 = null;
+ var target_environ: ?[]u8 = null;
+ var mmacosx_version_min: ?[]u8 = null;
+ var mios_version_min: ?[]u8 = null;
+ var linker_script_arg: ?[]u8 = null;
+ var test_name_prefix_arg: ?[]u8 = null;
+
+ var test_filters = ArrayList([]const u8).init(allocator);
+ defer test_filters.deinit();
+
+ var lib_dirs = ArrayList([]const u8).init(allocator);
+ defer lib_dirs.deinit();
+
+ var clang_argv = ArrayList([]const u8).init(allocator);
+ defer clang_argv.deinit();
+
+ var llvm_argv = ArrayList([]const u8).init(allocator);
+ defer llvm_argv.deinit();
+
+ var link_libs = ArrayList([]const u8).init(allocator);
+ defer link_libs.deinit();
+
+ var frameworks = ArrayList([]const u8).init(allocator);
+ defer frameworks.deinit();
+
+ var objects = ArrayList([]const u8).init(allocator);
+ defer objects.deinit();
- const target_file = args[1];
+ var asm_files = ArrayList([]const u8).init(allocator);
+ defer asm_files.deinit();
- const target_file_buf = %return io.readFileAlloc(target_file, allocator);
- defer allocator.free(target_file_buf);
+ var rpath_list = ArrayList([]const u8).init(allocator);
+ defer rpath_list.deinit();
- var stderr_file = %return std.io.getStdErr();
- var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
- const out_stream = &stderr_file_out_stream.stream;
+ var ver_major: u32 = 0;
+ var ver_minor: u32 = 0;
+ var ver_patch: u32 = 0;
- warn("====input:====\n");
+ var arg_i: usize = 1;
+ while (arg_i < args.len) : (arg_i += 1) {
+ const arg = args[arg_i];
- warn("{}", target_file_buf);
+ if (arg.len != 0 and arg[0] == '-') {
+ if (mem.eql(u8, arg, "--release-fast")) {
+ build_mode = builtin.Mode.ReleaseFast;
+ } else if (mem.eql(u8, arg, "--release-safe")) {
+ build_mode = builtin.Mode.ReleaseSafe;
+ } else if (mem.eql(u8, arg, "--strip")) {
+ strip = true;
+ } else if (mem.eql(u8, arg, "--static")) {
+ is_static = true;
+ } else if (mem.eql(u8, arg, "--verbose-tokenize")) {
+ verbose_tokenize = true;
+ } else if (mem.eql(u8, arg, "--verbose-ast-tree")) {
+ verbose_ast_tree = true;
+ } else if (mem.eql(u8, arg, "--verbose-ast-fmt")) {
+ verbose_ast_fmt = true;
+ } else if (mem.eql(u8, arg, "--verbose-link")) {
+ verbose_link = true;
+ } else if (mem.eql(u8, arg, "--verbose-ir")) {
+ verbose_ir = true;
+ } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
+ verbose_llvm_ir = true;
+ } else if (mem.eql(u8, arg, "--verbose-cimport")) {
+ verbose_cimport = true;
+ } else if (mem.eql(u8, arg, "-mwindows")) {
+ mwindows = true;
+ } else if (mem.eql(u8, arg, "-mconsole")) {
+ mconsole = true;
+ } else if (mem.eql(u8, arg, "-rdynamic")) {
+ rdynamic = true;
+ } else if (mem.eql(u8, arg, "--each-lib-rpath")) {
+ each_lib_rpath = true;
+ } else if (mem.eql(u8, arg, "--enable-timing-info")) {
+ timing_info = true;
+ } else if (mem.eql(u8, arg, "--test-cmd-bin")) {
+ @panic("TODO --test-cmd-bin");
+ } else if (arg[1] == 'L' and arg.len > 2) {
+ // alias for --library-path
+ %return lib_dirs.append(arg[1..]);
+ } else if (mem.eql(u8, arg, "--pkg-begin")) {
+ @panic("TODO --pkg-begin");
+ } else if (mem.eql(u8, arg, "--pkg-end")) {
+ @panic("TODO --pkg-end");
+ } else if (arg_i + 1 >= args.len) {
+ return badArgs("expected another argument after {}", arg);
+ } else {
+ arg_i += 1;
+ if (mem.eql(u8, arg, "--output")) {
+ out_file = args[arg_i];
+ } else if (mem.eql(u8, arg, "--output-h")) {
+ out_file_h = args[arg_i];
+ } else if (mem.eql(u8, arg, "--color")) {
+ if (mem.eql(u8, args[arg_i], "auto")) {
+ color = ErrColor.Auto;
+ } else if (mem.eql(u8, args[arg_i], "on")) {
+ color = ErrColor.On;
+ } else if (mem.eql(u8, args[arg_i], "off")) {
+ color = ErrColor.Off;
+ } else {
+ return badArgs("--color options are 'auto', 'on', or 'off'");
+ }
+ } else if (mem.eql(u8, arg, "--emit")) {
+ if (mem.eql(u8, args[arg_i], "asm")) {
+ emit_file_type = Emit.Assembly;
+ } else if (mem.eql(u8, args[arg_i], "bin")) {
+ emit_file_type = Emit.Binary;
+ } else if (mem.eql(u8, args[arg_i], "llvm-ir")) {
+ emit_file_type = Emit.LlvmIr;
+ } else {
+ return badArgs("--emit options are 'asm', 'bin', or 'llvm-ir'");
+ }
+ } else if (mem.eql(u8, arg, "--name")) {
+ out_name_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "--libc-lib-dir")) {
+ libc_lib_dir_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "--libc-static-lib-dir")) {
+ libc_static_lib_dir_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "--libc-include-dir")) {
+ libc_include_dir_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "--msvc-lib-dir")) {
+ msvc_lib_dir_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "--kernel32-lib-dir")) {
+ kernel32_lib_dir_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "--zig-install-prefix")) {
+ zig_install_prefix = args[arg_i];
+ } else if (mem.eql(u8, arg, "--dynamic-linker")) {
+ dynamic_linker_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "-isystem")) {
+ %return clang_argv.append("-isystem");
+ %return clang_argv.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "-dirafter")) {
+ %return clang_argv.append("-dirafter");
+ %return clang_argv.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "-mllvm")) {
+ %return clang_argv.append("-mllvm");
+ %return clang_argv.append(args[arg_i]);
- warn("====tokenization:====\n");
- {
- var tokenizer = Tokenizer.init(target_file_buf);
- while (true) {
- const token = tokenizer.next();
- tokenizer.dump(token);
- if (token.id == Token.Id.Eof) {
- break;
+ %return llvm_argv.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "--library-path") or mem.eql(u8, arg, "-L")) {
+ %return lib_dirs.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "--library")) {
+ %return link_libs.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "--object")) {
+ %return objects.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "--assembly")) {
+ %return asm_files.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "--cache-dir")) {
+ cache_dir_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "--target-arch")) {
+ target_arch = args[arg_i];
+ } else if (mem.eql(u8, arg, "--target-os")) {
+ target_os = args[arg_i];
+ } else if (mem.eql(u8, arg, "--target-environ")) {
+ target_environ = args[arg_i];
+ } else if (mem.eql(u8, arg, "-mmacosx-version-min")) {
+ mmacosx_version_min = args[arg_i];
+ } else if (mem.eql(u8, arg, "-mios-version-min")) {
+ mios_version_min = args[arg_i];
+ } else if (mem.eql(u8, arg, "-framework")) {
+ %return frameworks.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "--linker-script")) {
+ linker_script_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "-rpath")) {
+ %return rpath_list.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "--test-filter")) {
+ %return test_filters.append(args[arg_i]);
+ } else if (mem.eql(u8, arg, "--test-name-prefix")) {
+ test_name_prefix_arg = args[arg_i];
+ } else if (mem.eql(u8, arg, "--ver-major")) {
+ ver_major = %return std.fmt.parseUnsigned(u32, args[arg_i], 10);
+ } else if (mem.eql(u8, arg, "--ver-minor")) {
+ ver_minor = %return std.fmt.parseUnsigned(u32, args[arg_i], 10);
+ } else if (mem.eql(u8, arg, "--ver-patch")) {
+ ver_patch = %return std.fmt.parseUnsigned(u32, args[arg_i], 10);
+ } else if (mem.eql(u8, arg, "--test-cmd")) {
+ @panic("TODO --test-cmd");
+ } else {
+ return badArgs("invalid argument: {}", arg);
+ }
}
+ } else if (cmd == Cmd.None) {
+ if (mem.eql(u8, arg, "build-obj")) {
+ cmd = Cmd.Build;
+ build_kind = Module.Kind.Obj;
+ } else if (mem.eql(u8, arg, "build-exe")) {
+ cmd = Cmd.Build;
+ build_kind = Module.Kind.Exe;
+ } else if (mem.eql(u8, arg, "build-lib")) {
+ cmd = Cmd.Build;
+ build_kind = Module.Kind.Lib;
+ } else if (mem.eql(u8, arg, "version")) {
+ cmd = Cmd.Version;
+ } else if (mem.eql(u8, arg, "zen")) {
+ cmd = Cmd.Zen;
+ } else if (mem.eql(u8, arg, "translate-c")) {
+ cmd = Cmd.TranslateC;
+ } else if (mem.eql(u8, arg, "test")) {
+ cmd = Cmd.Test;
+ build_kind = Module.Kind.Exe;
+ } else {
+ return badArgs("unrecognized command: {}", arg);
+ }
+ } else switch (cmd) {
+ Cmd.Build, Cmd.TranslateC, Cmd.Test => {
+ if (in_file_arg == null) {
+ in_file_arg = arg;
+ } else {
+ return badArgs("unexpected extra parameter: {}", arg);
+ }
+ },
+ Cmd.Version, Cmd.Zen, Cmd.Targets => {
+ return badArgs("unexpected extra parameter: {}", arg);
+ },
+ Cmd.None => unreachable,
}
}
- warn("====parse:====\n");
+ target.initializeAll();
+
+ // TODO
+// ZigTarget alloc_target;
+// ZigTarget *target;
+// if (!target_arch && !target_os && !target_environ) {
+// target = nullptr;
+// } else {
+// target = &alloc_target;
+// get_unknown_target(target);
+// if (target_arch) {
+// if (parse_target_arch(target_arch, &target->arch)) {
+// fprintf(stderr, "invalid --target-arch argument\n");
+// return usage(arg0);
+// }
+// }
+// if (target_os) {
+// if (parse_target_os(target_os, &target->os)) {
+// fprintf(stderr, "invalid --target-os argument\n");
+// return usage(arg0);
+// }
+// }
+// if (target_environ) {
+// if (parse_target_environ(target_environ, &target->env_type)) {
+// fprintf(stderr, "invalid --target-environ argument\n");
+// return usage(arg0);
+// }
+// }
+// }
+
+ switch (cmd) {
+ Cmd.None => return badArgs("expected command"),
+ Cmd.Zen => return printZen(),
+ Cmd.Build, Cmd.Test, Cmd.TranslateC => {
+ if (cmd == Cmd.Build and in_file_arg == null and objects.len == 0 and asm_files.len == 0) {
+ return badArgs("expected source file argument or at least one --object or --assembly argument");
+ } else if ((cmd == Cmd.TranslateC or cmd == Cmd.Test) and in_file_arg == null) {
+ return badArgs("expected source file argument");
+ } else if (cmd == Cmd.Build and build_kind == Module.Kind.Obj and objects.len != 0) {
+ return badArgs("When building an object file, --object arguments are invalid");
+ }
+
+ const root_name = switch (cmd) {
+ Cmd.Build, Cmd.TranslateC => x: {
+ if (out_name_arg) |out_name| {
+ break :x out_name;
+ } else if (in_file_arg) |in_file_path| {
+ const basename = os.path.basename(in_file_path);
+ var it = mem.split(basename, ".");
+ break :x it.next() ?? return badArgs("file name cannot be empty");
+ } else {
+ return badArgs("--name [name] not provided and unable to infer");
+ }
+ },
+ Cmd.Test => "test",
+ else => unreachable,
+ };
+
+ const zig_root_source_file = if (cmd == Cmd.TranslateC) null else in_file_arg;
+
+ const chosen_cache_dir = cache_dir_arg ?? default_zig_cache_name;
+ const full_cache_dir = %return os.path.resolve(allocator, ".", chosen_cache_dir);
+ defer allocator.free(full_cache_dir);
+
+ const zig_lib_dir = %return resolveZigLibDir(allocator, zig_install_prefix);
+ %defer allocator.free(zig_lib_dir);
+
+ const module = %return Module.create(allocator, root_name, zig_root_source_file,
+ Target.Native, build_kind, build_mode, zig_lib_dir, full_cache_dir);
+ defer module.destroy();
+
+ module.version_major = ver_major;
+ module.version_minor = ver_minor;
+ module.version_patch = ver_patch;
+
+ module.is_test = cmd == Cmd.Test;
+ if (linker_script_arg) |linker_script| {
+ module.linker_script = linker_script;
+ }
+ module.each_lib_rpath = each_lib_rpath;
+ module.clang_argv = clang_argv.toSliceConst();
+ module.llvm_argv = llvm_argv.toSliceConst();
+ module.strip = strip;
+ module.is_static = is_static;
+
+ if (libc_lib_dir_arg) |libc_lib_dir| {
+ module.libc_lib_dir = libc_lib_dir;
+ }
+ if (libc_static_lib_dir_arg) |libc_static_lib_dir| {
+ module.libc_static_lib_dir = libc_static_lib_dir;
+ }
+ if (libc_include_dir_arg) |libc_include_dir| {
+ module.libc_include_dir = libc_include_dir;
+ }
+ if (msvc_lib_dir_arg) |msvc_lib_dir| {
+ module.msvc_lib_dir = msvc_lib_dir;
+ }
+ if (kernel32_lib_dir_arg) |kernel32_lib_dir| {
+ module.kernel32_lib_dir = kernel32_lib_dir;
+ }
+ if (dynamic_linker_arg) |dynamic_linker| {
+ module.dynamic_linker = dynamic_linker;
+ }
+ module.verbose_tokenize = verbose_tokenize;
+ module.verbose_ast_tree = verbose_ast_tree;
+ module.verbose_ast_fmt = verbose_ast_fmt;
+ module.verbose_link = verbose_link;
+ module.verbose_ir = verbose_ir;
+ module.verbose_llvm_ir = verbose_llvm_ir;
+ module.verbose_cimport = verbose_cimport;
+
+ module.err_color = color;
+
+ module.lib_dirs = lib_dirs.toSliceConst();
+ module.darwin_frameworks = frameworks.toSliceConst();
+ module.rpath_list = rpath_list.toSliceConst();
+
+ for (link_libs.toSliceConst()) |name| {
+ _ = %return module.addLinkLib(name, true);
+ }
+
+ module.windows_subsystem_windows = mwindows;
+ module.windows_subsystem_console = mconsole;
+ module.linker_rdynamic = rdynamic;
+
+ if (mmacosx_version_min != null and mios_version_min != null) {
+ return badArgs("-mmacosx-version-min and -mios-version-min options not allowed together");
+ }
+
+ if (mmacosx_version_min) |ver| {
+ module.darwin_version_min = Module.DarwinVersionMin { .MacOS = ver };
+ } else if (mios_version_min) |ver| {
+ module.darwin_version_min = Module.DarwinVersionMin { .Ios = ver };
+ }
+
+ module.test_filters = test_filters.toSliceConst();
+ module.test_name_prefix = test_name_prefix_arg;
+ module.out_h_path = out_file_h;
+
+ // TODO
+ //add_package(g, cur_pkg, g->root_package);
+
+ switch (cmd) {
+ Cmd.Build => {
+ module.emit_file_type = emit_file_type;
+
+ module.link_objects = objects.toSliceConst();
+ module.assembly_files = asm_files.toSliceConst();
+
+ %return module.build();
+ %return module.link(out_file);
+ },
+ Cmd.TranslateC => @panic("TODO translate-c"),
+ Cmd.Test => @panic("TODO test cmd"),
+ else => unreachable,
+ }
+ },
+ Cmd.Version => @panic("TODO zig version"),
+ Cmd.Targets => @panic("TODO zig targets"),
+ }
+}
+
+fn printUsage(stream: &io.OutStream) -> %void {
+ %return stream.write(
+ \\Usage: zig [command] [options]
+ \\
+ \\Commands:
+ \\ build build project from build.zig
+ \\ build-exe [source] create executable from source or object files
+ \\ build-lib [source] create library from source or object files
+ \\ build-obj [source] create object from source or assembly
+ \\ translate-c [source] convert c code to zig code
+ \\ targets list available compilation targets
+ \\ test [source] create and run a test build
+ \\ version print version number and exit
+ \\ zen print zen of zig and exit
+ \\Compile Options:
+ \\ --assembly [source] add assembly file to build
+ \\ --cache-dir [path] override the cache directory
+ \\ --color [auto|off|on] enable or disable colored error messages
+ \\ --emit [filetype] emit a specific file format as compilation output
+ \\ --enable-timing-info print timing diagnostics
+ \\ --libc-include-dir [path] directory where libc stdlib.h resides
+ \\ --name [name] override output name
+ \\ --output [file] override destination path
+ \\ --output-h [file] override generated header file path
+ \\ --pkg-begin [name] [path] make package available to import and push current pkg
+ \\ --pkg-end pop current pkg
+ \\ --release-fast build with optimizations on and safety off
+ \\ --release-safe build with optimizations on and safety on
+ \\ --static output will be statically linked
+ \\ --strip exclude debug symbols
+ \\ --target-arch [name] specify target architecture
+ \\ --target-environ [name] specify target environment
+ \\ --target-os [name] specify target operating system
+ \\ --verbose-tokenize enable compiler debug info: tokenization
+ \\ --verbose-ast-tree enable compiler debug info: parsing into an AST (treeview)
+ \\ --verbose-ast-fmt enable compiler debug info: parsing into an AST (render source)
+ \\ --verbose-cimport enable compiler debug info: C imports
+ \\ --verbose-ir enable compiler debug info: Zig IR
+ \\ --verbose-llvm-ir enable compiler debug info: LLVM IR
+ \\ --verbose-link enable compiler debug info: linking
+ \\ --zig-install-prefix [path] override directory where zig thinks it is installed
+ \\ -dirafter [dir] same as -isystem but do it last
+ \\ -isystem [dir] add additional search path for other .h files
+ \\ -mllvm [arg] additional arguments to forward to LLVM's option processing
+ \\Link Options:
+ \\ --ar-path [path] set the path to ar
+ \\ --dynamic-linker [path] set the path to ld.so
+ \\ --each-lib-rpath add rpath for each used dynamic library
+ \\ --libc-lib-dir [path] directory where libc crt1.o resides
+ \\ --libc-static-lib-dir [path] directory where libc crtbegin.o resides
+ \\ --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides
+ \\ --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides
+ \\ --library [lib] link against lib
+ \\ --library-path [dir] add a directory to the library search path
+ \\ --linker-script [path] use a custom linker script
+ \\ --object [obj] add object file to build
+ \\ -L[dir] alias for --library-path
+ \\ -rdynamic add all symbols to the dynamic symbol table
+ \\ -rpath [path] add directory to the runtime library search path
+ \\ -mconsole (windows) --subsystem console to the linker
+ \\ -mwindows (windows) --subsystem windows to the linker
+ \\ -framework [name] (darwin) link against framework
+ \\ -mios-version-min [ver] (darwin) set iOS deployment target
+ \\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target
+ \\ --ver-major [ver] dynamic library semver major version
+ \\ --ver-minor [ver] dynamic library semver minor version
+ \\ --ver-patch [ver] dynamic library semver patch version
+ \\Test Options:
+ \\ --test-filter [text] skip tests that do not match filter
+ \\ --test-name-prefix [text] add prefix to all tests
+ \\ --test-cmd [arg] specify test execution command one arg at a time
+ \\ --test-cmd-bin appends test binary path to test cmd args
+ \\
+ );
+}
- var tokenizer = Tokenizer.init(target_file_buf);
- var parser = Parser.init(&tokenizer, allocator, target_file);
- defer parser.deinit();
+fn printZen() -> %void {
+ var stdout_file = %return io.getStdErr();
+ %return stdout_file.write(
+ \\
+ \\ * Communicate intent precisely.
+ \\ * Edge cases matter.
+ \\ * Favor reading code over writing code.
+ \\ * Only one obvious way to do things.
+ \\ * Runtime crashes are better than bugs.
+ \\ * Compile errors are better than runtime crashes.
+ \\ * Incremental improvements.
+ \\ * Avoid local maximums.
+ \\ * Reduce the amount one must remember.
+ \\ * Minimize energy spent on coding style.
+ \\ * Together we serve end users.
+ \\
+ \\
+ );
+}
+
+/// Caller must free result
+fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) -> %[]u8 {
+ if (zig_install_prefix_arg) |zig_install_prefix| {
+ return testZigInstallPrefix(allocator, zig_install_prefix) %% |err| {
+ warn("No Zig installation found at prefix {}: {}\n", zig_install_prefix_arg, @errorName(err));
+ return error.ZigInstallationNotFound;
+ };
+ } else {
+ return findZigLibDir(allocator) %% |err| {
+ warn("Unable to find zig lib directory: {}.\nReinstall Zig or use --zig-install-prefix.\n",
+ @errorName(err));
+ return error.ZigLibDirNotFound;
+ };
+ }
+}
- const root_node = %return parser.parse();
- defer parser.freeAst(root_node);
+/// Caller must free result
+fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[]u8 {
+ const test_zig_dir = %return os.path.join(allocator, test_path, "lib", "zig");
+ %defer allocator.free(test_zig_dir);
- %return parser.renderAst(out_stream, root_node);
+ const test_index_file = %return os.path.join(allocator, test_zig_dir, "std", "index.zig");
+ defer allocator.free(test_index_file);
- warn("====fmt:====\n");
- %return parser.renderSource(out_stream, root_node);
+ var file = %return io.File.openRead(test_index_file, allocator);
+ file.close();
+
+ return test_zig_dir;
}
-test "import other tests" {
- _ = @import("parser.zig");
- _ = @import("tokenizer.zig");
+/// Caller must free result
+fn findZigLibDir(allocator: &mem.Allocator) -> %[]u8 {
+ const self_exe_path = %return os.selfExeDirPath(allocator);
+ defer allocator.free(self_exe_path);
+
+ var cur_path: []const u8 = self_exe_path;
+ while (true) {
+ const test_dir = os.path.dirname(cur_path);
+
+ if (mem.eql(u8, test_dir, cur_path)) {
+ break;
+ }
+
+ return testZigInstallPrefix(allocator, test_dir) %% |err| {
+ cur_path = test_dir;
+ continue;
+ };
+ }
+
+ // TODO look in hard coded installation path from configuration
+ //if (ZIG_INSTALL_PREFIX != nullptr) {
+ // if (test_zig_install_prefix(buf_create_from_str(ZIG_INSTALL_PREFIX), out_path)) {
+ // return 0;
+ // }
+ //}
+
+ return error.FileNotFound;
}
src-self-hosted/module.zig
@@ -0,0 +1,295 @@
+const std = @import("std");
+const os = std.os;
+const io = std.io;
+const mem = std.mem;
+const Buffer = std.Buffer;
+const llvm = @import("llvm.zig");
+const c = @import("c.zig");
+const builtin = @import("builtin");
+const Target = @import("target.zig").Target;
+const warn = std.debug.warn;
+const Tokenizer = @import("tokenizer.zig").Tokenizer;
+const Token = @import("tokenizer.zig").Token;
+const Parser = @import("parser.zig").Parser;
+const ArrayList = std.ArrayList;
+
+pub const Module = struct {
+ allocator: &mem.Allocator,
+ name: Buffer,
+ root_src_path: ?[]const u8,
+ module: llvm.ModuleRef,
+ context: llvm.ContextRef,
+ builder: llvm.BuilderRef,
+ target: Target,
+ build_mode: builtin.Mode,
+ zig_lib_dir: []const u8,
+
+ version_major: u32,
+ version_minor: u32,
+ version_patch: u32,
+
+ linker_script: ?[]const u8,
+ cache_dir: []const u8,
+ libc_lib_dir: ?[]const u8,
+ libc_static_lib_dir: ?[]const u8,
+ libc_include_dir: ?[]const u8,
+ msvc_lib_dir: ?[]const u8,
+ kernel32_lib_dir: ?[]const u8,
+ dynamic_linker: ?[]const u8,
+ out_h_path: ?[]const u8,
+
+ is_test: bool,
+ each_lib_rpath: bool,
+ strip: bool,
+ is_static: bool,
+ linker_rdynamic: bool,
+
+ clang_argv: []const []const u8,
+ llvm_argv: []const []const u8,
+ lib_dirs: []const []const u8,
+ rpath_list: []const []const u8,
+ assembly_files: []const []const u8,
+ link_objects: []const []const u8,
+
+ windows_subsystem_windows: bool,
+ windows_subsystem_console: bool,
+
+ link_libs_list: ArrayList(&LinkLib),
+ libc_link_lib: ?&LinkLib,
+
+ err_color: ErrColor,
+
+ verbose_tokenize: bool,
+ verbose_ast_tree: bool,
+ verbose_ast_fmt: bool,
+ verbose_cimport: bool,
+ verbose_ir: bool,
+ verbose_llvm_ir: bool,
+ verbose_link: bool,
+
+ darwin_frameworks: []const []const u8,
+ darwin_version_min: DarwinVersionMin,
+
+ test_filters: []const []const u8,
+ test_name_prefix: ?[]const u8,
+
+ emit_file_type: Emit,
+
+ kind: Kind,
+
+ pub const DarwinVersionMin = union(enum) {
+ None,
+ MacOS: []const u8,
+ Ios: []const u8,
+ };
+
+ pub const Kind = enum {
+ Exe,
+ Lib,
+ Obj,
+ };
+
+ pub const ErrColor = enum {
+ Auto,
+ Off,
+ On,
+ };
+
+ pub const LinkLib = struct {
+ name: []const u8,
+ path: ?[]const u8,
+ /// the list of symbols we depend on from this lib
+ symbols: ArrayList([]u8),
+ provided_explicitly: bool,
+ };
+
+ pub const Emit = enum {
+ Binary,
+ Assembly,
+ LlvmIr,
+ };
+
+ pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target,
+ kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) -> %&Module
+ {
+ var name_buffer = %return Buffer.init(allocator, name);
+ %defer name_buffer.deinit();
+
+ const context = c.LLVMContextCreate() ?? return error.OutOfMemory;
+ %defer c.LLVMContextDispose(context);
+
+ const module = c.LLVMModuleCreateWithNameInContext(name_buffer.ptr(), context) ?? return error.OutOfMemory;
+ %defer c.LLVMDisposeModule(module);
+
+ const builder = c.LLVMCreateBuilderInContext(context) ?? return error.OutOfMemory;
+ %defer c.LLVMDisposeBuilder(builder);
+
+ const module_ptr = %return allocator.create(Module);
+ %defer allocator.destroy(module_ptr);
+
+ *module_ptr = Module {
+ .allocator = allocator,
+ .name = name_buffer,
+ .root_src_path = root_src_path,
+ .module = module,
+ .context = context,
+ .builder = builder,
+ .target = *target,
+ .kind = kind,
+ .build_mode = build_mode,
+ .zig_lib_dir = zig_lib_dir,
+ .cache_dir = cache_dir,
+
+ .version_major = 0,
+ .version_minor = 0,
+ .version_patch = 0,
+
+ .verbose_tokenize = false,
+ .verbose_ast_tree = false,
+ .verbose_ast_fmt = false,
+ .verbose_cimport = false,
+ .verbose_ir = false,
+ .verbose_llvm_ir = false,
+ .verbose_link = false,
+
+ .linker_script = null,
+ .libc_lib_dir = null,
+ .libc_static_lib_dir = null,
+ .libc_include_dir = null,
+ .msvc_lib_dir = null,
+ .kernel32_lib_dir = null,
+ .dynamic_linker = null,
+ .out_h_path = null,
+ .is_test = false,
+ .each_lib_rpath = false,
+ .strip = false,
+ .is_static = false,
+ .linker_rdynamic = false,
+ .clang_argv = [][]const u8{},
+ .llvm_argv = [][]const u8{},
+ .lib_dirs = [][]const u8{},
+ .rpath_list = [][]const u8{},
+ .assembly_files = [][]const u8{},
+ .link_objects = [][]const u8{},
+ .windows_subsystem_windows = false,
+ .windows_subsystem_console = false,
+ .link_libs_list = ArrayList(&LinkLib).init(allocator),
+ .libc_link_lib = null,
+ .err_color = ErrColor.Auto,
+ .darwin_frameworks = [][]const u8{},
+ .darwin_version_min = DarwinVersionMin.None,
+ .test_filters = [][]const u8{},
+ .test_name_prefix = null,
+ .emit_file_type = Emit.Binary,
+ };
+ return module_ptr;
+ }
+
+ fn dump(self: &Module) {
+ c.LLVMDumpModule(self.module);
+ }
+
+ pub fn destroy(self: &Module) {
+ c.LLVMDisposeBuilder(self.builder);
+ c.LLVMDisposeModule(self.module);
+ c.LLVMContextDispose(self.context);
+ self.name.deinit();
+
+ self.allocator.destroy(self);
+ }
+
+ pub fn build(self: &Module) -> %void {
+ const root_src_path = self.root_src_path ?? @panic("TODO handle null root src path");
+ const root_src_real_path = os.path.real(self.allocator, root_src_path) %% |err| {
+ %return printError("unable to open '{}': {}", root_src_path, err);
+ return err;
+ };
+ %defer self.allocator.free(root_src_real_path);
+
+ const source_code = io.readFileAlloc(root_src_real_path, self.allocator) %% |err| {
+ %return printError("unable to open '{}': {}", root_src_real_path, err);
+ return err;
+ };
+ %defer self.allocator.free(source_code);
+
+ warn("====input:====\n");
+
+ warn("{}", source_code);
+
+ warn("====tokenization:====\n");
+ {
+ var tokenizer = Tokenizer.init(source_code);
+ while (true) {
+ const token = tokenizer.next();
+ tokenizer.dump(token);
+ if (token.id == Token.Id.Eof) {
+ break;
+ }
+ }
+ }
+
+ warn("====parse:====\n");
+
+ var tokenizer = Tokenizer.init(source_code);
+ var parser = Parser.init(&tokenizer, self.allocator, root_src_real_path);
+ defer parser.deinit();
+
+ const root_node = %return parser.parse();
+ defer parser.freeAst(root_node);
+
+ var stderr_file = %return std.io.getStdErr();
+ var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
+ const out_stream = &stderr_file_out_stream.stream;
+ %return parser.renderAst(out_stream, root_node);
+
+ warn("====fmt:====\n");
+ %return parser.renderSource(out_stream, root_node);
+
+ warn("====ir:====\n");
+ warn("TODO\n\n");
+
+ warn("====llvm ir:====\n");
+ self.dump();
+
+ }
+
+ pub fn link(self: &Module, out_file: ?[]const u8) -> %void {
+ warn("TODO link");
+ }
+
+ pub fn addLinkLib(self: &Module, name: []const u8, provided_explicitly: bool) -> %&LinkLib {
+ const is_libc = mem.eql(u8, name, "c");
+
+ if (is_libc) {
+ if (self.libc_link_lib) |libc_link_lib| {
+ return libc_link_lib;
+ }
+ }
+
+ for (self.link_libs_list.toSliceConst()) |existing_lib| {
+ if (mem.eql(u8, name, existing_lib.name)) {
+ return existing_lib;
+ }
+ }
+
+ const link_lib = %return self.allocator.create(LinkLib);
+ *link_lib = LinkLib {
+ .name = name,
+ .path = null,
+ .provided_explicitly = provided_explicitly,
+ .symbols = ArrayList([]u8).init(self.allocator),
+ };
+ %return self.link_libs_list.append(link_lib);
+ if (is_libc) {
+ self.libc_link_lib = link_lib;
+ }
+ return link_lib;
+ }
+};
+
+fn printError(comptime format: []const u8, args: ...) -> %void {
+ var stderr_file = %return std.io.getStdErr();
+ var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
+ const out_stream = &stderr_file_out_stream.stream;
+ %return out_stream.print(format, args);
+}
src-self-hosted/target.zig
@@ -1,5 +1,56 @@
+const builtin = @import("builtin");
const c = @import("c.zig");
+pub const CrossTarget = struct {
+ arch: builtin.Arch,
+ os: builtin.Os,
+ environ: builtin.Environ,
+};
+
+pub const Target = union(enum) {
+ Native,
+ Cross: CrossTarget,
+
+ pub fn oFileExt(self: &const Target) -> []const u8 {
+ const environ = switch (*self) {
+ Target.Native => builtin.environ,
+ Target.Cross => |t| t.environ,
+ };
+ return switch (environ) {
+ builtin.Environ.msvc => ".obj",
+ else => ".o",
+ };
+ }
+
+ pub fn exeFileExt(self: &const Target) -> []const u8 {
+ return switch (self.getOs()) {
+ builtin.Os.windows => ".exe",
+ else => "",
+ };
+ }
+
+ pub fn getOs(self: &const Target) -> builtin.Os {
+ return switch (*self) {
+ Target.Native => builtin.os,
+ Target.Cross => |t| t.os,
+ };
+ }
+
+ pub fn isDarwin(self: &const Target) -> bool {
+ return switch (self.getOs()) {
+ builtin.Os.darwin, builtin.Os.ios, builtin.Os.macosx => true,
+ else => false,
+ };
+ }
+
+ pub fn isWindows(self: &const Target) -> bool {
+ return switch (self.getOs()) {
+ builtin.Os.windows => true,
+ else => false,
+ };
+ }
+};
+
pub fn initializeAll() {
c.LLVMInitializeAllTargets();
c.LLVMInitializeAllTargetInfos();
std/c/index.zig
@@ -48,3 +48,4 @@ pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) -> c_int;
pub extern "c" fn malloc(usize) -> ?&c_void;
pub extern "c" fn realloc(&c_void, usize) -> ?&c_void;
pub extern "c" fn free(&c_void);
+pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) -> c_int;
std/os/index.zig
@@ -1543,6 +1543,39 @@ pub fn openSelfExe() -> %io.File {
}
}
+/// Get the directory path that contains the current executable.
+/// Caller owns returned memory.
+pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 {
+ switch (builtin.os) {
+ Os.linux => {
+ // If the currently executing binary has been deleted,
+ // the file path looks something like `/a/b/c/exe (deleted)`
+ // This path cannot be opened, but it's valid for determining the directory
+ // the executable was in when it was run.
+ const full_exe_path = %return readLink(allocator, "/proc/self/exe");
+ %defer allocator.free(full_exe_path);
+ const dir = path.dirname(full_exe_path);
+ return allocator.shrink(u8, full_exe_path, dir.len);
+ },
+ Os.windows => {
+ @panic("TODO windows std.os.selfExeDirPath");
+ //buf_resize(out_path, 256);
+ //for (;;) {
+ // DWORD copied_amt = GetModuleFileName(nullptr, buf_ptr(out_path), buf_len(out_path));
+ // if (copied_amt <= 0) {
+ // return ErrorFileNotFound;
+ // }
+ // if (copied_amt < buf_len(out_path)) {
+ // buf_resize(out_path, copied_amt);
+ // return 0;
+ // }
+ // buf_resize(out_path, buf_len(out_path) * 2);
+ //}
+ },
+ else => @compileError("unimplemented: std.os.selfExeDirPath for " ++ @tagName(builtin.os)),
+ }
+}
+
pub fn isTty(handle: FileHandle) -> bool {
if (is_windows) {
return windows_util.windowsIsTty(handle);
std/buffer.zig
@@ -139,6 +139,11 @@ pub const Buffer = struct {
%return self.resize(m.len);
mem.copy(u8, self.list.toSlice(), m);
}
+
+ /// For passing to C functions.
+ pub fn ptr(self: &const Buffer) -> &u8 {
+ return self.list.items.ptr;
+ }
};
test "simple Buffer" {
std/heap.zig
@@ -10,7 +10,8 @@ const Allocator = mem.Allocator;
error OutOfMemory;
-pub var c_allocator = Allocator {
+pub const c_allocator = &c_allocator_state;
+var c_allocator_state = Allocator {
.allocFn = cAlloc,
.reallocFn = cRealloc,
.freeFn = cFree,
@@ -24,15 +25,13 @@ fn cAlloc(self: &Allocator, n: usize, alignment: u29) -> %[]u8 {
}
fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 {
- if (new_size <= old_mem.len) {
+ const old_ptr = @ptrCast(&c_void, old_mem.ptr);
+ if (c.realloc(old_ptr, new_size)) |buf| {
+ return @ptrCast(&u8, buf)[0..new_size];
+ } else if (new_size <= old_mem.len) {
return old_mem[0..new_size];
} else {
- const old_ptr = @ptrCast(&c_void, old_mem.ptr);
- if (c.realloc(old_ptr, usize(new_size))) |buf| {
- return @ptrCast(&u8, buf)[0..new_size];
- } else {
- return error.OutOfMemory;
- }
+ return error.OutOfMemory;
}
}
build.zig
@@ -32,15 +32,18 @@ pub fn build(b: &Builder) {
docs_step.dependOn(&docgen_cmd.step);
docs_step.dependOn(&docgen_home_cmd.step);
- var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
- exe.setBuildMode(mode);
- exe.linkSystemLibrary("c");
- dependOnLib(exe, findLLVM(b));
+ if (findLLVM(b)) |llvm| {
+ var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
+ exe.setBuildMode(mode);
+ exe.linkSystemLibrary("c");
+ dependOnLib(exe, llvm);
- b.default_step.dependOn(&exe.step);
- b.default_step.dependOn(docs_step);
+ b.default_step.dependOn(&exe.step);
+ b.default_step.dependOn(docs_step);
- b.installArtifact(exe);
+ b.installArtifact(exe);
+ installStdLib(b);
+ }
const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
@@ -91,7 +94,7 @@ const LibraryDep = struct {
includes: ArrayList([]const u8),
};
-fn findLLVM(b: &Builder) -> LibraryDep {
+fn findLLVM(b: &Builder) -> ?LibraryDep {
const llvm_config_exe = b.findProgram(
[][]const u8{"llvm-config-5.0", "llvm-config"},
[][]const u8{
@@ -102,7 +105,8 @@ fn findLLVM(b: &Builder) -> LibraryDep {
"C:/Libraries/llvm-5.0.0/bin",
}) %% |err|
{
- std.debug.panic("unable to find llvm-config: {}\n", err);
+ warn("unable to find llvm-config: {}\n", err);
+ return null;
};
const libs_output = b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
const includes_output = b.exec([][]const u8{llvm_config_exe, "--includedir"});
@@ -143,3 +147,126 @@ fn findLLVM(b: &Builder) -> LibraryDep {
}
return result;
}
+
+pub fn installStdLib(b: &Builder) {
+ const stdlib_files = []const []const u8 {
+ "array_list.zig",
+ "base64.zig",
+ "buf_map.zig",
+ "buf_set.zig",
+ "buffer.zig",
+ "build.zig",
+ "c/darwin.zig",
+ "c/index.zig",
+ "c/linux.zig",
+ "c/windows.zig",
+ "cstr.zig",
+ "debug.zig",
+ "dwarf.zig",
+ "elf.zig",
+ "empty.zig",
+ "endian.zig",
+ "fmt/errol/enum3.zig",
+ "fmt/errol/index.zig",
+ "fmt/errol/lookup.zig",
+ "fmt/index.zig",
+ "hash_map.zig",
+ "heap.zig",
+ "index.zig",
+ "io.zig",
+ "linked_list.zig",
+ "math/acos.zig",
+ "math/acosh.zig",
+ "math/asin.zig",
+ "math/asinh.zig",
+ "math/atan.zig",
+ "math/atan2.zig",
+ "math/atanh.zig",
+ "math/cbrt.zig",
+ "math/ceil.zig",
+ "math/copysign.zig",
+ "math/cos.zig",
+ "math/cosh.zig",
+ "math/exp.zig",
+ "math/exp2.zig",
+ "math/expm1.zig",
+ "math/expo2.zig",
+ "math/fabs.zig",
+ "math/floor.zig",
+ "math/fma.zig",
+ "math/frexp.zig",
+ "math/hypot.zig",
+ "math/ilogb.zig",
+ "math/index.zig",
+ "math/inf.zig",
+ "math/isfinite.zig",
+ "math/isinf.zig",
+ "math/isnan.zig",
+ "math/isnormal.zig",
+ "math/ln.zig",
+ "math/log.zig",
+ "math/log10.zig",
+ "math/log1p.zig",
+ "math/log2.zig",
+ "math/modf.zig",
+ "math/nan.zig",
+ "math/pow.zig",
+ "math/round.zig",
+ "math/scalbn.zig",
+ "math/signbit.zig",
+ "math/sin.zig",
+ "math/sinh.zig",
+ "math/sqrt.zig",
+ "math/tan.zig",
+ "math/tanh.zig",
+ "math/trunc.zig",
+ "mem.zig",
+ "net.zig",
+ "os/child_process.zig",
+ "os/darwin.zig",
+ "os/darwin_errno.zig",
+ "os/get_user_id.zig",
+ "os/index.zig",
+ "os/linux.zig",
+ "os/linux_errno.zig",
+ "os/linux_i386.zig",
+ "os/linux_x86_64.zig",
+ "os/path.zig",
+ "os/windows/error.zig",
+ "os/windows/index.zig",
+ "os/windows/util.zig",
+ "rand.zig",
+ "sort.zig",
+ "special/bootstrap.zig",
+ "special/bootstrap_lib.zig",
+ "special/build_file_template.zig",
+ "special/build_runner.zig",
+ "special/builtin.zig",
+ "special/compiler_rt/aulldiv.zig",
+ "special/compiler_rt/aullrem.zig",
+ "special/compiler_rt/comparetf2.zig",
+ "special/compiler_rt/fixuint.zig",
+ "special/compiler_rt/fixunsdfdi.zig",
+ "special/compiler_rt/fixunsdfsi.zig",
+ "special/compiler_rt/fixunsdfti.zig",
+ "special/compiler_rt/fixunssfdi.zig",
+ "special/compiler_rt/fixunssfsi.zig",
+ "special/compiler_rt/fixunssfti.zig",
+ "special/compiler_rt/fixunstfdi.zig",
+ "special/compiler_rt/fixunstfsi.zig",
+ "special/compiler_rt/fixunstfti.zig",
+ "special/compiler_rt/index.zig",
+ "special/compiler_rt/udivmod.zig",
+ "special/compiler_rt/udivmoddi4.zig",
+ "special/compiler_rt/udivmodti4.zig",
+ "special/compiler_rt/udivti3.zig",
+ "special/compiler_rt/umodti3.zig",
+ "special/panic.zig",
+ "special/test_runner.zig",
+ };
+ for (stdlib_files) |stdlib_file| {
+ const src_path = %%os.path.join(b.allocator, "std", stdlib_file);
+ const dest_path = %%os.path.join(b.allocator, "lib", "zig", "std", stdlib_file);
+ b.installFile(src_path, dest_path);
+ }
+}
README.md
@@ -119,31 +119,22 @@ libc. Create demo games using Zig.
[](https://travis-ci.org/zig-lang/zig)
[](https://ci.appveyor.com/project/andrewrk/zig-d3l86/branch/master)
-### Dependencies
+### Stage 1: Build Zig from C++ Source Code
-#### Build Dependencies
-
-These compile tools must be available on your system and are used to build
-the Zig compiler itself:
+#### Dependencies
##### POSIX
* gcc >= 5.0.0 or clang >= 3.6.0
* cmake >= 2.8.5
+ * LLVM, Clang, LLD libraries == 5.x, compiled with the same gcc or clang version above
##### Windows
* Microsoft Visual Studio 2015
+ * LLVM, Clang, LLD libraries == 5.x, compiled with the same MSVC version above
-#### Library Dependencies
-
-These libraries must be installed on your system, with the development files
-available. The Zig compiler links against them. You have to use the same
-compiler for these libraries as you do to compile Zig.
-
- * LLVM, Clang, and LLD libraries == 5.x
-
-### Debug / Development Build
+#### Instructions
If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR`,
`ZIG_LIBC_STATIC_LIB_DIR`, and `ZIG_LIBC_INCLUDE_DIR` should be set to
@@ -158,7 +149,7 @@ make install
./zig build --build-file ../build.zig test
```
-#### MacOS
+##### MacOS
`ZIG_LIBC_LIB_DIR` and `ZIG_LIBC_STATIC_LIB_DIR` are unused.
@@ -172,21 +163,35 @@ make install
./zig build --build-file ../build.zig test
```
-#### Windows
+##### Windows
See https://github.com/zig-lang/zig/wiki/Building-Zig-on-Windows
-### Release / Install Build
+### Stage 2: Build Self-Hosted Zig from Zig Source Code
-Once installed, `ZIG_LIBC_LIB_DIR` and `ZIG_LIBC_INCLUDE_DIR` can be overridden
-by the `--libc-lib-dir` and `--libc-include-dir` parameters to the zig binary.
+*Note: Stage 2 compiler is not complete. Beta users of Zig should use the
+Stage 1 compiler for now.*
+
+Dependencies are the same as Stage 1, except now you have a working zig compiler.
```
-mkdir build
-cd build
-cmake .. -DCMAKE_BUILD_TYPE=Release -DZIG_LIBC_LIB_DIR=/some/path -DZIG_LIBC_INCLUDE_DIR=/some/path -DZIG_LIBC_STATIC_INCLUDE_DIR=/some/path
-make
-sudo make install
+bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
+```
+
+### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler
+
+This is the actual compiler binary that we will install to the system.
+
+#### Debug / Development Build
+
+```
+./stage2/bin/zig build --build-file ../build.zig --prefix $(pwd)/stage3 install
+```
+
+#### Release / Install Build
+
+```
+./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast
```
### Test Coverage