Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2019 Andrew Kelley
3 : : *
4 : : * This file is part of zig, which is MIT licensed.
5 : : * See http://opensource.org/licenses/MIT
6 : : */
7 : :
8 : : #include "libc_installation.hpp"
9 : : #include "os.hpp"
10 : : #include "windows_sdk.h"
11 : : #include "target.hpp"
12 : :
13 : : static const char *zig_libc_keys[] = {
14 : : "include_dir",
15 : : "sys_include_dir",
16 : : "crt_dir",
17 : : "static_crt_dir",
18 : : "msvc_lib_dir",
19 : : "kernel32_lib_dir",
20 : : };
21 : :
22 : : static const size_t zig_libc_keys_len = array_length(zig_libc_keys);
23 : :
24 : 0 : static bool zig_libc_match_key(Slice<uint8_t> name, Slice<uint8_t> value, bool *found_keys,
25 : : size_t index, Buf *field_ptr)
26 : : {
27 [ # # ]: 0 : if (!memEql(name, str(zig_libc_keys[index]))) return false;
28 : 0 : buf_init_from_mem(field_ptr, (const char*)value.ptr, value.len);
29 : 0 : found_keys[index] = true;
30 : 0 : return true;
31 : : }
32 : :
33 : 0 : static void zig_libc_init_empty(ZigLibCInstallation *libc) {
34 : 0 : *libc = {};
35 : 0 : buf_init_from_str(&libc->include_dir, "");
36 : 0 : buf_init_from_str(&libc->sys_include_dir, "");
37 : 0 : buf_init_from_str(&libc->crt_dir, "");
38 : 0 : buf_init_from_str(&libc->static_crt_dir, "");
39 : 0 : buf_init_from_str(&libc->msvc_lib_dir, "");
40 : 0 : buf_init_from_str(&libc->kernel32_lib_dir, "");
41 : 0 : }
42 : :
43 : 0 : Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget *target, bool verbose) {
44 : : Error err;
45 : 0 : zig_libc_init_empty(libc);
46 : :
47 : 0 : bool found_keys[array_length(zig_libc_keys)] = {};
48 : :
49 : 0 : Buf *contents = buf_alloc();
50 [ # # ]: 0 : if ((err = os_fetch_file_path(libc_file, contents))) {
51 [ # # ][ # # ]: 0 : if (err != ErrorFileNotFound && verbose) {
52 : 0 : fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err));
53 : : }
54 : 0 : return err;
55 : : }
56 : :
57 : 0 : SplitIterator it = memSplit(buf_to_slice(contents), str("\n"));
58 : : for (;;) {
59 : 0 : Optional<Slice<uint8_t>> opt_line = SplitIterator_next(&it);
60 [ # # ]: 0 : if (!opt_line.is_some)
61 : 0 : break;
62 : :
63 [ # # ][ # # ]: 0 : if (opt_line.value.len == 0 || opt_line.value.ptr[0] == '#')
64 : 0 : continue;
65 : :
66 : 0 : SplitIterator line_it = memSplit(opt_line.value, str("="));
67 : : Slice<uint8_t> name;
68 [ # # ]: 0 : if (!SplitIterator_next(&line_it).unwrap(&name)) {
69 [ # # ]: 0 : if (verbose) {
70 : 0 : fprintf(stderr, "missing equal sign after field name\n");
71 : : }
72 : 0 : return ErrorSemanticAnalyzeFail;
73 : : }
74 : 0 : Slice<uint8_t> value = SplitIterator_rest(&line_it);
75 : 0 : bool match = false;
76 [ # # ][ # # ]: 0 : match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir);
77 [ # # ][ # # ]: 0 : match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->sys_include_dir);
78 [ # # ][ # # ]: 0 : match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_dir);
79 [ # # ][ # # ]: 0 : match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->static_crt_dir);
80 [ # # ][ # # ]: 0 : match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->msvc_lib_dir);
81 [ # # ][ # # ]: 0 : match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->kernel32_lib_dir);
82 : 0 : }
83 : :
84 [ # # ]: 0 : for (size_t i = 0; i < zig_libc_keys_len; i += 1) {
85 [ # # ]: 0 : if (!found_keys[i]) {
86 [ # # ]: 0 : if (verbose) {
87 : 0 : fprintf(stderr, "missing field: %s\n", zig_libc_keys[i]);
88 : : }
89 : 0 : return ErrorSemanticAnalyzeFail;
90 : : }
91 : : }
92 : :
93 [ # # ]: 0 : if (buf_len(&libc->include_dir) == 0) {
94 [ # # ]: 0 : if (verbose) {
95 : 0 : fprintf(stderr, "include_dir may not be empty\n");
96 : : }
97 : 0 : return ErrorSemanticAnalyzeFail;
98 : : }
99 : :
100 [ # # ]: 0 : if (buf_len(&libc->sys_include_dir) == 0) {
101 [ # # ]: 0 : if (verbose) {
102 : 0 : fprintf(stderr, "sys_include_dir may not be empty\n");
103 : : }
104 : 0 : return ErrorSemanticAnalyzeFail;
105 : : }
106 : :
107 [ # # ]: 0 : if (buf_len(&libc->crt_dir) == 0) {
108 [ # # ]: 0 : if (!target_os_is_darwin(target->os)) {
109 [ # # ]: 0 : if (verbose) {
110 : 0 : fprintf(stderr, "crt_dir may not be empty for %s\n", target_os_name(target->os));
111 : : }
112 : 0 : return ErrorSemanticAnalyzeFail;
113 : : }
114 : : }
115 : :
116 [ # # ]: 0 : if (buf_len(&libc->static_crt_dir) == 0) {
117 [ # # ][ # # ]: 0 : if (target->os == OsWindows && target_abi_is_gnu(target->abi)) {
[ # # ]
118 [ # # ]: 0 : if (verbose) {
119 : 0 : fprintf(stderr, "static_crt_dir may not be empty for %s\n", target_os_name(target->os));
120 : : }
121 : 0 : return ErrorSemanticAnalyzeFail;
122 : : }
123 : : }
124 : :
125 [ # # ]: 0 : if (buf_len(&libc->msvc_lib_dir) == 0) {
126 [ # # ][ # # ]: 0 : if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) {
[ # # ]
127 [ # # ]: 0 : if (verbose) {
128 : 0 : fprintf(stderr, "msvc_lib_dir may not be empty for %s\n", target_os_name(target->os));
129 : : }
130 : 0 : return ErrorSemanticAnalyzeFail;
131 : : }
132 : : }
133 : :
134 [ # # ]: 0 : if (buf_len(&libc->kernel32_lib_dir) == 0) {
135 [ # # ][ # # ]: 0 : if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) {
[ # # ]
136 [ # # ]: 0 : if (verbose) {
137 : 0 : fprintf(stderr, "kernel32_lib_dir may not be empty for %s\n", target_os_name(target->os));
138 : : }
139 : 0 : return ErrorSemanticAnalyzeFail;
140 : : }
141 : : }
142 : :
143 : 0 : return ErrorNone;
144 : : }
145 : :
146 : : #if defined(ZIG_OS_WINDOWS)
147 : : #define CC_EXE "cc.exe"
148 : : #else
149 : : #define CC_EXE "cc"
150 : : #endif
151 : :
152 : 0 : static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, bool verbose) {
153 : 0 : const char *cc_exe = getenv("CC");
154 [ # # ]: 0 : cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe;
155 : 0 : ZigList<const char *> args = {};
156 : 0 : args.append(cc_exe);
157 : 0 : args.append("-E");
158 : 0 : args.append("-Wp,-v");
159 : 0 : args.append("-xc");
160 : : #if defined(ZIG_OS_WINDOWS)
161 : : args.append("nul");
162 : : #else
163 : 0 : args.append("/dev/null");
164 : : #endif
165 : :
166 : : Termination term;
167 : 0 : Buf *out_stderr = buf_alloc();
168 : 0 : Buf *out_stdout = buf_alloc();
169 : : Error err;
170 [ # # ]: 0 : if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) {
171 [ # # ]: 0 : if (verbose) {
172 : 0 : fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err));
173 : : }
174 : 0 : return err;
175 : : }
176 [ # # ][ # # ]: 0 : if (term.how != TerminationIdClean || term.code != 0) {
177 [ # # ]: 0 : if (verbose) {
178 : 0 : fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe);
179 : : }
180 : 0 : return ErrorCCompileErrors;
181 : : }
182 : 0 : char *prev_newline = buf_ptr(out_stderr);
183 : 0 : ZigList<const char *> search_paths = {};
184 : : for (;;) {
185 : 0 : char *newline = strchr(prev_newline, '\n');
186 [ # # ]: 0 : if (newline == nullptr) {
187 : 0 : break;
188 : : }
189 : :
190 : : #if defined(ZIG_OS_WINDOWS)
191 : : *(newline - 1) = 0;
192 : : #endif
193 : 0 : *newline = 0;
194 : :
195 [ # # ]: 0 : if (prev_newline[0] == ' ') {
196 : 0 : search_paths.append(prev_newline);
197 : : }
198 : 0 : prev_newline = newline + 1;
199 : 0 : }
200 [ # # ]: 0 : if (search_paths.length == 0) {
201 [ # # ]: 0 : if (verbose) {
202 : 0 : fprintf(stderr, "unable to determine libc include path: '%s' cannot find libc headers\n", cc_exe);
203 : : }
204 : 0 : return ErrorCCompileErrors;
205 : : }
206 [ # # ]: 0 : for (size_t i = 0; i < search_paths.length; i += 1) {
207 : : // search in reverse order
208 : 0 : const char *search_path = search_paths.items[search_paths.length - i - 1];
209 : : // cut off spaces
210 [ # # ]: 0 : while (*search_path == ' ') {
211 : 0 : search_path += 1;
212 : : }
213 : :
214 : : #if defined(ZIG_OS_WINDOWS)
215 : : if (buf_len(&self->include_dir) == 0) {
216 : : Buf *stdlib_path = buf_sprintf("%s\\stdlib.h", search_path);
217 : : bool exists;
218 : : if ((err = os_file_exists(stdlib_path, &exists))) {
219 : : exists = false;
220 : : }
221 : : if (exists) {
222 : : buf_init_from_str(&self->include_dir, search_path);
223 : : }
224 : : }
225 : : if (buf_len(&self->sys_include_dir) == 0) {
226 : : Buf *stdlib_path = buf_sprintf("%s\\sys\\types.h", search_path);
227 : : bool exists;
228 : : if ((err = os_file_exists(stdlib_path, &exists))) {
229 : : exists = false;
230 : : }
231 : : if (exists) {
232 : : buf_init_from_str(&self->sys_include_dir, search_path);
233 : : }
234 : : }
235 : : #else
236 [ # # ]: 0 : if (buf_len(&self->include_dir) == 0) {
237 : 0 : Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path);
238 : : bool exists;
239 [ # # ]: 0 : if ((err = os_file_exists(stdlib_path, &exists))) {
240 : 0 : exists = false;
241 : : }
242 [ # # ]: 0 : if (exists) {
243 : 0 : buf_init_from_str(&self->include_dir, search_path);
244 : : }
245 : : }
246 [ # # ]: 0 : if (buf_len(&self->sys_include_dir) == 0) {
247 : 0 : Buf *stdlib_path = buf_sprintf("%s/sys/errno.h", search_path);
248 : : bool exists;
249 [ # # ]: 0 : if ((err = os_file_exists(stdlib_path, &exists))) {
250 : 0 : exists = false;
251 : : }
252 [ # # ]: 0 : if (exists) {
253 : 0 : buf_init_from_str(&self->sys_include_dir, search_path);
254 : : }
255 : : }
256 : : #endif
257 : :
258 [ # # ][ # # ]: 0 : if (buf_len(&self->include_dir) != 0 && buf_len(&self->sys_include_dir) != 0) {
[ # # ]
259 : 0 : return ErrorNone;
260 : : }
261 : : }
262 [ # # ]: 0 : if (verbose) {
263 [ # # ]: 0 : if (buf_len(&self->include_dir) == 0) {
264 : 0 : fprintf(stderr, "unable to determine libc include path: stdlib.h not found in '%s' search paths\n", cc_exe);
265 : : }
266 [ # # ]: 0 : if (buf_len(&self->sys_include_dir) == 0) {
267 : : #if defined(ZIG_OS_WINDOWS)
268 : : fprintf(stderr, "unable to determine libc include path: sys/types.h not found in '%s' search paths\n", cc_exe);
269 : : #else
270 : 0 : fprintf(stderr, "unable to determine libc include path: sys/errno.h not found in '%s' search paths\n", cc_exe);
271 : : #endif
272 : : }
273 : : }
274 : 0 : return ErrorFileNotFound;
275 : : }
276 : :
277 : 0 : Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose) {
278 : 0 : const char *cc_exe = getenv("CC");
279 [ # # ]: 0 : cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe;
280 : 0 : ZigList<const char *> args = {};
281 : 0 : args.append(cc_exe);
282 : 0 : args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file)));
283 : : Termination term;
284 : 0 : Buf *out_stderr = buf_alloc();
285 : 0 : Buf *out_stdout = buf_alloc();
286 : : Error err;
287 [ # # ]: 0 : if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) {
288 [ # # ]: 0 : if (err == ErrorFileNotFound)
289 : 0 : return ErrorNoCCompilerInstalled;
290 [ # # ]: 0 : if (verbose) {
291 : 0 : fprintf(stderr, "unable to determine libc library path: executing '%s': %s\n", cc_exe, err_str(err));
292 : : }
293 : 0 : return err;
294 : : }
295 [ # # ][ # # ]: 0 : if (term.how != TerminationIdClean || term.code != 0) {
296 [ # # ]: 0 : if (verbose) {
297 : 0 : fprintf(stderr, "unable to determine libc library path: executing '%s' failed\n", cc_exe);
298 : : }
299 : 0 : return ErrorCCompileErrors;
300 : : }
301 : : #if defined(ZIG_OS_WINDOWS)
302 : : if (buf_ends_with_str(out_stdout, "\r\n")) {
303 : : buf_resize(out_stdout, buf_len(out_stdout) - 2);
304 : : }
305 : : #else
306 [ # # ]: 0 : if (buf_ends_with_str(out_stdout, "\n")) {
307 : 0 : buf_resize(out_stdout, buf_len(out_stdout) - 1);
308 : : }
309 : : #endif
310 [ # # ][ # # ]: 0 : if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) {
[ # # ]
311 : 0 : return ErrorCCompilerCannotFindFile;
312 : : }
313 [ # # ]: 0 : if (want_dirname) {
314 : 0 : os_path_dirname(out_stdout, out);
315 : : } else {
316 : 0 : buf_init_from_buf(out, out_stdout);
317 : : }
318 : 0 : return ErrorNone;
319 : : }
320 : :
321 : : #undef CC_EXE
322 : :
323 : : #if defined(ZIG_OS_WINDOWS) || defined(ZIG_OS_LINUX)
324 : 0 : static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool verbose) {
325 : 0 : return zig_libc_cc_print_file_name("crt1.o", &self->crt_dir, true, verbose);
326 : : }
327 : : #endif
328 : :
329 : : #if defined(ZIG_OS_WINDOWS)
330 : : static Error zig_libc_find_native_static_crt_dir_posix(ZigLibCInstallation *self, bool verbose) {
331 : : return zig_libc_cc_print_file_name("crtbegin.o", &self->static_crt_dir, true, verbose);
332 : : }
333 : :
334 : : static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
335 : : Error err;
336 : : if ((err = os_get_win32_ucrt_include_path(sdk, &self->include_dir))) {
337 : : if (verbose) {
338 : : fprintf(stderr, "Unable to determine libc include path: %s\n", err_str(err));
339 : : }
340 : : return err;
341 : : }
342 : : return ErrorNone;
343 : : }
344 : :
345 : : static Error zig_libc_find_native_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
346 : : bool verbose)
347 : : {
348 : : Error err;
349 : : if ((err = os_get_win32_ucrt_lib_path(sdk, &self->crt_dir, target->arch))) {
350 : : if (verbose) {
351 : : fprintf(stderr, "Unable to determine ucrt path: %s\n", err_str(err));
352 : : }
353 : : return err;
354 : : }
355 : : return ErrorNone;
356 : : }
357 : :
358 : : static Error zig_libc_find_kernel32_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
359 : : bool verbose)
360 : : {
361 : : Error err;
362 : : if ((err = os_get_win32_kern32_path(sdk, &self->kernel32_lib_dir, target->arch))) {
363 : : if (verbose) {
364 : : fprintf(stderr, "Unable to determine kernel32 path: %s\n", err_str(err));
365 : : }
366 : : return err;
367 : : }
368 : : return ErrorNone;
369 : : }
370 : :
371 : : static Error zig_libc_find_native_msvc_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
372 : : if (sdk->msvc_lib_dir_ptr == nullptr) {
373 : : if (verbose) {
374 : : fprintf(stderr, "Unable to determine vcruntime.lib path\n");
375 : : }
376 : : return ErrorFileNotFound;
377 : : }
378 : : buf_init_from_mem(&self->msvc_lib_dir, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len);
379 : : return ErrorNone;
380 : : }
381 : :
382 : : static Error zig_libc_find_native_msvc_include_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
383 : : Error err;
384 : : if (sdk->msvc_lib_dir_ptr == nullptr) {
385 : : if (verbose) {
386 : : fprintf(stderr, "Unable to determine vcruntime.h path\n");
387 : : }
388 : : return ErrorFileNotFound;
389 : : }
390 : : Buf search_path = BUF_INIT;
391 : : buf_init_from_mem(&search_path, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len);
392 : : buf_append_str(&search_path, "\\..\\..\\include");
393 : :
394 : : Buf *vcruntime_path = buf_sprintf("%s\\vcruntime.h", buf_ptr(&search_path));
395 : : bool exists;
396 : : if ((err = os_file_exists(vcruntime_path, &exists))) {
397 : : exists = false;
398 : : }
399 : : if (exists) {
400 : : self->sys_include_dir = search_path;
401 : : return ErrorNone;
402 : : }
403 : :
404 : : if (verbose) {
405 : : fprintf(stderr, "Unable to determine vcruntime.h path\n");
406 : : }
407 : : return ErrorFileNotFound;
408 : : }
409 : : #endif
410 : :
411 : 0 : void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
412 : 0 : fprintf(file,
413 : : "# The directory that contains `stdlib.h`.\n"
414 : : "# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`\n"
415 : : "include_dir=%s\n"
416 : : "# The system-specific include directory. May be the same as `include_dir`.\n"
417 : : "# On Windows it's the directory that includes `vcruntime.h`.\n"
418 : : "# On POSIX it's the directory that includes `sys/errno.h`.\n"
419 : : "sys_include_dir=%s\n"
420 : : "\n"
421 : : "# The directory that contains `crt1.o` or `crt2.o`.\n"
422 : : "# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n"
423 : : "# Not needed when targeting MacOS.\n"
424 : : "crt_dir=%s\n"
425 : : "\n"
426 : : "# The directory that contains `crtbegin.o`.\n"
427 : : "# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.\n"
428 : : "# Not needed when targeting MacOS.\n"
429 : : "static_crt_dir=%s\n"
430 : : "\n"
431 : : "# The directory that contains `vcruntime.lib`.\n"
432 : : "# Only needed when targeting MSVC on Windows.\n"
433 : : "msvc_lib_dir=%s\n"
434 : : "\n"
435 : : "# The directory that contains `kernel32.lib`.\n"
436 : : "# Only needed when targeting MSVC on Windows.\n"
437 : : "kernel32_lib_dir=%s\n"
438 : : "\n"
439 : : ,
440 : : buf_ptr(&self->include_dir),
441 : : buf_ptr(&self->sys_include_dir),
442 : : buf_ptr(&self->crt_dir),
443 : : buf_ptr(&self->static_crt_dir),
444 : : buf_ptr(&self->msvc_lib_dir),
445 : : buf_ptr(&self->kernel32_lib_dir)
446 : : );
447 : 0 : }
448 : :
449 : 0 : Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
450 : : Error err;
451 : 0 : zig_libc_init_empty(self);
452 : : #if defined(ZIG_OS_WINDOWS)
453 : : ZigTarget native_target;
454 : : get_native_target(&native_target);
455 : : if (target_abi_is_gnu(native_target.abi)) {
456 : : if ((err = zig_libc_find_native_include_dir_posix(self, verbose)))
457 : : return err;
458 : : if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))
459 : : return err;
460 : : if ((err = zig_libc_find_native_static_crt_dir_posix(self, verbose)))
461 : : return err;
462 : : return ErrorNone;
463 : : } else {
464 : : ZigWindowsSDK *sdk;
465 : : switch (zig_find_windows_sdk(&sdk)) {
466 : : case ZigFindWindowsSdkErrorNone:
467 : : if ((err = zig_libc_find_native_msvc_include_dir(self, sdk, verbose)))
468 : : return err;
469 : : if ((err = zig_libc_find_native_msvc_lib_dir(self, sdk, verbose)))
470 : : return err;
471 : : if ((err = zig_libc_find_kernel32_lib_dir(self, sdk, &native_target, verbose)))
472 : : return err;
473 : : if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose)))
474 : : return err;
475 : : if ((err = zig_libc_find_native_crt_dir_windows(self, sdk, &native_target, verbose)))
476 : : return err;
477 : : return ErrorNone;
478 : : case ZigFindWindowsSdkErrorOutOfMemory:
479 : : return ErrorNoMem;
480 : : case ZigFindWindowsSdkErrorNotFound:
481 : : return ErrorFileNotFound;
482 : : case ZigFindWindowsSdkErrorPathTooLong:
483 : : return ErrorPathTooLong;
484 : : }
485 : : }
486 : : zig_unreachable();
487 : : #else
488 [ # # ]: 0 : if ((err = zig_libc_find_native_include_dir_posix(self, verbose)))
489 : 0 : return err;
490 : : #if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
491 : : buf_init_from_str(&self->crt_dir, "/usr/lib");
492 : : #elif defined(ZIG_OS_LINUX)
493 [ # # ]: 0 : if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))
494 : 0 : return err;
495 : : #endif
496 : 0 : return ErrorNone;
497 : : #endif
498 : : }
|