Skip to content

[clang][InstallAPI] Introduce basic driver to write out tbd files #81571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -804,4 +804,7 @@ def warn_android_unversioned_fallback : Warning<

def err_drv_triple_version_invalid : Error<
"version '%0' in target triple '%1' is invalid">;

def err_drv_installapi_unsupported : Error<
"the clang compiler does not support '%0' for InstallAPI">;
}
12 changes: 12 additions & 0 deletions clang/include/clang/Driver/Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class Action {
PreprocessJobClass,
PrecompileJobClass,
ExtractAPIJobClass,
InstallAPIJobClass,
AnalyzeJobClass,
MigrateJobClass,
CompileJobClass,
Expand Down Expand Up @@ -448,6 +449,17 @@ 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;

Expand Down
12 changes: 10 additions & 2 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ 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.
Expand Down Expand Up @@ -1114,7 +1116,8 @@ 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">;
def current__version : JoinedOrSeparate<["-"], "current_version">,
Visibility<[ClangOption, CC1Option]>;
def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group<clang_i_Group>,
HelpText<"Add directory to the C++ SYSTEM include search path">,
Visibility<[ClangOption, CC1Option]>,
Expand Down Expand Up @@ -1529,6 +1532,9 @@ def static_libsan : Flag<["-"], "static-libsan">,
HelpText<"Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin)">;
def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>;
def fasm : Flag<["-"], "fasm">, Group<f_Group>;
def installapi : Flag<["-"], "installapi">,
Visibility<[ClangOption, CC1Option]>, Group<Action_Group>,
HelpText<"Create a text-based stub file by scanning header files">;

defm assume_unique_vtables : BoolFOption<"assume-unique-vtables",
CodeGenOpts<"AssumeUniqueVTables">, DefaultTrue,
Expand Down Expand Up @@ -4291,7 +4297,9 @@ 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">;
def install__name : Separate<["-"], "install_name">,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString<InstallAPIOpts<"InstallName">>;
def iprefix : JoinedOrSeparate<["-"], "iprefix">, Group<clang_i_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">, MetaVarName<"<dir>">;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Driver/Types.def
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ 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::Compile)
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)
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Frontend/CompilerInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,13 @@ class CompilerInstance : public ModuleLoader {
return Invocation->getFrontendOpts();
}

InstallAPIOptions &getInstallAPIOpts() {
return Invocation->getInstallAPIOpts();
}
const InstallAPIOptions &getInstallAPIOpts() const {
return Invocation->getInstallAPIOpts();
}

HeaderSearchOptions &getHeaderSearchOpts() {
return Invocation->getHeaderSearchOpts();
}
Expand Down
9 changes: 8 additions & 1 deletion clang/include/clang/Frontend/CompilerInvocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
#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"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include <memory>
#include <string>

Expand Down Expand Up @@ -111,6 +112,9 @@ 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 {};
Expand Down Expand Up @@ -145,6 +149,7 @@ class CompilerInvocationBase {
const PreprocessorOutputOptions &getPreprocessorOutputOpts() const {
return *PreprocessorOutputOpts;
}
const InstallAPIOptions &getInstallAPIOpts() const { return *InstallAPIOpts; }
/// @}

/// Command line generation.
Expand Down Expand Up @@ -237,6 +242,7 @@ class CompilerInvocation : public CompilerInvocationBase {
using CompilerInvocationBase::getFrontendOpts;
using CompilerInvocationBase::getDependencyOutputOpts;
using CompilerInvocationBase::getPreprocessorOutputOpts;
using CompilerInvocationBase::getInstallAPIOpts;
/// @}

/// Mutable getters.
Expand All @@ -258,6 +264,7 @@ class CompilerInvocation : public CompilerInvocationBase {
PreprocessorOutputOptions &getPreprocessorOutputOpts() {
return *PreprocessorOutputOpts;
}
InstallAPIOptions &getInstallAPIOpts() { return *InstallAPIOpts; }
/// @}

/// Base class internals.
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Frontend/FrontendActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ 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,
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ enum ActionKind {
/// Only execute frontend initialization.
InitOnly,

// Create TextAPI stub.
InstallAPI,

/// Dump information about a module file.
ModuleFileInfo,

Expand Down
28 changes: 28 additions & 0 deletions clang/include/clang/Frontend/InstallAPIOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===--- 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
65 changes: 65 additions & 0 deletions clang/include/clang/InstallAPI/Context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//===- InstallAPI/Context.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
//
//===----------------------------------------------------------------------===//
//
// Top level types for interacting with the generic clang driver and frontend
// for InstallAPI operations.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INSTALLAPI_CONTEXT_H
#define LLVM_CLANG_INSTALLAPI_CONTEXT_H

#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/TextAPI/InterfaceFile.h"
#include "llvm/TextAPI/RecordVisitor.h"
#include "llvm/TextAPI/RecordsSlice.h"

namespace clang {
namespace installapi {

/// Struct used for generating validating InstallAPI.
/// The attributes captured represent all necessary information
/// to generate TextAPI output.
struct InstallAPIContext {

/// Library attributes that are typically passed as linker inputs.
llvm::MachO::RecordsSlice::BinaryAttrs BA;

/// 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{};

/// What encoding to write output as.
llvm::MachO::FileType FT = llvm::MachO::FileType::TBD_V5;
};

class InstallAPIConsumer : public ASTConsumer {
public:
InstallAPIConsumer(InstallAPIContext InstallAPICtx)
: Ctx(std::move(InstallAPICtx)) {}

void HandleTranslationUnit(ASTContext &ASTContext) override;

private:
InstallAPIContext Ctx;
};

} // namespace installapi
} // namespace clang

#endif // LLVM_CLANG_INSTALLAPI_CONTEXT_H
1 change: 1 addition & 0 deletions clang/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ add_subdirectory(Tooling)
add_subdirectory(DirectoryWatcher)
add_subdirectory(Index)
add_subdirectory(IndexSerialization)
add_subdirectory(InstallAPI)
add_subdirectory(StaticAnalyzer)
add_subdirectory(Format)
if(CLANG_INCLUDE_TESTS)
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Driver/Action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const char *Action::getClassName(ActionClass AC) {
case CompileJobClass: return "compiler";
case BackendJobClass: return "backend";
case AssembleJobClass: return "assembler";
case InstallAPIJobClass:
return "installapi";
case IfsMergeJobClass: return "interface-stub-merger";
case LinkJobClass: return "linker";
case LipoJobClass: return "lipo";
Expand Down Expand Up @@ -362,6 +364,11 @@ 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)
Expand Down
15 changes: 14 additions & 1 deletion clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4189,6 +4189,11 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
break;
}

if (auto *IAA = dyn_cast<InstallAPIJobAction>(Current)) {
Current = nullptr;
break;
}

// FIXME: Should we include any prior module file outputs as inputs of
// later actions in the same command line?

Expand Down Expand Up @@ -4319,6 +4324,12 @@ 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)) {
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,
Expand Down Expand Up @@ -4762,6 +4773,8 @@ 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: {
Expand Down Expand Up @@ -6441,7 +6454,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<ExtractAPIJobAction>(JA) && !isa<InstallAPIJobAction>(JA))
return false;

return true;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ 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:
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4939,6 +4939,17 @@ 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.");
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ add_clang_library(clangFrontend
HeaderIncludeGen.cpp
InitPreprocessor.cpp
LayoutOverrideSource.cpp
InstallAPIConsumer.cpp
LogDiagnosticPrinter.cpp
ModuleDependencyCollector.cpp
MultiplexConsumer.cpp
Expand All @@ -53,6 +54,7 @@ add_clang_library(clangFrontend
clangBasic
clangDriver
clangEdit
clangInstallAPI
clangLex
clangParse
clangSema
Expand Down
Loading