-
Notifications
You must be signed in to change notification settings - Fork 285
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
Reduce invalid output of cmake usage heuristics #849
Conversation
Any deviation from the usual generated form calls for manual action.
vcpkg wants config in 'share/${PORT}/' which maps to CMake's '<prefix>/(lib/<arch>|lib|share)/<name>*/' pattern, i.e. the beginning of the directory name must match the package name, case-insensitively.
Correlate package names and targets per 'share/${PORT}'. Ignore nested dirs.
If both non-namespaced and namespaced targets exist, assume that the non-namespaced target is newer and preferred. Example: xerces_xerces-c -> XercesC::XercesC
./vcpkg install grpc : grpc provides CMake targets:
# this is heuristically generated, and may not be correct
find_package(gRPC CONFIG REQUIRED)
# note: 7 additional targets are not displayed.
target_link_libraries(main PRIVATE gRPC::gpr gRPC::grpc gRPC::grpc++ gRPC::grpc++_alts)
- find_package(modules CONFIG REQUIRED)
- target_link_libraries(main PRIVATE re2::re2 c-ares::cares)
- |
xerces-c: xerces-c provides CMake targets:
# this is heuristically generated, and may not be correct
find_package(XercesC CONFIG REQUIRED)
- target_link_libraries(main PRIVATE xerces_xerces-c XercesC::XercesC)
+ target_link_libraries(main PRIVATE XercesC::XercesC) |
jsoncpp: jsoncpp provides CMake targets:
# this is heuristically generated, and may not be correct
find_package(jsoncpp CONFIG REQUIRED)
- target_link_libraries(main PRIVATE jsoncpp_object jsoncpp_static JsonCpp::JsonCpp)
+ target_link_libraries(main PRIVATE JsonCpp::JsonCpp) |
auto with_var = get_cmake_add_library_names("add_library(bar${foo}) add_library(${foo}) add_library( \nbar)"); | ||
CHECK(with_var.empty()); | ||
|
||
auto with_comment = get_cmake_add_library_names("add_library( # rem \n foo) add_library( bar# rem3)"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto with_comment = get_cmake_add_library_names("add_library( # rem \n foo) add_library( bar# rem3)"); | |
auto with_comment = get_cmake_add_library_names("add_library( # rem \n foo) add_library( bar # rem3\n)"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or should the target name be bar# ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point is to not return any target name at all from this input. It is not the generated form. If there is a comment, it likely that the heuristics won't generate useful output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah but the input should still be valid cmake shouldn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no benefit from perfection here. It is not a full parser.
Don't print targets when the config file is missing.
Last not least (microsoft/vcpkg#20190 (comment)): -shapelib provides CMake targets:
-
- # this is heuristically generated, and may not be correct
- find_package(shp CONFIG REQUIRED)
- target_link_libraries(main PRIVATE shp)
- |
In particular, ignore everything in d(ebug) and all directory filepaths
Header-only output due to lack of config file for exports: -mdns provides CMake targets:
-
- # this is heuristically generated, and may not be correct
- find_package(cmake CONFIG REQUIRED)
- target_link_libraries(main PRIVATE mdns::mdns)
+mdns is header-only and can be used from CMake via:
+
+ find_path(MDNS_INCLUDE_DIRS "mdns.h")
+ target_include_directories(main PRIVATE ${MDNS_INCLUDE_DIRS}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only extreme nitpicks here; this looks good to me :)
src/vcpkg/install.cpp
Outdated
if (Strings::ends_with(filename, "Config.cmake")) | ||
{ | ||
res = filename.substr(0, filename.size() - 12); | ||
} | ||
else if (Strings::ends_with(filename, "-config.cmake")) | ||
{ | ||
res = filename.substr(0, filename.size() - 13); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spent some time trying to get rid of the magic numbers. What do you think of:
// above
namespace {
bool remove_suffix(StringView& haystack, StringLiteral needle) {
if (Strings::ends_with(haystack, needle)) {
haystack = StringView{haystack.data(), haystack.size() - needle.size()};
return true;
}
return false;
}
}
Then:
if (Strings::ends_with(filename, "Config.cmake")) | |
{ | |
res = filename.substr(0, filename.size() - 12); | |
} | |
else if (Strings::ends_with(filename, "-config.cmake")) | |
{ | |
res = filename.substr(0, filename.size() - 13); | |
} | |
if (!remove_suffix(filename, "Config.cmake")) { | |
remove_suffix(filename, "-config.cmake"); | |
} |
(I'm not myself convinced that the cure is worse than the disease but thought I'd mention)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will use StringLiteral.
continue; | ||
} | ||
res.emplace_back(start_of_library_name, end_of_library_name); | ||
first = end_of_library_name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
first = end_of_library_name; | |
first = end_of_library_name; |
src/vcpkg/install.cpp
Outdated
@@ -740,122 +760,165 @@ namespace vcpkg | |||
auto files = fs.read_lines(installed.listfile_path(bpgh), ec); | |||
if (!ec) | |||
{ | |||
std::unordered_map<std::string, std::string> config_files; | |||
// Mapping directories to unique config names and to library targets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment suggests that "name" should be "target"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I added the comment, it was for multiple lines. But the lines changed since that time.
src/vcpkg/install.cpp
Outdated
@@ -740,122 +760,165 @@ namespace vcpkg | |||
auto files = fs.read_lines(installed.listfile_path(bpgh), ec); | |||
if (!ec) | |||
{ | |||
std::unordered_map<std::string, std::string> config_files; | |||
// Mapping directories to unique config names and to library targets | |||
struct ConfigPackages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm personally not a fan of local structs like this but some other maintainers like them. Can it at least be moved out of the if?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The struct gives better names than first
and second
, and its location in the smallest possible scope. The alternative is to move it out of the function to an anonymous namespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm suggesting leaving it in the function but out of the if.
src/vcpkg/install.cpp
Outdated
{ | ||
auto msg = msg::format(msgCMakeTargetsUsage, msg::package_name = bpgh.spec.name()).append_raw("\n\n"); | ||
msg.append_indent().append(msgCMakeTargetsUsageHeuristicMessage).append_raw('\n'); | ||
|
||
for (auto&& library_target_pair : library_targets) | ||
for (const auto package_targets_pair : ret.cmake_targets_map) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for (const auto package_targets_pair : ret.cmake_targets_map) | |
for (auto&& package_targets_pair : ret.cmake_targets_map) |
I believe auto&& as formerly written is more correct here: there's no reason to introduce an extra by-value copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverting. What I really wanted is a const reference. The block visits the container but must not modify it.
Thanks! |
For microsoft/vcpkg#20190.