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

feat: support conan 2 #249

Merged
merged 10 commits into from
Feb 25, 2024
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,16 @@ jobs:
cmake: ${{ matrix.cmake }}
ninja: true
vcpkg: true
conan: true
conan: false
FeignClaims marked this conversation as resolved.
Show resolved Hide resolved
cppcheck: true
clangtidy: true
task: true
doxygen: ${{ !contains(matrix.os, 'macos-11') }}

- name: Install conan2
run: |
pip3 install conan==2.1.0

- name: Test
if: ${{ !cancelled() }}
run: |
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ CMake experience following the best practices.
FetchContent, vcpkg, etc.
- `run_vcpkg`: automatic installation of vcpkg and the project
dependencies
- `run_conan2`: automatic installation of vcpkg and the project
dependencies
- `ENABLE_CONAN` in `project_options`: automatic installation of Conan
and the project dependencies
- `dynamic_project_options`: a wrapper around `project_options` to
Expand Down
1 change: 1 addition & 0 deletions docs/src/Readme_top.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ A general-purpose CMake library that provides functions that improve the CMake e
- using custom linkers (e.g. lld)
- `package_project`: automatic packaging/installation of the project for seamless usage via find_package/target_link through CMake's FetchContent, vcpkg, etc.
- `run_vcpkg`: automatic installation of vcpkg and the project dependencies
- `run_conan2`: automatic installation of Conan 2 and the project dependencies
- `ENABLE_CONAN` in `project_options`: automatic installation of Conan and the project dependencies
- `dynamic_project_options`: a wrapper around `project_options` to change the options on the fly dynamically
- `target_link_system_libraries` and `target_include_system_directories`: linking/including external dependencies/headers without warnings
Expand Down
132 changes: 132 additions & 0 deletions src/Conan.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
include_guard()

function(conan_get_version conan_current_version)
find_program(conan_command "conan" REQUIRED)
execute_process(
COMMAND ${conan_command} --version
OUTPUT_VARIABLE conan_output
RESULT_VARIABLE conan_result
OUTPUT_STRIP_TRAILING_WHITESPACE
)

if(conan_result)
message(FATAL_ERROR "Error when trying to run Conan")
endif()

string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" conan_version ${conan_output})
set(${conan_current_version} ${conan_version} PARENT_SCOPE)
endfunction()

# Run Conan for dependency management
macro(run_conan)
conan_get_version(_conan_current_version)
if(_conan_current_version VERSION_GREATER_EQUAL "2.0.0")
message(FATAL_ERROR
"ENABLE_CONAN in project_options(...) only supports conan 1.\n"
" If you're using conan 2, disable ENABLE_CONAN and use run_conan2(...) before project(...).")
endif()

# Download automatically, you can also just copy the conan.cmake file
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
Expand Down Expand Up @@ -117,3 +141,111 @@ macro(run_conan)
endif()

endmacro()

#[[.rst:

``run_conan2``
=============

Install conan 2 and conan 2 dependencies:

.. code:: cmake

run_conan2()

.. code:: cmake

run_conan2(
HOST_PROFILE default auto-cmake
BUILD_PROFILE default
INSTALL_ARGS --build=missing
)

Note that it should be called before defining ``project()``.

Named String:

- Values are semicolon separated, e.g. ``"--build=never;--update;--lockfile-out=''"``.
However, you can make use of the cmake behaviour that automatically concatenates
multiple space separated string into a semicolon seperated list, e.g.
``--build=never --update --lockfile-out=''``.

- ``HOST_PROFILE``: (Defaults to ``"default;auto-cmake"``). This option
sets the host profile used by conan. When ``auto-cmake`` is specified,
cmake-conan will invoke conan's autodetection mechanism which tries to
guess the system defaults. If multiple profiles are specified, a
`compound profile <https://docs.conan.io/2.0/reference/commands/install.html#profiles-settings-options-conf>`_
will be used - compounded from left to right, where right has the highest priority.

- ``BUILD_PROFILE``: (Defaults to ``"default"``). This option
sets the build profile used by conan. If multiple profiles are specified,
a `compound profile <https://docs.conan.io/2.0/reference/commands/install.html#profiles-settings-options-conf>`_
will be used - compounded from left to right, where right has the highest priority.

- ``INSTALL_ARGS``: (Defaults to ``"--build=missing"``). This option
customizes ``conan install`` command invocation. Note that ``--build``
must be specified, otherwise conan will revert to its default behaviour.

