1 //===-- Options.cpp -------------------------------------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Options.h" 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" 24 25 using namespace llvm; 26 using namespace llvm::opt; 27 using namespace llvm::MachO; 28 29 namespace drv = clang::driver::options; 30 31 namespace clang { 32 namespace installapi { 33 34 #define OPTTABLE_STR_TABLE_CODE 35 #include "InstallAPIOpts.inc" 36 #undef OPTTABLE_STR_TABLE_CODE 37 38 #define OPTTABLE_PREFIXES_TABLE_CODE 39 #include "InstallAPIOpts.inc" 40 #undef OPTTABLE_PREFIXES_TABLE_CODE 41 42 #define OPTTABLE_PREFIXES_UNION_CODE 43 #include "InstallAPIOpts.inc" 44 #undef OPTTABLE_PREFIXES_UNION_CODE 45 46 /// Create table mapping all options defined in InstallAPIOpts.td. 47 static constexpr OptTable::Info InfoTable[] = { 48 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), 49 #include "InstallAPIOpts.inc" 50 #undef OPTION 51 }; 52 53 namespace { 54 55 /// \brief Create OptTable class for parsing actual command line arguments. 56 class DriverOptTable : public opt::PrecomputedOptTable { 57 public: 58 DriverOptTable() 59 : PrecomputedOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, 60 OptionPrefixesUnion) {} 61 }; 62 63 } // end anonymous namespace. 64 65 static llvm::opt::OptTable *createDriverOptTable() { 66 return new DriverOptTable(); 67 } 68 69 /// Parse JSON input into argument list. 70 /// 71 /* Expected input format. 72 * { "label" : ["-ClangArg1", "-ClangArg2"] } 73 */ 74 /// 75 /// Input is interpreted as "-Xlabel ClangArg1 -XLabel ClangArg2". 76 static Expected<llvm::opt::InputArgList> 77 getArgListFromJSON(const StringRef Input, llvm::opt::OptTable *Table, 78 std::vector<std::string> &Storage) { 79 using namespace json; 80 Expected<Value> ValOrErr = json::parse(Input); 81 if (!ValOrErr) 82 return ValOrErr.takeError(); 83 84 const Object *Root = ValOrErr->getAsObject(); 85 if (!Root) 86 return llvm::opt::InputArgList(); 87 88 for (const auto &KV : *Root) { 89 const Array *ArgList = KV.getSecond().getAsArray(); 90 std::string Label = "-X" + KV.getFirst().str(); 91 if (!ArgList) 92 return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat); 93 for (auto Arg : *ArgList) { 94 std::optional<StringRef> ArgStr = Arg.getAsString(); 95 if (!ArgStr) 96 return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat); 97 Storage.emplace_back(Label); 98 Storage.emplace_back(*ArgStr); 99 } 100 } 101 102 std::vector<const char *> CArgs(Storage.size()); 103 llvm::for_each(Storage, 104 [&CArgs](StringRef Str) { CArgs.emplace_back(Str.data()); }); 105 106 unsigned MissingArgIndex, MissingArgCount; 107 return Table->ParseArgs(CArgs, MissingArgIndex, MissingArgCount); 108 } 109 110 bool Options::processDriverOptions(InputArgList &Args) { 111 // Handle inputs. 112 for (const StringRef Path : Args.getAllArgValues(drv::OPT_INPUT)) { 113 // Assume any input that is not a directory is a filelist. 114 // InstallAPI does not accept multiple directories, so retain the last one. 115 if (FM->getOptionalDirectoryRef(Path)) 116 DriverOpts.InputDirectory = Path.str(); 117 else 118 DriverOpts.FileLists.emplace_back(Path.str()); 119 } 120 121 // Handle output. 122 SmallString<PATH_MAX> OutputPath; 123 if (auto *Arg = Args.getLastArg(drv::OPT_o)) { 124 OutputPath = Arg->getValue(); 125 if (OutputPath != "-") 126 FM->makeAbsolutePath(OutputPath); 127 DriverOpts.OutputPath = std::string(OutputPath); 128 } 129 if (DriverOpts.OutputPath.empty()) { 130 Diags->Report(diag::err_no_output_file); 131 return false; 132 } 133 134 // Do basic error checking first for mixing -target and -arch options. 135 auto *ArgArch = Args.getLastArgNoClaim(drv::OPT_arch); 136 auto *ArgTarget = Args.getLastArgNoClaim(drv::OPT_target); 137 auto *ArgTargetVariant = 138 Args.getLastArgNoClaim(drv::OPT_darwin_target_variant); 139 if (ArgArch && (ArgTarget || ArgTargetVariant)) { 140 Diags->Report(clang::diag::err_drv_argument_not_allowed_with) 141 << ArgArch->getAsString(Args) 142 << (ArgTarget ? ArgTarget : ArgTargetVariant)->getAsString(Args); 143 return false; 144 } 145 146 auto *ArgMinTargetOS = Args.getLastArgNoClaim(drv::OPT_mtargetos_EQ); 147 if ((ArgTarget || ArgTargetVariant) && ArgMinTargetOS) { 148 Diags->Report(clang::diag::err_drv_cannot_mix_options) 149 << ArgTarget->getAsString(Args) << ArgMinTargetOS->getAsString(Args); 150 return false; 151 } 152 153 // Capture target triples first. 154 if (ArgTarget) { 155 for (const Arg *A : Args.filtered(drv::OPT_target)) { 156 A->claim(); 157 llvm::Triple TargetTriple(A->getValue()); 158 Target TAPITarget = Target(TargetTriple); 159 if ((TAPITarget.Arch == AK_unknown) || 160 (TAPITarget.Platform == PLATFORM_UNKNOWN)) { 161 Diags->Report(clang::diag::err_drv_unsupported_opt_for_target) 162 << "installapi" << TargetTriple.str(); 163 return false; 164 } 165 DriverOpts.Targets[TAPITarget] = TargetTriple; 166 } 167 } 168 169 // Capture target variants. 170 DriverOpts.Zippered = ArgTargetVariant != nullptr; 171 for (Arg *A : Args.filtered(drv::OPT_darwin_target_variant)) { 172 A->claim(); 173 Triple Variant(A->getValue()); 174 if (Variant.getVendor() != Triple::Apple) { 175 Diags->Report(diag::err_unsupported_vendor) 176 << Variant.getVendorName() << A->getAsString(Args); 177 return false; 178 } 179 180 switch (Variant.getOS()) { 181 default: 182 Diags->Report(diag::err_unsupported_os) 183 << Variant.getOSName() << A->getAsString(Args); 184 return false; 185 case Triple::MacOSX: 186 case Triple::IOS: 187 break; 188 } 189 190 switch (Variant.getEnvironment()) { 191 default: 192 Diags->Report(diag::err_unsupported_environment) 193 << Variant.getEnvironmentName() << A->getAsString(Args); 194 return false; 195 case Triple::UnknownEnvironment: 196 case Triple::MacABI: 197 break; 198 } 199 200 Target TAPIVariant(Variant); 201 // See if there is a matching --target option for this --target-variant 202 // option. 203 auto It = find_if(DriverOpts.Targets, [&](const auto &T) { 204 return (T.first.Arch == TAPIVariant.Arch) && 205 (T.first.Platform != PlatformType::PLATFORM_UNKNOWN); 206 }); 207 208 if (It == DriverOpts.Targets.end()) { 209 Diags->Report(diag::err_no_matching_target) << Variant.str(); 210 return false; 211 } 212 213 DriverOpts.Targets[TAPIVariant] = Variant; 214 } 215 216 DriverOpts.Verbose = Args.hasArgNoClaim(drv::OPT_v); 217 218 return true; 219 } 220 221 bool Options::processInstallAPIXOptions(InputArgList &Args) { 222 for (arg_iterator It = Args.begin(), End = Args.end(); It != End; ++It) { 223 Arg *A = *It; 224 if (A->getOption().matches(OPT_Xarch__)) { 225 if (!processXarchOption(Args, It)) 226 return false; 227 continue; 228 } else if (A->getOption().matches(OPT_Xplatform__)) { 229 if (!processXplatformOption(Args, It)) 230 return false; 231 continue; 232 } else if (A->getOption().matches(OPT_Xproject)) { 233 if (!processXprojectOption(Args, It)) 234 return false; 235 continue; 236 } else if (!A->getOption().matches(OPT_X__)) 237 continue; 238 239 // Handle any user defined labels. 240 const StringRef Label = A->getValue(0); 241 242 // Ban "public" and "private" labels. 243 if ((Label.lower() == "public") || (Label.lower() == "private")) { 244 Diags->Report(diag::err_invalid_label) << Label; 245 return false; 246 } 247 248 auto NextIt = std::next(It); 249 if (NextIt == End) { 250 Diags->Report(clang::diag::err_drv_missing_argument) 251 << A->getAsString(Args) << 1; 252 return false; 253 } 254 Arg *NextA = *NextIt; 255 switch ((ID)NextA->getOption().getID()) { 256 case OPT_D: 257 case OPT_U: 258 break; 259 default: 260 Diags->Report(clang::diag::err_drv_argument_not_allowed_with) 261 << A->getAsString(Args) << NextA->getAsString(Args); 262 return false; 263 } 264 const StringRef ASpelling = NextA->getSpelling(); 265 const auto &AValues = NextA->getValues(); 266 if (AValues.empty()) 267 FEOpts.UniqueArgs[Label].emplace_back(ASpelling.str()); 268 else 269 for (const StringRef Val : AValues) 270 FEOpts.UniqueArgs[Label].emplace_back((ASpelling + Val).str()); 271 272 A->claim(); 273 NextA->claim(); 274 } 275 276 return true; 277 } 278 279 bool Options::processXplatformOption(InputArgList &Args, arg_iterator Curr) { 280 Arg *A = *Curr; 281 282 PlatformType Platform = getPlatformFromName(A->getValue(0)); 283 if (Platform == PLATFORM_UNKNOWN) { 284 Diags->Report(diag::err_unsupported_os) 285 << getPlatformName(Platform) << A->getAsString(Args); 286 return false; 287 } 288 auto NextIt = std::next(Curr); 289 if (NextIt == Args.end()) { 290 Diags->Report(diag::err_drv_missing_argument) << A->getAsString(Args) << 1; 291 return false; 292 } 293 294 Arg *NextA = *NextIt; 295 switch ((ID)NextA->getOption().getID()) { 296 case OPT_iframework: 297 FEOpts.SystemFwkPaths.emplace_back(NextA->getValue(), Platform); 298 break; 299 default: 300 Diags->Report(diag::err_drv_invalid_argument_to_option) 301 << A->getAsString(Args) << NextA->getAsString(Args); 302 return false; 303 } 304 305 A->claim(); 306 NextA->claim(); 307 308 return true; 309 } 310 311 bool Options::processXprojectOption(InputArgList &Args, arg_iterator Curr) { 312 Arg *A = *Curr; 313 auto NextIt = std::next(Curr); 314 if (NextIt == Args.end()) { 315 Diags->Report(diag::err_drv_missing_argument) << A->getAsString(Args) << 1; 316 return false; 317 } 318 319 Arg *NextA = *NextIt; 320 switch ((ID)NextA->getOption().getID()) { 321 case OPT_fobjc_arc: 322 case OPT_fmodules: 323 case OPT_fmodules_cache_path: 324 case OPT_include_: 325 case OPT_fvisibility_EQ: 326 break; 327 default: 328 Diags->Report(diag::err_drv_argument_not_allowed_with) 329 << A->getAsString(Args) << NextA->getAsString(Args); 330 return false; 331 } 332 333 std::string ArgString = NextA->getSpelling().str(); 334 for (const StringRef Val : NextA->getValues()) 335 ArgString += Val.str(); 336 337 ProjectLevelArgs.push_back(ArgString); 338 A->claim(); 339 NextA->claim(); 340 341 return true; 342 } 343 344 bool Options::processXarchOption(InputArgList &Args, arg_iterator Curr) { 345 Arg *CurrArg = *Curr; 346 Architecture Arch = getArchitectureFromName(CurrArg->getValue(0)); 347 if (Arch == AK_unknown) { 348 Diags->Report(diag::err_drv_invalid_arch_name) 349 << CurrArg->getAsString(Args); 350 return false; 351 } 352 353 auto NextIt = std::next(Curr); 354 if (NextIt == Args.end()) { 355 Diags->Report(diag::err_drv_missing_argument) 356 << CurrArg->getAsString(Args) << 1; 357 return false; 358 } 359 360 // InstallAPI has a limited understanding of supported Xarch options. 361 // Currently this is restricted to linker inputs. 362 const Arg *NextArg = *NextIt; 363 switch (NextArg->getOption().getID()) { 364 case OPT_allowable_client: 365 case OPT_reexport_l: 366 case OPT_reexport_framework: 367 case OPT_reexport_library: 368 case OPT_rpath: 369 break; 370 default: 371 Diags->Report(diag::err_drv_invalid_argument_to_option) 372 << NextArg->getAsString(Args) << CurrArg->getAsString(Args); 373 return false; 374 } 375 376 ArgToArchMap[NextArg] = Arch; 377 CurrArg->claim(); 378 379 return true; 380 } 381 382 bool Options::processOptionList(InputArgList &Args, 383 llvm::opt::OptTable *Table) { 384 Arg *A = Args.getLastArg(OPT_option_list); 385 if (!A) 386 return true; 387 388 const StringRef Path = A->getValue(0); 389 auto InputOrErr = FM->getBufferForFile(Path); 390 if (auto Err = InputOrErr.getError()) { 391 Diags->Report(diag::err_cannot_open_file) << Path << Err.message(); 392 return false; 393 } 394 // Backing storage referenced for argument processing. 395 std::vector<std::string> Storage; 396 auto ArgsOrErr = 397 getArgListFromJSON((*InputOrErr)->getBuffer(), Table, Storage); 398 399 if (auto Err = ArgsOrErr.takeError()) { 400 Diags->Report(diag::err_cannot_read_input_list) 401 << "option" << Path << toString(std::move(Err)); 402 return false; 403 } 404 return processInstallAPIXOptions(*ArgsOrErr); 405 } 406 407 bool Options::processLinkerOptions(InputArgList &Args) { 408 // Handle required arguments. 409 if (const Arg *A = Args.getLastArg(drv::OPT_install__name)) 410 LinkerOpts.InstallName = A->getValue(); 411 if (LinkerOpts.InstallName.empty()) { 412 Diags->Report(diag::err_no_install_name); 413 return false; 414 } 415 416 // Defaulted or optional arguments. 417 if (auto *Arg = Args.getLastArg(drv::OPT_current__version)) 418 LinkerOpts.CurrentVersion.parse64(Arg->getValue()); 419 420 if (auto *Arg = Args.getLastArg(drv::OPT_compatibility__version)) 421 LinkerOpts.CompatVersion.parse64(Arg->getValue()); 422 423 if (auto *Arg = Args.getLastArg(drv::OPT_compatibility__version)) 424 LinkerOpts.CompatVersion.parse64(Arg->getValue()); 425 426 if (auto *Arg = Args.getLastArg(drv::OPT_umbrella)) 427 LinkerOpts.ParentUmbrella = Arg->getValue(); 428 429 LinkerOpts.IsDylib = Args.hasArg(drv::OPT_dynamiclib); 430 431 for (auto *Arg : Args.filtered(drv::OPT_alias_list)) { 432 LinkerOpts.AliasLists.emplace_back(Arg->getValue()); 433 Arg->claim(); 434 } 435 436 LinkerOpts.AppExtensionSafe = Args.hasFlag( 437 drv::OPT_fapplication_extension, drv::OPT_fno_application_extension, 438 /*Default=*/LinkerOpts.AppExtensionSafe); 439 440 if (::getenv("LD_NO_ENCRYPT") != nullptr) 441 LinkerOpts.AppExtensionSafe = true; 442 443 if (::getenv("LD_APPLICATION_EXTENSION_SAFE") != nullptr) 444 LinkerOpts.AppExtensionSafe = true; 445 446 // Capture library paths. 447 PathSeq LibraryPaths; 448 for (const Arg *A : Args.filtered(drv::OPT_L)) { 449 LibraryPaths.emplace_back(A->getValue()); 450 A->claim(); 451 } 452 453 if (!LibraryPaths.empty()) 454 LinkerOpts.LibPaths = std::move(LibraryPaths); 455 456 return true; 457 } 458 459 // NOTE: Do not claim any arguments, as they will be passed along for CC1 460 // invocations. 461 bool Options::processFrontendOptions(InputArgList &Args) { 462 // Capture language mode. 463 if (auto *A = Args.getLastArgNoClaim(drv::OPT_x)) { 464 FEOpts.LangMode = llvm::StringSwitch<clang::Language>(A->getValue()) 465 .Case("c", clang::Language::C) 466 .Case("c++", clang::Language::CXX) 467 .Case("objective-c", clang::Language::ObjC) 468 .Case("objective-c++", clang::Language::ObjCXX) 469 .Default(clang::Language::Unknown); 470 471 if (FEOpts.LangMode == clang::Language::Unknown) { 472 Diags->Report(clang::diag::err_drv_invalid_value) 473 << A->getAsString(Args) << A->getValue(); 474 return false; 475 } 476 } 477 for (auto *A : Args.filtered(drv::OPT_ObjC, drv::OPT_ObjCXX)) { 478 if (A->getOption().matches(drv::OPT_ObjC)) 479 FEOpts.LangMode = clang::Language::ObjC; 480 else 481 FEOpts.LangMode = clang::Language::ObjCXX; 482 } 483 484 // Capture Sysroot. 485 if (const Arg *A = Args.getLastArgNoClaim(drv::OPT_isysroot)) { 486 SmallString<PATH_MAX> Path(A->getValue()); 487 FM->makeAbsolutePath(Path); 488 if (!FM->getOptionalDirectoryRef(Path)) { 489 Diags->Report(diag::err_missing_sysroot) << Path; 490 return false; 491 } 492 FEOpts.ISysroot = std::string(Path); 493 } else if (FEOpts.ISysroot.empty()) { 494 // Mirror CLANG and obtain the isysroot from the SDKROOT environment 495 // variable, if it wasn't defined by the command line. 496 if (auto *Env = ::getenv("SDKROOT")) { 497 if (StringRef(Env) != "/" && llvm::sys::path::is_absolute(Env) && 498 FM->getOptionalFileRef(Env)) 499 FEOpts.ISysroot = Env; 500 } 501 } 502 503 // Capture system frameworks for all platforms. 504 for (const Arg *A : Args.filtered(drv::OPT_iframework)) 505 FEOpts.SystemFwkPaths.emplace_back(A->getValue(), 506 std::optional<PlatformType>{}); 507 508 // Capture framework paths. 509 PathSeq FrameworkPaths; 510 for (const Arg *A : Args.filtered(drv::OPT_F)) 511 FrameworkPaths.emplace_back(A->getValue()); 512 513 if (!FrameworkPaths.empty()) 514 FEOpts.FwkPaths = std::move(FrameworkPaths); 515 516 // Add default framework/library paths. 517 PathSeq DefaultLibraryPaths = {"/usr/lib", "/usr/local/lib"}; 518 PathSeq DefaultFrameworkPaths = {"/Library/Frameworks", 519 "/System/Library/Frameworks"}; 520 521 for (const StringRef LibPath : DefaultLibraryPaths) { 522 SmallString<PATH_MAX> Path(FEOpts.ISysroot); 523 sys::path::append(Path, LibPath); 524 LinkerOpts.LibPaths.emplace_back(Path.str()); 525 } 526 for (const StringRef FwkPath : DefaultFrameworkPaths) { 527 SmallString<PATH_MAX> Path(FEOpts.ISysroot); 528 sys::path::append(Path, FwkPath); 529 FEOpts.SystemFwkPaths.emplace_back(Path.str(), 530 std::optional<PlatformType>{}); 531 } 532 533 return true; 534 } 535 536 bool Options::addFilePaths(InputArgList &Args, PathSeq &Headers, 537 OptSpecifier ID) { 538 for (const StringRef Path : Args.getAllArgValues(ID)) { 539 if ((bool)FM->getOptionalDirectoryRef(Path, /*CacheFailure=*/false)) { 540 auto InputHeadersOrErr = enumerateFiles(*FM, Path); 541 if (!InputHeadersOrErr) { 542 Diags->Report(diag::err_cannot_open_file) 543 << Path << toString(InputHeadersOrErr.takeError()); 544 return false; 545 } 546 // Sort headers to ensure deterministic behavior. 547 sort(*InputHeadersOrErr); 548 for (StringRef H : *InputHeadersOrErr) 549 Headers.emplace_back(std::move(H)); 550 } else 551 Headers.emplace_back(Path); 552 } 553 return true; 554 } 555 556 std::vector<const char *> 557 Options::processAndFilterOutInstallAPIOptions(ArrayRef<const char *> Args) { 558 std::unique_ptr<llvm::opt::OptTable> Table; 559 Table.reset(createDriverOptTable()); 560 561 unsigned MissingArgIndex, MissingArgCount; 562 auto ParsedArgs = Table->ParseArgs(Args.slice(1), MissingArgIndex, 563 MissingArgCount, Visibility()); 564 565 // Capture InstallAPI only driver options. 566 if (!processInstallAPIXOptions(ParsedArgs)) 567 return {}; 568 569 if (!processOptionList(ParsedArgs, Table.get())) 570 return {}; 571 572 DriverOpts.Demangle = ParsedArgs.hasArg(OPT_demangle); 573 574 if (auto *A = ParsedArgs.getLastArg(OPT_filetype)) { 575 DriverOpts.OutFT = TextAPIWriter::parseFileType(A->getValue()); 576 if (DriverOpts.OutFT == FileType::Invalid) { 577 Diags->Report(clang::diag::err_drv_invalid_value) 578 << A->getAsString(ParsedArgs) << A->getValue(); 579 return {}; 580 } 581 } 582 583 if (const Arg *A = ParsedArgs.getLastArg(OPT_verify_mode_EQ)) { 584 DriverOpts.VerifyMode = 585 StringSwitch<VerificationMode>(A->getValue()) 586 .Case("ErrorsOnly", VerificationMode::ErrorsOnly) 587 .Case("ErrorsAndWarnings", VerificationMode::ErrorsAndWarnings) 588 .Case("Pedantic", VerificationMode::Pedantic) 589 .Default(VerificationMode::Invalid); 590 591 if (DriverOpts.VerifyMode == VerificationMode::Invalid) { 592 Diags->Report(clang::diag::err_drv_invalid_value) 593 << A->getAsString(ParsedArgs) << A->getValue(); 594 return {}; 595 } 596 } 597 598 if (const Arg *A = ParsedArgs.getLastArg(OPT_verify_against)) 599 DriverOpts.DylibToVerify = A->getValue(); 600 601 if (const Arg *A = ParsedArgs.getLastArg(OPT_dsym)) 602 DriverOpts.DSYMPath = A->getValue(); 603 604 DriverOpts.TraceLibraryLocation = ParsedArgs.hasArg(OPT_t); 605 606 // Linker options not handled by clang driver. 607 LinkerOpts.OSLibNotForSharedCache = 608 ParsedArgs.hasArg(OPT_not_for_dyld_shared_cache); 609 610 for (const Arg *A : ParsedArgs.filtered(OPT_allowable_client)) { 611 LinkerOpts.AllowableClients[A->getValue()] = 612 ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 613 A->claim(); 614 } 615 616 for (const Arg *A : ParsedArgs.filtered(OPT_reexport_l)) { 617 LinkerOpts.ReexportedLibraries[A->getValue()] = 618 ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 619 A->claim(); 620 } 621 622 for (const Arg *A : ParsedArgs.filtered(OPT_reexport_library)) { 623 LinkerOpts.ReexportedLibraryPaths[A->getValue()] = 624 ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 625 A->claim(); 626 } 627 628 for (const Arg *A : ParsedArgs.filtered(OPT_reexport_framework)) { 629 LinkerOpts.ReexportedFrameworks[A->getValue()] = 630 ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 631 A->claim(); 632 } 633 634 for (const Arg *A : ParsedArgs.filtered(OPT_rpath)) { 635 LinkerOpts.RPaths[A->getValue()] = 636 ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); 637 A->claim(); 638 } 639 640 // Handle exclude & extra header directories or files. 641 auto handleAdditionalInputArgs = [&](PathSeq &Headers, 642 clang::installapi::ID OptID) { 643 if (ParsedArgs.hasArgNoClaim(OptID)) 644 Headers.clear(); 645 return addFilePaths(ParsedArgs, Headers, OptID); 646 }; 647 648 if (!handleAdditionalInputArgs(DriverOpts.ExtraPublicHeaders, 649 OPT_extra_public_header)) 650 return {}; 651 652 if (!handleAdditionalInputArgs(DriverOpts.ExtraPrivateHeaders, 653 OPT_extra_private_header)) 654 return {}; 655 if (!handleAdditionalInputArgs(DriverOpts.ExtraProjectHeaders, 656 OPT_extra_project_header)) 657 return {}; 658 659 if (!handleAdditionalInputArgs(DriverOpts.ExcludePublicHeaders, 660 OPT_exclude_public_header)) 661 return {}; 662 if (!handleAdditionalInputArgs(DriverOpts.ExcludePrivateHeaders, 663 OPT_exclude_private_header)) 664 return {}; 665 if (!handleAdditionalInputArgs(DriverOpts.ExcludeProjectHeaders, 666 OPT_exclude_project_header)) 667 return {}; 668 669 // Handle umbrella headers. 670 if (const Arg *A = ParsedArgs.getLastArg(OPT_public_umbrella_header)) 671 DriverOpts.PublicUmbrellaHeader = A->getValue(); 672 673 if (const Arg *A = ParsedArgs.getLastArg(OPT_private_umbrella_header)) 674 DriverOpts.PrivateUmbrellaHeader = A->getValue(); 675 676 if (const Arg *A = ParsedArgs.getLastArg(OPT_project_umbrella_header)) 677 DriverOpts.ProjectUmbrellaHeader = A->getValue(); 678 679 /// Any unclaimed arguments should be forwarded to the clang driver. 680 std::vector<const char *> ClangDriverArgs(ParsedArgs.size()); 681 for (const Arg *A : ParsedArgs) { 682 if (A->isClaimed()) 683 continue; 684 // Forward along unclaimed but overlapping arguments to the clang driver. 685 if (A->getOption().getID() > (unsigned)OPT_UNKNOWN) { 686 ClangDriverArgs.push_back(A->getSpelling().data()); 687 } else 688 llvm::copy(A->getValues(), std::back_inserter(ClangDriverArgs)); 689 } 690 return ClangDriverArgs; 691 } 692 693 Options::Options(DiagnosticsEngine &Diag, FileManager *FM, 694 ArrayRef<const char *> Args, const StringRef ProgName) 695 : Diags(&Diag), FM(FM) { 696 697 // First process InstallAPI specific options. 698 auto DriverArgs = processAndFilterOutInstallAPIOptions(Args); 699 if (Diags->hasErrorOccurred()) 700 return; 701 702 // Set up driver to parse remaining input arguments. 703 clang::driver::Driver Driver(ProgName, llvm::sys::getDefaultTargetTriple(), 704 *Diags, "clang installapi tool"); 705 auto TargetAndMode = 706 clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName); 707 Driver.setTargetAndMode(TargetAndMode); 708 bool HasError = false; 709 llvm::opt::InputArgList ArgList = 710 Driver.ParseArgStrings(DriverArgs, /*UseDriverMode=*/true, HasError); 711 if (HasError) 712 return; 713 Driver.setCheckInputsExist(false); 714 715 if (!processDriverOptions(ArgList)) 716 return; 717 718 if (!processLinkerOptions(ArgList)) 719 return; 720 721 if (!processFrontendOptions(ArgList)) 722 return; 723 724 // After all InstallAPI necessary arguments have been collected. Go back and 725 // assign values that were unknown before the clang driver opt table was used. 726 ArchitectureSet AllArchs; 727 llvm::for_each(DriverOpts.Targets, 728 [&AllArchs](const auto &T) { AllArchs.set(T.first.Arch); }); 729 auto assignDefaultLibAttrs = [&AllArchs](LibAttrs &Attrs) { 730 for (StringMapEntry<ArchitectureSet> &Entry : Attrs) 731 if (Entry.getValue().empty()) 732 Entry.setValue(AllArchs); 733 }; 734 assignDefaultLibAttrs(LinkerOpts.AllowableClients); 735 assignDefaultLibAttrs(LinkerOpts.ReexportedFrameworks); 736 assignDefaultLibAttrs(LinkerOpts.ReexportedLibraries); 737 assignDefaultLibAttrs(LinkerOpts.ReexportedLibraryPaths); 738 assignDefaultLibAttrs(LinkerOpts.RPaths); 739 740 /// Force cc1 options that should always be on. 741 FrontendArgs = {"-fsyntax-only", "-Wprivate-extern"}; 742 743 /// Any unclaimed arguments should be handled by invoking the clang frontend. 744 for (const Arg *A : ArgList) { 745 if (A->isClaimed()) 746 continue; 747 FrontendArgs.emplace_back(A->getSpelling()); 748 llvm::copy(A->getValues(), std::back_inserter(FrontendArgs)); 749 } 750 } 751 752 static Expected<std::unique_ptr<InterfaceFile>> 753 getInterfaceFile(const StringRef Filename) { 754 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 755 MemoryBuffer::getFile(Filename); 756 if (auto Err = BufferOrErr.getError()) 757 return errorCodeToError(std::move(Err)); 758 759 auto Buffer = std::move(*BufferOrErr); 760 std::unique_ptr<InterfaceFile> IF; 761 switch (identify_magic(Buffer->getBuffer())) { 762 case file_magic::macho_dynamically_linked_shared_lib: 763 case file_magic::macho_dynamically_linked_shared_lib_stub: 764 case file_magic::macho_universal_binary: 765 return DylibReader::get(Buffer->getMemBufferRef()); 766 break; 767 case file_magic::tapi_file: 768 return TextAPIReader::get(Buffer->getMemBufferRef()); 769 default: 770 return make_error<TextAPIError>(TextAPIErrorCode::InvalidInputFormat, 771 "unsupported library file format"); 772 } 773 llvm_unreachable("unexpected failure in getInterface"); 774 } 775 776 std::pair<LibAttrs, ReexportedInterfaces> Options::getReexportedLibraries() { 777 LibAttrs Reexports; 778 ReexportedInterfaces ReexportIFs; 779 auto AccumulateReexports = [&](StringRef Path, const ArchitectureSet &Archs) { 780 auto ReexportIFOrErr = getInterfaceFile(Path); 781 if (!ReexportIFOrErr) 782 return false; 783 std::unique_ptr<InterfaceFile> Reexport = std::move(*ReexportIFOrErr); 784 StringRef InstallName = Reexport->getInstallName(); 785 assert(!InstallName.empty() && "Parse error for install name"); 786 Reexports.insert({InstallName, Archs}); 787 ReexportIFs.emplace_back(std::move(*Reexport)); 788 return true; 789 }; 790 791 PlatformSet Platforms; 792 llvm::for_each(DriverOpts.Targets, 793 [&](const auto &T) { Platforms.insert(T.first.Platform); }); 794 // Populate search paths by looking at user paths before system ones. 795 PathSeq FwkSearchPaths(FEOpts.FwkPaths.begin(), FEOpts.FwkPaths.end()); 796 for (const PlatformType P : Platforms) { 797 PathSeq PlatformSearchPaths = getPathsForPlatform(FEOpts.SystemFwkPaths, P); 798 FwkSearchPaths.insert(FwkSearchPaths.end(), PlatformSearchPaths.begin(), 799 PlatformSearchPaths.end()); 800 for (const StringMapEntry<ArchitectureSet> &Lib : 801 LinkerOpts.ReexportedFrameworks) { 802 std::string Name = (Lib.getKey() + ".framework/" + Lib.getKey()).str(); 803 std::string Path = findLibrary(Name, *FM, FwkSearchPaths, {}, {}); 804 if (Path.empty()) { 805 Diags->Report(diag::err_cannot_find_reexport) << false << Lib.getKey(); 806 return {}; 807 } 808 if (DriverOpts.TraceLibraryLocation) 809 errs() << Path << "\n"; 810 811 AccumulateReexports(Path, Lib.getValue()); 812 } 813 FwkSearchPaths.resize(FwkSearchPaths.size() - PlatformSearchPaths.size()); 814 } 815 816 for (const StringMapEntry<ArchitectureSet> &Lib : 817 LinkerOpts.ReexportedLibraries) { 818 std::string Name = "lib" + Lib.getKey().str() + ".dylib"; 819 std::string Path = findLibrary(Name, *FM, {}, LinkerOpts.LibPaths, {}); 820 if (Path.empty()) { 821 Diags->Report(diag::err_cannot_find_reexport) << true << Lib.getKey(); 822 return {}; 823 } 824 if (DriverOpts.TraceLibraryLocation) 825 errs() << Path << "\n"; 826 827 AccumulateReexports(Path, Lib.getValue()); 828 } 829 830 for (const StringMapEntry<ArchitectureSet> &Lib : 831 LinkerOpts.ReexportedLibraryPaths) 832 AccumulateReexports(Lib.getKey(), Lib.getValue()); 833 834 return {std::move(Reexports), std::move(ReexportIFs)}; 835 } 836 837 InstallAPIContext Options::createContext() { 838 InstallAPIContext Ctx; 839 Ctx.FM = FM; 840 Ctx.Diags = Diags; 841 842 // InstallAPI requires two level namespacing. 843 Ctx.BA.TwoLevelNamespace = true; 844 845 Ctx.BA.InstallName = LinkerOpts.InstallName; 846 Ctx.BA.CurrentVersion = LinkerOpts.CurrentVersion; 847 Ctx.BA.CompatVersion = LinkerOpts.CompatVersion; 848 Ctx.BA.AppExtensionSafe = LinkerOpts.AppExtensionSafe; 849 Ctx.BA.ParentUmbrella = LinkerOpts.ParentUmbrella; 850 Ctx.BA.OSLibNotForSharedCache = LinkerOpts.OSLibNotForSharedCache; 851 Ctx.FT = DriverOpts.OutFT; 852 Ctx.OutputLoc = DriverOpts.OutputPath; 853 Ctx.LangMode = FEOpts.LangMode; 854 855 auto [Reexports, ReexportedIFs] = getReexportedLibraries(); 856 if (Diags->hasErrorOccurred()) 857 return Ctx; 858 Ctx.Reexports = Reexports; 859 860 // Collect symbols from alias lists. 861 AliasMap Aliases; 862 for (const StringRef ListPath : LinkerOpts.AliasLists) { 863 auto Buffer = FM->getBufferForFile(ListPath); 864 if (auto Err = Buffer.getError()) { 865 Diags->Report(diag::err_cannot_open_file) << ListPath << Err.message(); 866 return Ctx; 867 } 868 Expected<AliasMap> Result = parseAliasList(Buffer.get()); 869 if (!Result) { 870 Diags->Report(diag::err_cannot_read_input_list) 871 << "symbol alias" << ListPath << toString(Result.takeError()); 872 return Ctx; 873 } 874 Aliases.insert(Result.get().begin(), Result.get().end()); 875 } 876 877 // Attempt to find umbrella headers by capturing framework name. 878 StringRef FrameworkName; 879 if (!LinkerOpts.IsDylib) 880 FrameworkName = 881 Library::getFrameworkNameFromInstallName(LinkerOpts.InstallName); 882 883 /// Process inputs headers. 884 // 1. For headers discovered by directory scanning, sort them. 885 // 2. For headers discovered by filelist, respect ordering. 886 // 3. Append extra headers and mark any excluded headers. 887 // 4. Finally, surface up umbrella headers to top of the list. 888 if (!DriverOpts.InputDirectory.empty()) { 889 DirectoryScanner Scanner(*FM, LinkerOpts.IsDylib 890 ? ScanMode::ScanDylibs 891 : ScanMode::ScanFrameworks); 892 SmallString<PATH_MAX> NormalizedPath(DriverOpts.InputDirectory); 893 FM->getVirtualFileSystem().makeAbsolute(NormalizedPath); 894 sys::path::remove_dots(NormalizedPath, /*remove_dot_dot=*/true); 895 if (llvm::Error Err = Scanner.scan(NormalizedPath)) { 896 Diags->Report(diag::err_directory_scanning) 897 << DriverOpts.InputDirectory << std::move(Err); 898 return Ctx; 899 } 900 std::vector<Library> InputLibraries = Scanner.takeLibraries(); 901 if (InputLibraries.size() > 1) { 902 Diags->Report(diag::err_more_than_one_library); 903 return Ctx; 904 } 905 llvm::append_range(Ctx.InputHeaders, 906 DirectoryScanner::getHeaders(InputLibraries)); 907 llvm::stable_sort(Ctx.InputHeaders); 908 } 909 910 for (const StringRef ListPath : DriverOpts.FileLists) { 911 auto Buffer = FM->getBufferForFile(ListPath); 912 if (auto Err = Buffer.getError()) { 913 Diags->Report(diag::err_cannot_open_file) << ListPath << Err.message(); 914 return Ctx; 915 } 916 if (auto Err = FileListReader::loadHeaders(std::move(Buffer.get()), 917 Ctx.InputHeaders, FM)) { 918 Diags->Report(diag::err_cannot_read_input_list) 919 << "header file" << ListPath << std::move(Err); 920 return Ctx; 921 } 922 } 923 // After initial input has been processed, add any extra headers. 924 auto HandleExtraHeaders = [&](PathSeq &Headers, HeaderType Type) -> bool { 925 assert(Type != HeaderType::Unknown && "Missing header type."); 926 for (const StringRef Path : Headers) { 927 if (!FM->getOptionalFileRef(Path)) { 928 Diags->Report(diag::err_no_such_header_file) << Path << (unsigned)Type; 929 return false; 930 } 931 SmallString<PATH_MAX> FullPath(Path); 932 FM->makeAbsolutePath(FullPath); 933 934 auto IncludeName = createIncludeHeaderName(FullPath); 935 Ctx.InputHeaders.emplace_back( 936 FullPath, Type, IncludeName.has_value() ? *IncludeName : ""); 937 Ctx.InputHeaders.back().setExtra(); 938 } 939 return true; 940 }; 941 942 if (!HandleExtraHeaders(DriverOpts.ExtraPublicHeaders, HeaderType::Public) || 943 !HandleExtraHeaders(DriverOpts.ExtraPrivateHeaders, 944 HeaderType::Private) || 945 !HandleExtraHeaders(DriverOpts.ExtraProjectHeaders, HeaderType::Project)) 946 return Ctx; 947 948 // After all headers have been added, consider excluded headers. 949 std::vector<std::unique_ptr<HeaderGlob>> ExcludedHeaderGlobs; 950 std::set<FileEntryRef> ExcludedHeaderFiles; 951 auto ParseGlobs = [&](const PathSeq &Paths, HeaderType Type) { 952 assert(Type != HeaderType::Unknown && "Missing header type."); 953 for (const StringRef Path : Paths) { 954 auto Glob = HeaderGlob::create(Path, Type); 955 if (Glob) 956 ExcludedHeaderGlobs.emplace_back(std::move(Glob.get())); 957 else { 958 consumeError(Glob.takeError()); 959 if (auto File = FM->getFileRef(Path)) 960 ExcludedHeaderFiles.emplace(*File); 961 else { 962 Diags->Report(diag::err_no_such_header_file) 963 << Path << (unsigned)Type; 964 return false; 965 } 966 } 967 } 968 return true; 969 }; 970 971 if (!ParseGlobs(DriverOpts.ExcludePublicHeaders, HeaderType::Public) || 972 !ParseGlobs(DriverOpts.ExcludePrivateHeaders, HeaderType::Private) || 973 !ParseGlobs(DriverOpts.ExcludeProjectHeaders, HeaderType::Project)) 974 return Ctx; 975 976 for (HeaderFile &Header : Ctx.InputHeaders) { 977 for (auto &Glob : ExcludedHeaderGlobs) 978 if (Glob->match(Header)) 979 Header.setExcluded(); 980 } 981 if (!ExcludedHeaderFiles.empty()) { 982 for (HeaderFile &Header : Ctx.InputHeaders) { 983 auto FileRef = FM->getFileRef(Header.getPath()); 984 if (!FileRef) 985 continue; 986 if (ExcludedHeaderFiles.count(*FileRef)) 987 Header.setExcluded(); 988 } 989 } 990 // Report if glob was ignored. 991 for (const auto &Glob : ExcludedHeaderGlobs) 992 if (!Glob->didMatch()) 993 Diags->Report(diag::warn_glob_did_not_match) << Glob->str(); 994 995 // Mark any explicit or inferred umbrella headers. If one exists, move 996 // that to the beginning of the input headers. 997 auto MarkandMoveUmbrellaInHeaders = [&](llvm::Regex &Regex, 998 HeaderType Type) -> bool { 999 auto It = find_if(Ctx.InputHeaders, [&Regex, Type](const HeaderFile &H) { 1000 return (H.getType() == Type) && Regex.match(H.getPath()); 1001 }); 1002 1003 if (It == Ctx.InputHeaders.end()) 1004 return false; 1005 It->setUmbrellaHeader(); 1006 1007 // Because there can be an umbrella header per header type, 1008 // find the first non umbrella header to swap position with. 1009 auto BeginPos = find_if(Ctx.InputHeaders, [](const HeaderFile &H) { 1010 return !H.isUmbrellaHeader(); 1011 }); 1012 if (BeginPos != Ctx.InputHeaders.end() && BeginPos < It) 1013 std::swap(*BeginPos, *It); 1014 return true; 1015 }; 1016 1017 auto FindUmbrellaHeader = [&](StringRef HeaderPath, HeaderType Type) -> bool { 1018 assert(Type != HeaderType::Unknown && "Missing header type."); 1019 if (!HeaderPath.empty()) { 1020 auto EscapedString = Regex::escape(HeaderPath); 1021 Regex UmbrellaRegex(EscapedString); 1022 if (!MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type)) { 1023 Diags->Report(diag::err_no_such_umbrella_header_file) 1024 << HeaderPath << (unsigned)Type; 1025 return false; 1026 } 1027 } else if (!FrameworkName.empty() && (Type != HeaderType::Project)) { 1028 auto UmbrellaName = "/" + Regex::escape(FrameworkName); 1029 if (Type == HeaderType::Public) 1030 UmbrellaName += "\\.h"; 1031 else 1032 UmbrellaName += "[_]?Private\\.h"; 1033 Regex UmbrellaRegex(UmbrellaName); 1034 MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type); 1035 } 1036 return true; 1037 }; 1038 if (!FindUmbrellaHeader(DriverOpts.PublicUmbrellaHeader, 1039 HeaderType::Public) || 1040 !FindUmbrellaHeader(DriverOpts.PrivateUmbrellaHeader, 1041 HeaderType::Private) || 1042 !FindUmbrellaHeader(DriverOpts.ProjectUmbrellaHeader, 1043 HeaderType::Project)) 1044 return Ctx; 1045 1046 // Parse binary dylib and initialize verifier. 1047 if (DriverOpts.DylibToVerify.empty()) { 1048 Ctx.Verifier = std::make_unique<DylibVerifier>(); 1049 return Ctx; 1050 } 1051 1052 auto Buffer = FM->getBufferForFile(DriverOpts.DylibToVerify); 1053 if (auto Err = Buffer.getError()) { 1054 Diags->Report(diag::err_cannot_open_file) 1055 << DriverOpts.DylibToVerify << Err.message(); 1056 return Ctx; 1057 } 1058 1059 DylibReader::ParseOption PO; 1060 PO.Undefineds = false; 1061 Expected<Records> Slices = 1062 DylibReader::readFile((*Buffer)->getMemBufferRef(), PO); 1063 if (auto Err = Slices.takeError()) { 1064 Diags->Report(diag::err_cannot_open_file) 1065 << DriverOpts.DylibToVerify << std::move(Err); 1066 return Ctx; 1067 } 1068 1069 Ctx.Verifier = std::make_unique<DylibVerifier>( 1070 std::move(*Slices), std::move(ReexportedIFs), std::move(Aliases), Diags, 1071 DriverOpts.VerifyMode, DriverOpts.Zippered, DriverOpts.Demangle, 1072 DriverOpts.DSYMPath); 1073 return Ctx; 1074 } 1075 1076 void Options::addConditionalCC1Args(std::vector<std::string> &ArgStrings, 1077 const llvm::Triple &Targ, 1078 const HeaderType Type) { 1079 // Unique to architecture (Xarch) options hold no arguments to pass along for 1080 // frontend. 1081 1082 // Add specific to platform arguments. 1083 PathSeq PlatformSearchPaths = 1084 getPathsForPlatform(FEOpts.SystemFwkPaths, mapToPlatformType(Targ)); 1085 llvm::for_each(PlatformSearchPaths, [&ArgStrings](const StringRef Path) { 1086 ArgStrings.push_back("-iframework"); 1087 ArgStrings.push_back(Path.str()); 1088 }); 1089 1090 // Add specific to header type arguments. 1091 if (Type == HeaderType::Project) 1092 for (const StringRef A : ProjectLevelArgs) 1093 ArgStrings.emplace_back(A); 1094 } 1095 1096 } // namespace installapi 1097 } // namespace clang 1098