19
19
#include " llvm/Bitcode/BitcodeReader.h"
20
20
#include " llvm/Object/ArchiveWriter.h"
21
21
#include " llvm/Object/COFF.h"
22
+ #include " llvm/Object/COFFModuleDefinition.h"
22
23
#include " llvm/Object/WindowsMachineFlag.h"
23
24
#include " llvm/Option/Arg.h"
24
25
#include " llvm/Option/ArgList.h"
31
32
#include < optional>
32
33
33
34
using namespace llvm ;
35
+ using namespace llvm ::object;
34
36
35
37
namespace {
36
38
@@ -60,7 +62,7 @@ class LibOptTable : public opt::GenericOptTable {
60
62
public:
61
63
LibOptTable () : opt::GenericOptTable(InfoTable, true ) {}
62
64
};
63
- }
65
+ } // namespace
64
66
65
67
static std::string getDefaultOutputPath (const NewArchiveMember &FirstMember) {
66
68
SmallString<128 > Val = StringRef (FirstMember.Buf ->getBufferIdentifier ());
@@ -91,6 +93,18 @@ static std::vector<StringRef> getSearchPaths(opt::InputArgList *Args,
91
93
return Ret;
92
94
}
93
95
96
+ // Opens a file. Path has to be resolved already. (used for def file)
97
+ std::unique_ptr<MemoryBuffer> openFile (const Twine &Path) {
98
+ ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB = MemoryBuffer::getFile (Path);
99
+
100
+ if (std::error_code EC = MB.getError ()) {
101
+ llvm::errs () << " cannot open file " << Path << " : " << EC.message () << " \n " ;
102
+ return nullptr ;
103
+ }
104
+
105
+ return std::move (*MB);
106
+ }
107
+
94
108
static std::string findInputFile (StringRef File, ArrayRef<StringRef> Paths) {
95
109
for (StringRef Dir : Paths) {
96
110
SmallString<128 > Path = Dir;
@@ -110,7 +124,7 @@ static void fatalOpenError(llvm::Error E, Twine File) {
110
124
});
111
125
}
112
126
113
- static void doList (opt::InputArgList& Args) {
127
+ static void doList (opt::InputArgList & Args) {
114
128
// lib.exe prints the contents of the first archive file.
115
129
std::unique_ptr<MemoryBuffer> B;
116
130
for (auto *Arg : Args.filtered (OPT_INPUT)) {
@@ -302,6 +316,63 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
302
316
for (auto *Arg : Args.filtered (OPT_ignore))
303
317
IgnoredWarnings.insert (Arg->getValue ());
304
318
319
+ // get output library path, if any
320
+ std::string OutputPath;
321
+ if (auto *Arg = Args.getLastArg (OPT_out)) {
322
+ OutputPath = Arg->getValue ();
323
+ }
324
+
325
+ COFF::MachineTypes LibMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
326
+ std::string LibMachineSource;
327
+ if (auto *Arg = Args.getLastArg (OPT_machine)) {
328
+ LibMachine = getMachineType (Arg->getValue ());
329
+ if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
330
+ llvm::errs () << " unknown /machine: arg " << Arg->getValue () << ' \n ' ;
331
+ return 1 ;
332
+ }
333
+ LibMachineSource =
334
+ std::string (" (from '/machine:" ) + Arg->getValue () + " ' flag)" ;
335
+ }
336
+
337
+ // create an import library
338
+ if (Args.hasArg (OPT_deffile)) {
339
+
340
+ if (OutputPath.empty ()) {
341
+ llvm::errs () << " no output path given\n " ;
342
+ return 1 ;
343
+ }
344
+
345
+ if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
346
+ llvm::errs () << " /def option requires /machine to be specified" << ' \n ' ;
347
+ return 1 ;
348
+ }
349
+
350
+ std::unique_ptr<MemoryBuffer> MB =
351
+ openFile (Args.getLastArg (OPT_deffile)->getValue ());
352
+ if (!MB)
353
+ return 1 ;
354
+
355
+ if (!MB->getBufferSize ()) {
356
+ llvm::errs () << " definition file empty\n " ;
357
+ return 1 ;
358
+ }
359
+
360
+ Expected<COFFModuleDefinition> Def =
361
+ parseCOFFModuleDefinition (*MB, LibMachine, true );
362
+
363
+ if (!Def) {
364
+ llvm::errs () << " error parsing definition\n "
365
+ << errorToErrorCode (Def.takeError ()).message ();
366
+ return 1 ;
367
+ }
368
+
369
+ return writeImportLibrary (Def->OutputFile , OutputPath, Def->Exports ,
370
+ LibMachine,
371
+ /* MinGW=*/ false )
372
+ ? 1
373
+ : 0 ;
374
+ }
375
+
305
376
// If no input files and not told otherwise, silently do nothing to match
306
377
// lib.exe
307
378
if (!Args.hasArgNoClaim (OPT_INPUT) && !Args.hasArg (OPT_llvmlibempty)) {
@@ -324,18 +395,6 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
324
395
325
396
std::vector<StringRef> SearchPaths = getSearchPaths (&Args, Saver);
326
397
327
- COFF::MachineTypes LibMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
328
- std::string LibMachineSource;
329
- if (auto *Arg = Args.getLastArg (OPT_machine)) {
330
- LibMachine = getMachineType (Arg->getValue ());
331
- if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
332
- llvm::errs () << " unknown /machine: arg " << Arg->getValue () << ' \n ' ;
333
- return 1 ;
334
- }
335
- LibMachineSource =
336
- std::string (" (from '/machine:" ) + Arg->getValue () + " ' flag)" ;
337
- }
338
-
339
398
std::vector<std::unique_ptr<MemoryBuffer>> MBs;
340
399
StringSet<> Seen;
341
400
std::vector<NewArchiveMember> Members;
@@ -373,14 +432,13 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
373
432
}
374
433
375
434
// Create an archive file.
376
- std::string OutputPath;
377
- if (auto *Arg = Args.getLastArg (OPT_out)) {
378
- OutputPath = Arg->getValue ();
379
- } else if (!Members.empty ()) {
380
- OutputPath = getDefaultOutputPath (Members[0 ]);
381
- } else {
382
- llvm::errs () << " no output path given, and cannot infer with no inputs\n " ;
383
- return 1 ;
435
+ if (OutputPath.empty ()) {
436
+ if (!Members.empty ()) {
437
+ OutputPath = getDefaultOutputPath (Members[0 ]);
438
+ } else {
439
+ llvm::errs () << " no output path given, and cannot infer with no inputs\n " ;
440
+ return 1 ;
441
+ }
384
442
}
385
443
// llvm-lib uses relative paths for both regular and thin archives, unlike
386
444
// standard GNU ar, which only uses relative paths for thin archives and
0 commit comments