| author | |
| committer | |
| log | 1c6000d0474a89bbc48897fc2f2f2d7331e2fe4e |
| tree | fa74f0cd662d01d03d0cbd3a1459404796414d79 |
| parent | 72fb2443e0e5dd0c8c3a0265428832796b4ff548 |
* add std.buf_map.BufMap
* add std.buf_set.BufSet
* add std.mem.split
* zig build system improvements (See #204)
- automatically parses NIX_CFLAGS_COMPILE and NIX_LDFLAGS
- add builder.addCIncludePath
- add builder.addRPath
- add builder.addLibPath
- add exe.linkLibrary9 files changed, 297 insertions(+), 91 deletions(-)
CMakeLists.txt+2| ... | @@ -204,6 +204,8 @@ install(TARGETS zig DESTINATION bin) | ... | @@ -204,6 +204,8 @@ install(TARGETS zig DESTINATION bin) |
| 204 | 204 | ||
| 205 | install(FILES ${C_HEADERS} DESTINATION ${C_HEADERS_DEST}) | 205 | install(FILES ${C_HEADERS} DESTINATION ${C_HEADERS_DEST}) |
| 206 | 206 | ||
| 207 | install(FILES "${CMAKE_SOURCE_DIR}/std/buf_map.zig" DESTINATION "${ZIG_STD_DEST}") | ||
| 208 | install(FILES "${CMAKE_SOURCE_DIR}/std/buf_set.zig" DESTINATION "${ZIG_STD_DEST}") | ||
| 207 | install(FILES "${CMAKE_SOURCE_DIR}/std/build.zig" DESTINATION "${ZIG_STD_DEST}") | 209 | install(FILES "${CMAKE_SOURCE_DIR}/std/build.zig" DESTINATION "${ZIG_STD_DEST}") |
| 208 | install(FILES "${CMAKE_SOURCE_DIR}/std/c/darwin.zig" DESTINATION "${ZIG_STD_DEST}/c") | 210 | install(FILES "${CMAKE_SOURCE_DIR}/std/c/darwin.zig" DESTINATION "${ZIG_STD_DEST}/c") |
| 209 | install(FILES "${CMAKE_SOURCE_DIR}/std/c/index.zig" DESTINATION "${ZIG_STD_DEST}/c") | 211 | install(FILES "${CMAKE_SOURCE_DIR}/std/c/index.zig" DESTINATION "${ZIG_STD_DEST}/c") |
src/main.cpp+1-1| ... | @@ -195,7 +195,7 @@ int main(int argc, char **argv) { | ... | @@ -195,7 +195,7 @@ int main(int argc, char **argv) { |
| 195 | fprintf(stderr, "\nBuild failed. Use the following command to reproduce the failure:\n"); | 195 | fprintf(stderr, "\nBuild failed. Use the following command to reproduce the failure:\n"); |
| 196 | fprintf(stderr, "./build"); | 196 | fprintf(stderr, "./build"); |
| 197 | for (size_t i = 0; i < args.length; i += 1) { | 197 | for (size_t i = 0; i < args.length; i += 1) { |
| 198 | fprintf(stderr, " \"%s\"", args.at(i)); | 198 | fprintf(stderr, " %s", args.at(i)); |
| 199 | } | 199 | } |
| 200 | fprintf(stderr, "\n"); | 200 | fprintf(stderr, "\n"); |
| 201 | } | 201 | } |
std/buf_map.zig created+71| ... | @@ -0,0 +1,71 @@ | ||
| 1 | const HashMap = @import("hash_map.zig").HashMap; | ||
| 2 | const mem = @import("mem.zig"); | ||
| 3 | const Allocator = mem.Allocator; | ||
| 4 | |||
| 5 | /// BufMap copies keys and values before they go into the map, and | ||
| 6 | /// frees them when they get removed. | ||
| 7 | pub const BufMap = struct { | ||
| 8 | hash_map: BufMapHashMap, | ||
| 9 | |||
| 10 | const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8); | ||
| 11 | |||
| 12 | pub fn init(allocator: &Allocator) -> BufMap { | ||
| 13 | var self = BufMap { | ||
| 14 | .hash_map = undefined, | ||
| 15 | }; | ||
| 16 | self.hash_map.init(allocator); | ||
| 17 | return self; | ||
| 18 | } | ||
| 19 | |||
| 20 | pub fn deinit(self: &BufMap) { | ||
| 21 | var it = self.hash_map.entryIterator(); | ||
| 22 | while (true) { | ||
| 23 | const entry = it.next() ?? break; | ||
| 24 | self.free(entry.key); | ||
| 25 | self.free(entry.value); | ||
| 26 | } | ||
| 27 | |||
| 28 | self.hash_map.deinit(); | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn set(self: &BufMap, key: []const u8, value: []const u8) -> %void { | ||
| 32 | if (const entry ?= self.hash_map.get(key)) { | ||
| 33 | const value_copy = %return self.copy(value); | ||
| 34 | %defer self.free(value_copy); | ||
| 35 | %return self.hash_map.put(key, value_copy); | ||
| 36 | self.free(entry.value); | ||
| 37 | } else { | ||
| 38 | const key_copy = %return self.copy(key); | ||
| 39 | %defer self.free(key_copy); | ||
| 40 | const value_copy = %return self.copy(value); | ||
| 41 | %defer self.free(value_copy); | ||
| 42 | %return self.hash_map.put(key_copy, value_copy); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | pub fn delete(self: &BufMap, key: []const u8) { | ||
| 47 | const entry = self.hash_map.remove(key) ?? return; | ||
| 48 | self.free(entry.key); | ||
| 49 | self.free(entry.value); | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn count(self: &const BufMap) -> usize { | ||
| 53 | return self.hash_map.size; | ||
| 54 | } | ||
| 55 | |||
| 56 | pub fn iterator(self: &const BufMap) -> BufMapHashMap.Iterator { | ||
| 57 | return self.hash_map.entryIterator(); | ||
| 58 | } | ||
| 59 | |||
| 60 | fn free(self: &BufMap, value: []const u8) { | ||
| 61 | // remove the const | ||
| 62 | const mut_value = @ptrcast(&u8, value.ptr)[0...value.len]; | ||
| 63 | self.hash_map.allocator.free(mut_value); | ||
| 64 | } | ||
| 65 | |||
| 66 | fn copy(self: &BufMap, value: []const u8) -> %[]const u8 { | ||
| 67 | const result = %return self.hash_map.allocator.alloc(u8, value.len); | ||
| 68 | mem.copy(u8, result, value); | ||
| 69 | return result; | ||
| 70 | } | ||
| 71 | }; | ||
std/buf_set.zig created+61| ... | @@ -0,0 +1,61 @@ | ||
| 1 | const HashMap = @import("hash_map.zig").HashMap; | ||
| 2 | const mem = @import("mem.zig"); | ||
| 3 | const Allocator = mem.Allocator; | ||
| 4 | |||
| 5 | pub const BufSet = struct { | ||
| 6 | hash_map: BufSetHashMap, | ||
| 7 | |||
| 8 | const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); | ||
| 9 | |||
| 10 | pub fn init(allocator: &Allocator) -> BufSet { | ||
| 11 | var self = BufSet { | ||
| 12 | .hash_map = undefined, | ||
| 13 | }; | ||
| 14 | self.hash_map.init(allocator); | ||
| 15 | return self; | ||
| 16 | } | ||
| 17 | |||
| 18 | pub fn deinit(self: &BufSet) { | ||
| 19 | var it = self.hash_map.entryIterator(); | ||
| 20 | while (true) { | ||
| 21 | const entry = it.next() ?? break; | ||
| 22 | self.free(entry.key); | ||
| 23 | } | ||
| 24 | |||
| 25 | self.hash_map.deinit(); | ||
| 26 | } | ||
| 27 | |||
| 28 | pub fn put(self: &BufSet, key: []const u8) -> %void { | ||
| 29 | if (self.hash_map.get(key) == null) { | ||
| 30 | const key_copy = %return self.copy(key); | ||
| 31 | %defer self.free(key_copy); | ||
| 32 | %return self.hash_map.put(key_copy, {}); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | pub fn delete(self: &BufSet, key: []const u8) { | ||
| 37 | const entry = self.hash_map.remove(key) ?? return; | ||
| 38 | self.free(entry.key); | ||
| 39 | } | ||
| 40 | |||
| 41 | pub fn count(self: &const BufSet) -> usize { | ||
| 42 | return self.hash_map.size; | ||
| 43 | } | ||
| 44 | |||
| 45 | pub fn iterator(self: &const BufSet) -> BufSetHashMap.Iterator { | ||
| 46 | return self.hash_map.entryIterator(); | ||
| 47 | } | ||
| 48 | |||
| 49 | fn free(self: &BufSet, value: []const u8) { | ||
| 50 | // remove the const | ||
| 51 | const mut_value = @ptrcast(&u8, value.ptr)[0...value.len]; | ||
| 52 | self.hash_map.allocator.free(mut_value); | ||
| 53 | } | ||
| 54 | |||
| 55 | fn copy(self: &BufSet, value: []const u8) -> %[]const u8 { | ||
| 56 | const result = %return self.hash_map.allocator.alloc(u8, value.len); | ||
| 57 | mem.copy(u8, result, value); | ||
| 58 | return result; | ||
| 59 | } | ||
| 60 | }; | ||
| 61 | |||
std/build.zig+110-5| ... | @@ -6,6 +6,7 @@ const Allocator = @import("mem.zig").Allocator; | ... | @@ -6,6 +6,7 @@ const Allocator = @import("mem.zig").Allocator; |
| 6 | const os = @import("os/index.zig"); | 6 | const os = @import("os/index.zig"); |
| 7 | const StdIo = os.ChildProcess.StdIo; | 7 | const StdIo = os.ChildProcess.StdIo; |
| 8 | const Term = os.ChildProcess.Term; | 8 | const Term = os.ChildProcess.Term; |
| 9 | const BufSet = @import("buf_set.zig").BufSet; | ||
| 9 | 10 | ||
| 10 | error ExtraArg; | 11 | error ExtraArg; |
| 11 | error UncleanExit; | 12 | error UncleanExit; |
| ... | @@ -14,13 +15,28 @@ pub const Builder = struct { | ... | @@ -14,13 +15,28 @@ pub const Builder = struct { |
| 14 | zig_exe: []const u8, | 15 | zig_exe: []const u8, |
| 15 | allocator: &Allocator, | 16 | allocator: &Allocator, |
| 16 | exe_list: List(&Exe), | 17 | exe_list: List(&Exe), |
| 18 | lib_paths: List([]const u8), | ||
| 19 | include_paths: List([]const u8), | ||
| 20 | rpaths: List([]const u8), | ||
| 17 | 21 | ||
| 18 | pub fn init(zig_exe: []const u8, allocator: &Allocator) -> Builder { | 22 | pub fn init(zig_exe: []const u8, allocator: &Allocator) -> Builder { |
| 19 | Builder { | 23 | var self = Builder { |
| 20 | .zig_exe = zig_exe, | 24 | .zig_exe = zig_exe, |
| 21 | .allocator = allocator, | 25 | .allocator = allocator, |
| 22 | .exe_list = List(&Exe).init(allocator), | 26 | .exe_list = List(&Exe).init(allocator), |
| 23 | } | 27 | .lib_paths = List([]const u8).init(allocator), |
| 28 | .include_paths = List([]const u8).init(allocator), | ||
| 29 | .rpaths = List([]const u8).init(allocator), | ||
| 30 | }; | ||
| 31 | self.processNixOSEnvVars(); | ||
| 32 | return self; | ||
| 33 | } | ||
| 34 | |||
| 35 | pub fn deinit(self: &Builder) { | ||
| 36 | self.exe_list.deinit(); | ||
| 37 | self.lib_paths.deinit(); | ||
| 38 | self.include_paths.deinit(); | ||
| 39 | self.rpaths.deinit(); | ||
| 24 | } | 40 | } |
| 25 | 41 | ||
| 26 | pub fn addExe(self: &Builder, root_src: []const u8, name: []const u8) -> &Exe { | 42 | pub fn addExe(self: &Builder, root_src: []const u8, name: []const u8) -> &Exe { |
| ... | @@ -34,11 +50,24 @@ pub const Builder = struct { | ... | @@ -34,11 +50,24 @@ pub const Builder = struct { |
| 34 | .name = name, | 50 | .name = name, |
| 35 | .target = Target.Native, | 51 | .target = Target.Native, |
| 36 | .linker_script = LinkerScript.None, | 52 | .linker_script = LinkerScript.None, |
| 53 | .link_libs = BufSet.init(self.allocator), | ||
| 37 | }; | 54 | }; |
| 38 | %return self.exe_list.append(exe); | 55 | %return self.exe_list.append(exe); |
| 39 | return exe; | 56 | return exe; |
| 40 | } | 57 | } |
| 41 | 58 | ||
| 59 | pub fn addCIncludePath(self: &Builder, path: []const u8) { | ||
| 60 | %%self.include_paths.append(path); | ||
| 61 | } | ||
| 62 | |||
| 63 | pub fn addRPath(self: &Builder, path: []const u8) { | ||
| 64 | %%self.rpaths.append(path); | ||
| 65 | } | ||
| 66 | |||
| 67 | pub fn addLibPath(self: &Builder, path: []const u8) { | ||
| 68 | %%self.lib_paths.append(path); | ||
| 69 | } | ||
| 70 | |||
| 42 | pub fn make(self: &Builder, leftover_arg_index: usize) -> %void { | 71 | pub fn make(self: &Builder, leftover_arg_index: usize) -> %void { |
| 43 | var env_map = %return os.getEnvMap(self.allocator); | 72 | var env_map = %return os.getEnvMap(self.allocator); |
| 44 | 73 | ||
| ... | @@ -96,18 +125,85 @@ pub const Builder = struct { | ... | @@ -96,18 +125,85 @@ pub const Builder = struct { |
| 96 | }, | 125 | }, |
| 97 | } | 126 | } |
| 98 | 127 | ||
| 99 | printInvocation(self.zig_exe, zig_args); | 128 | { |
| 129 | var it = exe.link_libs.iterator(); | ||
| 130 | while (true) { | ||
| 131 | const entry = it.next() ?? break; | ||
| 132 | %return zig_args.append("--library"[0...]); // TODO issue #296 | ||
| 133 | %return zig_args.append(entry.key); | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | for (self.include_paths.toSliceConst()) |include_path| { | ||
| 138 | %return zig_args.append("-isystem"[0...]); // TODO issue #296 | ||
| 139 | %return zig_args.append(include_path); | ||
| 140 | } | ||
| 141 | |||
| 142 | for (self.rpaths.toSliceConst()) |rpath| { | ||
| 143 | %return zig_args.append("-rpath"[0...]); // TODO issue #296 | ||
| 144 | %return zig_args.append(rpath); | ||
| 145 | } | ||
| 146 | |||
| 147 | for (self.lib_paths.toSliceConst()) |lib_path| { | ||
| 148 | %return zig_args.append("--library-path"[0...]); // TODO issue #296 | ||
| 149 | %return zig_args.append(lib_path); | ||
| 150 | } | ||
| 151 | |||
| 100 | // TODO issue #301 | 152 | // TODO issue #301 |
| 101 | var child = %return os.ChildProcess.spawn(self.zig_exe, zig_args.toSliceConst(), &env_map, | 153 | var child = %return os.ChildProcess.spawn(self.zig_exe, zig_args.toSliceConst(), &env_map, |
| 102 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, self.allocator); | 154 | StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, self.allocator); |
| 103 | const term = %return child.wait(); | 155 | const term = %return child.wait(); |
| 104 | switch (term) { | 156 | const exe_result = switch (term) { |
| 105 | Term.Clean => |code| { | 157 | Term.Clean => |code| { |
| 106 | if (code != 0) { | 158 | if (code != 0) { |
| 159 | %%io.stderr.printf("\nCompile failed with code {}. To reproduce:\n", code); | ||
| 160 | printInvocation(self.zig_exe, zig_args); | ||
| 107 | return error.UncleanExit; | 161 | return error.UncleanExit; |
| 108 | } | 162 | } |
| 109 | }, | 163 | }, |
| 110 | else => return error.UncleanExit, | 164 | else => { |
| 165 | %%io.stderr.printf("\nCompile crashed. To reproduce:\n"); | ||
| 166 | printInvocation(self.zig_exe, zig_args); | ||
| 167 | return error.UncleanExit; | ||
| 168 | }, | ||
| 169 | }; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | fn processNixOSEnvVars(self: &Builder) { | ||
| 174 | if (const nix_cflags_compile ?= os.getEnv("NIX_CFLAGS_COMPILE")) { | ||
| 175 | var it = mem.split(nix_cflags_compile, ' '); | ||
| 176 | while (true) { | ||
| 177 | const word = it.next() ?? break; | ||
| 178 | if (mem.eql(u8, word, "-isystem")) { | ||
| 179 | const include_path = it.next() ?? { | ||
| 180 | %%io.stderr.printf("Expected argument after -isystem in NIX_CFLAGS_COMPILE\n"); | ||
| 181 | break; | ||
| 182 | }; | ||
| 183 | self.addCIncludePath(include_path); | ||
| 184 | } else { | ||
| 185 | %%io.stderr.printf("Unrecognized C flag from NIX_CFLAGS_COMPILE: {}\n", word); | ||
| 186 | break; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | } | ||
| 190 | if (const nix_ldflags ?= os.getEnv("NIX_LDFLAGS")) { | ||
| 191 | var it = mem.split(nix_ldflags, ' '); | ||
| 192 | while (true) { | ||
| 193 | const word = it.next() ?? break; | ||
| 194 | if (mem.eql(u8, word, "-rpath")) { | ||
| 195 | const rpath = it.next() ?? { | ||
| 196 | %%io.stderr.printf("Expected argument after -rpath in NIX_LDFLAGS\n"); | ||
| 197 | break; | ||
| 198 | }; | ||
| 199 | self.addRPath(rpath); | ||
| 200 | } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') { | ||
| 201 | const lib_path = word[2...]; | ||
| 202 | self.addLibPath(lib_path); | ||
| 203 | } else { | ||
| 204 | %%io.stderr.printf("Unrecognized C flag from NIX_LDFLAGS: {}\n", word); | ||
| 205 | break; | ||
| 206 | } | ||
| 111 | } | 207 | } |
| 112 | } | 208 | } |
| 113 | } | 209 | } |
| ... | @@ -135,6 +231,11 @@ const Exe = struct { | ... | @@ -135,6 +231,11 @@ const Exe = struct { |
| 135 | name: []const u8, | 231 | name: []const u8, |
| 136 | target: Target, | 232 | target: Target, |
| 137 | linker_script: LinkerScript, | 233 | linker_script: LinkerScript, |
| 234 | link_libs: BufSet, | ||
| 235 | |||
| 236 | fn deinit(self: &Exe) { | ||
| 237 | self.link_libs.deinit(); | ||
| 238 | } | ||
| 138 | 239 | ||
| 139 | fn setTarget(self: &Exe, target_arch: Arch, target_os: Os, target_environ: Environ) { | 240 | fn setTarget(self: &Exe, target_arch: Arch, target_os: Os, target_environ: Environ) { |
| 140 | self.target = Target.Cross { | 241 | self.target = Target.Cross { |
| ... | @@ -155,6 +256,10 @@ const Exe = struct { | ... | @@ -155,6 +256,10 @@ const Exe = struct { |
| 155 | fn setLinkerScriptPath(self: &Exe, path: []const u8) { | 256 | fn setLinkerScriptPath(self: &Exe, path: []const u8) { |
| 156 | self.linker_script = LinkerScript.Path { path }; | 257 | self.linker_script = LinkerScript.Path { path }; |
| 157 | } | 258 | } |
| 259 | |||
| 260 | fn linkLibrary(self: &Exe, name: []const u8) { | ||
| 261 | %%self.link_libs.put(name); | ||
| 262 | } | ||
| 158 | }; | 263 | }; |
| 159 | 264 | ||
| 160 | fn handleErr(err: error) -> noreturn { | 265 | fn handleErr(err: error) -> noreturn { |
std/mem.zig+44| ... | @@ -176,6 +176,49 @@ pub fn writeInt(buf: []u8, value: var, big_endian: bool) { | ... | @@ -176,6 +176,49 @@ pub fn writeInt(buf: []u8, value: var, big_endian: bool) { |
| 176 | assert(bits == 0); | 176 | assert(bits == 0); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | |||
| 180 | pub fn hash_slice_u8(k: []const u8) -> u32 { | ||
| 181 | // FNV 32-bit hash | ||
| 182 | var h: u32 = 2166136261; | ||
| 183 | for (k) |b| { | ||
| 184 | h = (h ^ b) *% 16777619; | ||
| 185 | } | ||
| 186 | return h; | ||
| 187 | } | ||
| 188 | |||
| 189 | pub fn eql_slice_u8(a: []const u8, b: []const u8) -> bool { | ||
| 190 | return eql(u8, a, b); | ||
| 191 | } | ||
| 192 | |||
| 193 | pub fn split(s: []const u8, c: u8) -> SplitIterator { | ||
| 194 | SplitIterator { | ||
| 195 | .index = 0, | ||
| 196 | .s = s, | ||
| 197 | .c = c, | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | const SplitIterator = struct { | ||
| 202 | s: []const u8, | ||
| 203 | c: u8, | ||
| 204 | index: usize, | ||
| 205 | |||
| 206 | pub fn next(self: &SplitIterator) -> ?[]const u8 { | ||
| 207 | // move to beginning of token | ||
| 208 | while (self.index < self.s.len and self.s[self.index] == self.c; self.index += 1) {} | ||
| 209 | const start = self.index; | ||
| 210 | if (start == self.s.len) { | ||
| 211 | return null; | ||
| 212 | } | ||
| 213 | |||
| 214 | // move to end of token | ||
| 215 | while (self.index < self.s.len and self.s[self.index] != self.c; self.index += 1) {} | ||
| 216 | const end = self.index; | ||
| 217 | |||
| 218 | return self.s[start...end]; | ||
| 219 | } | ||
| 220 | }; | ||
| 221 | |||
| 179 | test "testStringEquality" { | 222 | test "testStringEquality" { |
| 180 | assert(eql(u8, "abcd", "abcd")); | 223 | assert(eql(u8, "abcd", "abcd")); |
| 181 | assert(!eql(u8, "abcdef", "abZdef")); | 224 | assert(!eql(u8, "abcdef", "abZdef")); |
| ... | @@ -223,3 +266,4 @@ fn testWriteIntImpl() { | ... | @@ -223,3 +266,4 @@ fn testWriteIntImpl() { |
| 223 | writeInt(bytes[0...], u16(0x1234), false); | 266 | writeInt(bytes[0...], u16(0x1234), false); |
| 224 | assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 })); | 267 | assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 })); |
| 225 | } | 268 | } |
| 269 |
std/os/child_process.zig+3-2| ... | @@ -6,6 +6,7 @@ const Allocator = mem.Allocator; | ... | @@ -6,6 +6,7 @@ const Allocator = mem.Allocator; |
| 6 | const errno = @import("errno.zig"); | 6 | const errno = @import("errno.zig"); |
| 7 | const debug = @import("../debug.zig"); | 7 | const debug = @import("../debug.zig"); |
| 8 | const assert = debug.assert; | 8 | const assert = debug.assert; |
| 9 | const BufMap = @import("../buf_map.zig").BufMap; | ||
| 9 | 10 | ||
| 10 | pub const ChildProcess = struct { | 11 | pub const ChildProcess = struct { |
| 11 | pid: i32, | 12 | pid: i32, |
| ... | @@ -29,7 +30,7 @@ pub const ChildProcess = struct { | ... | @@ -29,7 +30,7 @@ pub const ChildProcess = struct { |
| 29 | Close, | 30 | Close, |
| 30 | }; | 31 | }; |
| 31 | 32 | ||
| 32 | pub fn spawn(exe_path: []const u8, args: []const []const u8, env_map: &const os.EnvMap, | 33 | pub fn spawn(exe_path: []const u8, args: []const []const u8, env_map: &const BufMap, |
| 33 | stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess | 34 | stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess |
| 34 | { | 35 | { |
| 35 | switch (@compileVar("os")) { | 36 | switch (@compileVar("os")) { |
| ... | @@ -96,7 +97,7 @@ pub const ChildProcess = struct { | ... | @@ -96,7 +97,7 @@ pub const ChildProcess = struct { |
| 96 | }; | 97 | }; |
| 97 | } | 98 | } |
| 98 | 99 | ||
| 99 | fn spawnPosix(exe_path: []const u8, args: []const []const u8, env_map: &const os.EnvMap, | 100 | fn spawnPosix(exe_path: []const u8, args: []const []const u8, env_map: &const BufMap, |
| 100 | stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess | 101 | stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess |
| 101 | { | 102 | { |
| 102 | // TODO issue #295 | 103 | // TODO issue #295 |
std/os/index.zig+4-83| ... | @@ -21,7 +21,7 @@ const c = @import("../c/index.zig"); | ... | @@ -21,7 +21,7 @@ const c = @import("../c/index.zig"); |
| 21 | const mem = @import("../mem.zig"); | 21 | const mem = @import("../mem.zig"); |
| 22 | const Allocator = mem.Allocator; | 22 | const Allocator = mem.Allocator; |
| 23 | 23 | ||
| 24 | const HashMap = @import("../hash_map.zig").HashMap; | 24 | const BufMap = @import("../buf_map.zig").BufMap; |
| 25 | const cstr = @import("../cstr.zig"); | 25 | const cstr = @import("../cstr.zig"); |
| 26 | 26 | ||
| 27 | error Unexpected; | 27 | error Unexpected; |
| ... | @@ -204,7 +204,7 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { | ... | @@ -204,7 +204,7 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { |
| 204 | /// It must also convert to KEY=VALUE\0 format for environment variables, and include null | 204 | /// It must also convert to KEY=VALUE\0 format for environment variables, and include null |
| 205 | /// pointers after the args and after the environment variables. | 205 | /// pointers after the args and after the environment variables. |
| 206 | /// Also make the first arg equal to path. | 206 | /// Also make the first arg equal to path. |
| 207 | pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const EnvMap, | 207 | pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const BufMap, |
| 208 | allocator: &Allocator) -> %usize | 208 | allocator: &Allocator) -> %usize |
| 209 | { | 209 | { |
| 210 | const path_buf = %return allocator.alloc(u8, path.len + 1); | 210 | const path_buf = %return allocator.alloc(u8, path.len + 1); |
| ... | @@ -271,87 +271,8 @@ pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const E | ... | @@ -271,87 +271,8 @@ pub fn posixExecve(path: []const u8, argv: []const []const u8, env_map: &const E |
| 271 | 271 | ||
| 272 | pub var environ_raw: []&u8 = undefined; | 272 | pub var environ_raw: []&u8 = undefined; |
| 273 | 273 | ||
| 274 | pub const EnvMap = struct { | 274 | pub fn getEnvMap(allocator: &Allocator) -> %BufMap { |
| 275 | hash_map: EnvHashMap, | 275 | var result = BufMap.init(allocator); |
| 276 | |||
| 277 | const EnvHashMap = HashMap([]const u8, []const u8, hash_slice_u8, eql_slice_u8); | ||
| 278 | |||
| 279 | pub fn init(allocator: &Allocator) -> EnvMap { | ||
| 280 | var self = EnvMap { | ||
| 281 | .hash_map = undefined, | ||
| 282 | }; | ||
| 283 | self.hash_map.init(allocator); | ||
| 284 | return self; | ||
| 285 | } | ||
| 286 | |||
| 287 | pub fn deinit(self: &EnvMap) { | ||
| 288 | var it = self.hash_map.entryIterator(); | ||
| 289 | while (true) { | ||
| 290 | const entry = it.next() ?? break; | ||
| 291 | self.free(entry.key); | ||
| 292 | self.free(entry.value); | ||
| 293 | } | ||
| 294 | |||
| 295 | self.hash_map.deinit(); | ||
| 296 | } | ||
| 297 | |||
| 298 | pub fn set(self: &EnvMap, key: []const u8, value: []const u8) -> %void { | ||
| 299 | if (const entry ?= self.hash_map.get(key)) { | ||
| 300 | const value_copy = %return self.copy(value); | ||
| 301 | %defer self.free(value_copy); | ||
| 302 | %return self.hash_map.put(key, value_copy); | ||
| 303 | self.free(entry.value); | ||
| 304 | } else { | ||
| 305 | const key_copy = %return self.copy(key); | ||
| 306 | %defer self.free(key_copy); | ||
| 307 | const value_copy = %return self.copy(value); | ||
| 308 | %defer self.free(value_copy); | ||
| 309 | %return self.hash_map.put(key_copy, value_copy); | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | pub fn delete(self: &EnvMap, key: []const u8) { | ||
| 314 | const entry = self.hash_map.remove(key) ?? return; | ||
| 315 | self.free(entry.key); | ||
| 316 | self.free(entry.value); | ||
| 317 | } | ||
| 318 | |||
| 319 | pub fn count(self: &const EnvMap) -> usize { | ||
| 320 | return self.hash_map.size; | ||
| 321 | } | ||
| 322 | |||
| 323 | pub fn iterator(self: &const EnvMap) -> EnvHashMap.Iterator { | ||
| 324 | return self.hash_map.entryIterator(); | ||
| 325 | } | ||
| 326 | |||
| 327 | fn free(self: &EnvMap, value: []const u8) { | ||
| 328 | // remove the const | ||
| 329 | const mut_value = @ptrcast(&u8, value.ptr)[0...value.len]; | ||
| 330 | self.hash_map.allocator.free(mut_value); | ||
| 331 | } | ||
| 332 | |||
| 333 | fn copy(self: &EnvMap, value: []const u8) -> %[]const u8 { | ||
| 334 | const result = %return self.hash_map.allocator.alloc(u8, value.len); | ||
| 335 | mem.copy(u8, result, value); | ||
| 336 | return result; | ||
| 337 | } | ||
| 338 | |||
| 339 | fn hash_slice_u8(k: []const u8) -> u32 { | ||
| 340 | // FNV 32-bit hash | ||
| 341 | var h: u32 = 2166136261; | ||
| 342 | for (k) |b| { | ||
| 343 | h = (h ^ b) *% 16777619; | ||
| 344 | } | ||
| 345 | return h; | ||
| 346 | } | ||
| 347 | |||
| 348 | fn eql_slice_u8(a: []const u8, b: []const u8) -> bool { | ||
| 349 | return mem.eql(u8, a, b); | ||
| 350 | } | ||
| 351 | }; | ||
| 352 | |||
| 353 | pub fn getEnvMap(allocator: &Allocator) -> %EnvMap { | ||
| 354 | var result = EnvMap.init(allocator); | ||
| 355 | %defer result.deinit(); | 276 | %defer result.deinit(); |
| 356 | 277 | ||
| 357 | for (environ_raw) |ptr| { | 278 | for (environ_raw) |ptr| { |
std/special/build_runner.zig+1| ... | @@ -20,6 +20,7 @@ pub fn main() -> %void { | ... | @@ -20,6 +20,7 @@ pub fn main() -> %void { |
| 20 | defer inc_allocator.deinit(); | 20 | defer inc_allocator.deinit(); |
| 21 | 21 | ||
| 22 | var builder = Builder.init(zig_exe, &inc_allocator.allocator); | 22 | var builder = Builder.init(zig_exe, &inc_allocator.allocator); |
| 23 | defer builder.deinit(); | ||
| 23 | root.build(&builder); | 24 | root.build(&builder); |
| 24 | %return builder.make(leftover_arg_index); | 25 | %return builder.make(leftover_arg_index); |
| 25 | } | 26 | } |