mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 04:56:07 +00:00
COFF: Add /nodefaultlib option.
llvm-svn: 238679
This commit is contained in:
parent
54b71daec4
commit
d21b00bd7c
@ -20,6 +20,7 @@ namespace lld {
|
||||
namespace coff {
|
||||
|
||||
using llvm::COFF::WindowsSubsystem;
|
||||
using llvm::StringRef;
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
@ -28,6 +29,9 @@ public:
|
||||
WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
|
||||
std::string EntryName;
|
||||
|
||||
std::set<StringRef> NoDefaultLibs;
|
||||
bool NoDefaultLibAll = false;
|
||||
|
||||
uint64_t ImageBase = 0x140000000;
|
||||
uint64_t StackReserve = 1024 * 1024;
|
||||
uint64_t StackCommit = 4096;
|
||||
|
@ -95,18 +95,15 @@ LinkerDriver::parseDirectives(StringRef S,
|
||||
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;
|
||||
@ -125,17 +122,38 @@ StringRef LinkerDriver::findFile(StringRef 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.
|
||||
@ -190,6 +208,14 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) {
|
||||
}
|
||||
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)) {
|
||||
@ -235,13 +261,20 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
@ -289,9 +322,5 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LinkerDriver::insertFile(StringRef Path) {
|
||||
return VisitedFiles.insert(Path.lower()).second;
|
||||
}
|
||||
|
||||
} // namespace coff
|
||||
} // namespace lld
|
||||
|
@ -11,6 +11,7 @@
|
||||
#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"
|
||||
@ -28,6 +29,7 @@ extern LinkerDriver *Driver;
|
||||
|
||||
using llvm::COFF::MachineTypes;
|
||||
using llvm::COFF::WindowsSubsystem;
|
||||
using llvm::Optional;
|
||||
class InputFile;
|
||||
|
||||
// Entry point of the COFF linker.
|
||||
@ -43,13 +45,13 @@ public:
|
||||
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.
|
||||
@ -57,7 +59,6 @@ private:
|
||||
|
||||
std::vector<StringRef> SearchPaths;
|
||||
std::set<std::string> VisitedFiles;
|
||||
StringAllocator Alloc;
|
||||
};
|
||||
|
||||
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
|
||||
|
30
lld/test/COFF/nodefaultlib.test
Normal file
30
lld/test/COFF/nodefaultlib.test
Normal file
@ -0,0 +1,30 @@
|
||||
# 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
|
Loading…
x
Reference in New Issue
Block a user