Index: lld/trunk/COFF/Driver.cpp =================================================================== --- lld/trunk/COFF/Driver.cpp +++ lld/trunk/COFF/Driver.cpp @@ -603,6 +603,7 @@ for (auto *arg : args) { switch (arg->getOption().getID()) { case OPT_linkrepro: + case OPT_reproduce: case OPT_INPUT: case OPT_defaultlib: case OPT_libpath: @@ -1071,6 +1072,26 @@ }); } +// lld has a feature to create a tar file containing all input files as well as +// all command line options, so that other people can run lld again with exactly +// the same inputs. This feature is accessible via /linkrepro and /reproduce. +// +// /linkrepro and /reproduce are very similar, but /linkrepro takes a directory +// name while /reproduce takes a full path. We have /linkrepro for compatibility +// with Microsoft link.exe. +Optional getReproduceFile(const opt::InputArgList &args) { + if (auto *arg = args.getLastArg(OPT_reproduce)) + return std::string(arg->getValue()); + + if (auto *arg = args.getLastArg(OPT_linkrepro)) { + SmallString<64> path = StringRef(arg->getValue()); + sys::path::append(path, "repro.tar"); + return path.str().str(); + } + + return None; +} + void LinkerDriver::link(ArrayRef argsArr) { // Needed for LTO. InitializeAllTargetInfos(); @@ -1133,17 +1154,15 @@ // options are handled. config->mingw = args.hasArg(OPT_lldmingw); - if (auto *arg = args.getLastArg(OPT_linkrepro)) { - SmallString<64> path = StringRef(arg->getValue()); - sys::path::append(path, "repro.tar"); - + // Handle /linkrepro and /reproduce. + if (Optional path = getReproduceFile(args)) { Expected> errOrWriter = - TarWriter::create(path, "repro"); + TarWriter::create(*path, sys::path::stem(*path)); if (errOrWriter) { tar = std::move(*errOrWriter); } else { - error("/linkrepro: failed to open " + path + ": " + + error("/linkrepro: failed to open " + *path + ": " + toString(errOrWriter.takeError())); } } Index: lld/trunk/COFF/Options.td =================================================================== --- lld/trunk/COFF/Options.td +++ lld/trunk/COFF/Options.td @@ -112,6 +112,8 @@ def profile : F<"profile">; def repro : F<"Brepro">, HelpText<"Use a hash of the executable as the PE header timestamp">; +def reproduce : P<"reproduce", + "Dump linker invocation and input files for debugging">; def swaprun : P<"swaprun", "Comma-separated list of 'cd' or 'net'">; def swaprun_cd : F<"swaprun:cd">, Alias, AliasArgs<["cd"]>, Index: lld/trunk/test/COFF/linkrepro.test =================================================================== --- lld/trunk/test/COFF/linkrepro.test +++ lld/trunk/test/COFF/linkrepro.test @@ -12,6 +12,14 @@ # RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib # RUN: FileCheck %s --check-prefix=RSP < repro/response.txt +# RUN: cd %t.dir/build1 +# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \ +# RUN: /entry:main@0 /reproduce:repro2.tar /out:%t.exe +# RUN: tar xf repro2.tar +# RUN: diff %t.obj repro2/%:t.obj +# RUN: diff %p/Inputs/std32.lib repro2/%:p/Inputs/std32.lib +# RUN: FileCheck %s --check-prefix=RSP < repro2/response.txt + # RUN: cd %t.dir/build2 # RUN: lld-link %t.obj /libpath:%p/Inputs /defaultlib:std32 /subsystem:console \ # RUN: /entry:main@0 /linkrepro:. /out:%t.exe