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

[bug] Conan 1.37.2 CMakeDeps generator does not bootstrap package's own CMake config file #9112

Closed
SeanSnyders opened this issue Jun 15, 2021 · 15 comments · Fixed by #9206
Closed
Assignees
Milestone

Comments

@SeanSnyders
Copy link

Environment Details (include every applicable attribute)

  • Operating System+version: macOS Catalina
  • Compiler+version: n/a
  • Conan version: 1.37.2
  • Python version: 3.9.5

Problem

The new CMakeDeps generator behaviour generates generic CMake *Config.cmake etc files from the Conan recipes for the external libraries that are specified as dependencies.
What if a library provide its own *Config.cmake file(s)? It seems that the CMakeDeps generator does not defer to that.
I would expect the generator to generate the typical files for Conan, but then also still defer/include/execute the package's original *Config.cmake file(s).

Also, if there is any bootstrapping that needs to occur for said external library and this logic is embedded and shipped with the external library's package, how should that be accessed /executed using the CMakeDeps generator.
For past generators like find_package, it generates a Find<packagename>.cmake file, but this still had the functionality to include the build module if specified via self.cpp_info.build_modules[] in the recipe method package_info() for the library.
Adding self.cpp_info.build_modules["CMakeDeps"].append(...) does not seem to make any difference for the CMakeDeps generator.

Steps to reproduce

Step 1

Clone this repo to get a Conan package (in a sub-folder of this repo) that only contains CMake files that you will install into your local cache.
https://github.com/SeanSnyders/TestExamples.git

Step 2

Then use the gist below that is a recipe that depends on the package above that you installed. This recipe uses the Conan helloworld example as source code, and patches it to suit this test.
https://gist.github.com/SeanSnyders/30f73a76736864977bd88c0212f55fd7

Try to build this package for this gist and it'll fail because it cannot find a CMake utility file that it wants to include that is part of the first package above.

It fails because to illustrate the problem, this dependent library sets a variable CMAKE_PURECMAKEPACKAGE_PACKAGE_PATH which is defined in the library's own CMake config file. Conan does not seem to include this, thus this variable is not defined, and thus the 2nd package could not be built.

Logs (Executed commands with output)

Step 1

mkdir temp && cd temp
git clone https://github.com/SeanSnyders/TestExamples.git
cd TestExamples/PureCMakePackage
conan export . ssnyder/testing

image

Step 2

Download gist specified above into new folder, then

conan export . ssnyder/testing

image

Then build and install this package into the local cache

conan install ConanCMakeDepsGenerator/0.1.0@ssnyder/testing --build=ConanCMakeDepsGenerator -s build_type=Debug  --build missing

image

Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Debug
compiler=apple-clang
compiler.libcxx=libc++
compiler.version=12.0
os=Macos
os_build=Macos
[options]
[build_requires]
[env]

ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Forced build from source
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Generators in TestRecipe.build_requirements(): ('CMakeDeps', 'cmake_paths', 'virtualenv')
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: self.build_requires=<class 'conans.client.graph.graph_manager._RecipeBuildRequires'>
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: self.build_requires=cmake/3.19.4 (host), gtest/1.10.0 (host), PureCMakePackage/0.1.0@ssnyder/testing (host)
Installing package: ConanCMakeDepsGenerator/0.1.0@ssnyder/testing
Requirements
    ConanCMakeDepsGenerator/0.1.0@ssnyder/testing from local cache - Cache
Packages
    ConanCMakeDepsGenerator/0.1.0@ssnyder/testing:0458ed5e3c5080307ca8a3bae7bab3c04f2768cc - Build
Build requirements
    PureCMakePackage/0.1.0@ssnyder/testing from local cache - Cache
    cmake/3.19.4 from 'conan-center' - Cache
    gtest/1.10.0 from 'conan-center' - Cache
    openssl/1.1.1i from 'conan-center' - Cache
Build requirements packages
    PureCMakePackage/0.1.0@ssnyder/testing:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Build
    cmake/3.19.4:8780864092a6c58a5f5d385d2da47db0f418446d - Cache
    gtest/1.10.0:8ea16b5437d767794f13beec66099d7352875d19 - Cache
    openssl/1.1.1i:d98fae1010d1fb9e7f79a1e8a72bbf129d8660a2 - Cache

