Skip to content

Commit 21bd0e0

Browse files
committed
[InstallAPI] Set 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.
1 parent bd648b5 commit 21bd0e0

File tree

12 files changed

+479
-1
lines changed

12 files changed

+479
-1
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===- InstallAPI/Context.h -------------------------------------*- C++ -*-===//
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+
#ifndef LLVM_CLANG_INSTALLAPI_CONTEXT_H
10+
#define LLVM_CLANG_INSTALLAPI_CONTEXT_H
11+
12+
#include "llvm/TextAPI/InterfaceFile.h"
13+
#include "llvm/TextAPI/RecordVisitor.h"
14+
#include "llvm/TextAPI/RecordsSlice.h"
15+
16+
namespace clang {
17+
namespace installapi {
18+
19+
/// Struct used for generating validating InstallAPI.
20+
/// The attributes captured represent all necessary information
21+
/// to generate TextAPI output.
22+
struct InstallAPIContext {
23+
24+
/// Library attributes that are typically passed as linker inputs.
25+
llvm::MachO::RecordsSlice::BinaryAttrs BA;
26+
27+
/// Active target triple to parse.
28+
llvm::Triple TargetTriple{};
29+
30+
/// File Path of output location.
31+
StringRef OutputLoc{};
32+
33+
/// What encoding to write output as.
34+
llvm::MachO::FileType FT = llvm::MachO::FileType::TBD_V5;
35+
};
36+
37+
} // namespace installapi
38+
} // namespace clang
39+
40+
#endif // LLVM_CLANG_INSTALLAPI_CONTEXT_H

clang/lib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ add_subdirectory(Tooling)
2323
add_subdirectory(DirectoryWatcher)
2424
add_subdirectory(Index)
2525
add_subdirectory(IndexSerialization)
26+
add_subdirectory(InstallAPI)
2627
add_subdirectory(StaticAnalyzer)
2728
add_subdirectory(Format)
2829
if(CLANG_INCLUDE_TESTS)

clang/lib/InstallAPI/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ set(LLVM_LINK_COMPONENTS
44
)
55

