From 55df6743ed937a552a4fe3cf52e196576390307e Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Sun, 24 Mar 2024 08:27:37 +1100 Subject: [PATCH 1/9] remove unnecessary casts to bool in test_stdlib_on_azure --- tests/test_configure_feedstock.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/test_configure_feedstock.py b/tests/test_configure_feedstock.py index 2267b236c..2ef9b3d55 100644 --- a/tests/test_configure_feedstock.py +++ b/tests/test_configure_feedstock.py @@ -226,23 +226,19 @@ def test_stdlib_on_azure(stdlib_recipe, jinja_env): linux_lines = f.readlines() linux_content = "".join(linux_lines) # multiline pattern to ensure we don't match other stuff accidentally - assert bool(re.match(r"(?s).*c_stdlib:\s*- sysroot", linux_content)) - assert bool( - re.match(r"(?s).*c_stdlib_version:\s*- ['\"]?2\.\d+", linux_content) - ) + assert re.match(r"(?s).*c_stdlib:\s*- sysroot", linux_content) + assert re.match(r"(?s).*c_stdlib_version:\s*- ['\"]?2\.\d+", linux_content) with open(os.path.join(matrix_dir, "osx_64_.yaml")) as f: osx_lines = f.readlines() osx_content = "".join(osx_lines) - assert bool( - re.match(r"(?s).*c_stdlib:\s*- macosx_deployment_target", osx_content) - ) - assert bool( - re.match(r"(?s).*c_stdlib_version:\s*- ['\"]?1\d\.\d+", osx_content) + assert re.match( + r"(?s).*c_stdlib:\s*- macosx_deployment_target", osx_content ) + assert re.match(r"(?s).*c_stdlib_version:\s*- ['\"]?1\d\.\d+", osx_content) with open(os.path.join(matrix_dir, "win_64_.yaml")) as f: win_lines = f.readlines() win_content = "".join(win_lines) - assert bool(re.match(r"(?s).*c_stdlib:\s*- vs", win_content)) + assert re.match(r"(?s).*c_stdlib:\s*- vs", win_content) # no stdlib-version expected on windows From f1e80cd63b5a29ffdd410c5d9cdcef5968f68284 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Sun, 24 Mar 2024 08:29:49 +1100 Subject: [PATCH 2/9] merge c_stdlib_version & MACOSX_DEPLOYMENT_TARGET on osx --- conda_smithy/configure_feedstock.py | 34 +++++++++++++++++++ ...on-and-MACOSX_DEPLOYMENT_TARGET-on-osx.rst | 23 +++++++++++++ tests/conftest.py | 24 +++++++++++++ tests/test_configure_feedstock.py | 32 ++++++++++++++++- 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 news/1889-merge-c_stdlib_version-and-MACOSX_DEPLOYMENT_TARGET-on-osx.rst diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py index 3be1abe88..5d109d488 100644 --- a/conda_smithy/configure_feedstock.py +++ b/conda_smithy/configure_feedstock.py @@ -520,6 +520,40 @@ def _collapse_subpackage_variants( "BUILD", } + # on osx, merge MACOSX_DEPLOYMENT_TARGET & c_stdlib_version to max of either; see #1884 + if squished_used_variants["target_platform"][0].startswith("osx"): + # in global pinning, but use fallback to avoid having to set it in all tests + v_stdlib = squished_used_variants.get("c_stdlib_version", ["0.0"]) + # also in global pinning, but prepare for eventual disappearance + macdt = squished_used_variants.get("MACOSX_DEPLOYMENT_TARGET", [None]) + # the merge logic only deals with one version + if (len(v_stdlib) > 1 and macdt[0] is not None) or len(macdt) > 1: + raise ValueError( + "Not prepared to deal with multiple c_stdlib_version that do not match " + "MACOSX_DEPLOYMENT_TARGET! Please delete MACOSX_DEPLOYMENT_TARGET and " + "set only c_stdlib_version in conda_build_config.yaml!" + ) + # now that we ruled out multiple values, extract the single value + v_stdlib = v_stdlib[0] + macdt = macdt[0] + if macdt is not None and v_stdlib != macdt: + logger.warn( + "Duplicate specification of macosx deployment target!\n" + "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " + "please change the name of that key to `c_stdlib_version`!" + ) + # determine maximum version and use it to populate both + cond = VersionOrder(v_stdlib) > VersionOrder(macdt) + new_val = v_stdlib if cond else macdt + squished_used_variants["c_stdlib_version"] = [new_val] + + # in any case, we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version + # (if it is set), for ease of use in conda-forge-ci-setup + if "c_stdlib_version" in squished_used_variants: + squished_used_variants["MACOSX_DEPLOYMENT_TARGET"] = ( + squished_used_variants["c_stdlib_version"] + ) + if not is_noarch: always_keep_keys.add("target_platform") diff --git a/news/1889-merge-c_stdlib_version-and-MACOSX_DEPLOYMENT_TARGET-on-osx.rst b/news/1889-merge-c_stdlib_version-and-MACOSX_DEPLOYMENT_TARGET-on-osx.rst new file mode 100644 index 000000000..b0b71f828 --- /dev/null +++ b/news/1889-merge-c_stdlib_version-and-MACOSX_DEPLOYMENT_TARGET-on-osx.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* Ensure we populate MACOSX_DEPLOYMENT_TARGET for use in conda-forge-ci-setup also when using `c_stdlib_version` (#1884 via #1889) + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/tests/conftest.py b/tests/conftest.py index 8125265e9..d1f1f326c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -241,6 +241,30 @@ def stdlib_recipe(config_yaml, request): ) +@pytest.fixture(scope="function") +def stdlib_deployment_target_recipe(config_yaml, stdlib_recipe): + # append to existing stdlib_config.yaml from stdlib_recipe + with open( + os.path.join(config_yaml, "recipe", "stdlib_config.yaml"), "a" + ) as f: + f.write( + """\ +MACOSX_DEPLOYMENT_TARGET: # [osx] + - 10.14 # [osx and x86_64] + - 12.0 # [osx and arm64] +""" + ) + return RecipeConfigPair( + str(config_yaml), + _load_forge_config( + config_yaml, + exclusive_config_file=os.path.join( + config_yaml, "recipe", "stdlib_config.yaml" + ), + ), + ) + + @pytest.fixture(scope="function") def upload_on_branch_recipe(config_yaml, request): with open(os.path.join(config_yaml, "recipe", "meta.yaml"), "w") as fh: diff --git a/tests/test_configure_feedstock.py b/tests/test_configure_feedstock.py index 2ef9b3d55..5e078f010 100644 --- a/tests/test_configure_feedstock.py +++ b/tests/test_configure_feedstock.py @@ -234,7 +234,11 @@ def test_stdlib_on_azure(stdlib_recipe, jinja_env): assert re.match( r"(?s).*c_stdlib:\s*- macosx_deployment_target", osx_content ) - assert re.match(r"(?s).*c_stdlib_version:\s*- ['\"]?1\d\.\d+", osx_content) + assert re.match(r"(?s).*c_stdlib_version:\s*- ['\"]?10\.9", osx_content) + # ensure MACOSX_DEPLOYMENT_TARGET _also_ gets set to the same value + assert re.match( + r"(?s).*MACOSX_DEPLOYMENT_TARGET:\s*- ['\"]?10\.9", osx_content + ) with open(os.path.join(matrix_dir, "win_64_.yaml")) as f: win_lines = f.readlines() win_content = "".join(win_lines) @@ -242,6 +246,32 @@ def test_stdlib_on_azure(stdlib_recipe, jinja_env): # no stdlib-version expected on windows +def test_stdlib_deployment_target( + stdlib_deployment_target_recipe, jinja_env, caplog +): + with caplog.at_level(logging.WARNING): + configure_feedstock.render_azure( + jinja_env=jinja_env, + forge_config=stdlib_deployment_target_recipe.config, + forge_dir=stdlib_deployment_target_recipe.recipe, + ) + # this configuration should be run + assert stdlib_deployment_target_recipe.config["azure"]["enabled"] + matrix_dir = os.path.join( + stdlib_deployment_target_recipe.recipe, ".ci_support" + ) + assert os.path.isdir(matrix_dir) + with open(os.path.join(matrix_dir, "osx_64_.yaml")) as f: + lines = f.readlines() + content = "".join(lines) + # ensure both MACOSX_DEPLOYMENT_TARGET and c_stdlib_version match + # the maximum of either, c.f. stdlib_deployment_target_recipe fixture + assert re.match(r"(?s).*c_stdlib_version:\s*- ['\"]?10\.14", content) + assert re.match( + r"(?s).*MACOSX_DEPLOYMENT_TARGET:\s*- ['\"]?10\.14", content + ) + + def test_upload_on_branch_azure(upload_on_branch_recipe, jinja_env): configure_feedstock.render_azure( jinja_env=jinja_env, From 56f87d4ecc477f31f7a89a0f704342e29a92b1f4 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Sun, 24 Mar 2024 09:40:35 +1100 Subject: [PATCH 3/9] simplify merge logic by working on the right level of abstraction --- conda_smithy/configure_feedstock.py | 60 +++++++++++++---------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py index 5d109d488..67bde0dfb 100644 --- a/conda_smithy/configure_feedstock.py +++ b/conda_smithy/configure_feedstock.py @@ -459,6 +459,32 @@ def _collapse_subpackage_variants( if not meta.noarch: is_noarch = False + for var_dict in all_variants: + # on osx, merge MACOSX_DEPLOYMENT_TARGET & c_stdlib_version to max of either; see #1884 + if var_dict.get("target_platform", "dummy").startswith("osx"): + # in global pinning, but use fallback to avoid having to set it in all tests + v_stdlib = var_dict.get("c_stdlib_version", "0.0") + # also in global pinning, but prepare for eventual disappearance + macdt = var_dict.get("MACOSX_DEPLOYMENT_TARGET", None) + if macdt is not None and v_stdlib != macdt: + # determine maximum version and use it to populate both + cond = VersionOrder(v_stdlib) > VersionOrder(macdt) + new_val = v_stdlib if cond else macdt + var_dict["c_stdlib_version"] = new_val + logger.warn( + "Conflicting specification for minimum macOS deployment target!\n" + "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " + "please change the name of that key to `c_stdlib_version`!\n" + f"Using {new_val}=max(c_stdlib_version, MACOSX_DEPLOYMENT_TARGET)." + ) + + # in any case, we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version + # (if it is set), for ease of use in conda-forge-ci-setup + if "c_stdlib_version" in var_dict: + var_dict["MACOSX_DEPLOYMENT_TARGET"] = var_dict[ + "c_stdlib_version" + ] + top_level_loop_vars = list_of_metas[0].get_used_loop_vars( force_top_level=True ) @@ -520,40 +546,6 @@ def _collapse_subpackage_variants( "BUILD", } - # on osx, merge MACOSX_DEPLOYMENT_TARGET & c_stdlib_version to max of either; see #1884 - if squished_used_variants["target_platform"][0].startswith("osx"): - # in global pinning, but use fallback to avoid having to set it in all tests - v_stdlib = squished_used_variants.get("c_stdlib_version", ["0.0"]) - # also in global pinning, but prepare for eventual disappearance - macdt = squished_used_variants.get("MACOSX_DEPLOYMENT_TARGET", [None]) - # the merge logic only deals with one version - if (len(v_stdlib) > 1 and macdt[0] is not None) or len(macdt) > 1: - raise ValueError( - "Not prepared to deal with multiple c_stdlib_version that do not match " - "MACOSX_DEPLOYMENT_TARGET! Please delete MACOSX_DEPLOYMENT_TARGET and " - "set only c_stdlib_version in conda_build_config.yaml!" - ) - # now that we ruled out multiple values, extract the single value - v_stdlib = v_stdlib[0] - macdt = macdt[0] - if macdt is not None and v_stdlib != macdt: - logger.warn( - "Duplicate specification of macosx deployment target!\n" - "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " - "please change the name of that key to `c_stdlib_version`!" - ) - # determine maximum version and use it to populate both - cond = VersionOrder(v_stdlib) > VersionOrder(macdt) - new_val = v_stdlib if cond else macdt - squished_used_variants["c_stdlib_version"] = [new_val] - - # in any case, we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version - # (if it is set), for ease of use in conda-forge-ci-setup - if "c_stdlib_version" in squished_used_variants: - squished_used_variants["MACOSX_DEPLOYMENT_TARGET"] = ( - squished_used_variants["c_stdlib_version"] - ) - if not is_noarch: always_keep_keys.add("target_platform") From a8ae77599ddf013edede23eeeb9ff25d0a2d0b49 Mon Sep 17 00:00:00 2001 From: h-vetinari Date: Sun, 24 Mar 2024 23:11:20 +0100 Subject: [PATCH 4/9] Simplify merge implementation Co-authored-by: Marcel Bargull --- conda_smithy/configure_feedstock.py | 44 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py index 67bde0dfb..05ade0f82 100644 --- a/conda_smithy/configure_feedstock.py +++ b/conda_smithy/configure_feedstock.py @@ -459,31 +459,29 @@ def _collapse_subpackage_variants( if not meta.noarch: is_noarch = False - for var_dict in all_variants: + for var_dict in all_variants: # on osx, merge MACOSX_DEPLOYMENT_TARGET & c_stdlib_version to max of either; see #1884 - if var_dict.get("target_platform", "dummy").startswith("osx"): - # in global pinning, but use fallback to avoid having to set it in all tests - v_stdlib = var_dict.get("c_stdlib_version", "0.0") - # also in global pinning, but prepare for eventual disappearance - macdt = var_dict.get("MACOSX_DEPLOYMENT_TARGET", None) - if macdt is not None and v_stdlib != macdt: - # determine maximum version and use it to populate both - cond = VersionOrder(v_stdlib) > VersionOrder(macdt) - new_val = v_stdlib if cond else macdt - var_dict["c_stdlib_version"] = new_val - logger.warn( - "Conflicting specification for minimum macOS deployment target!\n" - "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " - "please change the name of that key to `c_stdlib_version`!\n" - f"Using {new_val}=max(c_stdlib_version, MACOSX_DEPLOYMENT_TARGET)." - ) + if not var_dict.get("target_platform", "dummy").startswith("osx"): + continue + if "c_stdlib_version" not in var_dict: + continue + v_stdlib = var_dict["c_stdlib_version"] + macdt = var_dict.get("MACOSX_DEPLOYMENT_TARGET", v_stdlib) + if v_stdlib != macdt: + # determine maximum version and use it to populate both + if VersionOrder(v_stdlib) < VersionOrder(macdt): + v_stdlib = macdt + logger.warning( + "Conflicting specification for minimum macOS deployment target!\n" + "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " + "please change the name of that key to `c_stdlib_version`!\n" + f"Using {v_stdlib}=max(c_stdlib_version, MACOSX_DEPLOYMENT_TARGET)." + ) - # in any case, we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version - # (if it is set), for ease of use in conda-forge-ci-setup - if "c_stdlib_version" in var_dict: - var_dict["MACOSX_DEPLOYMENT_TARGET"] = var_dict[ - "c_stdlib_version" - ] + # we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version, + # for ease of use in conda-forge-ci-setup + var_dict["c_stdlib_version"] = v_stdlib + var_dict["MACOSX_DEPLOYMENT_TARGET"] = v_stdlib top_level_loop_vars = list_of_metas[0].get_used_loop_vars( force_top_level=True From 7c0f92bf6fb1a2b221912226d9203bc05e6fb177 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2024 09:23:55 +1100 Subject: [PATCH 5/9] raise if c_stdlib_version/MACOSX_DEPLOYMENT_TARGET is a version range --- conda_smithy/configure_feedstock.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py index 05ade0f82..0c38a35cc 100644 --- a/conda_smithy/configure_feedstock.py +++ b/conda_smithy/configure_feedstock.py @@ -34,6 +34,7 @@ from conda.models.match_spec import MatchSpec from conda.models.version import VersionOrder +from conda.exceptions import InvalidVersionSpec import conda_build.api import conda_build.render @@ -459,7 +460,7 @@ def _collapse_subpackage_variants( if not meta.noarch: is_noarch = False - for var_dict in all_variants: + for var_dict in all_variants: # on osx, merge MACOSX_DEPLOYMENT_TARGET & c_stdlib_version to max of either; see #1884 if not var_dict.get("target_platform", "dummy").startswith("osx"): continue @@ -467,10 +468,17 @@ def _collapse_subpackage_variants( continue v_stdlib = var_dict["c_stdlib_version"] macdt = var_dict.get("MACOSX_DEPLOYMENT_TARGET", v_stdlib) + # error out if someone puts in a range of versions; we need a single version + try: + cond_update = VersionOrder(v_stdlib) < VersionOrder(macdt) + except InvalidVersionSpec: + raise ValueError( + "both and c_stdlib_version/MACOSX_DEPLOYMENT_TARGET need to be a " + "single version, not a version range!" + ) if v_stdlib != macdt: # determine maximum version and use it to populate both - if VersionOrder(v_stdlib) < VersionOrder(macdt): - v_stdlib = macdt + v_stdlib = macdt if cond_update else v_stdlib logger.warning( "Conflicting specification for minimum macOS deployment target!\n" "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " @@ -478,7 +486,7 @@ def _collapse_subpackage_variants( f"Using {v_stdlib}=max(c_stdlib_version, MACOSX_DEPLOYMENT_TARGET)." ) - # we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version, + # we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version, # for ease of use in conda-forge-ci-setup var_dict["c_stdlib_version"] = v_stdlib var_dict["MACOSX_DEPLOYMENT_TARGET"] = v_stdlib From e2c85dc777ed1cfbcae0c65144a410fd1afea9ae Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2024 11:45:30 +1100 Subject: [PATCH 6/9] warn only once for mismatch between c_stdlib_version & MACOSX_DEPLOYMENT_TARGET --- conda_smithy/configure_feedstock.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py index 0c38a35cc..5f310461b 100644 --- a/conda_smithy/configure_feedstock.py +++ b/conda_smithy/configure_feedstock.py @@ -13,6 +13,7 @@ import warnings from collections import Counter, OrderedDict, namedtuple from copy import deepcopy +from functools import lru_cache from itertools import chain, product from os import fspath from pathlib import Path, PurePath @@ -86,6 +87,13 @@ ) +# use lru_cache to avoid repeating warnings endlessly; +# this keeps track of 10 different messages and then warns again +@lru_cache(10) +def warn_once(msg: str): + logger.warning(msg) + + def package_key(config, used_loop_vars, subdir): # get the build string from whatever conda-build makes of the configuration key = "".join( @@ -479,7 +487,7 @@ def _collapse_subpackage_variants( if v_stdlib != macdt: # determine maximum version and use it to populate both v_stdlib = macdt if cond_update else v_stdlib - logger.warning( + warn_once( "Conflicting specification for minimum macOS deployment target!\n" "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " "please change the name of that key to `c_stdlib_version`!\n" From 53ed894e6532ccd63afecc0be41e5114cabaad75 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2024 12:11:51 +1100 Subject: [PATCH 7/9] do not warn if local CBC does not contain MACOSX_DEPLOYMENT_TARGET --- conda_smithy/configure_feedstock.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py index 5f310461b..cf7d07621 100644 --- a/conda_smithy/configure_feedstock.py +++ b/conda_smithy/configure_feedstock.py @@ -468,6 +468,16 @@ def _collapse_subpackage_variants( if not meta.noarch: is_noarch = False + # determine if MACOSX_DEPLOYMENT_TARGET appears in recipe-local CBC; + # all metas in list_of_metas come from same recipe, so path is identical + cbc_path = os.path.join(list_of_metas[0].path, "conda_build_config.yaml") + has_macdt = False + if os.path.exists(cbc_path): + with open(cbc_path, "r") as f: + lines = f.readlines() + if any(re.match(r"^\s*MACOSX_DEPLOYMENT_TARGET:", x) for x in lines): + has_macdt = True + for var_dict in all_variants: # on osx, merge MACOSX_DEPLOYMENT_TARGET & c_stdlib_version to max of either; see #1884 if not var_dict.get("target_platform", "dummy").startswith("osx"): @@ -487,12 +497,16 @@ def _collapse_subpackage_variants( if v_stdlib != macdt: # determine maximum version and use it to populate both v_stdlib = macdt if cond_update else v_stdlib - warn_once( + msg = ( "Conflicting specification for minimum macOS deployment target!\n" "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " "please change the name of that key to `c_stdlib_version`!\n" f"Using {v_stdlib}=max(c_stdlib_version, MACOSX_DEPLOYMENT_TARGET)." ) + # we don't want to warn for recipes that do not use MACOSX_DEPLOYMENT_TARGET + # in the local CBC, but only inherit it from the global pinning + if has_macdt: + warn_once(msg) # we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version, # for ease of use in conda-forge-ci-setup From 6c303742ec57fd0bf3c8313953bae29cc7a73352 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2024 19:45:15 +1100 Subject: [PATCH 8/9] break out osx merge logic into function; also apply it for squished_input_variants --- conda_smithy/configure_feedstock.py | 95 ++++++++++++++++++----------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py index cf7d07621..188dd21ac 100644 --- a/conda_smithy/configure_feedstock.py +++ b/conda_smithy/configure_feedstock.py @@ -430,6 +430,58 @@ def _get_used_key_values_by_input_order( return used_key_values +def _merge_deployment_target(container_of_dicts, has_macdt): + """ + For a collection of variant dictionaries, merge deployment target specs. + + - The "old" way is MACOSX_DEPLOYMENT_TARGET, the new way is c_stdlib_version; + For now, take the maximum to populate both. + - In any case, populate MACOSX_DEPLOYMENT_TARGET, as that is the key picked + up by https://github.com/conda-forge/conda-forge-ci-setup-feedstock + """ + result = [] + for var_dict in container_of_dicts: + # cases where no updates are necessary + if not var_dict.get("target_platform", "dummy").startswith("osx"): + result.append(var_dict) + continue + if "c_stdlib_version" not in var_dict: + result.append(var_dict) + continue + # case where we need to do processing + v_stdlib = var_dict["c_stdlib_version"] + macdt = var_dict.get("MACOSX_DEPLOYMENT_TARGET", v_stdlib) + # error out if someone puts in a range of versions; we need a single version + try: + cond_update = VersionOrder(v_stdlib) < VersionOrder(macdt) + except InvalidVersionSpec: + raise ValueError( + "both and c_stdlib_version/MACOSX_DEPLOYMENT_TARGET need to be a " + "single version, not a version range!" + ) + if v_stdlib != macdt: + # determine maximum version and use it to populate both + v_stdlib = macdt if cond_update else v_stdlib + msg = ( + "Conflicting specification for minimum macOS deployment target!\n" + "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " + "please change the name of that key to `c_stdlib_version`!\n" + f"Using {v_stdlib}=max(c_stdlib_version, MACOSX_DEPLOYMENT_TARGET)." + ) + # we don't want to warn for recipes that do not use MACOSX_DEPLOYMENT_TARGET + # in the local CBC, but only inherit it from the global pinning + if has_macdt: + warn_once(msg) + + # we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version, + # for ease of use in conda-forge-ci-setup + var_dict["c_stdlib_version"] = v_stdlib + var_dict["MACOSX_DEPLOYMENT_TARGET"] = v_stdlib + result.append(var_dict) + # ensure we keep type of wrapper container (set stays set, etc.) + return type(container_of_dicts)(result) + + def _collapse_subpackage_variants( list_of_metas, root_path, platform, arch, forge_config ): @@ -478,40 +530,8 @@ def _collapse_subpackage_variants( if any(re.match(r"^\s*MACOSX_DEPLOYMENT_TARGET:", x) for x in lines): has_macdt = True - for var_dict in all_variants: - # on osx, merge MACOSX_DEPLOYMENT_TARGET & c_stdlib_version to max of either; see #1884 - if not var_dict.get("target_platform", "dummy").startswith("osx"): - continue - if "c_stdlib_version" not in var_dict: - continue - v_stdlib = var_dict["c_stdlib_version"] - macdt = var_dict.get("MACOSX_DEPLOYMENT_TARGET", v_stdlib) - # error out if someone puts in a range of versions; we need a single version - try: - cond_update = VersionOrder(v_stdlib) < VersionOrder(macdt) - except InvalidVersionSpec: - raise ValueError( - "both and c_stdlib_version/MACOSX_DEPLOYMENT_TARGET need to be a " - "single version, not a version range!" - ) - if v_stdlib != macdt: - # determine maximum version and use it to populate both - v_stdlib = macdt if cond_update else v_stdlib - msg = ( - "Conflicting specification for minimum macOS deployment target!\n" - "If your conda_build_config.yaml sets `MACOSX_DEPLOYMENT_TARGET`, " - "please change the name of that key to `c_stdlib_version`!\n" - f"Using {v_stdlib}=max(c_stdlib_version, MACOSX_DEPLOYMENT_TARGET)." - ) - # we don't want to warn for recipes that do not use MACOSX_DEPLOYMENT_TARGET - # in the local CBC, but only inherit it from the global pinning - if has_macdt: - warn_once(msg) - - # we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version, - # for ease of use in conda-forge-ci-setup - var_dict["c_stdlib_version"] = v_stdlib - var_dict["MACOSX_DEPLOYMENT_TARGET"] = v_stdlib + # on osx, merge MACOSX_DEPLOYMENT_TARGET & c_stdlib_version to max of either; see #1884 + all_variants = _merge_deployment_target(all_variants, has_macdt) top_level_loop_vars = list_of_metas[0].get_used_loop_vars( force_top_level=True @@ -527,9 +547,10 @@ def _collapse_subpackage_variants( # this is the initial collection of all variants before we discard any. "Squishing" # them is necessary because the input form is already broken out into one matrix # configuration per item, and we want a single dict, with each key representing many values - squished_input_variants = ( - conda_build.variants.list_of_dicts_to_dict_of_lists( - list_of_metas[0].config.input_variants + squished_input_variants = conda_build.variants.list_of_dicts_to_dict_of_lists( + # ensure we update the input_variants in the same way as all_variants + _merge_deployment_target( + list_of_metas[0].config.input_variants, has_macdt ) ) squished_used_variants = ( From ae5c43e918419de33862c3fc1d381e8f60ac0227 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Mon, 25 Mar 2024 20:44:45 +1100 Subject: [PATCH 9/9] ensure we don't mutate inputs in _merge_deployment_target --- conda_smithy/configure_feedstock.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py index 188dd21ac..a990425ab 100644 --- a/conda_smithy/configure_feedstock.py +++ b/conda_smithy/configure_feedstock.py @@ -474,10 +474,16 @@ def _merge_deployment_target(container_of_dicts, has_macdt): warn_once(msg) # we set MACOSX_DEPLOYMENT_TARGET to match c_stdlib_version, - # for ease of use in conda-forge-ci-setup - var_dict["c_stdlib_version"] = v_stdlib - var_dict["MACOSX_DEPLOYMENT_TARGET"] = v_stdlib - result.append(var_dict) + # for ease of use in conda-forge-ci-setup; + # use new dictionary to avoid mutating existing var_dict in place + new_dict = conda_build.utils.HashableDict( + { + **var_dict, + "c_stdlib_version": v_stdlib, + "MACOSX_DEPLOYMENT_TARGET": v_stdlib, + } + ) + result.append(new_dict) # ensure we keep type of wrapper container (set stays set, etc.) return type(container_of_dicts)(result)