Repository: conan-io/conan
Pull request #16429 (2024-06-07 09:14:24)

Consider _global_defines in XcodeToolchain _check_if_extra_flags
Changelog: Bugfix: Fix XcodeToolchain when only defines are set.
Docs: Omit

Closes: https://github.com/conan-io/conan/issues/16422


Patch:
diff --git a/conan/internal/api/new/cmake_lib.py b/conan/internal/api/new/cmake_lib.py
index 56ea66935..a92a93052 100644
--- a/conan/internal/api/new/cmake_lib.py
+++ b/conan/internal/api/new/cmake_lib.py
@@ -32,7 +32,18 @@ class {{package_name}}Recipe(ConanFile):
 
     def layout(self):
         cmake_layout(self)
-
+    {% if requires is defined %}
+    def requirements(self):
+        {% for require in requires -%}
+        self.requires("{{ require }}")
+        {% endfor %}
+    {%- endif %}
+    {%- if tool_requires is defined %}
+    def build_requirements(self):
+        {% for require in tool_requires -%}
+        self.tool_requires("{{ require }}")
+        {% endfor %}
+    {%- endif %}
     def generate(self):
         deps = CMakeDeps(self)
         deps.generate()
@@ -51,20 +62,6 @@ class {{package_name}}Recipe(ConanFile):
     def package_info(self):
         self.cpp_info.libs = ["{{name}}"]
 
