| 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 | 62 | }; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | pub extern "c" var environ: [*:null]?[*:0]u8; | |
| 66 | ||
| 65 | 67 | pub extern "c" fn fopen(filename: [*:0]const u8, modes: [*:0]const u8) ?*FILE; |
| 66 | 68 | pub extern "c" fn fclose(stream: *FILE) c_int; |
| 67 | 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 | 70 | pub usingnamespace @import("os/bits.zig"); |
| 71 | 71 | |
| 72 | 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 | 75 | pub var environ: [][*:0]u8 = undefined; |
| 74 | 76 | |
| 75 | 77 | /// Populated by startup code before main(). |
| ... | ... | @@ -922,7 +924,11 @@ pub const execveC = execveZ; |
| 922 | 924 | /// Like `execve` except the parameters are null-terminated, |
| 923 | 925 | /// matching the syscall API on all targets. This removes the need for an allocator. |
| 924 | 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 | 932 | switch (errno(system.execve(path, child_argv, envp))) { |
| 927 | 933 | 0 => unreachable, |
| 928 | 934 | EFAULT => unreachable, |
| ... | ... | @@ -966,7 +972,7 @@ pub fn execvpeZ_expandArg0( |
| 966 | 972 | envp: [*:null]const ?[*:0]const u8, |
| 967 | 973 | ) ExecveError { |
| 968 | 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 | 977 | const PATH = getenvZ("PATH") orelse "/usr/local/bin:/bin/:/usr/bin"; |
| 972 | 978 | var path_buf: [MAX_PATH_BYTES]u8 = undefined; |
| ... | ... | @@ -993,7 +999,7 @@ pub fn execvpeZ_expandArg0( |
| 993 | 999 | .expand => child_argv[0] = full_path, |
| 994 | 1000 | .no_expand => {}, |
| 995 | 1001 | } |
| 996 | err = execveC(full_path, child_argv, envp); | |
| 1002 | err = execveZ(full_path, child_argv, envp); | |
| 997 | 1003 | switch (err) { |
| 998 | 1004 | error.AccessDenied => seen_eacces = true, |
| 999 | 1005 | error.FileNotFound, error.NotDir => {}, |
| ... | ... | @@ -1007,7 +1013,7 @@ pub fn execvpeZ_expandArg0( |
| 1007 | 1013 | /// Like `execvpe` except the parameters are null-terminated, |
| 1008 | 1014 | /// matching the syscall API on all targets. This removes the need for an allocator. |
| 1009 | 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 | 1017 | pub fn execvpeZ( |
| 1012 | 1018 | file: [*:0]const u8, |
| 1013 | 1019 | argv: [*:null]const ?[*:0]const u8, |
| ... | ... | @@ -1097,8 +1103,36 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) |
| 1097 | 1103 | |
| 1098 | 1104 | /// Get an environment variable. |
| 1099 | 1105 | /// See also `getenvZ`. |
| 1100 | /// TODO make this go through libc when we have it | |
| 1101 | 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 | 1136 | for (environ) |ptr| { |
| 1103 | 1137 | var line_i: usize = 0; |
| 1104 | 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 | 1158 | const value = system.getenv(key) orelse return null; |
| 1125 | 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 | 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 | 1195 | pub const GetCwdError = error{ |
| 1131 | 1196 | NameTooLong, |
| 1132 | 1197 | CurrentWorkingDirectoryUnlinked, |
lib/std/os/test.zig+8| ... | ... | @@ -351,3 +351,11 @@ test "mmap" { |
| 351 | 351 | |
| 352 | 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 | 1187 | DllPath: UNICODE_STRING, |
| 1188 | 1188 | ImagePathName: UNICODE_STRING, |
| 1189 | 1189 | CommandLine: UNICODE_STRING, |
| 1190 | Environment: [*]WCHAR, | |
| 1190 | Environment: [*:0]WCHAR, | |
| 1191 | 1191 | dwX: ULONG, |
| 1192 | 1192 | dwY: ULONG, |
| 1193 | 1193 | dwXSize: ULONG, |
lib/std/process.zig+35-41| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | 1 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | |
| 3 | 3 | const os = std.os; |
| 4 | 4 | const fs = std.fs; |
| 5 | 5 | const BufMap = std.BufMap; |
| ... | ... | @@ -31,20 +31,16 @@ test "getCwdAlloc" { |
| 31 | 31 | testing.allocator.free(cwd); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | /// Caller must free result when done. | |
| 35 | /// TODO make this go through libc when we have it | |
| 34 | /// Caller owns resulting `BufMap`. | |
| 36 | 35 | pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 37 | 36 | var result = BufMap.init(allocator); |
| 38 | 37 | errdefer result.deinit(); |
| 39 | 38 | |
| 40 | 39 | if (builtin.os == .windows) { |
| 41 | const ptr = try os.windows.GetEnvironmentStringsW(); | |
| 42 | defer os.windows.FreeEnvironmentStringsW(ptr); | |
| 40 | const ptr = os.windows.peb().ProcessParameters.Environment; | |
| 43 | 41 | |
| 44 | 42 | var i: usize = 0; |
| 45 | while (true) { | |
| 46 | if (ptr[i] == 0) return result; | |
| 47 | ||
| 43 | while (ptr[i] != 0) { | |
| 48 | 44 | const key_start = i; |
| 49 | 45 | |
| 50 | 46 | while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {} |
| ... | ... | @@ -64,6 +60,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 64 | 60 | |
| 65 | 61 | try result.setMove(key, value); |
| 66 | 62 | } |
| 63 | return result; | |
| 67 | 64 | } else if (builtin.os == .wasi) { |
| 68 | 65 | var environ_count: usize = undefined; |
| 69 | 66 | var environ_buf_size: usize = undefined; |
| ... | ... | @@ -95,15 +92,29 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 95 | 92 | } |
| 96 | 93 | } |
| 97 | 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 | 109 | } else { |
| 99 | for (os.environ) |ptr| { | |
| 110 | for (os.environ) |line| { | |
| 100 | 111 | var line_i: usize = 0; |
| 101 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} | |
| 102 | const key = ptr[0..line_i]; | |
| 112 | while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} | |
| 113 | const key = line[0..line_i]; | |
| 103 | 114 | |
| 104 | 115 | var end_i: usize = line_i; |
| 105 | while (ptr[end_i] != 0) : (end_i += 1) {} | |
| 106 | const value = ptr[line_i + 1 .. end_i]; | |
| 116 | while (line[end_i] != 0) : (end_i += 1) {} | |
| 117 | const value = line[line_i + 1 .. end_i]; | |
| 107 | 118 | |
| 108 | 119 | try result.set(key, value); |
| 109 | 120 | } |
| ... | ... | @@ -125,37 +136,20 @@ pub const GetEnvVarOwnedError = error{ |
| 125 | 136 | }; |
| 126 | 137 | |
| 127 | 138 | /// Caller must free returned memory. |
| 128 | /// TODO make this go through libc when we have it | |
| 129 | 139 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { |
| 130 | 140 | if (builtin.os == .windows) { |
| 131 | const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); | |
| 132 | defer allocator.free(key_with_null); | |
| 133 | ||
| 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 | } | |
| 141 | const result_w = blk: { | |
| 142 | const key_w = try std.unicode.utf8ToUtf16LeWithNull(allocator, key); | |
| 143 | defer allocator.free(key_w); | |
| 151 | 144 | |
| 152 | return std.unicode.utf16leToUtf8Alloc(allocator, buf[0..result]) catch |err| switch (err) { | |
| 153 | error.DanglingSurrogateHalf => return error.InvalidUtf8, | |
| 154 | error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, | |
| 155 | error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, | |
| 156 | else => |e| return e, | |
| 157 | }; | |
| 158 | } | |
| 145 | break :blk std.os.getenvW(key_w) orelse return error.EnvironmentVariableNotFound; | |
| 146 | }; | |
| 147 | return std.unicode.utf16leToUtf8Alloc(allocator, result_w) catch |err| switch (err) { | |
| 148 | error.DanglingSurrogateHalf => return error.InvalidUtf8, | |
| 149 | error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, | |
| 150 | error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, | |
| 151 | else => |e| return e, | |
| 152 | }; | |
| 159 | 153 | } else { |
| 160 | 154 | const result = os.getenv(key) orelse return error.EnvironmentVariableNotFound; |
| 161 | 155 | return mem.dupe(allocator, u8, result); |
lib/std/start.zig+8-2| ... | ... | @@ -21,7 +21,9 @@ comptime { |
| 21 | 21 | @export(main, .{ .name = "main", .linkage = .Weak }); |
| 22 | 22 | } |
| 23 | 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 | 27 | @export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" }); |
| 26 | 28 | } |
| 27 | 29 | } else if (builtin.os == .uefi) { |
| ... | ... | @@ -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 | 44 | if (@hasDecl(root, "DllMain")) { |
| 39 | 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 | 5 | const assert = std.debug.assert; |
| 6 | 6 | const process = std.process; |
| 7 | 7 | |
| 8 | const is_windows = std.Target.current.isWindows(); | |
| 9 | ||
| 8 | 10 | pub const NativePaths = struct { |
| 9 | 11 | include_dirs: ArrayList([:0]u8), |
| 10 | 12 | lib_dirs: ArrayList([:0]u8), |
| ... | ... | @@ -21,7 +23,9 @@ pub const NativePaths = struct { |
| 21 | 23 | errdefer self.deinit(); |
| 22 | 24 | |
| 23 | 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 | 29 | is_nix = true; |
| 26 | 30 | var it = mem.tokenize(nix_cflags_compile, " "); |
| 27 | 31 | while (true) { |
| ... | ... | @@ -37,8 +41,14 @@ pub const NativePaths = struct { |
| 37 | 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 | 52 | is_nix = true; |
| 43 | 53 | var it = mem.tokenize(nix_ldflags, " "); |
| 44 | 54 | while (true) { |
| ... | ... | @@ -57,39 +67,40 @@ pub const NativePaths = struct { |
| 57 | 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 | 75 | if (is_nix) { |
| 62 | 76 | return self; |
| 63 | 77 | } |
| 64 | 78 | |
| 65 | switch (std.builtin.os) { | |
| 66 | .windows => {}, | |
| 67 | else => { | |
| 68 | const triple = try std.Target.current.linuxTriple(allocator); | |
| 69 | ||
| 70 | // TODO: $ ld --verbose | grep SEARCH_DIR | |
| 71 | // the output contains some paths that end with lib64, maybe include them too? | |
| 72 | // TODO: what is the best possible order of things? | |
| 73 | // TODO: some of these are suspect and should only be added on some systems. audit needed. | |
| 74 | ||
| 75 | try self.addIncludeDir("/usr/local/include"); | |
| 76 | try self.addLibDir("/usr/local/lib"); | |
| 77 | try self.addLibDir("/usr/local/lib64"); | |
| 78 | ||
| 79 | try self.addIncludeDirFmt("/usr/include/{}", .{triple}); | |
| 80 | try self.addLibDirFmt("/usr/lib/{}", .{triple}); | |
| 81 | ||
| 82 | try self.addIncludeDir("/usr/include"); | |
| 83 | try self.addLibDir("/lib"); | |
| 84 | try self.addLibDir("/lib64"); | |
| 85 | try self.addLibDir("/usr/lib"); | |
| 86 | try self.addLibDir("/usr/lib64"); | |
| 87 | ||
| 88 | // example: on a 64-bit debian-based linux distro, with zlib installed from apt: | |
| 89 | // zlib.h is in /usr/include (added above) | |
| 90 | // libz.so.1 is in /lib/x86_64-linux-gnu (added here) | |
| 91 | try self.addLibDirFmt("/lib/{}", .{triple}); | |
| 92 | }, | |
| 79 | if (!is_windows) { | |
| 80 | const triple = try std.Target.current.linuxTriple(allocator); | |
| 81 | ||
| 82 | // TODO: $ ld --verbose | grep SEARCH_DIR | |
| 83 | // the output contains some paths that end with lib64, maybe include them too? | |
| 84 | // TODO: what is the best possible order of things? | |
| 85 | // TODO: some of these are suspect and should only be added on some systems. audit needed. | |
| 86 | ||
| 87 | try self.addIncludeDir("/usr/local/include"); | |
| 88 | try self.addLibDir("/usr/local/lib"); | |
| 89 | try self.addLibDir("/usr/local/lib64"); | |
| 90 | ||
| 91 | try self.addIncludeDirFmt("/usr/include/{}", .{triple}); | |
| 92 | try self.addLibDirFmt("/usr/lib/{}", .{triple}); | |
| 93 | ||
| 94 | try self.addIncludeDir("/usr/include"); | |
| 95 | try self.addLibDir("/lib"); | |
| 96 | try self.addLibDir("/lib64"); | |
| 97 | try self.addLibDir("/usr/lib"); | |
| 98 | try self.addLibDir("/usr/lib64"); | |
| 99 | ||
| 100 | // example: on a 64-bit debian-based linux distro, with zlib installed from apt: | |
| 101 | // zlib.h is in /usr/include (added above) | |
| 102 | // libz.so.1 is in /lib/x86_64-linux-gnu (added here) | |
| 103 | try self.addLibDirFmt("/lib/{}", .{triple}); | |
| 93 | 104 | } |
| 94 | 105 | |
| 95 | 106 | return self; |
src/os.cpp+1-5| ... | ... | @@ -81,11 +81,7 @@ static clock_serv_t macos_monotonic_clock; |
| 81 | 81 | #include <errno.h> |
| 82 | 82 | #include <time.h> |
| 83 | 83 | |
| 84 | // Apple doesn't provide the environ global variable | |
| 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) | |
| 84 | #if !defined(environ) | |
| 89 | 85 | extern char **environ; |
| 90 | 86 | #endif |
| 91 | 87 |