mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
Merge branch 'master' into llvm6
This commit is contained in:
commit
8b716f941d
21
build.zig
21
build.zig
@ -80,9 +80,12 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) {
|
||||
for (dep.libdirs.toSliceConst()) |lib_dir| {
|
||||
lib_exe_obj.addLibPath(lib_dir);
|
||||
}
|
||||
for (dep.libs.toSliceConst()) |lib| {
|
||||
for (dep.system_libs.toSliceConst()) |lib| {
|
||||
lib_exe_obj.linkSystemLibrary(lib);
|
||||
}
|
||||
for (dep.libs.toSliceConst()) |lib| {
|
||||
lib_exe_obj.addObjectFile(lib);
|
||||
}
|
||||
for (dep.includes.toSliceConst()) |include_path| {
|
||||
lib_exe_obj.addIncludeDir(include_path);
|
||||
}
|
||||
@ -91,6 +94,7 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) {
|
||||
const LibraryDep = struct {
|
||||
libdirs: ArrayList([]const u8),
|
||||
libs: ArrayList([]const u8),
|
||||
system_libs: ArrayList([]const u8),
|
||||
includes: ArrayList([]const u8),
|
||||
};
|
||||
|
||||
@ -98,11 +102,11 @@ fn findLLVM(b: &Builder) -> ?LibraryDep {
|
||||
const llvm_config_exe = b.findProgram(
|
||||
[][]const u8{"llvm-config-5.0", "llvm-config"},
|
||||
[][]const u8{
|
||||
"/usr/local/opt/llvm@5/bin",
|
||||
"/mingw64/bin",
|
||||
"C:/Libraries/llvm-5.0.0/bin",
|
||||
"/c/msys64/mingw64/bin",
|
||||
"c:/msys64/mingw64/bin",
|
||||
"C:/Libraries/llvm-5.0.0/bin",
|
||||
"/usr/local/opt/llvm@5/bin",
|
||||
"/mingw64/bin",
|
||||
}) %% |err|
|
||||
{
|
||||
warn("unable to find llvm-config: {}\n", err);
|
||||
@ -114,6 +118,7 @@ fn findLLVM(b: &Builder) -> ?LibraryDep {
|
||||
|
||||
var result = LibraryDep {
|
||||
.libs = ArrayList([]const u8).init(b.allocator),
|
||||
.system_libs = ArrayList([]const u8).init(b.allocator),
|
||||
.includes = ArrayList([]const u8).init(b.allocator),
|
||||
.libdirs = ArrayList([]const u8).init(b.allocator),
|
||||
};
|
||||
@ -121,7 +126,13 @@ fn findLLVM(b: &Builder) -> ?LibraryDep {
|
||||
var it = mem.split(libs_output, " \n");
|
||||
while (it.next()) |lib_arg| {
|
||||
if (mem.startsWith(u8, lib_arg, "-l")) {
|
||||
%%result.libs.append(lib_arg[2..]);
|
||||
%%result.system_libs.append(lib_arg[2..]);
|
||||
} else {
|
||||
if (os.path.isAbsolute(lib_arg)) {
|
||||
%%result.libs.append(lib_arg);
|
||||
} else {
|
||||
%%result.system_libs.append(lib_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,8 +590,10 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
|
||||
bool is_optimized = g->build_mode != BuildModeDebug;
|
||||
bool is_internal_linkage = (fn_table_entry->body_node != nullptr &&
|
||||
fn_table_entry->export_list.length == 0);
|
||||
ZigLLVMDIScope *fn_di_scope = get_di_scope(g, scope->parent);
|
||||
assert(fn_di_scope != nullptr);
|
||||
ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
|
||||
get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "",
|
||||
fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
|
||||
import->di_file, line_number,
|
||||
fn_table_entry->type_entry->di_type, is_internal_linkage,
|
||||
is_definition, scope_line, flags, is_optimized, nullptr);
|
||||
|
||||
@ -14051,6 +14051,8 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc
|
||||
child_import->package = new_anonymous_package();
|
||||
child_import->package->package_table.put(buf_create_from_str("builtin"), ira->codegen->compile_var_package);
|
||||
child_import->package->package_table.put(buf_create_from_str("std"), ira->codegen->std_package);
|
||||
child_import->di_file = ZigLLVMCreateFile(ira->codegen->dbuilder,
|
||||
buf_ptr(buf_create_from_str("cimport.h")), buf_ptr(buf_create_from_str(".")));
|
||||
|
||||
ZigList<ErrorMsg *> errors = {0};
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@ pub const Builder = struct {
|
||||
env_map: BufMap,
|
||||
top_level_steps: ArrayList(&TopLevelStep),
|
||||
prefix: []const u8,
|
||||
search_prefixes: ArrayList([]const u8),
|
||||
lib_dir: []const u8,
|
||||
exe_dir: []const u8,
|
||||
installed_files: ArrayList([]const u8),
|
||||
@ -114,6 +115,7 @@ pub const Builder = struct {
|
||||
.default_step = undefined,
|
||||
.env_map = %%os.getEnvMap(allocator),
|
||||
.prefix = undefined,
|
||||
.search_prefixes = ArrayList([]const u8).init(allocator),
|
||||
.lib_dir = undefined,
|
||||
.exe_dir = undefined,
|
||||
.installed_files = ArrayList([]const u8).init(allocator),
|
||||
@ -671,7 +673,22 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) -> %[]const u8 {
|
||||
// TODO report error for ambiguous situations
|
||||
const exe_extension = (Target { .Native = {}}).exeFileExt();
|
||||
for (self.search_prefixes.toSliceConst()) |search_prefix| {
|
||||
for (names) |name| {
|
||||
if (os.path.isAbsolute(name)) {
|
||||
return name;
|
||||
}
|
||||
const full_path = %return os.path.join(self.allocator, search_prefix, "bin",
|
||||
self.fmt("{}{}", name, exe_extension));
|
||||
if (os.path.real(self.allocator, full_path)) |real_path| {
|
||||
return real_path;
|
||||
} else |_| {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (self.env_map.get("PATH")) |PATH| {
|
||||
for (names) |name| {
|
||||
if (os.path.isAbsolute(name)) {
|
||||
@ -727,6 +744,10 @@ pub const Builder = struct {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addSearchPrefix(self: &Builder, search_prefix: []const u8) {
|
||||
%%self.search_prefixes.append(search_prefix);
|
||||
}
|
||||
};
|
||||
|
||||
const Version = struct {
|
||||
|
||||
370
std/os/path.zig
370
std/os/path.zig
@ -111,6 +111,7 @@ test "os.path.isAbsoluteWindows" {
|
||||
testIsAbsoluteWindows("C:cwd\\another", false);
|
||||
testIsAbsoluteWindows("directory/directory", false);
|
||||
testIsAbsoluteWindows("directory\\directory", false);
|
||||
testIsAbsoluteWindows("/usr/local", true);
|
||||
}
|
||||
|
||||
test "os.path.isAbsolutePosix" {
|
||||
@ -128,53 +129,115 @@ fn testIsAbsolutePosix(path: []const u8, expected_result: bool) {
|
||||
assert(isAbsolutePosix(path) == expected_result);
|
||||
}
|
||||
|
||||
pub fn drive(path: []const u8) -> ?[]const u8 {
|
||||
if (path.len < 2)
|
||||
return null;
|
||||
if (path[1] != ':')
|
||||
return null;
|
||||
return path[0..2];
|
||||
}
|
||||
pub const WindowsPath = struct {
|
||||
is_abs: bool,
|
||||
kind: Kind,
|
||||
disk_designator: []const u8,
|
||||
|
||||
pub fn networkShare(path: []const u8) -> ?[]const u8 {
|
||||
if (path.len < "//a/b".len)
|
||||
return null;
|
||||
pub const Kind = enum {
|
||||
None,
|
||||
Drive,
|
||||
NetworkShare,
|
||||
};
|
||||
};
|
||||
|
||||
pub fn windowsParsePath(path: []const u8) -> WindowsPath {
|
||||
if (path.len >= 2 and path[1] == ':') {
|
||||
return WindowsPath {
|
||||
.is_abs = isAbsoluteWindows(path),
|
||||
.kind = WindowsPath.Kind.Drive,
|
||||
.disk_designator = path[0..2],
|
||||
};
|
||||
}
|
||||
if (path.len >= 1 and (path[0] == '/' or path[0] == '\\') and
|
||||
(path.len == 1 or (path[1] != '/' and path[1] != '\\')))
|
||||
{
|
||||
return WindowsPath {
|
||||
.is_abs = true,
|
||||
.kind = WindowsPath.Kind.None,
|
||||
.disk_designator = path[0..0],
|
||||
};
|
||||
}
|
||||
const relative_path = WindowsPath {
|
||||
.kind = WindowsPath.Kind.None,
|
||||
.disk_designator = []u8{},
|
||||
.is_abs = false,
|
||||
};
|
||||
if (path.len < "//a/b".len) {
|
||||
return relative_path;
|
||||
}
|
||||
|
||||
// TODO when I combined these together with `inline for` the compiler crashed
|
||||
{
|
||||
const this_sep = '/';
|
||||
const two_sep = []u8{this_sep, this_sep};
|
||||
if (mem.startsWith(u8, path, two_sep)) {
|
||||
if (path[2] == this_sep)
|
||||
return null;
|
||||
if (path[2] == this_sep) {
|
||||
return relative_path;
|
||||
}
|
||||
|
||||
var it = mem.split(path, []u8{this_sep});
|
||||
_ = (it.next() ?? return null);
|
||||
_ = (it.next() ?? return null);
|
||||
return path[0..it.index];
|
||||
_ = (it.next() ?? return relative_path);
|
||||
_ = (it.next() ?? return relative_path);
|
||||
return WindowsPath {
|
||||
.is_abs = isAbsoluteWindows(path),
|
||||
.kind = WindowsPath.Kind.NetworkShare,
|
||||
.disk_designator = path[0..it.index],
|
||||
};
|
||||
}
|
||||
}
|
||||
{
|
||||
const this_sep = '\\';
|
||||
const two_sep = []u8{this_sep, this_sep};
|
||||
if (mem.startsWith(u8, path, two_sep)) {
|
||||
if (path[2] == this_sep)
|
||||
return null;
|
||||
if (path[2] == this_sep) {
|
||||
return relative_path;
|
||||
}
|
||||
|
||||
var it = mem.split(path, []u8{this_sep});
|
||||
_ = (it.next() ?? return null);
|
||||
_ = (it.next() ?? return null);
|
||||
return path[0..it.index];
|
||||
_ = (it.next() ?? return relative_path);
|
||||
_ = (it.next() ?? return relative_path);
|
||||
return WindowsPath {
|
||||
.is_abs = isAbsoluteWindows(path),
|
||||
.kind = WindowsPath.Kind.NetworkShare,
|
||||
.disk_designator = path[0..it.index],
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return relative_path;
|
||||
}
|
||||
|
||||
test "os.path.networkShare" {
|
||||
assert(mem.eql(u8, ??networkShare("//a/b"), "//a/b"));
|
||||
assert(mem.eql(u8, ??networkShare("\\\\a\\b"), "\\\\a\\b"));
|
||||
|
||||
assert(networkShare("\\\\a\\") == null);
|
||||
test "os.path.windowsParsePath" {
|
||||
{
|
||||
const parsed = windowsParsePath("//a/b");
|
||||
assert(parsed.is_abs);
|
||||
assert(parsed.kind == WindowsPath.Kind.NetworkShare);
|
||||
assert(mem.eql(u8, parsed.disk_designator, "//a/b"));
|
||||
}
|
||||
{
|
||||
const parsed = windowsParsePath("\\\\a\\b");
|
||||
assert(parsed.is_abs);
|
||||
assert(parsed.kind == WindowsPath.Kind.NetworkShare);
|
||||
assert(mem.eql(u8, parsed.disk_designator, "\\\\a\\b"));
|
||||
}
|
||||
{
|
||||
const parsed = windowsParsePath("\\\\a\\");
|
||||
assert(!parsed.is_abs);
|
||||
assert(parsed.kind == WindowsPath.Kind.None);
|
||||
assert(mem.eql(u8, parsed.disk_designator, ""));
|
||||
}
|
||||
{
|
||||
const parsed = windowsParsePath("/usr/local");
|
||||
assert(parsed.is_abs);
|
||||
assert(parsed.kind == WindowsPath.Kind.None);
|
||||
assert(mem.eql(u8, parsed.disk_designator, ""));
|
||||
}
|
||||
{
|
||||
const parsed = windowsParsePath("c:../");
|
||||
assert(!parsed.is_abs);
|
||||
assert(parsed.kind == WindowsPath.Kind.Drive);
|
||||
assert(mem.eql(u8, parsed.disk_designator, "c:"));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn diskDesignator(path: []const u8) -> []const u8 {
|
||||
@ -186,10 +249,9 @@ pub fn diskDesignator(path: []const u8) -> []const u8 {
|
||||
}
|
||||
|
||||
pub fn diskDesignatorWindows(path: []const u8) -> []const u8 {
|
||||
return drive(path) ?? (networkShare(path) ?? []u8{});
|
||||
return windowsParsePath(path).disk_designator;
|
||||
}
|
||||
|
||||
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
|
||||
fn networkShareServersEql(ns1: []const u8, ns2: []const u8) -> bool {
|
||||
const sep1 = ns1[0];
|
||||
const sep2 = ns2[0];
|
||||
@ -197,9 +259,33 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) -> bool {
|
||||
var it1 = mem.split(ns1, []u8{sep1});
|
||||
var it2 = mem.split(ns2, []u8{sep2});
|
||||
|
||||
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
|
||||
return asciiEqlIgnoreCase(??it1.next(), ??it2.next());
|
||||
}
|
||||
|
||||
fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8) -> bool {
|
||||
switch (kind) {
|
||||
WindowsPath.Kind.None => {
|
||||
assert(p1.len == 0);
|
||||
assert(p2.len == 0);
|
||||
return true;
|
||||
},
|
||||
WindowsPath.Kind.Drive => {
|
||||
return asciiUpper(p1[0]) == asciiUpper(p2[0]);
|
||||
},
|
||||
WindowsPath.Kind.NetworkShare => {
|
||||
const sep1 = p1[0];
|
||||
const sep2 = p2[0];
|
||||
|
||||
var it1 = mem.split(p1, []u8{sep1});
|
||||
var it2 = mem.split(p2, []u8{sep2});
|
||||
|
||||
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
|
||||
return asciiEqlIgnoreCase(??it1.next(), ??it2.next()) and asciiEqlIgnoreCase(??it1.next(), ??it2.next());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn asciiUpper(byte: u8) -> u8 {
|
||||
return switch (byte) {
|
||||
'a' ... 'z' => 'A' + (byte - 'a'),
|
||||
@ -249,120 +335,157 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8
|
||||
return os.getCwd(allocator);
|
||||
}
|
||||
|
||||
// determine which drive we want to result with
|
||||
var result_drive_upcase: ?u8 = null;
|
||||
var have_abs = false;
|
||||
// determine which disk designator we will result with, if any
|
||||
var result_drive_buf = "_:";
|
||||
var result_disk_designator: []const u8 = "";
|
||||
var have_drive_kind = WindowsPath.Kind.None;
|
||||
var have_abs_path = false;
|
||||
var first_index: usize = 0;
|
||||
var max_size: usize = 0;
|
||||
for (paths) |p, i| {
|
||||
const is_abs = isAbsoluteWindows(p);
|
||||
if (is_abs) {
|
||||
have_abs = true;
|
||||
const parsed = windowsParsePath(p);
|
||||
if (parsed.is_abs) {
|
||||
have_abs_path = true;
|
||||
first_index = i;
|
||||
max_size = 0;
|
||||
max_size = result_disk_designator.len;
|
||||
}
|
||||
if (drive(p)) |d| {
|
||||
result_drive_upcase = asciiUpper(d[0]);
|
||||
} else if (networkShare(p)) |_| {
|
||||
result_drive_upcase = null;
|
||||
switch (parsed.kind) {
|
||||
WindowsPath.Kind.Drive => {
|
||||
result_drive_buf[0] = asciiUpper(parsed.disk_designator[0]);
|
||||
result_disk_designator = result_drive_buf[0..];
|
||||
have_drive_kind = WindowsPath.Kind.Drive;
|
||||
},
|
||||
WindowsPath.Kind.NetworkShare => {
|
||||
result_disk_designator = parsed.disk_designator;
|
||||
have_drive_kind = WindowsPath.Kind.NetworkShare;
|
||||
},
|
||||
WindowsPath.Kind.None => {},
|
||||
}
|
||||
max_size += p.len + 1;
|
||||
}
|
||||
|
||||
|
||||
// if we will result with a drive, loop again to determine
|
||||
// which is the first time the drive is absolutely specified, if any
|
||||
// and count up the max bytes for paths related to this drive
|
||||
if (result_drive_upcase) |res_dr| {
|
||||
have_abs = false;
|
||||
// if we will result with a disk designator, loop again to determine
|
||||
// which is the last time the disk designator is absolutely specified, if any
|
||||
// and count up the max bytes for paths related to this disk designator
|
||||
if (have_drive_kind != WindowsPath.Kind.None) {
|
||||
have_abs_path = false;
|
||||
first_index = 0;
|
||||
max_size = "_:".len;
|
||||
var correct_drive = false;
|
||||
max_size = result_disk_designator.len;
|
||||
var correct_disk_designator = false;
|
||||
|
||||
for (paths) |p, i| {
|
||||
if (drive(p)) |dr| {
|
||||
correct_drive = asciiUpper(dr[0]) == res_dr;
|
||||
} else if (networkShare(p)) |_| {
|
||||
const parsed = windowsParsePath(p);
|
||||
if (parsed.kind != WindowsPath.Kind.None) {
|
||||
if (parsed.kind == have_drive_kind) {
|
||||
correct_disk_designator = compareDiskDesignators(have_drive_kind,
|
||||
result_disk_designator, parsed.disk_designator);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!correct_disk_designator) {
|
||||
continue;
|
||||
}
|
||||
if (!correct_drive) {
|
||||
continue;
|
||||
}
|
||||
const is_abs = isAbsoluteWindows(p);
|
||||
if (is_abs) {
|
||||
if (parsed.is_abs) {
|
||||
first_index = i;
|
||||
max_size = "_:".len;
|
||||
have_abs = true;
|
||||
max_size = result_disk_designator.len;
|
||||
have_abs_path = true;
|
||||
}
|
||||
max_size += p.len + 1;
|
||||
}
|
||||
}
|
||||
|
||||
var drive_buf = "_:";
|
||||
|
||||
// Allocate result and fill in the disk designator, calling getCwd if we have to.
|
||||
var result: []u8 = undefined;
|
||||
var result_index: usize = 0;
|
||||
var root_slice: []const u8 = undefined;
|
||||
|
||||
if (have_abs) {
|
||||
result = %return allocator.alloc(u8, max_size);
|
||||
if (have_abs_path) {
|
||||
switch (have_drive_kind) {
|
||||
WindowsPath.Kind.Drive => {
|
||||
result = %return allocator.alloc(u8, max_size);
|
||||
|
||||
if (result_drive_upcase) |res_dr| {
|
||||
drive_buf[0] = res_dr;
|
||||
root_slice = drive_buf[0..];
|
||||
mem.copy(u8, result, result_disk_designator);
|
||||
result_index += result_disk_designator.len;
|
||||
},
|
||||
WindowsPath.Kind.NetworkShare => {
|
||||
result = %return allocator.alloc(u8, max_size);
|
||||
var it = mem.split(paths[first_index], "/\\");
|
||||
const server_name = ??it.next();
|
||||
const other_name = ??it.next();
|
||||
|
||||
mem.copy(u8, result, root_slice);
|
||||
result_index += root_slice.len;
|
||||
} else {
|
||||
// We know it looks like //a/b or \\a\b because of earlier code
|
||||
var it = mem.split(paths[first_index], "/\\");
|
||||
const server_name = ??it.next();
|
||||
const other_name = ??it.next();
|
||||
|
||||
result[result_index] = '\\';
|
||||
result_index += 1;
|
||||
result[result_index] = '\\';
|
||||
result_index += 1;
|
||||
mem.copy(u8, result[result_index..], server_name);
|
||||
result_index += server_name.len;
|
||||
result[result_index] = '\\';
|
||||
result_index += 1;
|
||||
mem.copy(u8, result[result_index..], other_name);
|
||||
result_index += other_name.len;
|
||||
|
||||
root_slice = result[0..result_index];
|
||||
result[result_index] = '\\';
|
||||
result_index += 1;
|
||||
result[result_index] = '\\';
|
||||
result_index += 1;
|
||||
mem.copy(u8, result[result_index..], server_name);
|
||||
result_index += server_name.len;
|
||||
result[result_index] = '\\';
|
||||
result_index += 1;
|
||||
mem.copy(u8, result[result_index..], other_name);
|
||||
result_index += other_name.len;
|
||||
|
||||
result_disk_designator = result[0..result_index];
|
||||
},
|
||||
WindowsPath.Kind.None => {
|
||||
assert(is_windows); // resolveWindows called on non windows can't use getCwd
|
||||
const cwd = %return os.getCwd(allocator);
|
||||
defer allocator.free(cwd);
|
||||
const parsed_cwd = windowsParsePath(cwd);
|
||||
result = %return allocator.alloc(u8, max_size + parsed_cwd.disk_designator.len + 1);
|
||||
mem.copy(u8, result, parsed_cwd.disk_designator);
|
||||
result_index += parsed_cwd.disk_designator.len;
|
||||
result_disk_designator = result[0..parsed_cwd.disk_designator.len];
|
||||
if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
|
||||
result[0] = asciiUpper(result[0]);
|
||||
}
|
||||
have_drive_kind = parsed_cwd.kind;
|
||||
},
|
||||
}
|
||||
} else {
|
||||
assert(is_windows); // resolveWindows called on non windows can't use getCwd
|
||||
// TODO get cwd for result_drive if applicable
|
||||
// TODO call get cwd for the result_disk_designator instead of the global one
|
||||
const cwd = %return os.getCwd(allocator);
|
||||
defer allocator.free(cwd);
|
||||
|
||||
result = %return allocator.alloc(u8, max_size + cwd.len + 1);
|
||||
|
||||
mem.copy(u8, result, cwd);
|
||||
result_index += cwd.len;
|
||||
|
||||
root_slice = diskDesignatorWindows(result[0..result_index]);
|
||||
const parsed_cwd = windowsParsePath(result[0..result_index]);
|
||||
result_disk_designator = parsed_cwd.disk_designator;
|
||||
if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
|
||||
result[0] = asciiUpper(result[0]);
|
||||
}
|
||||
have_drive_kind = parsed_cwd.kind;
|
||||
}
|
||||
%defer allocator.free(result);
|
||||
|
||||
var correct_drive = true;
|
||||
// Now we know the disk designator to use, if any, and what kind it is. And our result
|
||||
// is big enough to append all the paths to.
|
||||
var correct_disk_designator = true;
|
||||
for (paths[first_index..]) |p, i| {
|
||||
if (result_drive_upcase) |res_dr| {
|
||||
if (drive(p)) |dr| {
|
||||
correct_drive = asciiUpper(dr[0]) == res_dr;
|
||||
} else if (networkShare(p)) |_| {
|
||||
continue;
|
||||
}
|
||||
if (!correct_drive) {
|
||||
const parsed = windowsParsePath(p);
|
||||
|
||||
if (parsed.kind != WindowsPath.Kind.None) {
|
||||
if (parsed.kind == have_drive_kind) {
|
||||
correct_disk_designator = compareDiskDesignators(have_drive_kind,
|
||||
result_disk_designator, parsed.disk_designator);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var it = mem.split(p[diskDesignatorWindows(p).len..], "/\\");
|
||||
if (!correct_disk_designator) {
|
||||
continue;
|
||||
}
|
||||
var it = mem.split(p[parsed.disk_designator.len..], "/\\");
|
||||
while (it.next()) |component| {
|
||||
if (mem.eql(u8, component, ".")) {
|
||||
continue;
|
||||
} else if (mem.eql(u8, component, "..")) {
|
||||
while (true) {
|
||||
if (result_index == 0 or result_index == root_slice.len)
|
||||
if (result_index == 0 or result_index == result_disk_designator.len)
|
||||
break;
|
||||
result_index -= 1;
|
||||
if (result[result_index] == '\\' or result[result_index] == '/')
|
||||
@ -377,7 +500,7 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8
|
||||
}
|
||||
}
|
||||
|
||||
if (result_index == root_slice.len) {
|
||||
if (result_index == result_disk_designator.len) {
|
||||
result[result_index] = '\\';
|
||||
result_index += 1;
|
||||
}
|
||||
@ -455,6 +578,9 @@ pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) -> %[]u8 {
|
||||
test "os.path.resolve" {
|
||||
const cwd = %%os.getCwd(debug.global_allocator);
|
||||
if (is_windows) {
|
||||
if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
|
||||
cwd[0] = asciiUpper(cwd[0]);
|
||||
}
|
||||
assert(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));
|
||||
} else {
|
||||
assert(mem.eql(u8, testResolvePosix([][]const u8{"a/b/c/", "../../.."}), cwd));
|
||||
@ -463,6 +589,29 @@ test "os.path.resolve" {
|
||||
}
|
||||
|
||||
test "os.path.resolveWindows" {
|
||||
if (is_windows) {
|
||||
const cwd = %%os.getCwd(debug.global_allocator);
|
||||
const parsed_cwd = windowsParsePath(cwd);
|
||||
{
|
||||
const result = testResolveWindows([][]const u8{"/usr/local", "lib\\zig\\std\\array_list.zig"});
|
||||
const expected = %%join(debug.global_allocator,
|
||||
parsed_cwd.disk_designator, "usr\\local\\lib\\zig\\std\\array_list.zig");
|
||||
if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
|
||||
expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
|
||||
}
|
||||
assert(mem.eql(u8, result, expected));
|
||||
}
|
||||
{
|
||||
const result = testResolveWindows([][]const u8{"usr/local", "lib\\zig"});
|
||||
const expected = %%join(debug.global_allocator, cwd, "usr\\local\\lib\\zig");
|
||||
if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
|
||||
expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
|
||||
}
|
||||
assert(mem.eql(u8, result, expected));
|
||||
}
|
||||
}
|
||||
|
||||
assert(mem.eql(u8, testResolveWindows([][]const u8{"c:\\a\\b\\c", "/hi", "ok"}), "C:\\hi\\ok"));
|
||||
assert(mem.eql(u8, testResolveWindows([][]const u8{"c:/blah\\blah", "d:/games", "c:../a"}), "C:\\blah\\a"));
|
||||
assert(mem.eql(u8, testResolveWindows([][]const u8{"c:/blah\\blah", "d:/games", "C:../a"}), "C:\\blah\\a"));
|
||||
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)
|
||||
const resolved_to = %return resolveWindows(allocator, [][]const u8{to});
|
||||
defer if (clean_up_resolved_to) allocator.free(resolved_to);
|
||||
|
||||
const result_is_to = if (drive(resolved_to)) |to_drive|
|
||||
if (drive(resolved_from)) |from_drive|
|
||||
asciiUpper(from_drive[0]) != asciiUpper(to_drive[0])
|
||||
else
|
||||
true
|
||||
else if (networkShare(resolved_to)) |to_ns|
|
||||
if (networkShare(resolved_from)) |from_ns|
|
||||
!networkShareServersEql(to_ns, from_ns)
|
||||
else
|
||||
true
|
||||
else
|
||||
unreachable;
|
||||
const parsed_from = windowsParsePath(resolved_from);
|
||||
const parsed_to = windowsParsePath(resolved_to);
|
||||
const result_is_to = x: {
|
||||
if (parsed_from.kind != parsed_to.kind) {
|
||||
break :x true;
|
||||
} else switch (parsed_from.kind) {
|
||||
WindowsPath.Kind.NetworkShare => {
|
||||
break :x !networkShareServersEql(parsed_to.disk_designator, parsed_from.disk_designator);
|
||||
},
|
||||
WindowsPath.Kind.Drive => {
|
||||
break :x asciiUpper(parsed_from.disk_designator[0]) != asciiUpper(parsed_to.disk_designator[0]);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
};
|
||||
|
||||
if (result_is_to) {
|
||||
clean_up_resolved_to = false;
|
||||
|
||||
@ -84,6 +84,12 @@ pub fn main() -> %void {
|
||||
warn("Expected argument after --prefix\n\n");
|
||||
return usageAndErr(&builder, false, %return stderr_stream);
|
||||
});
|
||||
} else if (mem.eql(u8, arg, "--search-prefix")) {
|
||||
const search_prefix = %return unwrapArg(arg_it.next(allocator) ?? {
|
||||
warn("Expected argument after --search-prefix\n\n");
|
||||
return usageAndErr(&builder, false, %return stderr_stream);
|
||||
});
|
||||
builder.addSearchPrefix(search_prefix);
|
||||
} else if (mem.eql(u8, arg, "--verbose-tokenize")) {
|
||||
builder.verbose_tokenize = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-ast")) {
|
||||
@ -145,6 +151,7 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream)
|
||||
\\ --help Print this help and exit
|
||||
\\ --verbose Print commands before executing them
|
||||
\\ --prefix [path] Override default install prefix
|
||||
\\ --search-prefix [path] Add a path to look for binaries, libraries, headers
|
||||
\\
|
||||
\\Project-Specific Options:
|
||||
\\
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user