Skip to content

[PS5][Driver] Allow selection of CRT with -L #145869

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2025

Conversation

playstation-edd
Copy link
Contributor

There's long standing behaviour in PlayStation to allow user-supplied library search paths (-L) to influence lookup of CRT objects. This seems to be a historical quirk that has persisted to the present day.

This usage of -L for CRT selection is deeply entrenched among users of the PS5 toolchain. While this change is conceptually bothersome, it does reflect what's shipped.

SIE tracker: TOOLCHAIN-17706

There's long standing behaviour in PlayStation to allow user-supplied
library search paths (`-L`) to influence lookup of CRT objects. This
seems to be a historical quirk that has persisted to the present day.

This usage of `-L` for CRT selection is deeply entrenched among users of
the PS5 toolchain. While this change is conceptually bothersome, it does
reflect what's shipped.

SIE tracker: TOOLCHAIN-17706
@playstation-edd playstation-edd requested review from jmorse and pogo59 June 26, 2025 11:00
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Jun 26, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 26, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-driver

Author: Edd Dawson (playstation-edd)

Changes

There's long standing behaviour in PlayStation to allow user-supplied library search paths (-L) to influence lookup of CRT objects. This seems to be a historical quirk that has persisted to the present day.

This usage of -L for CRT selection is deeply entrenched among users of the PS5 toolchain. While this change is conceptually bothersome, it does reflect what's shipped.

SIE tracker: TOOLCHAIN-17706


Full diff: https://github.com/llvm/llvm-project/pull/145869.diff

2 Files Affected:

  • (modified) clang/lib/Driver/ToolChains/PS4CPU.cpp (+4-2)
  • (modified) clang/test/Driver/ps5-linker.c (+10-12)
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp
index e965786d269fa..21e23d486f9d4 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -379,8 +379,10 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       !Relocatable &&
       !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib);
 
