aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Frontend/CompilerInvocation.cpp
diff options
context:
space:
mode:
authorCyndy Ishida <cyndy_ishida@apple.com>2024-02-13 18:52:11 -0800
committerGitHub <noreply@github.com>2024-02-13 18:52:11 -0800
commit09e98950bfcff7ad376922932efb2b56e4db9898 (patch)
tree9b41974d9abcf9ac73f53e9d6fa78057c781bf56 /clang/lib/Frontend/CompilerInvocation.cpp
parent14b0d0de1fb3e55d16fac70a69980a003106d0aa (diff)
downloadllvm-09e98950bfcff7ad376922932efb2b56e4db9898.zip
llvm-09e98950bfcff7ad376922932efb2b56e4db9898.tar.gz
llvm-09e98950bfcff7ad376922932efb2b56e4db9898.tar.bz2
[clang][InstallAPI] Introduce basic driver to write out tbd files (#81571)
This introduces a basic outline of installapi as a clang driver option. It captures relevant information as cc1 args, which are common arguments already passed to the linker to encode into TBD file outputs. This is effectively an upstream for what already exists as `tapi installapi` in Xcode toolchains, but directly in Clang. This patch does not handle any AST traversing on input yet. InstallAPI is broadly an operation that takes a series of header files that represent a single dynamic library and generates a TBD file out of it which represents all the linkable symbols and necessary attributes for statically linking in clients. It is the linkable object in all Apple SDKs and when building dylibs in Xcode. `clang -installapi` also will support verification where it compares all the information recorded for the TBD files against the already built binary, to catch possible mismatches like when a declaration is missing a definition for an exported symbol.
Diffstat (limited to 'clang/lib/Frontend/CompilerInvocation.cpp')
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp41
1 files changed, 40 insertions, 1 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 8d7b75b..bcb3124 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -149,7 +149,8 @@ CompilerInvocationBase::CompilerInvocationBase()
FSOpts(std::make_shared<FileSystemOptions>()),
FrontendOpts(std::make_shared<FrontendOptions>()),
DependencyOutputOpts(std::make_shared<DependencyOutputOptions>()),
- PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()) {}
+ PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()),
+ InstallAPIOpts(std::make_shared<InstallAPIOptions>()) {}
CompilerInvocationBase &
CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) {
@@ -167,6 +168,7 @@ 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;
}
@@ -187,6 +189,7 @@ CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) {
FrontendOpts = X.FrontendOpts;
DependencyOutputOpts = X.DependencyOutputOpts;
PreprocessorOutputOpts = X.PreprocessorOutputOpts;
+ InstallAPIOpts = X.InstallAPIOpts;
}
return *this;
}
@@ -2158,6 +2161,34 @@ 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;
@@ -2557,6 +2588,7 @@ 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},
@@ -4280,6 +4312,7 @@ 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:
@@ -4654,6 +4687,11 @@ 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()) {
@@ -4844,6 +4882,7 @@ void CompilerInvocationBase::generateCC1CommandLine(
GeneratePreprocessorOutputArgs(getPreprocessorOutputOpts(), Consumer,
getFrontendOpts().ProgramAction);
GenerateDependencyOutputArgs(getDependencyOutputOpts(), Consumer);
+ GenerateInstallAPIArgs(getInstallAPIOpts(), Consumer);
}
std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const {