Skip to content

[feature] Multiple CMake builds from single conanfile #17303

@s-geiger-si

Description

@s-geiger-si

What is your suggestion?

Extracting this issue from #10220 after @memsharded suggested in a comment that it should be its own issue.

I would like to be able to build code that is being generated with the OpenAPI generator which I invoke via Conan. The issue is that the openapi-generator produces a folder tree that contains a pretty-much self contained CMake project.

I tried to explore several alternative options:

  1. Moving openapi generation and built from Conan into CMake
  2. Generating the openapi code via Conan and using add_subdirectory to build everything from a single CMake project.
  3. Building the openapi generated code from conan as a separate project (this is what this issue is about).

Option 1 would imply that we move everything into CMake and use add_custom_command to invoke the openapi-generator. This is not possible, since we cannot load additional CMakeLists.txt files during a CMake configure call.
Option 2 is generally possible, but it has the disadvantage, that install() directives from the openapi modules are being leaked into the main project and we end up installing headers, static libs and other stuff into the main install prefix and then need to filter them out later on.

A better solution would be to explore option 3 and to configure and build the openapi generated code as a separate sub-step via Conan, install it into a CMAKE_PREFIX_PATH and then use find_package from the main project to resolve the dependencies. The openapi generated code only produces static libraries which are being consumed in the main project, so I do not need to create a Conan package from them. Currently I have not found a way to do this, because CMakeToolchain, and CMake assume that a single build is happening.

What I would like to do is:

  1. Install Conan dependencies
  2. Generate OpenAPI stubs with the openapi-generator
  3. Build each of the generated folders and install them via a separate CMake build tree (which can be private to Conan)
  4. Configure the main project and add the install tree to the CMAKE_PREFIX_PATH
  5. Build the main project and proceed to install/package it.

Further background can also be found here: https://stackoverflow.com/questions/78361333/integrate-openapi-generate-with-conan-2-and-cmake-with-proper-caching

Question from @memsharded

@s-geiger-si it would be good to understand why a different toolchain would be necessary. How this would be managed without Conan? Isn't it possible to do it with CMake only then?

Have you tried just calling self.run("cmake .... ) directly for the subprojects?

Not yet, I was hoping that I could reuse the Conan classes for CMake and CMakeToolchain, since I had the impression that this is the best practice approach.

The CMake(self) is a relatively thin wrapper, and regarding the toolchain, still need to understand what toolchain would be use[d] to build these libraries, why the same toolchain wouldn't be the right one.

I think I could reuse the same toolchain, since I do not need a different dependency subset, but as I understand it, the toolchain seems to also control details such as the CMAKE_PREFIX_PATH and the CMAKE_INSTALL_PREFIX or the build folder for the CMake build tree and I am not able to pass this as an overwrite to CMake(self) or to cmake.configure().

What I would effectively like to have is some structure like the following (if that makes sense):

<build-root>/     # as set via --output-folder to conan install/build (i.e., --output-folder ./build)
   main-build/`   # build tree for main project
     install/     # install tree for main project
   openapi-1/     # source tree (generated via conan using openapi-generator)
      build/      # build tree for openapi generated code
        install/  # install tree for openapi generated and built code
   openapi-2/`    # source tree (generated via conan using openapi-generator)
      build/
        install/
   cmake_toolchain.json
   [ other files generated by conan ]

For the main project build tree, I would then like to configure CMake to set CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH:./openapi-1/build/install:./openapi-2/build/install.

So basically, I was hoping I could do something like:

def build(self):
  build_openapi_stubs(...)

  cmake = CMake(self, main-tc) # set build tree to ./main-build and update CMAKE_PREFIX_PATH
  cmake.configure()
  cmake.build()
  
def build_openapi_stubs(...):
   generate_stubs(...)
   cmake = CMake(self) # set build tree to ./openapi-N and install target to ./openapi-N/install
   cmake.configure()
   cmake.build()
   cmake.install()

Maybe I am missing something and this is totally the wrong approach?

Have you read the CONTRIBUTING guide?

  • I've read the CONTRIBUTING guide

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions