Skip to content
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

Merged
merged 22 commits into from
Jan 13, 2023

Conversation

dg0yt
Copy link
Contributor

@dg0yt dg0yt commented Jan 8, 2023

@dg0yt dg0yt marked this pull request as draft January 8, 2023 17:45
dg0yt added 5 commits January 8, 2023 19:25
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
@dg0yt dg0yt marked this pull request as ready for review January 8, 2023 19:06
@dg0yt
Copy link
Contributor Author

dg0yt commented Jan 8, 2023

./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)
-

@dg0yt
Copy link
Contributor Author

dg0yt commented Jan 8, 2023

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)

@dg0yt
Copy link
Contributor Author

dg0yt commented Jan 8, 2023

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)");
Copy link
Contributor

@Neumann-A Neumann-A Jan 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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)");

Copy link
Contributor

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# ?

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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.

@dg0yt
Copy link
Contributor Author

dg0yt commented Jan 9, 2023

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)
-

dg0yt added 3 commits January 10, 2023 09:24
In particular, ignore everything in d(ebug) and all directory filepaths
@dg0yt dg0yt changed the title Reduce broken output of cmake usage heuristics Reduce invalid output of cmake usage heuristics Jan 10, 2023
@dg0yt
Copy link
Contributor Author

dg0yt commented Jan 10, 2023

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})

Copy link
Member

@BillyONeal BillyONeal left a 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 :)

Comment on lines 723 to 730
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);
}
Copy link
Member

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:

Suggested change
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)

Copy link
Contributor Author

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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
first = end_of_library_name;
first = end_of_library_name;

@@ -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
Copy link
Member

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"?

Copy link
Contributor Author

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.

@@ -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
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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.

{
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.

Copy link
Contributor Author

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.

@BillyONeal BillyONeal merged commit fb588e9 into microsoft:main Jan 13, 2023
@BillyONeal
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants