|
40 | 40 | #endif |
41 | 41 |
|
42 | 42 | #include <stdio.h> |
| 43 | +#include <stdlib.h> |
43 | 44 | #include <string.h> |
44 | 45 | #include <string> |
45 | 46 | #include <vector> |
46 | 47 | #include <sys/stat.h> |
47 | 48 |
|
| 49 | +/* |
| 50 | + Compile-time default include headers for Nix enter here and are |
| 51 | + interned into the executable so we don't need to wrap ponyc |
| 52 | + or require the end user to specify them. |
| 53 | +*/ |
| 54 | +#ifndef PONY_NIX_INCLUDE_DIRS |
| 55 | +# define PONY_NIX_INCLUDE_DIRS "" |
| 56 | +#endif |
| 57 | + |
48 | 58 | #ifdef PLATFORM_IS_WINDOWS |
49 | 59 | # define PATH_SLASH '\\' |
50 | 60 | #else |
@@ -349,6 +359,148 @@ static bool push_isystem(pass_opt_t* opt, std::vector<const char*>& args, |
349 | 359 | } |
350 | 360 |
|
351 | 361 |
|
| 362 | +/* |
| 363 | + Add each existing directory in a ':' deliminited list as an |
| 364 | + -internal-isystem search directory. |
| 365 | +*/ |
| 366 | +static bool add_colon_include_dirs(pass_opt_t* opt, const char* list, |
| 367 | + std::vector<const char*>& args, errors_t* errors) |
| 368 | +{ |
| 369 | + if(list == NULL || list[0] == '\0') |
| 370 | + return false; |
| 371 | + |
| 372 | + bool any = false; |
| 373 | + char buf[FILENAME_MAX]; |
| 374 | + size_t len = 0; |
| 375 | + for(const char* p = list; ; p++) |
| 376 | + { |
| 377 | + if(*p == ':' || *p == '\0') |
| 378 | + { |
| 379 | + if(len > 0) |
| 380 | + { |
| 381 | + buf[len] = '\0'; |
| 382 | + any |= push_isystem(opt, args, errors, "-internal-isystem", buf, ""); |
| 383 | + len = 0; |
| 384 | + } |
| 385 | + if(*p == '\0') |
| 386 | + break; |
| 387 | + } |
| 388 | + else if(len < sizeof(buf) - 1) |
| 389 | + { |
| 390 | + buf[len++] = *p; |
| 391 | + } |
| 392 | + } |
| 393 | + |
| 394 | + return any; |
| 395 | +} |
| 396 | + |
| 397 | +/* |
| 398 | + Unwrap the provided include directories from the nix environment. |
| 399 | + As well as covering the basics, this should also include any |
| 400 | + includes that would have come via pkgconf et al. |
| 401 | +*/ |
| 402 | +static bool add_flag_string_include_dirs(pass_opt_t* opt, const char* flags, |
| 403 | + std::vector<const char*>& args, errors_t* errors) |
| 404 | +{ |
| 405 | + if(flags == NULL || flags[0] == '\0') |
| 406 | + return false; |
| 407 | + |
| 408 | + // Tokenize on whitespace first, then interpret include-dir flags. |
| 409 | + std::vector<const char*> toks; |
| 410 | + char buf[FILENAME_MAX]; |
| 411 | + size_t len = 0; |
| 412 | + for(const char* p = flags; ; p++) |
| 413 | + { |
| 414 | + if(*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == '\0') |
| 415 | + { |
| 416 | + if(len > 0) |
| 417 | + { |
| 418 | + buf[len] = '\0'; |
| 419 | + toks.push_back(stringtab(opt->strtab, buf)); |
| 420 | + len = 0; |
| 421 | + } |
| 422 | + if(*p == '\0') |
| 423 | + break; |
| 424 | + } |
| 425 | + else if(len < sizeof(buf) - 1) |
| 426 | + { |
| 427 | + buf[len++] = *p; |
| 428 | + } |
| 429 | + } |
| 430 | + |
| 431 | + bool any = false; |
| 432 | + for(size_t i = 0; i < toks.size(); i++) |
| 433 | + { |
| 434 | + const char* t = toks[i]; |
| 435 | + const char* dir = NULL; |
| 436 | + |
| 437 | + if(strcmp(t, "-isystem") == 0 || strcmp(t, "-idirafter") == 0 || |
| 438 | + strcmp(t, "-iquote") == 0 || strcmp(t, "-I") == 0) |
| 439 | + { |
| 440 | + if(i + 1 < toks.size()) |
| 441 | + dir = toks[++i]; |
| 442 | + } |
| 443 | + else if(strncmp(t, "-I", 2) == 0 && t[2] != '\0') |
| 444 | + { |
| 445 | + dir = t + 2; |
| 446 | + } |
| 447 | + |
| 448 | + if(dir != NULL) |
| 449 | + any |= push_isystem(opt, args, errors, "-internal-isystem", dir, ""); |
| 450 | + } |
| 451 | + |
| 452 | + return any; |
| 453 | +} |
| 454 | + |
| 455 | +static bool read_nix_support_file(const char* nix_cc, const char* name, |
| 456 | + char* out, size_t outsz) |
| 457 | +{ |
| 458 | + char path[FILENAME_MAX]; |
| 459 | + snprintf(path, sizeof(path), "%s/nix-support/%s", nix_cc, name); |
| 460 | + |
| 461 | + FILE* f = fopen(path, "rb"); |
| 462 | + if(f == NULL) |
| 463 | + return false; |
| 464 | + |
| 465 | + size_t n = fread(out, 1, outsz - 1, f); |
| 466 | + fclose(f); |
| 467 | + out[n] = '\0'; |
| 468 | + |
| 469 | + while(n > 0 && (out[n - 1] == '\n' || out[n - 1] == '\r' || |
| 470 | + out[n - 1] == ' ' || out[n - 1] == '\t')) |
| 471 | + out[--n] = '\0'; |
| 472 | + |
| 473 | + return n > 0; |
| 474 | +} |
| 475 | + |
| 476 | +/* |
| 477 | + Extra include files from the nix environment: |
| 478 | + * PONY_NIX_INCLUDE_DIRS |
| 479 | + * PONY_INCLUDE_DIRS |
| 480 | + * NIX_CFLAGS_COMPILE |
| 481 | +*/ |
| 482 | +static bool add_nix_include_dirs(pass_opt_t* opt, |
| 483 | + std::vector<const char*>& args, errors_t* errors) |
| 484 | +{ |
| 485 | + bool any = false; |
| 486 | + |
| 487 | + any |= add_colon_include_dirs(opt, PONY_NIX_INCLUDE_DIRS, args, errors); |
| 488 | + any |= add_colon_include_dirs(opt, getenv("PONY_INCLUDE_DIRS"), args, errors); |
| 489 | + any |= add_flag_string_include_dirs(opt, getenv("NIX_CFLAGS_COMPILE"), args, |
| 490 | + errors); |
| 491 | + |
| 492 | + const char* nix_cc = getenv("NIX_CC"); |
| 493 | + if(nix_cc != NULL && nix_cc[0] != '\0') |
| 494 | + { |
| 495 | + char cflags[FILENAME_MAX * 4]; |
| 496 | + if(read_nix_support_file(nix_cc, "libc-cflags", cflags, sizeof(cflags))) |
| 497 | + any |= add_flag_string_include_dirs(opt, cflags, args, errors); |
| 498 | + } |
| 499 | + |
| 500 | + return any; |
| 501 | +} |
| 502 | + |
| 503 | + |
352 | 504 | // System include directories for the target, derived from the same sysroot |
353 | 505 | // the embedded linker uses — hand-rolled like LLD rather than driven through |
354 | 506 | // clang's Driver, so the headers the shim compiles against stay consistent |
@@ -488,6 +640,9 @@ static bool add_system_include_args(pass_opt_t* opt, const char* sysroot, |
488 | 640 | any |= push_isystem(opt, args, errors, "-internal-externc-isystem", |
489 | 641 | sysroot, "/usr/include"); |
490 | 642 |
|
| 643 | + if(sysroot[0] == '\0') |
| 644 | + any |= add_nix_include_dirs(opt, args, errors); |
| 645 | + |
491 | 646 | // Per-directory skipping is right (multiarch and /usr/local are |
492 | 647 | // legitimately absent on many systems), but an explicit --sysroot that |
493 | 648 | // yields nothing at all deserves a direct answer, like the macOS branch |
|
0 commit comments