1 //===- LibDriver.cpp - lib.exe-compatible driver --------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Defines an interface to a lib.exe-compatible driver that also understands
10 // bitcode files. Used by llvm-lib and lld-link /lib.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/StringSet.h"
17 #include "llvm/BinaryFormat/COFF.h"
18 #include "llvm/BinaryFormat/Magic.h"
19 #include "llvm/Bitcode/BitcodeReader.h"
20 #include "llvm/Object/ArchiveWriter.h"
21 #include "llvm/Object/COFF.h"
22 #include "llvm/Object/WindowsMachineFlag.h"
23 #include "llvm/Option/Arg.h"
24 #include "llvm/Option/ArgList.h"
25 #include "llvm/Option/Option.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Support/Path.h"
28 #include "llvm/Support/Process.h"
29 #include "llvm/Support/StringSaver.h"
30 #include "llvm/Support/raw_ostream.h"
38 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
39 #include "Options.inc"
43 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
44 #include "Options.inc"
47 static const opt::OptTable::Info InfoTable
[] = {
48 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
49 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \
50 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
51 #include "Options.inc"
55 class LibOptTable
: public opt::OptTable
{
57 LibOptTable() : OptTable(InfoTable
, true) {}
62 static std::string
getOutputPath(opt::InputArgList
*Args
,
63 const NewArchiveMember
&FirstMember
) {
64 if (auto *Arg
= Args
->getLastArg(OPT_out
))
65 return Arg
->getValue();
66 SmallString
<128> Val
= StringRef(FirstMember
.Buf
->getBufferIdentifier());
67 sys::path::replace_extension(Val
, ".lib");
71 static std::vector
<StringRef
> getSearchPaths(opt::InputArgList
*Args
,
73 std::vector
<StringRef
> Ret
;
74 // Add current directory as first item of the search path.
77 // Add /libpath flags.
78 for (auto *Arg
: Args
->filtered(OPT_libpath
))
79 Ret
.push_back(Arg
->getValue());
82 Optional
<std::string
> EnvOpt
= sys::Process::GetEnv("LIB");
83 if (!EnvOpt
.hasValue())
85 StringRef Env
= Saver
.save(*EnvOpt
);
86 while (!Env
.empty()) {
88 std::tie(Path
, Env
) = Env
.split(';');
94 static std::string
findInputFile(StringRef File
, ArrayRef
<StringRef
> Paths
) {
95 for (StringRef Dir
: Paths
) {
96 SmallString
<128> Path
= Dir
;
97 sys::path::append(Path
, File
);
98 if (sys::fs::exists(Path
))
99 return Path
.str().str();
104 static void fatalOpenError(llvm::Error E
, Twine File
) {
107 handleAllErrors(std::move(E
), [&](const llvm::ErrorInfoBase
&EIB
) {
108 llvm::errs() << "error opening '" << File
<< "': " << EIB
.message() << '\n';
113 static void doList(opt::InputArgList
& Args
) {
114 // lib.exe prints the contents of the first archive file.
115 std::unique_ptr
<MemoryBuffer
> B
;
116 for (auto *Arg
: Args
.filtered(OPT_INPUT
)) {
117 // Create or open the archive object.
118 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> MaybeBuf
=
119 MemoryBuffer::getFile(Arg
->getValue(), -1, false);
120 fatalOpenError(errorCodeToError(MaybeBuf
.getError()), Arg
->getValue());
122 if (identify_magic(MaybeBuf
.get()->getBuffer()) == file_magic::archive
) {
123 B
= std::move(MaybeBuf
.get());
128 // lib.exe doesn't print an error if no .lib files are passed.
132 Error Err
= Error::success();
133 object::Archive
Archive(B
.get()->getMemBufferRef(), Err
);
134 fatalOpenError(std::move(Err
), B
->getBufferIdentifier());
136 for (auto &C
: Archive
.children(Err
)) {
137 Expected
<StringRef
> NameOrErr
= C
.getName();
138 fatalOpenError(NameOrErr
.takeError(), B
->getBufferIdentifier());
139 StringRef Name
= NameOrErr
.get();
140 llvm::outs() << Name
<< '\n';
142 fatalOpenError(std::move(Err
), B
->getBufferIdentifier());
145 static COFF::MachineTypes
getCOFFFileMachine(MemoryBufferRef MB
) {
147 object::COFFObjectFile
Obj(MB
, EC
);
149 llvm::errs() << MB
.getBufferIdentifier()
150 << ": failed to open: " << EC
.message() << '\n';
154 uint16_t Machine
= Obj
.getMachine();
155 if (Machine
!= COFF::IMAGE_FILE_MACHINE_I386
&&
156 Machine
!= COFF::IMAGE_FILE_MACHINE_AMD64
&&
157 Machine
!= COFF::IMAGE_FILE_MACHINE_ARMNT
&&
158 Machine
!= COFF::IMAGE_FILE_MACHINE_ARM64
) {
159 llvm::errs() << MB
.getBufferIdentifier() << ": unknown machine: " << Machine
164 return static_cast<COFF::MachineTypes
>(Machine
);
167 static COFF::MachineTypes
getBitcodeFileMachine(MemoryBufferRef MB
) {
168 Expected
<std::string
> TripleStr
= getBitcodeTargetTriple(MB
);
170 llvm::errs() << MB
.getBufferIdentifier()
171 << ": failed to get target triple from bitcode\n";
175 switch (Triple(*TripleStr
).getArch()) {
177 return COFF::IMAGE_FILE_MACHINE_I386
;
179 return COFF::IMAGE_FILE_MACHINE_AMD64
;
181 return COFF::IMAGE_FILE_MACHINE_ARMNT
;
182 case Triple::aarch64
:
183 return COFF::IMAGE_FILE_MACHINE_ARM64
;
185 llvm::errs() << MB
.getBufferIdentifier()
186 << ": unknown arch in target triple " << *TripleStr
<< '\n';
191 static void appendFile(std::vector
<NewArchiveMember
> &Members
,
192 COFF::MachineTypes
&LibMachine
,
193 std::string
&LibMachineSource
, MemoryBufferRef MB
) {
194 file_magic Magic
= identify_magic(MB
.getBuffer());
196 if (Magic
!= file_magic::coff_object
&& Magic
!= file_magic::bitcode
&&
197 Magic
!= file_magic::archive
&& Magic
!= file_magic::windows_resource
) {
198 llvm::errs() << MB
.getBufferIdentifier()
199 << ": not a COFF object, bitcode, archive or resource file\n";
203 // If a user attempts to add an archive to another archive, llvm-lib doesn't
204 // handle the first archive file as a single file. Instead, it extracts all
205 // members from the archive and add them to the second archive. This beahvior
206 // is for compatibility with Microsoft's lib command.
207 if (Magic
== file_magic::archive
) {
208 Error Err
= Error::success();
209 object::Archive
Archive(MB
, Err
);
210 fatalOpenError(std::move(Err
), MB
.getBufferIdentifier());
212 for (auto &C
: Archive
.children(Err
)) {
213 Expected
<MemoryBufferRef
> ChildMB
= C
.getMemoryBufferRef();
215 handleAllErrors(ChildMB
.takeError(), [&](const ErrorInfoBase
&EIB
) {
216 llvm::errs() << MB
.getBufferIdentifier() << ": " << EIB
.message()
222 appendFile(Members
, LibMachine
, LibMachineSource
, *ChildMB
);
225 fatalOpenError(std::move(Err
), MB
.getBufferIdentifier());
229 // Check that all input files have the same machine type.
230 // Mixing normal objects and LTO bitcode files is fine as long as they
231 // have the same machine type.
232 // Doing this here duplicates the header parsing work that writeArchive()
233 // below does, but it's not a lot of work and it's a bit awkward to do
234 // in writeArchive() which needs to support many tools, can't assume the
235 // input is COFF, and doesn't have a good way to report errors.
236 if (Magic
== file_magic::coff_object
|| Magic
== file_magic::bitcode
) {
237 COFF::MachineTypes FileMachine
= (Magic
== file_magic::coff_object
)
238 ? getCOFFFileMachine(MB
)
239 : getBitcodeFileMachine(MB
);
241 // FIXME: Once lld-link rejects multiple resource .obj files:
242 // Call convertResToCOFF() on .res files and add the resulting
243 // COFF file to the .lib output instead of adding the .res file, and remove
244 // this check. See PR42180.
245 if (FileMachine
!= COFF::IMAGE_FILE_MACHINE_UNKNOWN
) {
246 if (LibMachine
== COFF::IMAGE_FILE_MACHINE_UNKNOWN
) {
247 LibMachine
= FileMachine
;
249 (" (inferred from earlier file '" + MB
.getBufferIdentifier() + "')")
251 } else if (LibMachine
!= FileMachine
) {
252 llvm::errs() << MB
.getBufferIdentifier() << ": file machine type "
253 << machineToStr(FileMachine
)
254 << " conflicts with library machine type "
255 << machineToStr(LibMachine
) << LibMachineSource
<< '\n';
261 Members
.emplace_back(MB
);
264 int llvm::libDriverMain(ArrayRef
<const char *> ArgsArr
) {
265 BumpPtrAllocator Alloc
;
266 StringSaver
Saver(Alloc
);
268 // Parse command line arguments.
269 SmallVector
<const char *, 20> NewArgs(ArgsArr
.begin(), ArgsArr
.end());
270 cl::ExpandResponseFiles(Saver
, cl::TokenizeWindowsCommandLine
, NewArgs
);
274 unsigned MissingIndex
;
275 unsigned MissingCount
;
276 opt::InputArgList Args
=
277 Table
.ParseArgs(ArgsArr
.slice(1), MissingIndex
, MissingCount
);
279 llvm::errs() << "missing arg value for \""
280 << Args
.getArgString(MissingIndex
) << "\", expected "
282 << (MissingCount
== 1 ? " argument.\n" : " arguments.\n");
285 for (auto *Arg
: Args
.filtered(OPT_UNKNOWN
))
286 llvm::errs() << "ignoring unknown argument: " << Arg
->getAsString(Args
)
290 if (Args
.hasArg(OPT_help
)) {
291 Table
.PrintHelp(outs(), "llvm-lib [options] file...", "LLVM Lib");
295 // If no input files, silently do nothing to match lib.exe.
296 if (!Args
.hasArgNoClaim(OPT_INPUT
))
299 if (Args
.hasArg(OPT_lst
)) {
304 std::vector
<StringRef
> SearchPaths
= getSearchPaths(&Args
, Saver
);
306 COFF::MachineTypes LibMachine
= COFF::IMAGE_FILE_MACHINE_UNKNOWN
;
307 std::string LibMachineSource
;
308 if (auto *Arg
= Args
.getLastArg(OPT_machine
)) {
309 LibMachine
= getMachineType(Arg
->getValue());
310 if (LibMachine
== COFF::IMAGE_FILE_MACHINE_UNKNOWN
) {
311 llvm::errs() << "unknown /machine: arg " << Arg
->getValue() << '\n';
315 std::string(" (from '/machine:") + Arg
->getValue() + "' flag)";
318 std::vector
<std::unique_ptr
<MemoryBuffer
>> MBs
;
320 std::vector
<NewArchiveMember
> Members
;
322 // Create a NewArchiveMember for each input file.
323 for (auto *Arg
: Args
.filtered(OPT_INPUT
)) {
325 std::string Path
= findInputFile(Arg
->getValue(), SearchPaths
);
327 llvm::errs() << Arg
->getValue() << ": no such file or directory\n";
331 // Input files are uniquified by pathname. If you specify the exact same
332 // path more than once, all but the first one are ignored.
334 // Note that there's a loophole in the rule; you can prepend `.\` or
335 // something like that to a path to make it look different, and they are
336 // handled as if they were different files. This behavior is compatible with
337 // Microsoft lib.exe.
338 if (!Seen
.insert(Path
).second
)
342 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> MOrErr
=
343 MemoryBuffer::getFile(Path
, -1, false);
344 fatalOpenError(errorCodeToError(MOrErr
.getError()), Path
);
345 MemoryBufferRef MBRef
= (*MOrErr
)->getMemBufferRef();
348 appendFile(Members
, LibMachine
, LibMachineSource
, MBRef
);
350 // Take the ownership of the file buffer to keep the file open.
351 MBs
.push_back(std::move(*MOrErr
));
354 // Create an archive file.
355 std::string OutputPath
= getOutputPath(&Args
, Members
[0]);
356 // llvm-lib uses relative paths for both regular and thin archives, unlike
357 // standard GNU ar, which only uses relative paths for thin archives and
358 // basenames for regular archives.
359 for (NewArchiveMember
&Member
: Members
) {
360 if (sys::path::is_relative(Member
.MemberName
)) {
361 Expected
<std::string
> PathOrErr
=
362 computeArchiveRelativePath(OutputPath
, Member
.MemberName
);
364 Member
.MemberName
= Saver
.save(*PathOrErr
);
369 writeArchive(OutputPath
, Members
,
370 /*WriteSymtab=*/true, object::Archive::K_GNU
,
371 /*Deterministic*/ true, Args
.hasArg(OPT_llvmlibthin
))) {
372 handleAllErrors(std::move(E
), [&](const ErrorInfoBase
&EI
) {
373 llvm::errs() << OutputPath
<< ": " << EI
.message() << "\n";