https://github.com/cyndyishida created https://github.com/llvm/llvm-project/pull/82293
Installapi has important distinctions when compared to the clang driver, so much that, it doesn't make much sense to try to integrate into it. This patch partially reverts the CC1 action & driver support to replace with its own driver as a clang tool. For distribution, we could use `LLVM_TOOL_LLVM_DRIVER_BUILD` mechanism for integrating the functionality into clang such that the toolchain size is less impacted. >From a98cd84ae140c4e78c12e61d2a40049b070c7bcf Mon Sep 17 00:00:00 2001 From: Cyndy Ishida <cyndy_ish...@apple.com> Date: Mon, 19 Feb 2024 08:25:22 -0800 Subject: [PATCH] [InstallAPI] Introduce InstallAPI as a standalone tool instead of CC1 action. Installapi has important distinctions when compared to the clang driver, so much that, it doesn't make much sense to try to integrate into it. This patch partially reverts the CC1 action & driver support to replace with its own driver as a clang tool. For distribution, we could use `LLVM_TOOL_LLVM_DRIVER_BUILD` mechanism for integrating the functionality into clang such that the toolchain size is less impacted. --- clang/include/clang/Driver/Action.h | 12 -- clang/include/clang/Driver/Options.td | 9 +- clang/include/clang/Driver/Types.def | 1 - .../include/clang/Frontend/CompilerInstance.h | 7 - .../clang/Frontend/CompilerInvocation.h | 21 +-- .../include/clang/Frontend/FrontendActions.h | 10 -- .../include/clang/Frontend/FrontendOptions.h | 3 - .../clang/Frontend/InstallAPIOptions.h | 28 ---- clang/include/clang/InstallAPI/Context.h | 15 ++- clang/lib/Driver/Action.cpp | 10 +- clang/lib/Driver/Driver.cpp | 16 +-- clang/lib/Driver/ToolChain.cpp | 1 - clang/lib/Driver/ToolChains/Clang.cpp | 11 -- clang/lib/Frontend/CMakeLists.txt | 3 - clang/lib/Frontend/CompilerInvocation.cpp | 41 +----- clang/lib/Frontend/InstallAPIConsumer.cpp | 43 ------ .../ExecuteCompilerInvocation.cpp | 5 +- clang/lib/InstallAPI/CMakeLists.txt | 1 + clang/lib/InstallAPI/Context.cpp | 13 +- clang/test/CMakeLists.txt | 1 + clang/test/Driver/installapi.h | 13 -- clang/test/InstallAPI/installapi-basic.test | 39 +++++- .../installapi-driver-invalid-options.test | 4 + clang/test/lit.cfg.py | 1 + clang/tools/CMakeLists.txt | 1 + clang/tools/clang-installapi/CMakeLists.txt | 20 +++ .../clang-installapi/ClangInstallAPI.cpp | 124 ++++++++++++++++++ clang/tools/clang-installapi/Options.cpp | 106 +++++++++++++++ clang/tools/clang-installapi/Options.h | 85 ++++++++++++ 29 files changed, 410 insertions(+), 234 deletions(-) delete mode 100644 clang/include/clang/Frontend/InstallAPIOptions.h delete mode 100644 clang/lib/Frontend/InstallAPIConsumer.cpp delete mode 100644 clang/test/Driver/installapi.h create mode 100644 clang/test/InstallAPI/installapi-driver-invalid-options.test create mode 100644 clang/tools/clang-installapi/CMakeLists.txt create mode 100644 clang/tools/clang-installapi/ClangInstallAPI.cpp create mode 100644 clang/tools/clang-installapi/Options.cpp create mode 100644 clang/tools/clang-installapi/Options.h diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h index 2768e2f5df1a9e..04fa8b01b418f8 100644 --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -59,7 +59,6 @@ class Action { PreprocessJobClass, PrecompileJobClass, ExtractAPIJobClass, - InstallAPIJobClass, AnalyzeJobClass, MigrateJobClass, CompileJobClass, @@ -449,17 +448,6 @@ class ExtractAPIJobAction : public JobAction { void addHeaderInput(Action *Input) { getInputs().push_back(Input); } }; -class InstallAPIJobAction : public JobAction { - void anchor() override; - -public: - InstallAPIJobAction(Action *Input, types::ID OutputType); - - static bool classof(const Action *A) { - return A->getKind() == InstallAPIJobClass; - } -}; - class AnalyzeJobAction : public JobAction { void anchor() override; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 53f23f9abb4c96..6e58e63590b675 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -336,8 +336,6 @@ class AnalyzerOpts<string base> : KeyPathAndMacro<"AnalyzerOpts->", base, "ANALYZER_"> {} class MigratorOpts<string base> : KeyPathAndMacro<"MigratorOpts.", base, "MIGRATOR_"> {} -class InstallAPIOpts<string base> - : KeyPathAndMacro<"InstallAPIOpts.", base, "INSTALLAPI_"> {} // A boolean option which is opt-in in CC1. The positive option exists in CC1 and // Args.hasArg(OPT_ffoo) can be used to check that the flag is enabled. @@ -1143,8 +1141,7 @@ def config_user_dir_EQ : Joined<["--"], "config-user-dir=">, def coverage : Flag<["-", "--"], "coverage">, Group<Link_Group>, Visibility<[ClangOption, CLOption]>; def cpp_precomp : Flag<["-"], "cpp-precomp">, Group<clang_ignored_f_Group>; -def current__version : JoinedOrSeparate<["-"], "current_version">, - Visibility<[ClangOption, CC1Option]>; +def current__version : JoinedOrSeparate<["-"], "current_version">; def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group<clang_i_Group>, HelpText<"Add directory to the C++ SYSTEM include search path">, Visibility<[ClangOption, CC1Option]>, @@ -4324,9 +4321,7 @@ def verify_pch : Flag<["-"], "verify-pch">, Group<Action_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Load and verify that a pre-compiled header file is not stale">; def init : Separate<["-"], "init">; -def install__name : Separate<["-"], "install_name">, - Visibility<[ClangOption, CC1Option]>, - MarshallingInfoString<InstallAPIOpts<"InstallName">>; +def install__name : Separate<["-"], "install_name">; def iprefix : JoinedOrSeparate<["-"], "iprefix">, Group<clang_i_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">, MetaVarName<"<dir>">; diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index 570a53441d1c74..f72c27e1ee7019 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -94,7 +94,6 @@ TYPE("lto-bc", LTO_BC, INVALID, "o", phases TYPE("ast", AST, INVALID, "ast", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("ifs", IFS, INVALID, "ifs", phases::IfsMerge) TYPE("ifs-cpp", IFS_CPP, INVALID, "ifs", phases::Compile, phases::IfsMerge) -TYPE("tbd", TextAPI, INVALID, "tbd", phases::Precompile) TYPE("pcm", ModuleFile, INVALID, "pcm", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("header-unit", HeaderUnit, INVALID, "pcm", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("plist", Plist, INVALID, "plist", phases::Compile, phases::Backend, phases::Assemble, phases::Link) diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 6eb7972f86ca5b..ac2f940769fbe9 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -294,13 +294,6 @@ class CompilerInstance : public ModuleLoader { return Invocation->getFrontendOpts(); } - InstallAPIOptions &getInstallAPIOpts() { - return Invocation->getInstallAPIOpts(); - } - const InstallAPIOptions &getInstallAPIOpts() const { - return Invocation->getInstallAPIOpts(); - } - HeaderSearchOptions &getHeaderSearchOpts() { return Invocation->getHeaderSearchOpts(); } diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h index a01d9695dce203..8d75efdd23488b 100644 --- a/clang/include/clang/Frontend/CompilerInvocation.h +++ b/clang/include/clang/Frontend/CompilerInvocation.h @@ -18,7 +18,6 @@ #include "clang/Basic/LangStandard.h" #include "clang/Frontend/DependencyOutputOptions.h" #include "clang/Frontend/FrontendOptions.h" -#include "clang/Frontend/InstallAPIOptions.h" #include "clang/Frontend/MigratorOptions.h" #include "clang/Frontend/PreprocessorOutputOptions.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" @@ -112,9 +111,6 @@ class CompilerInvocationBase { /// Options controlling preprocessed output. std::shared_ptr<PreprocessorOutputOptions> PreprocessorOutputOpts; - /// Options controlling InstallAPI operations and output. - std::shared_ptr<InstallAPIOptions> InstallAPIOpts; - /// Dummy tag type whose instance can be passed into the constructor to /// prevent creation of the reference-counted option objects. struct EmptyConstructor {}; @@ -149,7 +145,6 @@ class CompilerInvocationBase { const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { return *PreprocessorOutputOpts; } - const InstallAPIOptions &getInstallAPIOpts() const { return *InstallAPIOpts; } /// @} /// Command line generation. @@ -229,20 +224,19 @@ class CompilerInvocation : public CompilerInvocationBase { /// @{ // Note: These need to be pulled in manually. Otherwise, they get hidden by // the mutable getters with the same names. - using CompilerInvocationBase::getLangOpts; - using CompilerInvocationBase::getTargetOpts; - using CompilerInvocationBase::getDiagnosticOpts; - using CompilerInvocationBase::getHeaderSearchOpts; - using CompilerInvocationBase::getPreprocessorOpts; using CompilerInvocationBase::getAnalyzerOpts; - using CompilerInvocationBase::getMigratorOpts; using CompilerInvocationBase::getAPINotesOpts; using CompilerInvocationBase::getCodeGenOpts; + using CompilerInvocationBase::getDependencyOutputOpts; + using CompilerInvocationBase::getDiagnosticOpts; using CompilerInvocationBase::getFileSystemOpts; using CompilerInvocationBase::getFrontendOpts; - using CompilerInvocationBase::getDependencyOutputOpts; + using CompilerInvocationBase::getHeaderSearchOpts; + using CompilerInvocationBase::getLangOpts; + using CompilerInvocationBase::getMigratorOpts; + using CompilerInvocationBase::getPreprocessorOpts; using CompilerInvocationBase::getPreprocessorOutputOpts; - using CompilerInvocationBase::getInstallAPIOpts; + using CompilerInvocationBase::getTargetOpts; /// @} /// Mutable getters. @@ -264,7 +258,6 @@ class CompilerInvocation : public CompilerInvocationBase { PreprocessorOutputOptions &getPreprocessorOutputOpts() { return *PreprocessorOutputOpts; } - InstallAPIOptions &getInstallAPIOpts() { return *InstallAPIOpts; } /// @} /// Base class internals. diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index b8229252f5ed22..fcce31ac0590ff 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -130,16 +130,6 @@ class GenerateModuleAction : public ASTFrontendAction { bool shouldEraseOutputFiles() override; }; -class InstallAPIAction : public ASTFrontendAction { -protected: - std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; - -public: - static std::unique_ptr<llvm::raw_pwrite_stream> - CreateOutputFile(CompilerInstance &CI, StringRef InFile); -}; - class GenerateInterfaceStubsAction : public ASTFrontendAction { protected: std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 62d16ba542ea4d..53a8681cfdbba0 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -100,9 +100,6 @@ enum ActionKind { /// Only execute frontend initialization. InitOnly, - // Create TextAPI stub. - InstallAPI, - /// Dump information about a module file. ModuleFileInfo, diff --git a/clang/include/clang/Frontend/InstallAPIOptions.h b/clang/include/clang/Frontend/InstallAPIOptions.h deleted file mode 100644 index cf65a3350c6de6..00000000000000 --- a/clang/include/clang/Frontend/InstallAPIOptions.h +++ /dev/null @@ -1,28 +0,0 @@ -//===--- InstallAPIOptions.h ------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_FRONTEND_INSTALLAPIOPTIONS_H -#define LLVM_CLANG_FRONTEND_INSTALLAPIOPTIONS_H - -#include "llvm/TextAPI/PackedVersion.h" - -namespace clang { - -/// InstallAPIOptions - Options for controlling InstallAPI verification and -/// TextAPI output. -class InstallAPIOptions { -public: - /// The install name which is apart of the library's ID. - std::string InstallName; - - /// The current version which is apart of the library's ID. - llvm::MachO::PackedVersion CurrentVersion; -}; -} // namespace clang - -#endif diff --git a/clang/include/clang/InstallAPI/Context.h b/clang/include/clang/InstallAPI/Context.h index a1ff7c12a2f835..649e62529b9743 100644 --- a/clang/include/clang/InstallAPI/Context.h +++ b/clang/include/clang/InstallAPI/Context.h @@ -15,7 +15,8 @@ #define LLVM_CLANG_INSTALLAPI_CONTEXT_H #include "clang/AST/ASTConsumer.h" -#include "clang/Basic/Diagnostic.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/TextAPI/InterfaceFile.h" #include "llvm/TextAPI/RecordVisitor.h" @@ -35,12 +36,6 @@ struct InstallAPIContext { /// Active target triple to parse. llvm::Triple TargetTriple{}; - /// Output stream to write TextAPI file to. - std::unique_ptr<llvm::raw_pwrite_stream> OS = nullptr; - - /// DiagnosticsEngine to report errors. - llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags = nullptr; - /// File Path of output location. StringRef OutputLoc{}; @@ -48,6 +43,12 @@ struct InstallAPIContext { llvm::MachO::FileType FT = llvm::MachO::FileType::TBD_V5; }; +class InstallAPIAction : public ASTFrontendAction { +public: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; +}; + class InstallAPIConsumer : public ASTConsumer { public: InstallAPIConsumer(InstallAPIContext InstallAPICtx) diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp index 7b1a1bb0228c41..741d6cd5a3945c 100644 --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -31,9 +31,8 @@ const char *Action::getClassName(ActionClass AC) { case MigrateJobClass: return "migrator"; case CompileJobClass: return "compiler"; case BackendJobClass: return "backend"; - case AssembleJobClass: return "assembler"; - case InstallAPIJobClass: - return "installapi"; + case AssembleJobClass: + return "assembler"; case IfsMergeJobClass: return "interface-stub-merger"; case LinkJobClass: return "linker"; case LipoJobClass: return "lipo"; @@ -364,11 +363,6 @@ void ExtractAPIJobAction::anchor() {} ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType) : JobAction(ExtractAPIJobClass, Inputs, OutputType) {} -void InstallAPIJobAction::anchor() {} - -InstallAPIJobAction::InstallAPIJobAction(Action *Inputs, types::ID OutputType) - : JobAction(InstallAPIJobClass, Inputs, OutputType) {} - void AnalyzeJobAction::anchor() {} AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 5a323bf4c0c5f4..00e14071a4afec 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4189,11 +4189,6 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, break; } - if (isa<InstallAPIJobAction>(Current)) { - Current = nullptr; - break; - } - // FIXME: Should we include any prior module file outputs as inputs of // later actions in the same command line? @@ -4324,13 +4319,6 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, if (!MergerInputs.empty()) Actions.push_back( C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image)); - } else if (Args.hasArg(options::OPT_installapi)) { - // TODO: Lift restriction once operation can handle multiple inputs. - assert(Inputs.size() == 1 && "InstallAPI action can only handle 1 input"); - const auto [InputType, InputArg] = Inputs.front(); - Action *Current = C.MakeAction<InputAction>(*InputArg, InputType); - Actions.push_back( - C.MakeAction<InstallAPIJobAction>(Current, types::TY_TextAPI)); } for (auto Opt : {options::OPT_print_supported_cpus, @@ -4774,8 +4762,6 @@ Action *Driver::ConstructPhaseAction( return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing); if (Args.hasArg(options::OPT_extract_api)) return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO); - if (Args.hasArg(options::OPT_installapi)) - return C.MakeAction<InstallAPIJobAction>(Input, types::TY_TextAPI); return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC); } case phases::Backend: { @@ -6455,7 +6441,7 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const { // And say "no" if this is not a kind of action clang understands. if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA) && - !isa<ExtractAPIJobAction>(JA) && !isa<InstallAPIJobAction>(JA)) + !isa<ExtractAPIJobAction>(JA)) return false; return true; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 657577cea6c7d8..388030592b4836 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -532,7 +532,6 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::PrecompileJobClass: case Action::PreprocessJobClass: case Action::ExtractAPIJobClass: - case Action::InstallAPIJobClass: case Action::AnalyzeJobClass: case Action::MigrateJobClass: case Action::VerifyPCHJobClass: diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 47305f798c5fee..4459d86e77d5d9 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4939,17 +4939,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *ExtractAPIIgnoresFileArg = Args.getLastArg(options::OPT_extract_api_ignores_EQ)) ExtractAPIIgnoresFileArg->render(Args, CmdArgs); - } else if (isa<InstallAPIJobAction>(JA)) { - if (!Triple.isOSDarwin()) - D.Diag(diag::err_drv_installapi_unsupported) << Triple.str(); - - CmdArgs.push_back("-installapi"); - // Add necessary library arguments for InstallAPI. - if (const Arg *A = Args.getLastArg(options::OPT_install__name)) - A->render(Args, CmdArgs); - if (const Arg *A = Args.getLastArg(options::OPT_current__version)) - A->render(Args, CmdArgs); - } else { assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) && "Invalid action for clang tool."); diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index f443d88b5d30cb..a9166672088459 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -7,7 +7,6 @@ set(LLVM_LINK_COMPONENTS ProfileData Support TargetParser - TextAPI ) add_clang_library(clangFrontend @@ -28,7 +27,6 @@ add_clang_library(clangFrontend HeaderIncludeGen.cpp InitPreprocessor.cpp LayoutOverrideSource.cpp - InstallAPIConsumer.cpp LogDiagnosticPrinter.cpp ModuleDependencyCollector.cpp MultiplexConsumer.cpp @@ -55,7 +53,6 @@ add_clang_library(clangFrontend clangBasic clangDriver clangEdit - clangInstallAPI clangLex clangParse clangSema diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index bcb31243056b7e..8d7b75b56d6129 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -149,8 +149,7 @@ CompilerInvocationBase::CompilerInvocationBase() FSOpts(std::make_shared<FileSystemOptions>()), FrontendOpts(std::make_shared<FrontendOptions>()), DependencyOutputOpts(std::make_shared<DependencyOutputOptions>()), - PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()), - InstallAPIOpts(std::make_shared<InstallAPIOptions>()) {} + PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()) {} CompilerInvocationBase & CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) { @@ -168,7 +167,6 @@ CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) { FrontendOpts = make_shared_copy(X.getFrontendOpts()); DependencyOutputOpts = make_shared_copy(X.getDependencyOutputOpts()); PreprocessorOutputOpts = make_shared_copy(X.getPreprocessorOutputOpts()); - InstallAPIOpts = make_shared_copy(X.getInstallAPIOpts()); } return *this; } @@ -189,7 +187,6 @@ CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) { FrontendOpts = X.FrontendOpts; DependencyOutputOpts = X.DependencyOutputOpts; PreprocessorOutputOpts = X.PreprocessorOutputOpts; - InstallAPIOpts = X.InstallAPIOpts; } return *this; } @@ -2161,34 +2158,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, return Diags.getNumErrors() == NumErrorsBefore; } -static bool ParseInstallAPIArgs(InstallAPIOptions &Opts, ArgList &Args, - DiagnosticsEngine &Diags, - frontend::ActionKind Action) { - unsigned NumErrorsBefore = Diags.getNumErrors(); - - InstallAPIOptions &InstallAPIOpts = Opts; -#define INSTALLAPI_OPTION_WITH_MARSHALLING(...) \ - PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) -#include "clang/Driver/Options.inc" -#undef INSTALLAPI_OPTION_WITH_MARSHALLING - if (Arg *A = Args.getLastArg(options::OPT_current__version)) - Opts.CurrentVersion.parse64(A->getValue()); - - return Diags.getNumErrors() == NumErrorsBefore; -} - -static void GenerateInstallAPIArgs(const InstallAPIOptions &Opts, - ArgumentConsumer Consumer) { - const InstallAPIOptions &InstallAPIOpts = Opts; -#define INSTALLAPI_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) -#include "clang/Driver/Options.inc" -#undef INSTALLAPI_OPTION_WITH_MARSHALLING - if (!Opts.CurrentVersion.empty()) - GenerateArg(Consumer, OPT_current__version, - std::string(Opts.CurrentVersion)); -} - static void GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts, ArgumentConsumer Consumer) { const DependencyOutputOptions &DependencyOutputOpts = Opts; @@ -2588,7 +2557,6 @@ static const auto &getFrontendActionTable() { {frontend::GeneratePCH, OPT_emit_pch}, {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs}, {frontend::InitOnly, OPT_init_only}, - {frontend::InstallAPI, OPT_installapi}, {frontend::ParseSyntaxOnly, OPT_fsyntax_only}, {frontend::ModuleFileInfo, OPT_module_file_info}, {frontend::VerifyPCH, OPT_verify_pch}, @@ -4312,7 +4280,6 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::GenerateHeaderUnit: case frontend::GeneratePCH: case frontend::GenerateInterfaceStubs: - case frontend::InstallAPI: case frontend::ParseSyntaxOnly: case frontend::ModuleFileInfo: case frontend::VerifyPCH: @@ -4687,11 +4654,6 @@ bool CompilerInvocation::CreateFromArgsImpl( Res.getDependencyOutputOpts().Targets.empty()) Diags.Report(diag::err_fe_dependency_file_requires_MT); - if (Args.hasArg(OPT_installapi)) { - ParseInstallAPIArgs(Res.getInstallAPIOpts(), Args, Diags, - Res.getFrontendOpts().ProgramAction); - } - // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses. if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses && !Res.getLangOpts().Sanitize.empty()) { @@ -4882,7 +4844,6 @@ void CompilerInvocationBase::generateCC1CommandLine( GeneratePreprocessorOutputArgs(getPreprocessorOutputOpts(), Consumer, getFrontendOpts().ProgramAction); GenerateDependencyOutputArgs(getDependencyOutputOpts(), Consumer); - GenerateInstallAPIArgs(getInstallAPIOpts(), Consumer); } std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const { diff --git a/clang/lib/Frontend/InstallAPIConsumer.cpp b/clang/lib/Frontend/InstallAPIConsumer.cpp deleted file mode 100644 index c0f22c1a589f38..00000000000000 --- a/clang/lib/Frontend/InstallAPIConsumer.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===--- InstallAPIConsumer.cpp -------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendActions.h" -#include "clang/InstallAPI/Context.h" - -using namespace clang; -using namespace clang::installapi; - -std::unique_ptr<ASTConsumer> -InstallAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - const InstallAPIOptions &Opts = CI.getInstallAPIOpts(); - InstallAPIContext Ctx; - Ctx.BA.InstallName = Opts.InstallName; - Ctx.BA.AppExtensionSafe = CI.getLangOpts().AppExt; - Ctx.BA.CurrentVersion = Opts.CurrentVersion; - // InstallAPI requires two level namespacing. - Ctx.BA.TwoLevelNamespace = true; - Ctx.TargetTriple = CI.getTarget().getTriple(); - - Ctx.Diags = &CI.getDiagnostics(); - Ctx.OutputLoc = CI.getFrontendOpts().OutputFile; - Ctx.OS = CreateOutputFile(CI, InFile); - if (!Ctx.OS) - return nullptr; - return std::make_unique<InstallAPIConsumer>(std::move(Ctx)); -} - -std::unique_ptr<llvm::raw_pwrite_stream> -InstallAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { - std::unique_ptr<raw_pwrite_stream> OS = - CI.createDefaultOutputFile(/*Binary=*/false, InFile, /*Extension=*/"tbd", - /*RemoveFileOnSignal=*/false); - if (!OS) - return nullptr; - return OS; -} diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index a47c474e520a01..7ea0b85a52bbad 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -70,9 +70,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) { case GeneratePCH: return std::make_unique<GeneratePCHAction>(); case GenerateInterfaceStubs: return std::make_unique<GenerateInterfaceStubsAction>(); - case InitOnly: return std::make_unique<InitOnlyAction>(); - case InstallAPI: - return std::make_unique<InstallAPIAction>(); + case InitOnly: + return std::make_unique<InitOnlyAction>(); case ParseSyntaxOnly: return std::make_unique<SyntaxOnlyAction>(); case ModuleFileInfo: return std::make_unique<DumpModuleInfoAction>(); case VerifyPCH: return std::make_unique<VerifyPCHAction>(); diff --git a/clang/lib/InstallAPI/CMakeLists.txt b/clang/lib/InstallAPI/CMakeLists.txt index 1476b737c5e61c..5e4f5f1e60af5a 100644 --- a/clang/lib/InstallAPI/CMakeLists.txt +++ b/clang/lib/InstallAPI/CMakeLists.txt @@ -9,4 +9,5 @@ add_clang_library(clangInstallAPI LINK_LIBS clangAST clangBasic + clangFrontend ) diff --git a/clang/lib/InstallAPI/Context.cpp b/clang/lib/InstallAPI/Context.cpp index d4df52f66560c1..29c15ab6586963 100644 --- a/clang/lib/InstallAPI/Context.cpp +++ b/clang/lib/InstallAPI/Context.cpp @@ -17,11 +17,10 @@ using namespace llvm::MachO; void InstallAPIConsumer::HandleTranslationUnit(ASTContext &Context) { if (Context.getDiagnostics().hasErrorOccurred()) return; - InterfaceFile IF; - // Set library attributes captured through cc1 args. - Target T(Ctx.TargetTriple); - IF.addTarget(T); - IF.setFromBinaryAttrs(Ctx.BA, T); - if (auto Err = TextAPIWriter::writeToStream(*Ctx.OS, IF, Ctx.FT)) - Ctx.Diags->Report(diag::err_cannot_open_file) << Ctx.OutputLoc; +} + +std::unique_ptr<ASTConsumer> +InstallAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { + InstallAPIContext Ctx; + return std::make_unique<InstallAPIConsumer>(std::move(Ctx)); } diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index 841317cef880a2..6b5cb0a18457bd 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -71,6 +71,7 @@ list(APPEND CLANG_TEST_DEPS clang-rename clang-refactor clang-diff + clang-installapi clang-scan-deps clang-linker-wrapper clang-offload-bundler diff --git a/clang/test/Driver/installapi.h b/clang/test/Driver/installapi.h deleted file mode 100644 index 99379b44d1379c..00000000000000 --- a/clang/test/Driver/installapi.h +++ /dev/null @@ -1,13 +0,0 @@ -// Check non-darwin triple is rejected. -// RUN: not %clang -target x86_64-unknown-unknown -installapi %s 2> %t -// RUN: FileCheck --check-prefix INVALID_INSTALLAPI -input-file %t %s - -// INVALID_INSTALLAPI: error: InstallAPI is not supported for 'x86_64-unknown-unknown' - -// Check installapi phases. -// RUN: %clang -target x86_64-apple-macos11 -ccc-print-phases -installapi %s 2> %t -// RUN: FileCheck --check-prefix INSTALLAPI_PHASES -input-file %t %s - -// INSTALLAPI_PHASES: 0: input, -// INSTALLAPI_PHASES: installapi, -// INSTALLAPI_PHASES-SAME: tbd diff --git a/clang/test/InstallAPI/installapi-basic.test b/clang/test/InstallAPI/installapi-basic.test index 8035166d076dab..22b04792ca2c30 100644 --- a/clang/test/InstallAPI/installapi-basic.test +++ b/clang/test/InstallAPI/installapi-basic.test @@ -1,10 +1,17 @@ // RUN: rm -rf %t // RUN: split-file %s %t -// RUN: %clang_cc1 -x objective-c -triple arm64-apple-ios13.0.0 -installapi \ +/// Check basic arguments are captured. +// RUN: clang-installapi -x objective-c -target arm64-apple-ios13.0.0 \ // RUN: -fapplication-extension -current_version 1 -install_name /usr/lib/basic.dylib \ // RUN: %t/basic_inputs.json -o %t/basic.tbd 2>&1 | FileCheck %s --allow-empty // RUN: llvm-readtapi -compare %t/basic.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty +/// Check multiple targets are captured. +// RUN: clang-installapi -x objective-c -target arm64-apple-ios14.1 -target arm64e-apple-ios14.1 \ +// RUN: -fapplication-extension -install_name /usr/lib/basic.dylib \ +// RUN: %t/basic_inputs.json -o %t/multi-targets.tbd 2>&1 | FileCheck %s --allow-empty +// RUN: llvm-readtapi -compare %t/multi-targets.tbd %t/expected-multi.tbd 2>&1 | FileCheck %s --allow-empty + // CHECK-NOT: error: // CHECK-NOT: warning: @@ -32,3 +39,33 @@ }, "tapi_tbd_version": 5 } + +//--- expected-multi.tbd +{ + "main_library": { + "compatibility_versions": [ + { + "version": "0" + }], + "current_versions": [ + { + "version": "0" + }], + "install_names": [ + { + "name": "/usr/lib/basic.dylib" + } + ], + "target_info": [ + { + "min_deployment": "14.1", + "target": "arm64-ios" + }, + { + "min_deployment": "14.1", + "target": "arm64e-ios" + } + ] + }, + "tapi_tbd_version": 5 +} diff --git a/clang/test/InstallAPI/installapi-driver-invalid-options.test b/clang/test/InstallAPI/installapi-driver-invalid-options.test new file mode 100644 index 00000000000000..07b13b4fffc1bf --- /dev/null +++ b/clang/test/InstallAPI/installapi-driver-invalid-options.test @@ -0,0 +1,4 @@ +/// Check non-darwin triple is rejected. +// RUN: not clang-installapi -target x86_64-unknown-unknown %s 2> %t +// RUN: FileCheck --check-prefix INVALID_INSTALLAPI -input-file %t %s +// INVALID_INSTALLAPI: error: InstallAPI is not supported for 'x86_64-unknown-unknown' diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index f93b5d9c945886..e5630a07424c7c 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -90,6 +90,7 @@ "clang-offload-packager", "clang-tblgen", "clang-scan-deps", + "clang-installapi", "opt", "llvm-ifs", "yaml2obj", diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt index f60db6ef0ba345..bdd8004be3e02f 100644 --- a/clang/tools/CMakeLists.txt +++ b/clang/tools/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_subdirectory(clang-linker-wrapper) add_clang_subdirectory(clang-offload-packager) add_clang_subdirectory(clang-offload-bundler) add_clang_subdirectory(clang-scan-deps) +add_clang_subdirectory(clang-installapi) if(HAVE_CLANG_REPL_SUPPORT) add_clang_subdirectory(clang-repl) endif() diff --git a/clang/tools/clang-installapi/CMakeLists.txt b/clang/tools/clang-installapi/CMakeLists.txt new file mode 100644 index 00000000000000..c8dd56db101daa --- /dev/null +++ b/clang/tools/clang-installapi/CMakeLists.txt @@ -0,0 +1,20 @@ +set(LLVM_LINK_COMPONENTS + Support + TargetParser + TextAPI + ) + +add_clang_tool(clang-installapi + ClangInstallAPI.cpp + Options.cpp + + GENERATE_DRIVER + ) + +clang_target_link_libraries(clang-installapi + PRIVATE + clangInstallAPI + clangDriver + clangFrontend + clangTooling + ) diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp new file mode 100644 index 00000000000000..2047b3e555a846 --- /dev/null +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -0,0 +1,124 @@ +#include "Options.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Tool.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/InstallAPI/Context.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/LLVMDriver.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" +#include "llvm/TargetParser/Host.h" +#include "llvm/TextAPI/TextAPIWriter.h" + +using namespace clang; +using namespace clang::installapi; +using namespace llvm::opt; +using namespace llvm::MachO; +using namespace clang::driver::options; + +static InstallAPIContext createContextFromOptions(const Options &Opts) { + InstallAPIContext Ctx; + // InstallAPI requires two level namespacing. + Ctx.BA.TwoLevelNamespace = true; + + Ctx.BA.InstallName = Opts.LinkerOptions.InstallName; + Ctx.BA.CurrentVersion = Opts.LinkerOptions.CurrentVersion; + Ctx.BA.AppExtensionSafe = Opts.LinkerOptions.AppExtensionSafe; + Ctx.FT = Opts.DriverOptions.OutFT; + Ctx.OutputLoc = Opts.DriverOptions.OutputPath; + return Ctx; +} + +static bool run(ArrayRef<const char *> CommandArgs, const char *ProgName) { + // InstallAPI only needs to parse AST, so always force on certain options. + std::vector<const char *> Args; + Args.reserve(CommandArgs.size() + 1); + llvm::copy(CommandArgs, std::back_inserter(Args)); + Args.push_back("-fsyntax-only"); + + // Setup Diagnostics engine. + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); + const llvm::opt::OptTable &ClangOpts= clang::driver::getDriverOptTable(); + unsigned MissingArgIndex, MissingArgCount; + llvm::opt::InputArgList ParsedArgs = ClangOpts.ParseArgs( + ArrayRef(Args).slice(1), MissingArgIndex, MissingArgCount); + ParseDiagnosticArgs(*DiagOpts, ParsedArgs); + + IntrusiveRefCntPtr<DiagnosticsEngine> Diag = new clang::DiagnosticsEngine( + new clang::DiagnosticIDs(), DiagOpts.get(), + new clang::TextDiagnosticPrinter(llvm::errs(), DiagOpts.get())); + + // Create file manager for all file operations. + IntrusiveRefCntPtr<clang::FileManager> FM(new FileManager(clang::FileSystemOptions())); + + // Set up driver to parse input arguments. + auto DriverArgs = llvm::ArrayRef(Args).slice(1); + clang::driver::Driver Driver(ProgName, llvm::sys::getDefaultTargetTriple(), + *Diag, "clang installapi tool"); + Driver.setInstalledDir(llvm::sys::path::parent_path(ProgName)); + auto TargetAndMode = + clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName); + Driver.setTargetAndMode(TargetAndMode); + bool HasError = false; + llvm::opt::InputArgList ArgList = + Driver.ParseArgStrings(DriverArgs, /*UseDriverMode=*/true, HasError); + if (HasError) + return EXIT_FAILURE; + Driver.setCheckInputsExist(false); + + // Capture InstallAPI specific options and diagnose any option errors. + Options Opts(*Diag, FM.get(), ArgList); + if (Diag->hasErrorOccurred()) + return EXIT_FAILURE; + InstallAPIContext Ctx = createContextFromOptions(Opts); + + // Set up compilation. + std::unique_ptr<CompilerInstance> CI(new CompilerInstance()); + CI->setFileManager(FM.get()); + + auto Out = CI->createOutputFile(Ctx.OutputLoc, /*Binary=*/false, + /*RemoveFileOnSignal=*/false, + /*UseTemporary=*/false, + /*CreateMissingDirectories=*/false); + if (!Out) + return EXIT_FAILURE; + + // Assign attributes for serialization. + InterfaceFile IF; + for (const auto &TargetInfo : Opts.DriverOptions.Targets) { + IF.addTarget(TargetInfo.first); + IF.setFromBinaryAttrs(Ctx.BA, TargetInfo.first); + } + + // Write output file and perform CI cleanup. + if (auto Err = TextAPIWriter::writeToStream(*Out, IF, Ctx.FT)) { + Diag->Report(diag::err_cannot_open_file) << Ctx.OutputLoc; + CI->clearOutputFiles(/*EraseFiles=*/true); + return EXIT_FAILURE; + } + + CI->clearOutputFiles(/*EraseFiles=*/false); + return EXIT_SUCCESS; +} + +int clang_installapi_main(int argc, char **argv, + const llvm::ToolContext &ToolContext) { + // Standard set up, so program fails gracefully. + llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); + llvm::PrettyStackTraceProgram StackPrinter(argc, argv); + llvm::llvm_shutdown_obj Shutdown; + + if (llvm::sys::Process::FixupStandardFileDescriptors()) + return 1; + + const char *ProgName = + ToolContext.NeedsPrependArg ? ToolContext.PrependArg : ToolContext.Path; + return run(llvm::ArrayRef(argv, argc), ProgName); +} diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp new file mode 100644 index 00000000000000..700f65062ffb53 --- /dev/null +++ b/clang/tools/clang-installapi/Options.cpp @@ -0,0 +1,106 @@ +#include "Options.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Driver/Driver.h" +#include "llvm/Support/Program.h" +#include "llvm/TargetParser/Host.h" + +using namespace clang::driver; +using namespace clang::driver::options; +using namespace llvm::opt; +using namespace llvm::MachO; + +namespace clang { +namespace installapi { + +bool Options::processDriverOptions(InputArgList& Args) { + // Handle inputs. + llvm::vfs::Status Stat; + for (const auto &Path : Args.getAllArgValues(OPT_INPUT)) { + if (FM->getNoncachedStatValue(Path, Stat) || !Stat.exists()) { + Diags->Report(clang::diag::err_drv_no_such_file) << Path; + return false; + } + DriverOptions.FileLists.push_back(Path); + } + + // Handle output. + SmallString<PATH_MAX> OutputPath; + if (auto *Arg = Args.getLastArg(OPT_o)) { + OutputPath = Arg->getValue(); + if (OutputPath != "-") + FM->makeAbsolutePath(OutputPath); + DriverOptions.OutputPath = std::string(OutputPath); + } + + // Do basic error checking first for mixing -target and -arch options. + auto *ArgArch = Args.getLastArgNoClaim(OPT_arch); + auto *ArgTarget = Args.getLastArgNoClaim(OPT_target); + auto *ArgTargetVariant = + Args.getLastArgNoClaim(OPT_darwin_target_variant_triple); + if (ArgArch && (ArgTarget || ArgTargetVariant)) { + Diags->Report(clang::diag::err_drv_argument_not_allowed_with) + << ArgArch->getAsString(Args) + << (ArgTarget ? ArgTarget : ArgTargetVariant)->getAsString(Args); + return false; + } + + auto *ArgMinTargetOS = Args.getLastArgNoClaim(OPT_mtargetos_EQ); + if ((ArgTarget || ArgTargetVariant) && ArgMinTargetOS) { + Diags->Report(clang::diag::err_drv_cannot_mix_options) + << ArgTarget->getAsString(Args) << ArgMinTargetOS->getAsString(Args); + return false; + } + + // Capture target triples first. + if (ArgTarget) { + for (auto *Arg : Args.filtered(OPT_target)) { + llvm::Triple TargetTriple(Arg->getValue()); + Target TAPITarget = Target(TargetTriple); + if ((TAPITarget.Arch == AK_unknown) || + (TAPITarget.Platform == PLATFORM_UNKNOWN)) { + Diags->Report(clang::diag::err_drv_installapi_unsupported) + << TargetTriple.str(); + return false; + } + DriverOptions.Targets[TAPITarget] = TargetTriple; + } + } + + return true; +} +bool Options::processLinkerOptions(InputArgList &Args) { + // TODO: add error handling. + + // Required arguments. + if (const Arg *A = Args.getLastArg(options::OPT_install__name)) + LinkerOptions.InstallName = A->getValue(); + + // Defaulted or optional arguments. + if (auto *Arg = Args.getLastArg(OPT_current__version)) + LinkerOptions.CurrentVersion.parse64(Arg->getValue()); + + LinkerOptions.IsDylib = Args.hasArg(OPT_dynamiclib); + + LinkerOptions.AppExtensionSafe = + Args.hasFlag(OPT_fapplication_extension, OPT_fno_application_extension, + /*Default=*/LinkerOptions.AppExtensionSafe); + + if (::getenv("LD_NO_ENCRYPT") != nullptr) + LinkerOptions.AppExtensionSafe = true; + + if (::getenv("LD_APPLICATION_EXTENSION_SAFE") != nullptr) + LinkerOptions.AppExtensionSafe = true; + return true; +} + +Options::Options(DiagnosticsEngine &Diag, FileManager *FM, + InputArgList &ArgList) + : Diags(&Diag), FM(FM) { + if (!processDriverOptions(ArgList)) + return; + + if (!processLinkerOptions(ArgList)) + return; +} +} +} diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h new file mode 100644 index 00000000000000..85eaeb4ee86771 --- /dev/null +++ b/clang/tools/clang-installapi/Options.h @@ -0,0 +1,85 @@ +//===--- clang-installapi/Options.h - Options -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_CLANG_INSTALLAPI_OPTIONS_H +#define LLVM_CLANG_TOOLS_CLANG_INSTALLAPI_OPTIONS_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/FileManager.h" +#include "clang/Frontend/FrontendOptions.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/Program.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/TextAPI/Architecture.h" +#include "llvm/TextAPI/InterfaceFile.h" +#include "llvm/TextAPI/PackedVersion.h" +#include "llvm/TextAPI/Platform.h" +#include "llvm/TextAPI/Target.h" +#include "llvm/TextAPI/Utils.h" +#include <set> +#include <string> +#include <vector> + +namespace clang { +namespace installapi { +using Macro = std::pair<std::string, bool /*isUndef*/>; + +struct DriverOptions { + /// \brief Path to input file lists (JSON). + llvm::MachO::PathSeq FileLists; + + /// \brief Mappings of target triples & tapi targets to build for. + std::map<llvm::MachO::Target, llvm::Triple> Targets; + + /// \brief Output path. + std::string OutputPath; + + /// \brief File encoding to print. + llvm::MachO::FileType OutFT = llvm::MachO::FileType::TBD_V5; +}; + +struct LinkerOptions { + /// \brief The install name to use for the dynamic library. + std::string InstallName; + + /// \brief The current version to use for the dynamic library. + llvm::MachO::PackedVersion CurrentVersion; + + /// \brief Is application extension safe. + bool AppExtensionSafe = false; + + /// \brief Set if we should scan for a dynamic library and not a framework. + bool IsDylib = false; + +}; + +class Options { +private: + bool processDriverOptions(llvm::opt::InputArgList &Args); + bool processLinkerOptions(llvm::opt::InputArgList &Args); + +public: + + /// The various options grouped together. + DriverOptions DriverOptions; + LinkerOptions LinkerOptions; + + Options() = delete; + + /// \brief Constructor for options. + Options(clang::DiagnosticsEngine &Diag, FileManager* FM, llvm::opt::InputArgList& Args); + +private: + DiagnosticsEngine* Diags; + FileManager* FM; +}; + +} +} +#endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits