Skip to content

Commit a994b56

Browse files
committed
[clang][InstallAPI] Add input file support to library
This patch adds support for expected InstallAPI inputs. InstallAPI accepts a well defined filelist of headers and how those headers represent a single library. InstallAPI captures header files to determine linkable symbols to then compare against what was compiled in a binary dylib and generate TBD files.
1 parent ec5f4a4 commit a994b56

File tree

10 files changed

+672
-4
lines changed

10 files changed

+672
-4
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//===- InstallAPI/FileList.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+
/// The JSON file list parser is used to communicate input to InstallAPI.
10+
///
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_INSTALLAPI_FILELIST_H
14+
#define LLVM_CLANG_INSTALLAPI_FILELIST_H
15+
16+
#include "clang/Basic/Diagnostic.h"
17+
#include "clang/Basic/FileManager.h"
18+
#include "clang/InstallAPI/HeaderFile.h"
19+
#include "llvm/Support/Error.h"
20+
#include "llvm/Support/MemoryBuffer.h"
21+
22+
namespace clang {
23+
namespace installapi {
24+
25+
/// Abstract Interface for reading FileList JSON Input.
26+
class FileListReader {
27+
class Implementation;
28+
29+
Implementation &Impl;
30+
31+
FileListReader(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
32+
llvm::Error &Err);
33+
34+
public:
35+
static llvm::Expected<std::unique_ptr<FileListReader>>
36+
get(std::unique_ptr<llvm::MemoryBuffer> InputBuffer);
37+
38+
~FileListReader();
39+
40+
FileListReader(const FileListReader &) = delete;
41+
FileListReader &operator=(const FileListReader &) = delete;
42+
43+
int getVersion() const;
44+
45+
struct HeaderInfo {
46+
HeaderType Type;
47+
std::string Path;
48+
std::optional<clang::Language> Language;
49+
};
50+
51+
/// Visitor used when walking the contents of the file list.
52+
class Visitor {
53+
public:
54+
virtual ~Visitor();
55+
56+
virtual void visitHeaderFile(HeaderInfo &header) = 0;
57+
};
58+
59+
/// Visit the contents of the header list file, passing each entity to the
60+
/// given visitor. It visits in the same order as they appear in the json
61+
/// file.
62+
void visit(Visitor &visitor);
63+
};
64+
65+
class FileListVisitor final : public FileListReader::Visitor {
66+
FileManager &FM;
67+
DiagnosticsEngine &Diag;
68+
HeaderSeq &HeaderFiles;
69+
70+
public:
71+
FileListVisitor(FileManager &FM, DiagnosticsEngine &Diag,
72+
HeaderSeq &HeaderFiles)
73+
: FM(FM), Diag(Diag), HeaderFiles(HeaderFiles) {}
74+
75+
void visitHeaderFile(FileListReader::HeaderInfo &Header) override;
76+
};
77+
} // namespace installapi
78+
} // namespace clang
79+
80+
#endif // LLVM_CLANG_INSTALLAPI_FILELIST_H
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//===- InstallAPI/HeaderFile.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+
/// Representations of a library's headers for InstallAPI.
10+
///
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_INSTALLAPI_HEADERFILE_H
14+
#define LLVM_CLANG_INSTALLAPI_HEADERFILE_H
15+
16+
#include "clang/Basic/LangStandard.h"
17+
#include "llvm/ADT/StringRef.h"
18+
#include "llvm/Support/Regex.h"
19+
#include <optional>
20+
#include <string>
21+
22+
namespace clang::installapi {
23+
24+
const llvm::Regex DarwinFwkHeaderRule("/(.+)\\.framework/(.+)?Headers/(.+)");
25+
26+
enum class HeaderType {
27+
/// Represents declarations accessible to all clients.
28+
Public,
29+
/// Represents declarations accessible to a disclosed set of clients.
30+
Private,
31+
/// Represents declarations only accessible as implementation details to the
32+
/// input library.
33+
Project,
34+
};
35+
36+
class HeaderFile {
37+
/// Full input path to header.
38+
std::string FullPath;
39+
/// Access level of header.
40+
HeaderType Type;
41+
/// Expected way header will be included by clients.
42+
std::string IncludeName;
43+
/// Supported language mode for header.
44+
std::optional<clang::Language> Language;
45+
46+
public:
47+
HeaderFile(StringRef FullPath, HeaderType Type,
48+
StringRef IncludeName = StringRef(),
49+
std::optional<clang::Language> Language = std::nullopt)
50+
: FullPath(FullPath), Type(Type), IncludeName(IncludeName),
51+
Language(Language) {}
52+
53+
HeaderType getType() const { return Type; }
54+
};
55+
56+
/// Assemble expected way header will be included by clients.
57+
/// As in what maps inside the brackets of `#include <IncludeName.h>`
58+
/// For example,
59+
/// "/System/Library/Frameworks/Foo.framework/Headers/Foo.h" returns
60+
/// "Foo/Foo.h"
61+
///
62+
/// \param FullPath Path to the header file which includes the library
63+
/// structure.
64+
std::optional<std::string> createIncludeHeaderName(const StringRef FullPath);
65+
using HeaderSeq = std::vector<HeaderFile>;
66+
67+
} // namespace clang::installapi
68+
69+
#endif // LLVM_CLANG_INSTALLAPI_HEADERFILE_H

clang/lib/ExtractAPI/ExtractAPIConsumer.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "clang/Frontend/CompilerInstance.h"
3131
#include "clang/Frontend/FrontendOptions.h"
3232
#include "clang/Frontend/MultiplexConsumer.h"
33+
#include "clang/InstallAPI/HeaderFile.h"
3334
#include "clang/Lex/MacroInfo.h"
3435
#include "clang/Lex/PPCallbacks.h"
3536
#include "clang/Lex/Preprocessor.h"
@@ -61,9 +62,6 @@ std::optional<std::string> getRelativeIncludeName(const CompilerInstance &CI,
6162
"CompilerInstance does not have a FileNamager!");
6263

6364
using namespace llvm::sys;
64-
// Matches framework include patterns
65-
const llvm::Regex Rule("/(.+)\\.framework/(.+)?Headers/(.+)");
66-
6765
const auto &FS = CI.getVirtualFileSystem();
6866

6967
SmallString<128> FilePath(File.begin(), File.end());
@@ -147,7 +145,7 @@ std::optional<std::string> getRelativeIncludeName(const CompilerInstance &CI,
147145
// include name `<Framework/Header.h>`
148146
if (Entry.IsFramework) {
149147
SmallVector<StringRef, 4> Matches;
150-
Rule.match(File, &Matches);
148+
clang::installapi::DarwinFwkHeaderRule.match(File, &Matches);
151149
// Returned matches are always in stable order.
152150
if (Matches.size() != 4)
153151
return std::nullopt;

clang/lib/InstallAPI/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS
55

66
add_clang_library(clangInstallAPI
77
Context.cpp
8+
FileList.cpp
9+
HeaderFile.cpp
810

911
LINK_LIBS
1012
clangAST

0 commit comments

Comments
 (0)