- Two arguments are reserved to the dependency provider implementation
and must not be set: the path to a ``conanfile.txt|.py``, and the output
format (``--format``).

]]
macro(run_conan2)
set(options)
set(one_value_args)
set(multi_value_args
HOST_PROFILE
BUILD_PROFILE
INSTALL_ARGS
)
cmake_parse_arguments(_args "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})

if(CMAKE_VERSION VERSION_LESS "3.24.0")
message(FATAL_ERROR
"run_conan2 only supports cmake 3.24+, please update your cmake.\n"
" If you're using conan 1, set ENABLE_CONAN using project_options(...) or dynamic_project_options(...) after project().")
endif()

conan_get_version(_conan_current_version)
if(_conan_current_version VERSION_LESS "2.0.5")
message(FATAL_ERROR
"run_conan2 only supports conan 2.0.5+, please update your conan.\n"
" If you're using conan 1, set ENABLE_CONAN using project_options(...) or dynamic_project_options(...) after project().")
endif()

# Download automatically, you can also just copy the conan.cmake file
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan_provider.cmake")
message(STATUS "Downloading conan_provider.cmake from https://github.com/conan-io/cmake-conan")
file(
DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/f6464d1e13ef7a47c569f5061f9607ea63339d39/conan_provider.cmake"
"${CMAKE_BINARY_DIR}/conan_provider.cmake"
EXPECTED_HASH SHA256=0a5eb4afbdd94faf06dcbf82d3244331605ef2176de32c09ea9376e768cbb0fc

# TLS_VERIFY ON # fails on some systems
)
endif()

if(NOT _args_HOST_PROFILE)
set(_args_HOST_PROFILE "default;auto-cmake")
endif()

if(NOT _args_BUILD_PROFILE)
set(_args_BUILD_PROFILE "default")
endif()

if(NOT _args_INSTALL_ARGS)
set(_args_INSTALL_ARGS "--build=missing")
endif()

set(CONAN_HOST_PROFILE "${_args_HOST_PROFILE}" CACHE STRING "Conan host profile" FORCE)
set(CONAN_BUILD_PROFILE "${_args_BUILD_PROFILE}" CACHE STRING "Conan build profile" FORCE)
set(CONAN_INSTALL_ARGS "${_args_INSTALL_ARGS}" CACHE STRING "Command line arguments for conan install" FORCE)

# A workaround from https://github.com/conan-io/cmake-conan/issues/595
list(APPEND CMAKE_PROJECT_TOP_LEVEL_INCLUDES ${CMAKE_BINARY_DIR}/conan_provider.cmake)

# Add this to invoke conan even when there's no find_package in CMakeLists.txt.
# This helps users get the third-party package names, which is used in later find_package.
cmake_language(DEFER DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} CALL find_package Git QUIET)
endmacro()
2 changes: 1 addition & 1 deletion tests/install/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ cmake_minimum_required(VERSION 3.16...3.21)
include(../../src/Index.cmake)

run_vcpkg()
run_conan2()

project(anotherproj VERSION 0.1.0 LANGUAGES CXX C)

# Initialize project_options
project_options(
ENABLE_CACHE
ENABLE_CONAN
# WARNINGS_AS_ERRORS
ENABLE_CPPCHECK
ENABLE_CLANG_TIDY
Expand Down
2 changes: 1 addition & 1 deletion tests/install/conanfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
docopt.cpp/0.6.3

[generators]
cmake_find_package_multi
CMakeDeps
2 changes: 1 addition & 1 deletion tests/myproj/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ endif()
run_vcpkg(VCPKG_URL "https://github.com/microsoft/vcpkg.git" VCPKG_REV
"10e052511428d6b0c7fcc63a139e8024bb146032" ENABLE_VCPKG_UPDATE
)
run_conan2()

project(myproj VERSION 0.2.0 LANGUAGES CXX C)

Expand Down Expand Up @@ -54,7 +55,6 @@ project_options(
PREFIX
"myproj"
ENABLE_CACHE
ENABLE_CONAN
# WARNINGS_AS_ERRORS
ENABLE_CPPCHECK
ENABLE_CLANG_TIDY
Expand Down
2 changes: 1 addition & 1 deletion tests/myproj/conanfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
docopt.cpp/0.6.3

[generators]
cmake_find_package_multi
CMakeDeps
Loading