[clang] [LinkerWrapper] Do not mistake ld64's -lto_library for -l<libname> (PR #216939)
Paulius Velesko via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 17 14:47:22 PDT 2026
https://github.com/pvelesko updated https://github.com/llvm/llvm-project/pull/216939
>From b94adae2c7c777f886e1ee071f96a1071223910a Mon Sep 17 00:00:00 2001
From: Paulius Velesko <pvelesko at pglc.io>
Date: Tue, 18 Aug 2026 10:08:06 +0300
Subject: [PATCH 1/2] [LinkerWrapper] Do not mistake ld64's -lto_library for
-l<libname>
On Darwin the linker wrapper is handed the ld64 command line clang
builds, which can contain `-lto_library <path>` (added for ld64, not
lld) and, for LTO links, `-object_path_lto <path>`. `-l` and `-o` are
`JoinedOrSeparate`, so the first was parsed as the library `to_library`
and failed with `unable to find library -lto_library`, and the second as
the output file `bject_path_lto`.
Define both as `Separate` options so they are parsed as what they are
and forwarded to the linker unchanged.
The other ld64 options that start with `-l` (`-lazy_library`,
`-lazy_framework`, `-load_hidden`) name libraries that can hold
offloading code, so they need to be searched, not only forwarded; that
is left for a follow up.
---
.../test/OffloadTools/clang-linker-wrapper/linker-wrapper.c | 6 ++++++
clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td | 4 ++++
2 files changed, 10 insertions(+)
diff --git a/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
index 550cab4b0604de..62936ccc8bd3e6 100644
--- a/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
+++ b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
@@ -77,6 +77,12 @@ __attribute__((visibility("protected"), used)) int x;
// HOST-LINK: ld.lld{{.*}}-a -b -c {{.*}}.o -o a.out
// HOST-LINK-NOT: ld.lld{{.*}}-abc
+// RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-apple-macosx15.0.0 \
+// RUN: --linker-path=/usr/bin/ld -lto_library /lib/libLTO.dylib \
+// RUN: -object_path_lto /tmp/lto.o %t.elf.o -o a.out 2>&1 | FileCheck %s --check-prefix=LD64-LINK
+
+// LD64-LINK: ld{{.*}}-lto_library /lib/libLTO.dylib -object_path_lto /tmp/lto.o {{.*}}.o -o a.out
+
// RUN: llvm-offload-binary -o %t-lib.out \
// RUN: --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70 \
// RUN: --image=file=%t.elf.o,kind=cuda,triple=nvptx64-nvidia-cuda,arch=sm_52
diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
index fc48eac2637eeb..4c175252f626ec 100644
--- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
+++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
@@ -136,6 +136,10 @@ def relocatable : Flag<["--", "-"], "relocatable">,
HelpText<"Link device code to create a relocatable offloading application">;
def r : Flag<["-"], "r">, Alias<relocatable>;
+// ld64-style linker options, defined so they are not parsed as -l or -o.
+def lto_library : Separate<["-"], "lto_library">, Flags<[HelpHidden]>;
+def object_path_lto : Separate<["-"], "object_path_lto">, Flags<[HelpHidden]>;
+
// link.exe-style linker options.
def out : Joined<["/", "-", "/?", "-?"], "out:">, Flags<[HelpHidden]>;
def libpath : Joined<["/", "-", "/?", "-?"], "libpath:">, Flags<[HelpHidden]>;
>From f3c6b1f2c2d00dd0f0a42b79381e8384f1396561 Mon Sep 17 00:00:00 2001
From: Paulius Velesko <pvelesko at pglc.io>
Date: Sat, 17 Oct 2026 22:27:50 +0300
Subject: [PATCH 2/2] [LinkerWrapper] Move the ld64 option test to a
target-independent file
The check only needs clang-linker-wrapper's --dry-run output, so it no
longer needs an object input or the registered targets linker-wrapper.c
requires.
---
.../clang-linker-wrapper/linker-wrapper-ld64-options.c | 4 ++++
.../test/OffloadTools/clang-linker-wrapper/linker-wrapper.c | 6 ------
2 files changed, 4 insertions(+), 6 deletions(-)
create mode 100644 clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper-ld64-options.c
diff --git a/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper-ld64-options.c b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper-ld64-options.c
new file mode 100644
index 00000000000000..3fd719fcfcf78c
--- /dev/null
+++ b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper-ld64-options.c
@@ -0,0 +1,4 @@
+// RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-apple-macosx15.0.0 \
+// RUN: --linker-path=/usr/bin/ld -lto_library /lib/libLTO.dylib \
+// RUN: -object_path_lto /tmp/lto.o -o a.out 2>&1 | FileCheck %s
+// CHECK: ld{{.*}}-lto_library /lib/libLTO.dylib -object_path_lto /tmp/lto.o -o a.out
diff --git a/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
index 62936ccc8bd3e6..550cab4b0604de 100644
--- a/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
+++ b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
@@ -77,12 +77,6 @@ __attribute__((visibility("protected"), used)) int x;
// HOST-LINK: ld.lld{{.*}}-a -b -c {{.*}}.o -o a.out
// HOST-LINK-NOT: ld.lld{{.*}}-abc
-// RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-apple-macosx15.0.0 \
-// RUN: --linker-path=/usr/bin/ld -lto_library /lib/libLTO.dylib \
-// RUN: -object_path_lto /tmp/lto.o %t.elf.o -o a.out 2>&1 | FileCheck %s --check-prefix=LD64-LINK
-
-// LD64-LINK: ld{{.*}}-lto_library /lib/libLTO.dylib -object_path_lto /tmp/lto.o {{.*}}.o -o a.out
-
// RUN: llvm-offload-binary -o %t-lib.out \
// RUN: --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70 \
// RUN: --image=file=%t.elf.o,kind=cuda,triple=nvptx64-nvidia-cuda,arch=sm_52
More information about the cfe-commits
mailing list