aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
diff options
context:
space:
mode:
authorVadim Paretsky (Intel Americas Inc) <b-vadipa@microsoft.com>2023-03-01 20:32:35 -0800
committerVadim Paretsky (Intel Americas Inc) <b-vadipa@microsoft.com>2023-03-01 20:32:35 -0800
commit395ec4458fb7fc700551f7017c0a395d68c55873 (patch)
tree654d6faeb81816bcde27f5ecdb1a88028c335e80 /llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
parent52ced140988a3f9ba715683d3a07b87d93faa9d1 (diff)
downloadllvm-395ec4458fb7fc700551f7017c0a395d68c55873.zip
llvm-395ec4458fb7fc700551f7017c0a395d68c55873.tar.gz
llvm-395ec4458fb7fc700551f7017c0a395d68c55873.tar.bz2
[llvm-lib] 'llvm-lib' currently cannot generate an import library from a Windows
.def file, functionality supported by 'lib'. This incompatibility is breaking clang based Windows openmp builds. This revision adds basic support for this feature to llvm-lib by cloning the corresponding code from 'dlltool'. Differential Revision:https://reviews.llvm.org/D144765
Diffstat (limited to 'llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp')
-rw-r--r--llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp102
1 files changed, 80 insertions, 22 deletions
diff --git a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
index f92ff3d..3a609ee 100644
--- a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
+++ b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
@@ -19,6 +19,7 @@
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Object/COFFModuleDefinition.h"
#include "llvm/Object/WindowsMachineFlag.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
@@ -31,6 +32,7 @@
#include <optional>
using namespace llvm;
+using namespace llvm::object;
namespace {
@@ -60,7 +62,7 @@ class LibOptTable : public opt::GenericOptTable {
public:
LibOptTable() : opt::GenericOptTable(InfoTable, true) {}
};
-}
+} // namespace
static std::string getDefaultOutputPath(const NewArchiveMember &FirstMember) {
SmallString<128> Val = StringRef(FirstMember.Buf->getBufferIdentifier());
@@ -91,6 +93,18 @@ static std::vector<StringRef> getSearchPaths(opt::InputArgList *Args,
return Ret;
}
+// Opens a file. Path has to be resolved already. (used for def file)
+std::unique_ptr<MemoryBuffer> openFile(const Twine &Path) {
+ ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB = MemoryBuffer::getFile(Path);
+
+ if (std::error_code EC = MB.getError()) {
+ llvm::errs() << "cannot open file " << Path << ": " << EC.message() << "\n";
+ return nullptr;
+ }
+
+ return std::move(*MB);
+}
+
static std::string findInputFile(StringRef File, ArrayRef<StringRef> Paths) {
for (StringRef Dir : Paths) {
SmallString<128> Path = Dir;
@@ -110,7 +124,7 @@ static void fatalOpenError(llvm::Error E, Twine File) {
});
}
-static void doList(opt::InputArgList& Args) {
+static void doList(opt::InputArgList &Args) {
// lib.exe prints the contents of the first archive file.
std::unique_ptr<MemoryBuffer> B;
for (auto *Arg : Args.filtered(OPT_INPUT)) {
@@ -302,6 +316,63 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
for (auto *Arg : Args.filtered(OPT_ignore))
IgnoredWarnings.insert(Arg->getValue());
+ // get output library path, if any
+ std::string OutputPath;
+ if (auto *Arg = Args.getLastArg(OPT_out)) {
+ OutputPath = Arg->getValue();
+ }
+
+ COFF::MachineTypes LibMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
+ std::string LibMachineSource;
+ if (auto *Arg = Args.getLastArg(OPT_machine)) {
+ LibMachine = getMachineType(Arg->getValue());
+ if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
+ llvm::errs() << "unknown /machine: arg " << Arg->getValue() << '\n';
+ return 1;
+ }
+ LibMachineSource =
+ std::string(" (from '/machine:") + Arg->getValue() + "' flag)";
+ }
+
+ // create an import library
+ if (Args.hasArg(OPT_deffile)) {
+
+ if (OutputPath.empty()) {
+ llvm::errs() << "no output path given\n";
+ return 1;
+ }
+
+ if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
+ llvm::errs() << "/def option requires /machine to be specified" << '\n';
+ return 1;
+ }
+
+ std::unique_ptr<MemoryBuffer> MB =
+ openFile(Args.getLastArg(OPT_deffile)->getValue());
+ if (!MB)
+ return 1;
+
+ if (!MB->getBufferSize()) {
+ llvm::errs() << "definition file empty\n";
+ return 1;
+ }
+
+ Expected<COFFModuleDefinition> Def =
+ parseCOFFModuleDefinition(*MB, LibMachine, true);
+
+ if (!Def) {
+ llvm::errs() << "error parsing definition\n"
+ << errorToErrorCode(Def.takeError()).message();
+ return 1;
+ }
+
+ return writeImportLibrary(Def->OutputFile, OutputPath, Def->Exports,
+ LibMachine,
+ /*MinGW=*/false)
+ ? 1
+ : 0;
+ }
+
// If no input files and not told otherwise, silently do nothing to match
// lib.exe
if (!Args.hasArgNoClaim(OPT_INPUT) && !Args.hasArg(OPT_llvmlibempty)) {
@@ -324,18 +395,6 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
std::vector<StringRef> SearchPaths = getSearchPaths(&Args, Saver);
- COFF::MachineTypes LibMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
- std::string LibMachineSource;
- if (auto *Arg = Args.getLastArg(OPT_machine)) {
- LibMachine = getMachineType(Arg->getValue());
- if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
- llvm::errs() << "unknown /machine: arg " << Arg->getValue() << '\n';
- return 1;
- }
- LibMachineSource =
- std::string(" (from '/machine:") + Arg->getValue() + "' flag)";
- }
-
std::vector<std::unique_ptr<MemoryBuffer>> MBs;
StringSet<> Seen;
std::vector<NewArchiveMember> Members;
@@ -373,14 +432,13 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
}
// Create an archive file.
- std::string OutputPath;
- if (auto *Arg = Args.getLastArg(OPT_out)) {
- OutputPath = Arg->getValue();
- } else if (!Members.empty()) {
- OutputPath = getDefaultOutputPath(Members[0]);
- } else {
- llvm::errs() << "no output path given, and cannot infer with no inputs\n";
- return 1;
+ if (OutputPath.empty()) {
+ if (!Members.empty()) {
+ OutputPath = getDefaultOutputPath(Members[0]);
+ } else {
+ llvm::errs() << "no output path given, and cannot infer with no inputs\n";
+ return 1;
+ }
}
// llvm-lib uses relative paths for both regular and thin archives, unlike
// standard GNU ar, which only uses relative paths for thin archives and