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
getDefaultOutputPath(const NewArchiveMember
&FirstMember
) {
63 SmallString
<128> Val
= StringRef(FirstMember
.Buf
->getBufferIdentifier());
64 sys::path::replace_extension(Val
, ".lib");
65 return std::string(Val
.str());
68 static std::vector
<StringRef
> getSearchPaths(opt::InputArgList
*Args
,
70 std::vector
<StringRef
> Ret
;
71 // Add current directory as first item of the search path.
74 // Add /libpath flags.
75 for (auto *Arg
: Args
->filtered(OPT_libpath
))
76 Ret
.push_back(Arg
->getValue());
79 Optional
<std::string
> EnvOpt
= sys::Process::GetEnv("LIB");
80 if (!EnvOpt
.hasValue())
82 StringRef Env
= Saver
.save(*EnvOpt
);
83 while (!Env
.empty()) {
85 std::tie(Path
, Env
) = Env
.split(';');
91 static std::string
findInputFile(StringRef File
, ArrayRef
<StringRef
> Paths
) {
92 for (StringRef Dir
: Paths
) {
93 SmallString
<128> Path
= Dir
;
94 sys::path::append(Path
, File
);
95 if (sys::fs::exists(Path
))
96 return std::string(Path
);
101 static void fatalOpenError(llvm::Error E
, Twine File
) {
104 handleAllErrors(std::move(E
), [&](const llvm::ErrorInfoBase
&EIB
) {
105 llvm::errs() << "error opening '" << File
<< "': " << EIB
.message() << '\n';
110 static void doList(opt::InputArgList
& Args
) {
111 // lib.exe prints the contents of the first archive file.
112 std::unique_ptr
<MemoryBuffer
> B
;
113 for (auto *Arg
: Args
.filtered(OPT_INPUT
)) {
114 // Create or open the archive object.
115 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> MaybeBuf
= MemoryBuffer::getFile(
116 Arg
->getValue(), /*IsText=*/false, /*RequiresNullTerminator=*/false);
117 fatalOpenError(errorCodeToError(MaybeBuf
.getError()), Arg
->getValue());
119 if (identify_magic(MaybeBuf
.get()->getBuffer()) == file_magic::archive
) {
120 B
= std::move(MaybeBuf
.get());
125 // lib.exe doesn't print an error if no .lib files are passed.
129 Error Err
= Error::success();
130 object::Archive
Archive(B
.get()->getMemBufferRef(), Err
);
131 fatalOpenError(std::move(Err
), B
->getBufferIdentifier());
133 for (auto &C
: Archive
.children(Err
)) {
134 Expected
<StringRef
> NameOrErr
= C
.getName();
135 fatalOpenError(NameOrErr
.takeError(), B
->getBufferIdentifier());
136 StringRef Name
= NameOrErr
.get();
137 llvm::outs() << Name
<< '\n';
139 fatalOpenError(std::move(Err
), B
->getBufferIdentifier());
142 static Expected
<COFF::MachineTypes
> getCOFFFileMachine(MemoryBufferRef MB
) {
144 auto Obj
= object::COFFObjectFile::create(MB
);
146 return Obj
.takeError();
148 uint16_t Machine
= (*Obj
)->getMachine();
149 if (Machine
!= COFF::IMAGE_FILE_MACHINE_I386
&&
150 Machine
!= COFF::IMAGE_FILE_MACHINE_AMD64
&&
151 Machine
!= COFF::IMAGE_FILE_MACHINE_ARMNT
&&
152 Machine
!= COFF::IMAGE_FILE_MACHINE_ARM64
) {
153 return createStringError(inconvertibleErrorCode(),
154 "unknown machine: " + std::to_string(Machine
));
157 return static_cast<COFF::MachineTypes
>(Machine
);
160 static Expected
<COFF::MachineTypes
> getBitcodeFileMachine(MemoryBufferRef MB
) {
161 Expected
<std::string
> TripleStr
= getBitcodeTargetTriple(MB
);
163 return TripleStr
.takeError();
165 switch (Triple(*TripleStr
).getArch()) {
167 return COFF::IMAGE_FILE_MACHINE_I386
;
169 return COFF::IMAGE_FILE_MACHINE_AMD64
;
171 return COFF::IMAGE_FILE_MACHINE_ARMNT
;
172 case Triple::aarch64
:
173 return COFF::IMAGE_FILE_MACHINE_ARM64
;
175 return createStringError(inconvertibleErrorCode(),
176 "unknown arch in target triple: " + *TripleStr
);
180 static void appendFile(std::vector
<NewArchiveMember
> &Members
,
181 COFF::MachineTypes
&LibMachine
,
182 std::string
&LibMachineSource
, MemoryBufferRef MB
) {
183 file_magic Magic
= identify_magic(MB
.getBuffer());
185 if (Magic
!= file_magic::coff_object
&& Magic
!= file_magic::bitcode
&&
186 Magic
!= file_magic::archive
&& Magic
!= file_magic::windows_resource
&&
187 Magic
!= file_magic::coff_import_library
) {
188 llvm::errs() << MB
.getBufferIdentifier()
189 << ": not a COFF object, bitcode, archive, import library or "
194 // If a user attempts to add an archive to another archive, llvm-lib doesn't
195 // handle the first archive file as a single file. Instead, it extracts all
196 // members from the archive and add them to the second archive. This behavior
197 // is for compatibility with Microsoft's lib command.
198 if (Magic
== file_magic::archive
) {
199 Error Err
= Error::success();
200 object::Archive
Archive(MB
, Err
);
201 fatalOpenError(std::move(Err
), MB
.getBufferIdentifier());
203 for (auto &C
: Archive
.children(Err
)) {
204 Expected
<MemoryBufferRef
> ChildMB
= C
.getMemoryBufferRef();
206 handleAllErrors(ChildMB
.takeError(), [&](const ErrorInfoBase
&EIB
) {
207 llvm::errs() << MB
.getBufferIdentifier() << ": " << EIB
.message()
213 appendFile(Members
, LibMachine
, LibMachineSource
, *ChildMB
);
216 fatalOpenError(std::move(Err
), MB
.getBufferIdentifier());
220 // Check that all input files have the same machine type.
221 // Mixing normal objects and LTO bitcode files is fine as long as they
222 // have the same machine type.
223 // Doing this here duplicates the header parsing work that writeArchive()
224 // below does, but it's not a lot of work and it's a bit awkward to do
225 // in writeArchive() which needs to support many tools, can't assume the
226 // input is COFF, and doesn't have a good way to report errors.
227 if (Magic
== file_magic::coff_object
|| Magic
== file_magic::bitcode
) {
228 Expected
<COFF::MachineTypes
> MaybeFileMachine
=
229 (Magic
== file_magic::coff_object
) ? getCOFFFileMachine(MB
)
230 : getBitcodeFileMachine(MB
);
231 if (!MaybeFileMachine
) {
232 handleAllErrors(MaybeFileMachine
.takeError(), [&](const ErrorInfoBase
&EIB
) {
233 llvm::errs() << MB
.getBufferIdentifier() << ": " << EIB
.message()
238 COFF::MachineTypes FileMachine
= *MaybeFileMachine
;
240 // FIXME: Once lld-link rejects multiple resource .obj files:
241 // Call convertResToCOFF() on .res files and add the resulting
242 // COFF file to the .lib output instead of adding the .res file, and remove
243 // this check. See PR42180.
244 if (FileMachine
!= COFF::IMAGE_FILE_MACHINE_UNKNOWN
) {
245 if (LibMachine
== COFF::IMAGE_FILE_MACHINE_UNKNOWN
) {
246 LibMachine
= FileMachine
;
248 (" (inferred from earlier file '" + MB
.getBufferIdentifier() + "')")
250 } else if (LibMachine
!= FileMachine
) {
251 llvm::errs() << MB
.getBufferIdentifier() << ": file machine type "
252 << machineToStr(FileMachine
)
253 << " conflicts with library machine type "
254 << machineToStr(LibMachine
) << LibMachineSource
<< '\n';
260 Members
.emplace_back(MB
);
263 int llvm::libDriverMain(ArrayRef
<const char *> ArgsArr
) {
264 BumpPtrAllocator Alloc
;
265 StringSaver
Saver(Alloc
);
267 // Parse command line arguments.
268 SmallVector
<const char *, 20> NewArgs(ArgsArr
.begin(), ArgsArr
.end());
269 cl::ExpandResponseFiles(Saver
, cl::TokenizeWindowsCommandLine
, NewArgs
);
273 unsigned MissingIndex
;
274 unsigned MissingCount
;
275 opt::InputArgList Args
=
276 Table
.ParseArgs(ArgsArr
.slice(1), MissingIndex
, MissingCount
);
278 llvm::errs() << "missing arg value for \""
279 << Args
.getArgString(MissingIndex
) << "\", expected "
281 << (MissingCount
== 1 ? " argument.\n" : " arguments.\n");
284 for (auto *Arg
: Args
.filtered(OPT_UNKNOWN
))
285 llvm::errs() << "ignoring unknown argument: " << Arg
->getAsString(Args
)
289 if (Args
.hasArg(OPT_help
)) {
290 Table
.printHelp(outs(), "llvm-lib [options] file...", "LLVM Lib");
294 // If no input files and not told otherwise, silently do nothing to match
296 if (!Args
.hasArgNoClaim(OPT_INPUT
) && !Args
.hasArg(OPT_llvmlibempty
))
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
= MemoryBuffer::getFile(
343 Path
, /*IsText=*/false, /*RequiresNullTerminator=*/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
;
356 if (auto *Arg
= Args
.getLastArg(OPT_out
)) {
357 OutputPath
= Arg
->getValue();
358 } else if (!Members
.empty()) {
359 OutputPath
= getDefaultOutputPath(Members
[0]);
361 llvm::errs() << "no output path given, and cannot infer with no inputs\n";
364 // llvm-lib uses relative paths for both regular and thin archives, unlike
365 // standard GNU ar, which only uses relative paths for thin archives and
366 // basenames for regular archives.
367 for (NewArchiveMember
&Member
: Members
) {
368 if (sys::path::is_relative(Member
.MemberName
)) {
369 Expected
<std::string
> PathOrErr
=
370 computeArchiveRelativePath(OutputPath
, Member
.MemberName
);
372 Member
.MemberName
= Saver
.save(*PathOrErr
);
377 writeArchive(OutputPath
, Members
,
378 /*WriteSymtab=*/true, object::Archive::K_GNU
,
379 /*Deterministic*/ true, Args
.hasArg(OPT_llvmlibthin
))) {
380 handleAllErrors(std::move(E
), [&](const ErrorInfoBase
&EI
) {
381 llvm::errs() << OutputPath
<< ": " << EI
.message() << "\n";