return EC;
std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
- for (auto *Arg : Args->filtered(OPT_defaultlib)) {
- StringRef Path = findLib(Arg->getValue());
- if (!insertFile(Path))
- continue;
- Res->push_back(llvm::make_unique<ArchiveFile>(Path));
- }
+ for (auto *Arg : Args->filtered(OPT_defaultlib))
+ if (Optional<StringRef> Path = findLib(Arg->getValue()))
+ Res->push_back(llvm::make_unique<ArchiveFile>(*Path));
return std::error_code();
}
// Find file from search paths. You can omit ".obj", this function takes
// care of that. Note that the returned path is not guaranteed to exist.
-StringRef LinkerDriver::findFile(StringRef Filename) {
+StringRef LinkerDriver::doFindFile(StringRef Filename) {
bool hasPathSep = (Filename.find_first_of("/\\") != StringRef::npos);
if (hasPathSep)
return Filename;
return Filename;
}
-StringRef LinkerDriver::findLib(StringRef Filename) {
- StringRef S = addExtOpt(Filename, ".lib");
- return findFile(S);
+// Resolves a file path. This never returns the same path
+// (in that case, it returns None).
+Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {
+ StringRef Path = doFindFile(Filename);
+ bool Seen = !VisitedFiles.insert(Path.lower()).second;
+ if (Seen)
+ return None;
+ return Path;
}
-// Add Ext to Filename if Filename has no file extension.
-StringRef LinkerDriver::addExtOpt(StringRef Filename, StringRef Ext) {
+// Find library file from search path.
+StringRef LinkerDriver::doFindLib(StringRef Filename) {
+ // Add ".lib" to Filename if that has no file extension.
bool hasExt = (Filename.find('.') != StringRef::npos);
- if (hasExt)
- return Filename;
- return Alloc.save(Filename + Ext);
+ if (!hasExt)
+ Filename = Alloc.save(Filename + ".lib");
+ return doFindFile(Filename);
+}
+
+// Resolves a library path. /nodefaultlib options are taken into
+// consideration. This never returns the same path (in that case,
+// it returns None).
+Optional<StringRef> LinkerDriver::findLib(StringRef Filename) {
+ if (Config->NoDefaultLibAll)
+ return None;
+ StringRef Path = doFindLib(Filename);
+ if (Config->NoDefaultLibs.count(Path))
+ return None;
+ bool Seen = !VisitedFiles.insert(Path.lower()).second;
+ if (Seen)
+ return None;
+ return Path;
}
// Parses LIB environment which contains a list of search paths.
}
Config->MachineType = MTOrErr.get();
+ // Handle /nodefaultlib:<filename>
+ for (auto *Arg : Args->filtered(OPT_nodefaultlib))
+ Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
+
+ // Handle /nodefaultlib
+ if (Args->hasArg(OPT_nodefaultlib_all))
+ Config->NoDefaultLibAll = true;
+
// Handle /base
if (auto *Arg = Args->getLastArg(OPT_base)) {
if (auto EC = parseNumbers(Arg->getValue(), &Config->ImageBase)) {
}
}
+ // Create a list of input files. Files can be given as arguments
+ // for /defaultlib option.
+ std::vector<StringRef> Inputs;
+ for (auto *Arg : Args->filtered(OPT_INPUT))
+ if (Optional<StringRef> Path = findFile(Arg->getValue()))
+ Inputs.push_back(*Path);
+ for (auto *Arg : Args->filtered(OPT_defaultlib))
+ if (Optional<StringRef> Path = findLib(Arg->getValue()))
+ Inputs.push_back(*Path);
+
// Parse all input files and put all symbols to the symbol table.
// The symbol table will take care of name resolution.
SymbolTable Symtab;
- for (auto *Arg : Args->filtered(OPT_INPUT)) {
- StringRef Path = findFile(Arg->getValue());
- if (!insertFile(Path))
- continue;
+ for (StringRef Path : Inputs) {
if (auto EC = Symtab.addFile(createFile(Path))) {
llvm::errs() << Path << ": " << EC.message() << "\n";
return false;
return true;
}
-bool LinkerDriver::insertFile(StringRef Path) {
- return VisitedFiles.insert(Path.lower()).second;
-}
-
} // namespace coff
} // namespace lld
#define LLD_COFF_DRIVER_H
#include "Memory.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/COFF.h"
#include "llvm/Option/Arg.h"
using llvm::COFF::MachineTypes;
using llvm::COFF::WindowsSubsystem;
+using llvm::Optional;
class InputFile;
// Entry point of the COFF linker.
parseDirectives(StringRef S, std::vector<std::unique_ptr<InputFile>> *Res);
private:
- // Returns false if a given file has already been read.
- bool insertFile(StringRef Path);
+ StringAllocator Alloc;
// Searches a file from search paths.
- StringRef findFile(StringRef Filename);
- StringRef findLib(StringRef Filename);
- StringRef addExtOpt(StringRef Filename, StringRef Ext);
+ Optional<StringRef> findFile(StringRef Filename);
+ Optional<StringRef> findLib(StringRef Filename);
+ StringRef doFindFile(StringRef Filename);
+ StringRef doFindLib(StringRef Filename);
// Parses LIB environment which contains a list of search paths.
// The returned list always contains "." as the first element.
std::vector<StringRef> SearchPaths;
std::set<std::string> VisitedFiles;
- StringAllocator Alloc;
};
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
--- /dev/null
+# RUN: cp %p/Inputs/hello64.obj %T
+# RUN: cp %p/Inputs/std64.lib %T
+
+# RUN: not lld -flavor link2 /out:%t.exe /entry:main /subsystem:console \
+# RUN: hello64.obj /defaultlib:std64.lib >& %t.log
+# RUN: FileCheck -check-prefix=CHECK1 %s < %t.log
+
+# RUN: not lld -flavor link2 /out:%t.exe /entry:main /subsystem:console \
+# RUN: hello64 /defaultlib:std64.lib >& %t.log
+# RUN: FileCheck -check-prefix=CHECK2 %s < %t.log
+
+### On Windows, "env" command does not propagate subcommand exit status.
+### On Unix it does. "|| true" is a hack to deal with that.
+
+# RUN: env LIB=%T lld -flavor link2 /out:%t.exe /entry:main \
+# RUN: /subsystem:console hello64.obj /defaultlib:std64.lib \
+# RUN: /nodefaultlib:std64.lib >& %t.log || true
+# RUN: FileCheck -check-prefix=CHECK3 %s < %t.log
+
+# RUN: env LIB=%T lld -flavor link2 /out:%t.exe /entry:main \
+# RUN: /subsystem:console hello64.obj /defaultlib:std64 \
+# RUN: /nodefaultlib:std64.lib >& %t.log || true
+# RUN: FileCheck -check-prefix=CHECK3 %s < %t.log
+
+CHECK1: hello64.obj: {{[Nn]}}o such file or directory
+CHECK2: hello64: {{[Nn]}}o such file or directory
+CHECK3: undefined symbol: MessageBoxA
+
+# RUN: env LIB=%T lld -flavor link2 /out:%t.exe /entry:main \
+# RUN: /subsystem:console hello64.obj /defaultlib:std64.lib