From 9ac4720e159950a96f3fd0dcef602c0029524fab Mon Sep 17 00:00:00 2001
From: James <james@conan.io>
Date: Tue, 27 Feb 2024 09:44:18 +0100
Subject: [PATCH] fix issues and improve CMakeToolchain.preprocessor (#15756)

* fix issues and improve CMakeToolchain.preprocessor

* fix test
---
 conan/tools/cmake/toolchain/toolchain.py      | 21 ++++++++++++++-----
 .../functional/toolchains/cmake/test_cmake.py |  9 ++++----
 .../toolchains/cmake/test_cmake_toolchain.py  |  5 +++++
 3 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/conan/tools/cmake/toolchain/toolchain.py b/conan/tools/cmake/toolchain/toolchain.py
index ac5770515bf..1772e3155c2 100644
--- a/conan/tools/cmake/toolchain/toolchain.py
+++ b/conan/tools/cmake/toolchain/toolchain.py
@@ -60,6 +60,7 @@ class CMakeToolchain(object):
 
     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() %}
@@ -74,12 +75,8 @@ class CMakeToolchain(object):
                 {% endfor %}
                 {% for i in range(values|count) %}{% set genexpr.str = genexpr.str + '>' %}
                 {% endfor %}
-                {% if action=='set' %}
                 set({{ it }} {{ genexpr.str }} CACHE STRING
                     "Variable {{ it }} conan-toolchain defined")
-                {% elif action=='add_compile_definitions' -%}
-                add_compile_definitions({{ it }}={{ genexpr.str }})
-                {% endif %}
             {% endfor %}
         {% endmacro %}
 
@@ -120,7 +117,21 @@ class CMakeToolchain(object):
         {% endif %}
         {% endfor %}
         # Preprocessor definitions per configuration
-        {{ iterate_configs(preprocessor_definitions_config, action='add_compile_definitions') }}
+        {% 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()
diff --git a/conans/test/functional/toolchains/cmake/test_cmake.py b/conans/test/functional/toolchains/cmake/test_cmake.py
index 40aabeb0c47..d98610e4ade 100644
--- a/conans/test/functional/toolchains/cmake/test_cmake.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake.py
@@ -378,10 +378,11 @@ def test_toolchain_linux(self, build_type, cppstd, arch, libcxx, shared):
         extensions_str = "ON" if "gnu" in cppstd else "OFF"
         arch_str = "-m32" if arch == "x86" else "-m64"
         cxx11_abi_str = "_GLIBCXX_USE_CXX11_ABI=0;" if libcxx == "libstdc++" else ""
-        defines = '%sMYDEFINE="MYDEF_VALUE";MYDEFINEINT=42;'\
-                  'MYDEFINE_CONFIG=$<IF:$<CONFIG:debug>,"MYDEF_DEBUG",$<IF:$<CONFIG:release>,'\
-                  '"MYDEF_RELEASE","">>;MYDEFINEINT_CONFIG=$<IF:$<CONFIG:debug>,421,'\
-                  '$<IF:$<CONFIG:release>,422,"">>' % cxx11_abi_str
+        defines = '%sMYDEFINE="MYDEF_VALUE";MYDEFINEINT=42;' \
+                  '$<$<CONFIG:debug>:MYDEFINE_CONFIG="MYDEF_DEBUG">' \
+                  '$<$<CONFIG:release>:MYDEFINE_CONFIG="MYDEF_RELEASE">;' \
+                  '$<$<CONFIG:debug>:MYDEFINEINT_CONFIG=421>' \
+                  '$<$<CONFIG:release>:MYDEFINEINT_CONFIG=422>' % cxx11_abi_str
         vals = {"CMAKE_CXX_STANDARD": "14",
                 "CMAKE_CXX_EXTENSIONS": extensions_str,
                 "CMAKE_BUILD_TYPE": build_type,
diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
index 877575cf91e..1e5c1930f53 100644
--- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
@@ -343,6 +343,7 @@ def generate(self):
                 tc.preprocessor_definitions.release["spaces_release"] = "release me you"
                 tc.preprocessor_definitions.release["foobar_release"] = "release bazbuz"
                 tc.preprocessor_definitions.release["answer_release"] = 42
+                tc.preprocessor_definitions.release["NOVALUE_DEF_RELEASE"] = None
 
                 tc.preprocessor_definitions.debug["escape_debug"] = "debug partially \"escaped\""
                 tc.preprocessor_definitions.debug["spaces_debug"] = "debug me you"
@@ -386,6 +387,9 @@ def build(self):
             #ifdef NOVALUE_DEF
             printf("NO VALUE!!!!");
             #endif
+            #ifdef NOVALUE_DEF_RELEASE
+            printf("NO VALUE RELEASE!!!!");
+            #endif
             return 0;
         }
         """)
@@ -416,6 +420,7 @@ def build(self):
     assert 'foobar_release=release bazbuz' in client.out
     assert 'answer_release=42' in client.out
     assert "NO VALUE!!!!" in client.out
+    assert "NO VALUE RELEASE!!!!" in client.out
 
     client.run("install . -pr=./profile -s build_type=Debug")
     client.run("build . -pr=./profile -s build_type=Debug")