Improve pkgconfig postbuild check: Allow empty Libs: in share/pkgconfig and improve suggestions
MODIFY
src/vcpkg/postbuildlint.cpp
src/vcpkg/postbuildlint.cpp
@@ -739,21 +739,57 @@ namespace vcpkg::PostBuildLint
static LintStatus check_pkgconfig_dir_only_in_lib_dir(const Filesystem& fs, const Path& dir_raw)
{
+ struct MisplacedFile
+ {
+ Path path;
+ enum class Type
+ {
+ Release,
+ Debug,
+ Share
+ } type;
+ };
+ std::vector<MisplacedFile> misplaced_pkgconfig_files;
+ bool contains_release = false;
+ bool contains_debug = false;
+ bool contains_share = false;
+
auto dir = dir_raw.lexically_normal().generic_u8string(); // force /s
- std::vector<Path> misplaced_pkgconfig_files = fs.get_regular_files_recursive(dir, IgnoreErrors{});
- Util::erase_remove_if(misplaced_pkgconfig_files, [&fs](const Path& path) {
- if (!Strings::ends_with(path, ".pc")) return true;
+ for (Path& path : fs.get_regular_files_recursive(dir, IgnoreErrors{}))
+ {
+ if (!Strings::ends_with(path, ".pc")) continue;
// Always forbid .pc files not in a "pkgconfig" directory:
const auto parent_path = Path(path.parent_path());
- if (parent_path.filename() != "pkgconfig") return false;
+ if (parent_path.filename() != "pkgconfig") continue;
const auto pkgconfig_parent_name = Path(parent_path.parent_path()).filename().to_string();
// Always allow .pc files in "lib/pkgconfig":
- if (pkgconfig_parent_name == "lib") return true;
+ if (pkgconfig_parent_name == "lib") continue;
// Allow .pc in "share/pkgconfig" if and only if it contains no "Libs:" or "Libs.private:" directives:
- return pkgconfig_parent_name == "share" &&
- !Util::any_of(fs.read_lines(path, VCPKG_LINE_INFO),
- [](const auto& line) { return Strings::starts_with(line, "Libs"); });
+ const bool contains_libs = Util::any_of(fs.read_lines(path, VCPKG_LINE_INFO), [](const std::string& line) {
+ if (Strings::starts_with(line, "Libs"))
+ {
+ // only consider "Libs:" or "Libs.private:" directives when they have a value
+ const auto colon = line.find_first_of(':');
+ if (colon != std::string::npos && line.find_first_not_of(' ', colon + 1) != std::string::npos)
+ return true;
+ }
+ return false;
});
+ if (pkgconfig_parent_name == "share" && !contains_libs) continue;
+ if (!contains_libs)
+ {
+ contains_share = true;
+ misplaced_pkgconfig_files.push_back({std::move(path), MisplacedFile::Type::Share});
+ continue;
+ }
+ const bool is_release = path.native().find("debug/") == std::string::npos;
+ misplaced_pkgconfig_files.push_back(
+ {std::move(path), is_release ? MisplacedFile::Type::Release : MisplacedFile::Type::Debug});
+ if (is_release)
+ contains_release = true;
+ else
+ contains_debug = true;
+ }
if (!misplaced_pkgconfig_files.empty())
{
@@ -761,23 +797,9 @@ namespace vcpkg::PostBuildLint
"pkgconfig directories should be one of share/pkgconfig (for header only libraries only), "
"lib/pkgconfig, or lib/debug/pkgconfig.\n");
print2("The following misplaced pkgconfig files were found:\n");
- print_paths(misplaced_pkgconfig_files);
-
- bool contains_release = false;
- bool contains_debug = false;
- std::vector<char> misplaced_is_release(misplaced_pkgconfig_files.size()); // vector<bool>ish
- for (size_t idx = 0; idx < misplaced_pkgconfig_files.size(); ++idx)
- {
- bool is_release = misplaced_pkgconfig_files[idx].native().find("debug/") == std::string::npos;
- misplaced_is_release[idx] = is_release;
- if (is_release)
+ for (const auto& item : misplaced_pkgconfig_files)
{
- contains_release = true;
- }
- else
- {
- contains_debug = true;
- }
+ print2(" ", item.path, '\n');
}
print2(Color::warning,
@@ -795,24 +817,28 @@ namespace vcpkg::PostBuildLint
create_directory_line += R"###( "${CURRENT_PACKAGES_DIR}/lib/debug/pkgconfig")###";
}
+ if (contains_share)
+ {
+ create_directory_line += R"###( "${CURRENT_PACKAGES_DIR}/share/pkgconfig")###";
+ }
+
create_directory_line.append(")\n");
print2(Color::warning, create_directory_line);
- for (size_t idx = 0; idx < misplaced_pkgconfig_files.size(); ++idx)
+ for (const auto& item : misplaced_pkgconfig_files)
{
- const auto& misplaced = misplaced_pkgconfig_files[idx];
- auto relative = misplaced.native().substr(dir.size());
+ auto relative = item.path.native().substr(dir.size());
std::string rename_line(R"###( file(RENAME "${CURRENT_PACKAGES_DIR})###");
rename_line.append(relative);
rename_line.append(R"###(" "${CURRENT_PACKAGES_DIR}/)###");
- if (!misplaced_is_release[idx])
+ switch (item.type)
{
- rename_line.append("debug/");
+ case MisplacedFile::Type::Debug: rename_line.append("debug/lib/pkgconfig/"); break;
+ case MisplacedFile::Type::Release: rename_line.append("lib/pkgconfig/"); break;
+ case MisplacedFile::Type::Share: rename_line.append("share/pkgconfig/"); break;
}
-
- rename_line.append(R"###(lib/pkgconfig/)###");
- rename_line.append(misplaced.filename().to_string());
+ rename_line.append(item.path.filename().to_string());
rename_line.append("\")\n");
print2(Color::warning, rename_line);
}

Improve pkgconfig postbuild check: Allow empty Libs: in share/pkgconfig and improve suggestions (#255)