Repository: conan-io/conan
Pull request #16720 (2024-07-24 10:40:12)

fixed bug in package settings with include()
Changelog: Bugfix: Fix profile ``include()`` with per-package ``[settings]`` with partial definition
Docs: Omit

Close https://github.com/conan-io/conan/issues/16718



Patch:
diff --git a/conan/internal/api/profile/profile_loader.py b/conan/internal/api/profile/profile_loader.py
index 6f6a83b81..8b36ef61f 100644
--- a/conan/internal/api/profile/profile_loader.py
+++ b/conan/internal/api/profile/profile_loader.py
@@ -319,7 +319,10 @@ class _ProfileValueParser(object):
 
         base_profile.settings.update(settings)
         for pkg_name, values_dict in package_settings.items():
-            base_profile.package_settings[pkg_name].update(values_dict)
+            existing = base_profile.package_settings[pkg_name]
+            existing.update(values_dict)
+            # Make sure they are ordered, so `compiler=xxx` goes before `compiler.cppstd` always
+            base_profile.package_settings[pkg_name] = OrderedDict(sorted(existing.items()))
         for pattern, refs in tool_requires.items():
             # If the same package, different version is added, the latest version prevail
             current = base_profile.tool_requires.setdefault(pattern, [])


Test patch:
diff --git a/test/integration/configuration/test_profile_priority.py b/test/integration/configuration/test_profile_priority.py
index 3a18ae74f..5fb859766 100644
--- a/test/integration/configuration/test_profile_priority.py
+++ b/test/integration/configuration/test_profile_priority.py
@@ -76,3 +76,43 @@ def test_profile_cli_priority():
     assert "user.myconf:myvalue3={'3': '5', 'a': 'b'}" in c.out
     assert "user.myconf:myvalue4={'1': '2'}" in c.out
     assert "user.myconf:myvalue5={'6': '7'}" in c.out
+
+
+def test_profiles_patterns_include():
+    # https://github.com/conan-io/conan/issues/16718
+    c = TestClient()
+    msvc = textwrap.dedent("""
+        [settings]
+        compiler=msvc
+        compiler.cppstd=14
+        compiler.version=193
+        os=Windows
+
+        test*/*:compiler.cppstd=14
+        """)
+    clang = textwrap.dedent("""
+        include(./msvc)
+        [settings]
+        test*/*:compiler=clang
+        test*/*:compiler.cppstd=17
+        test*/*:compiler.runtime_version=v144
+        test*/*:compiler.version=18
+        """)
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        class Pkg(ConanFile):
+            name = "test_pkg"
+            version = "0.1"
+            settings = "os", "compiler"
+            def generate(self):
+                self.output.info(f"MyCompiler={self.settings.compiler}!!!")
+                self.output.info(f"MyCompilerVersion={self.settings.compiler.version}!!!")
+                self.output.info(f"MyCompilerCpp={self.settings.compiler.cppstd}!!!")
+            """)
+    c.save({"conanfile.py": conanfile,
+            "msvc": msvc,
+            "clang": clang})
+    c.run("install . -pr=clang")
+    assert "conanfile.py (test_pkg/0.1): MyCompiler=clang!!!" in c.out
+    assert "conanfile.py (test_pkg/0.1): MyCompilerVersion=18!!!" in c.out
+    assert "conanfile.py (test_pkg/0.1): MyCompilerCpp=17!!!" in c.out