1 //===-- Options.cpp -------------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
10 #include "clang/Basic/DiagnosticIDs.h"
11 #include "clang/Driver/Driver.h"
12 #include "clang/InstallAPI/DirectoryScanner.h"
13 #include "clang/InstallAPI/FileList.h"
14 #include "clang/InstallAPI/HeaderFile.h"
15 #include "clang/InstallAPI/InstallAPIDiagnostic.h"
16 #include "llvm/BinaryFormat/Magic.h"
17 #include "llvm/Support/JSON.h"
18 #include "llvm/Support/Program.h"
19 #include "llvm/TargetParser/Host.h"
20 #include "llvm/TextAPI/DylibReader.h"
21 #include "llvm/TextAPI/TextAPIError.h"
22 #include "llvm/TextAPI/TextAPIReader.h"
23 #include "llvm/TextAPI/TextAPIWriter.h"
26 using namespace llvm::opt
;
27 using namespace llvm::MachO
;
29 namespace drv
= clang::driver::options
;
32 namespace installapi
{
34 /// Create prefix string literals used in InstallAPIOpts.td.
35 #define PREFIX(NAME, VALUE) \
36 static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \
37 static constexpr llvm::ArrayRef<llvm::StringLiteral> NAME( \
38 NAME##_init, std::size(NAME##_init) - 1);
39 #include "InstallAPIOpts.inc"
42 static constexpr const llvm::StringLiteral PrefixTable_init
[] =
43 #define PREFIX_UNION(VALUES) VALUES
44 #include "InstallAPIOpts.inc"
47 static constexpr const ArrayRef
<StringLiteral
>
48 PrefixTable(PrefixTable_init
, std::size(PrefixTable_init
) - 1);
50 /// Create table mapping all options defined in InstallAPIOpts.td.
51 static constexpr OptTable::Info InfoTable
[] = {
52 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \
53 VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, \
58 HELPTEXTSFORVARIANTS, \
61 Option::KIND##Class, \
69 #include "InstallAPIOpts.inc"
75 /// \brief Create OptTable class for parsing actual command line arguments.
76 class DriverOptTable
: public opt::PrecomputedOptTable
{
78 DriverOptTable() : PrecomputedOptTable(InfoTable
, PrefixTable
) {}
81 } // end anonymous namespace.
83 static llvm::opt::OptTable
*createDriverOptTable() {
84 return new DriverOptTable();
87 /// Parse JSON input into argument list.
89 /* Expected input format.
90 * { "label" : ["-ClangArg1", "-ClangArg2"] }
93 /// Input is interpreted as "-Xlabel ClangArg1 -XLabel ClangArg2".
94 static Expected
<llvm::opt::InputArgList
>
95 getArgListFromJSON(const StringRef Input
, llvm::opt::OptTable
*Table
,
96 std::vector
<std::string
> &Storage
) {
98 Expected
<Value
> ValOrErr
= json::parse(Input
);
100 return ValOrErr
.takeError();
102 const Object
*Root
= ValOrErr
->getAsObject();
104 return llvm::opt::InputArgList();
106 for (const auto &KV
: *Root
) {
107 const Array
*ArgList
= KV
.getSecond().getAsArray();
108 std::string Label
= "-X" + KV
.getFirst().str();
110 return make_error
<TextAPIError
>(TextAPIErrorCode::InvalidInputFormat
);
111 for (auto Arg
: *ArgList
) {
112 std::optional
<StringRef
> ArgStr
= Arg
.getAsString();
114 return make_error
<TextAPIError
>(TextAPIErrorCode::InvalidInputFormat
);
115 Storage
.emplace_back(Label
);
116 Storage
.emplace_back(*ArgStr
);
120 std::vector
<const char *> CArgs(Storage
.size());
121 llvm::for_each(Storage
,
122 [&CArgs
](StringRef Str
) { CArgs
.emplace_back(Str
.data()); });
124 unsigned MissingArgIndex
, MissingArgCount
;
125 return Table
->ParseArgs(CArgs
, MissingArgIndex
, MissingArgCount
);
128 bool Options::processDriverOptions(InputArgList
&Args
) {
130 for (const StringRef Path
: Args
.getAllArgValues(drv::OPT_INPUT
)) {
131 // Assume any input that is not a directory is a filelist.
132 // InstallAPI does not accept multiple directories, so retain the last one.
133 if (FM
->getOptionalDirectoryRef(Path
))
134 DriverOpts
.InputDirectory
= Path
.str();
136 DriverOpts
.FileLists
.emplace_back(Path
.str());
140 SmallString
<PATH_MAX
> OutputPath
;
141 if (auto *Arg
= Args
.getLastArg(drv::OPT_o
)) {
142 OutputPath
= Arg
->getValue();
143 if (OutputPath
!= "-")
144 FM
->makeAbsolutePath(OutputPath
);
145 DriverOpts
.OutputPath
= std::string(OutputPath
);
147 if (DriverOpts
.OutputPath
.empty()) {
148 Diags
->Report(diag::err_no_output_file
);
152 // Do basic error checking first for mixing -target and -arch options.
153 auto *ArgArch
= Args
.getLastArgNoClaim(drv::OPT_arch
);
154 auto *ArgTarget
= Args
.getLastArgNoClaim(drv::OPT_target
);
155 auto *ArgTargetVariant
=
156 Args
.getLastArgNoClaim(drv::OPT_darwin_target_variant
);
157 if (ArgArch
&& (ArgTarget
|| ArgTargetVariant
)) {
158 Diags
->Report(clang::diag::err_drv_argument_not_allowed_with
)
159 << ArgArch
->getAsString(Args
)
160 << (ArgTarget
? ArgTarget
: ArgTargetVariant
)->getAsString(Args
);
164 auto *ArgMinTargetOS
= Args
.getLastArgNoClaim(drv::OPT_mtargetos_EQ
);
165 if ((ArgTarget
|| ArgTargetVariant
) && ArgMinTargetOS
) {
166 Diags
->Report(clang::diag::err_drv_cannot_mix_options
)
167 << ArgTarget
->getAsString(Args
) << ArgMinTargetOS
->getAsString(Args
);
171 // Capture target triples first.
173 for (const Arg
*A
: Args
.filtered(drv::OPT_target
)) {
175 llvm::Triple
TargetTriple(A
->getValue());
176 Target TAPITarget
= Target(TargetTriple
);
177 if ((TAPITarget
.Arch
== AK_unknown
) ||
178 (TAPITarget
.Platform
== PLATFORM_UNKNOWN
)) {
179 Diags
->Report(clang::diag::err_drv_unsupported_opt_for_target
)
180 << "installapi" << TargetTriple
.str();
183 DriverOpts
.Targets
[TAPITarget
] = TargetTriple
;
187 // Capture target variants.
188 DriverOpts
.Zippered
= ArgTargetVariant
!= nullptr;
189 for (Arg
*A
: Args
.filtered(drv::OPT_darwin_target_variant
)) {
191 Triple
Variant(A
->getValue());
192 if (Variant
.getVendor() != Triple::Apple
) {
193 Diags
->Report(diag::err_unsupported_vendor
)
194 << Variant
.getVendorName() << A
->getAsString(Args
);
198 switch (Variant
.getOS()) {
200 Diags
->Report(diag::err_unsupported_os
)
201 << Variant
.getOSName() << A
->getAsString(Args
);
208 switch (Variant
.getEnvironment()) {
210 Diags
->Report(diag::err_unsupported_environment
)
211 << Variant
.getEnvironmentName() << A
->getAsString(Args
);
213 case Triple::UnknownEnvironment
:
218 Target
TAPIVariant(Variant
);
219 // See if there is a matching --target option for this --target-variant
221 auto It
= find_if(DriverOpts
.Targets
, [&](const auto &T
) {
222 return (T
.first
.Arch
== TAPIVariant
.Arch
) &&
223 (T
.first
.Platform
!= PlatformType::PLATFORM_UNKNOWN
);
226 if (It
== DriverOpts
.Targets
.end()) {
227 Diags
->Report(diag::err_no_matching_target
) << Variant
.str();
231 DriverOpts
.Targets
[TAPIVariant
] = Variant
;
234 DriverOpts
.Verbose
= Args
.hasArgNoClaim(drv::OPT_v
);
239 bool Options::processInstallAPIXOptions(InputArgList
&Args
) {
240 for (arg_iterator It
= Args
.begin(), End
= Args
.end(); It
!= End
; ++It
) {
242 if (A
->getOption().matches(OPT_Xarch__
)) {
243 if (!processXarchOption(Args
, It
))
246 } else if (A
->getOption().matches(OPT_Xplatform__
)) {
247 if (!processXplatformOption(Args
, It
))
250 } else if (A
->getOption().matches(OPT_Xproject
)) {
251 if (!processXprojectOption(Args
, It
))
254 } else if (!A
->getOption().matches(OPT_X__
))
257 // Handle any user defined labels.
258 const StringRef Label
= A
->getValue(0);
260 // Ban "public" and "private" labels.
261 if ((Label
.lower() == "public") || (Label
.lower() == "private")) {
262 Diags
->Report(diag::err_invalid_label
) << Label
;
266 auto NextIt
= std::next(It
);
268 Diags
->Report(clang::diag::err_drv_missing_argument
)
269 << A
->getAsString(Args
) << 1;
272 Arg
*NextA
= *NextIt
;
273 switch ((ID
)NextA
->getOption().getID()) {
278 Diags
->Report(clang::diag::err_drv_argument_not_allowed_with
)
279 << A
->getAsString(Args
) << NextA
->getAsString(Args
);
282 const StringRef ASpelling
= NextA
->getSpelling();
283 const auto &AValues
= NextA
->getValues();
285 FEOpts
.UniqueArgs
[Label
].emplace_back(ASpelling
.str());
287 for (const StringRef Val
: AValues
)
288 FEOpts
.UniqueArgs
[Label
].emplace_back((ASpelling
+ Val
).str());
297 bool Options::processXplatformOption(InputArgList
&Args
, arg_iterator Curr
) {
300 PlatformType Platform
= getPlatformFromName(A
->getValue(0));
301 if (Platform
== PLATFORM_UNKNOWN
) {
302 Diags
->Report(diag::err_unsupported_os
)
303 << getPlatformName(Platform
) << A
->getAsString(Args
);
306 auto NextIt
= std::next(Curr
);
307 if (NextIt
== Args
.end()) {
308 Diags
->Report(diag::err_drv_missing_argument
) << A
->getAsString(Args
) << 1;
312 Arg
*NextA
= *NextIt
;
313 switch ((ID
)NextA
->getOption().getID()) {
315 FEOpts
.SystemFwkPaths
.emplace_back(NextA
->getValue(), Platform
);
318 Diags
->Report(diag::err_drv_invalid_argument_to_option
)
319 << A
->getAsString(Args
) << NextA
->getAsString(Args
);
329 bool Options::processXprojectOption(InputArgList
&Args
, arg_iterator Curr
) {
331 auto NextIt
= std::next(Curr
);
332 if (NextIt
== Args
.end()) {
333 Diags
->Report(diag::err_drv_missing_argument
) << A
->getAsString(Args
) << 1;
337 Arg
*NextA
= *NextIt
;
338 switch ((ID
)NextA
->getOption().getID()) {
341 case OPT_fmodules_cache_path
:
343 case OPT_fvisibility_EQ
:
346 Diags
->Report(diag::err_drv_argument_not_allowed_with
)
347 << A
->getAsString(Args
) << NextA
->getAsString(Args
);
351 std::string ArgString
= NextA
->getSpelling().str();
352 for (const StringRef Val
: NextA
->getValues())
353 ArgString
+= Val
.str();
355 ProjectLevelArgs
.push_back(ArgString
);
362 bool Options::processXarchOption(InputArgList
&Args
, arg_iterator Curr
) {
363 Arg
*CurrArg
= *Curr
;
364 Architecture Arch
= getArchitectureFromName(CurrArg
->getValue(0));
365 if (Arch
== AK_unknown
) {
366 Diags
->Report(diag::err_drv_invalid_arch_name
)
367 << CurrArg
->getAsString(Args
);
371 auto NextIt
= std::next(Curr
);
372 if (NextIt
== Args
.end()) {
373 Diags
->Report(diag::err_drv_missing_argument
)
374 << CurrArg
->getAsString(Args
) << 1;
378 // InstallAPI has a limited understanding of supported Xarch options.
379 // Currently this is restricted to linker inputs.
380 const Arg
*NextArg
= *NextIt
;
381 switch (NextArg
->getOption().getID()) {
382 case OPT_allowable_client
:
384 case OPT_reexport_framework
:
385 case OPT_reexport_library
:
389 Diags
->Report(diag::err_drv_invalid_argument_to_option
)
390 << NextArg
->getAsString(Args
) << CurrArg
->getAsString(Args
);
394 ArgToArchMap
[NextArg
] = Arch
;
400 bool Options::processOptionList(InputArgList
&Args
,
401 llvm::opt::OptTable
*Table
) {
402 Arg
*A
= Args
.getLastArg(OPT_option_list
);
406 const StringRef Path
= A
->getValue(0);
407 auto InputOrErr
= FM
->getBufferForFile(Path
);
408 if (auto Err
= InputOrErr
.getError()) {
409 Diags
->Report(diag::err_cannot_open_file
) << Path
<< Err
.message();
412 // Backing storage referenced for argument processing.
413 std::vector
<std::string
> Storage
;
415 getArgListFromJSON((*InputOrErr
)->getBuffer(), Table
, Storage
);
417 if (auto Err
= ArgsOrErr
.takeError()) {
418 Diags
->Report(diag::err_cannot_read_input_list
)
419 << "option" << Path
<< toString(std::move(Err
));
422 return processInstallAPIXOptions(*ArgsOrErr
);
425 bool Options::processLinkerOptions(InputArgList
&Args
) {
426 // Handle required arguments.
427 if (const Arg
*A
= Args
.getLastArg(drv::OPT_install__name
))
428 LinkerOpts
.InstallName
= A
->getValue();
429 if (LinkerOpts
.InstallName
.empty()) {
430 Diags
->Report(diag::err_no_install_name
);
434 // Defaulted or optional arguments.
435 if (auto *Arg
= Args
.getLastArg(drv::OPT_current__version
))
436 LinkerOpts
.CurrentVersion
.parse64(Arg
->getValue());
438 if (auto *Arg
= Args
.getLastArg(drv::OPT_compatibility__version
))
439 LinkerOpts
.CompatVersion
.parse64(Arg
->getValue());
441 if (auto *Arg
= Args
.getLastArg(drv::OPT_compatibility__version
))
442 LinkerOpts
.CompatVersion
.parse64(Arg
->getValue());
444 if (auto *Arg
= Args
.getLastArg(drv::OPT_umbrella
))
445 LinkerOpts
.ParentUmbrella
= Arg
->getValue();
447 LinkerOpts
.IsDylib
= Args
.hasArg(drv::OPT_dynamiclib
);
449 for (auto *Arg
: Args
.filtered(drv::OPT_alias_list
)) {
450 LinkerOpts
.AliasLists
.emplace_back(Arg
->getValue());
454 LinkerOpts
.AppExtensionSafe
= Args
.hasFlag(
455 drv::OPT_fapplication_extension
, drv::OPT_fno_application_extension
,
456 /*Default=*/LinkerOpts
.AppExtensionSafe
);
458 if (::getenv("LD_NO_ENCRYPT") != nullptr)
459 LinkerOpts
.AppExtensionSafe
= true;
461 if (::getenv("LD_APPLICATION_EXTENSION_SAFE") != nullptr)
462 LinkerOpts
.AppExtensionSafe
= true;
464 // Capture library paths.
465 PathSeq LibraryPaths
;
466 for (const Arg
*A
: Args
.filtered(drv::OPT_L
)) {
467 LibraryPaths
.emplace_back(A
->getValue());
471 if (!LibraryPaths
.empty())
472 LinkerOpts
.LibPaths
= std::move(LibraryPaths
);
477 // NOTE: Do not claim any arguments, as they will be passed along for CC1
479 bool Options::processFrontendOptions(InputArgList
&Args
) {
480 // Capture language mode.
481 if (auto *A
= Args
.getLastArgNoClaim(drv::OPT_x
)) {
482 FEOpts
.LangMode
= llvm::StringSwitch
<clang::Language
>(A
->getValue())
483 .Case("c", clang::Language::C
)
484 .Case("c++", clang::Language::CXX
)
485 .Case("objective-c", clang::Language::ObjC
)
486 .Case("objective-c++", clang::Language::ObjCXX
)
487 .Default(clang::Language::Unknown
);
489 if (FEOpts
.LangMode
== clang::Language::Unknown
) {
490 Diags
->Report(clang::diag::err_drv_invalid_value
)
491 << A
->getAsString(Args
) << A
->getValue();
495 for (auto *A
: Args
.filtered(drv::OPT_ObjC
, drv::OPT_ObjCXX
)) {
496 if (A
->getOption().matches(drv::OPT_ObjC
))
497 FEOpts
.LangMode
= clang::Language::ObjC
;
499 FEOpts
.LangMode
= clang::Language::ObjCXX
;
503 if (const Arg
*A
= Args
.getLastArgNoClaim(drv::OPT_isysroot
)) {
504 SmallString
<PATH_MAX
> Path(A
->getValue());
505 FM
->makeAbsolutePath(Path
);
506 if (!FM
->getOptionalDirectoryRef(Path
)) {
507 Diags
->Report(diag::err_missing_sysroot
) << Path
;
510 FEOpts
.ISysroot
= std::string(Path
);
511 } else if (FEOpts
.ISysroot
.empty()) {
512 // Mirror CLANG and obtain the isysroot from the SDKROOT environment
513 // variable, if it wasn't defined by the command line.
514 if (auto *Env
= ::getenv("SDKROOT")) {
515 if (StringRef(Env
) != "/" && llvm::sys::path::is_absolute(Env
) &&
516 FM
->getOptionalFileRef(Env
))
517 FEOpts
.ISysroot
= Env
;
521 // Capture system frameworks for all platforms.
522 for (const Arg
*A
: Args
.filtered(drv::OPT_iframework
))
523 FEOpts
.SystemFwkPaths
.emplace_back(A
->getValue(),
524 std::optional
<PlatformType
>{});
526 // Capture framework paths.
527 PathSeq FrameworkPaths
;
528 for (const Arg
*A
: Args
.filtered(drv::OPT_F
))
529 FrameworkPaths
.emplace_back(A
->getValue());
531 if (!FrameworkPaths
.empty())
532 FEOpts
.FwkPaths
= std::move(FrameworkPaths
);
534 // Add default framework/library paths.
535 PathSeq DefaultLibraryPaths
= {"/usr/lib", "/usr/local/lib"};
536 PathSeq DefaultFrameworkPaths
= {"/Library/Frameworks",
537 "/System/Library/Frameworks"};
539 for (const StringRef LibPath
: DefaultLibraryPaths
) {
540 SmallString
<PATH_MAX
> Path(FEOpts
.ISysroot
);
541 sys::path::append(Path
, LibPath
);
542 LinkerOpts
.LibPaths
.emplace_back(Path
.str());
544 for (const StringRef FwkPath
: DefaultFrameworkPaths
) {
545 SmallString
<PATH_MAX
> Path(FEOpts
.ISysroot
);
546 sys::path::append(Path
, FwkPath
);
547 FEOpts
.SystemFwkPaths
.emplace_back(Path
.str(),
548 std::optional
<PlatformType
>{});
554 bool Options::addFilePaths(InputArgList
&Args
, PathSeq
&Headers
,
556 for (const StringRef Path
: Args
.getAllArgValues(ID
)) {
557 if ((bool)FM
->getOptionalDirectoryRef(Path
, /*CacheFailure=*/false)) {
558 auto InputHeadersOrErr
= enumerateFiles(*FM
, Path
);
559 if (!InputHeadersOrErr
) {
560 Diags
->Report(diag::err_cannot_open_file
)
561 << Path
<< toString(InputHeadersOrErr
.takeError());
564 // Sort headers to ensure deterministic behavior.
565 sort(*InputHeadersOrErr
);
566 for (StringRef H
: *InputHeadersOrErr
)
567 Headers
.emplace_back(std::move(H
));
569 Headers
.emplace_back(Path
);
574 std::vector
<const char *>
575 Options::processAndFilterOutInstallAPIOptions(ArrayRef
<const char *> Args
) {
576 std::unique_ptr
<llvm::opt::OptTable
> Table
;
577 Table
.reset(createDriverOptTable());
579 unsigned MissingArgIndex
, MissingArgCount
;
580 auto ParsedArgs
= Table
->ParseArgs(Args
.slice(1), MissingArgIndex
,
581 MissingArgCount
, Visibility());
583 // Capture InstallAPI only driver options.
584 if (!processInstallAPIXOptions(ParsedArgs
))
587 if (!processOptionList(ParsedArgs
, Table
.get()))
590 DriverOpts
.Demangle
= ParsedArgs
.hasArg(OPT_demangle
);
592 if (auto *A
= ParsedArgs
.getLastArg(OPT_filetype
)) {
593 DriverOpts
.OutFT
= TextAPIWriter::parseFileType(A
->getValue());
594 if (DriverOpts
.OutFT
== FileType::Invalid
) {
595 Diags
->Report(clang::diag::err_drv_invalid_value
)
596 << A
->getAsString(ParsedArgs
) << A
->getValue();
601 if (const Arg
*A
= ParsedArgs
.getLastArg(OPT_verify_mode_EQ
)) {
602 DriverOpts
.VerifyMode
=
603 StringSwitch
<VerificationMode
>(A
->getValue())
604 .Case("ErrorsOnly", VerificationMode::ErrorsOnly
)
605 .Case("ErrorsAndWarnings", VerificationMode::ErrorsAndWarnings
)
606 .Case("Pedantic", VerificationMode::Pedantic
)
607 .Default(VerificationMode::Invalid
);
609 if (DriverOpts
.VerifyMode
== VerificationMode::Invalid
) {
610 Diags
->Report(clang::diag::err_drv_invalid_value
)
611 << A
->getAsString(ParsedArgs
) << A
->getValue();
616 if (const Arg
*A
= ParsedArgs
.getLastArg(OPT_verify_against
))
617 DriverOpts
.DylibToVerify
= A
->getValue();
619 if (const Arg
*A
= ParsedArgs
.getLastArg(OPT_dsym
))
620 DriverOpts
.DSYMPath
= A
->getValue();
622 DriverOpts
.TraceLibraryLocation
= ParsedArgs
.hasArg(OPT_t
);
624 // Linker options not handled by clang driver.
625 LinkerOpts
.OSLibNotForSharedCache
=
626 ParsedArgs
.hasArg(OPT_not_for_dyld_shared_cache
);
628 for (const Arg
*A
: ParsedArgs
.filtered(OPT_allowable_client
)) {
629 LinkerOpts
.AllowableClients
[A
->getValue()] =
630 ArgToArchMap
.count(A
) ? ArgToArchMap
[A
] : ArchitectureSet();
634 for (const Arg
*A
: ParsedArgs
.filtered(OPT_reexport_l
)) {
635 LinkerOpts
.ReexportedLibraries
[A
->getValue()] =
636 ArgToArchMap
.count(A
) ? ArgToArchMap
[A
] : ArchitectureSet();
640 for (const Arg
*A
: ParsedArgs
.filtered(OPT_reexport_library
)) {
641 LinkerOpts
.ReexportedLibraryPaths
[A
->getValue()] =
642 ArgToArchMap
.count(A
) ? ArgToArchMap
[A
] : ArchitectureSet();
646 for (const Arg
*A
: ParsedArgs
.filtered(OPT_reexport_framework
)) {
647 LinkerOpts
.ReexportedFrameworks
[A
->getValue()] =
648 ArgToArchMap
.count(A
) ? ArgToArchMap
[A
] : ArchitectureSet();
652 for (const Arg
*A
: ParsedArgs
.filtered(OPT_rpath
)) {
653 LinkerOpts
.RPaths
[A
->getValue()] =
654 ArgToArchMap
.count(A
) ? ArgToArchMap
[A
] : ArchitectureSet();
658 // Handle exclude & extra header directories or files.
659 auto handleAdditionalInputArgs
= [&](PathSeq
&Headers
,
660 clang::installapi::ID OptID
) {
661 if (ParsedArgs
.hasArgNoClaim(OptID
))
663 return addFilePaths(ParsedArgs
, Headers
, OptID
);
666 if (!handleAdditionalInputArgs(DriverOpts
.ExtraPublicHeaders
,
667 OPT_extra_public_header
))
670 if (!handleAdditionalInputArgs(DriverOpts
.ExtraPrivateHeaders
,
671 OPT_extra_private_header
))
673 if (!handleAdditionalInputArgs(DriverOpts
.ExtraProjectHeaders
,
674 OPT_extra_project_header
))
677 if (!handleAdditionalInputArgs(DriverOpts
.ExcludePublicHeaders
,
678 OPT_exclude_public_header
))
680 if (!handleAdditionalInputArgs(DriverOpts
.ExcludePrivateHeaders
,
681 OPT_exclude_private_header
))
683 if (!handleAdditionalInputArgs(DriverOpts
.ExcludeProjectHeaders
,
684 OPT_exclude_project_header
))
687 // Handle umbrella headers.
688 if (const Arg
*A
= ParsedArgs
.getLastArg(OPT_public_umbrella_header
))
689 DriverOpts
.PublicUmbrellaHeader
= A
->getValue();
691 if (const Arg
*A
= ParsedArgs
.getLastArg(OPT_private_umbrella_header
))
692 DriverOpts
.PrivateUmbrellaHeader
= A
->getValue();
694 if (const Arg
*A
= ParsedArgs
.getLastArg(OPT_project_umbrella_header
))
695 DriverOpts
.ProjectUmbrellaHeader
= A
->getValue();
697 /// Any unclaimed arguments should be forwarded to the clang driver.
698 std::vector
<const char *> ClangDriverArgs(ParsedArgs
.size());
699 for (const Arg
*A
: ParsedArgs
) {
702 // Forward along unclaimed but overlapping arguments to the clang driver.
703 if (A
->getOption().getID() > (unsigned)OPT_UNKNOWN
) {
704 ClangDriverArgs
.push_back(A
->getSpelling().data());
706 llvm::copy(A
->getValues(), std::back_inserter(ClangDriverArgs
));
708 return ClangDriverArgs
;
711 Options::Options(DiagnosticsEngine
&Diag
, FileManager
*FM
,
712 ArrayRef
<const char *> Args
, const StringRef ProgName
)
713 : Diags(&Diag
), FM(FM
) {
715 // First process InstallAPI specific options.
716 auto DriverArgs
= processAndFilterOutInstallAPIOptions(Args
);
717 if (Diags
->hasErrorOccurred())
720 // Set up driver to parse remaining input arguments.
721 clang::driver::Driver
Driver(ProgName
, llvm::sys::getDefaultTargetTriple(),
722 *Diags
, "clang installapi tool");
724 clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName
);
725 Driver
.setTargetAndMode(TargetAndMode
);
726 bool HasError
= false;
727 llvm::opt::InputArgList ArgList
=
728 Driver
.ParseArgStrings(DriverArgs
, /*UseDriverMode=*/true, HasError
);
731 Driver
.setCheckInputsExist(false);
733 if (!processDriverOptions(ArgList
))
736 if (!processLinkerOptions(ArgList
))
739 if (!processFrontendOptions(ArgList
))
742 // After all InstallAPI necessary arguments have been collected. Go back and
743 // assign values that were unknown before the clang driver opt table was used.
744 ArchitectureSet AllArchs
;
745 llvm::for_each(DriverOpts
.Targets
,
746 [&AllArchs
](const auto &T
) { AllArchs
.set(T
.first
.Arch
); });
747 auto assignDefaultLibAttrs
= [&AllArchs
](LibAttrs
&Attrs
) {
748 for (StringMapEntry
<ArchitectureSet
> &Entry
: Attrs
)
749 if (Entry
.getValue().empty())
750 Entry
.setValue(AllArchs
);
752 assignDefaultLibAttrs(LinkerOpts
.AllowableClients
);
753 assignDefaultLibAttrs(LinkerOpts
.ReexportedFrameworks
);
754 assignDefaultLibAttrs(LinkerOpts
.ReexportedLibraries
);
755 assignDefaultLibAttrs(LinkerOpts
.ReexportedLibraryPaths
);
756 assignDefaultLibAttrs(LinkerOpts
.RPaths
);
758 /// Force cc1 options that should always be on.
759 FrontendArgs
= {"-fsyntax-only", "-Wprivate-extern"};
761 /// Any unclaimed arguments should be handled by invoking the clang frontend.
762 for (const Arg
*A
: ArgList
) {
765 FrontendArgs
.emplace_back(A
->getSpelling());
766 llvm::copy(A
->getValues(), std::back_inserter(FrontendArgs
));
770 static Expected
<std::unique_ptr
<InterfaceFile
>>
771 getInterfaceFile(const StringRef Filename
) {
772 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> BufferOrErr
=
773 MemoryBuffer::getFile(Filename
);
774 if (auto Err
= BufferOrErr
.getError())
775 return errorCodeToError(std::move(Err
));
777 auto Buffer
= std::move(*BufferOrErr
);
778 std::unique_ptr
<InterfaceFile
> IF
;
779 switch (identify_magic(Buffer
->getBuffer())) {
780 case file_magic::macho_dynamically_linked_shared_lib
:
781 case file_magic::macho_dynamically_linked_shared_lib_stub
:
782 case file_magic::macho_universal_binary
:
783 return DylibReader::get(Buffer
->getMemBufferRef());
785 case file_magic::tapi_file
:
786 return TextAPIReader::get(Buffer
->getMemBufferRef());
788 return make_error
<TextAPIError
>(TextAPIErrorCode::InvalidInputFormat
,
789 "unsupported library file format");
791 llvm_unreachable("unexpected failure in getInterface");
794 std::pair
<LibAttrs
, ReexportedInterfaces
> Options::getReexportedLibraries() {
796 ReexportedInterfaces ReexportIFs
;
797 auto AccumulateReexports
= [&](StringRef Path
, const ArchitectureSet
&Archs
) {
798 auto ReexportIFOrErr
= getInterfaceFile(Path
);
799 if (!ReexportIFOrErr
)
801 std::unique_ptr
<InterfaceFile
> Reexport
= std::move(*ReexportIFOrErr
);
802 StringRef InstallName
= Reexport
->getInstallName();
803 assert(!InstallName
.empty() && "Parse error for install name");
804 Reexports
.insert({InstallName
, Archs
});
805 ReexportIFs
.emplace_back(std::move(*Reexport
));
809 PlatformSet Platforms
;
810 llvm::for_each(DriverOpts
.Targets
,
811 [&](const auto &T
) { Platforms
.insert(T
.first
.Platform
); });
812 // Populate search paths by looking at user paths before system ones.
813 PathSeq
FwkSearchPaths(FEOpts
.FwkPaths
.begin(), FEOpts
.FwkPaths
.end());
814 for (const PlatformType P
: Platforms
) {
815 PathSeq PlatformSearchPaths
= getPathsForPlatform(FEOpts
.SystemFwkPaths
, P
);
816 FwkSearchPaths
.insert(FwkSearchPaths
.end(), PlatformSearchPaths
.begin(),
817 PlatformSearchPaths
.end());
818 for (const StringMapEntry
<ArchitectureSet
> &Lib
:
819 LinkerOpts
.ReexportedFrameworks
) {
820 std::string Name
= (Lib
.getKey() + ".framework/" + Lib
.getKey()).str();
821 std::string Path
= findLibrary(Name
, *FM
, FwkSearchPaths
, {}, {});
823 Diags
->Report(diag::err_cannot_find_reexport
) << false << Lib
.getKey();
826 if (DriverOpts
.TraceLibraryLocation
)
827 errs() << Path
<< "\n";
829 AccumulateReexports(Path
, Lib
.getValue());
831 FwkSearchPaths
.resize(FwkSearchPaths
.size() - PlatformSearchPaths
.size());
834 for (const StringMapEntry
<ArchitectureSet
> &Lib
:
835 LinkerOpts
.ReexportedLibraries
) {
836 std::string Name
= "lib" + Lib
.getKey().str() + ".dylib";
837 std::string Path
= findLibrary(Name
, *FM
, {}, LinkerOpts
.LibPaths
, {});
839 Diags
->Report(diag::err_cannot_find_reexport
) << true << Lib
.getKey();
842 if (DriverOpts
.TraceLibraryLocation
)
843 errs() << Path
<< "\n";
845 AccumulateReexports(Path
, Lib
.getValue());
848 for (const StringMapEntry
<ArchitectureSet
> &Lib
:
849 LinkerOpts
.ReexportedLibraryPaths
)
850 AccumulateReexports(Lib
.getKey(), Lib
.getValue());
852 return {std::move(Reexports
), std::move(ReexportIFs
)};
855 InstallAPIContext
Options::createContext() {
856 InstallAPIContext Ctx
;
860 // InstallAPI requires two level namespacing.
861 Ctx
.BA
.TwoLevelNamespace
= true;
863 Ctx
.BA
.InstallName
= LinkerOpts
.InstallName
;
864 Ctx
.BA
.CurrentVersion
= LinkerOpts
.CurrentVersion
;
865 Ctx
.BA
.CompatVersion
= LinkerOpts
.CompatVersion
;
866 Ctx
.BA
.AppExtensionSafe
= LinkerOpts
.AppExtensionSafe
;
867 Ctx
.BA
.ParentUmbrella
= LinkerOpts
.ParentUmbrella
;
868 Ctx
.BA
.OSLibNotForSharedCache
= LinkerOpts
.OSLibNotForSharedCache
;
869 Ctx
.FT
= DriverOpts
.OutFT
;
870 Ctx
.OutputLoc
= DriverOpts
.OutputPath
;
871 Ctx
.LangMode
= FEOpts
.LangMode
;
873 auto [Reexports
, ReexportedIFs
] = getReexportedLibraries();
874 if (Diags
->hasErrorOccurred())
876 Ctx
.Reexports
= Reexports
;
878 // Collect symbols from alias lists.
880 for (const StringRef ListPath
: LinkerOpts
.AliasLists
) {
881 auto Buffer
= FM
->getBufferForFile(ListPath
);
882 if (auto Err
= Buffer
.getError()) {
883 Diags
->Report(diag::err_cannot_open_file
) << ListPath
<< Err
.message();
886 Expected
<AliasMap
> Result
= parseAliasList(Buffer
.get());
888 Diags
->Report(diag::err_cannot_read_input_list
)
889 << "symbol alias" << ListPath
<< toString(Result
.takeError());
892 Aliases
.insert(Result
.get().begin(), Result
.get().end());
895 // Attempt to find umbrella headers by capturing framework name.
896 StringRef FrameworkName
;
897 if (!LinkerOpts
.IsDylib
)
899 Library::getFrameworkNameFromInstallName(LinkerOpts
.InstallName
);
901 /// Process inputs headers.
902 // 1. For headers discovered by directory scanning, sort them.
903 // 2. For headers discovered by filelist, respect ordering.
904 // 3. Append extra headers and mark any excluded headers.
905 // 4. Finally, surface up umbrella headers to top of the list.
906 if (!DriverOpts
.InputDirectory
.empty()) {
907 DirectoryScanner
Scanner(*FM
, LinkerOpts
.IsDylib
908 ? ScanMode::ScanDylibs
909 : ScanMode::ScanFrameworks
);
910 SmallString
<PATH_MAX
> NormalizedPath(DriverOpts
.InputDirectory
);
911 FM
->getVirtualFileSystem().makeAbsolute(NormalizedPath
);
912 sys::path::remove_dots(NormalizedPath
, /*remove_dot_dot=*/true);
913 if (llvm::Error Err
= Scanner
.scan(NormalizedPath
)) {
914 Diags
->Report(diag::err_directory_scanning
)
915 << DriverOpts
.InputDirectory
<< std::move(Err
);
918 std::vector
<Library
> InputLibraries
= Scanner
.takeLibraries();
919 if (InputLibraries
.size() > 1) {
920 Diags
->Report(diag::err_more_than_one_library
);
923 llvm::append_range(Ctx
.InputHeaders
,
924 DirectoryScanner::getHeaders(InputLibraries
));
925 llvm::stable_sort(Ctx
.InputHeaders
);
928 for (const StringRef ListPath
: DriverOpts
.FileLists
) {
929 auto Buffer
= FM
->getBufferForFile(ListPath
);
930 if (auto Err
= Buffer
.getError()) {
931 Diags
->Report(diag::err_cannot_open_file
) << ListPath
<< Err
.message();
934 if (auto Err
= FileListReader::loadHeaders(std::move(Buffer
.get()),
935 Ctx
.InputHeaders
, FM
)) {
936 Diags
->Report(diag::err_cannot_read_input_list
)
937 << "header file" << ListPath
<< std::move(Err
);
941 // After initial input has been processed, add any extra headers.
942 auto HandleExtraHeaders
= [&](PathSeq
&Headers
, HeaderType Type
) -> bool {
943 assert(Type
!= HeaderType::Unknown
&& "Missing header type.");
944 for (const StringRef Path
: Headers
) {
945 if (!FM
->getOptionalFileRef(Path
)) {
946 Diags
->Report(diag::err_no_such_header_file
) << Path
<< (unsigned)Type
;
949 SmallString
<PATH_MAX
> FullPath(Path
);
950 FM
->makeAbsolutePath(FullPath
);
952 auto IncludeName
= createIncludeHeaderName(FullPath
);
953 Ctx
.InputHeaders
.emplace_back(
954 FullPath
, Type
, IncludeName
.has_value() ? *IncludeName
: "");
955 Ctx
.InputHeaders
.back().setExtra();
960 if (!HandleExtraHeaders(DriverOpts
.ExtraPublicHeaders
, HeaderType::Public
) ||
961 !HandleExtraHeaders(DriverOpts
.ExtraPrivateHeaders
,
962 HeaderType::Private
) ||
963 !HandleExtraHeaders(DriverOpts
.ExtraProjectHeaders
, HeaderType::Project
))
966 // After all headers have been added, consider excluded headers.
967 std::vector
<std::unique_ptr
<HeaderGlob
>> ExcludedHeaderGlobs
;
968 std::set
<FileEntryRef
> ExcludedHeaderFiles
;
969 auto ParseGlobs
= [&](const PathSeq
&Paths
, HeaderType Type
) {
970 assert(Type
!= HeaderType::Unknown
&& "Missing header type.");
971 for (const StringRef Path
: Paths
) {
972 auto Glob
= HeaderGlob::create(Path
, Type
);
974 ExcludedHeaderGlobs
.emplace_back(std::move(Glob
.get()));
976 consumeError(Glob
.takeError());
977 if (auto File
= FM
->getFileRef(Path
))
978 ExcludedHeaderFiles
.emplace(*File
);
980 Diags
->Report(diag::err_no_such_header_file
)
981 << Path
<< (unsigned)Type
;
989 if (!ParseGlobs(DriverOpts
.ExcludePublicHeaders
, HeaderType::Public
) ||
990 !ParseGlobs(DriverOpts
.ExcludePrivateHeaders
, HeaderType::Private
) ||
991 !ParseGlobs(DriverOpts
.ExcludeProjectHeaders
, HeaderType::Project
))
994 for (HeaderFile
&Header
: Ctx
.InputHeaders
) {
995 for (auto &Glob
: ExcludedHeaderGlobs
)
996 if (Glob
->match(Header
))
997 Header
.setExcluded();
999 if (!ExcludedHeaderFiles
.empty()) {
1000 for (HeaderFile
&Header
: Ctx
.InputHeaders
) {
1001 auto FileRef
= FM
->getFileRef(Header
.getPath());
1004 if (ExcludedHeaderFiles
.count(*FileRef
))
1005 Header
.setExcluded();
1008 // Report if glob was ignored.
1009 for (const auto &Glob
: ExcludedHeaderGlobs
)
1010 if (!Glob
->didMatch())
1011 Diags
->Report(diag::warn_glob_did_not_match
) << Glob
->str();
1013 // Mark any explicit or inferred umbrella headers. If one exists, move
1014 // that to the beginning of the input headers.
1015 auto MarkandMoveUmbrellaInHeaders
= [&](llvm::Regex
&Regex
,
1016 HeaderType Type
) -> bool {
1017 auto It
= find_if(Ctx
.InputHeaders
, [&Regex
, Type
](const HeaderFile
&H
) {
1018 return (H
.getType() == Type
) && Regex
.match(H
.getPath());
1021 if (It
== Ctx
.InputHeaders
.end())
1023 It
->setUmbrellaHeader();
1025 // Because there can be an umbrella header per header type,
1026 // find the first non umbrella header to swap position with.
1027 auto BeginPos
= find_if(Ctx
.InputHeaders
, [](const HeaderFile
&H
) {
1028 return !H
.isUmbrellaHeader();
1030 if (BeginPos
!= Ctx
.InputHeaders
.end() && BeginPos
< It
)
1031 std::swap(*BeginPos
, *It
);
1035 auto FindUmbrellaHeader
= [&](StringRef HeaderPath
, HeaderType Type
) -> bool {
1036 assert(Type
!= HeaderType::Unknown
&& "Missing header type.");
1037 if (!HeaderPath
.empty()) {
1038 auto EscapedString
= Regex::escape(HeaderPath
);
1039 Regex
UmbrellaRegex(EscapedString
);
1040 if (!MarkandMoveUmbrellaInHeaders(UmbrellaRegex
, Type
)) {
1041 Diags
->Report(diag::err_no_such_umbrella_header_file
)
1042 << HeaderPath
<< (unsigned)Type
;
1045 } else if (!FrameworkName
.empty() && (Type
!= HeaderType::Project
)) {
1046 auto UmbrellaName
= "/" + Regex::escape(FrameworkName
);
1047 if (Type
== HeaderType::Public
)
1048 UmbrellaName
+= "\\.h";
1050 UmbrellaName
+= "[_]?Private\\.h";
1051 Regex
UmbrellaRegex(UmbrellaName
);
1052 MarkandMoveUmbrellaInHeaders(UmbrellaRegex
, Type
);
1056 if (!FindUmbrellaHeader(DriverOpts
.PublicUmbrellaHeader
,
1057 HeaderType::Public
) ||
1058 !FindUmbrellaHeader(DriverOpts
.PrivateUmbrellaHeader
,
1059 HeaderType::Private
) ||
1060 !FindUmbrellaHeader(DriverOpts
.ProjectUmbrellaHeader
,
1061 HeaderType::Project
))
1064 // Parse binary dylib and initialize verifier.
1065 if (DriverOpts
.DylibToVerify
.empty()) {
1066 Ctx
.Verifier
= std::make_unique
<DylibVerifier
>();
1070 auto Buffer
= FM
->getBufferForFile(DriverOpts
.DylibToVerify
);
1071 if (auto Err
= Buffer
.getError()) {
1072 Diags
->Report(diag::err_cannot_open_file
)
1073 << DriverOpts
.DylibToVerify
<< Err
.message();
1077 DylibReader::ParseOption PO
;
1078 PO
.Undefineds
= false;
1079 Expected
<Records
> Slices
=
1080 DylibReader::readFile((*Buffer
)->getMemBufferRef(), PO
);
1081 if (auto Err
= Slices
.takeError()) {
1082 Diags
->Report(diag::err_cannot_open_file
)
1083 << DriverOpts
.DylibToVerify
<< std::move(Err
);
1087 Ctx
.Verifier
= std::make_unique
<DylibVerifier
>(
1088 std::move(*Slices
), std::move(ReexportedIFs
), std::move(Aliases
), Diags
,
1089 DriverOpts
.VerifyMode
, DriverOpts
.Zippered
, DriverOpts
.Demangle
,
1090 DriverOpts
.DSYMPath
);
1094 void Options::addConditionalCC1Args(std::vector
<std::string
> &ArgStrings
,
1095 const llvm::Triple
&Targ
,
1096 const HeaderType Type
) {
1097 // Unique to architecture (Xarch) options hold no arguments to pass along for
1100 // Add specific to platform arguments.
1101 PathSeq PlatformSearchPaths
=
1102 getPathsForPlatform(FEOpts
.SystemFwkPaths
, mapToPlatformType(Targ
));
1103 llvm::for_each(PlatformSearchPaths
, [&ArgStrings
](const StringRef Path
) {
1104 ArgStrings
.push_back("-iframework");
1105 ArgStrings
.push_back(Path
.str());
1108 // Add specific to header type arguments.
1109 if (Type
== HeaderType::Project
)
1110 for (const StringRef A
: ProjectLevelArgs
)
1111 ArgStrings
.emplace_back(A
);
1114 } // namespace installapi
1115 } // namespace clang