-  auto AddCRTObject = [&](const char *Name) {
-    CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(Name)));
+  auto AddCRTObject = [&](StringRef Name) {
+    // CRT objects can be found on user supplied library paths. This is
+    // an entrenched expectation on PlayStation.
+    CmdArgs.push_back(Args.MakeArgString("-l:" + Name));
   };
 
   if (AddStartFiles) {
diff --git a/clang/test/Driver/ps5-linker.c b/clang/test/Driver/ps5-linker.c
index 777826aade7ff..753085d2e1b0b 100644
--- a/clang/test/Driver/ps5-linker.c
+++ b/clang/test/Driver/ps5-linker.c
@@ -146,9 +146,9 @@
 // RUN: %clang --target=x86_64-sie-ps5 %s -nostdlib++ -static -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-STATIC-CRT,CHECK-NO-LIBCPP,CHECK-STATIC-LIBC,CHECK-STATIC-CORE-LIBS %s
 
 // CHECK-LD: {{ld(\.exe)?}}"
-// CHECK-MAIN-CRT-SAME: "crt1.o" "crti.o" "crtbegin.o"
-// CHECK-SHARED-CRT-SAME: "crti.o" "crtbeginS.o"
-// CHECK-STATIC-CRT-SAME: "crt1.o" "crti.o" "crtbeginT.o"
+// CHECK-MAIN-CRT-SAME: "-l:crt1.o" "-l:crti.o" "-l:crtbegin.o"
+// CHECK-SHARED-CRT-SAME: "-l:crti.o" "-l:crtbeginS.o"
+// CHECK-STATIC-CRT-SAME: "-l:crt1.o" "-l:crti.o" "-l:crtbeginT.o"
 
 // CHECK-NO-LIBC-NOT: "-lc{{(_stub_weak)?}}"
 // CHECK-NO-LIBCPP-NOT: "-l{{c_stub_weak|stdc\+\+}}"
@@ -161,11 +161,11 @@
 
 // CHECK-PTHREAD-SAME: "-lpthread"
 
-// CHECK-MAIN-CRT-SAME: "crtend.o" "crtn.o"
-// CHECK-SHARED-CRT-SAME: "crtendS.o" "crtn.o"
-// CHECK-STATIC-CRT-SAME: "crtend.o" "crtn.o"
+// CHECK-MAIN-CRT-SAME: "-l:crtend.o" "-l:crtn.o"
+// CHECK-SHARED-CRT-SAME: "-l:crtendS.o" "-l:crtn.o"
+// CHECK-STATIC-CRT-SAME: "-l:crtend.o" "-l:crtn.o"
 
-// CHECK-NO-CRT-NOT: "crt{{[^"]*}}.o"
+// CHECK-NO-CRT-NOT: crt{{[^"]*}}.o"
 // CHECK-NO-LIBS-NOT: "-l{{[^"]*}}"
 
 // Test the driver's control over the -fcrash-diagnostics-dir behavior with linker flags.
@@ -186,9 +186,9 @@
 
 // Test implicit library search paths are supplied to the linker, after any
 // search paths specified by the user. <sdk-root>/target/lib is implicitly
-// added if it exists. CRT objects are found there. "." is always implicitly
-// added to library search paths. This is long-standing behavior, unique to
-// PlayStation toolchains.
+// added if it exists. CRT objects are found there if not on user search paths.
+// "." is always implicitly added to library search paths. These are
+// long-standing and entrenched behaviors, unique to PlayStation toolchains.
 
 // RUN: rm -rf %t.dir && mkdir %t.dir
 // RUN: env SCE_PROSPERO_SDK_DIR=%t.dir %clang --target=x64_64-sie-ps5 %s -### -Luser 2>&1 | FileCheck --check-prefixes=CHECK-NO-TARGETLIB %s
@@ -200,7 +200,6 @@
 // CHECK-NO-TARGETLIB-SAME: "-L."
 
 // RUN: mkdir -p %t.dir/myroot/target/lib
-// RUN: touch %t.dir/myroot/target/lib/crti.o
 // RUN: env SCE_PROSPERO_SDK_DIR=%t.dir/myroot %clang --target=x64_64-sie-ps5 %s -### -Luser 2>&1 | FileCheck --check-prefixes=CHECK-TARGETLIB %s
 // RUN: %clang --target=x64_64-sie-ps5 %s -### -Luser --sysroot=%t.dir/myroot 2>&1 | FileCheck --check-prefixes=CHECK-TARGETLIB %s
 
@@ -208,4 +207,3 @@
 // CHECK-TARGETLIB-SAME: "-Luser"
 // CHECK-TARGETLIB-SAME: "-L{{.*}}myroot{{/|\\\\}}target{{/|\\\\}}lib"
 // CHECK-TARGETLIB-SAME: "-L."
-// CHECK-TARGETLIB-SAME: "{{.*}}myroot{{/|\\\\}}target{{/|\\\\}}lib{{/|\\\\}}crti.o"

Copy link
Member

@jmorse jmorse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a question

@@ -200,12 +200,10 @@
// CHECK-NO-TARGETLIB-SAME: "-L."

// RUN: mkdir -p %t.dir/myroot/target/lib
// RUN: touch %t.dir/myroot/target/lib/crti.o
// RUN: env SCE_PROSPERO_SDK_DIR=%t.dir/myroot %clang --target=x64_64-sie-ps5 %s -### -Luser 2>&1 | FileCheck --check-prefixes=CHECK-TARGETLIB %s
// RUN: %clang --target=x64_64-sie-ps5 %s -### -Luser --sysroot=%t.dir/myroot 2>&1 | FileCheck --check-prefixes=CHECK-TARGETLIB %s

// CHECK-TARGETLIB: {{ld(\.exe)?}}"
// CHECK-TARGETLIB-SAME: "-Luser"
// CHECK-TARGETLIB-SAME: "-L{{.*}}myroot{{/|\\\\}}target{{/|\\\\}}lib"
// CHECK-TARGETLIB-SAME: "-L."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to check the thinking: we don't need to check how the linker is directed to crti.o, these check lines are purely about ensuring the correct -L flags come out of the driver? (Seeing deleted lines suggests to me we're losing coverage, but I suppose it's not truly meaningful coverage).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to check the thinking: we don't need to check how the linker is directed to crti.o, these check lines are purely about ensuring the correct -L flags come out of the driver?

In short: yes.

In full:

The deleted line checked that crti.o was resolved to <user-supplied-sysroot>/target/lib/crti.o by the driver. That resolution will still occur, because -L<user-supplied-sysroot>/target/lib and -l:crti.o are passed to the linker, but it will now be the linker that does the resolution instead of the driver.

The removed line below could have been replaced with:

// CHECK-TARGETLIB-SAME: "-l:crti.o"

But the user supplied sysroot has no interaction with this part - "-l:crti.o" appears regardless. And since the appearance of "-l:crti.o" and friends are checked elsewhere in this file, I didn't think it was worth repeating again here.

The remaining CHECK-TARGETLIB lines continue to confirm user supplied library paths are passed to the linker before the defaults (<sysroot>/target/lib and .).

@playstation-edd playstation-edd merged commit 772009c into llvm:main Jun 27, 2025
10 checks passed
@playstation-edd playstation-edd deleted the ps5-driver-L-for-CRT branch June 27, 2025 14:31
rlavaee pushed a commit to rlavaee/llvm-project that referenced this pull request Jul 1, 2025
There's long standing behaviour in PlayStation to allow user-supplied
library search paths (`-L`) to influence lookup of CRT objects. This
seems to be a historical quirk that has persisted to the present day.

This usage of `-L` for CRT selection is deeply entrenched among users of
the PS5 toolchain. While this change is conceptually bothersome, it does
reflect what's shipped.

SIE tracker: TOOLCHAIN-17706
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants