[lld] [lld][ELF] Only convert dependdency filename to native form on Windows (PR #160927)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 26 10:48:20 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld
Author: Ruoyu Zhong (ZhongRuoyu)
<details>
<summary>Changes</summary>
Currently, `llvm::sys::path::native` is used unconditionally when generating dependency filenames. This is correct on Windows, where backslashes are valid path separators, but can be incorrect on non-Windows platforms, because in that case backslashes in the filenames are converted to forward slashes, while they should be treated as ordinary characters.
This fixes the following inconsistency between `ld.lld` and `ld.bfd`:
```console
$ cat test.s
.globl _start
_start:
$ cc -c test.s -o "back\\slash.o"
$ ld.lld -o test "back\\slash.o" --dependency-file=/dev/stdout
test: \
back/slash.o
back/slash.o:
$ ld.bfd -o test "back\\slash.o" --dependency-file=/dev/stdout
test: \
back\slash.o
back\slash.o:
```
In addition, while we're here, use 2-space indentation when printing out dependency filenames (consistent with Clang and `ld.bfd`), and escape the target filename too.
---
Full diff: https://github.com/llvm/llvm-project/pull/160927.diff
3 Files Affected:
- (modified) lld/ELF/Driver.cpp (+8-3)
- (added) lld/test/ELF/dependency-file-backslash-as-normal-char.s (+13)
- (added) lld/test/ELF/dependency-file-backslash-as-path-separator.s (+13)
``````````diff
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 1beab8d33f4ba..8483e01364982 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2482,10 +2482,14 @@ static void writeDependencyFile(Ctx &ctx) {
// We use the same escape rules as Clang/GCC which are accepted by Make/Ninja:
// * A space is escaped by a backslash which itself must be escaped.
// * A hash sign is escaped by a single backslash.
- // * $ is escapes as $$.
+ // * $ is escaped as $$.
auto printFilename = [](raw_fd_ostream &os, StringRef filename) {
llvm::SmallString<256> nativePath;
+#ifdef _WIN32
llvm::sys::path::native(filename.str(), nativePath);
+#else
+ nativePath = filename;
+#endif
llvm::sys::path::remove_dots(nativePath, /*remove_dot_dot=*/true);
for (unsigned i = 0, e = nativePath.size(); i != e; ++i) {
if (nativePath[i] == '#') {
@@ -2502,9 +2506,10 @@ static void writeDependencyFile(Ctx &ctx) {
}
};
- os << ctx.arg.outputFile << ":";
+ printFilename(os, ctx.arg.outputFile);
+ os << ":";
for (StringRef path : ctx.arg.dependencyFiles) {
- os << " \\\n ";
+ os << " \\\n ";
printFilename(os, path);
}
os << "\n";
diff --git a/lld/test/ELF/dependency-file-backslash-as-normal-char.s b/lld/test/ELF/dependency-file-backslash-as-normal-char.s
new file mode 100644
index 0000000000000..278e06d41d683
--- /dev/null
+++ b/lld/test/ELF/dependency-file-backslash-as-normal-char.s
@@ -0,0 +1,13 @@
+# REQUIRES: x86, !system-windows
+# RUN: mkdir -p %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o "%t/back\\slash.o"
+# RUN: ld.lld -o %t/foo.exe "%t/back\\slash.o" --dependency-file=%t/foo.d
+# RUN: FileCheck --match-full-lines -DFILE=%t %s < %t/foo.d
+
+# CHECK: [[FILE]]/foo.exe: \
+# CHECK-NEXT: [[FILE]]/back\slash.o
+# CHECK-EMPTY:
+# CHECK-NEXT: [[FILE]]/back\slash.o:
+
+.global _start
+_start:
diff --git a/lld/test/ELF/dependency-file-backslash-as-path-separator.s b/lld/test/ELF/dependency-file-backslash-as-path-separator.s
new file mode 100644
index 0000000000000..6e738626c4127
--- /dev/null
+++ b/lld/test/ELF/dependency-file-backslash-as-path-separator.s
@@ -0,0 +1,13 @@
+# REQUIRES: x86, system-windows
+# RUN: mkdir -p %t/back
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o "%t/back\\slash.o"
+# RUN: ld.lld -o %t/foo.exe "%t/back\\slash.o" --dependency-file=%t/foo.d
+# RUN: FileCheck --match-full-lines -DFILE=%t %s < %t/foo.d
+
+# CHECK: [[FILE]]\foo.exe: \
+# CHECK-NEXT: [[FILE]]\back\slash.o
+# CHECK-EMPTY:
+# CHECK-NEXT: [[FILE]]\back\slash.o:
+
+.global _start
+_start:
``````````
</details>
https://github.com/llvm/llvm-project/pull/160927
More information about the llvm-commits
mailing list