What is a conda package (short version)?¶
A conda package is fundamentally a zip compressed archive (.conda) that contains two .tar.zst archives with one containing the package files and the other containing all the metadata.
The JSON metadata describes the package structure, provenance, requirements, and dependencies.
The package files consist of relocatable, platform-specific binaries and, optionally, symlinks (on supported platforms).
The package format is simple yet general, powerful, and language agnostic — effectively any software can be packaged as a conda package.
What are “platforms”?
Conda “platforms” are combinations of operating systems (e.g. Linux, macOS) and computing architectures (e.g. x86_64, AArch64) for which a particular conda package is built.
Example of conda platform name mapping:
linux-64: Linux x86_64linux-aarch64: Linux AArch64osx-64: macOS x86_64osx-arm64: macOS Apple silicon (ARM64-based)win-64: Windows x86_64win-arm64: Windows ARM64
Building a conda package¶
Conda packages are defined through a package recipe YAML file (recipe.yaml) with Jinja2 templating support and a robust schema. Recipes are built with a recipe build tool (rattler-build) into packages (the archives that are distributed).
The recipe file is separated into multiple sections that can conditionally be excluded or included
| Sections | Description |
|---|---|
context | Defines variables that can be used in the Jinja context later in the recipe (e.g. version is commonly interpolated in strings) |
package | Defines the name and version of the package you are currently building and will be the name of the final output |
source | Defines where the source code is going to be downloaded from and checksums |
build | Settings for the build and the build script |
requirements | Allows the definition of build, host, run and run-constrained dependencies |
rattler-build can then be used to build the recipe at the command line with rattler-build’s CLI API:
# pixi global install rattler-build
rattler-build build --recipe <path to recipe directory>Example conda recipes¶
Pure-Python (noarch: python)¶
(From the conda-forge maintainer documentation)
schema_version: 1
context:
version: 1.2.3
python_min: "3.10"
package:
name: example-package
version: ${{ version }}
source:
url: https://pypi.org/packages/source/e/example-package/example_package-${{ version }}.tar.gz
sha256: 12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a
build:
noarch: python
number: 0
script: ${{ PYTHON }} -m pip install . -vv --no-deps --no-build-isolation
requirements:
host:
- python ${{ python_min }}.*
- hatchling # your build-system build tool goes here
- pip
run:
- python >=${{ python_min }}
tests:
- python:
imports:
- example_package
python_version:
- ${{ python_min }}.*
- "*"
pip_check: true
about:
homepage: https://example.com/example-package
license: BSD-3-Clause
license_file: LICENSE
summary: Single-line summary of the package.
description: |
One or two paragraphs with more information about the package.
repository: https://github.com/example/example-package/
documentation: https://example.com/example-package-docs/
extra:
recipe-maintainers:
# GitHub username
- henryiii
- matthewfeickertCompiled extensions¶
If the package recipe has compiled extensions the package will be built against every version of Python that is currently supported by conda-forge.
schema_version: 1
context:
version: 1.2.3
package:
name: example-package
version: ${{ version }}
source:
url: https://pypi.org/packages/source/e/example-package/example_package-${{ version }}.tar.gz
sha256: 12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a
build:
number: 0
script:
env:
CMAKE_GENERATOR: Ninja
content:
- ${{ PYTHON }} -m pip install . -vv --no-deps --no-build-isolation
requirements:
build:
- ${{ stdlib("c") }}
- ${{ compiler("cxx") }}
- cmake
- ninja
- if: build_platform != host_platform
then:
- cross-python_${{ host_platform }}
- python
- numpy
host:
- python
- pip
- scikit-build-core
- numpy
run:
- python
- numpy
tests:
- python:
imports:
- example_package
pip_check: true
- script:
- example-package-cli --help
about:
homepage: https://example.com/example-package
license: BSD-3-Clause
license_file: LICENSE
summary: Single-line summary of the package.
description: |
One or two paragraphs with more information about the package.
repository: https://github.com/example/example-package/
documentation: https://example.com/example-package-docs/
extra:
recipe-maintainers:
# GitHub username
- henryiii
- matthewfeickertSubmitting a package to conda-forge¶
The building of packages for the conda-forge conda channel is centralized through a community maintained build farm which builds all of the conda-forge feedstocks — GitHub repository with the conda package recipe, supporting scripts, and CI configuration — on https://
Submitting recipes to conda-forge/staged-recipes workflow¶
Fork https://
github .com /conda -forge /staged -recipes to your personal GitHub. # pixi global install gh git gh repo fork conda-forge/staged-recipes --clone=false git clone --depth 10 git@github.com:<your GitHub account username>/staged-recipes.git cd staged-recipes git remote add upstream git@github.com:conda-forge/staged-recipes.git git fetch --all --depth 10 --prune # You can optionally unshallow your clone if you wantMake a new branch from
mainfor your package’s recipe.git checkout upstream/main -b feat/add-my-packageCreate the package recipe
If the package exists on PyPI already use Pixi and
grayskullto generate the recipepixi run pypi <PyPI package name>Example:
pixi run pypi boost-histogramThis will produce the recipe at
./recipes/<PyPI package name>/.If the package is not already on PyPI, copy the example
rattler-build(“v1”) recipe into a directory named for your package (replacingexample_packagewith your unique package name)cp -R ./recipes/example-v1 ./recipes/example_packageand then edit the package’s
recipe.yamlto meet your package needs following the hints in the comments, in theREADME.md, and therattler-builddocs/tutorials.
Once you have your recipe ready, stage and commit it to Git, and then lint the recipe
pixi run lintIf the linter fails, address the issues before continuing.
Run a test build of the package locally.
pixi run <build-linux|build-osx|build-win>If the test build passes, make sure all your changes are committed, and push your branch to your fork
git push -u origin HEADand then open a draft pull request against the
upstream’smainbranch.Ensure that you read, follow, and complete the checklist. Once your builds are passing, mark your PR as ready for review and tag the relevant conda-forge/staged-recipes review team. For pure-Python packages this would be
@conda-forge/help-python, ready for review!and for packages with compiled extensions this would be
@conda-forge/help-python-c, ready for review!Once you do so, the conda-forge-webservices will apply the relevant tags for the review team to find the recipe.
Once your recipe is reviewed and approved, it will be merged, which will then kick off automation to generate a conda-forge feedstock at
https://github.com/conda-forge/<package name>-feedstockand to generate a maintainer team on GitHub populated by theextra.recipe-maintainerslist in the package recipe. Your package feedstock will be automatically regenerated by theconda-forge-adminbot account and then the built packages will be automatically uploaded to https://anaconda .org /channels /conda -forge.
Getting help¶
When in doubt, just ask! The conda-forge Zulip server is the best way to get responses from the community and the conda-forge/core team, but also make sure to check out the maintainer knowledge base in the documentation first.
rattler-build recipe build example¶
Here is an valid rattler-build recipe for the collatz example from the A minimal compiled package with scikit-build section
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64schema_version: 1 context: version: 0.1.0 package: name: rattler-collatz version: ${{ version }} source: url: https://github.com/scikit-build/SIMPLE-Py/archive/8c60b848fe7f8d72391d49c2130b27c88aad8dfb.tar.gz # pixi global install curl openssl # curl -sL <url> | openssl sha256 sha256: fbd494e7216db678ec5b5f9f7bf7713faaf142690fd46298dcdd2e4d202dcc23 build: number: 0 script: env: CMAKE_GENERATOR: Ninja content: - cd examples/5_02_pixi_build/compiled - ${{ PYTHON }} -m pip install . -vv --no-deps --no-build-isolation requirements: build: # This is provided by conda-forge and so needs to be commented out for now. # - ${{ stdlib("c") }} - ${{ compiler("cxx") }} - cmake - ninja - if: build_platform != host_platform then: - cross-python_${{ host_platform }} - python host: - python - pip - scikit-build-core - pybind11 run: - python tests: - python: imports: - collatz pip_check: true about: homepage: https://github.com/scikit-build/SIMPLE-Py license: BSD-3-Clause license_file: examples/5_02_pixi_build/compiled/LICENSE summary: Single-line summary of the package. description: | One or two paragraphs with more information about the package. repository: https://github.com/scikit-build/SIMPLE-Py documentation: https://github.com/scikit-build/SIMPLE-Py extra: recipe-maintainers: # GitHub username - henryiii - matthewfeickert