Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: corrupted build string in direct violation of its specification #5571

Open
2 tasks done
h-vetinari opened this issue Dec 19, 2024 · 13 comments
Open
2 tasks done
Labels
type::bug describes erroneous operation, use severity::* to classify the type

Comments

@h-vetinari
Copy link
Contributor

h-vetinari commented Dec 19, 2024

Checklist

  • I added a descriptive title
  • I searched open reports and couldn't find a duplicate

What happened?

Our blas metapackage is surely not trivial and ends up pushing conda-build into unusual corners (there are several bugs in addition to this one; perhaps I get around to raising more issues).

This issue is pretty blatant though. As of h-vetinari/blas-feedstock@4a63a00, the recipe contains:

  - name: blas
    version: "{{ blas_major }}.{{ blas_minor }}"
    script: test_blas.sh   # [unix]
    script: test_blas.bat  # [win]
    build:
      string: "{{ blas_impl }}"

And yet, when the blis-variant gets built, what we see is (added linebreaks for readability)

BUILD START: [
    'libblas-3.9.0-27_hde320c6_blis.conda',
    'libcblas-3.9.0-27_h35a6ab0_blis.conda',
    'blas-devel-3.9.0-27_h35a6ab0_blis.conda',
    'blas-2.127-blish14e4bdd.conda'
                    ^^^^^^^^
                    What?!
]

That's despite the fully rendered recipe (in the logs) looking like this:

  - build:
      activate_in_script: true
      string: blis
    name: blas
    requirements:

Later this obviously falls over when it doesn't match expectations anymore:

Could not solve for environment specs
The following packages are incompatible
├─ blas 2.127.* blish14e4bdd is requested and can be installed;
└─ libcblas 3.9.0.* 27_h35a6ab0_blis is not installable because it requires
   └─ blas * blis, which conflicts with any installable versions previously reported.

Conda Info

++ conda info

     active environment : base
    active env location : /opt/conda
            shell level : 1
       user config file : /home/conda/.condarc
 populated config files : /opt/conda/.condarc
                          /home/conda/.condarc
          conda version : 24.11.1
    conda-build version : 24.11.2
         python version : 3.12.8.final.0
                 solver : libmamba (default)
       virtual packages : __archspec=1=broadwell
                          __conda=24.11.1=0
                          __glibc=2.34=0
                          __linux=6.5.0=0
                          __unix=0=0
       base environment : /opt/conda  (writable)
      conda av data dir : /opt/conda/etc/conda
  conda av metadata url : None
           channel URLs : https://conda.anaconda.org/conda-forge/linux-64
                          https://conda.anaconda.org/conda-forge/noarch
          package cache : /home/conda/feedstock_root/build_artifacts/pkg_cache
                          /opt/conda/pkgs
       envs directories : /opt/conda/envs
                          /home/conda/.conda/envs
               platform : linux-64
             user-agent : conda/24.11.1 requests/2.32.3 CPython/3.12.8 Linux/6.5.0-1025-azure almalinux/9.5 glibc/2.34 solver/libmamba conda-libmamba-solver/24.11.1 libmambapy/2.0.5
                UID:GID : 1001:1001
             netrc file : None
           offline mode : False

Conda Config

++ conda config --env --show-sources
==> /opt/conda/.condarc <==
add_pip_as_python_dependency: False
auto_update_conda: False
aggressive_update_packages:
  - ca-certificates
  - certifi
channel_priority: strict
channels:
  - conda-forge
show_channel_urls: True
conda_build:
  pkg_format: 2
  zstd_compression_level: 19

==> /home/conda/.condarc <==
pkgs_dirs:
  - /home/conda/feedstock_root/build_artifacts/pkg_cache
  - /opt/conda/pkgs
solver: libmamba
conda-build:
  root-dir: /home/conda/feedstock_root/build_artifacts

==> envvars <==
allow_softlinks: False
bld_path: /home/conda/feedstock_root/build_artifacts

Conda list

