[vcpkg] Improve CMake messages to account for case-sensitive filesystems.
Improve CMake messages to display shortest targets first (which are hopefully the "public" ones).
Also, fix bug in StringLiteral.
MODIFY
include/vcpkg/base/stringliteral.h
include/vcpkg/base/stringliteral.h
@@ -7,7 +7,8 @@ namespace vcpkg
struct StringLiteral
{
template<int N>
- constexpr StringLiteral(const char (&str)[N]) : m_size(N), m_cstr(str)
+ constexpr StringLiteral(const char (&str)[N])
+ : m_size(N - 1) /* -1 here accounts for the null byte at the end*/, m_cstr(str)
{
}

MODIFY
include/vcpkg/base/strings.h
include/vcpkg/base/strings.h
#pragma once
#include <vcpkg/base/cstringview.h>
+#include <vcpkg/base/stringliteral.h>
#include <vector>
@@ -53,6 +54,7 @@ namespace vcpkg::Strings
std::string ascii_to_uppercase(std::string s);
bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern);
+ bool ends_with(const std::string& s, StringLiteral pattern);
template<class Container, class Transformer>
std::string join(const char* delimiter, const Container& v, Transformer transformer)

MODIFY
src/vcpkg/base/strings.cpp
src/vcpkg/base/strings.cpp
@@ -128,6 +128,12 @@ namespace vcpkg::Strings
#endif
}
+ bool ends_with(const std::string& s, StringLiteral pattern)
+ {
+ if (s.size() < pattern.size()) return false;
+ return std::equal(s.end() - pattern.size(), s.end(), pattern.c_str(), pattern.c_str() + pattern.size());
+ }
+
std::string replace_all(std::string&& s, const std::string& search, const std::string& rep)
{
size_t pos = 0;

MODIFY
src/vcpkg/commands.cache.cpp
src/vcpkg/commands.cache.cpp
@@ -61,7 +61,7 @@ namespace vcpkg::Commands::Cache
for (const BinaryParagraph& binary_paragraph : binary_paragraphs)
{
const std::string displayname = binary_paragraph.displayname();
- if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end())
+ if (!Strings::case_insensitive_ascii_contains(displayname, args.command_arguments[0]))
{
continue;
}

MODIFY
src/vcpkg/commands.list.cpp
src/vcpkg/commands.list.cpp
@@ -76,7 +76,7 @@ namespace vcpkg::Commands::List
for (const StatusParagraph* status_paragraph : installed_packages)
{
const std::string displayname = status_paragraph->package.displayname();
- if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end())
+ if (!Strings::case_insensitive_ascii_contains(displayname, args.command_arguments[0]))
{
continue;
}

MODIFY
src/vcpkg/install.cpp
src/vcpkg/install.cpp
@@ -462,14 +462,14 @@ namespace vcpkg::Install
auto files = fs.read_lines(paths.listfile_path(bpgh));
if (auto p_lines = files.get())
{
+ std::map<std::string, std::string> config_files;
std::map<std::string, std::vector<std::string>> library_targets;
for (auto&& suffix : *p_lines)
{
- if (Strings::case_insensitive_ascii_find(suffix, "/share/") != suffix.end() &&
- suffix.substr(suffix.size() - 6) == ".cmake")
+ if (Strings::case_insensitive_ascii_contains(suffix, "/share/") && Strings::ends_with(suffix, ".cmake"))
{
- // File is inside the share folder
+ // CMake file is inside the share folder
auto path = paths.installed / suffix;
auto maybe_contents = fs.read_contents(path);
auto find_package_name = path.parent_path().filename().u8string();
@@ -485,6 +485,21 @@ namespace vcpkg::Install
++next;
}
}
+
+ auto filename = fs::u8path(suffix).filename().u8string();
+
+ if (Strings::ends_with(filename, "Config.cmake"))
+ {
+ auto root = filename.substr(0, filename.size() - 12);
+ if (Strings::case_insensitive_ascii_equals(root, find_package_name))
+ config_files[find_package_name] = root;
+ }
+ else if (Strings::ends_with(filename, "-config.cmake"))
+ {
+ auto root = filename.substr(0, filename.size() - 13);
+ if (Strings::case_insensitive_ascii_equals(root, find_package_name))
+ config_files[find_package_name] = root;
+ }
}
}
@@ -497,11 +512,23 @@ namespace vcpkg::Install
for (auto&& library_target_pair : library_targets)
{
+ auto config_it = config_files.find(library_target_pair.first);
+ if (config_it != config_files.end())
+ System::println(" find_package(%s CONFIG REQUIRED)", config_it->second);
+ else
+ System::println(" find_package(%s CONFIG REQUIRED)", library_target_pair.first);
+
+ std::sort(library_target_pair.second.begin(),
+ library_target_pair.second.end(),
+ [](const std::string& l, const std::string& r) {
+ if (l.size() < r.size()) return true;
+ if (l.size() > r.size()) return false;
+ return l < r;
+ });
+
if (library_target_pair.second.size() <= 4)
{
- System::println(" find_package(%s REQUIRED)\n"
- " target_link_libraries(main PRIVATE %s)\n",
- library_target_pair.first,
+ System::println(" target_link_libraries(main PRIVATE %s)\n",
Strings::join(" ", library_target_pair.second));
}
else
@@ -509,10 +536,8 @@ namespace vcpkg::Install
auto omitted = library_target_pair.second.size() - 4;
library_target_pair.second.erase(library_target_pair.second.begin() + 4,
library_target_pair.second.end());
- System::println(" find_package(%s REQUIRED)\n"
- " # Note: %zd targets were omitted\n"
+ System::println(" # Note: %zd target(s) were omitted.\n"
" target_link_libraries(main PRIVATE %s)\n",
- library_target_pair.first,
omitted,
Strings::join(" ", library_target_pair.second));
}

[vcpkg] Improve CMake messages to account for case-sensitive filesystems.

Improve CMake messages to display shortest targets first (which are hopefully the "public" ones).
Also, fix bug in StringLiteral.