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/LLVMDriver.h"
27 #include "llvm/Support/LineIterator.h"
28 #include "llvm/Support/TargetSelect.h"
29 #include "llvm/Support/VirtualFileSystem.h"
30 #include "llvm/Support/WithColor.h"
31 #include "llvm/Support/YAMLTraits.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include "llvm/TextAPI/Architecture.h"
36 #include <type_traits>
39 using namespace llvm::object
;
40 using namespace llvm::opt
;
42 // Command-line option boilerplate.
45 OPT_INVALID
= 0, // This is not an option ID.
46 #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
51 #define OPTTABLE_STR_TABLE_CODE
53 #undef OPTTABLE_STR_TABLE_CODE
55 #define OPTTABLE_PREFIXES_TABLE_CODE
57 #undef OPTTABLE_PREFIXES_TABLE_CODE
59 static constexpr opt::OptTable::Info InfoTable
[] = {
60 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
65 class LibtoolDarwinOptTable
: public opt::GenericOptTable
{
67 LibtoolDarwinOptTable()
68 : GenericOptTable(OptionStrTable
, OptionPrefixesTable
, InfoTable
) {}
70 } // end anonymous namespace
72 class NewArchiveMemberList
;
73 typedef std::map
<uint64_t, NewArchiveMemberList
> MembersPerArchitectureMap
;
75 static std::string OutputFile
;
76 static std::vector
<std::string
> InputFiles
;
77 static std::optional
<std::string
> ArchType
;
79 enum class Operation
{ None
, Static
};
80 static Operation LibraryOperation
= Operation::None
;
82 static bool DeterministicOption
;
83 static bool NonDeterministicOption
;
84 static std::string FileList
;
85 static std::vector
<std::string
> Libraries
;
86 static std::vector
<std::string
> LibrarySearchDirs
;
87 static std::string DependencyInfoPath
;
88 static bool VersionOption
;
89 static bool NoWarningForNoSymbols
;
90 static bool WarningsAsErrors
;
91 static std::string IgnoredSyslibRoot
;
93 static const std::array
<std::string
, 3> StandardSearchDirs
{
99 std::unique_ptr
<DependencyInfo
> GlobalDependencyInfo
;
102 bool Deterministic
= true; // Updated by 'D' and 'U' modifiers.
103 uint32_t ArchCPUType
;
104 uint32_t ArchCPUSubtype
;
107 static Expected
<std::string
> searchForFile(const Twine
&FileName
) {
110 ArrayRef
<std::string
> SearchDirs
) -> std::optional
<std::string
> {
111 for (StringRef Dir
: SearchDirs
) {
112 SmallString
<128> Path
;
113 sys::path::append(Path
, Dir
, FileName
);
115 if (sys::fs::exists(Path
))
116 return std::string(Path
);
118 GlobalDependencyInfo
->addMissingInput(Path
);
123 std::optional
<std::string
> Found
= FindLib(LibrarySearchDirs
);
125 Found
= FindLib(StandardSearchDirs
);
129 return createStringError(std::errc::invalid_argument
,
130 "cannot locate file '%s'", FileName
.str().c_str());
133 static Error
processCommandLineLibraries() {
134 for (StringRef BaseName
: Libraries
) {
135 Expected
<std::string
> FullPath
= searchForFile(
136 BaseName
.ends_with(".o") ? BaseName
.str() : "lib" + BaseName
+ ".a");
138 return FullPath
.takeError();
139 InputFiles
.push_back(FullPath
.get());
142 return Error::success();
145 static Error
processFileList() {
146 StringRef FileName
, DirName
;
147 std::tie(FileName
, DirName
) = StringRef(FileList
).rsplit(",");
149 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> FileOrErr
=
150 MemoryBuffer::getFileOrSTDIN(FileName
, /*IsText=*/false,
151 /*RequiresNullTerminator=*/false);
152 if (std::error_code EC
= FileOrErr
.getError())
153 return createFileError(FileName
, errorCodeToError(EC
));
154 const MemoryBuffer
&Ref
= *FileOrErr
.get();
156 line_iterator
I(Ref
, /*SkipBlanks=*/false);
158 return createStringError(std::errc::invalid_argument
,
159 "file list file: '%s' is empty",
160 FileName
.str().c_str());
161 for (; !I
.is_at_eof(); ++I
) {
164 return createStringError(std::errc::invalid_argument
,
165 "file list file: '%s': filename cannot be empty",
166 FileName
.str().c_str());
168 SmallString
<128> Path
;
169 if (!DirName
.empty())
170 sys::path::append(Path
, DirName
, Line
);
172 sys::path::append(Path
, Line
);
173 InputFiles
.push_back(static_cast<std::string
>(Path
));
175 return Error::success();
178 static Error
validateArchitectureName(StringRef ArchitectureName
) {
179 if (!MachOObjectFile::isValidArch(ArchitectureName
)) {
181 raw_string_ostream
OS(Buf
);
182 for (StringRef Arch
: MachOObjectFile::getValidArchs())
185 return createStringError(
186 std::errc::invalid_argument
,
187 "invalid architecture '%s': valid architecture names are %s",
188 ArchitectureName
.str().c_str(), Buf
.c_str());
190 return Error::success();
193 static uint64_t getCPUID(uint32_t CPUType
, uint32_t CPUSubtype
) {
195 case MachO::CPU_TYPE_ARM
:
196 case MachO::CPU_TYPE_ARM64
:
197 case MachO::CPU_TYPE_ARM64_32
:
198 case MachO::CPU_TYPE_X86_64
:
199 // We consider CPUSubtype only for the above 4 CPUTypes to match cctools'
201 return static_cast<uint64_t>(CPUType
) << 32 | CPUSubtype
;
207 // MembersData is an organized collection of members.
209 // MembersPerArchitectureMap is a mapping from CPU architecture to a list of
211 MembersPerArchitectureMap MembersPerArchitecture
;
212 std::vector
<std::unique_ptr
<MemoryBuffer
>> FileBuffers
;
215 // NewArchiveMemberList instances serve as collections of archive members and
216 // information about those members.
217 class NewArchiveMemberList
{
218 std::vector
<NewArchiveMember
> Members
;
219 // This vector contains the file that each NewArchiveMember from Members came
220 // from. Therefore, it has the same size as Members.
221 std::vector
<StringRef
> Files
;
224 // Add a NewArchiveMember and the file it came from to the list.
225 void push_back(NewArchiveMember
&&Member
, StringRef File
) {
226 Members
.push_back(std::move(Member
));
227 Files
.push_back(File
);
230 ArrayRef
<NewArchiveMember
> getMembers() const { return Members
; }
232 ArrayRef
<StringRef
> getFiles() const { return Files
; }
235 std::is_same
<decltype(MembersData::MembersPerArchitecture
)::mapped_type
,
236 NewArchiveMemberList
>(),
237 "This test makes sure NewArchiveMemberList is used by MembersData since "
238 "the following asserts test invariants required for MembersData.");
240 !std::is_copy_constructible_v
<
241 decltype(NewArchiveMemberList::Members
)::value_type
>,
242 "MembersData::MembersPerArchitecture has a dependency on "
243 "MembersData::FileBuffers so it should not be able to "
244 "be copied on its own without FileBuffers. Unfortunately, "
245 "is_copy_constructible does not detect whether the container (ie vector) "
246 "of a non-copyable type is itself non-copyable so we have to test the "
247 "actual type of the stored data (ie, value_type).");
249 !std::is_copy_assignable_v
<
250 decltype(NewArchiveMemberList::Members
)::value_type
>,
251 "MembersData::MembersPerArchitecture has a dependency on "
252 "MembersData::FileBuffers so it should not be able to "
253 "be copied on its own without FileBuffers. Unfortunately, "
254 "is_copy_constructible does not detect whether the container (ie vector) "
255 "of a non-copyable type is itself non-copyable so we have to test the "
256 "actual type of the stored data (ie, value_type).");
259 // MembersBuilder collects and organizes all members from the files provided by
261 class MembersBuilder
{
263 MembersBuilder(LLVMContext
&LLVMCtx
, const Config
&C
)
264 : LLVMCtx(LLVMCtx
), C(C
) {}
266 Expected
<MembersData
> build() {
267 for (StringRef FileName
: InputFiles
)
268 if (Error E
= AddMember(*this, FileName
)())
271 std::string Arch
= ArchType
.value_or("");
273 uint64_t ArchCPUID
= getCPUID(C
.ArchCPUType
, C
.ArchCPUSubtype
);
274 if (Data
.MembersPerArchitecture
.find(ArchCPUID
) ==
275 Data
.MembersPerArchitecture
.end())
276 return createStringError(std::errc::invalid_argument
,
277 "no library created (no object files in input "
278 "files matching -arch_only %s)",
281 return std::move(Data
);
286 MembersBuilder
&Builder
;
290 AddMember(MembersBuilder
&Builder
, StringRef FileName
)
291 : Builder(Builder
), FileName(FileName
) {}
294 Expected
<NewArchiveMember
> NewMemberOrErr
=
295 NewArchiveMember::getFile(FileName
, Builder
.C
.Deterministic
);
297 return createFileError(FileName
, NewMemberOrErr
.takeError());
298 auto &NewMember
= *NewMemberOrErr
;
300 // For regular archives, use the basename of the object path for the
302 NewMember
.MemberName
= sys::path::filename(NewMember
.MemberName
);
303 file_magic Magic
= identify_magic(NewMember
.Buf
->getBuffer());
306 if (Magic
== file_magic::archive
)
307 return addArchiveMembers(std::move(NewMember
));
309 // Flatten universal files.
310 if (Magic
== file_magic::macho_universal_binary
)
311 return addUniversalMembers(std::move(NewMember
));
314 if (Magic
== file_magic::bitcode
)
315 return verifyAndAddIRObject(std::move(NewMember
));
317 return verifyAndAddMachOObject(std::move(NewMember
));
321 // Check that a file's architecture [FileCPUType, FileCPUSubtype]
322 // matches the architecture specified under -arch_only flag.
323 bool acceptFileArch(uint32_t FileCPUType
, uint32_t FileCPUSubtype
) {
324 if (Builder
.C
.ArchCPUType
!= FileCPUType
)
327 switch (Builder
.C
.ArchCPUType
) {
328 case MachO::CPU_TYPE_ARM
:
329 case MachO::CPU_TYPE_ARM64_32
:
330 case MachO::CPU_TYPE_X86_64
:
331 return Builder
.C
.ArchCPUSubtype
== FileCPUSubtype
;
333 case MachO::CPU_TYPE_ARM64
:
334 if (Builder
.C
.ArchCPUSubtype
== MachO::CPU_SUBTYPE_ARM64_ALL
)
335 return FileCPUSubtype
== MachO::CPU_SUBTYPE_ARM64_ALL
||
336 FileCPUSubtype
== MachO::CPU_SUBTYPE_ARM64_V8
;
338 return Builder
.C
.ArchCPUSubtype
== FileCPUSubtype
;
345 Error
verifyAndAddMachOObject(NewArchiveMember Member
) {
346 auto MBRef
= Member
.Buf
->getMemBufferRef();
347 Expected
<std::unique_ptr
<object::ObjectFile
>> ObjOrErr
=
348 object::ObjectFile::createObjectFile(MBRef
);
350 // Throw error if not a valid object file.
352 return createFileError(Member
.MemberName
, ObjOrErr
.takeError());
354 // Throw error if not in Mach-O format.
355 if (!isa
<object::MachOObjectFile
>(**ObjOrErr
))
356 return createStringError(std::errc::invalid_argument
,
357 "'%s': format not supported",
358 Member
.MemberName
.data());
360 auto *O
= cast
<MachOObjectFile
>(ObjOrErr
->get());
361 uint32_t FileCPUType
, FileCPUSubtype
;
362 std::tie(FileCPUType
, FileCPUSubtype
) = MachO::getCPUTypeFromArchitecture(
363 MachO::getArchitectureFromName(O
->getArchTriple().getArchName()));
365 // If -arch_only is specified then skip this file if it doesn't match
366 // the architecture specified.
367 if (ArchType
&& !acceptFileArch(FileCPUType
, FileCPUSubtype
)) {
368 return Error::success();
371 if (!NoWarningForNoSymbols
&& O
->symbols().empty()) {
372 Error E
= createFileError(
374 createStringError(std::errc::invalid_argument
,
375 "has no symbols for architecture %s",
376 O
->getArchTriple().getArchName().str().c_str()));
378 if (WarningsAsErrors
)
380 WithColor::defaultWarningHandler(std::move(E
));
383 uint64_t FileCPUID
= getCPUID(FileCPUType
, FileCPUSubtype
);
384 Builder
.Data
.MembersPerArchitecture
[FileCPUID
].push_back(
385 std::move(Member
), FileName
);
386 return Error::success();
389 Error
verifyAndAddIRObject(NewArchiveMember Member
) {
390 auto MBRef
= Member
.Buf
->getMemBufferRef();
391 Expected
<std::unique_ptr
<object::IRObjectFile
>> IROrErr
=
392 object::IRObjectFile::create(MBRef
, Builder
.LLVMCtx
);
394 // Throw error if not a valid IR object file.
396 return createFileError(Member
.MemberName
, IROrErr
.takeError());
398 Triple TT
= Triple(IROrErr
->get()->getTargetTriple());
400 Expected
<uint32_t> FileCPUTypeOrErr
= MachO::getCPUType(TT
);
401 if (!FileCPUTypeOrErr
)
402 return FileCPUTypeOrErr
.takeError();
404 Expected
<uint32_t> FileCPUSubTypeOrErr
= MachO::getCPUSubType(TT
);
405 if (!FileCPUSubTypeOrErr
)
406 return FileCPUSubTypeOrErr
.takeError();
408 // If -arch_only is specified then skip this file if it doesn't match
409 // the architecture specified.
411 !acceptFileArch(*FileCPUTypeOrErr
, *FileCPUSubTypeOrErr
)) {
412 return Error::success();
415 uint64_t FileCPUID
= getCPUID(*FileCPUTypeOrErr
, *FileCPUSubTypeOrErr
);
416 Builder
.Data
.MembersPerArchitecture
[FileCPUID
].push_back(
417 std::move(Member
), FileName
);
418 return Error::success();
421 Error
addChildMember(const object::Archive::Child
&M
) {
422 Expected
<NewArchiveMember
> NewMemberOrErr
=
423 NewArchiveMember::getOldMember(M
, Builder
.C
.Deterministic
);
425 return NewMemberOrErr
.takeError();
426 auto &NewMember
= *NewMemberOrErr
;
428 file_magic Magic
= identify_magic(NewMember
.Buf
->getBuffer());
430 if (Magic
== file_magic::bitcode
)
431 return verifyAndAddIRObject(std::move(NewMember
));
433 return verifyAndAddMachOObject(std::move(NewMember
));
436 Error
processArchive(object::Archive
&Lib
) {
437 Error Err
= Error::success();
438 for (const object::Archive::Child
&Child
: Lib
.children(Err
))
439 if (Error E
= addChildMember(Child
))
440 return createFileError(FileName
, std::move(E
));
442 return createFileError(FileName
, std::move(Err
));
444 return Error::success();
447 Error
addArchiveMembers(NewArchiveMember NewMember
) {
448 Expected
<std::unique_ptr
<Archive
>> LibOrErr
=
449 object::Archive::create(NewMember
.Buf
->getMemBufferRef());
451 return createFileError(FileName
, LibOrErr
.takeError());
453 if (Error E
= processArchive(**LibOrErr
))
456 // Update vector FileBuffers with the MemoryBuffers to transfer
458 Builder
.Data
.FileBuffers
.push_back(std::move(NewMember
.Buf
));
459 return Error::success();
462 Error
addUniversalMembers(NewArchiveMember NewMember
) {
463 Expected
<std::unique_ptr
<MachOUniversalBinary
>> BinaryOrErr
=
464 MachOUniversalBinary::create(NewMember
.Buf
->getMemBufferRef());
466 return createFileError(FileName
, BinaryOrErr
.takeError());
468 auto *UO
= BinaryOrErr
->get();
469 for (const MachOUniversalBinary::ObjectForArch
&O
: UO
->objects()) {
471 Expected
<std::unique_ptr
<MachOObjectFile
>> MachOObjOrErr
=
474 NewArchiveMember NewMember
=
475 NewArchiveMember(MachOObjOrErr
->get()->getMemoryBufferRef());
476 NewMember
.MemberName
= sys::path::filename(NewMember
.MemberName
);
478 if (Error E
= verifyAndAddMachOObject(std::move(NewMember
)))
483 Expected
<std::unique_ptr
<IRObjectFile
>> IRObjectOrError
=
484 O
.getAsIRObject(Builder
.LLVMCtx
);
485 if (IRObjectOrError
) {
486 // A universal file member can be a MachOObjectFile, an IRObject or an
487 // Archive. In case we can successfully cast the member as an
488 // IRObject, it is safe to throw away the error generated due to
489 // casting the object as a MachOObjectFile.
490 consumeError(MachOObjOrErr
.takeError());
492 NewArchiveMember NewMember
=
493 NewArchiveMember(IRObjectOrError
->get()->getMemoryBufferRef());
494 NewMember
.MemberName
= sys::path::filename(NewMember
.MemberName
);
496 if (Error E
= verifyAndAddIRObject(std::move(NewMember
)))
501 Expected
<std::unique_ptr
<Archive
>> ArchiveOrError
= O
.getAsArchive();
502 if (ArchiveOrError
) {
503 // A universal file member can be a MachOObjectFile, an IRObject or an
504 // Archive. In case we can successfully cast the member as an Archive,
505 // it is safe to throw away the error generated due to casting the
506 // object as a MachOObjectFile.
507 consumeError(MachOObjOrErr
.takeError());
508 consumeError(IRObjectOrError
.takeError());
510 if (Error E
= processArchive(**ArchiveOrError
))
515 Error CombinedError
= joinErrors(
516 ArchiveOrError
.takeError(),
517 joinErrors(IRObjectOrError
.takeError(), MachOObjOrErr
.takeError()));
518 return createFileError(FileName
, std::move(CombinedError
));
521 // Update vector FileBuffers with the MemoryBuffers to transfer
523 Builder
.Data
.FileBuffers
.push_back(std::move(NewMember
.Buf
));
524 return Error::success();
529 LLVMContext
&LLVMCtx
;
533 static Expected
<SmallVector
<Slice
, 2>>
534 buildSlices(LLVMContext
&LLVMCtx
,
535 ArrayRef
<OwningBinary
<Archive
>> OutputBinaries
) {
536 SmallVector
<Slice
, 2> Slices
;
538 for (const auto &OB
: OutputBinaries
) {
539 const Archive
&A
= *OB
.getBinary();
540 Expected
<Slice
> ArchiveSlice
= Slice::create(A
, &LLVMCtx
);
542 return ArchiveSlice
.takeError();
543 Slices
.push_back(*ArchiveSlice
);
549 checkForDuplicates(const MembersPerArchitectureMap
&MembersPerArch
) {
550 for (const auto &M
: MembersPerArch
) {
551 ArrayRef
<NewArchiveMember
> Members
= M
.second
.getMembers();
552 ArrayRef
<StringRef
> Files
= M
.second
.getFiles();
553 MapVector
<StringRef
, SmallVector
<StringRef
, 1>> MembersToFiles
;
554 for (auto Iterators
= std::make_pair(Members
.begin(), Files
.begin());
555 Iterators
.first
!= Members
.end();
556 ++Iterators
.first
, ++Iterators
.second
) {
557 assert(Iterators
.second
!= Files
.end() &&
558 "Files should be the same size as Members.");
559 MembersToFiles
[Iterators
.first
->MemberName
].push_back(*Iterators
.second
);
562 std::string ErrorData
;
563 raw_string_ostream
ErrorStream(ErrorData
);
564 for (const auto &[Key
, Value
] : MembersToFiles
) {
565 if (Value
.size() > 1) {
566 ErrorStream
<< "file '" << Key
<< "' was specified multiple times.\n";
568 for (StringRef OriginalFile
: Value
)
569 ErrorStream
<< "in: " << OriginalFile
.str() << '\n';
576 if (ErrorData
.size() > 0)
577 return createStringError(std::errc::invalid_argument
, ErrorData
.c_str());
579 return Error::success();
582 static Error
createStaticLibrary(LLVMContext
&LLVMCtx
, const Config
&C
) {
583 MembersBuilder
Builder(LLVMCtx
, C
);
584 auto DataOrError
= Builder
.build();
585 if (auto Error
= DataOrError
.takeError())
588 const auto &NewMembers
= DataOrError
->MembersPerArchitecture
;
590 if (Error E
= checkForDuplicates(NewMembers
)) {
591 if (WarningsAsErrors
)
593 WithColor::defaultWarningHandler(std::move(E
));
596 if (NewMembers
.size() == 1)
597 return writeArchive(OutputFile
, NewMembers
.begin()->second
.getMembers(),
598 SymtabWritingMode::NormalSymtab
,
599 /*Kind=*/object::Archive::K_DARWIN
, C
.Deterministic
,
602 SmallVector
<OwningBinary
<Archive
>, 2> OutputBinaries
;
603 for (const std::pair
<const uint64_t, NewArchiveMemberList
> &M
: NewMembers
) {
604 Expected
<std::unique_ptr
<MemoryBuffer
>> OutputBufferOrErr
=
605 writeArchiveToBuffer(
606 M
.second
.getMembers(), SymtabWritingMode::NormalSymtab
,
607 /*Kind=*/object::Archive::K_DARWIN
, C
.Deterministic
,
609 if (!OutputBufferOrErr
)
610 return OutputBufferOrErr
.takeError();
611 std::unique_ptr
<MemoryBuffer
> &OutputBuffer
= OutputBufferOrErr
.get();
613 Expected
<std::unique_ptr
<Archive
>> ArchiveOrError
=
614 Archive::create(OutputBuffer
->getMemBufferRef());
616 return ArchiveOrError
.takeError();
617 std::unique_ptr
<Archive
> &A
= ArchiveOrError
.get();
619 OutputBinaries
.push_back(
620 OwningBinary
<Archive
>(std::move(A
), std::move(OutputBuffer
)));
623 Expected
<SmallVector
<Slice
, 2>> Slices
= buildSlices(LLVMCtx
, OutputBinaries
);
625 return Slices
.takeError();
627 llvm::stable_sort(*Slices
);
628 return writeUniversalBinary(*Slices
, OutputFile
);
631 static void parseRawArgs(int Argc
, char **Argv
) {
632 LibtoolDarwinOptTable Tbl
;
633 llvm::BumpPtrAllocator A
;
634 llvm::StringSaver Saver
{A
};
635 opt::InputArgList Args
=
636 Tbl
.parseArgs(Argc
, Argv
, OPT_UNKNOWN
, Saver
, [&](StringRef Msg
) {
637 llvm::errs() << Msg
<< '\n';
641 if (Args
.hasArg(OPT_help
)) {
642 Tbl
.printHelp(llvm::outs(), "llvm-libtool-darwin [options] <input files>",
643 "llvm-libtool-darwin");
647 InputFiles
= Args
.getAllArgValues(OPT_INPUT
);
648 Libraries
= Args
.getAllArgValues(OPT_libraries
);
649 LibrarySearchDirs
= Args
.getAllArgValues(OPT_librarySearchDirs
);
651 if (const opt::Arg
*A
= Args
.getLastArg(OPT_outputFile
))
652 OutputFile
= A
->getValue();
654 if (const opt::Arg
*A
= Args
.getLastArg(OPT_archType
))
655 ArchType
= std::make_optional(A
->getValue());
657 if (const opt::Arg
*A
= Args
.getLastArg(OPT_fileList
))
658 FileList
= A
->getValue();
660 if (const opt::Arg
*A
= Args
.getLastArg(OPT_dependencyInfoPath
))
661 DependencyInfoPath
= A
->getValue();
663 if (const opt::Arg
*A
= Args
.getLastArg(OPT_ignoredSyslibRoot
))
664 IgnoredSyslibRoot
= A
->getValue();
667 Args
.hasArg(OPT_static
) ? Operation::Static
: Operation::None
;
668 DeterministicOption
= Args
.hasArg(OPT_deterministicOption
);
669 NonDeterministicOption
= Args
.hasArg(OPT_nonDeterministicOption
);
670 VersionOption
= Args
.hasArg(OPT_version
);
671 NoWarningForNoSymbols
= Args
.hasArg(OPT_noWarningForNoSymbols
);
672 WarningsAsErrors
= Args
.hasArg(OPT_warningsAsErrors
);
675 static Expected
<Config
> parseCommandLine(int Argc
, char **Argv
) {
677 parseRawArgs(Argc
, Argv
);
679 if (LibraryOperation
== Operation::None
) {
680 if (!VersionOption
) {
681 return createStringError(std::errc::invalid_argument
,
682 "-static option: must be specified");
687 GlobalDependencyInfo
=
688 DependencyInfoPath
.empty()
689 ? std::make_unique
<DummyDependencyInfo
>()
690 : std::make_unique
<DependencyInfo
>(DependencyInfoPath
);
692 if (OutputFile
.empty()) {
693 return createStringError(std::errc::invalid_argument
,
694 "-o option: must be specified");
697 if (DeterministicOption
&& NonDeterministicOption
)
698 return createStringError(std::errc::invalid_argument
,
699 "cannot specify both -D and -U flags");
700 else if (NonDeterministicOption
)
701 C
.Deterministic
= false;
703 if (!Libraries
.empty())
704 if (Error E
= processCommandLineLibraries())
707 if (!FileList
.empty())
708 if (Error E
= processFileList())
711 if (InputFiles
.empty())
712 return createStringError(std::errc::invalid_argument
,
713 "no input files specified");
716 if (Error E
= validateArchitectureName(ArchType
.value()))
719 std::tie(C
.ArchCPUType
, C
.ArchCPUSubtype
) =
720 MachO::getCPUTypeFromArchitecture(
721 MachO::getArchitectureFromName(ArchType
.value()));
724 GlobalDependencyInfo
->write("llvm-libtool-darwin " LLVM_VERSION_STRING
,
725 InputFiles
, OutputFile
);
730 int llvm_libtool_darwin_main(int Argc
, char **Argv
, const llvm::ToolContext
&) {
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
));