Repository: conan-io/conan
Pull request #16496 (2024-06-18 23:33:51)

CMakeToolchain refactor
Changelog: Omit
Docs: Omit

This had some level of risk of breaking:
- If users are ``select()`` selecting blocks, but count on the variables + preprocessor definitions to be there. I have explicitly excluded the new "variables" and "preprocessor" blocks to be filtered out by ``select()``, they won't and will need explicit ``.remove()`` them if desired, or use the new ``keep()`` method that supersedes ``select()``


Refactors:
- Adding automatically a header for every block with its name
- Adding explanation to every block about the inputs and definitions
- Moved some global code in the toolchain to its own dedicated blocks
- Added some more ``message()`` information when Conan define values in the toolchain
- Normalizing the blank lines
- Some minor PEP style fixes

The goal is to make the generated file more friendly to read, with more hints of what can be configured, and also to prepare the toolchain for a better customization and selection of what blocks to use.




Patch:
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index ae023a009..5d1f34051 100644
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -23,11 +23,12 @@ from conans.model.version import Version
 from conans.util.files import load
 
 
-class Block(object):
-    def __init__(self, conanfile, toolchain):
+class Block:
+    def __init__(self, conanfile, toolchain, name):
         self._conanfile = conanfile
         self._toolchain = toolchain
         self._context_values = None
+        self._name = name
 
     @property
     def values(self):
@@ -44,7 +45,8 @@ class Block(object):
         if context is None:
             return
 
-        template = Template(self.template, trim_blocks=True, lstrip_blocks=True)
+        template = f"########## '{self._name}' block #############\n" + self.template + "\n\n"
+        template = Template(template, trim_blocks=True, lstrip_blocks=True)
         return template.render(**context)
 
     def context(self):
@@ -56,8 +58,10 @@ class Block(object):
 
 
 class VSRuntimeBlock(Block):
-    template = textwrap.dedent("""
-        # Definition of VS runtime, defined from build_type, compiler.runtime, compiler.runtime_type
+    template = textwrap.dedent("""\
+        # Definition of VS runtime CMAKE_MSVC_RUNTIME_LIBRARY, from settings build_type,
+        # compiler.runtime, compiler.runtime_type
+
         {% set genexpr = namespace(str='') %}
         {% for config, value in vs_runtimes.items() %}
             {% set genexpr.str = genexpr.str +
@@ -67,6 +71,7 @@ class VSRuntimeBlock(Block):
         if(NOT "${POLICY_CMP0091}" STREQUAL NEW)
             message(FATAL_ERROR "The CMake policy CMP0091 must be NEW, but is '${POLICY_CMP0091}'")
         endif()
+        message(STATUS "Conan toolchain: Setting CMAKE_MSVC_RUNTIME_LIBRARY={{ genexpr.str  }}")
         set(CMAKE_MSVC_RUNTIME_LIBRARY "{{ genexpr.str }}")
         """)
 
@@ -116,9 +121,11 @@ class VSRuntimeBlock(Block):
 
 
 class VSDebuggerEnvironment(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Definition of CMAKE_VS_DEBUGGER_ENVIRONMENT from "bindirs" folders of dependencies
+        # for execution of applications with shared libraries within the VS IDE
+
         {% if vs_debugger_path %}
-        # Definition of CMAKE_VS_DEBUGGER_ENVIRONMENT
         set(CMAKE_VS_DEBUGGER_ENVIRONMENT "{{ vs_debugger_path }}")
         {% endif %}
         """)
@@ -166,7 +173,9 @@ class VSDebuggerEnvironment(Block):
 
 
 class FPicBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Defining CMAKE_POSITION_INDEPENDENT_CODE for static libraries when necessary
+
         {% if fpic %}
         message(STATUS "Conan toolchain: Setting CMAKE_POSITION_INDEPENDENT_CODE={{ fpic }} (options.fPIC)")
         set(CMAKE_POSITION_INDEPENDENT_CODE {{ fpic }} CACHE BOOL "Position independent code")
@@ -185,11 +194,16 @@ class FPicBlock(Block):
 
 
 class GLibCXXBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Definition of libcxx from 'compiler.libcxx' setting, defining the
+        # right CXX_FLAGS for that libcxx
+
         {% if set_libcxx %}
+        message(STATUS "Conan toolchain: Defining libcxx as C++ flags: {{ set_libcxx }}")
         string(APPEND CONAN_CXX_FLAGS " {{ set_libcxx }}")
         {% endif %}
         {% if glibcxx %}
+        message(STATUS "Conan toolchain: Adding glibcxx compile definition: {{ glibcxx }}")
         add_compile_definitions({{ glibcxx }})
         {% endif %}
         """)
@@ -200,7 +214,9 @@ class GLibCXXBlock(Block):
 
 
 class SkipRPath(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Defining CMAKE_SKIP_RPATH
+
         {% if skip_rpath %}
         set(CMAKE_SKIP_RPATH 1 CACHE BOOL "rpaths" FORCE)
         # Policy CMP0068
@@ -216,7 +232,10 @@ class SkipRPath(Block):
 
 
 class ArchitectureBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Define C++ flags, C flags and linker flags from 'settings.arch'
+
+        message(STATUS "Conan toolchain: Defining architecture flag: {{ arch_flag }}")
         string(APPEND CONAN_CXX_FLAGS " {{ arch_flag }}")
         string(APPEND CONAN_C_FLAGS " {{ arch_flag }}")
         string(APPEND CONAN_SHARED_LINKER_FLAGS " {{ arch_flag }}")
@@ -231,7 +250,10 @@ class ArchitectureBlock(Block):
 
 
 class LinkerScriptsBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Add linker flags from tools.build:linker_scripts conf
+
+        message(STATUS "Conan toolchain: Defining linker script flag: {{ linker_script_flags }}")
         string(APPEND CONAN_EXE_LINKER_FLAGS {{ linker_script_flags }})
         """)
 
