@@ -443,13 +443,18 @@ def test_compatibility_msvc_and_cppstd(self):
443443 compiler.runtime=dynamic
444444 """ )
445445 tc .save ({"dep/conanfile.py" : GenConanfile ("dep" , "1.0" ).with_setting ("compiler" ),
446- "conanfile.py" : GenConanfile ("app" , "1.0" ).with_require ("dep/1.0" ).with_setting ("compiler" ),
447446 "profile" : profile })
448447
449448 tc .run ("create dep -pr=profile -s compiler.cppstd=20" )
450- tc .run ("create . -pr=profile -s compiler.cppstd=17" )
449+ tc .run ("install --requires=dep/1.0 -pr=profile -s compiler.cppstd=17" )
451450 tc .assert_listed_binary ({"dep/1.0" : ("b6d26a6bc439b25b434113982791edf9cab4d004" , "Cache" )})
452451
452+ tc .run ("remove * -c" )
453+ tc .run ("create dep -pr=profile -s compiler.version=193 -s compiler.cppstd=20" )
454+ tc .run ("install --requires=dep/1.0 -pr=profile -s compiler.cppstd=17" )
455+ assert "compiler.cppstd=20, compiler.version=193" in tc .out
456+ tc .assert_listed_binary ({"dep/1.0" : ("535899bb58c3ca7d80a380313d31f4729e735d1c" , "Cache" )})
457+
453458
454459class TestCompatibleBuild :
455460 def test_build_compatible (self ):
@@ -706,3 +711,58 @@ def validate_build(self):
706711 pkga = liba ["packages" ][0 ][pkg_index ]
707712 assert pkga ["info" ]["compatibility_delta" ] == {"settings" : [["compiler.cppstd" , "14" ]]}
708713 assert pkga ["build_args" ] == "--requires=liba/0.1 --build=compatible:liba/0.1"
714+
715+
716+ def test_compatibility_new_setting_forwards_compat ():
717+ """ This test tries to reflect the following scenario:
718+ - User adds a new setting (libc.version in this case)
719+ - This setting is forward compatible
720+ How is it solved with compatibility.py? Like this:
721+ """
722+ tc = TestClient ()
723+ tc .save_home ({"settings_user.yml" : "libc_version: [1, 2, 3]" })
724+ tc .save ({"conanfile.py" : GenConanfile ("dep" , "1.0" ).with_settings ("libc_version" , "compiler" )})
725+ # The extra cppstd and compiler versions are for later demonstrations of combinations of settings
726+ # The cppstd=17 and compiler.version=193 are used thought until the last 2 install calls
727+ tc .run ("create . -s=libc_version=2 -s=compiler.cppstd=17" )
728+ dep_package_id = tc .created_package_id ("dep/1.0" )
729+ tc .run ("install --requires=dep/1.0 -s=libc_version=3 -s=compiler.cppstd=17" , assert_error = True )
730+ # We can't compile, because the dep is not compatible
731+ assert "Missing prebuilt package for 'dep/1.0'" in tc .out
732+
733+ # Let's create a compatibility extensions
734+ libc_compat = textwrap .dedent ("""
735+ from conan.tools.scm import Version
736+
737+ def libc_compat(conanfile):
738+ # Do we have the setting?
739+ libc_version = conanfile.settings.get_safe("libc_version")
740+ if libc_version is None:
741+ return []
742+ available_libc_versions = conanfile.settings.libc_version.possible_values()
743+ ret = []
744+ for possible_libc_version in available_libc_versions:
745+ if Version(possible_libc_version) < Version(libc_version):
746+ ret.append({"libc_version": possible_libc_version})
747+ return ret
748+ """ )
749+ compat = tc .load_home ("extensions/plugins/compatibility/compatibility.py" )
750+ compat = "from libc_compat import libc_compat\n " + compat
751+ compat = compat .replace ("# Append more factors for your custom compatibility rules here" ,
752+ "factors.append(libc_compat(conanfile))" )
753+ tc .save_home ({"extensions/plugins/compatibility/libc_compat.py" : libc_compat ,
754+ "extensions/plugins/compatibility/compatibility.py" : compat })
755+
756+ # Now we try again, this time app will find the compatible dep with libc_version 2
757+ tc .run ("install --requires=dep/1.0 -s=libc_version=3 -s=compiler.cppstd=17" )
758+ assert f"dep/1.0: Found compatible package '{ dep_package_id } '" in tc .out
759+
760+ # And now we try to create the app with libc_version 1, which is still not compatible
761+ tc .run ("install --requires=dep/1.0 -s=libc_version=1 -s=compiler.cppstd=17" , assert_error = True )
762+ assert "Missing prebuilt package for 'dep/1.0'" in tc .out
763+
764+ # Now we try again, this time app will find the compatible dep with libc_version 2
765+ # And see how we're also compatible over a different cppstd
766+ tc .run ("install --requires=dep/1.0 -s=libc_version=3 -s=compiler.cppstd=14" )
767+ assert f"dep/1.0: Found compatible package '{ dep_package_id } ': compiler.cppstd=17, " \
768+ f"libc_version=2" in tc .out
0 commit comments