Skip to content

Commit

Permalink
Fix handling of tools.build:defines for (Ninja) multi-config CMake …
Browse files Browse the repository at this point in the history
…CMake (#15921) (#16637)

* Add test for handling of tools.build:defines for Ninja multi-config CMake

* Fix handling of tools.build:defines for (Ninja) multi-config CMake

The CMake generator-expressions that results from the values given to
Conan's `tools.build:defines` configuration will now properly be put
into quotes to form a CMake string. (Note: CMake's generator-expressions
should never contain any (non-escaped) quotes.)

* use CMake 3.23 in test

* fix Windows (might pass by luck, using clang++ instead of cl)

* fix Windows activating conanbuild.bat for vcvars

---------

Co-authored-by: memsharded <james@conan.io>
  • Loading branch information
DenizThatMenace and memsharded authored Jul 10, 2024
1 parent 59bcd38 commit 671b46b
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
2 changes: 1 addition & 1 deletion conan/tools/cmake/toolchain/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ class ExtraFlagsBlock(Block):
{% if defines %}
{% if config %}
{% for define in defines %}
add_compile_definitions($<$<CONFIG:{{config}}>:"{{ define }}">)
add_compile_definitions("$<$<CONFIG:{{config}}>:{{ define }}>")
{% endfor %}
{% else %}
add_compile_definitions({% for define in defines %} "{{ define }}"{% endfor %})
Expand Down
103 changes: 103 additions & 0 deletions test/functional/toolchains/cmake/test_cmake_toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1913,3 +1913,106 @@ def build(self):
assert 'DEFINE conan_test_answer=123' in c.out
assert 'other=' not in c.out
assert "CPLUSPLUS: __cplusplus19" in c.out


@pytest.mark.tool("ninja")
@pytest.mark.tool("cmake", "3.23")
def test_cmake_toolchain_ninja_multi_config():
c = TestClient()
profile_release = textwrap.dedent(r"""
include(default)
[conf]
tools.cmake.cmaketoolchain:generator=Ninja Multi-Config
tools.build:defines=["conan_test_answer=42", "conan_test_other=24"]
""")
profile_debug = textwrap.dedent(r"""
include(default)
[settings]
build_type=Debug
[conf]
tools.cmake.cmaketoolchain:generator=Ninja Multi-Config
tools.build:defines=["conan_test_answer=123"]
""")
profile_relwithdebinfo = textwrap.dedent(r"""
include(default)
[settings]
build_type=RelWithDebInfo
[conf]
tools.cmake.cmaketoolchain:generator=Ninja Multi-Config
tools.build:defines=["conan_test_answer=456", "conan_test_other=abc", 'conan_test_complex="1 2"']
""")

conanfile = textwrap.dedent(r'''
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
class Test(ConanFile):
exports_sources = "CMakeLists.txt", "src/*"
settings = "os", "compiler", "arch", "build_type"
generators = "CMakeToolchain"
def layout(self):
cmake_layout(self)
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
''')

main = textwrap.dedent(r"""
#include <iostream>
#include <stdio.h>
#define STR(x) #x
#define SHOW_DEFINE(x) printf("DEFINE %s=%s!\n", #x, STR(x))
int main() {
SHOW_DEFINE(conan_test_answer);
#ifdef conan_test_other
SHOW_DEFINE(conan_test_other);
#endif
#ifdef conan_test_complex
SHOW_DEFINE(conan_test_complex);
#endif
}
""")

cmakelists = textwrap.dedent("""
cmake_minimum_required(VERSION 3.15)
project(Test CXX)
add_executable(example src/main.cpp)
""")

c.save({"conanfile.py": conanfile,
"profile_release": profile_release,
"profile_debug": profile_debug,
"profile_relwithdebinfo": profile_relwithdebinfo,
"src/main.cpp": main,
"CMakeLists.txt": cmakelists})
c.run("install . -pr=./profile_release")
c.run("install . -pr=./profile_debug")
c.run("install . -pr=./profile_relwithdebinfo")

with c.chdir("build"):
env = r".\generators\conanbuild.bat &&" if platform.system() == "Windows" else ""
c.run_command(f"{env} cmake .. -G \"Ninja Multi-Config\" "
"-DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake")
c.run_command(f"{env} cmake --build . --config Release")
c.run_command(f"{env} cmake --build . --config Debug")
c.run_command(f"{env} cmake --build . --config RelWithDebInfo")

c.run_command(os.sep.join([".", "build", "Release", "example"]))
assert 'DEFINE conan_test_answer=42!' in c.out
assert 'DEFINE conan_test_other=24!' in c.out
assert 'complex=' not in c.out

c.run_command(os.sep.join([".", "build", "Debug", "example"]))
assert 'DEFINE conan_test_answer=123' in c.out
assert 'other=' not in c.out
assert 'complex=' not in c.out

c.run_command(os.sep.join([".", "build", "RelWithDebInfo", "example"]))
assert 'DEFINE conan_test_answer=456!' in c.out
assert 'DEFINE conan_test_other=abc!' in c.out
assert 'DEFINE conan_test_complex="1 2"!' in c.out

0 comments on commit 671b46b

Please sign in to comment.