@@ -248,7 +270,9 @@ class LinkerScriptsBlock(Block):
 
 
 class CppStdBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Define the C++ and C standards from 'compiler.cppstd' and 'compiler.cstd'
+
         {% if cppstd %}
         message(STATUS "Conan toolchain: C++ Standard {{ cppstd }} with extensions {{ cppstd_extensions }}")
         set(CMAKE_CXX_STANDARD {{ cppstd }})
@@ -285,7 +309,9 @@ class CppStdBlock(Block):
 
 
 class SharedLibBock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Define BUILD_SHARED_LIBS for shared libraries
+
         message(STATUS "Conan toolchain: Setting BUILD_SHARED_LIBS = {{ shared_libs }}")
         set(BUILD_SHARED_LIBS {{ shared_libs }} CACHE BOOL "Build shared libraries")
         """)
@@ -299,7 +325,9 @@ class SharedLibBock(Block):
 
 
 class ParallelBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Define VS paralell build /MP flags
+
         string(APPEND CONAN_CXX_FLAGS " /MP{{ parallel }}")
         string(APPEND CONAN_C_FLAGS " /MP{{ parallel }}")
         """)
@@ -318,12 +346,18 @@ class ParallelBlock(Block):
 
 class AndroidSystemBlock(Block):
 
