Repository: conan-io/conan

Issue:
[bug] `tools.build:defines` is broken in multiconfig setting
### Describe the bug

`tools.build:defines` is broken in multiconfig setting, e.g. with MSVC. The quoting in the generator expression is not correct in `blocks.py`.

### How to reproduce it

- Set `tools.build:defines=['A=1', 'B=2']`
- Observe how the generated toolchain file or afterwards generated vxproj by CMake does not contain the right definitions.

EDIT: See PR #15924 for more info


Discussion:
I'm working on a PR

Resolving patch:
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -154,7 +154,7 @@ def context(self):
 
         if not config_dict:
             return None
-        
+
         vs_debugger_path = ""
         for config, value in config_dict.items():
             vs_debugger_path += f"$<$<CONFIG:{config}>:{value}>"
@@ -613,7 +613,9 @@ class ExtraFlagsBlock(Block):
         {% endif %}
         {% if defines %}
         {% if config %}
-        add_compile_definitions($<$<CONFIG:{{config}}>:{% for define in defines %}" {{ define }}"{% endfor %}>)
+        {% for define in defines %}
+        add_compile_definitions($<$<CONFIG:{{config}}>:"{{ define }}">)
+        {% endfor %}
         {% else %}
         add_compile_definitions({% for define in defines %} "{{ define }}"{% endfor %})
         {% endif %}


Test patch:
diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
--- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
+++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
@@ -1833,7 +1833,7 @@ def test_cmake_toolchain_cxxflags_multi_config():
     profile_release = textwrap.dedent(r"""
         include(default)
         [conf]
-        tools.build:defines=["answer=42"]
+        tools.build:defines=["conan_test_answer=42", "conan_test_other=24"]
         tools.build:cxxflags=["/Zc:__cplusplus"]
         """)
     profile_debug = textwrap.dedent(r"""
@@ -1841,7 +1841,7 @@ def test_cmake_toolchain_cxxflags_multi_config():
         [settings]
         build_type=Debug
         [conf]
-        tools.build:defines=["answer=123"]
+        tools.build:defines=["conan_test_answer=123"]
         tools.build:cxxflags=["/W4"]
         """)
 
@@ -1868,10 +1868,13 @@ def build(self):
         #include <stdio.h>
 
         #define STR(x)   #x
-        #define SHOW_DEFINE(x) printf("%s=%s\n", #x, STR(x))
+        #define SHOW_DEFINE(x) printf("DEFINE %s=%s!\n", #x, STR(x))
 
         int main() {
-            SHOW_DEFINE(answer);
+            SHOW_DEFINE(conan_test_answer);
+            #ifdef conan_test_other
+            SHOW_DEFINE(conan_test_other);
+            #endif
             char a = 123L;  // to trigger warnings
 
             #if __cplusplus
@@ -1902,9 +1905,11 @@ def build(self):
         assert "warning C4189" in c.out
 
     c.run_command(r"build\Release\example.exe")
-    assert 'answer=42' in c.out
+    assert 'DEFINE conan_test_answer=42!' in c.out
+    assert 'DEFINE conan_test_other=24!' in c.out
     assert "CPLUSPLUS: __cplusplus20" in c.out
 
     c.run_command(r"build\Debug\example.exe")
-    assert 'answer=123' in c.out
+    assert 'DEFINE conan_test_answer=123' in c.out
+    assert 'other=' not in c.out
     assert "CPLUSPLUS: __cplusplus19" in c.out