-
Couldn't load subscription status.
- Fork 15k
[lld][COFF] Add /linkreprofullpathrsp flag #165449
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
base: main
Are you sure you want to change the base?
Conversation
This patch adds the /linkreprofullpathrsp flag with the same behaviour as link.exe. This flag emits a file containing the full paths to each object passed to the link line. This is used in particular when linking Arm64X binaries, as you need the full path to all the Arm64 objects that were used in a standard Arm64 build. See: https://learn.microsoft.com/en-us/cpp/build/reference/link-repro-full-path-rsp for the Microsoft documentation of the flag.
|
@llvm/pr-subscribers-platform-windows @llvm/pr-subscribers-lld-coff Author: David Truby (DavidTruby) ChangesThis patch adds the /linkreprofullpathrsp flag with the same behaviour as link.exe. This flag emits a file containing the full paths to each object passed to the link line. This is used in particular when linking Arm64X binaries, as you need the full path to all the Arm64 objects that were used in a standard Arm64 build. See: Full diff: https://github.com/llvm/llvm-project/pull/165449.diff 4 Files Affected:
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 0e528de9c3652..e2ad2f1c1e993 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -318,7 +318,8 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
}
}
-void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) {
+void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy,
+ llvm::raw_ostream *reproFile, bool defaultlib) {
auto future = std::make_shared<std::future<MBErrPair>>(
createFutureForFile(std::string(path)));
std::string pathStr = std::string(path);
@@ -356,8 +357,17 @@ void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) {
Err(ctx) << msg;
else
Err(ctx) << msg << "; did you mean '" << nearest << "'";
- } else
+ } else {
+ // Write full path to library to repro file if /linkreprofullpathrsp
+ // is specified.
+ if (reproFile) {
+ *reproFile << '"';
+ if (defaultlib)
+ *reproFile << "/defaultlib:";
+ *reproFile << pathStr << "\"\n";
+ }
ctx.driver.addBuffer(std::move(mb), wholeArchive, lazy);
+ }
});
}
@@ -514,7 +524,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
break;
case OPT_defaultlib:
if (std::optional<StringRef> path = findLibIfNew(arg->getValue()))
- enqueuePath(*path, false, false);
+ enqueuePath(*path, false, false, nullptr);
break;
case OPT_entry:
if (!arg->getValue()[0])
@@ -2204,6 +2214,17 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
config->incremental = false;
}
+ // Handle /linkreprofullpathrsp.
+ std::unique_ptr<llvm::raw_ostream> reproFile;
+ if (auto *arg = args.getLastArg(OPT_linkreprofullpathrsp)) {
+ std::error_code ec;
+ reproFile = std::make_unique<llvm::raw_fd_ostream>(arg->getValue(), ec);
+ if (ec) {
+ Err(ctx) << "cannot open " << arg->getValue() << ": " << ec.message();
+ reproFile.reset();
+ }
+ }
+
if (errCount(ctx))
return;
@@ -2245,11 +2266,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
break;
case OPT_wholearchive_file:
if (std::optional<StringRef> path = findFileIfNew(arg->getValue()))
- enqueuePath(*path, true, inLib);
+ enqueuePath(*path, true, inLib, reproFile.get());
break;
case OPT_INPUT:
if (std::optional<StringRef> path = findFileIfNew(arg->getValue()))
- enqueuePath(*path, isWholeArchive(*path), inLib);
+ enqueuePath(*path, isWholeArchive(*path), inLib, reproFile.get());
break;
default:
// Ignore other options.
@@ -2289,7 +2310,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
// addWinSysRootLibSearchPaths(), which is why they are in a separate loop.
for (auto *arg : args.filtered(OPT_defaultlib))
if (std::optional<StringRef> path = findLibIfNew(arg->getValue()))
- enqueuePath(*path, false, false);
+ enqueuePath(*path, false, false, reproFile.get(), true);
run();
if (errorCount())
return;
diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h
index 14710d5853bcf..f4b72a317d077 100644
--- a/lld/COFF/Driver.h
+++ b/lld/COFF/Driver.h
@@ -88,11 +88,12 @@ class LinkerDriver {
void enqueueArchiveMember(const Archive::Child &c, const Archive::Symbol &sym,
StringRef parentName);
- void enqueuePDB(StringRef Path) { enqueuePath(Path, false, false); }
+ void enqueuePDB(StringRef Path) { enqueuePath(Path, false, false, nullptr); }
MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> mb);
- void enqueuePath(StringRef path, bool wholeArchive, bool lazy);
+ void enqueuePath(StringRef path, bool wholeArchive, bool lazy,
+ raw_ostream *reproFile, bool defaultlib = false);
// Returns a list of chunks of selected symbols.
std::vector<Chunk *> getChunks() const;
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index d77478fc9c987..dca8a721dc4fd 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -74,6 +74,9 @@ def libpath : P<"libpath", "Additional library search path">;
def linkrepro : Joined<["/", "-", "/?", "-?"], "linkrepro:">,
MetaVarName<"directory">,
HelpText<"Write repro.tar containing inputs and command to reproduce link">;
+def linkreprofullpathrsp : Joined<["/", "-", "/?", "-?"], "linkreprofullpathrsp:">,
+ MetaVarName<"directory">,
+ HelpText<"Write .rsp file containing inputs used to link with full paths">;
def lldignoreenv : F<"lldignoreenv">,
HelpText<"Ignore environment variables like %LIB%">;
def lldltocache : P<"lldltocache",
diff --git a/lld/test/COFF/linkreprofullpathrsp.test b/lld/test/COFF/linkreprofullpathrsp.test
new file mode 100644
index 0000000000000..c77f09eae9dcd
--- /dev/null
+++ b/lld/test/COFF/linkreprofullpathrsp.test
@@ -0,0 +1,38 @@
+# REQUIRES: x86
+# Unsupported on Windows due to maximum path length limitations.
+
+# RUN: rm -rf %t.dir
+# RUN: split-file %s %t.dir
+# RUN: yaml2obj %p/Inputs/hello32.yaml -o %t.obj
+# RUN: llvm-mc -filetype=obj -triple=i386-windows %t.dir/drectve.s -o %t.dir/drectve.obj
+# RUN: echo '_main@0' > %t.order
+# RUN: touch %t.def
+# RUN: touch %t.cg
+
+
+
+Test link.exe-style /linkreprofullpathrsp: flag.
+# RUN: mkdir -p %t.dir/build1
+# RUN: cd %t.dir/build1
+# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console /defaultlib:%p/Inputs/library.lib \
+# RUN: /entry:main@0 /linkreprofullpathrsp:%t.rsp /out:%t.exe
+# RUN: FileCheck %s --check-prefix=RSP -DT=%t -DP=%p < %t.rsp
+
+# RSP: [[T]].obj
+# RSP-NEXT: "[[P]]/Inputs/std32.lib"
+# RSP-NEXT: "/defaultlib:[[P]]/Inputs/library.lib"
+
+#--- drectve.s
+ .section .drectve, "yn"
+ .ascii "/defaultlib:std32"
+
+#--- archive.s
+ .text
+ .intel_syntax noprefix
+ .globl exportfn3
+ .p2align 4
+exportfn3:
+ ret
+
+ .section .drectve,"yni"
+ .ascii " /EXPORT:exportfn3"
|
This patch adds the /linkreprofullpathrsp flag with the same behaviour as link.exe. This flag emits a file containing the full paths to each object passed to the link line.
This is used in particular when linking Arm64X binaries, as you need the full path to all the Arm64 objects that were used in a standard Arm64 build.
See:
https://learn.microsoft.com/en-us/cpp/build/reference/link-repro-full-path-rsp for the Microsoft documentation of the flag.