-    template = textwrap.dedent("""
-        # New toolchain things
+    template = textwrap.dedent("""\
+        # Define Android variables ANDROID_PLATFORM, ANDROID_STL, ANDROID_ABI, etc
+        # and include(.../android.toolchain.cmake) from NDK toolchain file
+
+        # New Android toolchain definitions
+        message(STATUS "Conan toolchain: Setting Android platform: {{ android_platform }}")
         set(ANDROID_PLATFORM {{ android_platform }})
         {% if android_stl %}
+        message(STATUS "Conan toolchain: Setting Android stl: {{ android_stl }}")
         set(ANDROID_STL {{ android_stl }})
         {% endif %}
+        message(STATUS "Conan toolchain: Setting Android abi: {{ android_abi }}")
         set(ANDROID_ABI {{ android_abi }})
         {% if android_use_legacy_toolchain_file %}
         set(ANDROID_USE_LEGACY_TOOLCHAIN_FILE {{ android_use_legacy_toolchain_file }})
@@ -363,7 +397,9 @@ class AndroidSystemBlock(Block):
 
 
 class AppleSystemBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Define Apple architectures, sysroot, deployment target, bitcode, etc
+
         # Set the architectures for which to build.
         set(CMAKE_OSX_ARCHITECTURES {{ cmake_osx_architectures }} CACHE STRING "" FORCE)
         # Setting CMAKE_OSX_SYSROOT SDK, when using Xcode generator the name is enough
@@ -469,7 +505,9 @@ class AppleSystemBlock(Block):
 
 
 class FindFiles(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Define paths to find packages, programs, libraries, etc.
+
         {% if find_package_prefer_config %}
         set(CMAKE_FIND_PACKAGE_PREFER_CONFIG {{ find_package_prefer_config }})
         {% endif %}
@@ -618,7 +656,9 @@ class FindFiles(Block):
 
 
 class PkgConfigBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Define pkg-config from 'tools.gnu:pkg_config' executable and paths
+
         {% if pkg_config %}
         set(PKG_CONFIG_EXECUTABLE {{ pkg_config }} CACHE FILEPATH "pkg-config executable")
         {% endif %}
@@ -643,7 +683,9 @@ class PkgConfigBlock(Block):
 
 
 class UserToolchain(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Include one or more CMake user toolchain from tools.cmake.cmaketoolchain:user_toolchain
+
         {% for user_toolchain in paths %}
         include("{{user_toolchain}}")
         {% endfor %}
@@ -662,7 +704,10 @@ class UserToolchain(Block):
 class ExtraFlagsBlock(Block):
     """This block is adding flags directly from user [conf] section"""
 
-    _template = textwrap.dedent("""
+    _template = textwrap.dedent("""\
+        # Include extra C++, C and linker flags from configuration tools.build:<type>flags
+        # and from CMakeToolchain.extra_<type>_flags
+
         # Conan conf flags start: {{config}}
         {% if cxxflags %}
         string(APPEND CONAN_CXX_FLAGS{{suffix}} "{% for cxxflag in cxxflags %} {{ cxxflag }}{% endfor %}")
@@ -753,7 +798,9 @@ class ExtraFlagsBlock(Block):
 
 
 class CMakeFlagsInitBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Define CMAKE_<XXX>_FLAGS from CONAN_<XXX>_FLAGS
+
         foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
             string(TOUPPER ${config} config)
             if(DEFINED CONAN_CXX_FLAGS_${config})
@@ -782,12 +829,13 @@ class CMakeFlagsInitBlock(Block):
         if(DEFINED CONAN_EXE_LINKER_FLAGS)
           string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " ${CONAN_EXE_LINKER_FLAGS}")
         endif()
-
         """)
 
 
 class TryCompileBlock(Block):
-    template = textwrap.dedent("""
+    template = textwrap.dedent("""\
+        # Blocks after this one will not be added when running CMake try/checks
+
         get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE )
         if(_CMAKE_IN_TRY_COMPILE)
             message(STATUS "Running toolchain IN_TRY_COMPILE")
@@ -821,14 +869,12 @@ class CompilersBlock(Block):
 
 
 class GenericSystemBlock(Block):
-    template = textwrap.dedent("""
-        ########## generic_system block #############
+    template = textwrap.dedent("""\
         # Definition of system, platform and toolset
-        #############################################
+
         {% if cmake_sysroot %}
         set(CMAKE_SYSROOT {{ cmake_sysroot }})
         {% endif %}
-
         {% if cmake_system_name %}
         # Cross building
         set(CMAKE_SYSTEM_NAME {{ cmake_system_name }})
@@ -947,7 +993,8 @@ class GenericSystemBlock(Block):
         return os_host in ('iOS', 'watchOS', 'tvOS', 'visionOS') or (
                 os_host == 'Macos' and (arch_host != arch_build or os_build != os_host))
 
-    def _get_darwin_version(self, os_name, os_version):
+    @staticmethod
+    def _get_darwin_version(os_name, os_version):
         # version mapping from https://en.wikipedia.org/wiki/Darwin_(operating_system)
         version_mapping = {
             "Macos": {
@@ -1063,8 +1110,11 @@ class GenericSystemBlock(Block):
                 "winsdk_version": winsdk_version,
                 "gen_platform_sdk_version": gen_platform_sdk_version}
 
+
 class ExtraVariablesBlock(Block):
-    template = textwrap.dedent(r"""
+    template = textwrap.dedent("""\
+        # Definition of extra CMake variables from tools.cmake.cmaketoolchain:extra_variables
+
         {% if extra_variables %}
         {% for key, value in extra_variables.items() %}
         set({{ key }} {{ value }})
@@ -1072,7 +1122,7 @@ class ExtraVariablesBlock(Block):
         {% endif %}
     """)
 
-    CMAKE_CACHE_TYPES = ["BOOL","FILEPATH", "PATH", "STRING", "INTERNAL"]
+    CMAKE_CACHE_TYPES = ["BOOL", "FILEPATH", "PATH", "STRING", "INTERNAL"]
 
     def get_exact_type(self, key, value):
         if isinstance(value, str):
@@ -1096,27 +1146,30 @@ class ExtraVariablesBlock(Block):
                     raise ConanException(f'tools.cmake.cmaketoolchain:extra_variables "{key}" invalid type "{var_type}" for cache variable. Possible types: {", ".join(self.CMAKE_CACHE_TYPES)}')
                 # Set docstring as variable name if not defined
                 docstring = value.get("docstring") or key
-                force_str = " FORCE" if is_force else "" # Support python < 3.11
+                force_str = " FORCE" if is_force else ""  # Support python < 3.11
                 return f"{var_value} CACHE {var_type} \"{docstring}\"{force_str}"
             else:
                 if is_force:
                     raise ConanException(f'tools.cmake.cmaketoolchain:extra_variables "{key}" "force" is only allowed for cache variables')
                 return var_value
 
-
     def context(self):
         # Reading configuration from "tools.cmake.cmaketoolchain:extra_variables"
-        extra_variables = self._conanfile.conf.get("tools.cmake.cmaketoolchain:extra_variables", default={}, check_type=dict)
+        extra_variables = self._conanfile.conf.get("tools.cmake.cmaketoolchain:extra_variables",
+                                                   default={}, check_type=dict)
         parsed_extra_variables = {}
         for key, value in extra_variables.items():
             parsed_extra_variables[key] = self.get_exact_type(key, value)
         return {"extra_variables": parsed_extra_variables}
 
+
 class OutputDirsBlock(Block):
 
     @property
     def template(self):
-        return textwrap.dedent("""
+        return textwrap.dedent("""\
+           # Definition of CMAKE_INSTALL_XXX folders
+
            {% if package_folder %}
            set(CMAKE_INSTALL_PREFIX "{{package_folder}}")
            {% endif %}
@@ -1152,6 +1205,81 @@ class OutputDirsBlock(Block):
                 "default_res": self._get_cpp_info_value("resdirs")}
 
 
+class VariablesBlock(Block):
+    @property
+    def template(self):
+        return textwrap.dedent("""\
+            # Definition of CMake variables from CMakeToolchain.variables values
+
+            {% macro iterate_configs(var_config, action) %}
+            {% for it, values in var_config.items() %}
+                {% set genexpr = namespace(str='') %}
+                {% for conf, value in values -%}
+                set(CONAN_DEF_{{ conf }}{{ it }} "{{ value }}")
+                {% endfor %}
+                {% for conf, value in values -%}
+                    {% set genexpr.str = genexpr.str +
+                                          '$<IF:$<CONFIG:' + conf + '>,${CONAN_DEF_' + conf|string + it|string + '},' %}
+                    {% if loop.last %}{% set genexpr.str = genexpr.str + '""' -%}{%- endif -%}
+                {% endfor %}
+                {% for i in range(values|count) %}{% set genexpr.str = genexpr.str + '>' %}
+                {% endfor %}
+                set({{ it }} {{ genexpr.str }} CACHE STRING
+                    "Variable {{ it }} conan-toolchain defined")
+            {% endfor %}
+            {% endmacro %}
+            # Variables
+            {% for it, value in variables.items() %}
+            {% if value is boolean %}
+            set({{ it }} {{ "ON" if value else "OFF"}} CACHE BOOL "Variable {{ it }} conan-toolchain defined")
+            {% else %}
+            set({{ it }} "{{ value }}" CACHE STRING "Variable {{ it }} conan-toolchain defined")
+            {% endif %}
+            {% endfor %}
+            # Variables  per configuration
+            {{ iterate_configs(variables_config, action='set') }}
+            """)
+
+    def context(self):
+        return {"variables": self._toolchain.variables,
+                "variables_config": self._toolchain.variables.configuration_types}
+
+
+class PreprocessorBlock(Block):
+    @property
+    def template(self):
+        return textwrap.dedent("""\
+        # Preprocessor definitions from CMakeToolchain.preprocessor_definitions values
+
+        {% for it, value in preprocessor_definitions.items() %}
+        {% if value is none %}
+        add_compile_definitions("{{ it }}")
+        {% else %}
+        add_compile_definitions("{{ it }}={{ value }}")
+        {% endif %}
+        {% endfor %}
+        # Preprocessor definitions per configuration
+        {% for name, values in preprocessor_definitions_config.items() %}
+        {%- for (conf, value) in values %}
+        {% if value is none %}
+        set(CONAN_DEF_{{conf}}_{{name}} "{{name}}")
+        {% else %}
+        set(CONAN_DEF_{{conf}}_{{name}} "{{name}}={{value}}")
+        {% endif %}
+        {% endfor %}
+        add_compile_definitions(
+        {%- for (conf, value) in values %}
+        $<$<CONFIG:{{conf}}>:${CONAN_DEF_{{conf}}_{{name}}}>
+        {%- endfor -%})
+        {% endfor %}
+        """)
+
+    def context(self):
+        return {"preprocessor_definitions": self._toolchain.preprocessor_definitions,
+                "preprocessor_definitions_config":
+                    self._toolchain.preprocessor_definitions.configuration_types}
+
+
 class ToolchainBlocks:
     def __init__(self, conanfile, toolchain, items=None):
         self._blocks = OrderedDict()
@@ -1159,7 +1287,7 @@ class ToolchainBlocks:
         self._toolchain = toolchain
         if items:
             for name, block in items:
-                self._blocks[name] = block(conanfile, toolchain)
+                self._blocks[name] = block(conanfile, toolchain, name)
 
     def keys(self):
         return self._blocks.keys()
@@ -1173,6 +1301,16 @@ class ToolchainBlocks:
             del self._blocks[arg]
 
     def select(self, name, *args):
+        """
+        keep the blocks provided as arguments, remove the others, except pre-existing "variables"
+        and "preprocessor", to not break behavior
+        """
+        self._conanfile.output.warning("CMakeToolchain.select is deprecated. Use blocks.enabled()"
+                                       " instead", warn_tag="deprecated")
+        to_keep = [name] + list(args) + ["variables", "preprocessor"]
+        self._blocks = OrderedDict((k, v) for k, v in self._blocks.items() if k in to_keep)
+
+    def enabled(self, name, *args):
         """
         keep the blocks provided as arguments, remove the others
         """
@@ -1182,7 +1320,7 @@ class ToolchainBlocks:
     def __setitem__(self, name, block_type):
         # Create a new class inheriting Block with the elements of the provided one
         block_type = type('proxyUserBlock', (Block,), dict(block_type.__dict__))
-        self._blocks[name] = block_type(self._conanfile, self._toolchain)
+        self._blocks[name] = block_type(self._conanfile, self._toolchain, name)
 
     def __getitem__(self, name):
         return self._blocks[name]
diff --git a/conan/tools/cmake/toolchain/toolchain.py b/conan/tools/cmake/toolchain/toolchain.py
index 0692751eb..6d834ec9b 100644
--- a/conan/tools/cmake/toolchain/toolchain.py
+++ b/conan/tools/cmake/toolchain/toolchain.py
@@ -9,11 +9,12 @@ from conan.internal import check_duplicated_generator
 from conan.tools.build import use_win_mingw
 from conan.tools.cmake.presets import write_cmake_presets
 from conan.tools.cmake.toolchain import CONAN_TOOLCHAIN_FILENAME
-from conan.tools.cmake.toolchain.blocks import ExtraVariablesBlock, ToolchainBlocks, UserToolchain, GenericSystemBlock, \
+from conan.tools.cmake.toolchain.blocks import ExtraVariablesBlock, ToolchainBlocks, UserToolchain, \
+    GenericSystemBlock, \
     AndroidSystemBlock, AppleSystemBlock, FPicBlock, ArchitectureBlock, GLibCXXBlock, VSRuntimeBlock, \
     CppStdBlock, ParallelBlock, CMakeFlagsInitBlock, TryCompileBlock, FindFiles, PkgConfigBlock, \
     SkipRPath, SharedLibBock, OutputDirsBlock, ExtraFlagsBlock, CompilersBlock, LinkerScriptsBlock, \
-    VSDebuggerEnvironment
+    VSDebuggerEnvironment, VariablesBlock, PreprocessorBlock
 from conan.tools.cmake.utils import is_multi_configuration
 from conan.tools.env import VirtualBuildEnv, VirtualRunEnv
 from conan.tools.intel import IntelCC
@@ -56,39 +57,18 @@ class Variables(OrderedDict):
                     data[key] = str(var).replace('"', '\\"')
 
 
-class CMakeToolchain(object):
+class CMakeToolchain:
 
     filename = CONAN_TOOLCHAIN_FILENAME
 
-    # TODO: Clean this macro, do it explicitly for variables
-    _template = textwrap.dedent("""
-        {% macro iterate_configs(var_config, action) %}
-            {% for it, values in var_config.items() %}
-                {% set genexpr = namespace(str='') %}
-                {% for conf, value in values -%}
-                set(CONAN_DEF_{{ conf }}{{ it }} "{{ value }}")
-                {% endfor %}
-                {% for conf, value in values -%}
-                    {% set genexpr.str = genexpr.str +
-                                          '$<IF:$<CONFIG:' + conf + '>,${CONAN_DEF_' + conf|string + it|string + '},' %}
-                    {% if loop.last %}{% set genexpr.str = genexpr.str + '""' -%}{%- endif -%}
-                {% endfor %}
-                {% for i in range(values|count) %}{% set genexpr.str = genexpr.str + '>' %}
-                {% endfor %}
-                set({{ it }} {{ genexpr.str }} CACHE STRING
-                    "Variable {{ it }} conan-toolchain defined")
-            {% endfor %}
-        {% endmacro %}
-
+    _template = textwrap.dedent("""\
         # Conan automatically generated toolchain file
         # DO NOT EDIT MANUALLY, it will be overwritten
 
         # Avoid including toolchain file several times (bad if appending to variables like
         #   CMAKE_CXX_FLAGS. See https://github.com/android/ndk/issues/323
         include_guard()
-
         message(STATUS "Using Conan toolchain: ${CMAKE_CURRENT_LIST_FILE}")
-
         if(${CMAKE_VERSION} VERSION_LESS "3.15")
             message(FATAL_ERROR "The 'CMakeToolchain' generator only works with CMake >= 3.15")
         endif()
@@ -97,41 +77,6 @@ class CMakeToolchain(object):
         {{ conan_block }}
         {% endfor %}
 
-        # Variables
-        {% for it, value in variables.items() %}
-        {% if value is boolean %}
-        set({{ it }} {{ "ON" if value else "OFF"}} CACHE BOOL "Variable {{ it }} conan-toolchain defined")
-        {% else %}
-        set({{ it }} "{{ value }}" CACHE STRING "Variable {{ it }} conan-toolchain defined")
-        {% endif %}
-        {% endfor %}
-        # Variables  per configuration
-        {{ iterate_configs(variables_config, action='set') }}
-
-        # Preprocessor definitions
-        {% for it, value in preprocessor_definitions.items() %}
-        {% if value is none %}
-        add_compile_definitions("{{ it }}")
-        {% else %}
-        add_compile_definitions("{{ it }}={{ value }}")
-        {% endif %}
-        {% endfor %}
-        # Preprocessor definitions per configuration
-        {% for name, values in preprocessor_definitions_config.items() %}
-        {%- for (conf, value) in values %}
-        {% if value is none %}
-        set(CONAN_DEF_{{conf}}_{{name}} "{{name}}")
-        {% else %}
-        set(CONAN_DEF_{{conf}}_{{name}} "{{name}}={{value}}")
-        {% endif %}
-        {% endfor %}
-        add_compile_definitions(
-        {%- for (conf, value) in values %}
-        $<$<CONFIG:{{conf}}>:${CONAN_DEF_{{conf}}_{{name}}}>
-        {%- endfor -%})
-        {% endfor %}
-
-
         if(CMAKE_POLICY_DEFAULT_CMP0091)  # Avoid unused and not-initialized warnings
         endif()
         """)
@@ -171,7 +116,9 @@ class CMakeToolchain(object):
                                        ("pkg_config", PkgConfigBlock),
                                        ("rpath", SkipRPath),
                                        ("shared", SharedLibBock),
-                                       ("output_dirs", OutputDirsBlock)])
+                                       ("output_dirs", OutputDirsBlock),
+                                       ("variables", VariablesBlock),
+                                       ("preprocessor", PreprocessorBlock)])
 
         # Set the CMAKE_MODULE_PATH and CMAKE_PREFIX_PATH to the deps .builddirs
         self.find_builddirs = True
@@ -188,10 +135,7 @@ class CMakeToolchain(object):
 
         blocks = self.blocks.process_blocks()
         ctxt_toolchain = {
-            "variables": self.variables,
-            "variables_config": self.variables.configuration_types,
-            "preprocessor_definitions": self.preprocessor_definitions,
-            "preprocessor_definitions_config": self.preprocessor_definitions.configuration_types,
+
             "conan_blocks": blocks
         }
 


Test patch:
diff --git a/test/unittests/tools/cmake/test_cmaketoolchain.py b/test/unittests/tools/cmake/test_cmaketoolchain.py
index 3d66adada..8ba5ff7f0 100644
--- a/test/unittests/tools/cmake/test_cmaketoolchain.py
+++ b/test/unittests/tools/cmake/test_cmaketoolchain.py
@@ -58,10 +58,16 @@ def test_remove(conanfile):
     assert "_CMAKE_IN_TRY_COMPILE" in content
 
 
-def test_filter(conanfile):
+def test_select_blocks(conanfile):
     toolchain = CMakeToolchain(conanfile)
     toolchain.blocks.select("generic_system")
     content = toolchain.content
+    assert "########## 'generic_system' block #############" in content
+    assert "########## 'cmake_flags_init' block #############" not in content
+    assert "########## 'libcxx' block #############" not in content
+    # These are not removed by default, to not break behavior
+    assert "########## 'variables' block #############" in content
+    assert "########## 'preprocessor' block #############" in content
     assert 'CMAKE_SYSTEM_NAME' in content
     assert "CMAKE_CXX_FLAGS_INIT" not in content
     assert "_CMAKE_IN_TRY_COMPILE" not in content
@@ -70,10 +76,24 @@ def test_filter(conanfile):
     toolchain = CMakeToolchain(conanfile)
     toolchain.blocks.select("generic_system", "cmake_flags_init")
     content = toolchain.content
+    assert "########## 'generic_system' block #############" in content
+    assert "########## 'cmake_flags_init' block #############" in content
+    assert "########## 'libcxx' block #############" not in content
+    # These are not removed by default, to not break behavior
+    assert "########## 'variables' block #############" in content
+    assert "########## 'preprocessor' block #############" in content
     assert 'CMAKE_SYSTEM_NAME' in content
     assert "CMAKE_CXX_FLAGS_INIT" in content
     assert "_CMAKE_IN_TRY_COMPILE" not in content
 
+    # remove multiple
+    toolchain = CMakeToolchain(conanfile)
+    toolchain.blocks.enabled("generic_system")
+    content = toolchain.content
+    assert "########## 'generic_system' block #############" in content
+    assert "########## 'variables' block #############" not in content
+    assert "########## 'preprocessor' block #############" not in content
+
 
 def test_dict_keys(conanfile):
     toolchain = CMakeToolchain(conanfile)