Skip to content

Link executables for their target, not for the host - #113

Merged
Leitwolf11 merged 4 commits into
mainfrom
feature/cross-link
Oct 30, 2026
Merged

Leitwolf11 merged 4 commits into
mainfrom
feature/cross-link

Conversation

@Leitwolf11

Copy link
Copy Markdown
Contributor

Link executables for their target, not for the host

The native linker decided everything with host macros: on a Windows host
it accepted only COFF objects and wrote the kernel32 import library for
the host's machine (_M_ARM64), and elsewhere it always ran the host's cc.
An executable for another target therefore could not be linked at all,
and a Windows-on-Arm host would have written an x64 import library for an
x64 target.

What a link runs is now planned from the target triple in LinkPlan.cpp,
a pure function that touches no file and starts no process:

  • a Windows target (x86_64, aarch64) is linked by lld-link on every host,
    with /machine from the target and the import library written for that
    machine;
  • the host's own system, architecture and C library is linked by cc, as
    before;
  • another Linux, macOS or BSD target is linked by
    clang --target=<triple> -fuse-ld=lld, with --sysroot when given.

NativeLinker.cpp runs the plan: it checks that the objects have the
target's format, finds the target's runtime (beside talac for the host,
in runtimes// for another target), writes the import library and
starts the program on either kind of host. The link request carries the
resolved target triple from the backend artifact; an object given on the
command line belongs to --target.

LinkPlanTests plans every pair of target and host on whichever host runs
it (native, cross Linux, musl, macOS from Linux, Windows from Linux and
macOS, Windows on Arm, and the refusals) and joins the native test list.
verify-abi and the runtime-library helper test now read the programs and
library names from LinkPlan.cpp. CLI.md and the changelog describe the
behaviour.

Builds on #112 (--sysroot).

Leitwolf11 and others added 3 commits October 30, 2026 11:56
The native linker decided everything with host macros: on a Windows host
it accepted only COFF objects and wrote the kernel32 import library for
the host's machine (_M_ARM64), and elsewhere it always ran the host's cc.
An executable for another target therefore could not be linked at all,
and a Windows-on-Arm host would have written an x64 import library for an
x64 target.

What a link runs is now planned from the target triple in LinkPlan.cpp,
a pure function that touches no file and starts no process:

- a Windows target (x86_64, aarch64) is linked by lld-link on every host,
  with /machine from the target and the import library written for that
  machine;
- the host's own system, architecture and C library is linked by cc, as
  before;
- another Linux, macOS or BSD target is linked by
  `clang --target=<triple> -fuse-ld=lld`, with --sysroot when given.

NativeLinker.cpp runs the plan: it checks that the objects have the
target's format, finds the target's runtime (beside talac for the host,
in runtimes/<triple>/ for another target), writes the import library and
starts the program on either kind of host. The link request carries the
resolved target triple from the backend artifact; an object given on the
command line belongs to --target.

LinkPlanTests plans every pair of target and host on whichever host runs
it (native, cross Linux, musl, macOS from Linux, Windows from Linux and
macOS, Windows on Arm, and the refusals) and joins the native test list.
verify-abi and the runtime-library helper test now read the programs and
library names from LinkPlan.cpp. CLI.md and the changelog describe the
behaviour.

Builds on #112 (--sysroot).
@Leitwolf11

Copy link
Copy Markdown
Contributor Author

Self-review: LinkPlan is a pure function of the output, the inputs, the target triple and the host triple, so every target and host pair is planned and tested on whichever host runs the tests. COFF goes to lld-link with /machine taken from the target, the host's own target stays with cc, and a cross ELF or Mach-O target goes to clang --target=... -fuse-ld=lld, with TalaRT looked up in runtimes/<triple>/. NativeLinker only executes the plan. verify-abi reads the constants from their new home, and helpers runs link_plan_tests. Known limit: nothing stages runtimes/<triple>/ yet, so a cross link needs that archive put there by hand; the linker reports it when it is missing. CI 40/40 green.

@Leitwolf11
Leitwolf11 merged commit 2369a4a into main Oct 30, 2026
43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant