Skip to content

No mechanism to export local recipes before conan install is invoked #732

@juan-amd

Description

@juan-amd

Problem:

When a project has local Conan recipes (not on ConanCenter), there is no way to tell the cmake-conan provider to export them before it runs conan install on the first find_package() call. Because the provider runs conan install automatically, the local recipes must already be in the Conan cache — but there is no hook in the provider to make that happen.

Current workaround:

Manually calling conan export via execute_process in CMakeLists.txt, guarded by a stamp file to avoid re-exporting on every configure:

cmake_minimum_required(VERSION 3.25)
set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES "conan_provider.cmake")

project(MyProject)

# Must run before the first find_package() so local recipes are in the cache
# before the provider invokes conan install.
if(PROJECT_IS_TOP_LEVEL)
    find_program(CONAN_CMD conan REQUIRED)
    file(GLOB recipe_dirs CONFIGURE_DEPENDS LIST_DIRECTORIES true "${CMAKE_SOURCE_DIR}/conan/recipes/*/")
    foreach(recipe_dir ${recipe_dirs})
        if(EXISTS "${recipe_dir}/conanfile.py")
            set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${recipe_dir}/conanfile.py")
            cmake_path(GET recipe_dir FILENAME recipe_name)
            set(stamp "${CMAKE_BINARY_DIR}/conan_export_${recipe_name}.stamp")
            if("${recipe_dir}/conanfile.py" IS_NEWER_THAN "${stamp}")
                execute_process(
                    COMMAND "${CONAN_CMD}" export "${recipe_dir}"
                    COMMAND_ERROR_IS_FATAL ANY
                )
                file(TOUCH "${stamp}")
            endif()
        endif()
    endforeach()
endif()

# Provider runs conan install here, on the first find_package().
find_package(my-local-package REQUIRED)

This works but is boilerplate that every project with local recipes has to reinvent.

Proposed solution

A CONAN_LOCAL_RECIPES_DIR variable pointing at a directory of recipes. The provider would glob for conanfile.py files under it, export each one before invoking conan install, and handle the stamp logic internally:

cmake_minimum_required(VERSION 3.25)
set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES "conan_provider.cmake")
set(CONAN_LOCAL_RECIPES_DIR "${CMAKE_SOURCE_DIR}/conan/recipes/")

project(MyProject)

find_package(my-local-package REQUIRED)  # provider exports local recipes, then runs conan install

The provider would handle the stamp logic and error reporting internally, keeping CMakeLists.txt clean.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions