conan icon indicating copy to clipboard operation
conan copied to clipboard

[question] Can anyone help me migrate my project conanfile?

Open paulocoutinhox opened this issue 3 years ago • 13 comments

Hi,

Can anyone help me migrate my project conanfile?

My try is here: https://github.com/nativium/nativium/pull/23/files

Today, im generating conanbuildinfo.cmake, because it is imported into the cmake: https://github.com/nativium/nativium/blob/main/cmake/functions.cmake#L90-L97

Im searching a lot about how to migrate the current method to the new v2 method of using cmake.

@uilianries @ericLemanissier @SpaceIm can you help me?

Thanks for any help.

paulocoutinhox avatar Sep 20 '22 22:09 paulocoutinhox

The error is:

conanfile.py (nativium/None): Calling build()
ERROR: conanfile.py (nativium/None): Error in build() method, line 66
	cmake = CMake(self)
	ConanException: Usage of toolchain is only supported with 'cmake_find_package' or 'cmake_find_package_multi' generators
COMMAND: conan build /Users/paulo/Developer/workspaces/cpp/nativium/conan/recipe/conanfile.py --source-folder /Users/paulo/Developer/workspaces/cpp/nativium --build-folder /Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/target --install-folder /Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/conan
WORKING DIR: /Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/target
[ERROR] Command execution has failed

It fails inside conan:

def _validate_recipe(conanfile):
    forbidden_generators = ["cmake", "cmake_multi"]
    if any(it in conanfile.generators for it in forbidden_generators):
        raise ConanException("Usage of toolchain is only supported with 'cmake_find_package'"
                             " or 'cmake_find_package_multi' generators")

paulocoutinhox avatar Sep 20 '22 23:09 paulocoutinhox

Hi @paulocoutinhox

The first important steps:

  • Drop the generators = "cmake"
  • Use instead CMakeDeps and CMakeToolchain: https://docs.conan.io/en/latest/migrating_to_2.0/recipes.html#the-generate-method
  • The CMake helper that you are using should integrate them automatically

You probably also want to drop the layout specific generator in the recipe, as long as it is defined correctly in tools.cmake.cmaketoolchain:generator the layout will work.

memsharded avatar Sep 20 '22 23:09 memsharded

@memsharded How/where to define this tools.cmake.cmaketoolchain:generator?

paulocoutinhox avatar Sep 20 '22 23:09 paulocoutinhox

You can define it either in your profile, but most typical on your command line as -c tools.cmake...=value, because it is the developer that wants to select a different generator than the one typically used in CI, for example. Unless you want the generator kind of hardcoded in the recipe, it depends on the use case.

memsharded avatar Sep 20 '22 23:09 memsharded

@memsharded i already tried use CMakeDeps/CMakeToolchain, because i see on other recipes from CCI, but im still doing something wrong because when i use it, i get error on build:

conanfile.py (nativium/None): Calling build()
ERROR: conanfile.py (nativium/None): Error in build() method, line 59
	cmake = CMake(self)
	FileNotFoundError: [Errno 2] No such file or directory: '/Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/target/build/generators/CMakePresets.json'
COMMAND: conan build /Users/paulo/Developer/workspaces/cpp/nativium/conan/recipe/conanfile.py --source-folder /Users/paulo/Developer/workspaces/cpp/nativium --build-folder /Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/target --install-folder /Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/conan
WORKING DIR: /Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/target
[ERROR] Command execution has failed

And it don't generate the file conanbuildinfo.cmake.

I need remove the build method from my conanfile and change to generate method with code:

def generate(self):
        # This generates "conan_toolchain.cmake" in self.generators_folder
        tc = CMakeToolchain(self)
        tc.variables["MYVAR"] = "1"
        tc.preprocessor_definitions["MYDEFINE"] = "2"
        tc.generate()

???

paulocoutinhox avatar Sep 21 '22 00:09 paulocoutinhox

And it don't generate the file conanbuildinfo.cmake.

yes, they are not expected to generated that file. They provide "transparent" integration, your CMakeLists.txt will not have anything Conan specific. You need to add the standard find_package(...) to your CMakeLists, and the COnan generators will manage to get the dependencies.

Also the cmake.definitions in the build() still seems wrong, it has to be moved to the CMakeToolchain in generate().

Something seems wrong with the layout. Maybe trying out the conan new hello/0.1 -m=cmake_lib template can help understanding the basics of the new generators.

memsharded avatar Sep 21 '22 00:09 memsharded

@memsharded I do that changes, but the error is the same:

[INFO] Nativium: Extending conan configuration with module app-core
conanfile.py (nativium/None): Calling build()
ERROR: conanfile.py (nativium/None): Error in build() method, line 103
	cmake = CMake(self)
	FileNotFoundError: [Errno 2] No such file or directory: '/Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/target/build/generators/CMakePresets.json'
COMMAND: conan build /Users/paulo/Developer/workspaces/cpp/nativium/conan/recipe/conanfile.py --source-folder /Users/paulo/Developer/workspaces/cpp/nativium --build-folder /Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/target --install-folder /Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/conan
WORKING DIR: /Users/paulo/Developer/workspaces/cpp/nativium/build/macos/debug/x86_64/target

I generate a new project with conan new [...] and my conanfile is equal that generated file: https://github.com/nativium/nativium/pull/23/files

I also add the generator to profiles.

And after call install it only generate these files:

image

Log:

[INFO] Building for: arm64/release...
Configuration (profile_host):
[settings]
arch=armv8
arch_build=armv8
build_type=Release
compiler=apple-clang
compiler.libcxx=libc++
compiler.version=13.1
os=Macos
os.sdk=macosx
os.version=11.0
os_build=Macos
[options]
nativium_arch=arm64
nativium_build_type=release
nativium_product_name=Nativium
nativium_project_name=nativium
nativium_target=macos
nativium_version=1.0.0
nativium_version_code=1
[build_requires]
[env]
[conf]
tools.cmake.cmaketoolchain:generator=Xcode

Configuration (profile_build):
[settings]
arch=armv8
arch_build=armv8
build_type=Release
compiler=apple-clang
compiler.libcxx=libc++
compiler.version=13.1
os=Macos
os_build=Macos
[options]
[build_requires]
[env]

[INFO] Nativium: Extending conan configuration with module app-core
[INFO] Nativium: Extending conan requirements with module app-core
conanfile.py (nativium/None): Installing package
Requirements
Packages

Installing (downloading, building) binaries...
conanfile.py (nativium/None): Generator 'CMakeDeps' calling 'generate()'
conanfile.py (nativium/None): Generator txt created conanbuildinfo.txt
conanfile.py (nativium/None): Generator 'CMakeToolchain' calling 'generate()'
conanfile.py (nativium/None): Calling generate()
conanfile.py (nativium/None): Aggregating env generators
conanfile.py (nativium/None): Generated conaninfo.txt
conanfile.py (nativium/None): Generated graphinfo
[OK] 

paulocoutinhox avatar Sep 21 '22 00:09 paulocoutinhox

I am checking the PR and the code and the CI and I am missing something. The folder is D:\\a\\nativium\\nativium\\build\\tests\\debug\\x86_64\\target\\build\\generators\\CMakePresets.json, so it doesn't seem a conan create in the cache. Can you please share the steps to reproduce locally on Windows?

memsharded avatar Sep 21 '22 07:09 memsharded

Hi @memsharded,

Steps:

git clone https://github.com/nativium/nativium.git
cd nativium
python3 nativium.py conan setup
python3 nativium.py target windows setup
python3 nativium.py target windows build

paulocoutinhox avatar Sep 21 '22 10:09 paulocoutinhox

Hi @memsharded,

Did you found something?

Thanks.

paulocoutinhox avatar Sep 21 '22 19:09 paulocoutinhox

Hi @paulocoutinhox

Not yet, first I'd need to create a virtualenv to install your requirements like from pygemstones.io import file as f, that I don't have installed. I haven't done it yet, because I might be missing something. The code that I am checking out still contains the legacy cmake generator, no generate(), etc, so seem recipe is still not the modern one. Should I checkout a different branch?

memsharded avatar Sep 21 '22 22:09 memsharded

Hi @memsharded, sorry, my mistake about git clone. You need checkout branch "recipe-conan-v2":

git clone https://github.com/nativium/nativium.git -b recipe-conan-v2

paulocoutinhox avatar Sep 22 '22 01:09 paulocoutinhox

I am having a look, but struggling a bit to understand the layers on top of Conan.

I'd say that the usage of the different folders like

"--source-folder",
proj_path,
"--build-folder",

In the build command is not expected anymore. The goal of the layout() method is to get rid of those things. Is it possible that we could have a reproducible case with Conan commands directly? Maybe starting with a simple conan create would be a good start, then we could have a look to the local flow install + build.

memsharded avatar Sep 22 '22 08:09 memsharded

Ok @memsharded. I made a small project from conan new command and create a structure equal my project to make tests. https://github.com/paulocoutinhox/conan-cmake-v2

Only left a problem with include files using Find_package. I get a sample of sqlitecpp from CCI, and it is not finding the include paths:

Error: https://github.com/paulocoutinhox/conan-cmake-v2/actions/runs/3109394367/jobs/5039569584#step:10:255

Log:

[ 50%] Building CXX object CMakeFiles/hello.dir/src/hello.cpp.o
/home/runner/work/conan-cmake-v2/conan-cmake-v2/src/hello.cpp:3:10: fatal error: SQLiteCpp/SQLiteCpp.h: No such file or directory
    3 | #include <SQLiteCpp/SQLiteCpp.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

It only works when i add include dirs:

target_include_directories(${PROJECT_NAME} PUBLIC ${SQLiteCpp_INCLUDE_DIRS})

Is this correct? I need add all include paths to target?

paulocoutinhox avatar Sep 22 '22 23:09 paulocoutinhox

This fixes the conan create command:

diff --git a/conan/recipe/conanfile.py b/conan/recipe/conanfile.py
index 6b8451c..1dfd944 100644
--- a/conan/recipe/conanfile.py
+++ b/conan/recipe/conanfile.py
@@ -1,7 +1,7 @@
 import os

 from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps
-
+from conan.tools.files import copy
 from conan import ConanFile


@@ -20,11 +20,13 @@ class HelloConan(ConanFile):
     settings = "os", "compiler", "build_type", "arch"
     options = {"shared": [True, False], "fPIC": [True, False]}
     default_options = {"shared": False, "fPIC": True}
+    generators = "CMakeToolchain", "CMakeDeps"

     # Sources are located in the same place as this recipe, copy them to the recipe
-    exports_sources = "CMakeLists.txt", "src/*", "include/*"
-
-    generators = "CMakeToolchain", "CMakeDeps"
+    def export_sources(self):
+        copy(self, "CMakeLists.txt", os.path.join(self.recipe_folder, "../.."), self.export_sources_folder)
+        copy(self, "src/*", os.path.join(self.recipe_folder, "../.."), self.export_sources_folder)
+        copy(self, "include/*", os.path.join(self.recipe_folder, "../.."), self.export_sources_folder)

The problem is that the export_sources attribute is not capable of representing correctly a layout when you have the conanfile.py in a subfolder like conan/recipe, so you need the full power of the method. In general, putting the recipe in a subfolder instead of the root of the repo makes thing more complicated, and this is why it is recommended to put the conanfile.py in the root if possible.

The local flow also works with simply:

conan install conan/recipe 
conan build conan/recipe

memsharded avatar Sep 23 '22 00:09 memsharded

Hi @memsharded, this is already solved. Im only with one doubt.

For all dependencies i need add its library path and include path manually? Example for sqlitecpp:

target_link_libraries(${PROJECT_NAME} PRIVATE SQLiteCpp)
target_include_directories(${PROJECT_NAME} PUBLIC ${SQLiteCpp_INCLUDE_DIRS})

Sample project with all platforms tests: https://github.com/paulocoutinhox/conan-cmake-v2

paulocoutinhox avatar Sep 23 '22 00:09 paulocoutinhox

No, for dependencies, only linking with the targets is necessary, and only the direct dependencies declared, the transitive ones should be automatic. Definitely not the include dirs.

So something like:

find_package(sqlitecpp CONFIG REQUIRED)

target_link_libraries(mytarget PRIVATE sqlitecpp::sqlitecpp) # actual name of the target not tested

which is the standard modern CMake approach should work.

memsharded avatar Sep 23 '22 08:09 memsharded

@memsharded strange, because without add include dirs, it don't find the headers. You can see here: https://github.com/paulocoutinhox/conan-cmake-v2/blob/main/CMakeLists.txt

And can try:

git clone https://github.com/paulocoutinhox/conan-cmake-v2.git
cd conan-cmake-v2
make desktop

paulocoutinhox avatar Sep 23 '22 09:09 paulocoutinhox

But that still have the

target_link_libraries(${PROJECT_NAME} PRIVATE ${SQLite3_LIBRARIES})

You are linking with the bare libraries, not the target names. The target names should be displayed when cmake runs. You should replace it for something like:

target_link_libraries(${PROJECT_NAME} PRIVATE sqlite3::sqlite3)

memsharded avatar Sep 23 '22 09:09 memsharded

@memsharded forget man, it is working, my mistake in some place, thanks.

paulocoutinhox avatar Sep 23 '22 09:09 paulocoutinhox

Hi @memsharded. Everything was migrate. Thanks.

I open an issue about a bug that i get and create a simple project to check: https://github.com/conan-io/conan/issues/12195

Can you help there?

paulocoutinhox avatar Sep 25 '22 00:09 paulocoutinhox