66
add_clang_library(clangInstallAPI
7-
Context.cpp
87
FileList.cpp
98
HeaderFile.cpp
109

clang/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ list(APPEND CLANG_TEST_DEPS
7171
clang-rename
7272
clang-refactor
7373
clang-diff
74+
clang-installapi
7475
clang-scan-deps
7576
clang-linker-wrapper
7677
clang-offload-bundler
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
/// Check basic arguments are captured.
4+
// RUN: clang-installapi -x objective-c -target arm64-apple-ios13.0.0 \
5+
// RUN: -fapplication-extension -current_version 1 -install_name /usr/lib/basic.dylib \
6+
// RUN: %t/basic_inputs.json -o %t/basic.tbd 2>&1 | FileCheck %s --allow-empty
7+
// RUN: llvm-readtapi -compare %t/basic.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty
8+
9+
/// Check multiple targets are captured.
10+
// RUN: clang-installapi -x objective-c -target arm64-apple-ios14.1 -target arm64e-apple-ios14.1 \
11+
// RUN: -fapplication-extension -install_name /usr/lib/basic.dylib \
12+
// RUN: %t/basic_inputs.json -o %t/multi-targets.tbd 2>&1 | FileCheck %s --allow-empty
13+
// RUN: llvm-readtapi -compare %t/multi-targets.tbd %t/expected-multi.tbd 2>&1 | FileCheck %s --allow-empty
14+
15+
// CHECK-NOT: error:
16+
// CHECK-NOT: warning:
17+
18+
//--- basic_inputs.json
19+
20+
//--- expected.tbd
21+
{
22+
"main_library": {
23+
"compatibility_versions": [
24+
{
25+
"version": "0"
26+
}
27+
],
28+
"install_names": [
29+
{
30+
"name": "/usr/lib/basic.dylib"
31+
}
32+
],
33+
"target_info": [
34+
{
35+
"min_deployment": "13.0.0",
36+
"target": "arm64-ios"
37+
}
38+
]
39+
},
40+
"tapi_tbd_version": 5
41+
}
42+
43+
//--- expected-multi.tbd
44+
{
45+
"main_library": {
46+
"compatibility_versions": [
47+
{
48+
"version": "0"
49+
}],
50+
"current_versions": [
51+
{
52+
"version": "0"
53+
}],
54+
"install_names": [
55+
{
56+
"name": "/usr/lib/basic.dylib"
57+
}
58+
],
59+
"target_info": [
60+
{
61+
"min_deployment": "14.1",
62+
"target": "arm64-ios"
63+
},
64+
{
65+
"min_deployment": "14.1",
66+
"target": "arm64e-ios"
67+
}
68+
]
69+
},
70+
"tapi_tbd_version": 5
71+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// Check non-darwin triple is rejected.
2+
// RUN: not clang-installapi -target x86_64-unknown-unknown %s 2> %t
3+
// RUN: FileCheck --check-prefix INVALID_INSTALLAPI -input-file %t %s
4+
// INVALID_INSTALLAPI: error: unsupported option 'installapi' for target 'x86_64-unknown-unknown'
5+

clang/test/lit.cfg.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,15 @@
9090
"clang-offload-packager",
9191
"clang-tblgen",
9292
"clang-scan-deps",
93+
"clang-installapi",
9394
"opt",
9495
"llvm-ifs",
9596
"yaml2obj",
9697
"clang-linker-wrapper",
9798
"llvm-lto",
9899
"llvm-lto2",
99100
"llvm-profdata",
101+
"llvm-readtapi",
100102
ToolSubst(
101103
"%clang_extdef_map",
102104
command=FindTool("clang-extdef-mapping"),

clang/tools/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ add_clang_subdirectory(clang-linker-wrapper)
1212
add_clang_subdirectory(clang-offload-packager)
1313
add_clang_subdirectory(clang-offload-bundler)
1414
add_clang_subdirectory(clang-scan-deps)
15+
add_clang_subdirectory(clang-installapi)
1516
if(HAVE_CLANG_REPL_SUPPORT)
1617
add_clang_subdirectory(clang-repl)
1718
endif()
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
set(LLVM_LINK_COMPONENTS
2+
Support
3+
TargetParser
4+
TextAPI
5+
)
6+
7+
add_clang_tool(clang-installapi
8+
ClangInstallAPI.cpp
9+
Options.cpp
10+
11+
GENERATE_DRIVER
12+
)
13+
14+
clang_target_link_libraries(clang-installapi
15+
PRIVATE
16+
clangInstallAPI
17+
clangDriver
18+
clangFrontend
19+
clangTooling
20+
)
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
//===-- ClangInstallAPI.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+
// This is the entry point to clang-installapi; it is a wrapper
10+
// for functionality in the InstallAPI clang library.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "Options.h"
15+
#include "clang/Basic/DiagnosticIDs.h"
16+
#include "clang/Driver/Driver.h"
17+
#include "clang/Driver/DriverDiagnostic.h"
18+
#include "clang/Frontend/CompilerInstance.h"
19+
#include "clang/Frontend/TextDiagnosticPrinter.h"
20+
#include "clang/InstallAPI/Context.h"
21+
#include "llvm/ADT/ArrayRef.h"
22+
#include "llvm/Option/Option.h"
23+
#include "llvm/Support/CommandLine.h"
24+
#include "llvm/Support/LLVMDriver.h"
25+
#include "llvm/Support/ManagedStatic.h"
26+
#include "llvm/Support/PrettyStackTrace.h"
27+
#include "llvm/Support/Process.h"
28+
#include "llvm/Support/Signals.h"
29+
#include "llvm/TargetParser/Host.h"
30+
#include "llvm/TextAPI/TextAPIWriter.h"
31+
32+
using namespace clang;
33+
using namespace clang::installapi;
34+
using namespace clang::driver::options;
35+
using namespace llvm::opt;
36+
using namespace llvm::MachO;
37+
38+
static InstallAPIContext createContextFromOptions(const Options &Opts) {
39+
InstallAPIContext Ctx;
40+
// InstallAPI requires two level namespacing.
41+
Ctx.BA.TwoLevelNamespace = true;
42+
43+
Ctx.BA.InstallName = Opts.LinkerOpts.InstallName;
44+
Ctx.BA.CurrentVersion = Opts.LinkerOpts.CurrentVersion;
45+
Ctx.BA.AppExtensionSafe = Opts.LinkerOpts.AppExtensionSafe;
46+
Ctx.FT = Opts.DriverOpts.OutFT;
47+
Ctx.OutputLoc = Opts.DriverOpts.OutputPath;
48+
return Ctx;
49+
}
50+
51+
static bool run(ArrayRef<const char *> CommandArgs, const char *ProgName) {
52+
// InstallAPI only needs to parse AST, so always force on certain options.
53+
std::vector<const char *> Args;
54+
Args.reserve(CommandArgs.size() + 1);
55+
llvm::copy(CommandArgs, std::back_inserter(Args));
56+
Args.push_back("-fsyntax-only");
57+
58+
// Setup Diagnostics engine.
59+
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
60+
const llvm::opt::OptTable &ClangOpts = clang::driver::getDriverOptTable();
61+
unsigned MissingArgIndex, MissingArgCount;
62+
llvm::opt::InputArgList ParsedArgs = ClangOpts.ParseArgs(
63+
ArrayRef(Args).slice(1), MissingArgIndex, MissingArgCount);
64+
ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
65+
66+
IntrusiveRefCntPtr<DiagnosticsEngine> Diag = new clang::DiagnosticsEngine(
67+
new clang::DiagnosticIDs(), DiagOpts.get(),
68+
new clang::TextDiagnosticPrinter(llvm::errs(), DiagOpts.get()));
69+
70+
// Create file manager for all file operations.
71+
IntrusiveRefCntPtr<clang::FileManager> FM(
72+
new FileManager(clang::FileSystemOptions()));
73+
74+
// Set up driver to parse input arguments.
75+
auto DriverArgs = llvm::ArrayRef(Args).slice(1);
76+
clang::driver::Driver Driver(ProgName, llvm::sys::getDefaultTargetTriple(),
77+
*Diag, "clang installapi tool");
78+
Driver.setInstalledDir(llvm::sys::path::parent_path(ProgName));
79+
auto TargetAndMode =
80+
clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName);
81+
Driver.setTargetAndMode(TargetAndMode);
82+
bool HasError = false;
83+
llvm::opt::InputArgList ArgList =
84+
Driver.ParseArgStrings(DriverArgs, /*UseDriverMode=*/true, HasError);
85+
if (HasError)
86+
return EXIT_FAILURE;
87+
Driver.setCheckInputsExist(false);
88+
89+
// Capture InstallAPI specific options and diagnose any option errors.
90+
Options Opts(*Diag, FM.get(), ArgList);
91+
if (Diag->hasErrorOccurred())
92+
return EXIT_FAILURE;
93+
InstallAPIContext Ctx = createContextFromOptions(Opts);
94+
95+
// Set up compilation.
96+
std::unique_ptr<CompilerInstance> CI(new CompilerInstance());
97+
CI->setFileManager(FM.get());
98+
CI->createDiagnostics();
99+
if (!CI->hasDiagnostics())
100+
return EXIT_FAILURE;
101+
102+
auto Out = CI->createOutputFile(Ctx.OutputLoc, /*Binary=*/false,
103+
/*RemoveFileOnSignal=*/false,
104+
/*UseTemporary=*/false,
105+
/*CreateMissingDirectories=*/false);
106+
if (!Out)
107+
return EXIT_FAILURE;
108+
109+
// Assign attributes for serialization.
110+
InterfaceFile IF;
111+
for (const auto &TargetInfo : Opts.DriverOpts.Targets) {
112+
IF.addTarget(TargetInfo.first);
113+
IF.setFromBinaryAttrs(Ctx.BA, TargetInfo.first);
114+
}
115+
116+
// Write output file and perform CI cleanup.
117+
if (auto Err = TextAPIWriter::writeToStream(*Out, IF, Ctx.FT)) {
118+
Diag->Report(diag::err_cannot_open_file) << Ctx.OutputLoc;
119+
CI->clearOutputFiles(/*EraseFiles=*/true);
120+
return EXIT_FAILURE;
121+
}
122+
123+
CI->clearOutputFiles(/*EraseFiles=*/false);
124+
return EXIT_SUCCESS;
125+
}
126+
127+
int clang_installapi_main(int argc, char **argv,
128+
const llvm::ToolContext &ToolContext) {
129+
// Standard set up, so program fails gracefully.
130+
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
131+
llvm::PrettyStackTraceProgram StackPrinter(argc, argv);
132+
llvm::llvm_shutdown_obj Shutdown;
133+
134+
if (llvm::sys::Process::FixupStandardFileDescriptors())
135+
return EXIT_FAILURE;
136+
137+
const char *ProgName =
138+
ToolContext.NeedsPrependArg ? ToolContext.PrependArg : ToolContext.Path;
139+
return run(llvm::ArrayRef(argv, argc), ProgName);
140+
}

0 commit comments

Comments
 (0)