authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-23 21:21:32-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-23 21:21:32-05:00
log8b716f941dbd43936a994a008aec9cd21d0b08f2
treec9ad8a52ffeb52b9b7ca412b806d7c0b6213d6af
parentfe660462837231353b846bf398637ca84f67bfc9
parent87ba004d461f90032660a6f89479caee718bb378

Merge branch 'master' into llvm6


6 files changed, 311 insertions(+), 116 deletions(-)

build.zig+16-5
......@@ -80,9 +80,12 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) {
8080 for (dep.libdirs.toSliceConst()) |lib_dir| {
8181 lib_exe_obj.addLibPath(lib_dir);
8282 }
83 for (dep.libs.toSliceConst()) |lib| {
83 for (dep.system_libs.toSliceConst()) |lib| {
8484 lib_exe_obj.linkSystemLibrary(lib);
8585 }
86 for (dep.libs.toSliceConst()) |lib| {
87 lib_exe_obj.addObjectFile(lib);
88 }
8689 for (dep.includes.toSliceConst()) |include_path| {
8790 lib_exe_obj.addIncludeDir(include_path);
8891 }
......@@ -91,6 +94,7 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) {
9194const LibraryDep = struct {
9295 libdirs: ArrayList([]const u8),
9396 libs: ArrayList([]const u8),
97 system_libs: ArrayList([]const u8),
9498 includes: ArrayList([]const u8),
9599};
96100
......@@ -98,11 +102,11 @@ fn findLLVM(b: &Builder) -> ?LibraryDep {
98102 const llvm_config_exe = b.findProgram(
99103 [][]const u8{"llvm-config-5.0", "llvm-config"},
100104 [][]const u8{
101 "/usr/local/opt/llvm@5/bin",
102 "/mingw64/bin",
105 "C:/Libraries/llvm-5.0.0/bin",
103106 "/c/msys64/mingw64/bin",
104107 "c:/msys64/mingw64/bin",
105 "C:/Libraries/llvm-5.0.0/bin",
108 "/usr/local/opt/llvm@5/bin",
109 "/mingw64/bin",
106110 }) %% |err|
107111 {
108112 warn("unable to find llvm-config: {}\n", err);
......@@ -114,6 +118,7 @@ fn findLLVM(b: &Builder) -> ?LibraryDep {
114118
115119 var result = LibraryDep {
116120 .libs = ArrayList([]const u8).init(b.allocator),
121 .system_libs = ArrayList([]const u8).init(b.allocator),
117122 .includes = ArrayList([]const u8).init(b.allocator),
118123 .libdirs = ArrayList([]const u8).init(b.allocator),
119124 };
......@@ -121,7 +126,13 @@ fn findLLVM(b: &Builder) -> ?LibraryDep {
121126 var it = mem.split(libs_output, " \n");
122127 while (it.next()) |lib_arg| {
123128 if (mem.startsWith(u8, lib_arg, "-l")) {
124 %%result.libs.append(lib_arg[2..]);
129 %%result.system_libs.append(lib_arg[2..]);
130 } else {
131 if (os.path.isAbsolute(lib_arg)) {
132 %%result.libs.append(lib_arg);
133 } else {
134 %%result.system_libs.append(lib_arg);
135 }
125136 }
126137 }
127138 }
src/codegen.cpp+3-1
......@@ -590,8 +590,10 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
590590 bool is_optimized = g->build_mode != BuildModeDebug;
591591 bool is_internal_linkage = (fn_table_entry->body_node != nullptr &&
592592 fn_table_entry->export_list.length == 0);
593 ZigLLVMDIScope *fn_di_scope = get_di_scope(g, scope->parent);
594 assert(fn_di_scope != nullptr);
593595 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
594 get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "",
596 fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
595597 import->di_file, line_number,
596598 fn_table_entry->type_entry->di_type, is_internal_linkage,
597599 is_definition, scope_line, flags, is_optimized, nullptr);
src/ir.cpp+2
......@@ -14051,6 +14051,8 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc
1405114051 child_import->package = new_anonymous_package();
1405214052 child_import->package->package_table.put(buf_create_from_str("builtin"), ira->codegen->compile_var_package);
1405314053 child_import->package->package_table.put(buf_create_from_str("std"), ira->codegen->std_package);
14054 child_import->di_file = ZigLLVMCreateFile(ira->codegen->dbuilder,
14055 buf_ptr(buf_create_from_str("cimport.h")), buf_ptr(buf_create_from_str(".")));
1405414056
1405514057 ZigList<ErrorMsg *> errors = {0};
1405614058
std/build.zig+21
......@@ -47,6 +47,7 @@ pub const Builder = struct {
4747 env_map: BufMap,
4848 top_level_steps: ArrayList(&TopLevelStep),
4949 prefix: []const u8,
50 search_prefixes: ArrayList([]const u8),
5051 lib_dir: []const u8,
5152 exe_dir: []const u8,
5253 installed_files: ArrayList([]const u8),
......@@ -114,6 +115,7 @@ pub const Builder = struct {
114115 .default_step = undefined,
115116 .env_map = %%os.getEnvMap(allocator),
116117 .prefix = undefined,
118 .search_prefixes = ArrayList([]const u8).init(allocator),
117119 .lib_dir = undefined,
118120 .exe_dir = undefined,
119121 .installed_files = ArrayList([]const u8).init(allocator),
......@@ -671,7 +673,22 @@ pub const Builder = struct {
671673 }
672674
673675 pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) -> %[]const u8 {
676 // TODO report error for ambiguous situations
674677 const exe_extension = (Target { .Native = {}}).exeFileExt();
678 for (self.search_prefixes.toSliceConst()) |search_prefix| {
679 for (names) |name| {
680 if (os.path.isAbsolute(name)) {
681 return name;
682 }
683 const full_path = %return os.path.join(self.allocator, search_prefix, "bin",
684 self.fmt("{}{}", name, exe_extension));
685 if (os.path.real(self.allocator, full_path)) |real_path| {
686 return real_path;
687 } else |_| {
688 continue;
689 }
690 }
691 }
675692 if (self.env_map.get("PATH")) |PATH| {
676693 for (names) |name| {
677694 if (os.path.isAbsolute(name)) {
......@@ -727,6 +744,10 @@ pub const Builder = struct {
727744 },
728745 }
729746 }
747
748 pub fn addSearchPrefix(self: &Builder, search_prefix: []const u8) {
749 %%self.search_prefixes.append(search_prefix);
750 }
730751};
731752
732753const Version = struct {
std/os/path.zig+262-110
......@@ -111,6 +111,7 @@ test "os.path.isAbsoluteWindows" {
111111 testIsAbsoluteWindows("C:cwd\\another", false);
112112 testIsAbsoluteWindows("directory/directory", false);
113113 testIsAbsoluteWindows("directory\\directory", false);
114 testIsAbsoluteWindows("/usr/local", true);
114115}
115116
116117test "os.path.isAbsolutePosix" {
......@@ -128,53 +129,115 @@ fn testIsAbsolutePosix(path: []const u8, expected_result: bool) {
128129 assert(isAbsolutePosix(path) == expected_result);
129130}
130131
131pub fn drive(path: []const u8) -> ?[]const u8 {
132 if (path.len < 2)
133 return null;
134 if (path[1] != ':')
135 return null;
136 return path[0..2];
137}
132pub const WindowsPath = struct {
133 is_abs: bool,
134 kind: Kind,
135 disk_designator: []const u8,
138136
139pub fn networkShare(path: []const u8) -> ?[]const u8 {
140 if (path.len < "//a/b".len)
141 return null;
137 pub const Kind = enum {
138 None,
139 Drive,
140 NetworkShare,
141 };
142};
143
144pub fn windowsParsePath(path: []const u8) -> WindowsPath {
145 if (path.len >= 2 and path[1] == ':') {
146 return WindowsPath {
147 .is_abs = isAbsoluteWindows(path),
148 .kind = WindowsPath.Kind.Drive,
149 .disk_designator = path[0..2],
150 };
151 }
152 if (path.len >= 1 and (path[0] == '/' or path[0] == '\\') and
153 (path.len == 1 or (path[1] != '/' and path[1] != '\\')))
154 {
155 return WindowsPath {
156 .is_abs = true,
157 .kind = WindowsPath.Kind.None,
158 .disk_designator = path[0..0],
159 };
160 }
161 const relative_path = WindowsPath {
162 .kind = WindowsPath.Kind.None,
163 .disk_designator = []u8{},
164 .is_abs = false,
165 };
166 if (path.len < "//a/b".len) {
167 return relative_path;
168 }
142169
143170 // TODO when I combined these together with `inline for` the compiler crashed
144171 {
145172 const this_sep = '/';
146173 const two_sep = []u8{this_sep, this_sep};
147174 if (mem.startsWith(u8, path, two_sep)) {
148 if (path[2] == this_sep)
149 return null;
175 if (path[2] == this_sep) {
176 return relative_path;
177 }
150178
151179 var it = mem.split(path, []u8{this_sep});
152 _ = (it.next() ?? return null);
153 _ = (it.next() ?? return null);
154 return path[0..it.index];
180 _ = (it.next() ?? return relative_path);
181 _ = (it.next() ?? return relative_path);
182 return WindowsPath {
183 .is_abs = isAbsoluteWindows(path),
184 .kind = WindowsPath.Kind.NetworkShare,
185 .disk_designator = path[0..it.index],
186 };
155187 }
156188 }
157189 {
158190 const this_sep = '\\';
159191 const two_sep = []u8{this_sep, this_sep};
160192 if (mem.startsWith(u8, path, two_sep)) {
161 if (path[2] == this_sep)
162 return null;
193 if (path[2] == this_sep) {
194 return relative_path;
195 }
163196
164197 var it = mem.split(path, []u8{this_sep});
165 _ = (it.next() ?? return null);
166 _ = (it.next() ?? return null);
167 return path[0..it.index];
198 _ = (it.next() ?? return relative_path);
199 _ = (it.next() ?? return relative_path);
200 return WindowsPath {
201 .is_abs = isAbsoluteWindows(path),
202 .kind = WindowsPath.Kind.NetworkShare,
203 .disk_designator = path[0..it.index],
204 };
168205 }
169206 }
170 return null;
207 return relative_path;
171208}
172209
173test "os.path.networkShare" {
174 assert(mem.eql(u8, ??networkShare("//a/b"), "//a/b"));
175 assert(mem.eql(u8, ??networkShare("\\\\a\\b"), "\\\\a\\b"));
176
177 assert(networkShare("\\\\a\\") == null);
210test "os.path.windowsParsePath" {
211 {
212 const parsed = windowsParsePath("//a/b");
213 assert(parsed.is_abs);
214 assert(parsed.kind == WindowsPath.Kind.NetworkShare);
215 assert(mem.eql(u8, parsed.disk_designator, "//a/b"));
216 }
217 {
218 const parsed = windowsParsePath("\\\\a\\b");
219 assert(parsed.is_abs);
220 assert(parsed.kind == WindowsPath.Kind.NetworkShare);
221 assert(mem.eql(u8, parsed.disk_designator, "\\\\a\\b"));
222 }
223 {
224 const parsed = windowsParsePath("\\\\a\\");
225 assert(!parsed.is_abs);
226 assert(parsed.kind == WindowsPath.Kind.None);
227 assert(mem.eql(u8, parsed.disk_designator, ""));
228 }
229 {
230 const parsed = windowsParsePath("/usr/local");
231 assert(parsed.is_abs);
232 assert(parsed.kind == WindowsPath.Kind.None);
233 assert(mem.eql(u8, parsed.disk_designator, ""));
234 }
235 {
236 const parsed = windowsParsePath("c:../");
237 assert(!parsed.is_abs);
238 assert(parsed.kind == WindowsPath.Kind.Drive);
239 assert(mem.eql(u8, parsed.disk_designator, "c:"));
240 }
178241}
179242
180243pub fn diskDesignator(path: []const u8) -> []const u8 {
......@@ -186,10 +249,9 @@ pub fn diskDesignator(path: []const u8) -> []const u8 {
186249}
187250
188251pub fn diskDesignatorWindows(path: []const u8) -> []const u8 {
189 return drive(path) ?? (networkShare(path) ?? []u8{});
252 return windowsParsePath(path).disk_designator;
190253}
191254
192// TODO ASCII is wrong, we actually need full unicode support to compare paths.
193255fn networkShareServersEql(ns1: []const u8, ns2: []const u8) -> bool {
194256 const sep1 = ns1[0];
195257 const sep2 = ns2[0];
......@@ -197,9 +259,33 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) -> bool {
197259 var it1 = mem.split(ns1, []u8{sep1});
198260 var it2 = mem.split(ns2, []u8{sep2});
199261
262 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
200263 return asciiEqlIgnoreCase(??it1.next(), ??it2.next());
201264}
202265
266fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8) -> bool {
267 switch (kind) {
268 WindowsPath.Kind.None => {
269 assert(p1.len == 0);
270 assert(p2.len == 0);
271 return true;
272 },
273 WindowsPath.Kind.Drive => {
274 return asciiUpper(p1[0]) == asciiUpper(p2[0]);
275 },
276 WindowsPath.Kind.NetworkShare => {
277 const sep1 = p1[0];
278 const sep2 = p2[0];
279
280 var it1 = mem.split(p1, []u8{sep1});
281 var it2 = mem.split(p2, []u8{sep2});
282
283 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
284 return asciiEqlIgnoreCase(??it1.next(), ??it2.next()) and asciiEqlIgnoreCase(??it1.next(), ??it2.next());
285 },
286 }
287}
288
203289fn asciiUpper(byte: u8) -> u8 {
204290 return switch (byte) {
205291 'a' ... 'z' => 'A' + (byte - 'a'),
......@@ -249,120 +335,157 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8
249335 return os.getCwd(allocator);
250336 }
251337
252 // determine which drive we want to result with
253 var result_drive_upcase: ?u8 = null;
254 var have_abs = false;
338 // determine which disk designator we will result with, if any
339 var result_drive_buf = "_:";
340 var result_disk_designator: []const u8 = "";
341 var have_drive_kind = WindowsPath.Kind.None;
342 var have_abs_path = false;
255343 var first_index: usize = 0;
256344 var max_size: usize = 0;
257345 for (paths) |p, i| {
258 const is_abs = isAbsoluteWindows(p);
259 if (is_abs) {
260 have_abs = true;
346 const parsed = windowsParsePath(p);
347 if (parsed.is_abs) {
348 have_abs_path = true;
261349 first_index = i;
262 max_size = 0;
350 max_size = result_disk_designator.len;
263351 }
264 if (drive(p)) |d| {
265 result_drive_upcase = asciiUpper(d[0]);
266 } else if (networkShare(p)) |_| {
267 result_drive_upcase = null;
352 switch (parsed.kind) {
353 WindowsPath.Kind.Drive => {
354 result_drive_buf[0] = asciiUpper(parsed.disk_designator[0]);
355 result_disk_designator = result_drive_buf[0..];
356 have_drive_kind = WindowsPath.Kind.Drive;
357 },
358 WindowsPath.Kind.NetworkShare => {
359 result_disk_designator = parsed.disk_designator;
360 have_drive_kind = WindowsPath.Kind.NetworkShare;
361 },
362 WindowsPath.Kind.None => {},
268363 }
269364 max_size += p.len + 1;
270365 }
271366
272367
273 // if we will result with a drive, loop again to determine
274 // which is the first time the drive is absolutely specified, if any
275 // and count up the max bytes for paths related to this drive
276 if (result_drive_upcase) |res_dr| {
277 have_abs = false;
368 // if we will result with a disk designator, loop again to determine
369 // which is the last time the disk designator is absolutely specified, if any
370 // and count up the max bytes for paths related to this disk designator
371 if (have_drive_kind != WindowsPath.Kind.None) {
372 have_abs_path = false;
278373 first_index = 0;
279 max_size = "_:".len;
280 var correct_drive = false;
374 max_size = result_disk_designator.len;
375 var correct_disk_designator = false;
281376
282377 for (paths) |p, i| {
283 if (drive(p)) |dr| {
284 correct_drive = asciiUpper(dr[0]) == res_dr;
285 } else if (networkShare(p)) |_| {
286 continue;
378 const parsed = windowsParsePath(p);
379 if (parsed.kind != WindowsPath.Kind.None) {
380 if (parsed.kind == have_drive_kind) {
381 correct_disk_designator = compareDiskDesignators(have_drive_kind,
382 result_disk_designator, parsed.disk_designator);
383 } else {
384 continue;
385 }
287386 }
288 if (!correct_drive) {
387 if (!correct_disk_designator) {
289388 continue;
290389 }
291 const is_abs = isAbsoluteWindows(p);
292 if (is_abs) {
390 if (parsed.is_abs) {
293391 first_index = i;
294 max_size = "_:".len;
295 have_abs = true;
392 max_size = result_disk_designator.len;
393 have_abs_path = true;
296394 }
297395 max_size += p.len + 1;
298396 }
299397 }
300398
301 var drive_buf = "_:";
399
400 // Allocate result and fill in the disk designator, calling getCwd if we have to.
302401 var result: []u8 = undefined;
303402 var result_index: usize = 0;
304 var root_slice: []const u8 = undefined;
305
306 if (have_abs) {
307 result = %return allocator.alloc(u8, max_size);
308
309 if (result_drive_upcase) |res_dr| {
310 drive_buf[0] = res_dr;
311 root_slice = drive_buf[0..];
312403
313 mem.copy(u8, result, root_slice);
314 result_index += root_slice.len;
315 } else {
316 // We know it looks like //a/b or \\a\b because of earlier code
317 var it = mem.split(paths[first_index], "/\\");
318 const server_name = ??it.next();
319 const other_name = ??it.next();
320
321 result[result_index] = '\\';
322 result_index += 1;
323 result[result_index] = '\\';
324 result_index += 1;
325 mem.copy(u8, result[result_index..], server_name);
326 result_index += server_name.len;
327 result[result_index] = '\\';
328 result_index += 1;
329 mem.copy(u8, result[result_index..], other_name);
330 result_index += other_name.len;
331
332 root_slice = result[0..result_index];
404 if (have_abs_path) {
405 switch (have_drive_kind) {
406 WindowsPath.Kind.Drive => {
407 result = %return allocator.alloc(u8, max_size);
408
409 mem.copy(u8, result, result_disk_designator);
410 result_index += result_disk_designator.len;
411 },
412 WindowsPath.Kind.NetworkShare => {
413 result = %return allocator.alloc(u8, max_size);
414 var it = mem.split(paths[first_index], "/\\");
415 const server_name = ??it.next();
416 const other_name = ??it.next();
417
418 result[result_index] = '\\';
419 result_index += 1;
420 result[result_index] = '\\';
421 result_index += 1;
422 mem.copy(u8, result[result_index..], server_name);
423 result_index += server_name.len;
424 result[result_index] = '\\';
425 result_index += 1;
426 mem.copy(u8, result[result_index..], other_name);
427 result_index += other_name.len;
428
429 result_disk_designator = result[0..result_index];
430 },
431 WindowsPath.Kind.None => {
432 assert(is_windows); // resolveWindows called on non windows can't use getCwd
433 const cwd = %return os.getCwd(allocator);
434 defer allocator.free(cwd);
435 const parsed_cwd = windowsParsePath(cwd);
436 result = %return allocator.alloc(u8, max_size + parsed_cwd.disk_designator.len + 1);
437 mem.copy(u8, result, parsed_cwd.disk_designator);
438 result_index += parsed_cwd.disk_designator.len;
439 result_disk_designator = result[0..parsed_cwd.disk_designator.len];
440 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
441 result[0] = asciiUpper(result[0]);
442 }
443 have_drive_kind = parsed_cwd.kind;
444 },
333445 }
334446 } else {
335447 assert(is_windows); // resolveWindows called on non windows can't use getCwd
336 // TODO get cwd for result_drive if applicable
448 // TODO call get cwd for the result_disk_designator instead of the global one
337449 const cwd = %return os.getCwd(allocator);
338450 defer allocator.free(cwd);
451
339452 result = %return allocator.alloc(u8, max_size + cwd.len + 1);
453
340454 mem.copy(u8, result, cwd);
341455 result_index += cwd.len;
342
343 root_slice = diskDesignatorWindows(result[0..result_index]);
456 const parsed_cwd = windowsParsePath(result[0..result_index]);
457 result_disk_designator = parsed_cwd.disk_designator;
458 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
459 result[0] = asciiUpper(result[0]);
460 }
461 have_drive_kind = parsed_cwd.kind;
344462 }
345463 %defer allocator.free(result);
346464
347 var correct_drive = true;
465 // Now we know the disk designator to use, if any, and what kind it is. And our result
466 // is big enough to append all the paths to.
467 var correct_disk_designator = true;
348468 for (paths[first_index..]) |p, i| {
349 if (result_drive_upcase) |res_dr| {
350 if (drive(p)) |dr| {
351 correct_drive = asciiUpper(dr[0]) == res_dr;
352 } else if (networkShare(p)) |_| {
353 continue;
354 }
355 if (!correct_drive) {
469 const parsed = windowsParsePath(p);
470
471 if (parsed.kind != WindowsPath.Kind.None) {
472 if (parsed.kind == have_drive_kind) {
473 correct_disk_designator = compareDiskDesignators(have_drive_kind,
474 result_disk_designator, parsed.disk_designator);
475 } else {
356476 continue;
357477 }
358478 }
359 var it = mem.split(p[diskDesignatorWindows(p).len..], "/\\");
479 if (!correct_disk_designator) {
480 continue;
481 }
482 var it = mem.split(p[parsed.disk_designator.len..], "/\\");
360483 while (it.next()) |component| {
361484 if (mem.eql(u8, component, ".")) {
362485 continue;
363486 } else if (mem.eql(u8, component, "..")) {
364487 while (true) {
365 if (result_index == 0 or result_index == root_slice.len)
488 if (result_index == 0 or result_index == result_disk_designator.len)
366489 break;
367490 result_index -= 1;
368491 if (result[result_index] == '\\' or result[result_index] == '/')
......@@ -377,7 +500,7 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8
377500 }
378501 }
379502
380 if (result_index == root_slice.len) {
503 if (result_index == result_disk_designator.len) {
381504 result[result_index] = '\\';
382505 result_index += 1;
383506 }
......@@ -455,6 +578,9 @@ pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) -> %[]u8 {
455578test "os.path.resolve" {
456579 const cwd = %%os.getCwd(debug.global_allocator);
457580 if (is_windows) {
581 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
582 cwd[0] = asciiUpper(cwd[0]);
583 }
458584 assert(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));
459585 } else {
460586 assert(mem.eql(u8, testResolvePosix([][]const u8{"a/b/c/", "../../.."}), cwd));
......@@ -463,6 +589,29 @@ test "os.path.resolve" {
463589}
464590
465591test "os.path.resolveWindows" {
592 if (is_windows) {
593 const cwd = %%os.getCwd(debug.global_allocator);
594 const parsed_cwd = windowsParsePath(cwd);
595 {
596 const result = testResolveWindows([][]const u8{"/usr/local", "lib\\zig\\std\\array_list.zig"});
597 const expected = %%join(debug.global_allocator,
598 parsed_cwd.disk_designator, "usr\\local\\lib\\zig\\std\\array_list.zig");
599 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
600 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
601 }
602 assert(mem.eql(u8, result, expected));
603 }
604 {
605 const result = testResolveWindows([][]const u8{"usr/local", "lib\\zig"});
606 const expected = %%join(debug.global_allocator, cwd, "usr\\local\\lib\\zig");
607 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
608 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
609 }
610 assert(mem.eql(u8, result, expected));
611 }
612 }
613
614 assert(mem.eql(u8, testResolveWindows([][]const u8{"c:\\a\\b\\c", "/hi", "ok"}), "C:\\hi\\ok"));
466615 assert(mem.eql(u8, testResolveWindows([][]const u8{"c:/blah\\blah", "d:/games", "c:../a"}), "C:\\blah\\a"));
467616 assert(mem.eql(u8, testResolveWindows([][]const u8{"c:/blah\\blah", "d:/games", "C:../a"}), "C:\\blah\\a"));
468617 assert(mem.eql(u8, testResolveWindows([][]const u8{"c:/ignore", "d:\\a/b\\c/d", "\\e.exe"}), "D:\\e.exe"));
......@@ -749,18 +898,21 @@ pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8)
749898 const resolved_to = %return resolveWindows(allocator, [][]const u8{to});
750899 defer if (clean_up_resolved_to) allocator.free(resolved_to);
751900
752 const result_is_to = if (drive(resolved_to)) |to_drive|
753 if (drive(resolved_from)) |from_drive|
754 asciiUpper(from_drive[0]) != asciiUpper(to_drive[0])
755 else
756 true
757 else if (networkShare(resolved_to)) |to_ns|
758 if (networkShare(resolved_from)) |from_ns|
759 !networkShareServersEql(to_ns, from_ns)
760 else
761 true
762 else
763 unreachable;
901 const parsed_from = windowsParsePath(resolved_from);
902 const parsed_to = windowsParsePath(resolved_to);
903 const result_is_to = x: {
904 if (parsed_from.kind != parsed_to.kind) {
905 break :x true;
906 } else switch (parsed_from.kind) {
907 WindowsPath.Kind.NetworkShare => {
908 break :x !networkShareServersEql(parsed_to.disk_designator, parsed_from.disk_designator);
909 },
910 WindowsPath.Kind.Drive => {
911 break :x asciiUpper(parsed_from.disk_designator[0]) != asciiUpper(parsed_to.disk_designator[0]);
912 },
913 else => unreachable,
914 }
915 };
764916
765917 if (result_is_to) {
766918 clean_up_resolved_to = false;
std/special/build_runner.zig+7
......@@ -84,6 +84,12 @@ pub fn main() -> %void {
8484 warn("Expected argument after --prefix\n\n");
8585 return usageAndErr(&builder, false, %return stderr_stream);
8686 });
87 } else if (mem.eql(u8, arg, "--search-prefix")) {
88 const search_prefix = %return unwrapArg(arg_it.next(allocator) ?? {
89 warn("Expected argument after --search-prefix\n\n");
90 return usageAndErr(&builder, false, %return stderr_stream);
91 });
92 builder.addSearchPrefix(search_prefix);
8793 } else if (mem.eql(u8, arg, "--verbose-tokenize")) {
8894 builder.verbose_tokenize = true;
8995 } else if (mem.eql(u8, arg, "--verbose-ast")) {
......@@ -145,6 +151,7 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream)
145151 \\ --help Print this help and exit
146152 \\ --verbose Print commands before executing them
147153 \\ --prefix [path] Override default install prefix
154 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
148155 \\
149156 \\Project-Specific Options:
150157 \\