10a518db9SCyndy Ishida //===-- Options.cpp -------------------------------------------------------===// 20a518db9SCyndy Ishida // 30a518db9SCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40a518db9SCyndy Ishida // See https://llvm.org/LICENSE.txt for license information. 50a518db9SCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60a518db9SCyndy Ishida // 70a518db9SCyndy Ishida //===----------------------------------------------------------------------===// 80a518db9SCyndy Ishida 90a518db9SCyndy Ishida #include "Options.h" 1027b2d7d4SCyndy Ishida #include "clang/Basic/DiagnosticIDs.h" 110a518db9SCyndy Ishida #include "clang/Driver/Driver.h" 12feed66f3SCyndy Ishida #include "clang/InstallAPI/DirectoryScanner.h" 13c6cbf81cSCyndy Ishida #include "clang/InstallAPI/FileList.h" 14487720fcSCyndy Ishida #include "clang/InstallAPI/HeaderFile.h" 15c51095f5SCyndy Ishida #include "clang/InstallAPI/InstallAPIDiagnostic.h" 1627b2d7d4SCyndy Ishida #include "llvm/BinaryFormat/Magic.h" 17c9dc52d4SCyndy Ishida #include "llvm/Support/JSON.h" 180a518db9SCyndy Ishida #include "llvm/Support/Program.h" 190a518db9SCyndy Ishida #include "llvm/TargetParser/Host.h" 20c51095f5SCyndy Ishida #include "llvm/TextAPI/DylibReader.h" 2127b2d7d4SCyndy Ishida #include "llvm/TextAPI/TextAPIError.h" 2227b2d7d4SCyndy Ishida #include "llvm/TextAPI/TextAPIReader.h" 23c51095f5SCyndy Ishida #include "llvm/TextAPI/TextAPIWriter.h" 240a518db9SCyndy Ishida 25c51095f5SCyndy Ishida using namespace llvm; 260a518db9SCyndy Ishida using namespace llvm::opt; 270a518db9SCyndy Ishida using namespace llvm::MachO; 280a518db9SCyndy Ishida 29c51095f5SCyndy Ishida namespace drv = clang::driver::options; 30c51095f5SCyndy Ishida 310a518db9SCyndy Ishida namespace clang { 320a518db9SCyndy Ishida namespace installapi { 330a518db9SCyndy Ishida 34*dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE 35c51095f5SCyndy Ishida #include "InstallAPIOpts.inc" 36*dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE 37c51095f5SCyndy Ishida 38*dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE 39c51095f5SCyndy Ishida #include "InstallAPIOpts.inc" 40*dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE 41*dd647e3eSChandler Carruth 42*dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_UNION_CODE 43*dd647e3eSChandler Carruth #include "InstallAPIOpts.inc" 44*dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_UNION_CODE 45c51095f5SCyndy Ishida 46c51095f5SCyndy Ishida /// Create table mapping all options defined in InstallAPIOpts.td. 47c51095f5SCyndy Ishida static constexpr OptTable::Info InfoTable[] = { 48*dd647e3eSChandler Carruth #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), 49c51095f5SCyndy Ishida #include "InstallAPIOpts.inc" 50c51095f5SCyndy Ishida #undef OPTION 51c51095f5SCyndy Ishida }; 52c51095f5SCyndy Ishida 53c51095f5SCyndy Ishida namespace { 54c51095f5SCyndy Ishida 55c51095f5SCyndy Ishida /// \brief Create OptTable class for parsing actual command line arguments. 56c51095f5SCyndy Ishida class DriverOptTable : public opt::PrecomputedOptTable { 57c51095f5SCyndy Ishida public: 58*dd647e3eSChandler Carruth DriverOptTable() 59*dd647e3eSChandler Carruth : PrecomputedOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, 60*dd647e3eSChandler Carruth OptionPrefixesUnion) {} 61c51095f5SCyndy Ishida }; 62c51095f5SCyndy Ishida 63c51095f5SCyndy Ishida } // end anonymous namespace. 64c51095f5SCyndy Ishida 65c51095f5SCyndy Ishida static llvm::opt::OptTable *createDriverOptTable() { 66c51095f5SCyndy Ishida return new DriverOptTable(); 67c51095f5SCyndy Ishida } 68c51095f5SCyndy Ishida 69c9dc52d4SCyndy Ishida /// Parse JSON input into argument list. 70c9dc52d4SCyndy Ishida /// 71c9dc52d4SCyndy Ishida /* Expected input format. 72c9dc52d4SCyndy Ishida * { "label" : ["-ClangArg1", "-ClangArg2"] } 73c9dc52d4SCyndy Ishida */ 74c9dc52d4SCyndy Ishida /// 75c9dc52d4SCyndy Ishida /// Input is interpreted as "-Xlabel ClangArg1 -XLabel ClangArg2". 76c9dc52d4SCyndy Ishida static Expected<llvm::opt::InputArgList> 77c9dc52d4SCyndy Ishida getArgListFromJSON(const StringRef Input, llvm::opt::OptTable *Table, 78c9dc52d4SCyndy Ishida std::vector<std::string> &Storage) { 79c9dc52d4SCyndy Ishida using namespace json; 80c9dc52d4SCyndy Ishida Expected<Value> ValOrErr = json::parse(Input); 81c9dc52d4SCyndy Ishida if (!ValOrErr) 82c9dc52d4SCyndy Ishida return ValOrErr.takeError(); 83c9dc52d4SCyndy Ishida 84c9dc52d4SCyndy Ishida const Object *Root = ValOrErr->getAsObject(); 85c9dc52d4SCyndy Ishida if (!Root) 86c9dc52d4SCyndy Ishida return llvm::opt::InputArgList(); 87c9dc52d4SCyndy Ishida 88c9dc52d4SCyndy Ishida for (const auto &KV : *Root) { 89c9dc52d4SCyndy Ishida const Array *ArgList = KV.getSecond().getAsArray(); 90c9dc52d4SCyndy Ishida std::string Label = "-X" + KV.getFirst().str(); 91c9dc52d4SCyndy Ishida if (!ArgList) 92c9dc52d4SCyndy Ishida return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat); 93c9dc52d4SCyndy Ishida for (auto Arg : *ArgList) { 94c9dc52d4SCyndy Ishida std::optional<StringRef> ArgStr = Arg.getAsString(); 95c9dc52d4SCyndy Ishida if (!ArgStr) 96c9dc52d4SCyndy Ishida return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat); 97c9dc52d4SCyndy Ishida Storage.emplace_back(Label); 98c9dc52d4SCyndy Ishida Storage.emplace_back(*ArgStr); 99c9dc52d4SCyndy Ishida } 100c9dc52d4SCyndy Ishida } 101c9dc52d4SCyndy Ishida 102c9dc52d4SCyndy Ishida std::vector<const char *> CArgs(Storage.size()); 103c9dc52d4SCyndy Ishida llvm::for_each(Storage, 104c9dc52d4SCyndy Ishida [&CArgs](StringRef Str) { CArgs.emplace_back(Str.data()); }); 105c9dc52d4SCyndy Ishida 106c9dc52d4SCyndy Ishida unsigned MissingArgIndex, MissingArgCount; 107c9dc52d4SCyndy Ishida return Table->ParseArgs(CArgs, MissingArgIndex, MissingArgCount); 108c9dc52d4SCyndy Ishida } 109c9dc52d4SCyndy Ishida 1100a518db9SCyndy Ishida bool Options::processDriverOptions(InputArgList &Args) { 1110a518db9SCyndy Ishida // Handle inputs. 112feed66f3SCyndy Ishida for (const StringRef Path : Args.getAllArgValues(drv::OPT_INPUT)) { 113feed66f3SCyndy Ishida // Assume any input that is not a directory is a filelist. 114feed66f3SCyndy Ishida // InstallAPI does not accept multiple directories, so retain the last one. 115feed66f3SCyndy Ishida if (FM->getOptionalDirectoryRef(Path)) 116feed66f3SCyndy Ishida DriverOpts.InputDirectory = Path.str(); 117feed66f3SCyndy Ishida else 118feed66f3SCyndy Ishida DriverOpts.FileLists.emplace_back(Path.str()); 119feed66f3SCyndy Ishida } 1200a518db9SCyndy Ishida 1210a518db9SCyndy Ishida // Handle output. 1220a518db9SCyndy Ishida SmallString<PATH_MAX> OutputPath; 123c51095f5SCyndy Ishida if (auto *Arg = Args.getLastArg(drv::OPT_o)) { 1240a518db9SCyndy Ishida OutputPath = Arg->getValue(); 1250a518db9SCyndy Ishida if (OutputPath != "-") 1260a518db9SCyndy Ishida FM->makeAbsolutePath(OutputPath); 1270a518db9SCyndy Ishida DriverOpts.OutputPath = std::string(OutputPath); 1280a518db9SCyndy Ishida } 129c51095f5SCyndy Ishida if (DriverOpts.OutputPath.empty()) { 130c51095f5SCyndy Ishida Diags->Report(diag::err_no_output_file); 131c51095f5SCyndy Ishida return false; 132c51095f5SCyndy Ishida } 1330a518db9SCyndy Ishida 1340a518db9SCyndy Ishida // Do basic error checking first for mixing -target and -arch options. 135c51095f5SCyndy Ishida auto *ArgArch = Args.getLastArgNoClaim(drv::OPT_arch); 136c51095f5SCyndy Ishida auto *ArgTarget = Args.getLastArgNoClaim(drv::OPT_target); 1370a518db9SCyndy Ishida auto *ArgTargetVariant = 138c24efffaSCyndy Ishida Args.getLastArgNoClaim(drv::OPT_darwin_target_variant); 1390a518db9SCyndy Ishida if (ArgArch && (ArgTarget || ArgTargetVariant)) { 1400a518db9SCyndy Ishida Diags->Report(clang::diag::err_drv_argument_not_allowed_with) 1410a518db9SCyndy Ishida << ArgArch->getAsString(Args) 1420a518db9SCyndy Ishida << (ArgTarget ? ArgTarget : ArgTargetVariant)->getAsString(Args); 1430a518db9SCyndy Ishida return false; 1440a518db9SCyndy Ishida } 1450a518db9SCyndy Ishida 146c51095f5SCyndy Ishida auto *ArgMinTargetOS = Args.getLastArgNoClaim(drv::OPT_mtargetos_EQ); 1470a518db9SCyndy Ishida if ((ArgTarget || ArgTargetVariant) && ArgMinTargetOS) { 1480a518db9SCyndy Ishida Diags->Report(clang::diag::err_drv_cannot_mix_options) 1490a518db9SCyndy Ishida << ArgTarget->getAsString(Args) << ArgMinTargetOS->getAsString(Args); 1500a518db9SCyndy Ishida return false; 1510a518db9SCyndy Ishida } 1520a518db9SCyndy Ishida 1530a518db9SCyndy Ishida // Capture target triples first. 1540a518db9SCyndy Ishida if (ArgTarget) { 155c51095f5SCyndy Ishida for (const Arg *A : Args.filtered(drv::OPT_target)) { 156828bf134SCyndy Ishida A->claim(); 157828bf134SCyndy Ishida llvm::Triple TargetTriple(A->getValue()); 1580a518db9SCyndy Ishida Target TAPITarget = Target(TargetTriple); 1590a518db9SCyndy Ishida if ((TAPITarget.Arch == AK_unknown) || 1600a518db9SCyndy Ishida (TAPITarget.Platform == PLATFORM_UNKNOWN)) { 1610a518db9SCyndy Ishida Diags->Report(clang::diag::err_drv_unsupported_opt_for_target) 1620a518db9SCyndy Ishida << "installapi" << TargetTriple.str(); 1630a518db9SCyndy Ishida return false; 1640a518db9SCyndy Ishida } 1650a518db9SCyndy Ishida DriverOpts.Targets[TAPITarget] = TargetTriple; 1660a518db9SCyndy Ishida } 1670a518db9SCyndy Ishida } 1680a518db9SCyndy Ishida 169c24efffaSCyndy Ishida // Capture target variants. 170c24efffaSCyndy Ishida DriverOpts.Zippered = ArgTargetVariant != nullptr; 171c24efffaSCyndy Ishida for (Arg *A : Args.filtered(drv::OPT_darwin_target_variant)) { 172c24efffaSCyndy Ishida A->claim(); 173c24efffaSCyndy Ishida Triple Variant(A->getValue()); 174c24efffaSCyndy Ishida if (Variant.getVendor() != Triple::Apple) { 175c24efffaSCyndy Ishida Diags->Report(diag::err_unsupported_vendor) 176c24efffaSCyndy Ishida << Variant.getVendorName() << A->getAsString(Args); 177c24efffaSCyndy Ishida return false; 178c24efffaSCyndy Ishida } 179c24efffaSCyndy Ishida 180c24efffaSCyndy Ishida switch (Variant.getOS()) { 181c24efffaSCyndy Ishida default: 182c24efffaSCyndy Ishida Diags->Report(diag::err_unsupported_os) 183c24efffaSCyndy Ishida << Variant.getOSName() << A->getAsString(Args); 184c24efffaSCyndy Ishida return false; 185c24efffaSCyndy Ishida case Triple::MacOSX: 186c24efffaSCyndy Ishida case Triple::IOS: 187c24efffaSCyndy Ishida break; 188c24efffaSCyndy Ishida } 189c24efffaSCyndy Ishida 190c24efffaSCyndy Ishida switch (Variant.getEnvironment()) { 191c24efffaSCyndy Ishida default: 192c24efffaSCyndy Ishida Diags->Report(diag::err_unsupported_environment) 193c24efffaSCyndy Ishida << Variant.getEnvironmentName() << A->getAsString(Args); 194c24efffaSCyndy Ishida return false; 195c24efffaSCyndy Ishida case Triple::UnknownEnvironment: 196c24efffaSCyndy Ishida case Triple::MacABI: 197c24efffaSCyndy Ishida break; 198c24efffaSCyndy Ishida } 199c24efffaSCyndy Ishida 200c24efffaSCyndy Ishida Target TAPIVariant(Variant); 201c24efffaSCyndy Ishida // See if there is a matching --target option for this --target-variant 202c24efffaSCyndy Ishida // option. 203c24efffaSCyndy Ishida auto It = find_if(DriverOpts.Targets, [&](const auto &T) { 204c24efffaSCyndy Ishida return (T.first.Arch == TAPIVariant.Arch) && 205c24efffaSCyndy Ishida (T.first.Platform != PlatformType::PLATFORM_UNKNOWN); 206c24efffaSCyndy Ishida }); 207c24efffaSCyndy Ishida 208c24efffaSCyndy Ishida if (It == DriverOpts.Targets.end()) { 209c24efffaSCyndy Ishida Diags->Report(diag::err_no_matching_target) << Variant.str(); 210c24efffaSCyndy Ishida return false; 211c24efffaSCyndy Ishida } 212c24efffaSCyndy Ishida 213c24efffaSCyndy Ishida DriverOpts.Targets[TAPIVariant] = Variant; 214c24efffaSCyndy Ishida } 215c24efffaSCyndy Ishida 216c51095f5SCyndy Ishida DriverOpts.Verbose = Args.hasArgNoClaim(drv::OPT_v); 217c6cbf81cSCyndy Ishida 2180a518db9SCyndy Ishida return true; 2190a518db9SCyndy Ishida } 2200a518db9SCyndy Ishida 22127b2d7d4SCyndy Ishida bool Options::processInstallAPIXOptions(InputArgList &Args) { 22227b2d7d4SCyndy Ishida for (arg_iterator It = Args.begin(), End = Args.end(); It != End; ++It) { 223062f6fe3SCyndy Ishida Arg *A = *It; 224062f6fe3SCyndy Ishida if (A->getOption().matches(OPT_Xarch__)) { 22527b2d7d4SCyndy Ishida if (!processXarchOption(Args, It)) 22627b2d7d4SCyndy Ishida return false; 227062f6fe3SCyndy Ishida continue; 228062f6fe3SCyndy Ishida } else if (A->getOption().matches(OPT_Xplatform__)) { 229062f6fe3SCyndy Ishida if (!processXplatformOption(Args, It)) 230062f6fe3SCyndy Ishida return false; 231062f6fe3SCyndy Ishida continue; 232062f6fe3SCyndy Ishida } else if (A->getOption().matches(OPT_Xproject)) { 233062f6fe3SCyndy Ishida if (!processXprojectOption(Args, It)) 234062f6fe3SCyndy Ishida return false; 235062f6fe3SCyndy Ishida continue; 236062f6fe3SCyndy Ishida } else if (!A->getOption().matches(OPT_X__)) 237062f6fe3SCyndy Ishida continue; 238062f6fe3SCyndy Ishida 239062f6fe3SCyndy Ishida // Handle any user defined labels. 240062f6fe3SCyndy Ishida const StringRef Label = A->getValue(0); 241062f6fe3SCyndy Ishida 242062f6fe3SCyndy Ishida // Ban "public" and "private" labels. 243062f6fe3SCyndy Ishida if ((Label.lower() == "public") || (Label.lower() == "private")) { 244062f6fe3SCyndy Ishida Diags->Report(diag::err_invalid_label) << Label; 245062f6fe3SCyndy Ishida return false; 24627b2d7d4SCyndy Ishida } 247062f6fe3SCyndy Ishida 248062f6fe3SCyndy Ishida auto NextIt = std::next(It); 249062f6fe3SCyndy Ishida if (NextIt == End) { 250062f6fe3SCyndy Ishida Diags->Report(clang::diag::err_drv_missing_argument) 251062f6fe3SCyndy Ishida << A->getAsString(Args) << 1; 252062f6fe3SCyndy Ishida return false; 25327b2d7d4SCyndy Ishida } 254062f6fe3SCyndy Ishida Arg *NextA = *NextIt; 255062f6fe3SCyndy Ishida switch ((ID)NextA->getOption().getID()) { 256062f6fe3SCyndy Ishida case OPT_D: 257062f6fe3SCyndy Ishida case OPT_U: 258062f6fe3SCyndy Ishida break; 259062f6fe3SCyndy Ishida default: 260062f6fe3SCyndy Ishida Diags->Report(clang::diag::err_drv_argument_not_allowed_with) 261062f6fe3SCyndy Ishida << A->getAsString(Args) << NextA->getAsString(Args); 262062f6fe3SCyndy Ishida return false; 263062f6fe3SCyndy Ishida } 264062f6fe3SCyndy Ishida const StringRef ASpelling = NextA->getSpelling(); 265062f6fe3SCyndy Ishida const auto &AValues = NextA->getValues(); 266062f6fe3SCyndy Ishida if (AValues.empty()) 267062f6fe3SCyndy Ishida FEOpts.UniqueArgs[Label].emplace_back(ASpelling.str()); 268062f6fe3SCyndy Ishida else 269062f6fe3SCyndy Ishida for (const StringRef Val : AValues) 270062f6fe3SCyndy Ishida FEOpts.UniqueArgs[Label].emplace_back((ASpelling + Val).str()); 271062f6fe3SCyndy Ishida 272062f6fe3SCyndy Ishida A->claim(); 273062f6fe3SCyndy Ishida NextA->claim(); 274062f6fe3SCyndy Ishida } 275062f6fe3SCyndy Ishida 276062f6fe3SCyndy Ishida return true; 277062f6fe3SCyndy Ishida } 278062f6fe3SCyndy Ishida 279062f6fe3SCyndy Ishida bool Options::processXplatformOption(InputArgList &Args, arg_iterator Curr) { 280062f6fe3SCyndy Ishida Arg *A = *Curr; 281062f6fe3SCyndy Ishida 282062f6fe3SCyndy Ishida PlatformType Platform = getPlatformFromName(A->getValue(0)); 283062f6fe3SCyndy Ishida if (Platform == PLATFORM_UNKNOWN) { 284062f6fe3SCyndy Ishida Diags->Report(diag::err_unsupported_os) 285062f6fe3SCyndy Ishida << getPlatformName(Platform) << A->getAsString(Args); 286062f6fe3SCyndy Ishida return false; 287062f6fe3SCyndy Ishida } 288062f6fe3SCyndy Ishida auto NextIt = std::next(Curr); 289062f6fe3SCyndy Ishida if (NextIt == Args.end()) { 290062f6fe3SCyndy Ishida Diags->Report(diag::err_drv_missing_argument) << A->getAsString(Args) << 1; 291062f6fe3SCyndy Ishida return false; 292062f6fe3SCyndy Ishida } 293062f6fe3SCyndy Ishida 294062f6fe3SCyndy Ishida Arg *NextA = *NextIt; 295062f6fe3SCyndy Ishida switch ((ID)NextA->getOption().getID()) { 296062f6fe3SCyndy Ishida case OPT_iframework: 297062f6fe3SCyndy Ishida FEOpts.SystemFwkPaths.emplace_back(NextA->getValue(), Platform); 298062f6fe3SCyndy Ishida break; 299062f6fe3SCyndy Ishida default: 300062f6fe3SCyndy Ishida Diags->Report(diag::err_drv_invalid_argument_to_option) 301062f6fe3SCyndy Ishida << A->getAsString(Args) << NextA->getAsString(Args); 302062f6fe3SCyndy Ishida return false; 303062f6fe3SCyndy Ishida } 304062f6fe3SCyndy Ishida 305062f6fe3SCyndy Ishida A->claim(); 306062f6fe3SCyndy Ishida NextA->claim(); 307062f6fe3SCyndy Ishida 308062f6fe3SCyndy Ishida return true; 309062f6fe3SCyndy Ishida } 310062f6fe3SCyndy Ishida 311062f6fe3SCyndy Ishida bool Options::processXprojectOption(InputArgList &Args, arg_iterator Curr) { 312062f6fe3SCyndy Ishida Arg *A = *Curr; 313062f6fe3SCyndy Ishida auto NextIt = std::next(Curr); 314062f6fe3SCyndy Ishida if (NextIt == Args.end()) { 315062f6fe3SCyndy Ishida Diags->Report(diag::err_drv_missing_argument) << A->getAsString(Args) << 1; 316062f6fe3SCyndy Ishida return false; 317062f6fe3SCyndy Ishida } 318062f6fe3SCyndy Ishida 319062f6fe3SCyndy Ishida Arg *NextA = *NextIt; 320062f6fe3SCyndy Ishida switch ((ID)NextA->getOption().getID()) { 321062f6fe3SCyndy Ishida case OPT_fobjc_arc: 322062f6fe3SCyndy Ishida case OPT_fmodules: 323062f6fe3SCyndy Ishida case OPT_fmodules_cache_path: 324062f6fe3SCyndy Ishida case OPT_include_: 325062f6fe3SCyndy Ishida case OPT_fvisibility_EQ: 326062f6fe3SCyndy Ishida break; 327062f6fe3SCyndy Ishida default: 328062f6fe3SCyndy Ishida Diags->Report(diag::err_drv_argument_not_allowed_with) 329062f6fe3SCyndy Ishida << A->getAsString(Args) << NextA->getAsString(Args); 330062f6fe3SCyndy Ishida return false; 331062f6fe3SCyndy Ishida } 332062f6fe3SCyndy Ishida 333504cf554SCyndy Ishida std::string ArgString = NextA->getSpelling().str(); 334504cf554SCyndy Ishida for (const StringRef Val : NextA->getValues()) 335504cf554SCyndy Ishida ArgString += Val.str(); 336504cf554SCyndy Ishida 337504cf554SCyndy Ishida ProjectLevelArgs.push_back(ArgString); 338062f6fe3SCyndy Ishida A->claim(); 339062f6fe3SCyndy Ishida NextA->claim(); 34027b2d7d4SCyndy Ishida 34127b2d7d4SCyndy Ishida return true; 34227b2d7d4SCyndy Ishida } 34327b2d7d4SCyndy Ishida 34427b2d7d4SCyndy Ishida bool Options::processXarchOption(InputArgList &Args, arg_iterator Curr) { 34527b2d7d4SCyndy Ishida Arg *CurrArg = *Curr; 34627b2d7d4SCyndy Ishida Architecture Arch = getArchitectureFromName(CurrArg->getValue(0)); 34727b2d7d4SCyndy Ishida if (Arch == AK_unknown) { 34827b2d7d4SCyndy Ishida Diags->Report(diag::err_drv_invalid_arch_name) 34927b2d7d4SCyndy Ishida << CurrArg->getAsString(Args); 35027b2d7d4SCyndy Ishida return false; 35127b2d7d4SCyndy Ishida } 35227b2d7d4SCyndy Ishida 35327b2d7d4SCyndy Ishida auto NextIt = std::next(Curr); 35427b2d7d4SCyndy Ishida if (NextIt == Args.end()) { 35527b2d7d4SCyndy Ishida Diags->Report(diag::err_drv_missing_argument) 35627b2d7d4SCyndy Ishida << CurrArg->getAsString(Args) << 1; 35727b2d7d4SCyndy Ishida return false; 35827b2d7d4SCyndy Ishida } 35927b2d7d4SCyndy Ishida 36027b2d7d4SCyndy Ishida // InstallAPI has a limited understanding of supported Xarch options. 36127b2d7d4SCyndy Ishida // Currently this is restricted to linker inputs. 36227b2d7d4SCyndy Ishida const Arg *NextArg = *NextIt; 36327b2d7d4SCyndy Ishida switch (NextArg->getOption().getID()) { 36427b2d7d4SCyndy Ishida case OPT_allowable_client: 36527b2d7d4SCyndy Ishida case OPT_reexport_l: 36627b2d7d4SCyndy Ishida case OPT_reexport_framework: 36727b2d7d4SCyndy Ishida case OPT_reexport_library: 36827b2d7d4SCyndy Ishida case OPT_rpath: 36927b2d7d4SCyndy Ishida break; 37027b2d7d4SCyndy Ishida default: 37127b2d7d4SCyndy Ishida Diags->Report(diag::err_drv_invalid_argument_to_option) 37227b2d7d4SCyndy Ishida << NextArg->getAsString(Args) << CurrArg->getAsString(Args); 37327b2d7d4SCyndy Ishida return false; 37427b2d7d4SCyndy Ishida } 37527b2d7d4SCyndy Ishida 37627b2d7d4SCyndy Ishida ArgToArchMap[NextArg] = Arch; 37727b2d7d4SCyndy Ishida CurrArg->claim(); 37827b2d7d4SCyndy Ishida 37927b2d7d4SCyndy Ishida return true; 38027b2d7d4SCyndy Ishida } 38127b2d7d4SCyndy Ishida 382c9dc52d4SCyndy Ishida bool Options::processOptionList(InputArgList &Args, 383c9dc52d4SCyndy Ishida llvm::opt::OptTable *Table) { 384c9dc52d4SCyndy Ishida Arg *A = Args.getLastArg(OPT_option_list); 385c9dc52d4SCyndy Ishida if (!A) 386c9dc52d4SCyndy Ishida return true; 387c9dc52d4SCyndy Ishida 388c9dc52d4SCyndy Ishida const StringRef Path = A->getValue(0); 389c9dc52d4SCyndy Ishida auto InputOrErr = FM->getBufferForFile(Path); 390c9dc52d4SCyndy Ishida if (auto Err = InputOrErr.getError()) { 391c9dc52d4SCyndy Ishida Diags->Report(diag::err_cannot_open_file) << Path << Err.message(); 392c9dc52d4SCyndy Ishida return false; 393c9dc52d4SCyndy Ishida } 394c9dc52d4SCyndy Ishida // Backing storage referenced for argument processing. 395c9dc52d4SCyndy Ishida std::vector<std::string> Storage; 396c9dc52d4SCyndy Ishida auto ArgsOrErr = 397c9dc52d4SCyndy Ishida getArgListFromJSON((*InputOrErr)->getBuffer(), Table, Storage); 398c9dc52d4SCyndy Ishida 399c9dc52d4SCyndy Ishida if (auto Err = ArgsOrErr.takeError()) { 400c9dc52d4SCyndy Ishida Diags->Report(diag::err_cannot_read_input_list) 401c9dc52d4SCyndy Ishida << "option" << Path << toString(std::move(Err)); 402c9dc52d4SCyndy Ishida return false; 403c9dc52d4SCyndy Ishida } 404c9dc52d4SCyndy Ishida return processInstallAPIXOptions(*ArgsOrErr); 405c9dc52d4SCyndy Ishida } 406c9dc52d4SCyndy Ishida 4070a518db9SCyndy Ishida bool Options::processLinkerOptions(InputArgList &Args) { 408c51095f5SCyndy Ishida // Handle required arguments. 409c51095f5SCyndy Ishida if (const Arg *A = Args.getLastArg(drv::OPT_install__name)) 4100a518db9SCyndy Ishida LinkerOpts.InstallName = A->getValue(); 411c51095f5SCyndy Ishida if (LinkerOpts.InstallName.empty()) { 412c51095f5SCyndy Ishida Diags->Report(diag::err_no_install_name); 413c51095f5SCyndy Ishida return false; 414c51095f5SCyndy Ishida } 4150a518db9SCyndy Ishida 4160a518db9SCyndy Ishida // Defaulted or optional arguments. 417c51095f5SCyndy Ishida if (auto *Arg = Args.getLastArg(drv::OPT_current__version)) 4180a518db9SCyndy Ishida LinkerOpts.CurrentVersion.parse64(Arg->getValue()); 4190a518db9SCyndy Ishida 420c51095f5SCyndy Ishida if (auto *Arg = Args.getLastArg(drv::OPT_compatibility__version)) 421b058b7e6SCyndy Ishida LinkerOpts.CompatVersion.parse64(Arg->getValue()); 422b058b7e6SCyndy Ishida 42327b2d7d4SCyndy Ishida if (auto *Arg = Args.getLastArg(drv::OPT_compatibility__version)) 42427b2d7d4SCyndy Ishida LinkerOpts.CompatVersion.parse64(Arg->getValue()); 42527b2d7d4SCyndy Ishida 42627b2d7d4SCyndy Ishida if (auto *Arg = Args.getLastArg(drv::OPT_umbrella)) 42727b2d7d4SCyndy Ishida LinkerOpts.ParentUmbrella = Arg->getValue(); 42827b2d7d4SCyndy Ishida 429c51095f5SCyndy Ishida LinkerOpts.IsDylib = Args.hasArg(drv::OPT_dynamiclib); 4300a518db9SCyndy Ishida 4314c18681aSCyndy Ishida for (auto *Arg : Args.filtered(drv::OPT_alias_list)) { 4324c18681aSCyndy Ishida LinkerOpts.AliasLists.emplace_back(Arg->getValue()); 4334c18681aSCyndy Ishida Arg->claim(); 4344c18681aSCyndy Ishida } 4354c18681aSCyndy Ishida 436c51095f5SCyndy Ishida LinkerOpts.AppExtensionSafe = Args.hasFlag( 437c51095f5SCyndy Ishida drv::OPT_fapplication_extension, drv::OPT_fno_application_extension, 4380a518db9SCyndy Ishida /*Default=*/LinkerOpts.AppExtensionSafe); 4390a518db9SCyndy Ishida 4400a518db9SCyndy Ishida if (::getenv("LD_NO_ENCRYPT") != nullptr) 4410a518db9SCyndy Ishida LinkerOpts.AppExtensionSafe = true; 4420a518db9SCyndy Ishida 4430a518db9SCyndy Ishida if (::getenv("LD_APPLICATION_EXTENSION_SAFE") != nullptr) 4440a518db9SCyndy Ishida LinkerOpts.AppExtensionSafe = true; 44527b2d7d4SCyndy Ishida 44627b2d7d4SCyndy Ishida // Capture library paths. 44727b2d7d4SCyndy Ishida PathSeq LibraryPaths; 44827b2d7d4SCyndy Ishida for (const Arg *A : Args.filtered(drv::OPT_L)) { 44927b2d7d4SCyndy Ishida LibraryPaths.emplace_back(A->getValue()); 45027b2d7d4SCyndy Ishida A->claim(); 45127b2d7d4SCyndy Ishida } 45227b2d7d4SCyndy Ishida 45327b2d7d4SCyndy Ishida if (!LibraryPaths.empty()) 45427b2d7d4SCyndy Ishida LinkerOpts.LibPaths = std::move(LibraryPaths); 45527b2d7d4SCyndy Ishida 4560a518db9SCyndy Ishida return true; 4570a518db9SCyndy Ishida } 4580a518db9SCyndy Ishida 45927b2d7d4SCyndy Ishida // NOTE: Do not claim any arguments, as they will be passed along for CC1 4602c93beccSCyndy Ishida // invocations. 46127b2d7d4SCyndy Ishida bool Options::processFrontendOptions(InputArgList &Args) { 46227b2d7d4SCyndy Ishida // Capture language mode. 463c51095f5SCyndy Ishida if (auto *A = Args.getLastArgNoClaim(drv::OPT_x)) { 4642c93beccSCyndy Ishida FEOpts.LangMode = llvm::StringSwitch<clang::Language>(A->getValue()) 4652c93beccSCyndy Ishida .Case("c", clang::Language::C) 4662c93beccSCyndy Ishida .Case("c++", clang::Language::CXX) 4672c93beccSCyndy Ishida .Case("objective-c", clang::Language::ObjC) 4682c93beccSCyndy Ishida .Case("objective-c++", clang::Language::ObjCXX) 4692c93beccSCyndy Ishida .Default(clang::Language::Unknown); 4702c93beccSCyndy Ishida 4712c93beccSCyndy Ishida if (FEOpts.LangMode == clang::Language::Unknown) { 4722c93beccSCyndy Ishida Diags->Report(clang::diag::err_drv_invalid_value) 4732c93beccSCyndy Ishida << A->getAsString(Args) << A->getValue(); 4742c93beccSCyndy Ishida return false; 4752c93beccSCyndy Ishida } 4762c93beccSCyndy Ishida } 477c51095f5SCyndy Ishida for (auto *A : Args.filtered(drv::OPT_ObjC, drv::OPT_ObjCXX)) { 478c51095f5SCyndy Ishida if (A->getOption().matches(drv::OPT_ObjC)) 4792c93beccSCyndy Ishida FEOpts.LangMode = clang::Language::ObjC; 4802c93beccSCyndy Ishida else 4812c93beccSCyndy Ishida FEOpts.LangMode = clang::Language::ObjCXX; 4822c93beccSCyndy Ishida } 4832c93beccSCyndy Ishida 48427b2d7d4SCyndy Ishida // Capture Sysroot. 48527b2d7d4SCyndy Ishida if (const Arg *A = Args.getLastArgNoClaim(drv::OPT_isysroot)) { 48627b2d7d4SCyndy Ishida SmallString<PATH_MAX> Path(A->getValue()); 48727b2d7d4SCyndy Ishida FM->makeAbsolutePath(Path); 48827b2d7d4SCyndy Ishida if (!FM->getOptionalDirectoryRef(Path)) { 48927b2d7d4SCyndy Ishida Diags->Report(diag::err_missing_sysroot) << Path; 49027b2d7d4SCyndy Ishida return false; 49127b2d7d4SCyndy Ishida } 49227b2d7d4SCyndy Ishida FEOpts.ISysroot = std::string(Path); 49327b2d7d4SCyndy Ishida } else if (FEOpts.ISysroot.empty()) { 49427b2d7d4SCyndy Ishida // Mirror CLANG and obtain the isysroot from the SDKROOT environment 49527b2d7d4SCyndy Ishida // variable, if it wasn't defined by the command line. 49627b2d7d4SCyndy Ishida if (auto *Env = ::getenv("SDKROOT")) { 49727b2d7d4SCyndy Ishida if (StringRef(Env) != "/" && llvm::sys::path::is_absolute(Env) && 49827b2d7d4SCyndy Ishida FM->getOptionalFileRef(Env)) 49927b2d7d4SCyndy Ishida FEOpts.ISysroot = Env; 50027b2d7d4SCyndy Ishida } 50127b2d7d4SCyndy Ishida } 50227b2d7d4SCyndy Ishida 503062f6fe3SCyndy Ishida // Capture system frameworks for all platforms. 50427b2d7d4SCyndy Ishida for (const Arg *A : Args.filtered(drv::OPT_iframework)) 505062f6fe3SCyndy Ishida FEOpts.SystemFwkPaths.emplace_back(A->getValue(), 506062f6fe3SCyndy Ishida std::optional<PlatformType>{}); 50727b2d7d4SCyndy Ishida 50827b2d7d4SCyndy Ishida // Capture framework paths. 50927b2d7d4SCyndy Ishida PathSeq FrameworkPaths; 51027b2d7d4SCyndy Ishida for (const Arg *A : Args.filtered(drv::OPT_F)) 51127b2d7d4SCyndy Ishida FrameworkPaths.emplace_back(A->getValue()); 51227b2d7d4SCyndy Ishida 51327b2d7d4SCyndy Ishida if (!FrameworkPaths.empty()) 51427b2d7d4SCyndy Ishida FEOpts.FwkPaths = std::move(FrameworkPaths); 51527b2d7d4SCyndy Ishida 51627b2d7d4SCyndy Ishida // Add default framework/library paths. 51727b2d7d4SCyndy Ishida PathSeq DefaultLibraryPaths = {"/usr/lib", "/usr/local/lib"}; 51827b2d7d4SCyndy Ishida PathSeq DefaultFrameworkPaths = {"/Library/Frameworks", 51927b2d7d4SCyndy Ishida "/System/Library/Frameworks"}; 52027b2d7d4SCyndy Ishida 52127b2d7d4SCyndy Ishida for (const StringRef LibPath : DefaultLibraryPaths) { 52227b2d7d4SCyndy Ishida SmallString<PATH_MAX> Path(FEOpts.ISysroot); 52327b2d7d4SCyndy Ishida sys::path::append(Path, LibPath); 52427b2d7d4SCyndy Ishida LinkerOpts.LibPaths.emplace_back(Path.str()); 52527b2d7d4SCyndy Ishida } 52627b2d7d4SCyndy Ishida for (const StringRef FwkPath : DefaultFrameworkPaths) { 52727b2d7d4SCyndy Ishida SmallString<PATH_MAX> Path(FEOpts.ISysroot); 52827b2d7d4SCyndy Ishida sys::path::append(Path, FwkPath); 529062f6fe3SCyndy Ishida FEOpts.SystemFwkPaths.emplace_back(Path.str(), 530062f6fe3SCyndy Ishida std::optional<PlatformType>{}); 53127b2d7d4SCyndy Ishida } 53227b2d7d4SCyndy Ishida 5332c93beccSCyndy Ishida return true; 5342c93beccSCyndy Ishida } 5352c93beccSCyndy Ishida 536487720fcSCyndy Ishida bool Options::addFilePaths(InputArgList &Args, PathSeq &Headers, 537487720fcSCyndy Ishida OptSpecifier ID) { 538487720fcSCyndy Ishida for (const StringRef Path : Args.getAllArgValues(ID)) { 539b1aea98cSJan Svoboda if ((bool)FM->getOptionalDirectoryRef(Path, /*CacheFailure=*/false)) { 540487720fcSCyndy Ishida auto InputHeadersOrErr = enumerateFiles(*FM, Path); 541487720fcSCyndy Ishida if (!InputHeadersOrErr) { 542487720fcSCyndy Ishida Diags->Report(diag::err_cannot_open_file) 543487720fcSCyndy Ishida << Path << toString(InputHeadersOrErr.takeError()); 544487720fcSCyndy Ishida return false; 545487720fcSCyndy Ishida } 546487720fcSCyndy Ishida // Sort headers to ensure deterministic behavior. 547487720fcSCyndy Ishida sort(*InputHeadersOrErr); 54879dca25fSCyndy Ishida for (StringRef H : *InputHeadersOrErr) 549487720fcSCyndy Ishida Headers.emplace_back(std::move(H)); 550487720fcSCyndy Ishida } else 551487720fcSCyndy Ishida Headers.emplace_back(Path); 552487720fcSCyndy Ishida } 553487720fcSCyndy Ishida return true; 554487720fcSCyndy Ishida } 555487720fcSCyndy Ishida 556c51095f5SCyndy Ishida std::vector<const char *> 557c51095f5SCyndy Ishida Options::processAndFilterOutInstallAPIOptions(ArrayRef<const char *> Args) { 558c51095f5SCyndy Ishida std::unique_ptr<llvm::opt::OptTable> Table; 559c51095f5SCyndy Ishida Table.reset(createDriverOptTable()); 560c51095f5SCyndy Ishida 561c51095f5SCyndy Ishida unsigned MissingArgIndex, MissingArgCount; 562c51095f5SCyndy Ishida auto ParsedArgs = Table->ParseArgs(Args.slice(1), MissingArgIndex, 563c51095f5SCyndy Ishida MissingArgCount, Visibility()); 564c51095f5SCyndy Ishida 565c51095f5SCyndy Ishida // Capture InstallAPI only driver options. 56627b2d7d4SCyndy Ishida if (!processInstallAPIXOptions(ParsedArgs)) 56727b2d7d4SCyndy Ishida return {}; 56827b2d7d4SCyndy Ishida 569c9dc52d4SCyndy Ishida if (!processOptionList(ParsedArgs, Table.get())) 570c9dc52d4SCyndy Ishida return {}; 571c9dc52d4SCyndy Ishida 572c51095f5SCyndy Ishida DriverOpts.Demangle = ParsedArgs.hasArg(OPT_demangle); 573c51095f5SCyndy Ishida 574c51095f5SCyndy Ishida if (auto *A = ParsedArgs.getLastArg(OPT_filetype)) { 575c51095f5SCyndy Ishida DriverOpts.OutFT = TextAPIWriter::parseFileType(A->getValue()); 576c51095f5SCyndy Ishida if (DriverOpts.OutFT == FileType::Invalid) { 577c51095f5SCyndy Ishida Diags->Report(clang::diag::err_drv_invalid_value) 578c51095f5SCyndy Ishida << A->getAsString(ParsedArgs) << A->getValue(); 579c51095f5SCyndy Ishida return {}; 580c51095f5SCyndy Ishida } 581c51095f5SCyndy Ishida } 582c51095f5SCyndy Ishida 583c51095f5SCyndy Ishida if (const Arg *A = ParsedArgs.getLastArg(OPT_verify_mode_EQ)) { 584c51095f5SCyndy Ishida DriverOpts.VerifyMode = 585c51095f5SCyndy Ishida StringSwitch<VerificationMode>(A->getValue()) 586c51095f5SCyndy Ishida .Case("ErrorsOnly", VerificationMode::ErrorsOnly) 587c51095f5SCyndy Ishida .Case("ErrorsAndWarnings", VerificationMode::ErrorsAndWarnings) 588c51095f5SCyndy Ishida .Case("Pedantic", VerificationMode::Pedantic) 589c51095f5SCyndy Ishida .Default(VerificationMode::Invalid); 590c51095f5SCyndy Ishida 591c51095f5SCyndy Ishida if (DriverOpts.VerifyMode == VerificationMode::Invalid) { 592c51095f5SCyndy Ishida Diags->Report(clang::diag::err_drv_invalid_value) 593c51095f5SCyndy Ishida << A->getAsString(ParsedArgs) << A->getValue(); 594c51095f5SCyndy Ishida return {}; 595c51095f5SCyndy Ishida } 596c51095f5SCyndy Ishida } 597c51095f5SCyndy Ishida 598c51095f5SCyndy Ishida if (const Arg *A = ParsedArgs.getLastArg(OPT_verify_against)) 599c51095f5SCyndy Ishida DriverOpts.DylibToVerify = A->getValue(); 600c51095f5SCyndy Ishida 601a4de589dSCyndy Ishida if (const Arg *A = ParsedArgs.getLastArg(OPT_dsym)) 602a4de589dSCyndy Ishida DriverOpts.DSYMPath = A->getValue(); 603a4de589dSCyndy Ishida 60427b2d7d4SCyndy Ishida DriverOpts.TraceLibraryLocation = ParsedArgs.hasArg(OPT_t); 60527b2d7d4SCyndy Ishida 60627b2d7d4SCyndy Ishida // Linker options not handled by clang driver. 60727b2d7d4SCyndy Ishida LinkerOpts.OSLibNotForSharedCache = 60827b2d7d4SCyndy Ishida ParsedArgs.hasArg(OPT_not_for_dyld_shared_cache); 60927b2d7d4SCyndy Ishida 61027b2d7d4SCyndy Ishida for (const Arg *A : ParsedArgs.filtered(OPT_allowable_client)) { 61127b2d7d4SCyndy Ishida LinkerOpts.AllowableClients[A->getValue()] = 61227b2d7d4SCyndy Ishida ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 61327b2d7d4SCyndy Ishida A->claim(); 61427b2d7d4SCyndy Ishida } 61527b2d7d4SCyndy Ishida 61627b2d7d4SCyndy Ishida for (const Arg *A : ParsedArgs.filtered(OPT_reexport_l)) { 61727b2d7d4SCyndy Ishida LinkerOpts.ReexportedLibraries[A->getValue()] = 61827b2d7d4SCyndy Ishida ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 61927b2d7d4SCyndy Ishida A->claim(); 62027b2d7d4SCyndy Ishida } 62127b2d7d4SCyndy Ishida 62227b2d7d4SCyndy Ishida for (const Arg *A : ParsedArgs.filtered(OPT_reexport_library)) { 62327b2d7d4SCyndy Ishida LinkerOpts.ReexportedLibraryPaths[A->getValue()] = 62427b2d7d4SCyndy Ishida ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 62527b2d7d4SCyndy Ishida A->claim(); 62627b2d7d4SCyndy Ishida } 62727b2d7d4SCyndy Ishida 62827b2d7d4SCyndy Ishida for (const Arg *A : ParsedArgs.filtered(OPT_reexport_framework)) { 62927b2d7d4SCyndy Ishida LinkerOpts.ReexportedFrameworks[A->getValue()] = 63027b2d7d4SCyndy Ishida ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 63127b2d7d4SCyndy Ishida A->claim(); 63227b2d7d4SCyndy Ishida } 63327b2d7d4SCyndy Ishida 63427b2d7d4SCyndy Ishida for (const Arg *A : ParsedArgs.filtered(OPT_rpath)) { 63527b2d7d4SCyndy Ishida LinkerOpts.RPaths[A->getValue()] = 63627b2d7d4SCyndy Ishida ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 63727b2d7d4SCyndy Ishida A->claim(); 63827b2d7d4SCyndy Ishida } 63927b2d7d4SCyndy Ishida 640487720fcSCyndy Ishida // Handle exclude & extra header directories or files. 641487720fcSCyndy Ishida auto handleAdditionalInputArgs = [&](PathSeq &Headers, 642487720fcSCyndy Ishida clang::installapi::ID OptID) { 643487720fcSCyndy Ishida if (ParsedArgs.hasArgNoClaim(OptID)) 644487720fcSCyndy Ishida Headers.clear(); 645487720fcSCyndy Ishida return addFilePaths(ParsedArgs, Headers, OptID); 646487720fcSCyndy Ishida }; 647487720fcSCyndy Ishida 648487720fcSCyndy Ishida if (!handleAdditionalInputArgs(DriverOpts.ExtraPublicHeaders, 649487720fcSCyndy Ishida OPT_extra_public_header)) 650487720fcSCyndy Ishida return {}; 651487720fcSCyndy Ishida 652487720fcSCyndy Ishida if (!handleAdditionalInputArgs(DriverOpts.ExtraPrivateHeaders, 653487720fcSCyndy Ishida OPT_extra_private_header)) 654487720fcSCyndy Ishida return {}; 655487720fcSCyndy Ishida if (!handleAdditionalInputArgs(DriverOpts.ExtraProjectHeaders, 656487720fcSCyndy Ishida OPT_extra_project_header)) 657487720fcSCyndy Ishida return {}; 658487720fcSCyndy Ishida 659487720fcSCyndy Ishida if (!handleAdditionalInputArgs(DriverOpts.ExcludePublicHeaders, 660487720fcSCyndy Ishida OPT_exclude_public_header)) 661487720fcSCyndy Ishida return {}; 662487720fcSCyndy Ishida if (!handleAdditionalInputArgs(DriverOpts.ExcludePrivateHeaders, 663487720fcSCyndy Ishida OPT_exclude_private_header)) 664487720fcSCyndy Ishida return {}; 665487720fcSCyndy Ishida if (!handleAdditionalInputArgs(DriverOpts.ExcludeProjectHeaders, 666487720fcSCyndy Ishida OPT_exclude_project_header)) 667487720fcSCyndy Ishida return {}; 668487720fcSCyndy Ishida 6696ad1cf3bSCyndy Ishida // Handle umbrella headers. 6706ad1cf3bSCyndy Ishida if (const Arg *A = ParsedArgs.getLastArg(OPT_public_umbrella_header)) 6716ad1cf3bSCyndy Ishida DriverOpts.PublicUmbrellaHeader = A->getValue(); 6726ad1cf3bSCyndy Ishida 6736ad1cf3bSCyndy Ishida if (const Arg *A = ParsedArgs.getLastArg(OPT_private_umbrella_header)) 6746ad1cf3bSCyndy Ishida DriverOpts.PrivateUmbrellaHeader = A->getValue(); 6756ad1cf3bSCyndy Ishida 6766ad1cf3bSCyndy Ishida if (const Arg *A = ParsedArgs.getLastArg(OPT_project_umbrella_header)) 6776ad1cf3bSCyndy Ishida DriverOpts.ProjectUmbrellaHeader = A->getValue(); 6786ad1cf3bSCyndy Ishida 679c51095f5SCyndy Ishida /// Any unclaimed arguments should be forwarded to the clang driver. 680c51095f5SCyndy Ishida std::vector<const char *> ClangDriverArgs(ParsedArgs.size()); 681c51095f5SCyndy Ishida for (const Arg *A : ParsedArgs) { 682c51095f5SCyndy Ishida if (A->isClaimed()) 683c51095f5SCyndy Ishida continue; 684062f6fe3SCyndy Ishida // Forward along unclaimed but overlapping arguments to the clang driver. 685062f6fe3SCyndy Ishida if (A->getOption().getID() > (unsigned)OPT_UNKNOWN) { 686062f6fe3SCyndy Ishida ClangDriverArgs.push_back(A->getSpelling().data()); 687062f6fe3SCyndy Ishida } else 688c51095f5SCyndy Ishida llvm::copy(A->getValues(), std::back_inserter(ClangDriverArgs)); 689c51095f5SCyndy Ishida } 690c51095f5SCyndy Ishida return ClangDriverArgs; 691c51095f5SCyndy Ishida } 692c51095f5SCyndy Ishida 6930a518db9SCyndy Ishida Options::Options(DiagnosticsEngine &Diag, FileManager *FM, 694c51095f5SCyndy Ishida ArrayRef<const char *> Args, const StringRef ProgName) 6950a518db9SCyndy Ishida : Diags(&Diag), FM(FM) { 696c51095f5SCyndy Ishida 697c51095f5SCyndy Ishida // First process InstallAPI specific options. 698c51095f5SCyndy Ishida auto DriverArgs = processAndFilterOutInstallAPIOptions(Args); 699c51095f5SCyndy Ishida if (Diags->hasErrorOccurred()) 700c51095f5SCyndy Ishida return; 701c51095f5SCyndy Ishida 702c51095f5SCyndy Ishida // Set up driver to parse remaining input arguments. 703c51095f5SCyndy Ishida clang::driver::Driver Driver(ProgName, llvm::sys::getDefaultTargetTriple(), 704c51095f5SCyndy Ishida *Diags, "clang installapi tool"); 705c51095f5SCyndy Ishida auto TargetAndMode = 706c51095f5SCyndy Ishida clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName); 707c51095f5SCyndy Ishida Driver.setTargetAndMode(TargetAndMode); 708c51095f5SCyndy Ishida bool HasError = false; 709c51095f5SCyndy Ishida llvm::opt::InputArgList ArgList = 710c51095f5SCyndy Ishida Driver.ParseArgStrings(DriverArgs, /*UseDriverMode=*/true, HasError); 711c51095f5SCyndy Ishida if (HasError) 712c51095f5SCyndy Ishida return; 713c51095f5SCyndy Ishida Driver.setCheckInputsExist(false); 714c51095f5SCyndy Ishida 7150a518db9SCyndy Ishida if (!processDriverOptions(ArgList)) 7160a518db9SCyndy Ishida return; 7170a518db9SCyndy Ishida 7180a518db9SCyndy Ishida if (!processLinkerOptions(ArgList)) 7190a518db9SCyndy Ishida return; 720c6cbf81cSCyndy Ishida 7212c93beccSCyndy Ishida if (!processFrontendOptions(ArgList)) 7222c93beccSCyndy Ishida return; 7232c93beccSCyndy Ishida 72427b2d7d4SCyndy Ishida // After all InstallAPI necessary arguments have been collected. Go back and 72527b2d7d4SCyndy Ishida // assign values that were unknown before the clang driver opt table was used. 72627b2d7d4SCyndy Ishida ArchitectureSet AllArchs; 72727b2d7d4SCyndy Ishida llvm::for_each(DriverOpts.Targets, 72827b2d7d4SCyndy Ishida [&AllArchs](const auto &T) { AllArchs.set(T.first.Arch); }); 72927b2d7d4SCyndy Ishida auto assignDefaultLibAttrs = [&AllArchs](LibAttrs &Attrs) { 73027b2d7d4SCyndy Ishida for (StringMapEntry<ArchitectureSet> &Entry : Attrs) 73127b2d7d4SCyndy Ishida if (Entry.getValue().empty()) 73227b2d7d4SCyndy Ishida Entry.setValue(AllArchs); 73327b2d7d4SCyndy Ishida }; 73427b2d7d4SCyndy Ishida assignDefaultLibAttrs(LinkerOpts.AllowableClients); 73527b2d7d4SCyndy Ishida assignDefaultLibAttrs(LinkerOpts.ReexportedFrameworks); 73627b2d7d4SCyndy Ishida assignDefaultLibAttrs(LinkerOpts.ReexportedLibraries); 73727b2d7d4SCyndy Ishida assignDefaultLibAttrs(LinkerOpts.ReexportedLibraryPaths); 73827b2d7d4SCyndy Ishida assignDefaultLibAttrs(LinkerOpts.RPaths); 73927b2d7d4SCyndy Ishida 740936519f2SCyndy Ishida /// Force cc1 options that should always be on. 741936519f2SCyndy Ishida FrontendArgs = {"-fsyntax-only", "-Wprivate-extern"}; 742936519f2SCyndy Ishida 7432c93beccSCyndy Ishida /// Any unclaimed arguments should be handled by invoking the clang frontend. 744c6cbf81cSCyndy Ishida for (const Arg *A : ArgList) { 745c6cbf81cSCyndy Ishida if (A->isClaimed()) 746c6cbf81cSCyndy Ishida continue; 74750ae8a2aSCyndy Ishida FrontendArgs.emplace_back(A->getSpelling()); 74850ae8a2aSCyndy Ishida llvm::copy(A->getValues(), std::back_inserter(FrontendArgs)); 749c6cbf81cSCyndy Ishida } 7500a518db9SCyndy Ishida } 7510a518db9SCyndy Ishida 75227b2d7d4SCyndy Ishida static Expected<std::unique_ptr<InterfaceFile>> 75327b2d7d4SCyndy Ishida getInterfaceFile(const StringRef Filename) { 75427b2d7d4SCyndy Ishida ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 75527b2d7d4SCyndy Ishida MemoryBuffer::getFile(Filename); 75627b2d7d4SCyndy Ishida if (auto Err = BufferOrErr.getError()) 75727b2d7d4SCyndy Ishida return errorCodeToError(std::move(Err)); 75827b2d7d4SCyndy Ishida 75927b2d7d4SCyndy Ishida auto Buffer = std::move(*BufferOrErr); 76027b2d7d4SCyndy Ishida std::unique_ptr<InterfaceFile> IF; 76127b2d7d4SCyndy Ishida switch (identify_magic(Buffer->getBuffer())) { 76227b2d7d4SCyndy Ishida case file_magic::macho_dynamically_linked_shared_lib: 76327b2d7d4SCyndy Ishida case file_magic::macho_dynamically_linked_shared_lib_stub: 76427b2d7d4SCyndy Ishida case file_magic::macho_universal_binary: 76527b2d7d4SCyndy Ishida return DylibReader::get(Buffer->getMemBufferRef()); 76627b2d7d4SCyndy Ishida break; 76727b2d7d4SCyndy Ishida case file_magic::tapi_file: 76827b2d7d4SCyndy Ishida return TextAPIReader::get(Buffer->getMemBufferRef()); 76927b2d7d4SCyndy Ishida default: 77027b2d7d4SCyndy Ishida return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat, 77127b2d7d4SCyndy Ishida "unsupported library file format"); 77227b2d7d4SCyndy Ishida } 77327b2d7d4SCyndy Ishida llvm_unreachable("unexpected failure in getInterface"); 77427b2d7d4SCyndy Ishida } 77527b2d7d4SCyndy Ishida 77627b2d7d4SCyndy Ishida std::pair<LibAttrs, ReexportedInterfaces> Options::getReexportedLibraries() { 77727b2d7d4SCyndy Ishida LibAttrs Reexports; 77827b2d7d4SCyndy Ishida ReexportedInterfaces ReexportIFs; 77927b2d7d4SCyndy Ishida auto AccumulateReexports = [&](StringRef Path, const ArchitectureSet &Archs) { 78027b2d7d4SCyndy Ishida auto ReexportIFOrErr = getInterfaceFile(Path); 78127b2d7d4SCyndy Ishida if (!ReexportIFOrErr) 78227b2d7d4SCyndy Ishida return false; 78327b2d7d4SCyndy Ishida std::unique_ptr<InterfaceFile> Reexport = std::move(*ReexportIFOrErr); 78427b2d7d4SCyndy Ishida StringRef InstallName = Reexport->getInstallName(); 78527b2d7d4SCyndy Ishida assert(!InstallName.empty() && "Parse error for install name"); 78627b2d7d4SCyndy Ishida Reexports.insert({InstallName, Archs}); 78727b2d7d4SCyndy Ishida ReexportIFs.emplace_back(std::move(*Reexport)); 78827b2d7d4SCyndy Ishida return true; 78927b2d7d4SCyndy Ishida }; 79027b2d7d4SCyndy Ishida 791062f6fe3SCyndy Ishida PlatformSet Platforms; 792062f6fe3SCyndy Ishida llvm::for_each(DriverOpts.Targets, 793062f6fe3SCyndy Ishida [&](const auto &T) { Platforms.insert(T.first.Platform); }); 79427b2d7d4SCyndy Ishida // Populate search paths by looking at user paths before system ones. 79527b2d7d4SCyndy Ishida PathSeq FwkSearchPaths(FEOpts.FwkPaths.begin(), FEOpts.FwkPaths.end()); 796062f6fe3SCyndy Ishida for (const PlatformType P : Platforms) { 797062f6fe3SCyndy Ishida PathSeq PlatformSearchPaths = getPathsForPlatform(FEOpts.SystemFwkPaths, P); 798062f6fe3SCyndy Ishida FwkSearchPaths.insert(FwkSearchPaths.end(), PlatformSearchPaths.begin(), 799062f6fe3SCyndy Ishida PlatformSearchPaths.end()); 800062f6fe3SCyndy Ishida for (const StringMapEntry<ArchitectureSet> &Lib : 801062f6fe3SCyndy Ishida LinkerOpts.ReexportedFrameworks) { 802062f6fe3SCyndy Ishida std::string Name = (Lib.getKey() + ".framework/" + Lib.getKey()).str(); 803062f6fe3SCyndy Ishida std::string Path = findLibrary(Name, *FM, FwkSearchPaths, {}, {}); 804062f6fe3SCyndy Ishida if (Path.empty()) { 805062f6fe3SCyndy Ishida Diags->Report(diag::err_cannot_find_reexport) << false << Lib.getKey(); 806062f6fe3SCyndy Ishida return {}; 807062f6fe3SCyndy Ishida } 808062f6fe3SCyndy Ishida if (DriverOpts.TraceLibraryLocation) 809062f6fe3SCyndy Ishida errs() << Path << "\n"; 810062f6fe3SCyndy Ishida 811062f6fe3SCyndy Ishida AccumulateReexports(Path, Lib.getValue()); 812062f6fe3SCyndy Ishida } 813062f6fe3SCyndy Ishida FwkSearchPaths.resize(FwkSearchPaths.size() - PlatformSearchPaths.size()); 814062f6fe3SCyndy Ishida } 81527b2d7d4SCyndy Ishida 81627b2d7d4SCyndy Ishida for (const StringMapEntry<ArchitectureSet> &Lib : 81727b2d7d4SCyndy Ishida LinkerOpts.ReexportedLibraries) { 81827b2d7d4SCyndy Ishida std::string Name = "lib" + Lib.getKey().str() + ".dylib"; 81927b2d7d4SCyndy Ishida std::string Path = findLibrary(Name, *FM, {}, LinkerOpts.LibPaths, {}); 82027b2d7d4SCyndy Ishida if (Path.empty()) { 82127b2d7d4SCyndy Ishida Diags->Report(diag::err_cannot_find_reexport) << true << Lib.getKey(); 82227b2d7d4SCyndy Ishida return {}; 82327b2d7d4SCyndy Ishida } 82427b2d7d4SCyndy Ishida if (DriverOpts.TraceLibraryLocation) 82527b2d7d4SCyndy Ishida errs() << Path << "\n"; 82627b2d7d4SCyndy Ishida 82727b2d7d4SCyndy Ishida AccumulateReexports(Path, Lib.getValue()); 82827b2d7d4SCyndy Ishida } 82927b2d7d4SCyndy Ishida 83027b2d7d4SCyndy Ishida for (const StringMapEntry<ArchitectureSet> &Lib : 83127b2d7d4SCyndy Ishida LinkerOpts.ReexportedLibraryPaths) 83227b2d7d4SCyndy Ishida AccumulateReexports(Lib.getKey(), Lib.getValue()); 83327b2d7d4SCyndy Ishida 83427b2d7d4SCyndy Ishida return {std::move(Reexports), std::move(ReexportIFs)}; 83527b2d7d4SCyndy Ishida } 83627b2d7d4SCyndy Ishida 8370a518db9SCyndy Ishida InstallAPIContext Options::createContext() { 8380a518db9SCyndy Ishida InstallAPIContext Ctx; 839c6cbf81cSCyndy Ishida Ctx.FM = FM; 840c6cbf81cSCyndy Ishida Ctx.Diags = Diags; 841c6cbf81cSCyndy Ishida 8420a518db9SCyndy Ishida // InstallAPI requires two level namespacing. 8430a518db9SCyndy Ishida Ctx.BA.TwoLevelNamespace = true; 8440a518db9SCyndy Ishida 8450a518db9SCyndy Ishida Ctx.BA.InstallName = LinkerOpts.InstallName; 8460a518db9SCyndy Ishida Ctx.BA.CurrentVersion = LinkerOpts.CurrentVersion; 847b058b7e6SCyndy Ishida Ctx.BA.CompatVersion = LinkerOpts.CompatVersion; 8480a518db9SCyndy Ishida Ctx.BA.AppExtensionSafe = LinkerOpts.AppExtensionSafe; 84927b2d7d4SCyndy Ishida Ctx.BA.ParentUmbrella = LinkerOpts.ParentUmbrella; 85027b2d7d4SCyndy Ishida Ctx.BA.OSLibNotForSharedCache = LinkerOpts.OSLibNotForSharedCache; 8510a518db9SCyndy Ishida Ctx.FT = DriverOpts.OutFT; 8520a518db9SCyndy Ishida Ctx.OutputLoc = DriverOpts.OutputPath; 8532c93beccSCyndy Ishida Ctx.LangMode = FEOpts.LangMode; 854c6cbf81cSCyndy Ishida 85527b2d7d4SCyndy Ishida auto [Reexports, ReexportedIFs] = getReexportedLibraries(); 85627b2d7d4SCyndy Ishida if (Diags->hasErrorOccurred()) 85727b2d7d4SCyndy Ishida return Ctx; 85827b2d7d4SCyndy Ishida Ctx.Reexports = Reexports; 85927b2d7d4SCyndy Ishida 8604c18681aSCyndy Ishida // Collect symbols from alias lists. 8614c18681aSCyndy Ishida AliasMap Aliases; 8624c18681aSCyndy Ishida for (const StringRef ListPath : LinkerOpts.AliasLists) { 8634c18681aSCyndy Ishida auto Buffer = FM->getBufferForFile(ListPath); 8644c18681aSCyndy Ishida if (auto Err = Buffer.getError()) { 8654c18681aSCyndy Ishida Diags->Report(diag::err_cannot_open_file) << ListPath << Err.message(); 8664c18681aSCyndy Ishida return Ctx; 8674c18681aSCyndy Ishida } 8684c18681aSCyndy Ishida Expected<AliasMap> Result = parseAliasList(Buffer.get()); 8694c18681aSCyndy Ishida if (!Result) { 870278774e4SCyndy Ishida Diags->Report(diag::err_cannot_read_input_list) 871c9dc52d4SCyndy Ishida << "symbol alias" << ListPath << toString(Result.takeError()); 8724c18681aSCyndy Ishida return Ctx; 8734c18681aSCyndy Ishida } 8744c18681aSCyndy Ishida Aliases.insert(Result.get().begin(), Result.get().end()); 8754c18681aSCyndy Ishida } 8764c18681aSCyndy Ishida 8776ad1cf3bSCyndy Ishida // Attempt to find umbrella headers by capturing framework name. 8786ad1cf3bSCyndy Ishida StringRef FrameworkName; 8796ad1cf3bSCyndy Ishida if (!LinkerOpts.IsDylib) 880feed66f3SCyndy Ishida FrameworkName = 881feed66f3SCyndy Ishida Library::getFrameworkNameFromInstallName(LinkerOpts.InstallName); 8826ad1cf3bSCyndy Ishida 883feed66f3SCyndy Ishida /// Process inputs headers. 884feed66f3SCyndy Ishida // 1. For headers discovered by directory scanning, sort them. 885feed66f3SCyndy Ishida // 2. For headers discovered by filelist, respect ordering. 886feed66f3SCyndy Ishida // 3. Append extra headers and mark any excluded headers. 887feed66f3SCyndy Ishida // 4. Finally, surface up umbrella headers to top of the list. 888feed66f3SCyndy Ishida if (!DriverOpts.InputDirectory.empty()) { 889feed66f3SCyndy Ishida DirectoryScanner Scanner(*FM, LinkerOpts.IsDylib 890feed66f3SCyndy Ishida ? ScanMode::ScanDylibs 891feed66f3SCyndy Ishida : ScanMode::ScanFrameworks); 892feed66f3SCyndy Ishida SmallString<PATH_MAX> NormalizedPath(DriverOpts.InputDirectory); 893feed66f3SCyndy Ishida FM->getVirtualFileSystem().makeAbsolute(NormalizedPath); 894feed66f3SCyndy Ishida sys::path::remove_dots(NormalizedPath, /*remove_dot_dot=*/true); 895feed66f3SCyndy Ishida if (llvm::Error Err = Scanner.scan(NormalizedPath)) { 896feed66f3SCyndy Ishida Diags->Report(diag::err_directory_scanning) 897feed66f3SCyndy Ishida << DriverOpts.InputDirectory << std::move(Err); 898feed66f3SCyndy Ishida return Ctx; 899feed66f3SCyndy Ishida } 900feed66f3SCyndy Ishida std::vector<Library> InputLibraries = Scanner.takeLibraries(); 901feed66f3SCyndy Ishida if (InputLibraries.size() > 1) { 902feed66f3SCyndy Ishida Diags->Report(diag::err_more_than_one_library); 903feed66f3SCyndy Ishida return Ctx; 904feed66f3SCyndy Ishida } 905feed66f3SCyndy Ishida llvm::append_range(Ctx.InputHeaders, 906feed66f3SCyndy Ishida DirectoryScanner::getHeaders(InputLibraries)); 907feed66f3SCyndy Ishida llvm::stable_sort(Ctx.InputHeaders); 908feed66f3SCyndy Ishida } 909feed66f3SCyndy Ishida 91079dca25fSCyndy Ishida for (const StringRef ListPath : DriverOpts.FileLists) { 911c6cbf81cSCyndy Ishida auto Buffer = FM->getBufferForFile(ListPath); 912c6cbf81cSCyndy Ishida if (auto Err = Buffer.getError()) { 913c51095f5SCyndy Ishida Diags->Report(diag::err_cannot_open_file) << ListPath << Err.message(); 914c6cbf81cSCyndy Ishida return Ctx; 915c6cbf81cSCyndy Ishida } 916c6cbf81cSCyndy Ishida if (auto Err = FileListReader::loadHeaders(std::move(Buffer.get()), 917278774e4SCyndy Ishida Ctx.InputHeaders, FM)) { 918278774e4SCyndy Ishida Diags->Report(diag::err_cannot_read_input_list) 919c9dc52d4SCyndy Ishida << "header file" << ListPath << std::move(Err); 920c6cbf81cSCyndy Ishida return Ctx; 921c6cbf81cSCyndy Ishida } 922c6cbf81cSCyndy Ishida } 923487720fcSCyndy Ishida // After initial input has been processed, add any extra headers. 924487720fcSCyndy Ishida auto HandleExtraHeaders = [&](PathSeq &Headers, HeaderType Type) -> bool { 925487720fcSCyndy Ishida assert(Type != HeaderType::Unknown && "Missing header type."); 926487720fcSCyndy Ishida for (const StringRef Path : Headers) { 927487720fcSCyndy Ishida if (!FM->getOptionalFileRef(Path)) { 9286ad1cf3bSCyndy Ishida Diags->Report(diag::err_no_such_header_file) << Path << (unsigned)Type; 929487720fcSCyndy Ishida return false; 930487720fcSCyndy Ishida } 931487720fcSCyndy Ishida SmallString<PATH_MAX> FullPath(Path); 932487720fcSCyndy Ishida FM->makeAbsolutePath(FullPath); 933487720fcSCyndy Ishida 934487720fcSCyndy Ishida auto IncludeName = createIncludeHeaderName(FullPath); 935487720fcSCyndy Ishida Ctx.InputHeaders.emplace_back( 936487720fcSCyndy Ishida FullPath, Type, IncludeName.has_value() ? *IncludeName : ""); 937487720fcSCyndy Ishida Ctx.InputHeaders.back().setExtra(); 938487720fcSCyndy Ishida } 939487720fcSCyndy Ishida return true; 940487720fcSCyndy Ishida }; 941487720fcSCyndy Ishida 942487720fcSCyndy Ishida if (!HandleExtraHeaders(DriverOpts.ExtraPublicHeaders, HeaderType::Public) || 943487720fcSCyndy Ishida !HandleExtraHeaders(DriverOpts.ExtraPrivateHeaders, 944487720fcSCyndy Ishida HeaderType::Private) || 945487720fcSCyndy Ishida !HandleExtraHeaders(DriverOpts.ExtraProjectHeaders, HeaderType::Project)) 946487720fcSCyndy Ishida return Ctx; 947487720fcSCyndy Ishida 948487720fcSCyndy Ishida // After all headers have been added, consider excluded headers. 949487720fcSCyndy Ishida std::vector<std::unique_ptr<HeaderGlob>> ExcludedHeaderGlobs; 950487720fcSCyndy Ishida std::set<FileEntryRef> ExcludedHeaderFiles; 951487720fcSCyndy Ishida auto ParseGlobs = [&](const PathSeq &Paths, HeaderType Type) { 9526ad1cf3bSCyndy Ishida assert(Type != HeaderType::Unknown && "Missing header type."); 953487720fcSCyndy Ishida for (const StringRef Path : Paths) { 954487720fcSCyndy Ishida auto Glob = HeaderGlob::create(Path, Type); 955487720fcSCyndy Ishida if (Glob) 956487720fcSCyndy Ishida ExcludedHeaderGlobs.emplace_back(std::move(Glob.get())); 957487720fcSCyndy Ishida else { 958487720fcSCyndy Ishida consumeError(Glob.takeError()); 959487720fcSCyndy Ishida if (auto File = FM->getFileRef(Path)) 960487720fcSCyndy Ishida ExcludedHeaderFiles.emplace(*File); 961487720fcSCyndy Ishida else { 962487720fcSCyndy Ishida Diags->Report(diag::err_no_such_header_file) 963487720fcSCyndy Ishida << Path << (unsigned)Type; 964487720fcSCyndy Ishida return false; 965487720fcSCyndy Ishida } 966487720fcSCyndy Ishida } 967487720fcSCyndy Ishida } 968487720fcSCyndy Ishida return true; 969487720fcSCyndy Ishida }; 970487720fcSCyndy Ishida 971487720fcSCyndy Ishida if (!ParseGlobs(DriverOpts.ExcludePublicHeaders, HeaderType::Public) || 972487720fcSCyndy Ishida !ParseGlobs(DriverOpts.ExcludePrivateHeaders, HeaderType::Private) || 973487720fcSCyndy Ishida !ParseGlobs(DriverOpts.ExcludeProjectHeaders, HeaderType::Project)) 974487720fcSCyndy Ishida return Ctx; 975487720fcSCyndy Ishida 976487720fcSCyndy Ishida for (HeaderFile &Header : Ctx.InputHeaders) { 977487720fcSCyndy Ishida for (auto &Glob : ExcludedHeaderGlobs) 978487720fcSCyndy Ishida if (Glob->match(Header)) 979487720fcSCyndy Ishida Header.setExcluded(); 980487720fcSCyndy Ishida } 981487720fcSCyndy Ishida if (!ExcludedHeaderFiles.empty()) { 982487720fcSCyndy Ishida for (HeaderFile &Header : Ctx.InputHeaders) { 983487720fcSCyndy Ishida auto FileRef = FM->getFileRef(Header.getPath()); 984487720fcSCyndy Ishida if (!FileRef) 985487720fcSCyndy Ishida continue; 986487720fcSCyndy Ishida if (ExcludedHeaderFiles.count(*FileRef)) 987487720fcSCyndy Ishida Header.setExcluded(); 988487720fcSCyndy Ishida } 989487720fcSCyndy Ishida } 990487720fcSCyndy Ishida // Report if glob was ignored. 991487720fcSCyndy Ishida for (const auto &Glob : ExcludedHeaderGlobs) 992487720fcSCyndy Ishida if (!Glob->didMatch()) 993487720fcSCyndy Ishida Diags->Report(diag::warn_glob_did_not_match) << Glob->str(); 994c6cbf81cSCyndy Ishida 9956ad1cf3bSCyndy Ishida // Mark any explicit or inferred umbrella headers. If one exists, move 9966ad1cf3bSCyndy Ishida // that to the beginning of the input headers. 9976ad1cf3bSCyndy Ishida auto MarkandMoveUmbrellaInHeaders = [&](llvm::Regex &Regex, 9986ad1cf3bSCyndy Ishida HeaderType Type) -> bool { 9996ad1cf3bSCyndy Ishida auto It = find_if(Ctx.InputHeaders, [&Regex, Type](const HeaderFile &H) { 10006ad1cf3bSCyndy Ishida return (H.getType() == Type) && Regex.match(H.getPath()); 10016ad1cf3bSCyndy Ishida }); 10026ad1cf3bSCyndy Ishida 10036ad1cf3bSCyndy Ishida if (It == Ctx.InputHeaders.end()) 10046ad1cf3bSCyndy Ishida return false; 10056ad1cf3bSCyndy Ishida It->setUmbrellaHeader(); 10066ad1cf3bSCyndy Ishida 10076ad1cf3bSCyndy Ishida // Because there can be an umbrella header per header type, 10086ad1cf3bSCyndy Ishida // find the first non umbrella header to swap position with. 10096ad1cf3bSCyndy Ishida auto BeginPos = find_if(Ctx.InputHeaders, [](const HeaderFile &H) { 10106ad1cf3bSCyndy Ishida return !H.isUmbrellaHeader(); 10116ad1cf3bSCyndy Ishida }); 10126ad1cf3bSCyndy Ishida if (BeginPos != Ctx.InputHeaders.end() && BeginPos < It) 10136ad1cf3bSCyndy Ishida std::swap(*BeginPos, *It); 10146ad1cf3bSCyndy Ishida return true; 10156ad1cf3bSCyndy Ishida }; 10166ad1cf3bSCyndy Ishida 10176ad1cf3bSCyndy Ishida auto FindUmbrellaHeader = [&](StringRef HeaderPath, HeaderType Type) -> bool { 10186ad1cf3bSCyndy Ishida assert(Type != HeaderType::Unknown && "Missing header type."); 10196ad1cf3bSCyndy Ishida if (!HeaderPath.empty()) { 10206ad1cf3bSCyndy Ishida auto EscapedString = Regex::escape(HeaderPath); 10216ad1cf3bSCyndy Ishida Regex UmbrellaRegex(EscapedString); 10226ad1cf3bSCyndy Ishida if (!MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type)) { 10236ad1cf3bSCyndy Ishida Diags->Report(diag::err_no_such_umbrella_header_file) 10246ad1cf3bSCyndy Ishida << HeaderPath << (unsigned)Type; 10256ad1cf3bSCyndy Ishida return false; 10266ad1cf3bSCyndy Ishida } 10276ad1cf3bSCyndy Ishida } else if (!FrameworkName.empty() && (Type != HeaderType::Project)) { 10286ad1cf3bSCyndy Ishida auto UmbrellaName = "/" + Regex::escape(FrameworkName); 10296ad1cf3bSCyndy Ishida if (Type == HeaderType::Public) 10306ad1cf3bSCyndy Ishida UmbrellaName += "\\.h"; 10316ad1cf3bSCyndy Ishida else 10326ad1cf3bSCyndy Ishida UmbrellaName += "[_]?Private\\.h"; 10336ad1cf3bSCyndy Ishida Regex UmbrellaRegex(UmbrellaName); 10346ad1cf3bSCyndy Ishida MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type); 10356ad1cf3bSCyndy Ishida } 10366ad1cf3bSCyndy Ishida return true; 10376ad1cf3bSCyndy Ishida }; 10386ad1cf3bSCyndy Ishida if (!FindUmbrellaHeader(DriverOpts.PublicUmbrellaHeader, 10396ad1cf3bSCyndy Ishida HeaderType::Public) || 10406ad1cf3bSCyndy Ishida !FindUmbrellaHeader(DriverOpts.PrivateUmbrellaHeader, 10416ad1cf3bSCyndy Ishida HeaderType::Private) || 10426ad1cf3bSCyndy Ishida !FindUmbrellaHeader(DriverOpts.ProjectUmbrellaHeader, 10436ad1cf3bSCyndy Ishida HeaderType::Project)) 10446ad1cf3bSCyndy Ishida return Ctx; 10456ad1cf3bSCyndy Ishida 1046f2794cceSCyndy Ishida // Parse binary dylib and initialize verifier. 1047f2794cceSCyndy Ishida if (DriverOpts.DylibToVerify.empty()) { 1048f2794cceSCyndy Ishida Ctx.Verifier = std::make_unique<DylibVerifier>(); 1049c51095f5SCyndy Ishida return Ctx; 1050f2794cceSCyndy Ishida } 1051c51095f5SCyndy Ishida 1052c51095f5SCyndy Ishida auto Buffer = FM->getBufferForFile(DriverOpts.DylibToVerify); 1053c51095f5SCyndy Ishida if (auto Err = Buffer.getError()) { 1054c51095f5SCyndy Ishida Diags->Report(diag::err_cannot_open_file) 1055c51095f5SCyndy Ishida << DriverOpts.DylibToVerify << Err.message(); 1056c51095f5SCyndy Ishida return Ctx; 1057c51095f5SCyndy Ishida } 1058c51095f5SCyndy Ishida 1059c51095f5SCyndy Ishida DylibReader::ParseOption PO; 1060c51095f5SCyndy Ishida PO.Undefineds = false; 1061c51095f5SCyndy Ishida Expected<Records> Slices = 1062c51095f5SCyndy Ishida DylibReader::readFile((*Buffer)->getMemBufferRef(), PO); 1063c51095f5SCyndy Ishida if (auto Err = Slices.takeError()) { 106427b2d7d4SCyndy Ishida Diags->Report(diag::err_cannot_open_file) 106527b2d7d4SCyndy Ishida << DriverOpts.DylibToVerify << std::move(Err); 1066c51095f5SCyndy Ishida return Ctx; 1067c51095f5SCyndy Ishida } 1068c51095f5SCyndy Ishida 1069f2794cceSCyndy Ishida Ctx.Verifier = std::make_unique<DylibVerifier>( 10704c18681aSCyndy Ishida std::move(*Slices), std::move(ReexportedIFs), std::move(Aliases), Diags, 1071c24efffaSCyndy Ishida DriverOpts.VerifyMode, DriverOpts.Zippered, DriverOpts.Demangle, 1072c24efffaSCyndy Ishida DriverOpts.DSYMPath); 10730a518db9SCyndy Ishida return Ctx; 10740a518db9SCyndy Ishida } 10750a518db9SCyndy Ishida 1076062f6fe3SCyndy Ishida void Options::addConditionalCC1Args(std::vector<std::string> &ArgStrings, 1077062f6fe3SCyndy Ishida const llvm::Triple &Targ, 1078062f6fe3SCyndy Ishida const HeaderType Type) { 1079062f6fe3SCyndy Ishida // Unique to architecture (Xarch) options hold no arguments to pass along for 1080062f6fe3SCyndy Ishida // frontend. 1081062f6fe3SCyndy Ishida 1082062f6fe3SCyndy Ishida // Add specific to platform arguments. 1083062f6fe3SCyndy Ishida PathSeq PlatformSearchPaths = 1084062f6fe3SCyndy Ishida getPathsForPlatform(FEOpts.SystemFwkPaths, mapToPlatformType(Targ)); 1085062f6fe3SCyndy Ishida llvm::for_each(PlatformSearchPaths, [&ArgStrings](const StringRef Path) { 1086062f6fe3SCyndy Ishida ArgStrings.push_back("-iframework"); 1087062f6fe3SCyndy Ishida ArgStrings.push_back(Path.str()); 1088062f6fe3SCyndy Ishida }); 1089062f6fe3SCyndy Ishida 1090062f6fe3SCyndy Ishida // Add specific to header type arguments. 1091062f6fe3SCyndy Ishida if (Type == HeaderType::Project) 1092062f6fe3SCyndy Ishida for (const StringRef A : ProjectLevelArgs) 1093062f6fe3SCyndy Ishida ArgStrings.emplace_back(A); 1094062f6fe3SCyndy Ishida } 1095062f6fe3SCyndy Ishida 10960a518db9SCyndy Ishida } // namespace installapi 10970a518db9SCyndy Ishida } // namespace clang 1098