Skip to content

Commit

Permalink
[clang][InstallAPI] Add input file support to library
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cyndyishida committed Feb 14, 2024
1 parent ec5f4a4 commit a994b56
Show file tree
Hide file tree
Showing 10 changed files with 672 additions and 4 deletions.
80 changes: 80 additions & 0 deletions clang/include/clang/InstallAPI/FileList.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//===- InstallAPI/FileList.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
//
//===----------------------------------------------------------------------===//
///
/// The JSON file list parser is used to communicate input to InstallAPI.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INSTALLAPI_FILELIST_H
#define LLVM_CLANG_INSTALLAPI_FILELIST_H

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"

namespace clang {
namespace installapi {

/// Abstract Interface for reading FileList JSON Input.
class FileListReader {
class Implementation;

Implementation &Impl;

FileListReader(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
llvm::Error &Err);

public:
static llvm::Expected<std::unique_ptr<FileListReader>>
get(std::unique_ptr<llvm::MemoryBuffer> InputBuffer);

~FileListReader();

FileListReader(const FileListReader &) = delete;
FileListReader &operator=(const FileListReader &) = delete;

int getVersion() const;

struct HeaderInfo {
HeaderType Type;
std::string Path;
std::optional<clang::Language> Language;
};

/// Visitor used when walking the contents of the file list.
class Visitor {
public:
virtual ~Visitor();

virtual void visitHeaderFile(HeaderInfo &header) = 0;
};

/// Visit the contents of the header list file, passing each entity to the
/// given visitor. It visits in the same order as they appear in the json
/// file.
void visit(Visitor &visitor);
};

class FileListVisitor final : public FileListReader::Visitor {
FileManager &FM;
DiagnosticsEngine &Diag;
HeaderSeq &HeaderFiles;

public:
FileListVisitor(FileManager &FM, DiagnosticsEngine &Diag,
HeaderSeq &HeaderFiles)
: FM(FM), Diag(Diag), HeaderFiles(HeaderFiles) {}

void visitHeaderFile(FileListReader::HeaderInfo &Header) override;
};
} // namespace installapi
} // namespace clang

#endif // LLVM_CLANG_INSTALLAPI_FILELIST_H
69 changes: 69 additions & 0 deletions clang/include/clang/InstallAPI/HeaderFile.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//===- InstallAPI/HeaderFile.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
//
//===----------------------------------------------------------------------===//
///
/// Representations of a library's headers for InstallAPI.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INSTALLAPI_HEADERFILE_H
#define LLVM_CLANG_INSTALLAPI_HEADERFILE_H

#include "clang/Basic/LangStandard.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Regex.h"
#include <optional>
#include <string>

namespace clang::installapi {

const llvm::Regex DarwinFwkHeaderRule("/(.+)\\.framework/(.+)?Headers/(.+)");

enum class HeaderType {
/// Represents declarations accessible to all clients.
Public,
/// Represents declarations accessible to a disclosed set of clients.
Private,
/// Represents declarations only accessible as implementation details to the
/// input library.
Project,
};

class HeaderFile {
/// Full input path to header.
std::string FullPath;
/// Access level of header.
HeaderType Type;
/// Expected way header will be included by clients.
std::string IncludeName;
/// Supported language mode for header.
std::optional<clang::Language> Language;

public:
HeaderFile(StringRef FullPath, HeaderType Type,
StringRef IncludeName = StringRef(),
std::optional<clang::Language> Language = std::nullopt)
: FullPath(FullPath), Type(Type), IncludeName(IncludeName),
Language(Language) {}

HeaderType getType() const { return Type; }
};

/// Assemble expected way header will be included by clients.
/// As in what maps inside the brackets of `#include <IncludeName.h>`
/// For example,
/// "/System/Library/Frameworks/Foo.framework/Headers/Foo.h" returns
/// "Foo/Foo.h"
///
/// \param FullPath Path to the header file which includes the library
/// structure.
std::optional<std::string> createIncludeHeaderName(const StringRef FullPath);
using HeaderSeq = std::vector<HeaderFile>;

} // namespace clang::installapi

#endif // LLVM_CLANG_INSTALLAPI_HEADERFILE_H
6 changes: 2 additions & 4 deletions clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
Expand Down Expand Up @@ -61,9 +62,6 @@ std::optional<std::string> getRelativeIncludeName(const CompilerInstance &CI,
"CompilerInstance does not have a FileNamager!");

using namespace llvm::sys;
// Matches framework include patterns
const llvm::Regex Rule("/(.+)\\.framework/(.+)?Headers/(.+)");

const auto &FS = CI.getVirtualFileSystem();

SmallString<128> FilePath(File.begin(), File.end());
Expand Down Expand Up @@ -147,7 +145,7 @@ std::optional<std::string> getRelativeIncludeName(const CompilerInstance &CI,
// include name `<Framework/Header.h>`
if (Entry.IsFramework) {
SmallVector<StringRef, 4> Matches;
Rule.match(File, &Matches);
clang::installapi::DarwinFwkHeaderRule.match(File, &Matches);
// Returned matches are always in stable order.
if (Matches.size() != 4)
return std::nullopt;
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/InstallAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS

add_clang_library(clangInstallAPI
Context.cpp
FileList.cpp
HeaderFile.cpp

LINK_LIBS
clangAST
Expand Down
Loading

0 comments on commit a994b56

Please sign in to comment.