-    {% if requires is defined -%}
-    def requirements(self):
-        {% for require in requires -%}
-        self.requires("{{ require }}")
-        {% endfor %}
-    {%- endif %}
-
-    {% if tool_requires is defined -%}
-    def build_requirements(self):
-        {% for require in tool_requires -%}
-        self.tool_requires("{{ require }}")
-        {% endfor %}
-    {%- endif %}
-
 '''
 
 cmake_v2 = """cmake_minimum_required(VERSION 3.15)
@@ -270,12 +267,6 @@ project(PackageTest CXX)
 
 find_package({{name}} CONFIG REQUIRED)
 
-{% if requires is defined -%}
-{% for require in requires -%}
-find_package({{as_name(require)}} CONFIG REQUIRED)
-{% endfor %}
-{%- endif %}
-
 add_executable(example src/example.cpp)
 target_link_libraries(example {{name}}::{{name}})
 """
diff --git a/conan/tools/apple/xcodetoolchain.py b/conan/tools/apple/xcodetoolchain.py
index 5af04498a..c9e565c43 100644
--- a/conan/tools/apple/xcodetoolchain.py
+++ b/conan/tools/apple/xcodetoolchain.py
@@ -109,7 +109,7 @@ class XcodeToolchain(object):
 
     @property
     def _check_if_extra_flags(self):
-        return self._global_cflags or self._global_cxxflags or self._global_ldflags
+        return self._global_cflags or self._global_cxxflags or self._global_ldflags or self._global_defines
 
     @property
     def _flags_xcconfig_content(self):
diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py
index 34021ece8..6d15ac0b1 100644
--- a/conan/tools/cmake/toolchain/blocks.py
+++ b/conan/tools/cmake/toolchain/blocks.py
@@ -564,8 +564,8 @@ class FindFiles(Block):
         return host_runtime_dirs
 
     def _join_paths(self, paths):
-        paths = [relativize_path(p, self._conanfile, "${CMAKE_CURRENT_LIST_DIR}") for p in paths]
         paths = [p.replace('\\', '/').replace('$', '\\$').replace('"', '\\"') for p in paths]
+        paths = [relativize_path(p, self._conanfile, "${CMAKE_CURRENT_LIST_DIR}") for p in paths]
         return " ".join([f'"{p}"' for p in paths])
 
     def context(self):
diff --git a/conans/client/migrations.py b/conans/client/migrations.py
index 6c56d7035..74267a5b3 100644
--- a/conans/client/migrations.py
+++ b/conans/client/migrations.py
@@ -56,7 +56,9 @@ class ClientMigrator(Migrator):
         if old_version and old_version < "2.0.14-":
             _migrate_pkg_db_lru(self.cache_folder, old_version)
 
-        if old_version and old_version < "2.4":
+        # let the back migration files be stored
+        # if there was not a previous install (old_version==None)
+        if old_version is None or old_version < "2.4":
             _migrate_default_compatibility(self.cache_folder)
 
 
diff --git a/setup.py b/setup.py
index 45d16b892..3c14b1b87 100644
--- a/setup.py
+++ b/setup.py
@@ -14,7 +14,7 @@ from os import path
 
 # The tests utils are used by conan-package-tools
 here = path.abspath(path.dirname(__file__))
-excluded_test_packages = ["test"]
+excluded_test_packages = ["test*"]
 
 
 def get_requires(filename):


Test patch:
diff --git a/test/integration/test_migrations.py b/test/integration/test_migrations.py
index 73fa759e0..61b9761db 100644
--- a/test/integration/test_migrations.py
+++ b/test/integration/test_migrations.py
@@ -1,6 +1,7 @@
 import os
 import sqlite3
 import textwrap
+from unittest.mock import patch
 
 import pytest
 
@@ -8,6 +9,8 @@ from conan import conan_version
 from conan.test.assets.genconanfile import GenConanfile
 from conan.test.utils.test_files import temp_folder
 from conan.test.utils.tools import TestClient
+from conans.client.migrations import ClientMigrator
+from conans.model.version import Version
 from conans.util.files import save, load
 
 
@@ -131,3 +134,24 @@ def test_back_migrations():
         assert not os.path.exists(os.path.join(t.cache_folder, f"file{number}.txt"))
         migration_file = os.path.join(t.cache_folder, "migrations", f"2.100.0_{number}-migrate.py")
         assert not os.path.exists(migration_file)
+
+
+def test_back_default_compatibility_migration():
+    t = TestClient()
+
+    version_txt_file_path = os.path.join(t.cache_folder, "version.txt")
+
+    # emulate a clean install, no previous version
+    os.remove(version_txt_file_path)
+
+    t.run("-v")  # Fire the backward migration
+    migration_file = os.path.join(t.cache_folder, "migrations", "2.4_1-migrate.py")
+    assert os.path.exists(migration_file)
+
+    # downgrade from a clean latest conan_version to 2.3.2
+    # simulate that we are in 2.3.2 and the old one is latest conan_version
+    migrator = ClientMigrator(t.cache_folder, Version("2.3.2"))
+
+    with patch('conan.api.conan_api.ClientMigrator', new=lambda *args, **kwargs: migrator):
+        t.run("-v")  # Fire the backward migration
+        assert f"WARN: Downgrading cache from Conan {conan_version} to 2.3.2" in t.out
diff --git a/test/integration/toolchains/apple/test_xcodetoolchain.py b/test/integration/toolchains/apple/test_xcodetoolchain.py
index a7e4bee8d..ffae38c49 100644
--- a/test/integration/toolchains/apple/test_xcodetoolchain.py
+++ b/test/integration/toolchains/apple/test_xcodetoolchain.py
@@ -72,3 +72,14 @@ def test_toolchain_flags():
     assert "OTHER_LDFLAGS = $(inherited) flag3 flag4" in conan_global_flags
     conan_global_file = client.load("conan_config.xcconfig")
     assert '#include "conan_global_flags.xcconfig"' in conan_global_file
+
+
+def test_flags_generated_if_only_defines():
+    # https://github.com/conan-io/conan/issues/16422
+    client = TestClient()
+    client.save({"conanfile.txt": "[generators]\nXcodeToolchain\n"})
+    client.run("install . -c 'tools.build:defines=[\"MYDEFINITION\"]'")
+    conan_global_flags = client.load("conan_global_flags.xcconfig")
+    assert "GCC_PREPROCESSOR_DEFINITIONS = $(inherited) MYDEFINITION" in conan_global_flags
+    conan_global_file = client.load("conan_config.xcconfig")
+    assert '#include "conan_global_flags.xcconfig"' in conan_global_file
diff --git a/test/integration/toolchains/cmake/test_cmaketoolchain.py b/test/integration/toolchains/cmake/test_cmaketoolchain.py
index c21b35ffc..457f6a2b3 100644
--- a/test/integration/toolchains/cmake/test_cmaketoolchain.py
+++ b/test/integration/toolchains/cmake/test_cmaketoolchain.py
@@ -1501,6 +1501,7 @@ def test_toolchain_keep_absolute_paths():
     presets = json.loads(c.load(user_presets["include"][0]))
     assert os.path.isabs(presets["configurePresets"][0]["toolchainFile"])
 
+
 def test_output_dirs_gnudirs_local_default():
     # https://github.com/conan-io/conan/issues/14733
     c = TestClient()
@@ -1630,3 +1631,18 @@ def test_toolchain_extra_variables():
     toolchain = client.load("conan_toolchain.cmake")
     assert 'set(CACHE_VAR_DEFAULT_DOC "hello world" CACHE PATH "CACHE_VAR_DEFAULT_DOC")' in toolchain
 
+
+def test_variables_wrong_scaping():
+    # https://github.com/conan-io/conan/issues/16432
+    c = TestClient()
+    c.save({"tool/conanfile.py": GenConanfile("tool", "0.1"),
+            "pkg/conanfile.txt": "[tool_requires]\ntool/0.1\n[generators]\nCMakeToolchain"})
+    c.run("create tool")
+    c.run("install pkg")
+    toolchain = c.load("pkg/conan_toolchain.cmake")
+    cache_folder = c.cache_folder.replace("\\", "/")
+    assert f'list(PREPEND CMAKE_PROGRAM_PATH "{cache_folder}' in toolchain
+
+    c.run("install pkg --deployer=full_deploy")
+    toolchain = c.load("pkg/conan_toolchain.cmake")
+    assert 'list(PREPEND CMAKE_PROGRAM_PATH "${CMAKE_CURRENT_LIST_DIR}/full_deploy' in toolchain