++ conda list --show-channel-urls
# packages in environment at /opt/conda:
#
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                 conda_forge    conda-forge
_openmp_mutex             4.5                       2_gnu    conda-forge
anaconda-client           1.12.3             pyhd8ed1ab_1    conda-forge
archspec                  0.2.3              pyhd8ed1ab_0    conda-forge
attrs                     24.3.0             pyh71513ae_0    conda-forge
beautifulsoup4            4.12.3             pyha770c72_1    conda-forge
boltons                   24.0.0             pyhd8ed1ab_1    conda-forge
brotli-python             1.1.0           py312h2ec8cdc_2    conda-forge
bzip2                     1.0.8                h4bc722e_7    conda-forge
c-ares                    1.34.4               hb9d3cd8_0    conda-forge
ca-certificates           2024.12.14           hbcca054_0    conda-forge
certifi                   2024.12.14         pyhd8ed1ab_0    conda-forge
cffi                      1.17.1          py312h06ac9bb_0    conda-forge
chardet                   5.2.0           py312h7900ff3_2    conda-forge
charset-normalizer        3.4.0              pyhd8ed1ab_1    conda-forge
click                     8.1.7           unix_pyh707e725_1    conda-forge
colorama                  0.4.6              pyhd8ed1ab_1    conda-forge
conda                     24.11.1         py312h7900ff3_0    conda-forge
conda-build               24.11.2         py312h7900ff3_1    conda-forge
conda-env                 2.6.0                         1    conda-forge
conda-forge-ci-setup      4.14.0          py312hb3d6910_100    conda-forge
conda-forge-metadata      0.11.0             pyhd8ed1ab_0    conda-forge
conda-index               0.5.0              pyhd8ed1ab_0    conda-forge
conda-libmamba-solver     24.11.1            pyhd8ed1ab_0    conda-forge
conda-oci-mirror          0.2.1              pyhd8ed1ab_0    conda-forge
conda-package-handling    2.4.0              pyha770c72_1    conda-forge
conda-package-streaming   0.11.0             pyhd8ed1ab_0    conda-forge
cpp-expected              1.1.0                hf52228f_0    conda-forge
defusedxml                0.7.1              pyhd8ed1ab_0    conda-forge
deprecated                1.2.15             pyhd8ed1ab_1    conda-forge
distro                    1.9.0              pyhd8ed1ab_0    conda-forge
filelock                  3.16.1             pyhd8ed1ab_1    conda-forge
fmt                       11.0.2               h434a139_0    conda-forge
frozendict                2.4.6           py312h66e93f0_0    conda-forge
git                       2.47.1          pl5321h59d505e_0    conda-forge
h2                        4.1.0              pyhd8ed1ab_1    conda-forge
hpack                     4.0.0              pyhd8ed1ab_1    conda-forge
hyperframe                6.0.1              pyhd8ed1ab_1    conda-forge
icu                       75.1                 he02047a_0    conda-forge
idna                      3.10               pyhd8ed1ab_1    conda-forge
importlib_resources       6.4.5              pyhd8ed1ab_1    conda-forge
jinja2                    3.1.4              pyhd8ed1ab_1    conda-forge
joblib                    1.4.2              pyhd8ed1ab_1    conda-forge
jq                        1.7.1                hd590300_0    conda-forge
jsonpatch                 1.33               pyhd8ed1ab_1    conda-forge
jsonpointer               3.0.0           py312h7900ff3_1    conda-forge
jsonschema                4.23.0             pyhd8ed1ab_1    conda-forge
jsonschema-specifications 2024.10.1          pyhd8ed1ab_1    conda-forge
jupyter_core              5.7.2              pyh31011fe_1    conda-forge
keyutils                  1.6.1                h166bdaf_0    conda-forge
krb5                      1.21.3               h659f571_0    conda-forge
ld_impl_linux-64          2.43                 h712a8e2_2    conda-forge
libarchive                3.7.7                h4585015_3    conda-forge
libcurl                   8.11.1               h332b0f4_0    conda-forge
libedit                   3.1.20191231         he28a2e2_2    conda-forge
libev                     4.33                 hd590300_2    conda-forge
libexpat                  2.6.4                h5888daf_0    conda-forge
libffi                    3.4.2                h7f98852_5    conda-forge
libgcc                    14.2.0               h77fa898_1    conda-forge
libgcc-ng                 14.2.0               h69a702a_1    conda-forge
libgomp                   14.2.0               h77fa898_1    conda-forge
libiconv                  1.17                 hd590300_2    conda-forge
liblief                   0.14.1               h5888daf_2    conda-forge
liblzma                   5.6.3                hb9d3cd8_1    conda-forge
liblzma-devel             5.6.3                hb9d3cd8_1    conda-forge
libmamba                  2.0.5                hf72d635_0    conda-forge
libmambapy                2.0.5           py312hf3f0a4e_0    conda-forge
libnghttp2                1.64.0               h161d5f1_0    conda-forge
libnsl                    2.0.1                hd590300_0    conda-forge
libsolv                   0.7.30               h3509ff9_0    conda-forge
libsqlite                 3.47.2               hee588c1_0    conda-forge
libssh2                   1.11.1               hf672d98_0    conda-forge
libstdcxx                 14.2.0               hc0a3c3a_1    conda-forge
libstdcxx-ng              14.2.0               h4852527_1    conda-forge
libuuid                   2.38.1               h0b41bf4_0    conda-forge
libxcrypt                 4.4.36               hd590300_1    conda-forge
libxml2                   2.13.5               h8d12d68_1    conda-forge
libzlib                   1.3.1                hb9d3cd8_2    conda-forge
lz4-c                     1.10.0               h5888daf_1    conda-forge
lzo                       2.10              hd590300_1001    conda-forge
mamba                     2.0.5                hfdd0a45_0    conda-forge
markupsafe                3.0.2           py312h178313f_1    conda-forge
menuinst                  2.2.0           py312h7900ff3_0    conda-forge
more-itertools            10.5.0             pyhd8ed1ab_1    conda-forge
nbformat                  5.10.4             pyhd8ed1ab_1    conda-forge
ncurses                   6.5                  he02047a_1    conda-forge
nlohmann_json             3.11.3               he02047a_1    conda-forge
oniguruma                 6.9.9                hd590300_0    conda-forge
openssl                   3.4.0                hb9d3cd8_0    conda-forge
oras-py                   0.1.14             pyhd8ed1ab_0    conda-forge
packaging                 24.2               pyhd8ed1ab_2    conda-forge
patch                     2.7.6             h7f98852_1002    conda-forge
patchelf                  0.17.2               h58526e2_0    conda-forge
pcre2                     10.44                hba22ea6_2    conda-forge
perl                      5.32.1          7_hd590300_perl5    conda-forge
pip                       24.3.1             pyh145f28c_1    conda-forge
pkginfo                   1.12.0             pyhd8ed1ab_1    conda-forge
pkgutil-resolve-name      1.3.10             pyhd8ed1ab_2    conda-forge
platformdirs              4.3.6              pyhd8ed1ab_1    conda-forge
pluggy                    1.5.0              pyhd8ed1ab_1    conda-forge
psutil                    6.1.0           py312h66e93f0_0    conda-forge
py-lief                   0.14.1          py312h2ec8cdc_2    conda-forge
pybind11-abi              4                    hd8ed1ab_3    conda-forge
pycosat                   0.6.6           py312h66e93f0_2    conda-forge
pycparser                 2.22               pyh29332c3_1    conda-forge
pysocks                   1.7.1              pyha55dd90_7    conda-forge
python                    3.12.8          h9e4cc4f_1_cpython    conda-forge
python-dateutil           2.9.0.post0        pyhff2d567_1    conda-forge
python-fastjsonschema     2.21.1             pyhd8ed1ab_0    conda-forge
python-libarchive-c       5.1             py312h7900ff3_1    conda-forge
python_abi                3.12                    5_cp312    conda-forge
pytz                      2024.2             pyhd8ed1ab_1    conda-forge
pyyaml                    6.0.2           py312h66e93f0_1    conda-forge
rattler-build             0.33.0               hbcf9e9b_0    conda-forge
rattler-build-conda-compat 1.2.2              pyhd8ed1ab_0    conda-forge
readline                  8.2                  h8228510_1    conda-forge
referencing               0.35.1             pyhd8ed1ab_1    conda-forge
reproc                    14.2.5.post0         hb9d3cd8_0    conda-forge
reproc-cpp                14.2.5.post0         h5888daf_0    conda-forge
requests                  2.32.3             pyhd8ed1ab_1    conda-forge
requests-toolbelt         1.0.0              pyhd8ed1ab_1    conda-forge
ripgrep                   14.1.1               h8fae777_0    conda-forge
rpds-py                   0.22.3          py312h12e396e_0    conda-forge
ruamel.yaml               0.18.6          py312h66e93f0_1    conda-forge
ruamel.yaml.clib          0.2.8           py312h66e93f0_1    conda-forge
setuptools                75.6.0             pyhff2d567_1    conda-forge
shyaml                    0.6.2              pyhd3deb0d_0    conda-forge
simdjson                  3.11.3               h84d6215_0    conda-forge
six                       1.17.0             pyhd8ed1ab_0    conda-forge
soupsieve                 2.5                pyhd8ed1ab_1    conda-forge
spdlog                    1.14.1               hed91bc2_1    conda-forge
su-exec                   0.2               h166bdaf_1003    conda-forge
tini                      0.19.0               h166bdaf_1    conda-forge
tk                        8.6.13          noxft_h4845f30_101    conda-forge
tomli                     2.2.1              pyhd8ed1ab_1    conda-forge
tqdm                      4.67.1             pyhd8ed1ab_0    conda-forge
traitlets                 5.14.3             pyhd8ed1ab_1    conda-forge
truststore                0.10.0             pyhd8ed1ab_0    conda-forge
typing-extensions         4.12.2               hd8ed1ab_1    conda-forge
typing_extensions         4.12.2             pyha770c72_1    conda-forge
tzdata                    2024b                hc8b5060_0    conda-forge
urllib3                   2.2.3              pyhd8ed1ab_1    conda-forge
wheel                     0.45.1             pyhd8ed1ab_1    conda-forge
wrapt                     1.17.0          py312h66e93f0_0    conda-forge
xz                        5.6.3                hbcc6ac9_1    conda-forge
xz-gpl-tools              5.6.3                hbcc6ac9_1    conda-forge
xz-tools                  5.6.3                hb9d3cd8_1    conda-forge
yaml                      0.2.5                h7f98852_2    conda-forge
yaml-cpp                  0.8.0                h59595ed_0    conda-forge
zipp                      3.21.0             pyhd8ed1ab_1    conda-forge
zstandard                 0.23.0          py312hef9b889_1    conda-forge
zstd                      1.5.6                ha6fb4c9_0    conda-forge
@h-vetinari h-vetinari added the type::bug describes erroneous operation, use severity::* to classify the type label Dec 19, 2024
@github-project-automation github-project-automation bot moved this to 🆕 New in 🧭 Planning Dec 19, 2024
@jaimergp
Copy link
Contributor

