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

example for injecting cmake variables #3333

Merged
merged 5 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/tools/cmake/cmake.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ tools.cmake


cmake_toolchain/build_project_cmake_presets
cmake_toolchain/extend_own_cmake_presets
cmake_toolchain/extend_own_cmake_presets
cmake_toolchain/inject_cmake_variables
78 changes: 78 additions & 0 deletions examples/tools/cmake/cmake_toolchain/inject_cmake_variables.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
.. _examples-tools-cmake-toolchain-inject-variables:

CMakeToolchain: Inject arbitrary CMake variables into dependencies
==================================================================

memsharded marked this conversation as resolved.
Show resolved Hide resolved
In the general case, Conan package recipes provide the necessary abstractions via settings, confs, and options
to control different aspects of the build. Many recipes define ``options`` to activate or deactivate features,
optional dependencies, or binary characteristics. Configurations like ``tools.build:cxxflags`` can be used to
inject arbitrary C++ compile flags.

In some exceptional cases, it might be desired to inject CMake variables directly into dependencies doing CMake
builds. This is possible when these dependencies use the ``CMakeToolchain`` integration. Let's check it in this
simple example.

If we have the following package recipe, with a simple ``conanfile.py`` and a ``CMakeLists.txt`` printing a variable:

.. code-block:: python
:caption: conanfile.py

from conan import ConanFile
from conan.tools.cmake import CMake

class AppConan(ConanFile):
name = "foo"
version = "1.0"
settings = "os", "compiler", "build_type", "arch"
exports_sources = "CMakeLists.txt"

generators = "CMakeToolchain"

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()


.. code-block:: cmake
:caption: CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(foo LANGUAGES NONE)
message(STATUS "MYVAR1 ${MY_USER_VAR1}!!")

We can define a profile file and a ``myvars.cmake`` file (both in the same folder) like the following:

.. code-block:: ini
:caption: myprofile

include(default)
[conf]
tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/myvars.cmake

Note the ``{{profile_dir}}`` is a jinja template expression that evaluates to the current profile folder, allowing
to compute the necessary path to ``myvars.cmake`` file. The ``tools.cmake.cmaketoolchain:user_toolchain`` is a **list**
of files to inject to the generated ``conan_toolchain.cmake``, so the ``+=`` operator is used to append to it.

The ``myvars.cmake`` can define as many variables as we want:

.. code-block:: cmake
:caption: myvars.cmake

set(MY_USER_VAR1 "MYVALUE1")


Applying this profile, we can see that the package CMake build effectively uses the variable provided in the
external ``myvars.cmake`` file:

.. code-block:: bash

$ conan create . -pr=myprofile
...
-- MYVAR1 MYVALUE1!!

Note that using ``user_toolchain`` while defining values for confs like ``tools.cmake.cmaketoolchain:system_name`` is supported.

The ``tools.cmake.cmaketoolchain:user_toolchain`` conf value might also be passed in the command line ``-c`` argument,
but the location of the ``myvars.cmake`` needs to be absolute to be found, as jinja replacement doesn't happen in the
command line.