| author | |
| committer | |
| log | 39c7bd24e4f768b23074b8634ac637b175b7639f |
| tree | e3454d346c9d37abb9bb56847d3743eeb6cfa4e8 |
| parent | 760b307e8a8fcbb31fc1f2abb170ef7399aa917e |
10 files changed, 1156 insertions(+), 78 deletions(-)
README.md+29-24| ... | @@ -119,31 +119,22 @@ libc. Create demo games using Zig. | ... | @@ -119,31 +119,22 @@ libc. Create demo games using Zig. |
| 119 | [](https://travis-ci.org/zig-lang/zig) | 119 | [](https://travis-ci.org/zig-lang/zig) |
| 120 | [](https://ci.appveyor.com/project/andrewrk/zig-d3l86/branch/master) | 120 | [](https://ci.appveyor.com/project/andrewrk/zig-d3l86/branch/master) |
| 121 | 121 | ||
| 122 | ### Dependencies | 122 | ### Stage 1: Build Zig from C++ Source Code |
| 123 | 123 | ||
| 124 | #### Build Dependencies | 124 | #### Dependencies |
| 125 | |||
| 126 | These compile tools must be available on your system and are used to build | ||
| 127 | the Zig compiler itself: | ||
| 128 | 125 | ||
| 129 | ##### POSIX | 126 | ##### POSIX |
| 130 | 127 | ||
| 131 | * gcc >= 5.0.0 or clang >= 3.6.0 | 128 | * gcc >= 5.0.0 or clang >= 3.6.0 |
| 132 | * cmake >= 2.8.5 | 129 | * cmake >= 2.8.5 |
| 130 | * LLVM, Clang, LLD libraries == 5.x, compiled with the same gcc or clang version above | ||
| 133 | 131 | ||
| 134 | ##### Windows | 132 | ##### Windows |
| 135 | 133 | ||
| 136 | * Microsoft Visual Studio 2015 | 134 | * Microsoft Visual Studio 2015 |
| 135 | * LLVM, Clang, LLD libraries == 5.x, compiled with the same MSVC version above | ||
| 137 | 136 | ||
| 138 | #### Library Dependencies | 137 | #### Instructions |
| 139 | |||
| 140 | These libraries must be installed on your system, with the development files | ||
| 141 | available. The Zig compiler links against them. You have to use the same | ||
| 142 | compiler for these libraries as you do to compile Zig. | ||
| 143 | |||
| 144 | * LLVM, Clang, and LLD libraries == 5.x | ||
| 145 | |||
| 146 | ### Debug / Development Build | ||
| 147 | 138 | ||
| 148 | If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR`, | 139 | If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR`, |
| 149 | `ZIG_LIBC_STATIC_LIB_DIR`, and `ZIG_LIBC_INCLUDE_DIR` should be set to | 140 | `ZIG_LIBC_STATIC_LIB_DIR`, and `ZIG_LIBC_INCLUDE_DIR` should be set to |
| ... | @@ -158,7 +149,7 @@ make install | ... | @@ -158,7 +149,7 @@ make install |
| 158 | ./zig build --build-file ../build.zig test | 149 | ./zig build --build-file ../build.zig test |
| 159 | ``` | 150 | ``` |
| 160 | 151 | ||
| 161 | #### MacOS | 152 | ##### MacOS |
| 162 | 153 | ||
| 163 | `ZIG_LIBC_LIB_DIR` and `ZIG_LIBC_STATIC_LIB_DIR` are unused. | 154 | `ZIG_LIBC_LIB_DIR` and `ZIG_LIBC_STATIC_LIB_DIR` are unused. |
| 164 | 155 | ||
| ... | @@ -172,21 +163,35 @@ make install | ... | @@ -172,21 +163,35 @@ make install |
| 172 | ./zig build --build-file ../build.zig test | 163 | ./zig build --build-file ../build.zig test |
| 173 | ``` | 164 | ``` |
| 174 | 165 | ||
| 175 | #### Windows | 166 | ##### Windows |
| 176 | 167 | ||
| 177 | See https://github.com/zig-lang/zig/wiki/Building-Zig-on-Windows | 168 | See https://github.com/zig-lang/zig/wiki/Building-Zig-on-Windows |
| 178 | 169 | ||
| 179 | ### Release / Install Build | 170 | ### Stage 2: Build Self-Hosted Zig from Zig Source Code |
| 180 | 171 | ||
| 181 | Once installed, `ZIG_LIBC_LIB_DIR` and `ZIG_LIBC_INCLUDE_DIR` can be overridden | 172 | *Note: Stage 2 compiler is not complete. Beta users of Zig should use the |
| 182 | by the `--libc-lib-dir` and `--libc-include-dir` parameters to the zig binary. | 173 | Stage 1 compiler for now.* |
| 174 | |||
| 175 | Dependencies are the same as Stage 1, except now you have a working zig compiler. | ||
| 183 | 176 | ||
| 184 | ``` | 177 | ``` |
| 185 | mkdir build | 178 | bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install |
| 186 | cd build | 179 | ``` |
| 187 | cmake .. -DCMAKE_BUILD_TYPE=Release -DZIG_LIBC_LIB_DIR=/some/path -DZIG_LIBC_INCLUDE_DIR=/some/path -DZIG_LIBC_STATIC_INCLUDE_DIR=/some/path | 180 | |
| 188 | make | 181 | ### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler |
| 189 | sudo make install | 182 | |
| 183 | This is the actual compiler binary that we will install to the system. | ||
| 184 | |||
| 185 | #### Debug / Development Build | ||
| 186 | |||
| 187 | ``` | ||
| 188 | ./stage2/bin/zig build --build-file ../build.zig --prefix $(pwd)/stage3 install | ||
| 189 | ``` | ||
| 190 | |||
| 191 | #### Release / Install Build | ||
| 192 | |||
| 193 | ``` | ||
| 194 | ./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast | ||
| 190 | ``` | 195 | ``` |
| 191 | 196 | ||
| 192 | ### Test Coverage | 197 | ### Test Coverage |
build.zig+136-9| ... | @@ -32,15 +32,18 @@ pub fn build(b: &Builder) { | ... | @@ -32,15 +32,18 @@ pub fn build(b: &Builder) { |
| 32 | docs_step.dependOn(&docgen_cmd.step); | 32 | docs_step.dependOn(&docgen_cmd.step); |
| 33 | docs_step.dependOn(&docgen_home_cmd.step); | 33 | docs_step.dependOn(&docgen_home_cmd.step); |
| 34 | 34 | ||
| 35 | var exe = b.addExecutable("zig", "src-self-hosted/main.zig"); | 35 | if (findLLVM(b)) |llvm| { |
| 36 | exe.setBuildMode(mode); | 36 | var exe = b.addExecutable("zig", "src-self-hosted/main.zig"); |
| 37 | exe.linkSystemLibrary("c"); | 37 | exe.setBuildMode(mode); |
| 38 | dependOnLib(exe, findLLVM(b)); | 38 | exe.linkSystemLibrary("c"); |
| 39 | dependOnLib(exe, llvm); | ||
| 39 | 40 | ||
| 40 | b.default_step.dependOn(&exe.step); | 41 | b.default_step.dependOn(&exe.step); |
| 41 | b.default_step.dependOn(docs_step); | 42 | b.default_step.dependOn(docs_step); |
| 42 | 43 | ||
| 43 | b.installArtifact(exe); | 44 | b.installArtifact(exe); |
| 45 | installStdLib(b); | ||
| 46 | } | ||
| 44 | 47 | ||
| 45 | 48 | ||
| 46 | const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter"); | 49 | const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter"); |
| ... | @@ -91,7 +94,7 @@ const LibraryDep = struct { | ... | @@ -91,7 +94,7 @@ const LibraryDep = struct { |
| 91 | includes: ArrayList([]const u8), | 94 | includes: ArrayList([]const u8), |
| 92 | }; | 95 | }; |
| 93 | 96 | ||
| 94 | fn findLLVM(b: &Builder) -> LibraryDep { | 97 | fn findLLVM(b: &Builder) -> ?LibraryDep { |
| 95 | const llvm_config_exe = b.findProgram( | 98 | const llvm_config_exe = b.findProgram( |
| 96 | [][]const u8{"llvm-config-5.0", "llvm-config"}, | 99 | [][]const u8{"llvm-config-5.0", "llvm-config"}, |
| 97 | [][]const u8{ | 100 | [][]const u8{ |
| ... | @@ -102,7 +105,8 @@ fn findLLVM(b: &Builder) -> LibraryDep { | ... | @@ -102,7 +105,8 @@ fn findLLVM(b: &Builder) -> LibraryDep { |
| 102 | "C:/Libraries/llvm-5.0.0/bin", | 105 | "C:/Libraries/llvm-5.0.0/bin", |
| 103 | }) %% |err| | 106 | }) %% |err| |
| 104 | { | 107 | { |
| 105 | std.debug.panic("unable to find llvm-config: {}\n", err); | 108 | warn("unable to find llvm-config: {}\n", err); |
| 109 | return null; | ||
| 106 | }; | 110 | }; |
| 107 | const libs_output = b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"}); | 111 | const libs_output = b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"}); |
| 108 | const includes_output = b.exec([][]const u8{llvm_config_exe, "--includedir"}); | 112 | const includes_output = b.exec([][]const u8{llvm_config_exe, "--includedir"}); |
| ... | @@ -143,3 +147,126 @@ fn findLLVM(b: &Builder) -> LibraryDep { | ... | @@ -143,3 +147,126 @@ fn findLLVM(b: &Builder) -> LibraryDep { |
| 143 | } | 147 | } |
| 144 | return result; | 148 | return result; |
| 145 | } | 149 | } |
| 150 | |||
| 151 | pub fn installStdLib(b: &Builder) { | ||
| 152 | const stdlib_files = []const []const u8 { | ||
| 153 | "array_list.zig", | ||
| 154 | "base64.zig", | ||
| 155 | "buf_map.zig", | ||
| 156 | "buf_set.zig", | ||
| 157 | "buffer.zig", | ||
| 158 | "build.zig", | ||
| 159 | "c/darwin.zig", | ||
| 160 | "c/index.zig", | ||
| 161 | "c/linux.zig", | ||
| 162 | "c/windows.zig", | ||
| 163 | "cstr.zig", | ||
| 164 | "debug.zig", | ||
| 165 | "dwarf.zig", | ||
| 166 | "elf.zig", | ||
| 167 | "empty.zig", | ||
| 168 | "endian.zig", | ||
| 169 | "fmt/errol/enum3.zig", | ||
| 170 | "fmt/errol/index.zig", | ||
| 171 | "fmt/errol/lookup.zig", | ||
| 172 | "fmt/index.zig", | ||
| 173 | "hash_map.zig", | ||
| 174 | "heap.zig", | ||
| 175 | "index.zig", | ||
| 176 | "io.zig", | ||
| 177 | "linked_list.zig", | ||
| 178 | "math/acos.zig", | ||
| 179 | "math/acosh.zig", | ||
| 180 | "math/asin.zig", | ||
| 181 | "math/asinh.zig", | ||
| 182 | "math/atan.zig", | ||
| 183 | "math/atan2.zig", | ||
| 184 | "math/atanh.zig", | ||
| 185 | "math/cbrt.zig", | ||
| 186 | "math/ceil.zig", | ||
| 187 | "math/copysign.zig", | ||
| 188 | "math/cos.zig", | ||
| 189 | "math/cosh.zig", | ||
| 190 | "math/exp.zig", | ||
| 191 | "math/exp2.zig", | ||
| 192 | "math/expm1.zig", | ||
| 193 | "math/expo2.zig", | ||
| 194 | "math/fabs.zig", | ||
| 195 | "math/floor.zig", | ||
| 196 | "math/fma.zig", | ||
| 197 | "math/frexp.zig", | ||
| 198 | "math/hypot.zig", | ||
| 199 | "math/ilogb.zig", | ||
| 200 | "math/index.zig", | ||
| 201 | "math/inf.zig", | ||
| 202 | "math/isfinite.zig", | ||
| 203 | "math/isinf.zig", | ||
| 204 | "math/isnan.zig", | ||
| 205 | "math/isnormal.zig", | ||
| 206 | "math/ln.zig", | ||
| 207 | "math/log.zig", | ||
| 208 | "math/log10.zig", | ||
| 209 | "math/log1p.zig", | ||
| 210 | "math/log2.zig", | ||
| 211 | "math/modf.zig", | ||
| 212 | "math/nan.zig", | ||
| 213 | "math/pow.zig", | ||
| 214 | "math/round.zig", | ||
| 215 | "math/scalbn.zig", | ||
| 216 | "math/signbit.zig", | ||
| 217 | "math/sin.zig", | ||
| 218 | "math/sinh.zig", | ||
| 219 | "math/sqrt.zig", | ||
| 220 | "math/tan.zig", | ||
| 221 | "math/tanh.zig", | ||
| 222 | "math/trunc.zig", | ||
| 223 | "mem.zig", | ||
| 224 | "net.zig", | ||
| 225 | "os/child_process.zig", | ||
| 226 | "os/darwin.zig", | ||
| 227 | "os/darwin_errno.zig", | ||
| 228 | "os/get_user_id.zig", | ||
| 229 | "os/index.zig", | ||
| 230 | "os/linux.zig", | ||
| 231 | "os/linux_errno.zig", | ||
| 232 | "os/linux_i386.zig", | ||
| 233 | "os/linux_x86_64.zig", | ||
| 234 | "os/path.zig", | ||
| 235 | "os/windows/error.zig", | ||
| 236 | "os/windows/index.zig", | ||
| 237 | "os/windows/util.zig", | ||
| 238 | "rand.zig", | ||
| 239 | "sort.zig", | ||
| 240 | "special/bootstrap.zig", | ||
| 241 | "special/bootstrap_lib.zig", | ||
| 242 | "special/build_file_template.zig", | ||
| 243 | "special/build_runner.zig", | ||
| 244 | "special/builtin.zig", | ||
| 245 | "special/compiler_rt/aulldiv.zig", | ||
| 246 | "special/compiler_rt/aullrem.zig", | ||
| 247 | "special/compiler_rt/comparetf2.zig", | ||
| 248 | "special/compiler_rt/fixuint.zig", | ||
| 249 | "special/compiler_rt/fixunsdfdi.zig", | ||
| 250 | "special/compiler_rt/fixunsdfsi.zig", | ||
| 251 | "special/compiler_rt/fixunsdfti.zig", | ||
| 252 | "special/compiler_rt/fixunssfdi.zig", | ||
| 253 | "special/compiler_rt/fixunssfsi.zig", | ||
| 254 | "special/compiler_rt/fixunssfti.zig", | ||
| 255 | "special/compiler_rt/fixunstfdi.zig", | ||
| 256 | "special/compiler_rt/fixunstfsi.zig", | ||
| 257 | "special/compiler_rt/fixunstfti.zig", | ||
| 258 | "special/compiler_rt/index.zig", | ||
| 259 | "special/compiler_rt/udivmod.zig", | ||
| 260 | "special/compiler_rt/udivmoddi4.zig", | ||
| 261 | "special/compiler_rt/udivmodti4.zig", | ||
| 262 | "special/compiler_rt/udivti3.zig", | ||
| 263 | "special/compiler_rt/umodti3.zig", | ||
| 264 | "special/panic.zig", | ||
| 265 | "special/test_runner.zig", | ||
| 266 | }; | ||
| 267 | for (stdlib_files) |stdlib_file| { | ||
| 268 | const src_path = %%os.path.join(b.allocator, "std", stdlib_file); | ||
| 269 | const dest_path = %%os.path.join(b.allocator, "lib", "zig", "std", stdlib_file); | ||
| 270 | b.installFile(src_path, dest_path); | ||
| 271 | } | ||
| 272 | } |
src-self-hosted/llvm.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const c = @import("c.zig"); | ||
| 3 | const assert = @import("std").debug.assert; | ||
| 4 | |||
| 5 | pub const ValueRef = removeNullability(c.LLVMValueRef); | ||
| 6 | pub const ModuleRef = removeNullability(c.LLVMModuleRef); | ||
| 7 | pub const ContextRef = removeNullability(c.LLVMContextRef); | ||
| 8 | pub const BuilderRef = removeNullability(c.LLVMBuilderRef); | ||
| 9 | |||
| 10 | fn removeNullability(comptime T: type) -> type { | ||
| 11 | comptime assert(@typeId(T) == builtin.TypeId.Nullable); | ||
| 12 | return T.Child; | ||
| 13 | } | ||
src-self-hosted/main.zig+586-37| ... | @@ -4,71 +4,620 @@ const io = std.io; | ... | @@ -4,71 +4,620 @@ const io = std.io; |
| 4 | const os = std.os; | 4 | const os = std.os; |
| 5 | const heap = std.heap; | 5 | const heap = std.heap; |
| 6 | const warn = std.debug.warn; | 6 | const warn = std.debug.warn; |
| 7 | const Tokenizer = @import("tokenizer.zig").Tokenizer; | ||
| 8 | const Token = @import("tokenizer.zig").Token; | ||
| 9 | const Parser = @import("parser.zig").Parser; | ||
| 10 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 11 | const target = @import("target.zig"); | 8 | const target = @import("target.zig"); |
| 9 | const Target = target.Target; | ||
| 10 | const Module = @import("module.zig").Module; | ||
| 11 | const ErrColor = Module.ErrColor; | ||
| 12 | const Emit = Module.Emit; | ||
| 13 | const builtin = @import("builtin"); | ||
| 14 | const ArrayList = std.ArrayList; | ||
| 15 | |||
| 16 | error InvalidCommandLineArguments; | ||
| 17 | error ZigLibDirNotFound; | ||
| 18 | error ZigInstallationNotFound; | ||
| 19 | |||
| 20 | const default_zig_cache_name = "zig-cache"; | ||
| 12 | 21 | ||
| 13 | pub fn main() -> %void { | 22 | pub fn main() -> %void { |
| 14 | main2() %% |err| { | 23 | main2() %% |err| { |
| 15 | warn("{}\n", @errorName(err)); | 24 | if (err != error.InvalidCommandLineArguments) { |
| 25 | warn("{}\n", @errorName(err)); | ||
| 26 | } | ||
| 16 | return err; | 27 | return err; |
| 17 | }; | 28 | }; |
| 18 | } | 29 | } |
| 19 | 30 | ||
| 20 | pub fn main2() -> %void { | 31 | const Cmd = enum { |
| 21 | var incrementing_allocator = %return heap.IncrementingAllocator.init(10 * 1024 * 1024); | 32 | None, |
| 22 | defer incrementing_allocator.deinit(); | 33 | Build, |
| 34 | Test, | ||
| 35 | Version, | ||
| 36 | Zen, | ||
| 37 | TranslateC, | ||
| 38 | Targets, | ||
| 39 | }; | ||
| 23 | 40 | ||
| 24 | const allocator = &incrementing_allocator.allocator; | 41 | fn badArgs(comptime format: []const u8, args: ...) -> error { |
| 42 | var stderr = %return io.getStdErr(); | ||
| 43 | var stderr_stream_adapter = io.FileOutStream.init(&stderr); | ||
| 44 | const stderr_stream = &stderr_stream_adapter.stream; | ||
| 45 | %return stderr_stream.print(format ++ "\n\n", args); | ||
| 46 | %return printUsage(&stderr_stream_adapter.stream); | ||
| 47 | return error.InvalidCommandLineArguments; | ||
| 48 | } | ||
| 49 | |||
| 50 | pub fn main2() -> %void { | ||
| 51 | const allocator = std.heap.c_allocator; | ||
| 25 | 52 | ||
| 26 | const args = %return os.argsAlloc(allocator); | 53 | const args = %return os.argsAlloc(allocator); |
| 27 | defer os.argsFree(allocator, args); | 54 | defer os.argsFree(allocator, args); |
| 28 | 55 | ||
| 29 | target.initializeAll(); | 56 | var cmd = Cmd.None; |
| 57 | var build_kind: Module.Kind = undefined; | ||
| 58 | var build_mode: builtin.Mode = builtin.Mode.Debug; | ||
| 59 | var color = ErrColor.Auto; | ||
| 60 | var emit_file_type = Emit.Binary; | ||
| 61 | |||
| 62 | var strip = false; | ||
| 63 | var is_static = false; | ||
| 64 | var verbose_tokenize = false; | ||
| 65 | var verbose_ast_tree = false; | ||
| 66 | var verbose_ast_fmt = false; | ||
| 67 | var verbose_link = false; | ||
| 68 | var verbose_ir = false; | ||
| 69 | var verbose_llvm_ir = false; | ||
| 70 | var verbose_cimport = false; | ||
| 71 | var mwindows = false; | ||
| 72 | var mconsole = false; | ||
| 73 | var rdynamic = false; | ||
| 74 | var each_lib_rpath = false; | ||
| 75 | var timing_info = false; | ||
| 76 | |||
| 77 | var in_file_arg: ?[]u8 = null; | ||
| 78 | var out_file: ?[]u8 = null; | ||
| 79 | var out_file_h: ?[]u8 = null; | ||
| 80 | var out_name_arg: ?[]u8 = null; | ||
| 81 | var libc_lib_dir_arg: ?[]u8 = null; | ||
| 82 | var libc_static_lib_dir_arg: ?[]u8 = null; | ||
| 83 | var libc_include_dir_arg: ?[]u8 = null; | ||
| 84 | var msvc_lib_dir_arg: ?[]u8 = null; | ||
| 85 | var kernel32_lib_dir_arg: ?[]u8 = null; | ||
| 86 | var zig_install_prefix: ?[]u8 = null; | ||
| 87 | var dynamic_linker_arg: ?[]u8 = null; | ||
| 88 | var cache_dir_arg: ?[]const u8 = null; | ||
| 89 | var target_arch: ?[]u8 = null; | ||
| 90 | var target_os: ?[]u8 = null; | ||
| 91 | var target_environ: ?[]u8 = null; | ||
| 92 | var mmacosx_version_min: ?[]u8 = null; | ||
| 93 | var mios_version_min: ?[]u8 = null; | ||
| 94 | var linker_script_arg: ?[]u8 = null; | ||
| 95 | var test_name_prefix_arg: ?[]u8 = null; | ||
| 96 | |||
| 97 | var test_filters = ArrayList([]const u8).init(allocator); | ||
| 98 | defer test_filters.deinit(); | ||
| 99 | |||
| 100 | var lib_dirs = ArrayList([]const u8).init(allocator); | ||
| 101 | defer lib_dirs.deinit(); | ||
| 102 | |||
| 103 | var clang_argv = ArrayList([]const u8).init(allocator); | ||
| 104 | defer clang_argv.deinit(); | ||
| 105 | |||
| 106 | var llvm_argv = ArrayList([]const u8).init(allocator); | ||
| 107 | defer llvm_argv.deinit(); | ||
| 108 | |||
| 109 | var link_libs = ArrayList([]const u8).init(allocator); | ||
| 110 | defer link_libs.deinit(); | ||
| 111 | |||
| 112 | var frameworks = ArrayList([]const u8).init(allocator); | ||
| 113 | defer frameworks.deinit(); | ||
| 114 | |||
| 115 | var objects = ArrayList([]const u8).init(allocator); | ||
| 116 | defer objects.deinit(); | ||
| 30 | 117 | ||
| 31 | const target_file = args[1]; | 118 | var asm_files = ArrayList([]const u8).init(allocator); |
| 119 | defer asm_files.deinit(); | ||
| 32 | 120 | ||
| 33 | const target_file_buf = %return io.readFileAlloc(target_file, allocator); | 121 | var rpath_list = ArrayList([]const u8).init(allocator); |
| 34 | defer allocator.free(target_file_buf); | 122 | defer rpath_list.deinit(); |
| 35 | 123 | ||
| 36 | var stderr_file = %return std.io.getStdErr(); | 124 | var ver_major: u32 = 0; |
| 37 | var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file); | 125 | var ver_minor: u32 = 0; |
| 38 | const out_stream = &stderr_file_out_stream.stream; | 126 | var ver_patch: u32 = 0; |
| 39 | 127 | ||
| 40 | warn("====input:====\n"); | 128 | var arg_i: usize = 1; |
| 129 | while (arg_i < args.len) : (arg_i += 1) { | ||
| 130 | const arg = args[arg_i]; | ||
| 41 | 131 | ||
| 42 | warn("{}", target_file_buf); | 132 | if (arg.len != 0 and arg[0] == '-') { |
| 133 | if (mem.eql(u8, arg, "--release-fast")) { | ||
| 134 | build_mode = builtin.Mode.ReleaseFast; | ||
| 135 | } else if (mem.eql(u8, arg, "--release-safe")) { | ||
| 136 | build_mode = builtin.Mode.ReleaseSafe; | ||
| 137 | } else if (mem.eql(u8, arg, "--strip")) { | ||
| 138 | strip = true; | ||
| 139 | } else if (mem.eql(u8, arg, "--static")) { | ||
| 140 | is_static = true; | ||
| 141 | } else if (mem.eql(u8, arg, "--verbose-tokenize")) { | ||
| 142 | verbose_tokenize = true; | ||
| 143 | } else if (mem.eql(u8, arg, "--verbose-ast-tree")) { | ||
| 144 | verbose_ast_tree = true; | ||
| 145 | } else if (mem.eql(u8, arg, "--verbose-ast-fmt")) { | ||
| 146 | verbose_ast_fmt = true; | ||
| 147 | } else if (mem.eql(u8, arg, "--verbose-link")) { | ||
| 148 | verbose_link = true; | ||
| 149 | } else if (mem.eql(u8, arg, "--verbose-ir")) { | ||
| 150 | verbose_ir = true; | ||
| 151 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { | ||
| 152 | verbose_llvm_ir = true; | ||
| 153 | } else if (mem.eql(u8, arg, "--verbose-cimport")) { | ||
| 154 | verbose_cimport = true; | ||
| 155 | } else if (mem.eql(u8, arg, "-mwindows")) { | ||
| 156 | mwindows = true; | ||
| 157 | } else if (mem.eql(u8, arg, "-mconsole")) { | ||
| 158 | mconsole = true; | ||
| 159 | } else if (mem.eql(u8, arg, "-rdynamic")) { | ||
| 160 | rdynamic = true; | ||
| 161 | } else if (mem.eql(u8, arg, "--each-lib-rpath")) { | ||
| 162 | each_lib_rpath = true; | ||
| 163 | } else if (mem.eql(u8, arg, "--enable-timing-info")) { | ||
| 164 | timing_info = true; | ||
| 165 | } else if (mem.eql(u8, arg, "--test-cmd-bin")) { | ||
| 166 | @panic("TODO --test-cmd-bin"); | ||
| 167 | } else if (arg[1] == 'L' and arg.len > 2) { | ||
| 168 | // alias for --library-path | ||
| 169 | %return lib_dirs.append(arg[1..]); | ||
| 170 | } else if (mem.eql(u8, arg, "--pkg-begin")) { | ||
| 171 | @panic("TODO --pkg-begin"); | ||
| 172 | } else if (mem.eql(u8, arg, "--pkg-end")) { | ||
| 173 | @panic("TODO --pkg-end"); | ||
| 174 | } else if (arg_i + 1 >= args.len) { | ||
| 175 | return badArgs("expected another argument after {}", arg); | ||
| 176 | } else { | ||
| 177 | arg_i += 1; | ||
| 178 | if (mem.eql(u8, arg, "--output")) { | ||
| 179 | out_file = args[arg_i]; | ||
| 180 | } else if (mem.eql(u8, arg, "--output-h")) { | ||
| 181 | out_file_h = args[arg_i]; | ||
| 182 | } else if (mem.eql(u8, arg, "--color")) { | ||
| 183 | if (mem.eql(u8, args[arg_i], "auto")) { | ||
| 184 | color = ErrColor.Auto; | ||
| 185 | } else if (mem.eql(u8, args[arg_i], "on")) { | ||
| 186 | color = ErrColor.On; | ||
| 187 | } else if (mem.eql(u8, args[arg_i], "off")) { | ||
| 188 | color = ErrColor.Off; | ||
| 189 | } else { | ||
| 190 | return badArgs("--color options are 'auto', 'on', or 'off'"); | ||
| 191 | } | ||
| 192 | } else if (mem.eql(u8, arg, "--emit")) { | ||
| 193 | if (mem.eql(u8, args[arg_i], "asm")) { | ||
| 194 | emit_file_type = Emit.Assembly; | ||
| 195 | } else if (mem.eql(u8, args[arg_i], "bin")) { | ||
| 196 | emit_file_type = Emit.Binary; | ||
| 197 | } else if (mem.eql(u8, args[arg_i], "llvm-ir")) { | ||
| 198 | emit_file_type = Emit.LlvmIr; | ||
| 199 | } else { | ||
| 200 | return badArgs("--emit options are 'asm', 'bin', or 'llvm-ir'"); | ||
| 201 | } | ||
| 202 | } else if (mem.eql(u8, arg, "--name")) { | ||
| 203 | out_name_arg = args[arg_i]; | ||
| 204 | } else if (mem.eql(u8, arg, "--libc-lib-dir")) { | ||
| 205 | libc_lib_dir_arg = args[arg_i]; | ||
| 206 | } else if (mem.eql(u8, arg, "--libc-static-lib-dir")) { | ||
| 207 | libc_static_lib_dir_arg = args[arg_i]; | ||
| 208 | } else if (mem.eql(u8, arg, "--libc-include-dir")) { | ||
| 209 | libc_include_dir_arg = args[arg_i]; | ||
| 210 | } else if (mem.eql(u8, arg, "--msvc-lib-dir")) { | ||
| 211 | msvc_lib_dir_arg = args[arg_i]; | ||
| 212 | } else if (mem.eql(u8, arg, "--kernel32-lib-dir")) { | ||
| 213 | kernel32_lib_dir_arg = args[arg_i]; | ||
| 214 | } else if (mem.eql(u8, arg, "--zig-install-prefix")) { | ||
| 215 | zig_install_prefix = args[arg_i]; | ||
| 216 | } else if (mem.eql(u8, arg, "--dynamic-linker")) { | ||
| 217 | dynamic_linker_arg = args[arg_i]; | ||
| 218 | } else if (mem.eql(u8, arg, "-isystem")) { | ||
| 219 | %return clang_argv.append("-isystem"); | ||
| 220 | %return clang_argv.append(args[arg_i]); | ||
| 221 | } else if (mem.eql(u8, arg, "-dirafter")) { | ||
| 222 | %return clang_argv.append("-dirafter"); | ||
| 223 | %return clang_argv.append(args[arg_i]); | ||
| 224 | } else if (mem.eql(u8, arg, "-mllvm")) { | ||
| 225 | %return clang_argv.append("-mllvm"); | ||
| 226 | %return clang_argv.append(args[arg_i]); | ||
| 43 | 227 | ||
| 44 | warn("====tokenization:====\n"); | 228 | %return llvm_argv.append(args[arg_i]); |
| 45 | { | 229 | } else if (mem.eql(u8, arg, "--library-path") or mem.eql(u8, arg, "-L")) { |
| 46 | var tokenizer = Tokenizer.init(target_file_buf); | 230 | %return lib_dirs.append(args[arg_i]); |
| 47 | while (true) { | 231 | } else if (mem.eql(u8, arg, "--library")) { |
| 48 | const token = tokenizer.next(); | 232 | %return link_libs.append(args[arg_i]); |
| 49 | tokenizer.dump(token); | 233 | } else if (mem.eql(u8, arg, "--object")) { |
| 50 | if (token.id == Token.Id.Eof) { | 234 | %return objects.append(args[arg_i]); |
| 51 | break; | 235 | } else if (mem.eql(u8, arg, "--assembly")) { |
| 236 | %return asm_files.append(args[arg_i]); | ||
| 237 | } else if (mem.eql(u8, arg, "--cache-dir")) { | ||
| 238 | cache_dir_arg = args[arg_i]; | ||
| 239 | } else if (mem.eql(u8, arg, "--target-arch")) { | ||
| 240 | target_arch = args[arg_i]; | ||
| 241 | } else if (mem.eql(u8, arg, "--target-os")) { | ||
| 242 | target_os = args[arg_i]; | ||
| 243 | } else if (mem.eql(u8, arg, "--target-environ")) { | ||
| 244 | target_environ = args[arg_i]; | ||
| 245 | } else if (mem.eql(u8, arg, "-mmacosx-version-min")) { | ||
| 246 | mmacosx_version_min = args[arg_i]; | ||
| 247 | } else if (mem.eql(u8, arg, "-mios-version-min")) { | ||
| 248 | mios_version_min = args[arg_i]; | ||
| 249 | } else if (mem.eql(u8, arg, "-framework")) { | ||
| 250 | %return frameworks.append(args[arg_i]); | ||
| 251 | } else if (mem.eql(u8, arg, "--linker-script")) { | ||
| 252 | linker_script_arg = args[arg_i]; | ||
| 253 | } else if (mem.eql(u8, arg, "-rpath")) { | ||
| 254 | %return rpath_list.append(args[arg_i]); | ||
| 255 | } else if (mem.eql(u8, arg, "--test-filter")) { | ||
| 256 | %return test_filters.append(args[arg_i]); | ||
| 257 | } else if (mem.eql(u8, arg, "--test-name-prefix")) { | ||
| 258 | test_name_prefix_arg = args[arg_i]; | ||
| 259 | } else if (mem.eql(u8, arg, "--ver-major")) { | ||
| 260 | ver_major = %return std.fmt.parseUnsigned(u32, args[arg_i], 10); | ||
| 261 | } else if (mem.eql(u8, arg, "--ver-minor")) { | ||
| 262 | ver_minor = %return std.fmt.parseUnsigned(u32, args[arg_i], 10); | ||
| 263 | } else if (mem.eql(u8, arg, "--ver-patch")) { | ||
| 264 | ver_patch = %return std.fmt.parseUnsigned(u32, args[arg_i], 10); | ||
| 265 | } else if (mem.eql(u8, arg, "--test-cmd")) { | ||
| 266 | @panic("TODO --test-cmd"); | ||
| 267 | } else { | ||
| 268 | return badArgs("invalid argument: {}", arg); | ||
| 269 | } | ||
| 52 | } | 270 | } |
| 271 | } else if (cmd == Cmd.None) { | ||
| 272 | if (mem.eql(u8, arg, "build-obj")) { | ||
| 273 | cmd = Cmd.Build; | ||
| 274 | build_kind = Module.Kind.Obj; | ||
| 275 | } else if (mem.eql(u8, arg, "build-exe")) { | ||
| 276 | cmd = Cmd.Build; | ||
| 277 | build_kind = Module.Kind.Exe; | ||
| 278 | } else if (mem.eql(u8, arg, "build-lib")) { | ||
| 279 | cmd = Cmd.Build; | ||
| 280 | build_kind = Module.Kind.Lib; | ||
| 281 | } else if (mem.eql(u8, arg, "version")) { | ||
| 282 | cmd = Cmd.Version; | ||
| 283 | } else if (mem.eql(u8, arg, "zen")) { | ||
| 284 | cmd = Cmd.Zen; | ||
| 285 | } else if (mem.eql(u8, arg, "translate-c")) { | ||
| 286 | cmd = Cmd.TranslateC; | ||
| 287 | } else if (mem.eql(u8, arg, "test")) { | ||
| 288 | cmd = Cmd.Test; | ||
| 289 | build_kind = Module.Kind.Exe; | ||
| 290 | } else { | ||
| 291 | return badArgs("unrecognized command: {}", arg); | ||
| 292 | } | ||
| 293 | } else switch (cmd) { | ||
| 294 | Cmd.Build, Cmd.TranslateC, Cmd.Test => { | ||
| 295 | if (in_file_arg == null) { | ||
| 296 | in_file_arg = arg; | ||
| 297 | } else { | ||
| 298 | return badArgs("unexpected extra parameter: {}", arg); | ||
| 299 | } | ||
| 300 | }, | ||
| 301 | Cmd.Version, Cmd.Zen, Cmd.Targets => { | ||
| 302 | return badArgs("unexpected extra parameter: {}", arg); | ||
| 303 | }, | ||
| 304 | Cmd.None => unreachable, | ||
| 53 | } | 305 | } |
| 54 | } | 306 | } |
| 55 | 307 | ||
| 56 | warn("====parse:====\n"); | 308 | target.initializeAll(); |
| 309 | |||
| 310 | // TODO | ||
| 311 | // ZigTarget alloc_target; | ||
| 312 | // ZigTarget *target; | ||
| 313 | // if (!target_arch && !target_os && !target_environ) { | ||
| 314 | // target = nullptr; | ||
| 315 | // } else { | ||
| 316 | // target = &alloc_target; | ||
| 317 | // get_unknown_target(target); | ||
| 318 | // if (target_arch) { | ||
| 319 | // if (parse_target_arch(target_arch, &target->arch)) { | ||
| 320 | // fprintf(stderr, "invalid --target-arch argument\n"); | ||
| 321 | // return usage(arg0); | ||
| 322 | // } | ||
| 323 | // } | ||
| 324 | // if (target_os) { | ||
| 325 | // if (parse_target_os(target_os, &target->os)) { | ||
| 326 | // fprintf(stderr, "invalid --target-os argument\n"); | ||
| 327 | // return usage(arg0); | ||
| 328 | // } | ||
| 329 | // } | ||
| 330 | // if (target_environ) { | ||
| 331 | // if (parse_target_environ(target_environ, &target->env_type)) { | ||
| 332 | // fprintf(stderr, "invalid --target-environ argument\n"); | ||
| 333 | // return usage(arg0); | ||
| 334 | // } | ||
| 335 | // } | ||
| 336 | // } | ||
| 337 | |||
| 338 | switch (cmd) { | ||
| 339 | Cmd.None => return badArgs("expected command"), | ||
| 340 | Cmd.Zen => return printZen(), | ||
| 341 | Cmd.Build, Cmd.Test, Cmd.TranslateC => { | ||
| 342 | if (cmd == Cmd.Build and in_file_arg == null and objects.len == 0 and asm_files.len == 0) { | ||
| 343 | return badArgs("expected source file argument or at least one --object or --assembly argument"); | ||
| 344 | } else if ((cmd == Cmd.TranslateC or cmd == Cmd.Test) and in_file_arg == null) { | ||
| 345 | return badArgs("expected source file argument"); | ||
| 346 | } else if (cmd == Cmd.Build and build_kind == Module.Kind.Obj and objects.len != 0) { | ||
| 347 | return badArgs("When building an object file, --object arguments are invalid"); | ||
| 348 | } | ||
| 349 | |||
| 350 | const root_name = switch (cmd) { | ||
| 351 | Cmd.Build, Cmd.TranslateC => x: { | ||
| 352 | if (out_name_arg) |out_name| { | ||
| 353 | break :x out_name; | ||
| 354 | } else if (in_file_arg) |in_file_path| { | ||
| 355 | const basename = os.path.basename(in_file_path); | ||
| 356 | var it = mem.split(basename, "."); | ||
| 357 | break :x it.next() ?? return badArgs("file name cannot be empty"); | ||
| 358 | } else { | ||
| 359 | return badArgs("--name [name] not provided and unable to infer"); | ||
| 360 | } | ||
| 361 | }, | ||
| 362 | Cmd.Test => "test", | ||
| 363 | else => unreachable, | ||
| 364 | }; | ||
| 365 | |||
| 366 | const zig_root_source_file = if (cmd == Cmd.TranslateC) null else in_file_arg; | ||
| 367 | |||
| 368 | const chosen_cache_dir = cache_dir_arg ?? default_zig_cache_name; | ||
| 369 | const full_cache_dir = %return os.path.resolve(allocator, ".", chosen_cache_dir); | ||
| 370 | defer allocator.free(full_cache_dir); | ||
| 371 | |||
| 372 | const zig_lib_dir = %return resolveZigLibDir(allocator, zig_install_prefix); | ||
| 373 | %defer allocator.free(zig_lib_dir); | ||
| 374 | |||
| 375 | const module = %return Module.create(allocator, root_name, zig_root_source_file, | ||
| 376 | Target.Native, build_kind, build_mode, zig_lib_dir, full_cache_dir); | ||
| 377 | defer module.destroy(); | ||
| 378 | |||
| 379 | module.version_major = ver_major; | ||
| 380 | module.version_minor = ver_minor; | ||
| 381 | module.version_patch = ver_patch; | ||
| 382 | |||
| 383 | module.is_test = cmd == Cmd.Test; | ||
| 384 | if (linker_script_arg) |linker_script| { | ||
| 385 | module.linker_script = linker_script; | ||
| 386 | } | ||
| 387 | module.each_lib_rpath = each_lib_rpath; | ||
| 388 | module.clang_argv = clang_argv.toSliceConst(); | ||
| 389 | module.llvm_argv = llvm_argv.toSliceConst(); | ||
| 390 | module.strip = strip; | ||
| 391 | module.is_static = is_static; | ||
| 392 | |||
| 393 | if (libc_lib_dir_arg) |libc_lib_dir| { | ||
| 394 | module.libc_lib_dir = libc_lib_dir; | ||
| 395 | } | ||
| 396 | if (libc_static_lib_dir_arg) |libc_static_lib_dir| { | ||
| 397 | module.libc_static_lib_dir = libc_static_lib_dir; | ||
| 398 | } | ||
| 399 | if (libc_include_dir_arg) |libc_include_dir| { | ||
| 400 | module.libc_include_dir = libc_include_dir; | ||
| 401 | } | ||
| 402 | if (msvc_lib_dir_arg) |msvc_lib_dir| { | ||
| 403 | module.msvc_lib_dir = msvc_lib_dir; | ||
| 404 | } | ||
| 405 | if (kernel32_lib_dir_arg) |kernel32_lib_dir| { | ||
| 406 | module.kernel32_lib_dir = kernel32_lib_dir; | ||
| 407 | } | ||
| 408 | if (dynamic_linker_arg) |dynamic_linker| { | ||
| 409 | module.dynamic_linker = dynamic_linker; | ||
| 410 | } | ||
| 411 | module.verbose_tokenize = verbose_tokenize; | ||
| 412 | module.verbose_ast_tree = verbose_ast_tree; | ||
| 413 | module.verbose_ast_fmt = verbose_ast_fmt; | ||
| 414 | module.verbose_link = verbose_link; | ||
| 415 | module.verbose_ir = verbose_ir; | ||
| 416 | module.verbose_llvm_ir = verbose_llvm_ir; | ||
| 417 | module.verbose_cimport = verbose_cimport; | ||
| 418 | |||
| 419 | module.err_color = color; | ||
| 420 | |||
| 421 | module.lib_dirs = lib_dirs.toSliceConst(); | ||
| 422 | module.darwin_frameworks = frameworks.toSliceConst(); | ||
| 423 | module.rpath_list = rpath_list.toSliceConst(); | ||
| 424 | |||
| 425 | for (link_libs.toSliceConst()) |name| { | ||
| 426 | _ = %return module.addLinkLib(name, true); | ||
| 427 | } | ||
| 428 | |||
| 429 | module.windows_subsystem_windows = mwindows; | ||
| 430 | module.windows_subsystem_console = mconsole; | ||
| 431 | module.linker_rdynamic = rdynamic; | ||
| 432 | |||
| 433 | if (mmacosx_version_min != null and mios_version_min != null) { | ||
| 434 | return badArgs("-mmacosx-version-min and -mios-version-min options not allowed together"); | ||
| 435 | } | ||
| 436 | |||
| 437 | if (mmacosx_version_min) |ver| { | ||
| 438 | module.darwin_version_min = Module.DarwinVersionMin { .MacOS = ver }; | ||
| 439 | } else if (mios_version_min) |ver| { | ||
| 440 | module.darwin_version_min = Module.DarwinVersionMin { .Ios = ver }; | ||
| 441 | } | ||
| 442 | |||
| 443 | module.test_filters = test_filters.toSliceConst(); | ||
| 444 | module.test_name_prefix = test_name_prefix_arg; | ||
| 445 | module.out_h_path = out_file_h; | ||
| 446 | |||
| 447 | // TODO | ||
| 448 | //add_package(g, cur_pkg, g->root_package); | ||
| 449 | |||
| 450 | switch (cmd) { | ||
| 451 | Cmd.Build => { | ||
| 452 | module.emit_file_type = emit_file_type; | ||
| 453 | |||
| 454 | module.link_objects = objects.toSliceConst(); | ||
| 455 | module.assembly_files = asm_files.toSliceConst(); | ||
| 456 | |||
| 457 | %return module.build(); | ||
| 458 | %return module.link(out_file); | ||
| 459 | }, | ||
| 460 | Cmd.TranslateC => @panic("TODO translate-c"), | ||
| 461 | Cmd.Test => @panic("TODO test cmd"), | ||
| 462 | else => unreachable, | ||
| 463 | } | ||
| 464 | }, | ||
| 465 | Cmd.Version => @panic("TODO zig version"), | ||
| 466 | Cmd.Targets => @panic("TODO zig targets"), | ||
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 | fn printUsage(stream: &io.OutStream) -> %void { | ||
| 471 | %return stream.write( | ||
| 472 | \\Usage: zig [command] [options] | ||
| 473 | \\ | ||
| 474 | \\Commands: | ||
| 475 | \\ build build project from build.zig | ||
| 476 | \\ build-exe [source] create executable from source or object files | ||
| 477 | \\ build-lib [source] create library from source or object files | ||
| 478 | \\ build-obj [source] create object from source or assembly | ||
| 479 | \\ translate-c [source] convert c code to zig code | ||
| 480 | \\ targets list available compilation targets | ||
| 481 | \\ test [source] create and run a test build | ||
| 482 | \\ version print version number and exit | ||
| 483 | \\ zen print zen of zig and exit | ||
| 484 | \\Compile Options: | ||
| 485 | \\ --assembly [source] add assembly file to build | ||
| 486 | \\ --cache-dir [path] override the cache directory | ||
| 487 | \\ --color [auto|off|on] enable or disable colored error messages | ||
| 488 | \\ --emit [filetype] emit a specific file format as compilation output | ||
| 489 | \\ --enable-timing-info print timing diagnostics | ||
| 490 | \\ --libc-include-dir [path] directory where libc stdlib.h resides | ||
| 491 | \\ --name [name] override output name | ||
| 492 | \\ --output [file] override destination path | ||
| 493 | \\ --output-h [file] override generated header file path | ||
| 494 | \\ --pkg-begin [name] [path] make package available to import and push current pkg | ||
| 495 | \\ --pkg-end pop current pkg | ||
| 496 | \\ --release-fast build with optimizations on and safety off | ||
| 497 | \\ --release-safe build with optimizations on and safety on | ||
| 498 | \\ --static output will be statically linked | ||
| 499 | \\ --strip exclude debug symbols | ||
| 500 | \\ --target-arch [name] specify target architecture | ||
| 501 | \\ --target-environ [name] specify target environment | ||
| 502 | \\ --target-os [name] specify target operating system | ||
| 503 | \\ --verbose-tokenize enable compiler debug info: tokenization | ||
| 504 | \\ --verbose-ast-tree enable compiler debug info: parsing into an AST (treeview) | ||
| 505 | \\ --verbose-ast-fmt enable compiler debug info: parsing into an AST (render source) | ||
| 506 | \\ --verbose-cimport enable compiler debug info: C imports | ||
| 507 | \\ --verbose-ir enable compiler debug info: Zig IR | ||
| 508 | \\ --verbose-llvm-ir enable compiler debug info: LLVM IR | ||
| 509 | \\ --verbose-link enable compiler debug info: linking | ||
| 510 | \\ --zig-install-prefix [path] override directory where zig thinks it is installed | ||
| 511 | \\ -dirafter [dir] same as -isystem but do it last | ||
| 512 | \\ -isystem [dir] add additional search path for other .h files | ||
| 513 | \\ -mllvm [arg] additional arguments to forward to LLVM's option processing | ||
| 514 | \\Link Options: | ||
| 515 | \\ --ar-path [path] set the path to ar | ||
| 516 | \\ --dynamic-linker [path] set the path to ld.so | ||
| 517 | \\ --each-lib-rpath add rpath for each used dynamic library | ||
| 518 | \\ --libc-lib-dir [path] directory where libc crt1.o resides | ||
| 519 | \\ --libc-static-lib-dir [path] directory where libc crtbegin.o resides | ||
| 520 | \\ --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides | ||
| 521 | \\ --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides | ||
| 522 | \\ --library [lib] link against lib | ||
| 523 | \\ --library-path [dir] add a directory to the library search path | ||
| 524 | \\ --linker-script [path] use a custom linker script | ||
| 525 | \\ --object [obj] add object file to build | ||
| 526 | \\ -L[dir] alias for --library-path | ||
| 527 | \\ -rdynamic add all symbols to the dynamic symbol table | ||
| 528 | \\ -rpath [path] add directory to the runtime library search path | ||
| 529 | \\ -mconsole (windows) --subsystem console to the linker | ||
| 530 | \\ -mwindows (windows) --subsystem windows to the linker | ||
| 531 | \\ -framework [name] (darwin) link against framework | ||
| 532 | \\ -mios-version-min [ver] (darwin) set iOS deployment target | ||
| 533 | \\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target | ||
| 534 | \\ --ver-major [ver] dynamic library semver major version | ||
| 535 | \\ --ver-minor [ver] dynamic library semver minor version | ||
| 536 | \\ --ver-patch [ver] dynamic library semver patch version | ||
| 537 | \\Test Options: | ||
| 538 | \\ --test-filter [text] skip tests that do not match filter | ||
| 539 | \\ --test-name-prefix [text] add prefix to all tests | ||
| 540 | \\ --test-cmd [arg] specify test execution command one arg at a time | ||
| 541 | \\ --test-cmd-bin appends test binary path to test cmd args | ||
| 542 | \\ | ||
| 543 | ); | ||
| 544 | } | ||
| 57 | 545 | ||
| 58 | var tokenizer = Tokenizer.init(target_file_buf); | 546 | fn printZen() -> %void { |
| 59 | var parser = Parser.init(&tokenizer, allocator, target_file); | 547 | var stdout_file = %return io.getStdErr(); |
| 60 | defer parser.deinit(); | 548 | %return stdout_file.write( |
| 549 | \\ | ||
| 550 | \\ * Communicate intent precisely. | ||
| 551 | \\ * Edge cases matter. | ||
| 552 | \\ * Favor reading code over writing code. | ||
| 553 | \\ * Only one obvious way to do things. | ||
| 554 | \\ * Runtime crashes are better than bugs. | ||
| 555 | \\ * Compile errors are better than runtime crashes. | ||
| 556 | \\ * Incremental improvements. | ||
| 557 | \\ * Avoid local maximums. | ||
| 558 | \\ * Reduce the amount one must remember. | ||
| 559 | \\ * Minimize energy spent on coding style. | ||
| 560 | \\ * Together we serve end users. | ||
| 561 | \\ | ||
| 562 | \\ | ||
| 563 | ); | ||
| 564 | } | ||
| 565 | |||
| 566 | /// Caller must free result | ||
| 567 | fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) -> %[]u8 { | ||
| 568 | if (zig_install_prefix_arg) |zig_install_prefix| { | ||
| 569 | return testZigInstallPrefix(allocator, zig_install_prefix) %% |err| { | ||
| 570 | warn("No Zig installation found at prefix {}: {}\n", zig_install_prefix_arg, @errorName(err)); | ||
| 571 | return error.ZigInstallationNotFound; | ||
| 572 | }; | ||
| 573 | } else { | ||
| 574 | return findZigLibDir(allocator) %% |err| { | ||
| 575 | warn("Unable to find zig lib directory: {}.\nReinstall Zig or use --zig-install-prefix.\n", | ||
| 576 | @errorName(err)); | ||
| 577 | return error.ZigLibDirNotFound; | ||
| 578 | }; | ||
| 579 | } | ||
| 580 | } | ||
| 61 | 581 | ||
| 62 | const root_node = %return parser.parse(); | 582 | /// Caller must free result |
| 63 | defer parser.freeAst(root_node); | 583 | fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[]u8 { |
| 584 | const test_zig_dir = %return os.path.join(allocator, test_path, "lib", "zig"); | ||
| 585 | %defer allocator.free(test_zig_dir); | ||
| 64 | 586 | ||
| 65 | %return parser.renderAst(out_stream, root_node); | 587 | const test_index_file = %return os.path.join(allocator, test_zig_dir, "std", "index.zig"); |
| 588 | defer allocator.free(test_index_file); | ||
| 66 | 589 | ||
| 67 | warn("====fmt:====\n"); | 590 | var file = %return io.File.openRead(test_index_file, allocator); |
| 68 | %return parser.renderSource(out_stream, root_node); | 591 | file.close(); |
| 592 | |||
| 593 | return test_zig_dir; | ||
| 69 | } | 594 | } |
| 70 | 595 | ||
| 71 | test "import other tests" { | 596 | /// Caller must free result |
| 72 | _ = @import("parser.zig"); | 597 | fn findZigLibDir(allocator: &mem.Allocator) -> %[]u8 { |
| 73 | _ = @import("tokenizer.zig"); | 598 | const self_exe_path = %return os.selfExeDirPath(allocator); |
| 599 | defer allocator.free(self_exe_path); | ||
| 600 | |||
| 601 | var cur_path: []const u8 = self_exe_path; | ||
| 602 | while (true) { | ||
| 603 | const test_dir = os.path.dirname(cur_path); | ||
| 604 | |||
| 605 | if (mem.eql(u8, test_dir, cur_path)) { | ||
| 606 | break; | ||
| 607 | } | ||
| 608 | |||
| 609 | return testZigInstallPrefix(allocator, test_dir) %% |err| { | ||
| 610 | cur_path = test_dir; | ||
| 611 | continue; | ||
| 612 | }; | ||
| 613 | } | ||
| 614 | |||
| 615 | // TODO look in hard coded installation path from configuration | ||
| 616 | //if (ZIG_INSTALL_PREFIX != nullptr) { | ||
| 617 | // if (test_zig_install_prefix(buf_create_from_str(ZIG_INSTALL_PREFIX), out_path)) { | ||
| 618 | // return 0; | ||
| 619 | // } | ||
| 620 | //} | ||
| 621 | |||
| 622 | return error.FileNotFound; | ||
| 74 | } | 623 | } |
src-self-hosted/module.zig created+295| ... | @@ -0,0 +1,295 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const os = std.os; | ||
| 3 | const io = std.io; | ||
| 4 | const mem = std.mem; | ||
| 5 | const Buffer = std.Buffer; | ||
| 6 | const llvm = @import("llvm.zig"); | ||
| 7 | const c = @import("c.zig"); | ||
| 8 | const builtin = @import("builtin"); | ||
| 9 | const Target = @import("target.zig").Target; | ||
| 10 | const warn = std.debug.warn; | ||
| 11 | const Tokenizer = @import("tokenizer.zig").Tokenizer; | ||
| 12 | const Token = @import("tokenizer.zig").Token; | ||
| 13 | const Parser = @import("parser.zig").Parser; | ||
| 14 | const ArrayList = std.ArrayList; | ||
| 15 | |||
| 16 | pub const Module = struct { | ||
| 17 | allocator: &mem.Allocator, | ||
| 18 | name: Buffer, | ||
| 19 | root_src_path: ?[]const u8, | ||
| 20 | module: llvm.ModuleRef, | ||
| 21 | context: llvm.ContextRef, | ||
| 22 | builder: llvm.BuilderRef, | ||
| 23 | target: Target, | ||
| 24 | build_mode: builtin.Mode, | ||
| 25 | zig_lib_dir: []const u8, | ||
| 26 | |||
| 27 | version_major: u32, | ||
| 28 | version_minor: u32, | ||
| 29 | version_patch: u32, | ||
| 30 | |||
| 31 | linker_script: ?[]const u8, | ||
| 32 | cache_dir: []const u8, | ||
| 33 | libc_lib_dir: ?[]const u8, | ||
| 34 | libc_static_lib_dir: ?[]const u8, | ||
| 35 | libc_include_dir: ?[]const u8, | ||
| 36 | msvc_lib_dir: ?[]const u8, | ||
| 37 | kernel32_lib_dir: ?[]const u8, | ||
| 38 | dynamic_linker: ?[]const u8, | ||
| 39 | out_h_path: ?[]const u8, | ||
| 40 | |||
| 41 | is_test: bool, | ||
| 42 | each_lib_rpath: bool, | ||
| 43 | strip: bool, | ||
| 44 | is_static: bool, | ||
| 45 | linker_rdynamic: bool, | ||
| 46 | |||
| 47 | clang_argv: []const []const u8, | ||
| 48 | llvm_argv: []const []const u8, | ||
| 49 | lib_dirs: []const []const u8, | ||
| 50 | rpath_list: []const []const u8, | ||
| 51 | assembly_files: []const []const u8, | ||
| 52 | link_objects: []const []const u8, | ||
| 53 | |||
| 54 | windows_subsystem_windows: bool, | ||
| 55 | windows_subsystem_console: bool, | ||
| 56 | |||
| 57 | link_libs_list: ArrayList(&LinkLib), | ||
| 58 | libc_link_lib: ?&LinkLib, | ||
| 59 | |||
| 60 | err_color: ErrColor, | ||
| 61 | |||
| 62 | verbose_tokenize: bool, | ||
| 63 | verbose_ast_tree: bool, | ||
| 64 | verbose_ast_fmt: bool, | ||
| 65 | verbose_cimport: bool, | ||
| 66 | verbose_ir: bool, | ||
| 67 | verbose_llvm_ir: bool, | ||
| 68 | verbose_link: bool, | ||
| 69 | |||
| 70 | darwin_frameworks: []const []const u8, | ||
| 71 | darwin_version_min: DarwinVersionMin, | ||
| 72 | |||
| 73 | test_filters: []const []const u8, | ||
| 74 | test_name_prefix: ?[]const u8, | ||
| 75 | |||
| 76 | emit_file_type: Emit, | ||
| 77 | |||
| 78 | kind: Kind, | ||
| 79 | |||
| 80 | pub const DarwinVersionMin = union(enum) { | ||
| 81 | None, | ||
| 82 | MacOS: []const u8, | ||
| 83 | Ios: []const u8, | ||
| 84 | }; | ||
| 85 | |||
| 86 | pub const Kind = enum { | ||
| 87 | Exe, | ||
| 88 | Lib, | ||
| 89 | Obj, | ||
| 90 | }; | ||
| 91 | |||
| 92 | pub const ErrColor = enum { | ||
| 93 | Auto, | ||
| 94 | Off, | ||
| 95 | On, | ||
| 96 | }; | ||
| 97 | |||
| 98 | pub const LinkLib = struct { | ||
| 99 | name: []const u8, | ||
| 100 | path: ?[]const u8, | ||
| 101 | /// the list of symbols we depend on from this lib | ||
| 102 | symbols: ArrayList([]u8), | ||
| 103 | provided_explicitly: bool, | ||
| 104 | }; | ||
| 105 | |||
| 106 | pub const Emit = enum { | ||
| 107 | Binary, | ||
| 108 | Assembly, | ||
| 109 | LlvmIr, | ||
| 110 | }; | ||
| 111 | |||
| 112 | pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target, | ||
| 113 | kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) -> %&Module | ||
| 114 | { | ||
| 115 | var name_buffer = %return Buffer.init(allocator, name); | ||
| 116 | %defer name_buffer.deinit(); | ||
| 117 | |||
| 118 | const context = c.LLVMContextCreate() ?? return error.OutOfMemory; | ||
| 119 | %defer c.LLVMContextDispose(context); | ||
| 120 | |||
| 121 | const module = c.LLVMModuleCreateWithNameInContext(name_buffer.ptr(), context) ?? return error.OutOfMemory; | ||
| 122 | %defer c.LLVMDisposeModule(module); | ||
| 123 | |||
| 124 | const builder = c.LLVMCreateBuilderInContext(context) ?? return error.OutOfMemory; | ||
| 125 | %defer c.LLVMDisposeBuilder(builder); | ||
| 126 | |||
| 127 | const module_ptr = %return allocator.create(Module); | ||
| 128 | %defer allocator.destroy(module_ptr); | ||
| 129 | |||
| 130 | *module_ptr = Module { | ||
| 131 | .allocator = allocator, | ||
| 132 | .name = name_buffer, | ||
| 133 | .root_src_path = root_src_path, | ||
| 134 | .module = module, | ||
| 135 | .context = context, | ||
| 136 | .builder = builder, | ||
| 137 | .target = *target, | ||
| 138 | .kind = kind, | ||
| 139 | .build_mode = build_mode, | ||
| 140 | .zig_lib_dir = zig_lib_dir, | ||
| 141 | .cache_dir = cache_dir, | ||
| 142 | |||
| 143 | .version_major = 0, | ||
| 144 | .version_minor = 0, | ||
| 145 | .version_patch = 0, | ||
| 146 | |||
| 147 | .verbose_tokenize = false, | ||
| 148 | .verbose_ast_tree = false, | ||
| 149 | .verbose_ast_fmt = false, | ||
| 150 | .verbose_cimport = false, | ||
| 151 | .verbose_ir = false, | ||
| 152 | .verbose_llvm_ir = false, | ||
| 153 | .verbose_link = false, | ||
| 154 | |||
| 155 | .linker_script = null, | ||
| 156 | .libc_lib_dir = null, | ||
| 157 | .libc_static_lib_dir = null, | ||
| 158 | .libc_include_dir = null, | ||
| 159 | .msvc_lib_dir = null, | ||
| 160 | .kernel32_lib_dir = null, | ||
| 161 | .dynamic_linker = null, | ||
| 162 | .out_h_path = null, | ||
| 163 | .is_test = false, | ||
| 164 | .each_lib_rpath = false, | ||
| 165 | .strip = false, | ||
| 166 | .is_static = false, | ||
| 167 | .linker_rdynamic = false, | ||
| 168 | .clang_argv = [][]const u8{}, | ||
| 169 | .llvm_argv = [][]const u8{}, | ||
| 170 | .lib_dirs = [][]const u8{}, | ||
| 171 | .rpath_list = [][]const u8{}, | ||
| 172 | .assembly_files = [][]const u8{}, | ||
| 173 | .link_objects = [][]const u8{}, | ||
| 174 | .windows_subsystem_windows = false, | ||
| 175 | .windows_subsystem_console = false, | ||
| 176 | .link_libs_list = ArrayList(&LinkLib).init(allocator), | ||
| 177 | .libc_link_lib = null, | ||
| 178 | .err_color = ErrColor.Auto, | ||
| 179 | .darwin_frameworks = [][]const u8{}, | ||
| 180 | .darwin_version_min = DarwinVersionMin.None, | ||
| 181 | .test_filters = [][]const u8{}, | ||
| 182 | .test_name_prefix = null, | ||
| 183 | .emit_file_type = Emit.Binary, | ||
| 184 | }; | ||
| 185 | return module_ptr; | ||
| 186 | } | ||
| 187 | |||
| 188 | fn dump(self: &Module) { | ||
| 189 | c.LLVMDumpModule(self.module); | ||
| 190 | } | ||
| 191 | |||
| 192 | pub fn destroy(self: &Module) { | ||
| 193 | c.LLVMDisposeBuilder(self.builder); | ||
| 194 | c.LLVMDisposeModule(self.module); | ||
| 195 | c.LLVMContextDispose(self.context); | ||
| 196 | self.name.deinit(); | ||
| 197 | |||
| 198 | self.allocator.destroy(self); | ||
| 199 | } | ||
| 200 | |||
| 201 | pub fn build(self: &Module) -> %void { | ||
| 202 | const root_src_path = self.root_src_path ?? @panic("TODO handle null root src path"); | ||
| 203 | const root_src_real_path = os.path.real(self.allocator, root_src_path) %% |err| { | ||
| 204 | %return printError("unable to open '{}': {}", root_src_path, err); | ||
| 205 | return err; | ||
| 206 | }; | ||
| 207 | %defer self.allocator.free(root_src_real_path); | ||
| 208 | |||
| 209 | const source_code = io.readFileAlloc(root_src_real_path, self.allocator) %% |err| { | ||
| 210 | %return printError("unable to open '{}': {}", root_src_real_path, err); | ||
| 211 | return err; | ||
| 212 | }; | ||
| 213 | %defer self.allocator.free(source_code); | ||
| 214 | |||
| 215 | warn("====input:====\n"); | ||
| 216 | |||
| 217 | warn("{}", source_code); | ||
| 218 | |||
| 219 | warn("====tokenization:====\n"); | ||
| 220 | { | ||
| 221 | var tokenizer = Tokenizer.init(source_code); | ||
| 222 | while (true) { | ||
| 223 | const token = tokenizer.next(); | ||
| 224 | tokenizer.dump(token); | ||
| 225 | if (token.id == Token.Id.Eof) { | ||
| 226 | break; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | warn("====parse:====\n"); | ||
| 232 | |||
| 233 | var tokenizer = Tokenizer.init(source_code); | ||
| 234 | var parser = Parser.init(&tokenizer, self.allocator, root_src_real_path); | ||
| 235 | defer parser.deinit(); | ||
| 236 | |||
| 237 | const root_node = %return parser.parse(); | ||
| 238 | defer parser.freeAst(root_node); | ||
| 239 | |||
| 240 | var stderr_file = %return std.io.getStdErr(); | ||
| 241 | var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file); | ||
| 242 | const out_stream = &stderr_file_out_stream.stream; | ||
| 243 | %return parser.renderAst(out_stream, root_node); | ||
| 244 | |||
| 245 | warn("====fmt:====\n"); | ||
| 246 | %return parser.renderSource(out_stream, root_node); | ||
| 247 | |||
| 248 | warn("====ir:====\n"); | ||
| 249 | warn("TODO\n\n"); | ||
| 250 | |||
| 251 | warn("====llvm ir:====\n"); | ||
| 252 | self.dump(); | ||
| 253 | |||
| 254 | } | ||
| 255 | |||
| 256 | pub fn link(self: &Module, out_file: ?[]const u8) -> %void { | ||
| 257 | warn("TODO link"); | ||
| 258 | } | ||
| 259 | |||
| 260 | pub fn addLinkLib(self: &Module, name: []const u8, provided_explicitly: bool) -> %&LinkLib { | ||
| 261 | const is_libc = mem.eql(u8, name, "c"); | ||
| 262 | |||
| 263 | if (is_libc) { | ||
| 264 | if (self.libc_link_lib) |libc_link_lib| { | ||
| 265 | return libc_link_lib; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | for (self.link_libs_list.toSliceConst()) |existing_lib| { | ||
| 270 | if (mem.eql(u8, name, existing_lib.name)) { | ||
| 271 | return existing_lib; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | const link_lib = %return self.allocator.create(LinkLib); | ||
| 276 | *link_lib = LinkLib { | ||
| 277 | .name = name, | ||
| 278 | .path = null, | ||
| 279 | .provided_explicitly = provided_explicitly, | ||
| 280 | .symbols = ArrayList([]u8).init(self.allocator), | ||
| 281 | }; | ||
| 282 | %return self.link_libs_list.append(link_lib); | ||
| 283 | if (is_libc) { | ||
| 284 | self.libc_link_lib = link_lib; | ||
| 285 | } | ||
| 286 | return link_lib; | ||
| 287 | } | ||
| 288 | }; | ||
| 289 | |||
| 290 | fn printError(comptime format: []const u8, args: ...) -> %void { | ||
| 291 | var stderr_file = %return std.io.getStdErr(); | ||
| 292 | var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file); | ||
| 293 | const out_stream = &stderr_file_out_stream.stream; | ||
| 294 | %return out_stream.print(format, args); | ||
| 295 | } | ||
src-self-hosted/target.zig+51| ... | @@ -1,5 +1,56 @@ | ... | @@ -1,5 +1,56 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 1 | const c = @import("c.zig"); | 2 | const c = @import("c.zig"); |
| 2 | 3 | ||
| 4 | pub const CrossTarget = struct { | ||
| 5 | arch: builtin.Arch, | ||
| 6 | os: builtin.Os, | ||
| 7 | environ: builtin.Environ, | ||
| 8 | }; | ||
| 9 | |||
| 10 | pub const Target = union(enum) { | ||
| 11 | Native, | ||
| 12 | Cross: CrossTarget, | ||
| 13 | |||
| 14 | pub fn oFileExt(self: &const Target) -> []const u8 { | ||
| 15 | const environ = switch (*self) { | ||
| 16 | Target.Native => builtin.environ, | ||
| 17 | Target.Cross => |t| t.environ, | ||
| 18 | }; | ||
| 19 | return switch (environ) { | ||
| 20 | builtin.Environ.msvc => ".obj", | ||
| 21 | else => ".o", | ||
| 22 | }; | ||
| 23 | } | ||
| 24 | |||
| 25 | pub fn exeFileExt(self: &const Target) -> []const u8 { | ||
| 26 | return switch (self.getOs()) { | ||
| 27 | builtin.Os.windows => ".exe", | ||
| 28 | else => "", | ||
| 29 | }; | ||
| 30 | } | ||
| 31 | |||
| 32 | pub fn getOs(self: &const Target) -> builtin.Os { | ||
| 33 | return switch (*self) { | ||
| 34 | Target.Native => builtin.os, | ||
| 35 | Target.Cross => |t| t.os, | ||
| 36 | }; | ||
| 37 | } | ||
| 38 | |||
| 39 | pub fn isDarwin(self: &const Target) -> bool { | ||
| 40 | return switch (self.getOs()) { | ||
| 41 | builtin.Os.darwin, builtin.Os.ios, builtin.Os.macosx => true, | ||
| 42 | else => false, | ||
| 43 | }; | ||
| 44 | } | ||
| 45 | |||
| 46 | pub fn isWindows(self: &const Target) -> bool { | ||
| 47 | return switch (self.getOs()) { | ||
| 48 | builtin.Os.windows => true, | ||
| 49 | else => false, | ||
| 50 | }; | ||
| 51 | } | ||
| 52 | }; | ||
| 53 | |||
| 3 | pub fn initializeAll() { | 54 | pub fn initializeAll() { |
| 4 | c.LLVMInitializeAllTargets(); | 55 | c.LLVMInitializeAllTargets(); |
| 5 | c.LLVMInitializeAllTargetInfos(); | 56 | c.LLVMInitializeAllTargetInfos(); |
std/buffer.zig+5| ... | @@ -139,6 +139,11 @@ pub const Buffer = struct { | ... | @@ -139,6 +139,11 @@ pub const Buffer = struct { |
| 139 | %return self.resize(m.len); | 139 | %return self.resize(m.len); |
| 140 | mem.copy(u8, self.list.toSlice(), m); | 140 | mem.copy(u8, self.list.toSlice(), m); |
| 141 | } | 141 | } |
| 142 | |||
| 143 | /// For passing to C functions. | ||
| 144 | pub fn ptr(self: &const Buffer) -> &u8 { | ||
| 145 | return self.list.items.ptr; | ||
| 146 | } | ||
| 142 | }; | 147 | }; |
| 143 | 148 | ||
| 144 | test "simple Buffer" { | 149 | test "simple Buffer" { |
std/c/index.zig+1| ... | @@ -48,3 +48,4 @@ pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) -> c_int; | ... | @@ -48,3 +48,4 @@ pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) -> c_int; |
| 48 | pub extern "c" fn malloc(usize) -> ?&c_void; | 48 | pub extern "c" fn malloc(usize) -> ?&c_void; |
| 49 | pub extern "c" fn realloc(&c_void, usize) -> ?&c_void; | 49 | pub extern "c" fn realloc(&c_void, usize) -> ?&c_void; |
| 50 | pub extern "c" fn free(&c_void); | 50 | pub extern "c" fn free(&c_void); |
| 51 | pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) -> c_int; |
std/heap.zig+7-8| ... | @@ -10,7 +10,8 @@ const Allocator = mem.Allocator; | ... | @@ -10,7 +10,8 @@ const Allocator = mem.Allocator; |
| 10 | 10 | ||
| 11 | error OutOfMemory; | 11 | error OutOfMemory; |
| 12 | 12 | ||
| 13 | pub var c_allocator = Allocator { | 13 | pub const c_allocator = &c_allocator_state; |
| 14 | var c_allocator_state = Allocator { | ||
| 14 | .allocFn = cAlloc, | 15 | .allocFn = cAlloc, |
| 15 | .reallocFn = cRealloc, | 16 | .reallocFn = cRealloc, |
| 16 | .freeFn = cFree, | 17 | .freeFn = cFree, |
| ... | @@ -24,15 +25,13 @@ fn cAlloc(self: &Allocator, n: usize, alignment: u29) -> %[]u8 { | ... | @@ -24,15 +25,13 @@ fn cAlloc(self: &Allocator, n: usize, alignment: u29) -> %[]u8 { |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 26 | fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 { | 27 | fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 { |
| 27 | if (new_size <= old_mem.len) { | 28 | const old_ptr = @ptrCast(&c_void, old_mem.ptr); |
| 29 | if (c.realloc(old_ptr, new_size)) |buf| { | ||
| 30 | return @ptrCast(&u8, buf)[0..new_size]; | ||
| 31 | } else if (new_size <= old_mem.len) { | ||
| 28 | return old_mem[0..new_size]; | 32 | return old_mem[0..new_size]; |
| 29 | } else { | 33 | } else { |
| 30 | const old_ptr = @ptrCast(&c_void, old_mem.ptr); | 34 | return error.OutOfMemory; |
| 31 | if (c.realloc(old_ptr, usize(new_size))) |buf| { | ||
| 32 | return @ptrCast(&u8, buf)[0..new_size]; | ||
| 33 | } else { | ||
| 34 | return error.OutOfMemory; | ||
| 35 | } | ||
| 36 | } | 35 | } |
| 37 | } | 36 | } |
| 38 | 37 |
std/os/index.zig+33| ... | @@ -1543,6 +1543,39 @@ pub fn openSelfExe() -> %io.File { | ... | @@ -1543,6 +1543,39 @@ pub fn openSelfExe() -> %io.File { |
| 1543 | } | 1543 | } |
| 1544 | } | 1544 | } |
| 1545 | 1545 | ||
| 1546 | /// Get the directory path that contains the current executable. | ||
| 1547 | /// Caller owns returned memory. | ||
| 1548 | pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 { | ||
| 1549 | switch (builtin.os) { | ||
| 1550 | Os.linux => { | ||
| 1551 | // If the currently executing binary has been deleted, | ||
| 1552 | // the file path looks something like `/a/b/c/exe (deleted)` | ||
| 1553 | // This path cannot be opened, but it's valid for determining the directory | ||
| 1554 | // the executable was in when it was run. | ||
| 1555 | const full_exe_path = %return readLink(allocator, "/proc/self/exe"); | ||
| 1556 | %defer allocator.free(full_exe_path); | ||
| 1557 | const dir = path.dirname(full_exe_path); | ||
| 1558 | return allocator.shrink(u8, full_exe_path, dir.len); | ||
| 1559 | }, | ||
| 1560 | Os.windows => { | ||
| 1561 | @panic("TODO windows std.os.selfExeDirPath"); | ||
| 1562 | //buf_resize(out_path, 256); | ||
| 1563 | //for (;;) { | ||
| 1564 | // DWORD copied_amt = GetModuleFileName(nullptr, buf_ptr(out_path), buf_len(out_path)); | ||
| 1565 | // if (copied_amt <= 0) { | ||
| 1566 | // return ErrorFileNotFound; | ||
| 1567 | // } | ||
| 1568 | // if (copied_amt < buf_len(out_path)) { | ||
| 1569 | // buf_resize(out_path, copied_amt); | ||
| 1570 | // return 0; | ||
| 1571 | // } | ||
| 1572 | // buf_resize(out_path, buf_len(out_path) * 2); | ||
| 1573 | //} | ||
| 1574 | }, | ||
| 1575 | else => @compileError("unimplemented: std.os.selfExeDirPath for " ++ @tagName(builtin.os)), | ||
| 1576 | } | ||
| 1577 | } | ||
| 1578 | |||
| 1546 | pub fn isTty(handle: FileHandle) -> bool { | 1579 | pub fn isTty(handle: FileHandle) -> bool { |
| 1547 | if (is_windows) { | 1580 | if (is_windows) { |
| 1548 | return windows_util.windowsIsTty(handle); | 1581 | return windows_util.windowsIsTty(handle); |