Attaching CI logs from the offending PR in conda-forge/blas-feedstock#1302b61a42.

@jaimergp
Copy link
Contributor

I'm poking around and tried to undo the name =version=build_string constrains so they are more like the canonical three-field form of name version build_string. Interestingly, that triggers earlier errors that could be more telling:

  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/lib/python3.12/site-packages/conda_build/metadata.py", line 2696, in get_output_metadata_set
    ensure_matching_hashes(conda_packages)
  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/lib/python3.12/site-packages/conda_build/metadata.py", line 507, in ensure_matching_hashes
    raise RecipeError(
conda_build.exceptions.RecipeError: Mismatching hashes in recipe. Exact pins in dependencies that contribute to the hash often cause this. Can you change one or more exact pins to version bound constraints?
Involved packages were:
Mismatching package: blas-devel (id 27_he1c578d_blis); dep: blas-devel 3.9.0 27_*_blis; consumer package: blas

Maybe the equals-separated form is bypassing those early checks, unintentionally?

@jaimergp
Copy link
Contributor

If I undo all the equals-separated pin-exact=True replacements:

Attempting to finalize metadata for blas
Reloading output folder: ...working... done
Getting pinned dependencies: ...working... done
Traceback (most recent call last):
  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/bin/conda-build", line 11, in <module>
    sys.exit(execute())
             ^^^^^^^^^
  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/lib/python3.12/site-packages/conda_build/cli/main_build.py", line 622, in execute
    api.build(
  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/lib/python3.12/site-packages/conda_build/api.py", line 211, in build
    return build_tree(
           ^^^^^^^^^^^
  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/lib/python3.12/site-packages/conda_build/build.py", line 3656, in build_tree
    packages_from_this = build(
                         ^^^^^^
  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/lib/python3.12/site-packages/conda_build/build.py", line 2337, in build
    output_metas = expand_outputs([(m, need_source_download, need_reparse_in_env)])
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/lib/python3.12/site-packages/conda_build/render.py", line 926, in expand_outputs
    for output_dict, m in deepcopy(_m).get_output_metadata_set(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/lib/python3.12/site-packages/conda_build/metadata.py", line 2696, in get_output_metadata_set
    ensure_matching_hashes(conda_packages)
  File "/Users/jrodriguez/devel/blas-feedstock/miniforge3/lib/python3.12/site-packages/conda_build/metadata.py", line 507, in ensure_matching_hashes
    raise RecipeError(
conda_build.exceptions.RecipeError: Mismatching hashes in recipe. Exact pins in dependencies that contribute to the hash often cause this. Can you change one or more exact pins to version bound constraints?
Involved packages were:
Mismatching package: libblas (id 27_h09e100e_blis); dep: libblas 3.9.0 27_*_blis; consumer package: libcblas
Mismatching package: libblas (id 27_h09e100e_blis); dep: libblas 3.9.0 27_*_blis; consumer package: libcblas
Mismatching package: libblas (id 27_h09e100e_blis); dep: libblas 3.9.0 27_*_blis; consumer package: blas-devel
Mismatching package: libcblas (id 27_hb1fc1ef_blis); dep: libcblas 3.9.0 27_*_blis; consumer package: blas-devel
Mismatching package: blas-devel (id 27_he1c578d_blis); dep: blas-devel 3.9.0 27_*_blis; consumer package: blas
Mismatching package: blas-devel (id 27_he1c578d_blis); dep: blas-devel 3.9.0 27_*_blis; consumer package: blas

@jaimergp
Copy link
Contributor

You can see why the equals-separated string doesn't run into this:

def ensure_matching_hashes(output_metadata):
    envs = "build", "host", "run"
    problemos = []
    for _, m in output_metadata.values():
        for _, om in output_metadata.values():
            if m != om:
                run_exports = om.get_value("build/run_exports", [])
                if hasattr(run_exports, "keys"):
                    run_exports_list = []
                    for export_type in utils.RUN_EXPORTS_TYPES:
                        run_exports_list = run_exports_list + run_exports.get(
                            export_type, []
                        )
                    run_exports = run_exports_list
                deps = _get_all_dependencies(om, envs) + run_exports
                for dep in deps:
                    if (
                        dep.startswith(m.name() + " ")
                        and len(dep.split(" ")) == 3   # <---- See this check!
                        and dep.split(" ")[-1] != m.build_id()
                        and _variants_equal(m, om)
                    ):
                        problemos.append((m.name(), m.build_id(), dep, om.name()))

    if problemos:
        error = ""
        for prob in problemos:
            error += "Mismatching package: {} (id {}); dep: {}; consumer package: {}\n".format(
                *prob
            )
        raise RecipeError(
            "Mismatching hashes in recipe. Exact pins in dependencies "
            "that contribute to the hash often cause this. Can you "
            "change one or more exact pins to version bound constraints?\n"
            "Involved packages were:\n" + error
        )

It only considers the three-field variant of MatchSpec (instead of parsing it). If this is a false positive, some part of that if check might be responsible, either the _get_all_dependencies() call or the _variants_equal() one.

@h-vetinari
Copy link
Contributor Author

So what's the suggestion...? Remove the =?

Also, I was wondering if the

Mismatching package: libblas (id 27_h09e100e_blis); dep: libblas 3.9.0 27_*_blis;

bit isn't something that should have been solved by the glob-merge logic (conda/conda@6db7b91). Or has this somehow not arrived in conda-build yet?

@h-vetinari
Copy link
Contributor Author

So what's the suggestion...? Remove the =?

Sidenote: I had been completely unaware about the the divergences when using = or not (in the discussion whether rattler-build should support it), and I'm honestly shocked that this makes a difference. All the following should mean exactly the same!

pkg ==<version>=<hash>
pkg =<version=<hash>
pkg <version <hash

It's incomprehensible to me that this divergence would serve some purpose other than being a major footgun.

PS. Thanks a lot for digging into this! 🙏

@jaimergp
Copy link
Contributor

So what's the suggestion...? Remove the =?

Not exactly. I was just mentioning that it looks like conda-build had some logic to detect this magic hash contamination early, but that the equals bypassed it because they pre-parse fields assuming space separators. There should not be any difference but in practice we should lint against = forms because spaces are assumed in some places... There are also some round trip bugs that transform = into == and so on.

pkg ==<version>=<hash>
pkg =<version>=<hash>
pkg <version> <hash

Only 2 and 3 are equivalent. The first is an exact match, so ==3.9 will only match 3.9 but not 3.9.0.

@jaimergp
Copy link
Contributor

bit isn't something that should have been solved by the glob-merge logic (conda/conda@6db7b91). Or has this somehow not arrived in conda-build yet?

I think that check is not considering MatchSpec objects at all, just string comparisons? I need to look at this more deeply.

@jaimergp
Copy link
Contributor

jaimergp commented Jan 21, 2025

The function was introduced in #2065, then modified in #3237 (big PR, better see this blame) Also, #4603, but that's just a cleanup I think?.

In these PRs we could still see the original comments that explain why this is needed to begin with:

                # The loop above gives us enough info to determine the build order.  After that,
                #    we can "finalize" the metadata (fill in version pins) for the build metadata.
                #    This does not, however, account for circular dependencies
                #    where a runtime exact dependency pin on a downstream build
                #    subpackage in an upstream subpackage changes the upstream's
                #    hash, which then changes the downstream package's hash, which
                #    then recurses infinitely

                # In general, given upstream a and downstream b, b can depend on a
                # exactly, but a can only have version constraints on b at run or
                # run_exports, not exact=True

                # 3 passes here:
                #    1. fill in fully-resolved build-time dependencies
                #    2. fill in fully-resolved run-time dependencies.  Note that circular deps
                #       are allowed, but you can't have exact=True for circular run-time deps
                #    3. finally, everything should be filled in and done.
                conda_packages = finalize_outputs_pass(self, conda_packages, pass_no=0,
                                    permit_unsatisfiable_variants=permit_unsatisfiable_variants)

                # Sanity check: if any exact pins of any subpackages, make sure that they match
                ensure_matching_hashes(conda_packages)

However I'm having trouble parsing that text 😬 I'll need my morning brain I think 😂

@jaimergp
Copy link
Contributor

jaimergp commented Jan 21, 2025

I patched the ensure_matching_hashes function so it uses GlobStrLowerMatch (as it should), which makes this part pass, BUT it keeps failing at test time with the same error as reported:

Could not solve for environment specs
The following packages are incompatible
├─ blas-devel 3.9.0.* 27_*_blis is installable and it requires
│  └─ libcblas 3.9.0 27_*_blis, which requires
│     └─ blas 2.127 blis, which can be installed;
└─ blas 2.127.* blish150452e is not installable because it conflicts with any installable versions previously reported.

I searched this hash locally and it does appear in the pkgs/ cache:

{
    "info": {
        "subdir": "osx-64"
    },
    "packages": {},
    "packages.conda": {
        "blas-2.127-blish150452e.conda": {
            "build": "blish150452e",
            "build_number": 27,
            "depends": [
                "blas-devel 3.9.0 27_*_blis"
            ],
            "license": "BSD-3-Clause",
            "md5": "731ebd99f30c1b3fd2dc55e84e5436a8",
            "name": "blas",
            "sha256": "73b9c4abacad3cb8524556fa7b231b8f1b034731acb10afb6eee12af47010278",
            "size": 16824,
            "subdir": "osx-64",
            "timestamp": 1737474981292,
            "version": "2.127"
        },
        "blas-devel-3.9.0-27_he1c578d_blis.conda": {
            "build": "27_he1c578d_blis",
            "build_number": 27,
            "depends": [
                "blis 0.9.0.*",
                "libblas 3.9.0 27_*_blis",
                "libcblas 3.9.0 27_*_blis",
                "liblapack 3.9.0 *_netlib",
                "liblapacke 3.9.0 *_netlib"
            ],
            "license": "BSD-3-Clause",
            "md5": "c8befb15db1b0cf076f6682d9197982a",
            "name": "blas-devel",
            "sha256": "7b7f01e25d9938186e02335a5406515b9baaddc8ac080bcd0b18faa91b4cdc46",
            "size": 16398,
            "subdir": "osx-64",
            "timestamp": 1737474966930,
            "version": "3.9.0"
        },
        "libblas-3.9.0-27_h09e100e_blis.conda": {
            "build": "27_h09e100e_blis",
            "build_number": 27,
            "constrains": [
                "libcblas  3.9.0 27_*_blis",
                "blas  2.127 blis"
            ],
            "depends": [
                "blis >=0.9.0,<0.9.1.0a0"
            ],
            "license": "BSD-3-Clause",
            "md5": "4e7c08108d69a415c317583edf563886",
            "name": "libblas",
            "sha256": "81b547d9f02d75ce274595cdc464aa786644046217b1f384991ad3911bd67b30",
            "size": 16712,
            "subdir": "osx-64",
            "timestamp": 1737474957462,
            "track_features": "blas_blis",
            "version": "3.9.0"
        },
        "libcblas-3.9.0-27_hb1fc1ef_blis.conda": {
            "build": "27_hb1fc1ef_blis",
            "build_number": 27,
            "constrains": [
                "blas  2.127 blis"
            ],
            "depends": [
                "libblas 3.9.0 27_*_blis"
            ],
            "license": "BSD-3-Clause",
            "md5": "9e5e5b4dee396c1f33d984b9d4ea694e",
            "name": "libcblas",
            "sha256": "22eed66e2a4c857d4e119c388bd92c5fb2884e376e68167de04b33f68c1a0e50",
            "size": 16691,
            "subdir": "osx-64",
            "timestamp": 1737474961943,
            "track_features": "blas_blis",
            "version": "3.9.0"
        }
    },
    "removed": [],
    "repodata_version": 1
}

So we know it was generated by conda-build as such, and we are not hallucinating it in the solver side of things.

The package itself contains this index.json:

{
  "arch": "x86_64",
  "build": "blish150452e",
  "build_number": 27,
  "depends": [
    "blas-devel 3.9.0 27_*_blis"
  ],
  "license": "BSD-3-Clause",
  "name": "blas",
  "platform": "osx",
  "subdir": "osx-64",
  "timestamp": 1737478329382,
  "version": "2.127"
}

So once again, this is conda-build artifact generation pipeline, not a bug in conda-index.


Patched bit:

                for dep in deps:
                    if (
                        dep.startswith(m.name() + " ")
                        and len(dep.split(" ")) == 3
                        and not GlobLowerStrMatch(
                            dep.split(" ")[-1]
                        ).match(GlobLowerStrMatch(m.build_id()))
                        and _variants_equal(m, om)
                    ):
                        problemos.append((m.name(), m.build_id(), dep, om.name()))

@jaimergp
Copy link
Contributor

Interestingly, the conda render output is correct. blas's string is blis after all:

./miniforge3/bin/python -m conda render -m .ci_support/osx_64_blas_implblisblas_impl_liblibblis.4.dylib.yaml recipe
WARNING: Adding .* to spec 'blis 0.9.0' to ensure satisfiability.  Please consider putting {{{{ var_name }}}}.* or some relational operator (>/</>=/<=) on this spec in meta.yaml, or if req is also a build req, using {{{{ pin_compatible() }}}} jinja2 function instead.  See https://conda.io/docs/user-guide/tasks/build-packages/variants.html#pinning-at-the-variant-level
--------------
Hash contents:
--------------
{'blas_default_impl': 'openblas',
 'blas_impl': 'blis',
 'blas_impl_lib': 'libblis.4.dylib',
 'channel_targets': 'conda-forge main',
 'libblas': '3.9 *netlib',
 'target_platform': 'osx-64'}
----------
meta.yaml:
----------
package:
  name: libblas
  version: 3.9.0
source:
  - patches:
      - patches/0001-Test-BLAS-and-LAPACKE-in-addition-to-LAPACK.patch
      - patches/0002-remove-extraneous-semicolon.patch
      - patches/0003-read-pipe-as-binary.patch
      - patches/0004-add-DLL-import-export-machinery-for-RowMajorStrg.patch
    sha256: 106087f1bb5f46afdfba7f569d0cbe23dacb9a07cd24733765a0e89dbe1ad573
    url: https://github.com/Reference-LAPACK/lapack/archive/v3.9.0.tar.gz
  - folder: vecLibFort
    sha256: 80de7c6e83d1d84d016b4cb299f2c15f5a82b9d36865dd5c16bf221fe9a303ad
    url: https://github.com/isuruf/vecLibFort/archive/99af8640e98c829b41c3235e3706760cd5696fe4.tar.gz
build:
  number: 27
  run_exports:
    - libblas >=3.9.0,<4.0a0
  string: 27_h1234567_blis
  track_features:
    - blas_blis
requirements:
  host:
    - blis 0.9.0 hec52a4b_2
  run:
    - blis >=0.9.0,<0.9.1.0a0
  run_constrained:
    - blas  2.127 blis
    - libcblas  3.9.0 27_*_blis
test:
  commands:
    - test -f $PREFIX/lib/libblas.3.dylib
about:
  home: https://github.com/conda-forge/blas-feedstock
  license: BSD-3-Clause
  license_file:
    - LICENSE.txt
  summary: Metapackage to select the BLAS variant. Use conda's pinning mechanism in
    your environment to control which variant you want.
extra:
  copy_test_source_files: true
  feedstock-name: blas
  final: true
  parent_recipe:
    name: blas-split
    path: /Users/jrodriguez/devel/blas-feedstock/recipe
    version: 3.9.0
  recipe-maintainers:
    - jakirkham
    - pelson
    - isuruf
    - ocefpaf
    - h-vetinari

--------------
Hash contents:
--------------
{'blas_default_impl': 'openblas',
 'blas_impl': 'blis',
 'channel_targets': 'conda-forge main',
 'libcblas': '3.9 *netlib',
 'target_platform': 'osx-64'}
----------
meta.yaml:
----------
package:
  name: libcblas
  version: 3.9.0
source:
  - patches:
      - patches/0001-Test-BLAS-and-LAPACKE-in-addition-to-LAPACK.patch
      - patches/0002-remove-extraneous-semicolon.patch
      - patches/0003-read-pipe-as-binary.patch
      - patches/0004-add-DLL-import-export-machinery-for-RowMajorStrg.patch
    sha256: 106087f1bb5f46afdfba7f569d0cbe23dacb9a07cd24733765a0e89dbe1ad573
    url: https://github.com/Reference-LAPACK/lapack/archive/v3.9.0.tar.gz
  - folder: vecLibFort
    sha256: 80de7c6e83d1d84d016b4cb299f2c15f5a82b9d36865dd5c16bf221fe9a303ad
    url: https://github.com/isuruf/vecLibFort/archive/99af8640e98c829b41c3235e3706760cd5696fe4.tar.gz
build:
  number: 27
  run_exports:
    - libcblas >=3.9.0,<4.0a0
  string: 27_h1234567_blis
  track_features:
    - blas_blis
requirements:
  host:
    - libblas 3.9.0 27_*_blis
  run:
    - libblas 3.9.0 27_*_blis
  run_constrained:
    - blas  2.127 blis
test:
  commands:
    - test -f $PREFIX/lib/libcblas.3.dylib
about:
  home: https://github.com/conda-forge/blas-feedstock
  license: BSD-3-Clause
  license_file:
    - LICENSE.txt
  summary: Metapackage to select the BLAS variant. Use conda's pinning mechanism in
    your environment to control which variant you want.
extra:
  copy_test_source_files: true
  feedstock-name: blas
  final: true
  parent_recipe:
    name: blas-split
    path: /Users/jrodriguez/devel/blas-feedstock/recipe
    version: 3.9.0
  recipe-maintainers:
    - jakirkham
    - pelson
    - isuruf
    - ocefpaf
    - h-vetinari

--------------
Hash contents:
--------------
{'blas_default_impl': 'openblas',
 'blas_impl': 'blis',
 'channel_targets': 'conda-forge main',
 'libblas': '3.9 *netlib',
 'liblapack': '3.9 *netlib',
 'target_platform': 'osx-64'}
----------
meta.yaml:
----------
package:
  name: blas-devel
  version: 3.9.0
source:
  - patches:
      - patches/0001-Test-BLAS-and-LAPACKE-in-addition-to-LAPACK.patch
      - patches/0002-remove-extraneous-semicolon.patch
      - patches/0003-read-pipe-as-binary.patch
      - patches/0004-add-DLL-import-export-machinery-for-RowMajorStrg.patch
    sha256: 106087f1bb5f46afdfba7f569d0cbe23dacb9a07cd24733765a0e89dbe1ad573
    url: https://github.com/Reference-LAPACK/lapack/archive/v3.9.0.tar.gz
  - folder: vecLibFort
    sha256: 80de7c6e83d1d84d016b4cb299f2c15f5a82b9d36865dd5c16bf221fe9a303ad
    url: https://github.com/isuruf/vecLibFort/archive/99af8640e98c829b41c3235e3706760cd5696fe4.tar.gz
build:
  number: 27
  string: 27_h1234567_blis
requirements:
  host:
    - blis 0.9.0 hec52a4b_2
  run:
    - libcblas 3.9.0 27_*_blis
    - liblapack 3.9.0=*_netlib
    - liblapacke 3.9.0=*_netlib
    - blis 0.9.0.*
    - libblas 3.9.0 27_*_blis
test:
  commands:
    - test -f $PREFIX/lib/liblapack.dylib
    - test -f $PREFIX/lib/liblapacke.dylib
    - test -f $PREFIX/lib/liblapacke.3.dylib
about:
  home: https://github.com/conda-forge/blas-feedstock
  license: BSD-3-Clause
  license_file:
    - LICENSE.txt
  summary: Metapackage to select the BLAS variant. Use conda's pinning mechanism in
    your environment to control which variant you want.
extra:
  copy_test_source_files: true
  feedstock-name: blas
  final: true
  parent_recipe:
    name: blas-split
    path: /Users/jrodriguez/devel/blas-feedstock/recipe
    version: 3.9.0
  recipe-maintainers:
    - jakirkham
    - pelson
    - isuruf
    - ocefpaf
    - h-vetinari

--------------
Hash contents:
--------------
{'blas_default_impl': 'openblas',
 'blas_impl': 'blis',
 'channel_targets': 'conda-forge main',
 'libblas': '3.9 *netlib',
 'libcblas': '3.9 *netlib',
 'liblapack': '3.9 *netlib',
 'liblapacke': '3.9 *netlib',
 'target_platform': 'osx-64'}
----------
meta.yaml:
----------
package:
  name: blas
  version: '2.127'
source:
  - patches:
      - patches/0001-Test-BLAS-and-LAPACKE-in-addition-to-LAPACK.patch
      - patches/0002-remove-extraneous-semicolon.patch
      - patches/0003-read-pipe-as-binary.patch
      - patches/0004-add-DLL-import-export-machinery-for-RowMajorStrg.patch
    sha256: 106087f1bb5f46afdfba7f569d0cbe23dacb9a07cd24733765a0e89dbe1ad573
    url: https://github.com/Reference-LAPACK/lapack/archive/v3.9.0.tar.gz
  - folder: vecLibFort
    sha256: 80de7c6e83d1d84d016b4cb299f2c15f5a82b9d36865dd5c16bf221fe9a303ad
    url: https://github.com/isuruf/vecLibFort/archive/99af8640e98c829b41c3235e3706760cd5696fe4.tar.gz
build:
  activate_in_script: true
  ignore_run_exports_from:
    - macosx_deployment_target_osx-64 10.13.*
    - clang_osx-64 18.*
    - gfortran_osx-64 13.*
    - llvm-openmp
  number: 27
  string: blis
requirements:
  build:
    - libedit 3.1.20240808 pl5321hafb1f1b_0
    - macosx_deployment_target_osx-64 10.13 hbc8f3bb_2
    - libxml2 2.13.5 h178c5d8_1
    - libuv 1.50.0 h5505292_0
    - isl 0.26 imath32_h347afa1_101
    - clang_osx-64 18.1.8 ha3ec999_23
    - libev 4.33 h93a5062_2
    - compiler-rt_osx-arm64 18.1.8 h832e737_1
    - krb5 1.21.3 h237132a_0
    - libgfortran-devel_osx-arm64 13.2.0 h5d7a38c_3
    - libllvm18 18.1.8 h5090b49_2
    - liblzma 5.6.3 h39f12f2_1
    - gfortran_impl_osx-arm64 13.2.0 h252ada1_3
    - ca-certificates 2024.12.14 hf0a4a13_0
    - rhash 1.4.5 h7ab814d_0
    - zstd 1.5.6 hb46c0d2_0
    - clangxx 18.1.8 default_h1ffe849_6
    - clang 18.1.8 default_h474c9e2_6
    - libexpat 2.6.4 h286801f_0
    - libclang-cpp18.1 18.1.8 default_hf90f093_6
    - cctools_osx-arm64 1010.6 h908b477_2
    - libgfortran5 13.2.0 hf226fd6_3
    - gfortran_osx-64 13.2.0 he24f851_1
    - gmp 6.3.0 h7bae524_2
    - libzlib 1.3.1 h8359307_2
    - libcurl 8.11.1 h73640d1_0
    - libiconv 1.17 h0d3ecfb_2
    - openssl 3.4.0 h81ee809_1
    - libssh2 1.11.1 h9cc3647_0
    - sigtool 0.1.3 h44b9a77_0
    - clang_impl_osx-64 18.1.8 h5be24a6_23
    - cctools_osx-64 1010.6 h0e609b7_2
    - mpfr 4.2.1 hb693164_3
    - clang-18 18.1.8 default_hf90f093_6
    - gfortran_impl_osx-64 13.2.0 hc385ae8_3
    - libnghttp2 1.64.0 h6d7220d_0
    - mpc 1.3.1 h8f1351a_1
    - llvm-tools 18.1.8 h5090b49_2
    - cmake 3.31.5 ha25475f_0
    - libgfortran-devel_osx-64 13.2.0 h80d4556_3
    - libcxx-devel 18.1.8 h6dc3340_7
    - libcxx 19.1.7 ha82da77_0
    - c-ares 1.34.4 h5505292_0
    - zlib 1.3.1 h8359307_2
    - compiler-rt 18.1.8 h856b3c1_1
    - icu 75.1 hfee45f7_0
    - llvm-tools-18 18.1.8 h5090b49_2
    - ld64_osx-64 951.9 hc8706eb_2
    - ncurses 6.5 h5e97a16_2
    - bzip2 1.0.8 h99b78c6_7
    - tapi 1300.6.5 h03f4b80_0
    - ld64_osx-arm64 951.9 hfc0fa09_2
    - llvm-openmp 19.1.7 hdb05f8b_0
  host:
    - blas-devel 3.9.0 27_*_blis
  run:
    - blas-devel 3.9.0 27_*_blis
test:
  commands:
    - echo tested in build script
about:
  home: https://github.com/conda-forge/blas-feedstock
  license: BSD-3-Clause
  license_file:
    - LICENSE.txt
  summary: Metapackage to select the BLAS variant. Use conda's pinning mechanism in
    your environment to control which variant you want.
extra:
  copy_test_source_files: true
  feedstock-name: blas
  final: true
  parent_recipe:
    name: blas-split
    path: /Users/jrodriguez/devel/blas-feedstock/recipe
    version: 3.9.0
  recipe-maintainers:
    - jakirkham
    - pelson
    - isuruf
    - ocefpaf
    - h-vetinari

@jaimergp
Copy link
Contributor

I can verify that in

def build_id(self):
we fail to detect the "manual build string override", which leads to conda-build to calculate it on its own.

This is because

raw_recipe_text = self.extract_package_and_build_text()
returns the text bit for liblapacke, not blas! And that output does export PKG_HASH so it crosses results somehow. I'll investigate why extract_package_and_build_text() is buggy.

@jaimergp
Copy link
Contributor

jaimergp commented Jan 25, 2025

Ok, it comes from here

output_matches = output_re.findall(recipe_text)
outputs = self.meta.get("outputs") or (
self.parent_outputs if hasattr(self, "parent_outputs") else None
)

Because of the Jinja {% if ...} eliding some outputs, this causes some mismatch in how outputs are parsed and text-retrieved. The resulting tuples at

output_tuples = [out.get("name", self.name()) for out in outputs]
output_index = output_tuples.index(output_name)
are misaligned and the indices do not match. I think these part should not rely on tuple alignment but preferably a key-value mapping.

For now, I think this should work if skip: true statements are added instead of {% if ... %} omissions.

Edit: Yea, confirmed:

BUILD START: [
  'libblas-3.9.0-27_h09e100e_blis.conda',
  'libcblas-3.9.0-27_hb1fc1ef_blis.conda',
  'blas-devel-3.9.0-27_hcc04dd8_blis.conda',
  'blas-2.127-blis.conda',
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type::bug describes erroneous operation, use severity::* to classify the type
Projects
Status: 🆕 New
Development

No branches or pull requests

2 participants