1 //===-- llvm-libtool-darwin.cpp - a tool for creating libraries -----------===//
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 // A utility for creating static and dynamic libraries for Darwin.
11 //===----------------------------------------------------------------------===//
13 #include "DependencyInfo.h"
14 #include "llvm/ADT/MapVector.h"
15 #include "llvm/BinaryFormat/Magic.h"
16 #include "llvm/IR/LLVMContext.h"
17 #include "llvm/Object/ArchiveWriter.h"
18 #include "llvm/Object/IRObjectFile.h"
19 #include "llvm/Object/MachO.h"
20 #include "llvm/Object/MachOUniversal.h"
21 #include "llvm/Object/MachOUniversalWriter.h"
22 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Option/ArgList.h"
24 #include "llvm/Option/Option.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/InitLLVM.h"
27 #include "llvm/Support/LLVMDriver.h"
28 #include "llvm/Support/LineIterator.h"
29 #include "llvm/Support/TargetSelect.h"
30 #include "llvm/Support/VirtualFileSystem.h"
31 #include "llvm/Support/WithColor.h"
32 #include "llvm/Support/YAMLTraits.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include "llvm/TextAPI/Architecture.h"
37 #include <type_traits>
40 using namespace llvm::object
;
41 using namespace llvm::opt
;
43 // Command-line option boilerplate.
46 OPT_INVALID
= 0, // This is not an option ID.
47 #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
52 #define PREFIX(NAME, VALUE) \
53 static constexpr StringLiteral NAME##_init[] = VALUE; \
54 static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
55 std::size(NAME##_init) - 1);
59 static constexpr opt::OptTable::Info InfoTable
[] = {
60 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
65 class LibtoolDarwinOptTable
: public opt::GenericOptTable
{
67 LibtoolDarwinOptTable() : GenericOptTable(InfoTable
) {}
69 } // end anonymous namespace
71 class NewArchiveMemberList
;
72 typedef std::map
<uint64_t, NewArchiveMemberList
> MembersPerArchitectureMap
;
74 static std::string OutputFile
;
75 static std::vector
<std::string
> InputFiles
;
76 static std::optional
<std::string
> ArchType
;
78 enum class Operation
{ None
, Static
};
79 static Operation LibraryOperation
= Operation::None
;
81 static bool DeterministicOption
;
82 static bool NonDeterministicOption
;
83 static std::string FileList
;
84 static std::vector
<std::string
> Libraries
;
85 static std::vector
<std::string
> LibrarySearchDirs
;
86 static std::string DependencyInfoPath
;
87 static bool VersionOption
;
88 static bool NoWarningForNoSymbols
;
89 static bool WarningsAsErrors
;
90 static std::string IgnoredSyslibRoot
;
92 static const std::array
<std::string
, 3> StandardSearchDirs
{
98 std::unique_ptr
<DependencyInfo
> GlobalDependencyInfo
;
101 bool Deterministic
= true; // Updated by 'D' and 'U' modifiers.
102 uint32_t ArchCPUType
;
103 uint32_t ArchCPUSubtype
;
106 static Expected
<std::string
> searchForFile(const Twine
&FileName
) {
109 ArrayRef
<std::string
> SearchDirs
) -> std::optional
<std::string
> {
110 for (StringRef Dir
: SearchDirs
) {
111 SmallString
<128> Path
;
112 sys::path::append(Path
, Dir
, FileName
);
114 if (sys::fs::exists(Path
))
115 return std::string(Path
);
117 GlobalDependencyInfo
->addMissingInput(Path
);
122 std::optional
<std::string
> Found
= FindLib(LibrarySearchDirs
);
124 Found
= FindLib(StandardSearchDirs
);
128 return createStringError(std::errc::invalid_argument
,
129 "cannot locate file '%s'", FileName
.str().c_str());
132 static Error
processCommandLineLibraries() {
133 for (StringRef BaseName
: Libraries
) {
134 Expected
<std::string
> FullPath
= searchForFile(
135 BaseName
.endswith(".o") ? BaseName
.str() : "lib" + BaseName
+ ".a");
137 return FullPath
.takeError();
138 InputFiles
.push_back(FullPath
.get());
141 return Error::success();
144 static Error
processFileList() {
145 StringRef FileName
, DirName
;
146 std::tie(FileName
, DirName
) = StringRef(FileList
).rsplit(",");
148 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> FileOrErr
=
149 MemoryBuffer::getFileOrSTDIN(FileName
, /*IsText=*/false,
150 /*RequiresNullTerminator=*/false);
151 if (std::error_code EC
= FileOrErr
.getError())
152 return createFileError(FileName
, errorCodeToError(EC
));
153 const MemoryBuffer
&Ref
= *FileOrErr
.get();
155 line_iterator
I(Ref
, /*SkipBlanks=*/false);
157 return createStringError(std::errc::invalid_argument
,
158 "file list file: '%s' is empty",
159 FileName
.str().c_str());
160 for (; !I
.is_at_eof(); ++I
) {
163 return createStringError(std::errc::invalid_argument
,
164 "file list file: '%s': filename cannot be empty",
165 FileName
.str().c_str());
167 SmallString
<128> Path
;
168 if (!DirName
.empty())
169 sys::path::append(Path
, DirName
, Line
);
171 sys::path::append(Path
, Line
);
172 InputFiles
.push_back(static_cast<std::string
>(Path
));
174 return Error::success();
177 static Error
validateArchitectureName(StringRef ArchitectureName
) {
178 if (!MachOObjectFile::isValidArch(ArchitectureName
)) {
180 raw_string_ostream
OS(Buf
);
181 for (StringRef Arch
: MachOObjectFile::getValidArchs())
184 return createStringError(
185 std::errc::invalid_argument
,
186 "invalid architecture '%s': valid architecture names are %s",
187 ArchitectureName
.str().c_str(), OS
.str().c_str());
189 return Error::success();
192 static uint64_t getCPUID(uint32_t CPUType
, uint32_t CPUSubtype
) {
194 case MachO::CPU_TYPE_ARM
:
195 case MachO::CPU_TYPE_ARM64
:
196 case MachO::CPU_TYPE_ARM64_32
:
197 case MachO::CPU_TYPE_X86_64
:
198 // We consider CPUSubtype only for the above 4 CPUTypes to match cctools'
200 return static_cast<uint64_t>(CPUType
) << 32 | CPUSubtype
;
206 // MembersData is an organized collection of members.
208 // MembersPerArchitectureMap is a mapping from CPU architecture to a list of
210 MembersPerArchitectureMap MembersPerArchitecture
;
211 std::vector
<std::unique_ptr
<MemoryBuffer
>> FileBuffers
;
214 // NewArchiveMemberList instances serve as collections of archive members and
215 // information about those members.
216 class NewArchiveMemberList
{
217 std::vector
<NewArchiveMember
> Members
;
218 // This vector contains the file that each NewArchiveMember from Members came
219 // from. Therefore, it has the same size as Members.
220 std::vector
<StringRef
> Files
;
223 // Add a NewArchiveMember and the file it came from to the list.
224 void push_back(NewArchiveMember
&&Member
, StringRef File
) {
225 Members
.push_back(std::move(Member
));
226 Files
.push_back(File
);
229 ArrayRef
<NewArchiveMember
> getMembers() const { return Members
; }
231 ArrayRef
<StringRef
> getFiles() const { return Files
; }
234 std::is_same
<decltype(MembersData::MembersPerArchitecture
)::mapped_type
,
235 NewArchiveMemberList
>(),
236 "This test makes sure NewArchiveMemberList is used by MembersData since "
237 "the following asserts test invariants required for MembersData.");
239 !std::is_copy_constructible_v
<
240 decltype(NewArchiveMemberList::Members
)::value_type
>,
241 "MembersData::MembersPerArchitecture has a dependency on "
242 "MembersData::FileBuffers so it should not be able to "
243 "be copied on its own without FileBuffers. Unfortunately, "
244 "is_copy_constructible does not detect whether the container (ie vector) "
245 "of a non-copyable type is itself non-copyable so we have to test the "
246 "actual type of the stored data (ie, value_type).");
248 !std::is_copy_assignable_v
<
249 decltype(NewArchiveMemberList::Members
)::value_type
>,
250 "MembersData::MembersPerArchitecture has a dependency on "
251 "MembersData::FileBuffers so it should not be able to "
252 "be copied on its own without FileBuffers. Unfortunately, "
253 "is_copy_constructible does not detect whether the container (ie vector) "
254 "of a non-copyable type is itself non-copyable so we have to test the "
255 "actual type of the stored data (ie, value_type).");
258 // MembersBuilder collects and organizes all members from the files provided by
260 class MembersBuilder
{
262 MembersBuilder(LLVMContext
&LLVMCtx
, const Config
&C
)
263 : LLVMCtx(LLVMCtx
), C(C
) {}
265 Expected
<MembersData
> build() {
266 for (StringRef FileName
: InputFiles
)
267 if (Error E
= AddMember(*this, FileName
)())
270 std::string Arch
= ArchType
.value_or("");
272 uint64_t ArchCPUID
= getCPUID(C
.ArchCPUType
, C
.ArchCPUSubtype
);
273 if (Data
.MembersPerArchitecture
.find(ArchCPUID
) ==
274 Data
.MembersPerArchitecture
.end())
275 return createStringError(std::errc::invalid_argument
,
276 "no library created (no object files in input "
277 "files matching -arch_only %s)",
280 return std::move(Data
);
285 MembersBuilder
&Builder
;
289 AddMember(MembersBuilder
&Builder
, StringRef FileName
)
290 : Builder(Builder
), FileName(FileName
) {}
293 Expected
<NewArchiveMember
> NewMemberOrErr
=
294 NewArchiveMember::getFile(FileName
, Builder
.C
.Deterministic
);
296 return createFileError(FileName
, NewMemberOrErr
.takeError());
297 auto &NewMember
= *NewMemberOrErr
;
299 // For regular archives, use the basename of the object path for the
301 NewMember
.MemberName
= sys::path::filename(NewMember
.MemberName
);
302 file_magic Magic
= identify_magic(NewMember
.Buf
->getBuffer());
305 if (Magic
== file_magic::archive
)
306 return addArchiveMembers(std::move(NewMember
));
308 // Flatten universal files.
309 if (Magic
== file_magic::macho_universal_binary
)
310 return addUniversalMembers(std::move(NewMember
));
313 if (Magic
== file_magic::bitcode
)
314 return verifyAndAddIRObject(std::move(NewMember
));
316 return verifyAndAddMachOObject(std::move(NewMember
));
320 // Check that a file's architecture [FileCPUType, FileCPUSubtype]
321 // matches the architecture specified under -arch_only flag.
322 bool acceptFileArch(uint32_t FileCPUType
, uint32_t FileCPUSubtype
) {
323 if (Builder
.C
.ArchCPUType
!= FileCPUType
)
326 switch (Builder
.C
.ArchCPUType
) {
327 case MachO::CPU_TYPE_ARM
:
328 case MachO::CPU_TYPE_ARM64_32
:
329 case MachO::CPU_TYPE_X86_64
:
330 return Builder
.C
.ArchCPUSubtype
== FileCPUSubtype
;
332 case MachO::CPU_TYPE_ARM64
:
333 if (Builder
.C
.ArchCPUSubtype
== MachO::CPU_SUBTYPE_ARM64_ALL
)
334 return FileCPUSubtype
== MachO::CPU_SUBTYPE_ARM64_ALL
||
335 FileCPUSubtype
== MachO::CPU_SUBTYPE_ARM64_V8
;
337 return Builder
.C
.ArchCPUSubtype
== FileCPUSubtype
;
344 Error
verifyAndAddMachOObject(NewArchiveMember Member
) {
345 auto MBRef
= Member
.Buf
->getMemBufferRef();
346 Expected
<std::unique_ptr
<object::ObjectFile
>> ObjOrErr
=
347 object::ObjectFile::createObjectFile(MBRef
);
349 // Throw error if not a valid object file.
351 return createFileError(Member
.MemberName
, ObjOrErr
.takeError());
353 // Throw error if not in Mach-O format.
354 if (!isa
<object::MachOObjectFile
>(**ObjOrErr
))
355 return createStringError(std::errc::invalid_argument
,
356 "'%s': format not supported",
357 Member
.MemberName
.data());
359 auto *O
= cast
<MachOObjectFile
>(ObjOrErr
->get());
360 uint32_t FileCPUType
, FileCPUSubtype
;
361 std::tie(FileCPUType
, FileCPUSubtype
) = MachO::getCPUTypeFromArchitecture(
362 MachO::getArchitectureFromName(O
->getArchTriple().getArchName()));
364 // If -arch_only is specified then skip this file if it doesn't match
365 // the architecture specified.
366 if (ArchType
&& !acceptFileArch(FileCPUType
, FileCPUSubtype
)) {
367 return Error::success();
370 if (!NoWarningForNoSymbols
&& O
->symbols().empty()) {
371 Error E
= createFileError(
373 createStringError(std::errc::invalid_argument
,
374 "has no symbols for architecture %s",
375 O
->getArchTriple().getArchName().str().c_str()));
377 if (WarningsAsErrors
)
379 WithColor::defaultWarningHandler(std::move(E
));
382 uint64_t FileCPUID
= getCPUID(FileCPUType
, FileCPUSubtype
);
383 Builder
.Data
.MembersPerArchitecture
[FileCPUID
].push_back(
384 std::move(Member
), FileName
);
385 return Error::success();
388 Error
verifyAndAddIRObject(NewArchiveMember Member
) {
389 auto MBRef
= Member
.Buf
->getMemBufferRef();
390 Expected
<std::unique_ptr
<object::IRObjectFile
>> IROrErr
=
391 object::IRObjectFile::create(MBRef
, Builder
.LLVMCtx
);
393 // Throw error if not a valid IR object file.
395 return createFileError(Member
.MemberName
, IROrErr
.takeError());
397 Triple TT
= Triple(IROrErr
->get()->getTargetTriple());
399 Expected
<uint32_t> FileCPUTypeOrErr
= MachO::getCPUType(TT
);
400 if (!FileCPUTypeOrErr
)
401 return FileCPUTypeOrErr
.takeError();
403 Expected
<uint32_t> FileCPUSubTypeOrErr
= MachO::getCPUSubType(TT
);
404 if (!FileCPUSubTypeOrErr
)
405 return FileCPUSubTypeOrErr
.takeError();
407 // If -arch_only is specified then skip this file if it doesn't match
408 // the architecture specified.
410 !acceptFileArch(*FileCPUTypeOrErr
, *FileCPUSubTypeOrErr
)) {
411 return Error::success();
414 uint64_t FileCPUID
= getCPUID(*FileCPUTypeOrErr
, *FileCPUSubTypeOrErr
);
415 Builder
.Data
.MembersPerArchitecture
[FileCPUID
].push_back(
416 std::move(Member
), FileName
);
417 return Error::success();
420 Error
addChildMember(const object::Archive::Child
&M
) {
421 Expected
<NewArchiveMember
> NewMemberOrErr
=
422 NewArchiveMember::getOldMember(M
, Builder
.C
.Deterministic
);
424 return NewMemberOrErr
.takeError();
425 auto &NewMember
= *NewMemberOrErr
;
427 file_magic Magic
= identify_magic(NewMember
.Buf
->getBuffer());
429 if (Magic
== file_magic::bitcode
)
430 return verifyAndAddIRObject(std::move(NewMember
));
432 return verifyAndAddMachOObject(std::move(NewMember
));
435 Error
processArchive(object::Archive
&Lib
) {
436 Error Err
= Error::success();
437 for (const object::Archive::Child
&Child
: Lib
.children(Err
))
438 if (Error E
= addChildMember(Child
))
439 return createFileError(FileName
, std::move(E
));
441 return createFileError(FileName
, std::move(Err
));
443 return Error::success();
446 Error
addArchiveMembers(NewArchiveMember NewMember
) {
447 Expected
<std::unique_ptr
<Archive
>> LibOrErr
=
448 object::Archive::create(NewMember
.Buf
->getMemBufferRef());
450 return createFileError(FileName
, LibOrErr
.takeError());
452 if (Error E
= processArchive(**LibOrErr
))
455 // Update vector FileBuffers with the MemoryBuffers to transfer
457 Builder
.Data
.FileBuffers
.push_back(std::move(NewMember
.Buf
));
458 return Error::success();
461 Error
addUniversalMembers(NewArchiveMember NewMember
) {
462 Expected
<std::unique_ptr
<MachOUniversalBinary
>> BinaryOrErr
=
463 MachOUniversalBinary::create(NewMember
.Buf
->getMemBufferRef());
465 return createFileError(FileName
, BinaryOrErr
.takeError());
467 auto *UO
= BinaryOrErr
->get();
468 for (const MachOUniversalBinary::ObjectForArch
&O
: UO
->objects()) {
470 Expected
<std::unique_ptr
<MachOObjectFile
>> MachOObjOrErr
=
473 NewArchiveMember NewMember
=
474 NewArchiveMember(MachOObjOrErr
->get()->getMemoryBufferRef());
475 NewMember
.MemberName
= sys::path::filename(NewMember
.MemberName
);
477 if (Error E
= verifyAndAddMachOObject(std::move(NewMember
)))
482 Expected
<std::unique_ptr
<IRObjectFile
>> IRObjectOrError
=
483 O
.getAsIRObject(Builder
.LLVMCtx
);
484 if (IRObjectOrError
) {
485 // A universal file member can be a MachOObjectFile, an IRObject or an
486 // Archive. In case we can successfully cast the member as an
487 // IRObject, it is safe to throw away the error generated due to
488 // casting the object as a MachOObjectFile.
489 consumeError(MachOObjOrErr
.takeError());
491 NewArchiveMember NewMember
=
492 NewArchiveMember(IRObjectOrError
->get()->getMemoryBufferRef());
493 NewMember
.MemberName
= sys::path::filename(NewMember
.MemberName
);
495 if (Error E
= verifyAndAddIRObject(std::move(NewMember
)))
500 Expected
<std::unique_ptr
<Archive
>> ArchiveOrError
= O
.getAsArchive();
501 if (ArchiveOrError
) {
502 // A universal file member can be a MachOObjectFile, an IRObject or an
503 // Archive. In case we can successfully cast the member as an Archive,
504 // it is safe to throw away the error generated due to casting the
505 // object as a MachOObjectFile.
506 consumeError(MachOObjOrErr
.takeError());
507 consumeError(IRObjectOrError
.takeError());
509 if (Error E
= processArchive(**ArchiveOrError
))
514 Error CombinedError
= joinErrors(
515 ArchiveOrError
.takeError(),
516 joinErrors(IRObjectOrError
.takeError(), MachOObjOrErr
.takeError()));
517 return createFileError(FileName
, std::move(CombinedError
));
520 // Update vector FileBuffers with the MemoryBuffers to transfer
522 Builder
.Data
.FileBuffers
.push_back(std::move(NewMember
.Buf
));
523 return Error::success();
528 LLVMContext
&LLVMCtx
;
532 static Expected
<SmallVector
<Slice
, 2>>
533 buildSlices(LLVMContext
&LLVMCtx
,
534 ArrayRef
<OwningBinary
<Archive
>> OutputBinaries
) {
535 SmallVector
<Slice
, 2> Slices
;
537 for (const auto &OB
: OutputBinaries
) {
538 const Archive
&A
= *OB
.getBinary();
539 Expected
<Slice
> ArchiveSlice
= Slice::create(A
, &LLVMCtx
);
541 return ArchiveSlice
.takeError();
542 Slices
.push_back(*ArchiveSlice
);
548 checkForDuplicates(const MembersPerArchitectureMap
&MembersPerArch
) {
549 for (const auto &M
: MembersPerArch
) {
550 ArrayRef
<NewArchiveMember
> Members
= M
.second
.getMembers();
551 ArrayRef
<StringRef
> Files
= M
.second
.getFiles();
552 MapVector
<StringRef
, SmallVector
<StringRef
, 1>> MembersToFiles
;
553 for (auto Iterators
= std::make_pair(Members
.begin(), Files
.begin());
554 Iterators
.first
!= Members
.end();
555 ++Iterators
.first
, ++Iterators
.second
) {
556 assert(Iterators
.second
!= Files
.end() &&
557 "Files should be the same size as Members.");
558 MembersToFiles
[Iterators
.first
->MemberName
].push_back(*Iterators
.second
);
561 std::string ErrorData
;
562 raw_string_ostream
ErrorStream(ErrorData
);
563 for (const auto &[Key
, Value
] : MembersToFiles
) {
564 if (Value
.size() > 1) {
565 ErrorStream
<< "file '" << Key
<< "' was specified multiple times.\n";
567 for (StringRef OriginalFile
: Value
)
568 ErrorStream
<< "in: " << OriginalFile
.str() << '\n';
575 if (ErrorData
.size() > 0)
576 return createStringError(std::errc::invalid_argument
, ErrorData
.c_str());
578 return Error::success();
581 static Error
createStaticLibrary(LLVMContext
&LLVMCtx
, const Config
&C
) {
582 MembersBuilder
Builder(LLVMCtx
, C
);
583 auto DataOrError
= Builder
.build();
584 if (auto Error
= DataOrError
.takeError())
587 const auto &NewMembers
= DataOrError
->MembersPerArchitecture
;
589 if (Error E
= checkForDuplicates(NewMembers
)) {
590 if (WarningsAsErrors
)
592 WithColor::defaultWarningHandler(std::move(E
));
595 if (NewMembers
.size() == 1)
596 return writeArchive(OutputFile
, NewMembers
.begin()->second
.getMembers(),
597 SymtabWritingMode::NormalSymtab
,
598 /*Kind=*/object::Archive::K_DARWIN
, C
.Deterministic
,
601 SmallVector
<OwningBinary
<Archive
>, 2> OutputBinaries
;
602 for (const std::pair
<const uint64_t, NewArchiveMemberList
> &M
: NewMembers
) {
603 Expected
<std::unique_ptr
<MemoryBuffer
>> OutputBufferOrErr
=
604 writeArchiveToBuffer(
605 M
.second
.getMembers(), SymtabWritingMode::NormalSymtab
,
606 /*Kind=*/object::Archive::K_DARWIN
, C
.Deterministic
,
608 if (!OutputBufferOrErr
)
609 return OutputBufferOrErr
.takeError();
610 std::unique_ptr
<MemoryBuffer
> &OutputBuffer
= OutputBufferOrErr
.get();
612 Expected
<std::unique_ptr
<Archive
>> ArchiveOrError
=
613 Archive::create(OutputBuffer
->getMemBufferRef());
615 return ArchiveOrError
.takeError();
616 std::unique_ptr
<Archive
> &A
= ArchiveOrError
.get();
618 OutputBinaries
.push_back(
619 OwningBinary
<Archive
>(std::move(A
), std::move(OutputBuffer
)));
622 Expected
<SmallVector
<Slice
, 2>> Slices
= buildSlices(LLVMCtx
, OutputBinaries
);
624 return Slices
.takeError();
626 llvm::stable_sort(*Slices
);
627 return writeUniversalBinary(*Slices
, OutputFile
);
630 static void parseRawArgs(int Argc
, char **Argv
) {
631 LibtoolDarwinOptTable Tbl
;
632 llvm::BumpPtrAllocator A
;
633 llvm::StringSaver Saver
{A
};
634 opt::InputArgList Args
=
635 Tbl
.parseArgs(Argc
, Argv
, OPT_UNKNOWN
, Saver
, [&](StringRef Msg
) {
636 llvm::errs() << Msg
<< '\n';
640 if (Args
.hasArg(OPT_help
)) {
641 Tbl
.printHelp(llvm::outs(), "llvm-libtool-darwin [options] <input files>",
642 "llvm-libtool-darwin");
646 InputFiles
= Args
.getAllArgValues(OPT_INPUT
);
647 Libraries
= Args
.getAllArgValues(OPT_libraries
);
648 LibrarySearchDirs
= Args
.getAllArgValues(OPT_librarySearchDirs
);
650 if (const opt::Arg
*A
= Args
.getLastArg(OPT_outputFile
))
651 OutputFile
= A
->getValue();
653 if (const opt::Arg
*A
= Args
.getLastArg(OPT_archType
))
654 ArchType
= std::make_optional(A
->getValue());
656 if (const opt::Arg
*A
= Args
.getLastArg(OPT_fileList
))
657 FileList
= A
->getValue();
659 if (const opt::Arg
*A
= Args
.getLastArg(OPT_dependencyInfoPath
))
660 DependencyInfoPath
= A
->getValue();
662 if (const opt::Arg
*A
= Args
.getLastArg(OPT_ignoredSyslibRoot
))
663 IgnoredSyslibRoot
= A
->getValue();
666 Args
.hasArg(OPT_static
) ? Operation::Static
: Operation::None
;
667 DeterministicOption
= Args
.hasArg(OPT_deterministicOption
);
668 NonDeterministicOption
= Args
.hasArg(OPT_nonDeterministicOption
);
669 VersionOption
= Args
.hasArg(OPT_version
);
670 NoWarningForNoSymbols
= Args
.hasArg(OPT_noWarningForNoSymbols
);
671 WarningsAsErrors
= Args
.hasArg(OPT_warningsAsErrors
);
674 static Expected
<Config
> parseCommandLine(int Argc
, char **Argv
) {
676 parseRawArgs(Argc
, Argv
);
678 if (LibraryOperation
== Operation::None
) {
679 if (!VersionOption
) {
680 return createStringError(std::errc::invalid_argument
,
681 "-static option: must be specified");
686 GlobalDependencyInfo
=
687 DependencyInfoPath
.empty()
688 ? std::make_unique
<DummyDependencyInfo
>()
689 : std::make_unique
<DependencyInfo
>(DependencyInfoPath
);
691 if (OutputFile
.empty()) {
692 return createStringError(std::errc::invalid_argument
,
693 "-o option: must be specified");
696 if (DeterministicOption
&& NonDeterministicOption
)
697 return createStringError(std::errc::invalid_argument
,
698 "cannot specify both -D and -U flags");
699 else if (NonDeterministicOption
)
700 C
.Deterministic
= false;
702 if (!Libraries
.empty())
703 if (Error E
= processCommandLineLibraries())
706 if (!FileList
.empty())
707 if (Error E
= processFileList())
710 if (InputFiles
.empty())
711 return createStringError(std::errc::invalid_argument
,
712 "no input files specified");
715 if (Error E
= validateArchitectureName(ArchType
.value()))
718 std::tie(C
.ArchCPUType
, C
.ArchCPUSubtype
) =
719 MachO::getCPUTypeFromArchitecture(
720 MachO::getArchitectureFromName(ArchType
.value()));
723 GlobalDependencyInfo
->write("llvm-libtool-darwin " LLVM_VERSION_STRING
,
724 InputFiles
, OutputFile
);
729 int llvm_libtool_darwin_main(int Argc
, char **Argv
, const llvm::ToolContext
&) {
730 InitLLVM
X(Argc
, Argv
);
731 Expected
<Config
> ConfigOrErr
= parseCommandLine(Argc
, Argv
);
733 WithColor::defaultErrorHandler(ConfigOrErr
.takeError());
738 cl::PrintVersionMessage();
740 llvm::InitializeAllTargetInfos();
741 llvm::InitializeAllTargetMCs();
742 llvm::InitializeAllAsmParsers();
745 Config C
= *ConfigOrErr
;
746 switch (LibraryOperation
) {
747 case Operation::None
:
749 case Operation::Static
:
750 if (Error E
= createStaticLibrary(LLVMCtx
, C
)) {
751 WithColor::defaultErrorHandler(std::move(E
));