| author | |
| committer | |
| log | d1243bf272b591a8deba5abedb56050edf3c3d6a |
| tree | a9ca11c601631de614c0fdca478f730a2cc4dc01 |
| parent | 0cd89e9176ab36fc5e267120dc4d75cb79d32684 |
| parent | 94c3dbf9e3f9fcc63b2495adec36e6b4acb1813e |
| signature |
update std lib to integrate with libc for environ8 files changed, 166 insertions(+), 84 deletions(-)
lib/std/c.zig+2| ... | @@ -62,6 +62,8 @@ pub fn versionCheck(glibc_version: builtin.Version) type { | ... | @@ -62,6 +62,8 @@ pub fn versionCheck(glibc_version: builtin.Version) type { |
| 62 | }; | 62 | }; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | pub extern "c" var environ: [*:null]?[*:0]u8; | ||
| 66 | |||
| 65 | pub extern "c" fn fopen(filename: [*:0]const u8, modes: [*:0]const u8) ?*FILE; | 67 | pub extern "c" fn fopen(filename: [*:0]const u8, modes: [*:0]const u8) ?*FILE; |
| 66 | pub extern "c" fn fclose(stream: *FILE) c_int; | 68 | pub extern "c" fn fclose(stream: *FILE) c_int; |
| 67 | pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; | 69 | pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; |
lib/std/os.zig+70-5| ... | @@ -70,6 +70,8 @@ else switch (builtin.os) { | ... | @@ -70,6 +70,8 @@ else switch (builtin.os) { |
| 70 | pub usingnamespace @import("os/bits.zig"); | 70 | pub usingnamespace @import("os/bits.zig"); |
| 71 | 71 | ||
| 72 | /// See also `getenv`. Populated by startup code before main(). | 72 | /// See also `getenv`. Populated by startup code before main(). |
| 73 | /// TODO this is a footgun because the value will be undefined when using `zig build-lib`. | ||
| 74 | /// https://github.com/ziglang/zig/issues/4524 | ||
| 73 | pub var environ: [][*:0]u8 = undefined; | 75 | pub var environ: [][*:0]u8 = undefined; |
| 74 | 76 | ||
| 75 | /// Populated by startup code before main(). | 77 | /// Populated by startup code before main(). |
| ... | @@ -922,7 +924,11 @@ pub const execveC = execveZ; | ... | @@ -922,7 +924,11 @@ pub const execveC = execveZ; |
| 922 | /// Like `execve` except the parameters are null-terminated, | 924 | /// Like `execve` except the parameters are null-terminated, |
| 923 | /// matching the syscall API on all targets. This removes the need for an allocator. | 925 | /// matching the syscall API on all targets. This removes the need for an allocator. |
| 924 | /// This function ignores PATH environment variable. See `execvpeZ` for that. | 926 | /// This function ignores PATH environment variable. See `execvpeZ` for that. |
| 925 | pub fn execveZ(path: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError { | 927 | pub fn execveZ( |
| 928 | path: [*:0]const u8, | ||
| 929 | child_argv: [*:null]const ?[*:0]const u8, | ||
| 930 | envp: [*:null]const ?[*:0]const u8, | ||
| 931 | ) ExecveError { | ||
| 926 | switch (errno(system.execve(path, child_argv, envp))) { | 932 | switch (errno(system.execve(path, child_argv, envp))) { |
| 927 | 0 => unreachable, | 933 | 0 => unreachable, |
| 928 | EFAULT => unreachable, | 934 | EFAULT => unreachable, |
| ... | @@ -966,7 +972,7 @@ pub fn execvpeZ_expandArg0( | ... | @@ -966,7 +972,7 @@ pub fn execvpeZ_expandArg0( |
| 966 | envp: [*:null]const ?[*:0]const u8, | 972 | envp: [*:null]const ?[*:0]const u8, |
| 967 | ) ExecveError { | 973 | ) ExecveError { |
| 968 | const file_slice = mem.toSliceConst(u8, file); | 974 | const file_slice = mem.toSliceConst(u8, file); |
| 969 | if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveC(file, child_argv, envp); | 975 | if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveZ(file, child_argv, envp); |
| 970 | 976 | ||
| 971 | const PATH = getenvZ("PATH") orelse "/usr/local/bin:/bin/:/usr/bin"; | 977 | const PATH = getenvZ("PATH") orelse "/usr/local/bin:/bin/:/usr/bin"; |
| 972 | var path_buf: [MAX_PATH_BYTES]u8 = undefined; | 978 | var path_buf: [MAX_PATH_BYTES]u8 = undefined; |
| ... | @@ -993,7 +999,7 @@ pub fn execvpeZ_expandArg0( | ... | @@ -993,7 +999,7 @@ pub fn execvpeZ_expandArg0( |
| 993 | .expand => child_argv[0] = full_path, | 999 | .expand => child_argv[0] = full_path, |
| 994 | .no_expand => {}, | 1000 | .no_expand => {}, |
| 995 | } | 1001 | } |
| 996 | err = execveC(full_path, child_argv, envp); | 1002 | err = execveZ(full_path, child_argv, envp); |
| 997 | switch (err) { | 1003 | switch (err) { |
| 998 | error.AccessDenied => seen_eacces = true, | 1004 | error.AccessDenied => seen_eacces = true, |
| 999 | error.FileNotFound, error.NotDir => {}, | 1005 | error.FileNotFound, error.NotDir => {}, |
| ... | @@ -1007,7 +1013,7 @@ pub fn execvpeZ_expandArg0( | ... | @@ -1007,7 +1013,7 @@ pub fn execvpeZ_expandArg0( |
| 1007 | /// Like `execvpe` except the parameters are null-terminated, | 1013 | /// Like `execvpe` except the parameters are null-terminated, |
| 1008 | /// matching the syscall API on all targets. This removes the need for an allocator. | 1014 | /// matching the syscall API on all targets. This removes the need for an allocator. |
| 1009 | /// This function also uses the PATH environment variable to get the full path to the executable. | 1015 | /// This function also uses the PATH environment variable to get the full path to the executable. |
| 1010 | /// If `file` is an absolute path, this is the same as `execveC`. | 1016 | /// If `file` is an absolute path, this is the same as `execveZ`. |
| 1011 | pub fn execvpeZ( | 1017 | pub fn execvpeZ( |
| 1012 | file: [*:0]const u8, | 1018 | file: [*:0]const u8, |
| 1013 | argv: [*:null]const ?[*:0]const u8, | 1019 | argv: [*:null]const ?[*:0]const u8, |
| ... | @@ -1097,8 +1103,36 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) | ... | @@ -1097,8 +1103,36 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) |
| 1097 | 1103 | ||
| 1098 | /// Get an environment variable. | 1104 | /// Get an environment variable. |
| 1099 | /// See also `getenvZ`. | 1105 | /// See also `getenvZ`. |
| 1100 | /// TODO make this go through libc when we have it | ||
| 1101 | pub fn getenv(key: []const u8) ?[]const u8 { | 1106 | pub fn getenv(key: []const u8) ?[]const u8 { |
| 1107 | if (builtin.link_libc) { | ||
| 1108 | var small_key_buf: [64]u8 = undefined; | ||
| 1109 | if (key.len < small_key_buf.len) { | ||
| 1110 | mem.copy(u8, &small_key_buf, key); | ||
| 1111 | small_key_buf[key.len] = 0; | ||
| 1112 | const key0 = small_key_buf[0..key.len :0]; | ||
| 1113 | return getenvZ(key0); | ||
| 1114 | } | ||
| 1115 | // Search the entire `environ` because we don't have a null terminated pointer. | ||
| 1116 | var ptr = std.c.environ; | ||
| 1117 | while (ptr.*) |line| : (ptr += 1) { | ||
| 1118 | var line_i: usize = 0; | ||
| 1119 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} | ||
| 1120 | const this_key = line[0..line_i]; | ||
| 1121 | |||
| 1122 | if (!mem.eql(u8, this_key, key)) continue; | ||
| 1123 | |||
| 1124 | var end_i: usize = line_i; | ||
| 1125 | while (line[end_i] != 0) : (end_i += 1) {} | ||
| 1126 | const value = line[line_i + 1 .. end_i]; | ||
| 1127 | |||
| 1128 | return value; | ||
| 1129 | } | ||
| 1130 | return null; | ||
| 1131 | } | ||
| 1132 | if (builtin.os == .windows) { | ||
| 1133 | @compileError("std.os.getenv is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API."); | ||
| 1134 | } | ||
| 1135 | // TODO see https://github.com/ziglang/zig/issues/4524 | ||
| 1102 | for (environ) |ptr| { | 1136 | for (environ) |ptr| { |
| 1103 | var line_i: usize = 0; | 1137 | var line_i: usize = 0; |
| 1104 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} | 1138 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} |
| ... | @@ -1124,9 +1158,40 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { | ... | @@ -1124,9 +1158,40 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 { |
| 1124 | const value = system.getenv(key) orelse return null; | 1158 | const value = system.getenv(key) orelse return null; |
| 1125 | return mem.toSliceConst(u8, value); | 1159 | return mem.toSliceConst(u8, value); |
| 1126 | } | 1160 | } |
| 1161 | if (builtin.os == .windows) { | ||
| 1162 | @compileError("std.os.getenvZ is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API."); | ||
| 1163 | } | ||
| 1127 | return getenv(mem.toSliceConst(u8, key)); | 1164 | return getenv(mem.toSliceConst(u8, key)); |
| 1128 | } | 1165 | } |
| 1129 | 1166 | ||
| 1167 | /// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name. | ||
| 1168 | /// See also `getenv`. | ||
| 1169 | pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 { | ||
| 1170 | if (builtin.os != .windows) { | ||
| 1171 | @compileError("std.os.getenvW is a Windows-only API"); | ||
| 1172 | } | ||
| 1173 | const key_slice = mem.toSliceConst(u16, key); | ||
| 1174 | const ptr = windows.peb().ProcessParameters.Environment; | ||
| 1175 | var i: usize = 0; | ||
| 1176 | while (ptr[i] != 0) { | ||
| 1177 | const key_start = i; | ||
| 1178 | |||
| 1179 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} | ||
| 1180 | const this_key = ptr[key_start..i]; | ||
| 1181 | |||
| 1182 | if (ptr[i] == '=') i += 1; | ||
| 1183 | |||
| 1184 | const value_start = i; | ||
| 1185 | while (ptr[i] != 0) : (i += 1) {} | ||
| 1186 | const this_value = ptr[value_start..i :0]; | ||
| 1187 | |||
| 1188 | if (mem.eql(u16, key_slice, this_key)) return this_value; | ||
| 1189 | |||
| 1190 | i += 1; // skip over null byte | ||
| 1191 | } | ||
| 1192 | return null; | ||
| 1193 | } | ||
| 1194 | |||
| 1130 | pub const GetCwdError = error{ | 1195 | pub const GetCwdError = error{ |
| 1131 | NameTooLong, | 1196 | NameTooLong, |
| 1132 | CurrentWorkingDirectoryUnlinked, | 1197 | CurrentWorkingDirectoryUnlinked, |
lib/std/os/test.zig+8| ... | @@ -351,3 +351,11 @@ test "mmap" { | ... | @@ -351,3 +351,11 @@ test "mmap" { |
| 351 | 351 | ||
| 352 | try fs.cwd().deleteFile(test_out_file); | 352 | try fs.cwd().deleteFile(test_out_file); |
| 353 | } | 353 | } |
| 354 | |||
| 355 | test "getenv" { | ||
| 356 | if (builtin.os == .windows) { | ||
| 357 | expect(os.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null); | ||
| 358 | } else { | ||
| 359 | expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null); | ||
| 360 | } | ||
| 361 | } |
lib/std/os/windows/bits.zig+1-1| ... | @@ -1187,7 +1187,7 @@ pub const RTL_USER_PROCESS_PARAMETERS = extern struct { | ... | @@ -1187,7 +1187,7 @@ pub const RTL_USER_PROCESS_PARAMETERS = extern struct { |
| 1187 | DllPath: UNICODE_STRING, | 1187 | DllPath: UNICODE_STRING, |
| 1188 | ImagePathName: UNICODE_STRING, | 1188 | ImagePathName: UNICODE_STRING, |
| 1189 | CommandLine: UNICODE_STRING, | 1189 | CommandLine: UNICODE_STRING, |
| 1190 | Environment: [*]WCHAR, | 1190 | Environment: [*:0]WCHAR, |
| 1191 | dwX: ULONG, | 1191 | dwX: ULONG, |
| 1192 | dwY: ULONG, | 1192 | dwY: ULONG, |
| 1193 | dwXSize: ULONG, | 1193 | dwXSize: ULONG, |
lib/std/process.zig+35-41| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | ||
| 3 | const os = std.os; | 3 | const os = std.os; |
| 4 | const fs = std.fs; | 4 | const fs = std.fs; |
| 5 | const BufMap = std.BufMap; | 5 | const BufMap = std.BufMap; |
| ... | @@ -31,20 +31,16 @@ test "getCwdAlloc" { | ... | @@ -31,20 +31,16 @@ test "getCwdAlloc" { |
| 31 | testing.allocator.free(cwd); | 31 | testing.allocator.free(cwd); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | /// Caller must free result when done. | 34 | /// Caller owns resulting `BufMap`. |
| 35 | /// TODO make this go through libc when we have it | ||
| 36 | pub fn getEnvMap(allocator: *Allocator) !BufMap { | 35 | pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 37 | var result = BufMap.init(allocator); | 36 | var result = BufMap.init(allocator); |
| 38 | errdefer result.deinit(); | 37 | errdefer result.deinit(); |
| 39 | 38 | ||
| 40 | if (builtin.os == .windows) { | 39 | if (builtin.os == .windows) { |
| 41 | const ptr = try os.windows.GetEnvironmentStringsW(); | 40 | const ptr = os.windows.peb().ProcessParameters.Environment; |
| 42 | defer os.windows.FreeEnvironmentStringsW(ptr); | ||
| 43 | 41 | ||
| 44 | var i: usize = 0; | 42 | var i: usize = 0; |
| 45 | while (true) { | 43 | while (ptr[i] != 0) { |
| 46 | if (ptr[i] == 0) return result; | ||
| 47 | |||
| 48 | const key_start = i; | 44 | const key_start = i; |
| 49 | 45 | ||
| 50 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} | 46 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} |
| ... | @@ -64,6 +60,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -64,6 +60,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 64 | 60 | ||
| 65 | try result.setMove(key, value); | 61 | try result.setMove(key, value); |
| 66 | } | 62 | } |
| 63 | return result; | ||
| 67 | } else if (builtin.os == .wasi) { | 64 | } else if (builtin.os == .wasi) { |
| 68 | var environ_count: usize = undefined; | 65 | var environ_count: usize = undefined; |
| 69 | var environ_buf_size: usize = undefined; | 66 | var environ_buf_size: usize = undefined; |
| ... | @@ -95,15 +92,29 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -95,15 +92,29 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 95 | } | 92 | } |
| 96 | } | 93 | } |
| 97 | return result; | 94 | return result; |
| 95 | } else if (builtin.link_libc) { | ||
| 96 | var ptr = std.c.environ; | ||
| 97 | while (ptr.*) |line| : (ptr += 1) { | ||
| 98 | var line_i: usize = 0; | ||
| 99 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} | ||
| 100 | const key = line[0..line_i]; | ||
| 101 | |||
| 102 | var end_i: usize = line_i; | ||
| 103 | while (line[end_i] != 0) : (end_i += 1) {} | ||
| 104 | const value = line[line_i + 1 .. end_i]; | ||
| 105 | |||
| 106 | try result.set(key, value); | ||
| 107 | } | ||
| 108 | return result; | ||
| 98 | } else { | 109 | } else { |
| 99 | for (os.environ) |ptr| { | 110 | for (os.environ) |line| { |
| 100 | var line_i: usize = 0; | 111 | var line_i: usize = 0; |
| 101 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} | 112 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} |
| 102 | const key = ptr[0..line_i]; | 113 | const key = line[0..line_i]; |
| 103 | 114 | ||
| 104 | var end_i: usize = line_i; | 115 | var end_i: usize = line_i; |
| 105 | while (ptr[end_i] != 0) : (end_i += 1) {} | 116 | while (line[end_i] != 0) : (end_i += 1) {} |
| 106 | const value = ptr[line_i + 1 .. end_i]; | 117 | const value = line[line_i + 1 .. end_i]; |
| 107 | 118 | ||
| 108 | try result.set(key, value); | 119 | try result.set(key, value); |
| 109 | } | 120 | } |
| ... | @@ -125,37 +136,20 @@ pub const GetEnvVarOwnedError = error{ | ... | @@ -125,37 +136,20 @@ pub const GetEnvVarOwnedError = error{ |
| 125 | }; | 136 | }; |
| 126 | 137 | ||
| 127 | /// Caller must free returned memory. | 138 | /// Caller must free returned memory. |
| 128 | /// TODO make this go through libc when we have it | ||
| 129 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { | 139 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { |
| 130 | if (builtin.os == .windows) { | 140 | if (builtin.os == .windows) { |
| 131 | const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); | 141 | const result_w = blk: { |
| 132 | defer allocator.free(key_with_null); | 142 | const key_w = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); |
| 133 | 143 | defer allocator.free(key_w); | |
| 134 | var buf = try allocator.alloc(u16, 256); | ||
| 135 | defer allocator.free(buf); | ||
| 136 | |||
| 137 | while (true) { | ||
| 138 | const windows_buf_len = math.cast(os.windows.DWORD, buf.len) catch return error.OutOfMemory; | ||
| 139 | const result = os.windows.GetEnvironmentVariableW( | ||
| 140 | key_with_null.ptr, | ||
| 141 | buf.ptr, | ||
| 142 | windows_buf_len, | ||
| 143 | ) catch |err| switch (err) { | ||
| 144 | error.Unexpected => return error.EnvironmentVariableNotFound, | ||
| 145 | else => |e| return e, | ||
| 146 | }; | ||
| 147 | if (result > buf.len) { | ||
| 148 | buf = try allocator.realloc(buf, result); | ||
| 149 | continue; | ||
| 150 | } | ||
| 151 | 144 | ||
| 152 | return std.unicode.utf16leToUtf8Alloc(allocator, buf[0..result]) catch |err| switch (err) { | 145 | break :blk std.os.getenvW(key_w) orelse return error.EnvironmentVariableNotFound; |
| 153 | error.DanglingSurrogateHalf => return error.InvalidUtf8, | 146 | }; |
| 154 | error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, | 147 | return std.unicode.utf16leToUtf8Alloc(allocator, result_w) catch |err| switch (err) { |
| 155 | error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, | 148 | error.DanglingSurrogateHalf => return error.InvalidUtf8, |
| 156 | else => |e| return e, | 149 | error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, |
| 157 | }; | 150 | error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, |
| 158 | } | 151 | else => |e| return e, |
| 152 | }; | ||
| 159 | } else { | 153 | } else { |
| 160 | const result = os.getenv(key) orelse return error.EnvironmentVariableNotFound; | 154 | const result = os.getenv(key) orelse return error.EnvironmentVariableNotFound; |
| 161 | return mem.dupe(allocator, u8, result); | 155 | return mem.dupe(allocator, u8, result); |
lib/std/start.zig+8-2| ... | @@ -21,7 +21,9 @@ comptime { | ... | @@ -21,7 +21,9 @@ comptime { |
| 21 | @export(main, .{ .name = "main", .linkage = .Weak }); | 21 | @export(main, .{ .name = "main", .linkage = .Weak }); |
| 22 | } | 22 | } |
| 23 | } else if (builtin.os == .windows) { | 23 | } else if (builtin.os == .windows) { |
| 24 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) { | 24 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and |
| 25 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) | ||
| 26 | { | ||
| 25 | @export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" }); | 27 | @export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" }); |
| 26 | } | 28 | } |
| 27 | } else if (builtin.os == .uefi) { | 29 | } else if (builtin.os == .uefi) { |
| ... | @@ -34,7 +36,11 @@ comptime { | ... | @@ -34,7 +36,11 @@ comptime { |
| 34 | } | 36 | } |
| 35 | } | 37 | } |
| 36 | 38 | ||
| 37 | fn _DllMainCRTStartup(hinstDLL: std.os.windows.HINSTANCE, fdwReason: std.os.windows.DWORD, lpReserved: std.os.windows.LPVOID) callconv(.Stdcall) std.os.windows.BOOL { | 39 | fn _DllMainCRTStartup( |
| 40 | hinstDLL: std.os.windows.HINSTANCE, | ||
| 41 | fdwReason: std.os.windows.DWORD, | ||
| 42 | lpReserved: std.os.windows.LPVOID, | ||
| 43 | ) callconv(.Stdcall) std.os.windows.BOOL { | ||
| 38 | if (@hasDecl(root, "DllMain")) { | 44 | if (@hasDecl(root, "DllMain")) { |
| 39 | return root.DllMain(hinstDLL, fdwReason, lpReserved); | 45 | return root.DllMain(hinstDLL, fdwReason, lpReserved); |
| 40 | } | 46 | } |
lib/std/zig/system.zig+41-30| ... | @@ -5,6 +5,8 @@ const ArrayList = std.ArrayList; | ... | @@ -5,6 +5,8 @@ const ArrayList = std.ArrayList; |
| 5 | const assert = std.debug.assert; | 5 | const assert = std.debug.assert; |
| 6 | const process = std.process; | 6 | const process = std.process; |
| 7 | 7 | ||
| 8 | const is_windows = std.Target.current.isWindows(); | ||
| 9 | |||
| 8 | pub const NativePaths = struct { | 10 | pub const NativePaths = struct { |
| 9 | include_dirs: ArrayList([:0]u8), | 11 | include_dirs: ArrayList([:0]u8), |
| 10 | lib_dirs: ArrayList([:0]u8), | 12 | lib_dirs: ArrayList([:0]u8), |
| ... | @@ -21,7 +23,9 @@ pub const NativePaths = struct { | ... | @@ -21,7 +23,9 @@ pub const NativePaths = struct { |
| 21 | errdefer self.deinit(); | 23 | errdefer self.deinit(); |
| 22 | 24 | ||
| 23 | var is_nix = false; | 25 | var is_nix = false; |
| 24 | if (std.os.getenvZ("NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { | 26 | if (process.getEnvVarOwned(allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { |
| 27 | defer allocator.free(nix_cflags_compile); | ||
| 28 | |||
| 25 | is_nix = true; | 29 | is_nix = true; |
| 26 | var it = mem.tokenize(nix_cflags_compile, " "); | 30 | var it = mem.tokenize(nix_cflags_compile, " "); |
| 27 | while (true) { | 31 | while (true) { |
| ... | @@ -37,8 +41,14 @@ pub const NativePaths = struct { | ... | @@ -37,8 +41,14 @@ pub const NativePaths = struct { |
| 37 | break; | 41 | break; |
| 38 | } | 42 | } |
| 39 | } | 43 | } |
| 44 | } else |err| switch (err) { | ||
| 45 | error.InvalidUtf8 => {}, | ||
| 46 | error.EnvironmentVariableNotFound => {}, | ||
| 47 | error.OutOfMemory => |e| return e, | ||
| 40 | } | 48 | } |
| 41 | if (std.os.getenvZ("NIX_LDFLAGS")) |nix_ldflags| { | 49 | if (process.getEnvVarOwned(allocator, "NIX_LDFLAGS")) |nix_ldflags| { |
| 50 | defer allocator.free(nix_ldflags); | ||
| 51 | |||
| 42 | is_nix = true; | 52 | is_nix = true; |
| 43 | var it = mem.tokenize(nix_ldflags, " "); | 53 | var it = mem.tokenize(nix_ldflags, " "); |
| 44 | while (true) { | 54 | while (true) { |
| ... | @@ -57,39 +67,40 @@ pub const NativePaths = struct { | ... | @@ -57,39 +67,40 @@ pub const NativePaths = struct { |
| 57 | break; | 67 | break; |
| 58 | } | 68 | } |
| 59 | } | 69 | } |
| 70 | } else |err| switch (err) { | ||
| 71 | error.InvalidUtf8 => {}, | ||
| 72 | error.EnvironmentVariableNotFound => {}, | ||
| 73 | error.OutOfMemory => |e| return e, | ||
| 60 | } | 74 | } |
| 61 | if (is_nix) { | 75 | if (is_nix) { |
| 62 | return self; | 76 | return self; |
| 63 | } | 77 | } |
| 64 | 78 | ||
| 65 | switch (std.builtin.os) { | 79 | if (!is_windows) { |
| 66 | .windows => {}, | 80 | const triple = try std.Target.current.linuxTriple(allocator); |
| 67 | else => { | 81 | |
| 68 | const triple = try std.Target.current.linuxTriple(allocator); | 82 | // TODO: $ ld --verbose | grep SEARCH_DIR |
| 69 | 83 | // the output contains some paths that end with lib64, maybe include them too? | |
| 70 | // TODO: $ ld --verbose | grep SEARCH_DIR | 84 | // TODO: what is the best possible order of things? |
| 71 | // the output contains some paths that end with lib64, maybe include them too? | 85 | // TODO: some of these are suspect and should only be added on some systems. audit needed. |
| 72 | // TODO: what is the best possible order of things? | 86 | |
| 73 | // TODO: some of these are suspect and should only be added on some systems. audit needed. | 87 | try self.addIncludeDir("/usr/local/include"); |
| 74 | 88 | try self.addLibDir("/usr/local/lib"); | |
| 75 | try self.addIncludeDir("/usr/local/include"); | 89 | try self.addLibDir("/usr/local/lib64"); |
| 76 | try self.addLibDir("/usr/local/lib"); | 90 | |
| 77 | try self.addLibDir("/usr/local/lib64"); | 91 | try self.addIncludeDirFmt("/usr/include/{}", .{triple}); |
| 78 | 92 | try self.addLibDirFmt("/usr/lib/{}", .{triple}); | |
| 79 | try self.addIncludeDirFmt("/usr/include/{}", .{triple}); | 93 | |
| 80 | try self.addLibDirFmt("/usr/lib/{}", .{triple}); | 94 | try self.addIncludeDir("/usr/include"); |
| 81 | 95 | try self.addLibDir("/lib"); | |
| 82 | try self.addIncludeDir("/usr/include"); | 96 | try self.addLibDir("/lib64"); |
| 83 | try self.addLibDir("/lib"); | 97 | try self.addLibDir("/usr/lib"); |
| 84 | try self.addLibDir("/lib64"); | 98 | try self.addLibDir("/usr/lib64"); |
| 85 | try self.addLibDir("/usr/lib"); | 99 | |
| 86 | try self.addLibDir("/usr/lib64"); | 100 | // example: on a 64-bit debian-based linux distro, with zlib installed from apt: |
| 87 | 101 | // zlib.h is in /usr/include (added above) | |
| 88 | // example: on a 64-bit debian-based linux distro, with zlib installed from apt: | 102 | // libz.so.1 is in /lib/x86_64-linux-gnu (added here) |
| 89 | // zlib.h is in /usr/include (added above) | 103 | try self.addLibDirFmt("/lib/{}", .{triple}); |
| 90 | // libz.so.1 is in /lib/x86_64-linux-gnu (added here) | ||
| 91 | try self.addLibDirFmt("/lib/{}", .{triple}); | ||
| 92 | }, | ||
| 93 | } | 104 | } |
| 94 | 105 | ||
| 95 | return self; | 106 | return self; |
src/os.cpp+1-5| ... | @@ -81,11 +81,7 @@ static clock_serv_t macos_monotonic_clock; | ... | @@ -81,11 +81,7 @@ static clock_serv_t macos_monotonic_clock; |
| 81 | #include <errno.h> | 81 | #include <errno.h> |
| 82 | #include <time.h> | 82 | #include <time.h> |
| 83 | 83 | ||
| 84 | // Apple doesn't provide the environ global variable | 84 | #if !defined(environ) |
| 85 | #if defined(__APPLE__) && !defined(environ) | ||
| 86 | #include <crt_externs.h> | ||
| 87 | #define environ (*_NSGetEnviron()) | ||
| 88 | #elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY) | ||
| 89 | extern char **environ; | 85 | extern char **environ; |
| 90 | #endif | 86 | #endif |
| 91 | 87 |