Skip to content

[InstallAPI] Pick up input headers by directory traversal #94508

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 1 commit into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ def err_unsupported_environment : Error<"environment '%0' is not supported: '%1'
def err_unsupported_os : Error<"os '%0' is not supported: '%1'">;
def err_cannot_read_input_list : Error<"could not read %0 input list '%1': %2">;
def err_invalid_label: Error<"label '%0' is reserved: use a different label name for -X<label>">;
def err_directory_scanning: Error<"could not read directory '%0': %1">;
def err_more_than_one_library: Error<"more than one framework/dynamic library found">;
} // end of command line category.

let CategoryName = "Verification" in {
Expand Down
81 changes: 81 additions & 0 deletions clang/include/clang/InstallAPI/DirectoryScanner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//===- InstallAPI/DirectoryScanner.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 DirectoryScanner for collecting library files on the file system.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INSTALLAPI_DIRECTORYSCANNER_H
#define LLVM_CLANG_INSTALLAPI_DIRECTORYSCANNER_H

#include "clang/Basic/FileManager.h"
#include "clang/InstallAPI/Library.h"

namespace clang::installapi {

enum ScanMode {
/// Scanning Framework directory.
ScanFrameworks,
/// Scanning Dylib directory.
ScanDylibs,
};

class DirectoryScanner {
public:
DirectoryScanner(FileManager &FM, ScanMode Mode = ScanMode::ScanFrameworks)
: FM(FM), Mode(Mode) {}

/// Scan for all input files throughout directory.
///
/// \param Directory Path of input directory.
llvm::Error scan(StringRef Directory);

/// Take over ownership of stored libraries.
std::vector<Library> takeLibraries() { return std::move(Libraries); };

/// Get all the header files in libraries.
///
/// \param Libraries Reference of collection of libraries.
static HeaderSeq getHeaders(ArrayRef<Library> Libraries);

private:
/// Collect files for dylibs in usr/(local)/lib within directory.
llvm::Error scanForUnwrappedLibraries(StringRef Directory);

/// Collect files for any frameworks within directory.
llvm::Error scanForFrameworks(StringRef Directory);

/// Get a library from the libraries collection.
Library &getOrCreateLibrary(StringRef Path, std::vector<Library> &Libs) const;

/// Collect multiple frameworks from directory.
llvm::Error scanMultipleFrameworks(StringRef Directory,
std::vector<Library> &Libs) const;
/// Collect files from nested frameworks.
llvm::Error scanSubFrameworksDirectory(StringRef Directory,
std::vector<Library> &Libs) const;

/// Collect files from framework path.
llvm::Error scanFrameworkDirectory(StringRef Path, Library &Framework) const;

/// Collect header files from path.
llvm::Error scanHeaders(StringRef Path, Library &Lib, HeaderType Type,
StringRef BasePath,
StringRef ParentPath = StringRef()) const;

/// Collect files from Version directories inside Framework directories.
llvm::Error scanFrameworkVersionsDirectory(StringRef Path,
Library &Lib) const;
FileManager &FM;
ScanMode Mode;
StringRef RootPath;
std::vector<Library> Libraries;
};

} // namespace clang::installapi

#endif // LLVM_CLANG_INSTALLAPI_DIRECTORYSCANNER_H
13 changes: 13 additions & 0 deletions clang/include/clang/InstallAPI/HeaderFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ class HeaderFile {
Other.Excluded, Other.Extra,
Other.Umbrella);
}

bool operator<(const HeaderFile &Other) const {
/// For parsing of headers based on ordering,
/// group by type, then whether its an umbrella.
/// Capture 'extra' headers last.
/// This optimizes the chance of a sucessful parse for
/// headers that violate IWYU.
if (isExtra() && Other.isExtra())
return std::tie(Type, Umbrella) < std::tie(Other.Type, Other.Umbrella);

return std::tie(Type, Umbrella, Extra, FullPath) <
std::tie(Other.Type, Other.Umbrella, Other.Extra, Other.FullPath);
}
};

/// Glob that represents a pattern of header files to retreive.
Expand Down
65 changes: 65 additions & 0 deletions clang/include/clang/InstallAPI/Library.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//===- InstallAPI/Library.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
//
//===----------------------------------------------------------------------===//
///
/// Defines the content of a library, such as public and private
/// header files, and whether it is a framework.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INSTALLAPI_LIBRARY_H
#define LLVM_CLANG_INSTALLAPI_LIBRARY_H

#include "clang/InstallAPI/HeaderFile.h"
#include "clang/InstallAPI/MachO.h"

namespace clang::installapi {

class Library {
public:
Library(StringRef Directory) : BaseDirectory(Directory) {}

/// Capture the name of the framework by the install name.
///
/// \param InstallName The install name of the library encoded in a dynamic
/// library.
static StringRef getFrameworkNameFromInstallName(StringRef InstallName);

/// Get name of library by the discovered file path.
StringRef getName() const;

/// Get discovered path of library.
StringRef getPath() const { return BaseDirectory; }

/// Add a header file that belongs to the library.
///
/// \param FullPath Path to header file.
/// \param Type Access level of header.
/// \param IncludePath The way the header should be included.
void addHeaderFile(StringRef FullPath, HeaderType Type,
StringRef IncludePath = StringRef()) {
Headers.emplace_back(FullPath, Type, IncludePath);
}

/// Determine if library is empty.
bool empty() {
return SubFrameworks.empty() && Headers.empty() &&
FrameworkVersions.empty();
}

private:
std::string BaseDirectory;
HeaderSeq Headers;
std::vector<Library> SubFrameworks;
std::vector<Library> FrameworkVersions;
bool IsUnwrappedDylib{false};

friend class DirectoryScanner;
};

} // namespace clang::installapi

#endif // LLVM_CLANG_INSTALLAPI_LIBRARY_H
1 change: 1 addition & 0 deletions clang/include/clang/InstallAPI/MachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ using RecordLinkage = llvm::MachO::RecordLinkage;
using Record = llvm::MachO::Record;
using EncodeKind = llvm::MachO::EncodeKind;
using GlobalRecord = llvm::MachO::GlobalRecord;
using InterfaceFile = llvm::MachO::InterfaceFile;
using ObjCContainerRecord = llvm::MachO::ObjCContainerRecord;
using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord;
using ObjCCategoryRecord = llvm::MachO::ObjCCategoryRecord;
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 @@ -8,10 +8,12 @@ set(LLVM_LINK_COMPONENTS

add_clang_library(clangInstallAPI
DiagnosticBuilderWrappers.cpp
DirectoryScanner.cpp
DylibVerifier.cpp
FileList.cpp
Frontend.cpp
HeaderFile.cpp
Library.cpp
Visitor.cpp

LINK_LIBS
Expand Down
Loading
Loading