conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
8.2k stars 979 forks source link

[bug] `CMakeDeps` only looks at top level `cmake_build_modules` #10272

Open dvirtz opened 2 years ago

dvirtz commented 2 years ago

packages setting cmake_build_modules on a component, like protobuf, can't be used with CMakeDeps:

https://github.com/conan-io/conan/blob/70763b67d99c51cf92216f3e5d7b10b2849d2d90/conan/tools/cmake/cmakedeps/templates/target_data.py#L84

Environment Details (include every applicable attribute)

Steps to reproduce (Include if Applicable)

apply this patch to conan-center-index:

protobuf test_package patch ```diff diff --git a/recipes/protobuf/all/test_package/CMakeLists.txt b/recipes/protobuf/all/test_package/CMakeLists.txt index 1c4669f52..6c236a746 100644 --- a/recipes/protobuf/all/test_package/CMakeLists.txt +++ b/recipes/protobuf/all/test_package/CMakeLists.txt @@ -1,9 +1,6 @@ cmake_minimum_required(VERSION 3.1) project(test_package) -include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") -conan_basic_setup(TARGETS) - find_package(protobuf CONFIG REQUIRED) add_executable(${PROJECT_NAME} test_package.cpp addressbook.proto) diff --git a/recipes/protobuf/all/test_package/conanfile.py b/recipes/protobuf/all/test_package/conanfile.py index 9cf01fd2d..dd9763e95 100644 --- a/recipes/protobuf/all/test_package/conanfile.py +++ b/recipes/protobuf/all/test_package/conanfile.py @@ -1,18 +1,25 @@ -from conans import ConanFile, CMake, tools +from conans import ConanFile, tools +from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps import os class TestPackageConan(ConanFile): settings = "os", "arch", "compiler", "build_type" - generators = "cmake", "cmake_find_package_multi" def build_requirements(self): if hasattr(self, "settings_build") and tools.cross_building(self): self.build_requires(str(self.requires["protobuf"])) + def generate(self): + cd = CMakeDeps(self) + cd.generate() + + ct = CMakeToolchain(self) + ct.variables["protobuf_LITE"] = self.options["protobuf"].lite + ct.generate() + def build(self): cmake = CMake(self) - cmake.definitions["protobuf_LITE"] = self.options["protobuf"].lite cmake.configure() cmake.build() ```

then execute

conan create -pr:b=default -pr:h=default recipes/protobuf/all/ protobuf/3.17.1@

Logs (Executed commands with output) (Include/Attach if Applicable)

CMake Error at CMakeLists.txt:17 (protobuf_generate_cpp):
  Unknown CMake command "protobuf_generate_cpp".
memsharded commented 2 years ago

Please check https://docs.conan.io/en/latest/reference/conanfile/tools/cmake/cmakedeps.html#build-context-activated.

Build-requires need to be explicitly activated and found, the reason is that there are 2 different packages for protobuf, one in the host context and other in the build context. So it is impossible that find_package(protobuf can find and use both, one for the library in host and the other for the protoc exe in build context. So the approach is to explicitly say that you want a new find_package config for the build context, adding a suffix to differentiate it from the host one. This assumes that the ConanCenter recipe is already prepared to be used in this way.

Alternatively, you might want to try to call self.run("protoc ..."), directly in your recipe, instead via a CMake macro inside CMake. That will run out of the box (VirtualBuildEnv generator, or the new auto_use [conf] (use conan config list to display)

dvirtz commented 2 years ago

Thanks but I don't see how that relates to my problem. protobuf is only used as a build requirement when cross building which I'm not doing.

After digging deeper into the code, it seems that having only top level build modules is intentional and the problem is that component properties (including cmake_build_modules) are not aggregated as per https://github.com/conan-io/conan/blob/70763b67d99c51cf92216f3e5d7b10b2849d2d90/conans/model/new_build_info.py#L178-L180

I prefer to keep the cmake code calling protobuf_generate_cpp as is and not move that to the recipe.

sburton84 commented 2 years ago

I think this may be the same issue I'm running into. Running the older version 1.43.0 of Conan I get the following generated in protobuf-debug-x86_64-data.cmake:

set(protobuf_BUILD_MODULES_PATHS_DEBUG "${protobuf_PACKAGE_FOLDER_DEBUG}/lib/cmake/protobuf/protobuf-generate.cmake"
            "${protobuf_PACKAGE_FOLDER_DEBUG}/lib/cmake/protobuf/protobuf-module.cmake"
            "${protobuf_PACKAGE_FOLDER_DEBUG}/lib/cmake/protobuf/protobuf-options.cmake")

But if I update to Conan 1.43.1 or newer (including 1.44.0), it instead generates the following:

set(protobuf_BUILD_MODULES_PATHS_DEBUG )

I have tried using build_context_activated and build_context_suffix as well as build_context_build_modules to get it to generate a separate config for the build context, but regardless the generated config protobuf_BUILD-release-x86_64-data.cmake still seems to include none of the modules:

set(protobuf_BUILD_BUILD_MODULES_PATHS_RELEASE )

I've resorted to doing the following to include them manually which seems to work but I don't think should really be necessary:

find_package(protobuf CONFIG REQUIRED)
find_package(protobuf_BUILD CONFIG REQUIRED)

include("${protobuf_BUILD_PACKAGE_FOLDER_RELEASE}/lib/cmake/protobuf/protobuf-generate.cmake")
include("${protobuf_BUILD_PACKAGE_FOLDER_RELEASE}/lib/cmake/protobuf/protobuf-module.cmake")
include("${protobuf_BUILD_PACKAGE_FOLDER_RELEASE}/lib/cmake/protobuf/protobuf-options.cmake")
rajatgirotra commented 2 years ago

@memsharded I ran into a similar issue with prototobuf yesterday using conan 1.43.2 and had to downgrade to conan 1.43.0. I have raised #10282. Feel free to mark as duplicate if you think its the same issue.

I am using protobuf as regular requires not tool_requires and protobuf cmake_build_modules aren't set when I am trying to consume it using CMakeDeps generator.