conan
conan copied to clipboard
[question] Conan recipe for a thrift IDL wrapper
What is your question?
Hi, how would a recipe look for a thrift IDL wrapper library?
I am migrating an existing conan 1 legacy cmake generator recipe to the new generators (as a first step before considering conan 2)
My loose (but probably incorrect) requirements are:
- It should support local development using the current workflow:
conan install ..,conan build ..,ctest - It should be able to package:
conan create .. - It should not require extensive changes to our current CI Pipelines (but suggestions are welcome on how to update those in future)
- Changes to our pipeline should support both legacy and new generators (we have a lot of repos with the same pipeline, we can't change everything in one go)
What our current recipe and build does:
- The conan recipe in the
build()stage- downloads the specific version of the IDL as an archive from an URL and extracts it onto the
buildfolder - Modify the downloaded IDL (find-replace that can probably be a patch file)
- It has no logic, it is a straight forward find and replace that always does the same irrespective of any options or config.
- downloads the specific version of the IDL as an archive from an URL and extracts it onto the
- The build process (cmake)
- Generate the C++ code from the thrift IDL
- Build a library wrapper around the generated code
- Build some custom C++ code
- The conan
package()stage- Package the C++ library for usage down the chain
Our current recipe does the download and patching in the build() method, but in the spirit of conan 2 I want to remove functionality from the build() method so that we can start moving to the conan install .., cmake --preset XXX workflow.
I have tried to do the get() and patching in the source() method but could not get any combination of layout settings, destination or anything else to work between source() and generate() that enables my two workflows without bad hacking.
What is the proper way to try and support this?
See below an obfuscated example of my conanfile
Click to expand conanfile.py
from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake, cmake_layout
from conan.tools.files import copy, get, replace_in_file
import glob
class SomeInterface(ConanFile):
name = "some-interface"
url = "<url>"
description = "Some Server Interface"
topics = ("IDL")
settings = "os", "compiler", "build_type", "arch"
package_type = "library"
version = "4.1.20"
options = {
"shared": [True, False],
"fPIC": [True, False] }
default_options = {
"shared": False,
"fPIC": True }
default_user = "user"
default_channel = "testing"
exports = f"{name}.properties"
def requirements(self):
self.requires("thrift/0.17.0")
def export_sources(self):
copy(self, "CMakeLists.txt", src=self.recipe_folder, dst=self.export_sources_folder)
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
def configure(self):
if not self.settings.compiler.get_safe("cppstd"):
self.settings.compiler.cppstd = "20"
if self.options.shared:
self.options.rm_safe("fPIC")
def layout(self):
cmake_layout(self, 'Multi-Config')
def export(self):
pass
def source(self):
get(self, "https://some_url/{0}/some_package-{0}.tar.gz".format(self.version), destination="thrift")
for filename in glob.iglob('thrift/*.thrift', recursive=True):
replace_in_file(self, filename, search="namespace cpp <original>", replace="namespace cpp <new>")
def generate(self):
tc = CMakeToolchain(self)
tc.generate()
deps = CMakeDeps(self)
deps.generate()
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
self.copy("*.h", dst="include", src="./include")
self.copy("*.h", dst="include/user", src="user", keep_path=True)
self.copy("*.dll", dst="bin", keep_path=False)
self.copy("*.lib", dst="lib", keep_path=False)
self.copy("*.so", dst="lib", keep_path=False)
self.copy("*.a", dst="lib", keep_path=False)
def package_info(self):
self.cpp_info.libs = self.collect_libs
My CMakeLists.txt have something in this line
set(THRIFT_BASE_DIR ${CMAKE_BINARY_DIR}/thrift/)
I would suspect that if I do the correct thing in the conan recipe, I can drop the set() command in cmake and replace it with the correc: tc.variables["THRIFT_BASE_DIR"] in the generate() step, but I could not get the correct combination between the source() and generate() methods to work.
Any help will be appreciated
Have you read the CONTRIBUTING guide?
- [X] I've read the CONTRIBUTING guide
Hi @CJCombrink
It should support local development using the current workflow: conan install .., conan build .., ctest It should be able to package: conan create .. It should not require extensive changes to our current CI Pipelines (but suggestions are welcome on how to update those in future) Changes to our pipeline should support both legacy and new generators (we have a lot of repos with the same pipeline, we can't change everything in one go)
Yes, both conan create . are identical in Conan 1 and 2. The conan install and conan build are fairly similar, but they have differences, in Conan 2, commands will be simpler, like conan build already does conan install under the hood, so pipelines can be simplified. Also the layout() will encapsulate most of the logic, so command line is simpler, which helps with reproducibility among CI and developers
set(THRIFT_BASE_DIR ${CMAKE_BINARY_DIR}/thrift/)
Yes, it looks like it wouldnt be necessary to do this in CMakeLists.
I think to manage this it would be better to work with something that we can both build and reproduce, otherwise without having access to some_package-{0}.tar.gz, it can be a bit challenging.
I suggest starting from the example code in https://github.com/conan-io/examples2/tree/main/tutorial/developing_packages/local_package_development_flow
As you can see in https://docs.conan.io/2/tutorial/developing_packages/local_package_development_flow.html, I think this closely resembles your intended process. So maybe trying to modify that starting point, putting things in a branch you can share with us. If necessary the external src url "https://github.com/conan-io/libhello/archive/refs/heads/main.zip can point to a different place, if you want to create another simple zip with some fake sources that resemble your layout, that would be perfect to show the issues. It could be something like the strip_root=True or something to tweak in the layout.
Any further question? Can we close this ticket? Thanks!
@memsharded Sorry have not yet had time to get back to creating a test repo to talk around.
I am going to close: I will reach out again when I have a test repo in place, perhaps first on slack and if I then don't make progress I will reach out here again.