Installing (downloading, building) binaries...
PureCMakePackage/0.1.0@ssnyder/testing: Configuring sources in /Users/ssnyder/.conan/data/PureCMakePackage/0.1.0/ssnyder/testing/source
PureCMakePackage/0.1.0@ssnyder/testing: Copying sources to build folder
PureCMakePackage/0.1.0@ssnyder/testing: Building your package in /Users/ssnyder/.conan/data/PureCMakePackage/0.1.0/ssnyder/testing/build/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9
PureCMakePackage/0.1.0@ssnyder/testing: Generator txt created conanbuildinfo.txt
PureCMakePackage/0.1.0@ssnyder/testing: Calling build()
PureCMakePackage/0.1.0@ssnyder/testing: Running build in ConanRecipe...
PureCMakePackage/0.1.0@ssnyder/testing: Package '5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9' built
PureCMakePackage/0.1.0@ssnyder/testing: Build folder /Users/ssnyder/.conan/data/PureCMakePackage/0.1.0/ssnyder/testing/build/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9
PureCMakePackage/0.1.0@ssnyder/testing: Generated conaninfo.txt
PureCMakePackage/0.1.0@ssnyder/testing: Generated conanbuildinfo.txt
PureCMakePackage/0.1.0@ssnyder/testing: Generating the package
PureCMakePackage/0.1.0@ssnyder/testing: Package folder /Users/ssnyder/.conan/data/PureCMakePackage/0.1.0/ssnyder/testing/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9
PureCMakePackage/0.1.0@ssnyder/testing: Calling package()
PureCMakePackage/0.1.0@ssnyder/testing: Running package in ConanRecipe...
PureCMakePackage/0.1.0@ssnyder/testing package(): Packaged 2 '.cmake' files: PureCMakePackageConfig.cmake, Utils.cmake
PureCMakePackage/0.1.0@ssnyder/testing: Package '5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9' created
PureCMakePackage/0.1.0@ssnyder/testing: Created package revision b6387e11d78d612393aa2871ebe6c586
PureCMakePackage/0.1.0@ssnyder/testing: Running package_info in ConanRecipe...
gtest/1.10.0: Already installed!
openssl/1.1.1i: Already installed!
cmake/3.19.4: Already installed!
cmake/3.19.4: Appending PATH environment variable: /Users/ssnyder/.conan/data/cmake/3.19.4/_/_/package/8780864092a6c58a5f5d385d2da47db0f418446d/bin
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Applying build-requirement: cmake/3.19.4
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Applying build-requirement: gtest/1.10.0
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Applying build-requirement: PureCMakePackage/0.1.0@ssnyder/testing
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Applying build-requirement: openssl/1.1.1i
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Configuring sources in /Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/source
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Getting source in TestRecipe.source()....
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Copying sources to build folder
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Building your package in /Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/build/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Generator virtualenv created activate.ps1
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Generator virtualenv created deactivate.ps1
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Generator virtualenv created environment.ps1.env
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Generator virtualenv created activate.sh
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Generator virtualenv created deactivate.sh
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Generator virtualenv created environment.sh.env
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Generator cmake_paths created conan_paths.cmake
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Generator 'CMakeDeps' calling 'generate()'
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Calling generate()
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Running generate in TestRecipe...
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Calling build()
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: cmake.defs: OrderedDict([('CMAKE_BUILD_TYPE', 'Debug'), ('CMAKE_OSX_ARCHITECTURES', 'x86_64'), ('CMAKE_OSX_SYSROOT', '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk'), ('CONAN_IN_LOCAL_CACHE', 'ON'), ('CONAN_COMPILER', 'apple-clang'), ('CONAN_COMPILER_VERSION', '12.0'), ('CONAN_CXX_FLAGS', '-m64'), ('CONAN_SHARED_LINKER_FLAGS', '-m64'), ('CONAN_C_FLAGS', '-m64'), ('CONAN_LIBCXX', 'libc++'), ('CMAKE_INSTALL_PREFIX', '/Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/package/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc'), ('CMAKE_INSTALL_BINDIR', 'bin'), ('CMAKE_INSTALL_SBINDIR', 'bin'), ('CMAKE_INSTALL_LIBEXECDIR', 'bin'), ('CMAKE_INSTALL_LIBDIR', 'lib'), ('CMAKE_INSTALL_INCLUDEDIR', 'include'), ('CMAKE_INSTALL_OLDINCLUDEDIR', 'include'), ('CMAKE_INSTALL_DATAROOTDIR', 'share'), ('CMAKE_PREFIX_PATH', '/Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/build/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc'), ('CMAKE_MODULE_PATH', '/Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/build/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc'), ('CMAKE_EXPORT_NO_PACKAGE_REGISTRY', 'ON'), ('CONAN_EXPORTED', '1'), ('CMAKE_VERBOSE_MAKEFILE', 'ON')])
-- The C compiler identification is AppleClang 12.0.0.12000032
-- The CXX compiler identification is AppleClang 12.0.0.12000032
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Conan: Component target declared 'GTest::gtest'
-- Conan: Component target declared 'GTest::gtest_main'
-- Conan: Component target declared 'GTest::gmock'
-- Conan: Component target declared 'GTest::gmock_main'
-- Conan: Target declared 'GTest::GTest'
-- Conan: Target declared 'PureCMakePackage::PureCMakePackage'
-- PureCMakePackage PureCMakePackage_PACKAGE_FOLDER_RELEASE=
-- PureCMakePackage PureCMakePackage_PACKAGE_FOLDER_DEBUG=/Users/ssnyder/.conan/data/PureCMakePackage/0.1.0/ssnyder/testing/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9
-- PureCMakePackage CMAKE_PURECMAKEPACKAGE_PACKAGE_PATH=
CMake Error at CMakeLists.txt:9 (include):
  include could not find load file:

    /utils/Utils.cmake


-- Configuring incomplete, errors occurred!
See also "/Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/build/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc/CMakeFiles/CMakeOutput.log".
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: 
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: ERROR: Package '0458ed5e3c5080307ca8a3bae7bab3c04f2768cc' build failed
ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: WARN: Build folder /Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/build/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc
ERROR: ConanCMakeDepsGenerator/0.1.0@ssnyder/testing: Error in build() method, line 52
	cmake = self._configure_cmake()
while calling '_configure_cmake', line 48
	self._cmake.configure(source_folder="./hello")
	ConanException: Error 1 while executing cd '/Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/build/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc' && cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="Debug" -DCMAKE_OSX_ARCHITECTURES="x86_64" -DCMAKE_OSX_SYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk" -DCONAN_IN_LOCAL_CACHE="ON" -DCONAN_COMPILER="apple-clang" -DCONAN_COMPILER_VERSION="12.0" -DCONAN_CXX_FLAGS="-m64" -DCONAN_SHARED_LINKER_FLAGS="-m64" -DCONAN_C_FLAGS="-m64" -DCONAN_LIBCXX="libc++" -DCMAKE_INSTALL_PREFIX="/Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/package/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc" -DCMAKE_INSTALL_BINDIR="bin" -DCMAKE_INSTALL_SBINDIR="bin" -DCMAKE_INSTALL_LIBEXECDIR="bin" -DCMAKE_INSTALL_LIBDIR="lib" -DCMAKE_INSTALL_INCLUDEDIR="include" -DCMAKE_INSTALL_OLDINCLUDEDIR="include" -DCMAKE_INSTALL_DATAROOTDIR="share" -DCMAKE_PREFIX_PATH="/Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/build/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc" -DCMAKE_MODULE_PATH="/Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/build/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc" -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY="ON" -DCONAN_EXPORTED="1" -DCMAKE_VERBOSE_MAKEFILE="ON" -Wno-dev '/Users/ssnyder/.conan/data/ConanCMakeDepsGenerator/0.1.0/ssnyder/testing/build/0458ed5e3c5080307ca8a3bae7bab3c04f2768cc/./hello'
ssnyder-nz-la1:ConanCMakeDepsGenerator ssnyder$ 

@memsharded
Copy link
Member

Hi @SeanSnyders

What if a library provide its own *Config.cmake file(s)? It seems that the CMakeDeps generator does not defer to that.
I would expect the generator to generate the typical files for Conan, but then also still defer/include/execute the package's original *Config.cmake file(s).

Library provided config files have two limitations due to CMake:

  • They are not multi-config. You cannot find multiple packages (Debug, Release, etc), which is a blocker for users using Visual Studio or XCode (multi-config IDEs)
  • Package contained config.cmake files do not handle transitivity correctly in the general case, and could result in depending on incorrect version of transitive dependency, like a system one.

So in principle, it is not intended that CMakeDeps can defer to such config.cmake files in the packages automatically.

A different story is that the build_modules are not working correctly or they have some bug.
I think the issue could be that CMakeDeps might be using only the new properties, that will replace the previous syntax of names, filenames and build_modules. Something like:

self.cpp_info.set_property("cmake_build_modules", ["mymodule.cmake"])

Please check also the new variables to activate build_modules in the build context: https://docs.conan.io/en/latest/reference/conanfile/tools/cmake/cmakedeps.html: build_context_activated, build_context_suffix, build_context_build_modules

Please have a look, we will try to reproduce from your repo too.

@SeanSnyders
Copy link
Author

Hi @memsharded

The example (https://gist.github.com/SeanSnyders/30f73a76736864977bd88c0212f55fd7#file-conanfile-py-L34) I gave does enable the build modules in the build context as per the latest documentation:
image

But for your mention of "new properties", there is no documentation on this for cpp_info, so nothing for me to follow:

A different story is that the build_modules are not working correctly or they have some bug.
I think the issue could be that CMakeDeps might be using only the new properties, that will replace the previous syntax of names, filenames and build_modules. Something like:

self.cpp_info.set_property("cmake_build_modules", ["mymodule.cmake"])

@SeanSnyders
Copy link
Author

SeanSnyders commented Jun 20, 2021

Further investigation on the current example repro by adding below to the package_info() method of the PureCMakePackage external library:

self.cpp_info.set_property("cmake_build_modules", ["PureCMakePackageConfig.cmake"])

When specifying profiles on the command line (even the same default profile for host and build), then Conan seems to include the PureCMakePackageConfig.cmake file that is distributed/included in that external package.
This then sets the correct CMake variable for this repro.

conan install ConanCMakeDepsGenerator/0.1.0@ssnyder/testing --build=ConanCMakeDepsGenerator -s build_type=Debug  --build missing --profile:host default --profile:build default

image

But when not specifying any profiles (which is essentially the same as specifying the same profile for host and build contexts), then Conan only notes that the target is declared but does not include the external module library.

conan install ConanCMakeDepsGenerator/0.1.0@ssnyder/testing --build=ConanCMakeDepsGenerator -s build_type=Debug  --build missing

image

Overall this is problematic as there is no consistent way to thus include the external library into your CMake project.
The repro here of using the same default profile is just to illustrate the same thing happening on a different project when I try to cross-compile to e.g. android using this new CMakeDeps approach and setting the new cpp_info property cmake_build_modules.

Can you please try to repro on your side and respond with some further insights and direction?
Thanks.

@SeanSnyders
Copy link
Author

Delving deeper into Conan's source code and the CMakeDeps generated files for this repro, I noticed the following:

  1. The <pkg_name>_BUILD_MODULES_PATHS_<build_type> CMake variable as generated by the Conan ConfigDataTemplate:L78 is empty when not specifying profiles (e.g. -pr:b default -pr:h default) on the command line, and thus the build dependencies specified is not pulled in and their build modules not loaded during CMakeDeps.generate().
    But if the build and host profile is specified, then this CMake variable contains paths to the dependency's module path as specified via cpp_info.cmake_build_modules.
    So if this is fixed, and thus the specified build modules is loaded irrespective of whether I specify profiles or not, then the main issue of this ticket should be solved.

  2. The ConfigDataTemplate as well as the ConfigTemplate generates files for release rather than e.g. the actual build_type (e..g debug) as specified via the command line.
    image

@bldrvnlw
Copy link

bldrvnlw commented Jun 24, 2021

What if a library provide its own *Config.cmake file(s)

Hi @SeanSnyders

I also have a case where the conan package (hosted in a private artifactory) provides its own config.cmake files. However in that case the package is not a build requirement but a regular requirement of the code being built. Are you saying that the only way to get this "included" is to declare it as a build requirement?

In my case conan usage is restricted to a conan install, to retrieve the package, but the rest of the build is driven by calling CMake externally.

In a separate project I have implemented a completely conan free technique to get the right version of this package from the artifactory (using curl + aql) but I recently discovered the CMakeDeps and thought that might have less overhead.

Regards
Baldur

@SeanSnyders
Copy link
Author

@bldrvnlw Things are a bit uncertain and confusing at the moment - mainly due to lack some concrete example documentation (with toy packages as dependencies, etc) and some possible bugs in default behaviour of the feature. Maybe @memsharded can shed some more light, but through my latest experimentation in this issue I do not think it is behaving correctly yet.

I believe that setting self.cpp_info.set_property("cmake_build_modules", [<package>Config.cmake, ...] in the package_info() should make these available. When the host and build profiles are different (e.g. during cross-compiling) then you also need to explicitly activate your package to be available in the build context via CMakeDeps.build_context_activated = [<package>, ...] as well as possibly add the dependency to the CMakeDeps.build_context_modules = [<package>, ...] if you prefer to use the build context version of the dependency.

Best to check the current documentation of this feature and try things out for yourself: https://docs.conan.io/en/latest/reference/conanfile/tools/cmake/cmakedeps.html

@memsharded
Copy link
Member

I also have a case where the conan package (hosted in a private artifactory) provides its own config.cmake files. However in that case the package is not a build requirement but a regular requirement of the code being built. Are you saying that the only way to get this "included" is to declare it as a build requirement?

Hi @bldrvnlw

Using the internal package xxxx-config.cmake is still possible, that is only restricted in ConanCenter, because you should be aware of 2 main CMake limitations regarding xxxx-config.cmake:

  • Internal package xxx-config.cmake will not work in multi-config environments, because CMake cannot locate or cannot do generator expressions over find_package(). So if you want to switch Debug/Release configuration from Visual Studio or XCode IDEs, that will not work
  • Internal package xxx-config.cmake often have problems with transitivity, and they might find a transitive dependency in the system, instead of a Conan package.

If despite these limitations you still want to use the internal xxx-config.cmake, you can do it, by avoiding the CMakeDeps generator altogether, as you don't want Conan to generate the xxxx-config.cmake files for the dependencies. The CMakeToolchain might still be useful and it is intended to allow locating the xxx-config.cmake inside the packages too.

This discussion is mostly about the extra cmake modules that the CMakeDeps generator will be injecting, which is a different issue than wanting to use your internal xxx-config.cmake modules.

Please let me know if this helps.

@SeanSnyders yes, we know it is still not very clear, we are still heavily working and changing things in all this area, that is the reason the docs are still scarce and confusing. We are trying to stabilize and provide full examples (like conan-io/examples#90)

@memsharded memsharded modified the milestones: 1.38, 1.39 Jun 28, 2021
@cboos
Copy link

cboos commented Jun 28, 2021

My use case was very similar and actually used to work... in conan 1.36, but no longer afterward.

I built a "Qt5" binary package to put together our own special build of Qt. It's very simple and doesn't describe any components on its own, but rather aims at delegating all the details to the existing lib/cmake/Qt5/Qt5Config.cmake provided by Qt which is the entry point for hundreds of additional .cmake files...

I did it that way:

    def package_info(self):
        qt5config = os.path.join('lib', 'cmake', 'Qt5', 'Qt5Config.cmake')
        self.cpp_info.set_property('cmake_build_modules', [qt5config])

This used to work fine with 1.36, as this build module was loaded and thanks to that, all the logic for the various components was available.

However, since 1.37, the build modules are loaded last, so the check for components performed earlier in the generated Qt5Targets.cmake will now fail:

...
  Conan: Component 'Core' NOT found in package 'Qt5'
Call Stack (most recent call first):
  build/Qt5Targets.cmake:35 (conan_message)
  build/Qt5Config.cmake:9 (include)
...

So my request is the same as Sean's: it would be really great if there was an easy way (like we had in 1.36) to reuse the sometimes complex logic of existing cmake files, as provided by the targeted packages. If there's no particular reason to include the build modules last as it's done now, it would be great to simply move that up. If not, perhaps an alternative group of build modules (silly name: cmake_pre_build_modules?) could be defined and these ones could be included prior to the generated *Targets.cmake file?

@lasote lasote self-assigned this Jul 5, 2021
@lasote
Copy link
Contributor

lasote commented Jul 5, 2021

Hi @SeanSnyders, I've been looking at this, the thing is, the new toolchain generators like CMakeDeps and CMakeToolchain or the ones for msbuild, meson, bazel, autotools... all the new generators that work with the generate(self) method, are programmed assuming that the build profile is always specified. That is because, in the Conan 2.0 model, the build profile will be always present (declared or not by the user). That default behavior cannot be done in the 1.X because it would be breaking behavior (because without specifying it, all the build requirements are in the host context and not in the build context) but these new generators are there to help to migrate the recipes to the 2.0 model.
So, I agree the documentation is not explaining that correctly. What we are going to do:

A) Modify the documentation with a note indicating that the usage of build_context_activated, build_context_suffix and build_context_build_modules will fail if no build profile is specified.
B) Will raise when using these properties and there is no build profile
C) Every new generator will print a warning in the constructor if no build profile is specified.

So, summarizing, you would need to specify the build profile, sorry.

@lasote
Copy link
Contributor

lasote commented Jul 5, 2021

@cboos your issue is totally different. We are evaluating the best way to keep your use case working. I'll report back.

@lasote
Copy link
Contributor

lasote commented Jul 5, 2021

@cboos we are going to move the check later and also will check that the actual complete target exists, not based on the internal XXX_COMPONENT_NAMES variable so probably it will work smoothly for you, if the Qt build module declares the target, it would be fine. It will be released at 1.39

@SeanSnyders
Copy link
Author

Hi @lasote
Thanks for the explanation, this is now indeed making more sense into why it is failing for certain scenarios and not for others. I'll experiment with that.
That can explain point 1 in #9112 (comment), what of point 2?

@lasote
Copy link
Contributor

lasote commented Jul 6, 2021

Sure. 1=> is a consequence of the missing build profile, the build modules are not assigned.
2=> Not sure about the mixed build type, probably you have installed both release and debug configurations. Take into account, as marks a comment in the generated config file, that the build_modules are taken from the first configuration installed, that's because there is no CMake multi config mechanism for the build modules, they are just "includes".

@SeanSnyders
Copy link
Author

Hi @lasote

I'd like to get back to point 2 from my comment #9112 (comment): Release being generated when Debug build_type is specified for dependencies.

I am having issues with this where I specify Debug and have GTest/1.10.0 as a (build) dependency and, as in the screenshot in the previous comment, it generates a mixed situation for GTest. This causes linking failure when trying to link a debug unit test app with the release version of GTest that is picked up / generated by Conan:
image

Running command (even explicitly setting Debug for GTest):

conan install . -o shared=False -s build_type=Debug -if=cmake-build-debug -s gtest:build_type=Debug -e CONAN_RUN_TESTS=1 --profile:host=default --profile:build=default --build=missing

Shows these settings

Configuration (profile_host):
[settings]
arch=x86_64
arch_build=x86_64
build_type=Debug
compiler=Visual Studio
compiler.runtime=MDd
compiler.version=16
os=Windows
os_build=Windows
gtest:build_type=Debug
[options]
shared=False
[build_requires]
[env]
CONAN_RUN_TESTS=1
Configuration (profile_build):
[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=Visual Studio
compiler.runtime=MD
compiler.version=16
os=Windows
os_build=Windows
[options]
[build_requires]
[env]

and these requirements

Requirements
Python requires
   xxxxxx/0.5.0@xxxxxxxx/testing
Packages
Build requirements
    xxxxxxxx/0.5.0@xxxxxxx/testing from 'xxxxxxxxxx' - Cache
    cmake/3.19.4 from 'conan-center' - Cache
    gtest/1.10.0 from 'conan-center' - Cache
Build requirements packages
    xxxxxxxxxx/0.5.0@xxxxxx/testing:yyyyyyyyyyyyyyy- Cache
    cmake/3.19.4:0a420ff5c47119e668867cdb51baff0eca1fdb68 - Cache
    gtest/1.10.0:5ad274d83035c78ba2b205e6cf4f1b317aee8e05 - Cache

and note that the package ID for GTest is the Release version even though there is a Debug version on conan-center (https://conan.io/center/gtest?version=1.10.0&revision=5ee038e1d39b4057666e77e49011079e&tab=configuration&os=Windows) for the package.
image

I am confused as to the situation that the GTest conan package contains a Debug version and Conan knows about the different configurations, and the build_type is Debug, so why does Conan not generate cmake files pointing to the right binary package?

How should this work? How do I get my situation to work?

@SeanSnyders
Copy link
Author

SeanSnyders commented Aug 12, 2021

If I read correctly, Conan's build_modules is picking up the first installed configuration of GTest.
So, I did conan remove gtest before I did the same conan install command above with build_type=Debug, and still conan downloaded the Release version of GTest (gtest/1.10.0:5ad274d83035c78ba2b205e6cf4f1b317aee8e05)

image

Looking closer at the output, the profile_build still notes the build_type as Release. So the command line argument -s build_type=Debug only got set on the host profile. This causes the issue.
I created a specific debug profile file that just contains the build_type as Debug and then added it as another profile to be used for both host and build and then conan downloads and uses the correct version of GTest, e.g.
-pr:h default -pr:h buildtype_debug -pr:b default -pr:b buildtype_debug or specifying as command line arguments directly -s:b build_type=Debug -s:h build_type=Debug

Is this a bug? Or what is the logic here?

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

Successfully merging a pull request may close this issue.

5 participants