using namespace llvm;
using namespace llvm::object;
using namespace llvm::COFF;
-using llvm::sys::Process;
+using namespace llvm::sys;
namespace lld {
namespace coff {
return config->dll ? 0x10000000 : 0x400000;
}
+static std::string rewritePath(StringRef s) {
+ if (fs::exists(s))
+ return relativeToRoot(s);
+ return std::string(s);
+}
+
+// Reconstructs command line arguments so that so that you can re-run
+// the same command with the same inputs. This is for --reproduce.
static std::string createResponseFile(const opt::InputArgList &args,
ArrayRef<StringRef> filePaths,
ArrayRef<StringRef> searchPaths) {
case OPT_manifestinput:
case OPT_manifestuac:
break;
+ case OPT_call_graph_ordering_file:
+ case OPT_deffile:
+ case OPT_natvis:
+ os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << '\n';
+ break;
+ case OPT_order: {
+ StringRef orderFile = arg->getValue();
+ orderFile.consume_front("@");
+ os << arg->getSpelling() << '@' << quote(rewritePath(orderFile)) << '\n';
+ break;
+ }
+ case OPT_pdbstream: {
+ const std::pair<StringRef, StringRef> nameFile =
+ StringRef(arg->getValue()).split("=");
+ os << arg->getSpelling() << nameFile.first << '='
+ << quote(rewritePath(nameFile.second)) << '\n';
+ break;
+ }
case OPT_implib:
case OPT_pdb:
case OPT_pdbstripped:
COFFModuleDefinition m = check(parseCOFFModuleDefinition(
mb->getMemBufferRef(), config->machine, config->mingw));
+ // Include in /reproduce: output if applicable.
+ driver->takeBuffer(std::move(mb));
+
if (config->outputFile.empty())
config->outputFile = std::string(saver.save(m.OutputFile));
config->importName = std::string(saver.save(m.ImportName));
else
config->order[s] = INT_MIN + config->order.size();
}
+
+ // Include in /reproduce: output if applicable.
+ driver->takeBuffer(std::move(mb));
}
static void parseCallGraphFile(StringRef path) {
if (SectionChunk *to = findSection(fields[1]))
config->callGraphProfile[{from, to}] += count;
}
+
+ // Include in /reproduce: output if applicable.
+ driver->takeBuffer(std::move(mb));
}
static void readCallGraphsFromObjectFiles() {
void enqueuePath(StringRef path, bool wholeArchive, bool lazy);
-private:
std::unique_ptr<llvm::TarWriter> tar; // for /linkrepro
+private:
// Searches a file from search paths.
Optional<StringRef> findFile(StringRef filename);
Optional<StringRef> findLib(StringRef filename);
warn("Cannot open input file: " + file);
continue;
}
- builder.addInjectedSource(file, std::move(*dataOrErr));
+ std::unique_ptr<MemoryBuffer> data = std::move(*dataOrErr);
+
+ // Can't use takeBuffer() here since addInjectedSource() takes ownership.
+ if (driver->tar)
+ driver->tar->append(relativeToRoot(data->getBufferIdentifier()),
+ data->getBuffer());
+
+ builder.addInjectedSource(file, std::move(data));
}
}
warn("Cannot open input file: " + file);
continue;
}
- exitOnErr(builder.addNamedStream(stream, (*dataOrErr)->getBuffer()));
+ std::unique_ptr<MemoryBuffer> data = std::move(*dataOrErr);
+ exitOnErr(builder.addNamedStream(stream, data->getBuffer()));
+ driver->takeBuffer(std::move(data));
}
}
REQUIRES: x86, gnutar, manifest_tool
+manifest-related files are compiled to a .res file and the .res file is
+added to the repro archive, instead of adding the inputs.
+
RUN: rm -rf %t && mkdir %t && cd %t
-RUN: lld-link -entry:__ImageBase -nodefaultlib -linkrepro:%t -manifest:embed %p/Inputs/std32.lib -subsystem:console
+RUN: lld-link -entry:__ImageBase -nodefaultlib -linkrepro:%t \
+RUN: -manifest:embed %p/Inputs/std32.lib -subsystem:console \
+RUN: -manifestinput:%p/Inputs/manifestinput.test
+
RUN: tar tf repro.tar | FileCheck --check-prefix=LIST %s
RUN: tar xOf repro.tar repro/response.txt | FileCheck %s
RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj
RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj
RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb
-RUN: lld-link a.obj b.obj -entry:main -debug -out:%t.exe -pdb:%t.pdb -nodefaultlib -linkrepro:.
-RUN: tar xOf repro.tar repro/%:t/ts.pdb > repro-ts.pdb
-RUN: diff ts.pdb repro-ts.pdb
-
+RUN: cp %p/Inputs/natvis-1.natvis %t.natvis
+RUN: cp %p/Inputs/stream.txt %t.txt
+RUN: lld-link a.obj b.obj -entry:main -debug -out:%t.exe -pdb:%t.pdb \
+RUN: -nodefaultlib -linkrepro:. -natvis:%t.natvis \
+RUN: -pdbstream:srcsrv=%t.txt
+RUN: tar tf repro.tar | FileCheck --check-prefix=LIST %s
RUN: tar xf repro.tar
-RUN: cat repro/response.txt | FileCheck -check-prefix=PDB %s
+RUN: diff ts.pdb repro/%:t/ts.pdb
+RUN: diff %t.natvis repro/%:t.natvis
+RUN: diff %t.txt repro/%:t.txt
+RUN: cat repro/response.txt | FileCheck -check-prefix=RSP %s
+
+LIST: .obj
+LIST: response.txt
+LIST: .natvis
-PDB: -out:linkrepro-pdb.test.tmp.exe
-PDB-NEXT: -pdb:linkrepro-pdb.test.tmp.pdb
+RSP: -out:linkrepro-pdb.test.tmp.exe
+RSP-NEXT: -pdb:linkrepro-pdb.test.tmp.pdb
+RSP-NEXT: -nodefaultlib
+RSP-NOT: -natvis:/
+RSP-NOT: -pdbstream:srcsrv=/
RUN: yaml2obj %p/Inputs/export.yaml -o %t1.obj
-RUN: lld-link /out:%t1.dll /dll %t1.obj /implib:%t1.lib /export:exportfn1 /export:exportfn2 /linkrepro:.
-RUN: tar xf repro.tar
-RUN: cat repro/response.txt | FileCheck -check-prefix=IMP %s
+RUN: lld-link /out:%t1.dll /dll %t1.obj /implib:%t1.lib /export:exportfn1 /export:exportfn2 /reproduce:repro2.tar
+RUN: tar xf repro2.tar
+RUN: cat repro2/response.txt | FileCheck -check-prefix=IMP %s
IMP: /implib:linkrepro-pdb.test.tmp1.lib
# REQUIRES: x86, shell
# RUN: rm -rf %t.dir
-# RUN: mkdir -p %t.dir/build1 %t.dir/build2 %t.dir/build3 %t.dir/build4
# RUN: yaml2obj %p/Inputs/hello32.yaml -o %t.obj
+# RUN: echo '_main@0' > %t.order
+# RUN: touch %t.def
+# RUN: touch %t.cg
+Test link.exe-style /linkrepro: flag.
+# RUN: mkdir -p %t.dir/build1
# RUN: cd %t.dir/build1
# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \
# RUN: /entry:main@0 /linkrepro:. /out:%t.exe
# 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
+Test lld-style /reproduce: flag.
# 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 %p/Inputs/std32.lib repro2/%:p/Inputs/std32.lib
# RUN: FileCheck %s --check-prefix=RSP < repro2/response.txt
+Test LLD_REPRODUCE env var.
+# RUN: mkdir -p %t.dir/build2
# RUN: cd %t.dir/build2
# RUN: env LLD_REPRODUCE=repro.tar lld-link %t.obj %p/Inputs/std32.lib \
# RUN: /subsystem:console /entry:main@0 /out:%t.exe
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
+Test adding .lib files with /libpath: to repro archive,
+and various other flags.
+# RUN: mkdir -p %t.dir/build3
# RUN: cd %t.dir/build3
# RUN: lld-link %t.obj /libpath:%p/Inputs /defaultlib:std32 /subsystem:console \
-# RUN: /entry:main@0 /linkrepro:. /out:%t.exe
+# RUN: /entry:main@0 /linkrepro:. /out:%t.exe /order:@%t.order /def:%t.def
+# RUN: tar tf repro.tar | FileCheck --check-prefix=LIST %s
# RUN: tar xf repro.tar
# RUN: diff %t.obj repro/%:t.obj
+# RUN: diff %t.order repro/%:t.order
+# RUN: diff %t.def repro/%:t.def
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
+# RUN: cd repro; lld-link @response.txt
+Test adding .lib files with LIB env var to repro archive,
+and various other flags.
+# RUN: mkdir -p %t.dir/build4
# RUN: cd %t.dir/build4
# RUN: env LIB=%p/Inputs lld-link %t.obj /defaultlib:std32 /subsystem:console \
-# RUN: /entry:main@0 /linkrepro:. /out:%t.exe
+# RUN: /entry:main@0 /linkrepro:. /out:%t.exe /order:@%t.order /def:%t.def
+# RUN: tar tf repro.tar | FileCheck --check-prefix=LIST %s
# RUN: tar xf repro.tar
# RUN: diff %t.obj repro/%:t.obj
+# RUN: diff %t.order repro/%:t.order
+# RUN: diff %t.def repro/%:t.def
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
+# RUN: cd repro; lld-link @response.txt
+
+# LIST: .obj
+# LIST: std32.lib
+# LIST: response.txt
+# LIST: .def
+# LIST: .order
# RSP: /subsystem:console
# RSP: /entry:main@0
-# RSP-NOT: /linkrepro:
# RSP: /out:
+# RSP-NOT: /order:@/
+# RSP-NOT: /def:/
# RSP: linkrepro.test.tmp.obj
# RSP-NOT: defaultlib
# RSP: std32.lib
+
+Test /call-graph-ordering-file (can't be used with /order:, needs separate test)
+# RUN: mkdir -p %t.dir/build5
+# RUN: cd %t.dir/build5
+# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \
+# RUN: /entry:main@0 /linkrepro:. /out:%t.exe /call-graph-ordering-file:%t.cg
+# RUN: tar tf repro.tar | FileCheck --check-prefix=LISTCG %s
+# RUN: tar xf repro.tar
+# RUN: diff %t.obj repro/%:t.obj
+# RUN: diff %t.cg repro/%:t.cg
+# RUN: FileCheck %s --check-prefix=RSPCG < repro/response.txt
+# RUN: cd repro; lld-link @response.txt
+
+# LISTCG: .obj
+# LISTCG: response.txt
+# LISTCG: .cg
+
+# RSPCG-NOT: /call-graph-ordering-file:/