| ... | ... | @@ -50,6 +50,9 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) { |
| 50 | 50 | codegen_set_verbose(child_gen, parent_gen->verbose); |
| 51 | 51 | codegen_set_errmsg_color(child_gen, parent_gen->err_color); |
| 52 | 52 | |
| 53 | codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min); |
| 54 | codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min); |
| 55 | |
| 53 | 56 | Buf *full_path = buf_alloc(); |
| 54 | 57 | os_path_join(std_dir_path, source_basename, full_path); |
| 55 | 58 | Buf source_code = BUF_INIT; |
| ... | ... | @@ -391,38 +394,251 @@ static void construct_linker_job_mingw(LinkJob *lj) { |
| 391 | 394 | } |
| 392 | 395 | } |
| 393 | 396 | |
| 397 | |
| 398 | // Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the |
| 399 | // grouped values as integers. Numbers which are not provided are set to 0. |
| 400 | // return true if the entire string was parsed (9.2), or all groups were |
| 401 | // parsed (10.3.5extrastuff). |
| 402 | static bool darwin_get_release_version(const char *str, int *major, int *minor, int *micro, bool *had_extra) { |
| 403 | *had_extra = false; |
| 404 | |
| 405 | *major = 0; |
| 406 | *minor = 0; |
| 407 | *micro = 0; |
| 408 | |
| 409 | if (*str == '\0') |
| 410 | return false; |
| 411 | |
| 412 | char *end; |
| 413 | *major = strtol(str, &end, 10); |
| 414 | if (*str != '\0' && *end == '\0') |
| 415 | return true; |
| 416 | if (*end != '.') |
| 417 | return false; |
| 418 | |
| 419 | str = end + 1; |
| 420 | *minor = strtol(str, &end, 10); |
| 421 | if (*str != '\0' && *end == '\0') |
| 422 | return true; |
| 423 | if (*end != '.') |
| 424 | return false; |
| 425 | |
| 426 | str = end + 1; |
| 427 | *micro = strtol(str, &end, 10); |
| 428 | if (*str != '\0' && *end == '\0') |
| 429 | return true; |
| 430 | if (str == end) |
| 431 | return false; |
| 432 | *had_extra = true; |
| 433 | return true; |
| 434 | } |
| 435 | |
| 436 | enum DarwinPlatformKind { |
| 437 | MacOS, |
| 438 | IPhoneOS, |
| 439 | IPhoneOSSimulator, |
| 440 | }; |
| 441 | |
| 442 | struct DarwinPlatform { |
| 443 | DarwinPlatformKind kind; |
| 444 | int major; |
| 445 | int minor; |
| 446 | int micro; |
| 447 | }; |
| 448 | |
| 449 | static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) { |
| 450 | CodeGen *g = lj->codegen; |
| 451 | |
| 452 | if (g->mmacosx_version_min) { |
| 453 | platform->kind = MacOS; |
| 454 | } else if (g->mios_version_min) { |
| 455 | platform->kind = IPhoneOS; |
| 456 | } else { |
| 457 | zig_panic("unable to infer -macosx-version-min or -mios-version-min"); |
| 458 | } |
| 459 | |
| 460 | bool had_extra; |
| 461 | if (platform->kind == MacOS) { |
| 462 | if (!darwin_get_release_version(buf_ptr(g->mmacosx_version_min), |
| 463 | &platform->major, &platform->minor, &platform->micro, &had_extra) || |
| 464 | had_extra || platform->major != 10 || platform->minor >= 100 || platform->micro >= 100) |
| 465 | { |
| 466 | zig_panic("invalid -mmacosx-version-min"); |
| 467 | } |
| 468 | } else if (platform->kind == IPhoneOS) { |
| 469 | if (!darwin_get_release_version(buf_ptr(g->mios_version_min), |
| 470 | &platform->major, &platform->minor, &platform->micro, &had_extra) || |
| 471 | had_extra || platform->major >= 10 || platform->minor >= 100 || platform->micro >= 100) |
| 472 | { |
| 473 | zig_panic("invalid -mios-version-min"); |
| 474 | } |
| 475 | } else { |
| 476 | zig_unreachable(); |
| 477 | } |
| 478 | |
| 479 | if (platform->kind == IPhoneOS && |
| 480 | (g->zig_target.arch.arch == ZigLLVM_x86 || |
| 481 | g->zig_target.arch.arch == ZigLLVM_x86_64)) |
| 482 | { |
| 483 | platform->kind = IPhoneOSSimulator; |
| 484 | } |
| 485 | } |
| 486 | |
| 487 | static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) { |
| 488 | if (platform->major < major) { |
| 489 | return true; |
| 490 | } else if (platform->major > major) { |
| 491 | return false; |
| 492 | } |
| 493 | if (platform->minor < minor) { |
| 494 | return true; |
| 495 | } |
| 496 | return false; |
| 497 | } |
| 498 | |
| 499 | static void construct_linker_job_darwin(LinkJob *lj) { |
| 500 | CodeGen *g = lj->codegen; |
| 501 | |
| 502 | int ver_major; |
| 503 | int ver_minor; |
| 504 | int ver_micro; |
| 505 | bool had_extra; |
| 506 | |
| 507 | if (!darwin_get_release_version(buf_ptr(g->darwin_linker_version), &ver_major, &ver_minor, &ver_micro, |
| 508 | &had_extra) || had_extra) |
| 509 | { |
| 510 | zig_panic("invalid linker version number"); |
| 511 | } |
| 512 | |
| 513 | // Newer linkers support -demangle. Pass it if supported and not disabled by |
| 514 | // the user. |
| 515 | if (ver_major >= 100) { |
| 516 | lj->args.append("-demangle"); |
| 517 | } |
| 518 | |
| 519 | if (g->linker_rdynamic && ver_major >= 137) { |
| 520 | lj->args.append("-export_dynamic"); |
| 521 | } |
| 522 | |
| 523 | bool is_lib = g->out_type == OutTypeLib; |
| 524 | bool shared = !g->is_static && is_lib; |
| 525 | if (g->is_static) { |
| 526 | lj->args.append("-static"); |
| 527 | } else { |
| 528 | lj->args.append("-dynamic"); |
| 529 | } |
| 530 | |
| 531 | if (is_lib) { |
| 532 | zig_panic("TODO linker args on darwin for making a library"); |
| 533 | } |
| 534 | |
| 535 | DarwinPlatform platform; |
| 536 | get_darwin_platform(lj, &platform); |
| 537 | switch (platform.kind) { |
| 538 | case MacOS: |
| 539 | lj->args.append("-macosx_version_min"); |
| 540 | break; |
| 541 | case IPhoneOS: |
| 542 | lj->args.append("-iphoneos_version_min"); |
| 543 | break; |
| 544 | case IPhoneOSSimulator: |
| 545 | lj->args.append("-ios_simulator_version_min"); |
| 546 | break; |
| 547 | } |
| 548 | lj->args.append(buf_ptr(buf_sprintf("%d.%d.%d", platform.major, platform.minor, platform.micro))); |
| 549 | |
| 550 | |
| 551 | if (g->out_type == OutTypeExe) { |
| 552 | if (g->is_static) { |
| 553 | lj->args.append("-no_pie"); |
| 554 | } else { |
| 555 | lj->args.append("-pie"); |
| 556 | } |
| 557 | } |
| 558 | |
| 559 | lj->args.append("-o"); |
| 560 | lj->args.append(buf_ptr(&lj->out_file)); |
| 561 | |
| 562 | if (lj->link_in_crt) { |
| 563 | if (shared) { |
| 564 | zig_panic("TODO"); |
| 565 | } else if (g->is_static) { |
| 566 | lj->args.append("-lcrt0.o"); |
| 567 | } else { |
| 568 | switch (platform.kind) { |
| 569 | case MacOS: |
| 570 | if (darwin_version_lt(&platform, 10, 5)) { |
| 571 | lj->args.append("-lcrt1.o"); |
| 572 | } else if (darwin_version_lt(&platform, 10, 6)) { |
| 573 | lj->args.append("-lcrt1.10.5.o"); |
| 574 | } else if (darwin_version_lt(&platform, 10, 8)) { |
| 575 | lj->args.append("-lcrt1.10.6.o"); |
| 576 | } |
| 577 | break; |
| 578 | case IPhoneOS: |
| 579 | if (g->zig_target.arch.arch == ZigLLVM_aarch64) { |
| 580 | // iOS does not need any crt1 files for arm64 |
| 581 | } else if (darwin_version_lt(&platform, 3, 1)) { |
| 582 | lj->args.append("-lcrt1.o"); |
| 583 | } else if (darwin_version_lt(&platform, 6, 0)) { |
| 584 | lj->args.append("-lcrt1.3.1.o"); |
| 585 | } |
| 586 | break; |
| 587 | case IPhoneOSSimulator: |
| 588 | // no crt1.o needed |
| 589 | break; |
| 590 | } |
| 591 | } |
| 592 | } |
| 593 | |
| 594 | for (int i = 0; i < g->lib_dirs.length; i += 1) { |
| 595 | const char *lib_dir = g->lib_dirs.at(i); |
| 596 | lj->args.append("-L"); |
| 597 | lj->args.append(lib_dir); |
| 598 | } |
| 599 | |
| 600 | lj->args.append((const char *)buf_ptr(&lj->out_file_o)); |
| 601 | |
| 602 | for (int i = 0; i < g->link_libs.length; i += 1) { |
| 603 | Buf *link_lib = g->link_libs.at(i); |
| 604 | Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib)); |
| 605 | lj->args.append(buf_ptr(arg)); |
| 606 | } |
| 607 | |
| 608 | } |
| 609 | |
| 394 | 610 | static void construct_linker_job(LinkJob *lj) { |
| 395 | 611 | switch (lj->codegen->zig_target.os) { |
| 396 | 612 | case ZigLLVM_UnknownOS: |
| 397 | | zig_unreachable(); |
| 613 | zig_unreachable(); |
| 398 | 614 | case ZigLLVM_Linux: |
| 399 | | if (lj->codegen->zig_target.arch.arch == ZigLLVM_hexagon) { |
| 615 | if (lj->codegen->zig_target.arch.arch == ZigLLVM_hexagon) { |
| 400 | 616 | zig_panic("TODO construct hexagon_TC linker job"); |
| 401 | | } else { |
| 617 | } else { |
| 402 | 618 | return construct_linker_job_linux(lj); |
| 403 | | } |
| 619 | } |
| 404 | 620 | case ZigLLVM_CloudABI: |
| 405 | | zig_panic("TODO construct CloudABI linker job"); |
| 621 | zig_panic("TODO construct CloudABI linker job"); |
| 406 | 622 | case ZigLLVM_Darwin: |
| 407 | 623 | case ZigLLVM_MacOSX: |
| 408 | 624 | case ZigLLVM_IOS: |
| 409 | | zig_panic("TODO construct DarwinClang linker job"); |
| 625 | return construct_linker_job_darwin(lj); |
| 410 | 626 | case ZigLLVM_DragonFly: |
| 411 | | zig_panic("TODO construct DragonFly linker job"); |
| 627 | zig_panic("TODO construct DragonFly linker job"); |
| 412 | 628 | case ZigLLVM_OpenBSD: |
| 413 | | zig_panic("TODO construct OpenBSD linker job"); |
| 629 | zig_panic("TODO construct OpenBSD linker job"); |
| 414 | 630 | case ZigLLVM_Bitrig: |
| 415 | | zig_panic("TODO construct Bitrig linker job"); |
| 631 | zig_panic("TODO construct Bitrig linker job"); |
| 416 | 632 | case ZigLLVM_NetBSD: |
| 417 | | zig_panic("TODO construct NetBSD linker job"); |
| 633 | zig_panic("TODO construct NetBSD linker job"); |
| 418 | 634 | case ZigLLVM_FreeBSD: |
| 419 | | zig_panic("TODO construct FreeBSD linker job"); |
| 635 | zig_panic("TODO construct FreeBSD linker job"); |
| 420 | 636 | case ZigLLVM_Minix: |
| 421 | | zig_panic("TODO construct Minix linker job"); |
| 637 | zig_panic("TODO construct Minix linker job"); |
| 422 | 638 | case ZigLLVM_NaCl: |
| 423 | | zig_panic("TODO construct NaCl_TC linker job"); |
| 639 | zig_panic("TODO construct NaCl_TC linker job"); |
| 424 | 640 | case ZigLLVM_Solaris: |
| 425 | | zig_panic("TODO construct Solaris linker job"); |
| 641 | zig_panic("TODO construct Solaris linker job"); |
| 426 | 642 | case ZigLLVM_Win32: |
| 427 | 643 | switch (lj->codegen->zig_target.environ) { |
| 428 | 644 | default: |
| ... | ... | @@ -440,27 +656,27 @@ static void construct_linker_job(LinkJob *lj) { |
| 440 | 656 | case ZigLLVM_MSVC: |
| 441 | 657 | case ZigLLVM_UnknownEnvironment: |
| 442 | 658 | zig_panic("TODO construct MSVC linker job"); |
| 443 | | } |
| 659 | } |
| 444 | 660 | case ZigLLVM_CUDA: |
| 445 | | zig_panic("TODO construct Cuda linker job"); |
| 661 | zig_panic("TODO construct Cuda linker job"); |
| 446 | 662 | default: |
| 447 | | // Of these targets, Hexagon is the only one that might have |
| 448 | | // an OS of Linux, in which case it got handled above already. |
| 449 | | if (lj->codegen->zig_target.arch.arch == ZigLLVM_tce) { |
| 663 | // Of these targets, Hexagon is the only one that might have |
| 664 | // an OS of Linux, in which case it got handled above already. |
| 665 | if (lj->codegen->zig_target.arch.arch == ZigLLVM_tce) { |
| 450 | 666 | zig_panic("TODO construct TCE linker job"); |
| 451 | | } else if (lj->codegen->zig_target.arch.arch == ZigLLVM_hexagon) { |
| 667 | } else if (lj->codegen->zig_target.arch.arch == ZigLLVM_hexagon) { |
| 452 | 668 | zig_panic("TODO construct Hexagon_TC linker job"); |
| 453 | | } else if (lj->codegen->zig_target.arch.arch == ZigLLVM_xcore) { |
| 669 | } else if (lj->codegen->zig_target.arch.arch == ZigLLVM_xcore) { |
| 454 | 670 | zig_panic("TODO construct XCore linker job"); |
| 455 | | } else if (lj->codegen->zig_target.arch.arch == ZigLLVM_shave) { |
| 671 | } else if (lj->codegen->zig_target.arch.arch == ZigLLVM_shave) { |
| 456 | 672 | zig_panic("TODO construct SHAVE linker job"); |
| 457 | | } else if (lj->codegen->zig_target.oformat == ZigLLVM_ELF) { |
| 673 | } else if (lj->codegen->zig_target.oformat == ZigLLVM_ELF) { |
| 458 | 674 | zig_panic("TODO construct Generic_ELF linker job"); |
| 459 | | } else if (lj->codegen->zig_target.oformat == ZigLLVM_MachO) { |
| 675 | } else if (lj->codegen->zig_target.oformat == ZigLLVM_MachO) { |
| 460 | 676 | zig_panic("TODO construct MachO linker job"); |
| 461 | | } else { |
| 677 | } else { |
| 462 | 678 | zig_panic("TODO construct Generic_GCC linker job"); |
| 463 | | } |
| 679 | } |
| 464 | 680 | |
| 465 | 681 | } |
| 466 | 682 | } |
| ... | ... | @@ -535,7 +751,6 @@ void codegen_link(CodeGen *g, const char *out_file) { |
| 535 | 751 | } |
| 536 | 752 | |
| 537 | 753 | lj.link_in_crt = (g->link_libc && g->out_type == OutTypeExe); |
| 538 | | // invoke `ld` |
| 539 | 754 | ensure_we_have_linker_path(g); |
| 540 | 755 | |
| 541 | 756 | construct_linker_job(&lj); |