Skip to content

Commit 491a834

Browse files
committed
[Clang][Driver] Override Generic_ELF::buildLinker() to avoid calling gcc to link
This change primarily makes it so that when targeting freestanding/unknown OSes, the driver will not use `gcc` to link, but rather will link using the chosen linker (`-fuse-ld=...`) directly. If Clang is to be a cross compiler, there is no reason to assume that the host's gcc is in any way capable of handling the linkage of programs for targets that do not match the host's triple, especially for freestanding targets.
1 parent 6056f94 commit 491a834

File tree

4 files changed

+19
-1
lines changed

4 files changed

+19
-1
lines changed

clang/lib/Driver/ToolChains/Gnu.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3375,3 +3375,5 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
33753375
options::OPT_fno_use_init_array, true))
33763376
CC1Args.push_back("-fno-use-init-array");
33773377
}
3378+
3379+
Tool *Generic_ELF::buildLinker() const { return new tools::gnutools::Linker(*this); }

clang/lib/Driver/ToolChains/Gnu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,9 @@ class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
382382
}
383383

384384
virtual void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {}
385+
386+
protected:
387+
Tool *buildLinker() const override;
385388
};
386389

387390
} // end namespace toolchains

clang/test/Driver/baremetal-ld.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,16 @@
44

55
// RUN: %clang -### --target=armv7-unknown-none-eabi -mcpu=cortex-m4 --sysroot= -fuse-ld=ld -flto -O3 %s 2>&1 | FileCheck --check-prefix=LTO %s
66
// LTO: {{".*ld.*"}} {{.*}} "-plugin-opt=mcpu=cortex-m4" "-plugin-opt=O3"
7+
8+
// Ensure that, for freestanding -none targets, the linker does not call into gcc.
9+
// We do this by checking if clang is trying to pass "-fuse-ld=bfd" to the linker command.
10+
// RUN: %clang --target=aarch64-unknown-none-elf -ccc-print-bindings %s 2>&1 | FileCheck --check-prefix=LDAARCH64 %s
11+
// LDAARCH64: "baremetal::Linker"
12+
// RUN: %clang --target=loongarch64-unknown-none-elf -ccc-print-bindings %s 2>&1 | FileCheck --check-prefix=LDLOONGARCH64 %s
13+
// LDLOONGARCH64: "GNU::Linker"
14+
// RUN: %clang --target=riscv64-unknown-none-elf -ccc-print-bindings %s 2>&1 | FileCheck --check-prefix=LDRISCV64 %s
15+
// LDRISCV64: "baremetal::Linker"
16+
// RUN: %clang --target=x86_64-unknown-none-elf -ccc-print-bindings %s 2>&1 | FileCheck --check-prefix=LDX8664 %s
17+
// LDX8664: "GNU::Linker"
18+
// RUN: %clang --target=i386-unknown-none-elf -ccc-print-bindings %s 2>&1 | FileCheck --check-prefix=LDI386 %s
19+
// LDI386: "GNU::Linker"

clang/test/Driver/bindings.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %clang -target i386-unknown-unknown -ccc-print-bindings -no-integrated-as %s 2>&1 | FileCheck %s --check-prefix=CHECK01
33
// CHECK01: "clang", inputs: ["{{.*}}bindings.c"], output: "{{.*}}.s"
44
// CHECK01: "GNU::Assembler", inputs: ["{{.*}}.s"], output: "{{.*}}.o"
5-
// CHECK01: "gcc::Linker", inputs: ["{{.*}}.o"], output: "a.out"
5+
// CHECK01: "GNU::Linker", inputs: ["{{.*}}.o"], output: "a.out"
66

77
// Clang control options
88

0 commit comments

Comments
 (0)