Merge "Collect libc++ headers that have no file name extensions" am: 462b91aae1

Original change: https://android-review.googlesource.com/c/platform/development/+/2473566

Change-Id: Ie89f023c62b1dc45a6eb921aa90fe321c810533f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hsin-Yi Chen
2023-03-13 02:40:02 +00:00
committed by Automerger Merge Worker
2 changed files with 53 additions and 10 deletions

View File

@@ -29,13 +29,32 @@ namespace utils {
static const std::vector<std::string> header_extensions{
".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"};
static bool HasHeaderExtension(llvm::StringRef &file_name) {
static const std::vector<std::string> libcxx_include_dir{"libcxx", "include"};
static bool HasHeaderExtension(llvm::StringRef file_name) {
return std::find_if(header_extensions.begin(), header_extensions.end(),
[file_name](const std::string &e) {
return file_name.endswith(e);
}) != header_extensions.end();
}
static bool PathEndsWith(llvm::StringRef path,
const std::vector<std::string> &suffix) {
auto path_it = llvm::sys::path::rbegin(path);
auto suffix_it = suffix.rbegin();
while (suffix_it != suffix.rend()) {
if (path_it == llvm::sys::path::rend(path)) {
return false;
}
if (*path_it != *suffix_it) {
return false;
}
++path_it;
++suffix_it;
}
return true;
}
static std::string GetCwd() {
llvm::SmallString<256> cwd;
if (llvm::sys::fs::current_path(cwd)) {
@@ -117,6 +136,11 @@ std::string NormalizePath(std::string_view path, const RootDirs &root_dirs) {
static bool CollectExportedHeaderSet(const std::string &dir_name,
std::set<std::string> *exported_headers,
const RootDirs &root_dirs) {
// Bazel creates temporary files in header directories. To avoid race
// condition, this function filters headers by name extensions.
// An exception is that libc++ headers do not have extensions.
bool collect_headers_without_extensions =
PathEndsWith(dir_name, libcxx_include_dir);
std::error_code ec;
llvm::sys::fs::recursive_directory_iterator walker(dir_name, ec);
// Default construction - end of directory.
@@ -136,7 +160,11 @@ static bool CollectExportedHeaderSet(const std::string &dir_name,
walker.no_push();
continue;
}
if (!HasHeaderExtension(file_name)) {
if (!file_name.contains(".")) {
if (!collect_headers_without_extensions) {
continue;
}
} else if (!HasHeaderExtension(file_name)) {
continue;
}

View File

@@ -24,14 +24,20 @@ namespace header_checker {
namespace utils {
TEST(SourcePathUtilsTest, CollectAllExportedHeaders) {
// Prepare a header directory.
TemporaryDir temp_dir;
const std::filesystem::path header_dir = temp_dir.path;
std::error_code ec;
// Prepare a header directory containing links, hidden files, etc.
const std::filesystem::path header_dir =
std::filesystem::path(temp_dir.path) / "include";
ASSERT_TRUE(std::filesystem::create_directory(header_dir, ec));
ASSERT_FALSE(ec);
const std::filesystem::path header = header_dir / "header.h";
ASSERT_TRUE(android::base::WriteStringToFile("// test", header));
std::error_code ec;
const std::filesystem::path no_ext_header = header_dir / "header";
ASSERT_TRUE(android::base::WriteStringToFile("// test", no_ext_header));
const std::filesystem::path subdir = header_dir / "subdir";
ASSERT_TRUE(std::filesystem::create_directory(subdir, ec));
ASSERT_FALSE(ec);
@@ -55,15 +61,24 @@ TEST(SourcePathUtilsTest, CollectAllExportedHeaders) {
const std::filesystem::path non_header_link = subdir / "header_link.txt";
std::filesystem::create_symlink(header, non_header_link, ec);
ASSERT_FALSE(ec);
// Prepare a header directory like libc++.
const std::filesystem::path libcxx_dir =
std::filesystem::path(temp_dir.path) / "libcxx" / "include";
ASSERT_TRUE(std::filesystem::create_directories(libcxx_dir, ec));
ASSERT_FALSE(ec);
const std::filesystem::path libcxx_header = libcxx_dir / "array";
ASSERT_TRUE(android::base::WriteStringToFile("// test", libcxx_header));
// Test the function.
std::vector<std::string> exported_header_dirs{header_dir};
std::vector<RootDir> root_dirs{{header_dir, "include"}};
std::vector<std::string> exported_header_dirs{header_dir, libcxx_dir};
std::vector<RootDir> root_dirs{{header_dir, "include"},
{libcxx_dir, "libcxx"}};
std::set<std::string> headers =
CollectAllExportedHeaders(exported_header_dirs, root_dirs);
std::set<std::string> expected_headers{"include/header.h",
"include/subdir/header_link.h",
"include/subdir_link/header_link.h"};
std::set<std::string> expected_headers{
"include/header.h", "include/subdir/header_link.h",
"include/subdir_link/header_link.h", "libcxx/array"};
ASSERT_EQ(headers, expected_headers);
}