From 4b44b71a3f21003a2867ab78f2204d3e027c1fdd Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 14 Jul 2026 02:54:57 -0500 Subject: [PATCH 1/8] feat: Add compiled packaging example for Pixi Build --- content/other-tools/02_pixi_build.md | 2 ++ examples/5_02_pixi_build/basic/.gitignore | 1 + examples/5_02_pixi_build/compiled/pyproject.toml | 16 ++++++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 examples/5_02_pixi_build/compiled/pyproject.toml diff --git a/content/other-tools/02_pixi_build.md b/content/other-tools/02_pixi_build.md index 438fffb..0e2a7b0 100644 --- a/content/other-tools/02_pixi_build.md +++ b/content/other-tools/02_pixi_build.md @@ -223,3 +223,5 @@ pixi publish --clean --target-channel https://prefix.dev/ ::: :::: + +## Compiled Packaging diff --git a/examples/5_02_pixi_build/basic/.gitignore b/examples/5_02_pixi_build/basic/.gitignore index f0de7bf..2ce32db 100644 --- a/examples/5_02_pixi_build/basic/.gitignore +++ b/examples/5_02_pixi_build/basic/.gitignore @@ -224,3 +224,4 @@ src/rescale/_version.py .pixi/* !.pixi/config.toml pixi.lock +*.conda diff --git a/examples/5_02_pixi_build/compiled/pyproject.toml b/examples/5_02_pixi_build/compiled/pyproject.toml new file mode 100644 index 0000000..a617c1b --- /dev/null +++ b/examples/5_02_pixi_build/compiled/pyproject.toml @@ -0,0 +1,16 @@ +[build-system] +requires = ["scikit-build-core", "pybind11"] +build-backend = "scikit_build_core.build" + +[project] +name = "collatz" +version = "0.1.0" + +[tool.pixi.workspace] +channels = ["conda-forge"] +platforms = ["linux-64", "win-64", "osx-arm64", "linux-aarch64"] + +[tool.pixi.pypi-dependencies] +collatz = { path = ".", editable = true } + +[tool.pixi.tasks] From 2469e59bbdc14e7ab1f7c11eff3367f9872b3de2 Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 14 Jul 2026 03:14:41 -0500 Subject: [PATCH 2/8] Add outline of compiled packaging --- .../5_02_pixi_build/compiled/pyproject.toml | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/examples/5_02_pixi_build/compiled/pyproject.toml b/examples/5_02_pixi_build/compiled/pyproject.toml index a617c1b..2a01282 100644 --- a/examples/5_02_pixi_build/compiled/pyproject.toml +++ b/examples/5_02_pixi_build/compiled/pyproject.toml @@ -10,7 +10,33 @@ version = "0.1.0" channels = ["conda-forge"] platforms = ["linux-64", "win-64", "osx-arm64", "linux-aarch64"] -[tool.pixi.pypi-dependencies] -collatz = { path = ".", editable = true } +preview = ["pixi-build"] + +[tool.pixi.dependencies] +collatz = { path = "." } + +[tool.pixi.package] +name = "collatz" +version = "0.1.0" + +[tool.pixi.package.build.backend] +name = "pixi-build-python" +version = "0.*" + +[tool.pixi.package.build.config] +# c.f. https://pixi.prefix.dev/latest/build/backends/pixi-build-python/#compilers +# c.f. https://pixi.prefix.dev/latest/build/backends/pixi-build-python/#ignore-pypi-mapping +compilers = ["cxx"] +ignore-pypi-mapping = false + +# TODO: Ensure Ninja +[tool.pixi.package.build-dependencies] +cmake = "*" +ninja = "*" + +# Unneeded given package.build.config.ignore-pypi-mapping = false +# [tool.pixi.package.host-dependencies] +# scikit-build-core = "*" +# pybind11 = "*" [tool.pixi.tasks] From 59f81b57a01534e687d02ba0c61d004cb08051ab Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 14 Jul 2026 09:07:23 -0500 Subject: [PATCH 3/8] Get Ninja --- examples/5_02_pixi_build/compiled/pyproject.toml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/5_02_pixi_build/compiled/pyproject.toml b/examples/5_02_pixi_build/compiled/pyproject.toml index 2a01282..68b6b03 100644 --- a/examples/5_02_pixi_build/compiled/pyproject.toml +++ b/examples/5_02_pixi_build/compiled/pyproject.toml @@ -12,6 +12,14 @@ platforms = ["linux-64", "win-64", "osx-arm64", "linux-aarch64"] preview = ["pixi-build"] +[tool.scikit-build] +# rattler-build (through pixi-build-python) exports +# CMAKE_GENERATOR='Unix Makefiles' as a default behavior, which overrides +# scikit-build-core's default of Ninja. To override this and restore the +# default behavior provide scikit-build-core explicit arguments. +# c.f. https://github.com/prefix-dev/rattler-build/issues/2487 +cmake.args = ["-GNinja"] + [tool.pixi.dependencies] collatz = { path = "." } @@ -29,7 +37,6 @@ version = "0.*" compilers = ["cxx"] ignore-pypi-mapping = false -# TODO: Ensure Ninja [tool.pixi.package.build-dependencies] cmake = "*" ninja = "*" From 3ef01ec8a01934890c6e21f08de3d7c88e0230c1 Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 14 Jul 2026 09:31:21 -0500 Subject: [PATCH 4/8] Add summary of compiled packaging --- content/other-tools/02_pixi_build.md | 120 ++++++++++++++++++ .../5_02_pixi_build/compiled/pyproject.toml | 4 - 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/content/other-tools/02_pixi_build.md b/content/other-tools/02_pixi_build.md index 0e2a7b0..9bc3b80 100644 --- a/content/other-tools/02_pixi_build.md +++ b/content/other-tools/02_pixi_build.md @@ -7,6 +7,8 @@ To learn the sections and functionalities by example rather than by inspection o ## Basic Packaging +### Configuring the Pixi manifest + Take the example Python package directory tree from [Making a basic package](https://scikit-build.org/SIMPLE-Py/package/) as a starting foundation. ```bash @@ -225,3 +227,121 @@ pixi publish --clean --target-channel https://prefix.dev/ :::: ## Compiled Packaging + +### Configuring the Pixi manifest + +Take the example Python package directory tree from [A minimal compiled package with scikit-build](https://scikit-build.org/SIMPLE-Py/compiled) as a starting foundation. + +```bash +cp -R ./examples/2_01_package/collatz /tmp/compiled +cd /tmp/compiled +``` + +Next, create a Pixi manifest as a `pyproject.toml` `[tool.pixi]` table. + +```bash +pixi init --format pyproject +``` + +```{code} toml +:filename: pyproject.toml +:linenos: +:emphasize-lines: 13-16 +[build-system] +requires = ["scikit-build-core", "pybind11"] +build-backend = "scikit_build_core.build" + +[project] +name = "collatz" +version = "0.1.0" + +[tool.pixi.workspace] +channels = ["conda-forge"] +platforms = ["linux-64"] + +[tool.pixi.pypi-dependencies] +collatz = { path = ".", editable = true } + +[tool.pixi.tasks] +``` + +Now, enable the Pixi Build preview feature + +```toml +preview = ["pixi-build"] +``` + +and add the platforms you might want to support (like normal) + +```bash +pixi workspace platform add linux-64 osx-64 win-64 osx-arm64 linux-aarch64 +``` + +change `collatz` from a Python package dependency to a conda package dependency + +```diff +-[tool.pixi.pypi-dependencies] +-collatz = { path = ".", editable = true } ++[tool.pixi.dependencies] ++collatz = { path = "." } +``` + +add a `[package]` TOML table + +```toml +[tool.pixi.package] +name = "collatz" +version = "0.1.0" +``` + +add the Python build backend to the `[package.build.backend]` table. + +```toml +[tool.pixi.package.build.backend] +name = "pixi-build-python" +version = "0.*" +``` + +As we are using compilers we need to tell Pixi Build the compiler types that we require, and it can figure out the rest. +We can also set `ignore-pypi-mapping` to automatically enable PyPI-to-conda name mapping (which somewhat confusingly happens under `false`) to not have to redefine the `host` dependencies. + +```toml +[tool.pixi.package.build.config] +# c.f. https://pixi.prefix.dev/latest/build/backends/pixi-build-python/#compilers +# c.f. https://pixi.prefix.dev/latest/build/backends/pixi-build-python/#ignore-pypi-mapping +compilers = ["cxx"] +ignore-pypi-mapping = false # Enable automatic PyPI-to-conda mapping + +... + +# Unneeded given package.build.config.ignore-pypi-mapping = false +# [tool.pixi.package.host-dependencies] +# scikit-build-core = "*" +# pybind11 = "*" +``` + +Then add the the necessary `build` requirements. + +```toml +[tool.pixi.package.build-dependencies] +cmake = "*" +ninja = "*" +``` + +Finally, we want to take advantage of `scikit-build-core`'s defaults of using Ninja. +`rattler-build` (through `pixi-build-python`) exports `CMAKE_GENERATOR='Unix Makefiles'` as a default behavior, which overrides `scikit-build-core`'s default of Ninja.[^1] +To restore the default behavior provide `scikit-build-core` explicit arguments. + +```toml +[tool.scikit-build] +# c.f. https://github.com/prefix-dev/rattler-build/issues/2487 +cmake.args = ["-GNinja"] +``` + +```{literalinclude} ../../examples/5_02_pixi_build/compiled/pyproject.toml +:filename: pyproject.toml +:linenos: +:emphasize-lines: 15-17, 19-38 +``` + +[^1]: c.f. diff --git a/examples/5_02_pixi_build/compiled/pyproject.toml b/examples/5_02_pixi_build/compiled/pyproject.toml index 68b6b03..9fffed4 100644 --- a/examples/5_02_pixi_build/compiled/pyproject.toml +++ b/examples/5_02_pixi_build/compiled/pyproject.toml @@ -13,10 +13,6 @@ platforms = ["linux-64", "win-64", "osx-arm64", "linux-aarch64"] preview = ["pixi-build"] [tool.scikit-build] -# rattler-build (through pixi-build-python) exports -# CMAKE_GENERATOR='Unix Makefiles' as a default behavior, which overrides -# scikit-build-core's default of Ninja. To override this and restore the -# default behavior provide scikit-build-core explicit arguments. # c.f. https://github.com/prefix-dev/rattler-build/issues/2487 cmake.args = ["-GNinja"] From 92d6d3436f5dcf5d511824211dc7e1f164da2205 Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 14 Jul 2026 09:37:04 -0500 Subject: [PATCH 5/8] Add build exercise --- content/other-tools/02_pixi_build.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/content/other-tools/02_pixi_build.md b/content/other-tools/02_pixi_build.md index 9bc3b80..865caa0 100644 --- a/content/other-tools/02_pixi_build.md +++ b/content/other-tools/02_pixi_build.md @@ -344,4 +344,28 @@ cmake.args = ["-GNinja"] :emphasize-lines: 15-17, 19-38 ``` +So in just over 20 lines of TOML, we can build a conda package for a Python package with compiled extensions! + +::::{exercise} Build and install the conda package +:label: build-and-install-collatz + +Build `collatz` as a conda package and install it into your Pixi workspace environment. + +:::{solution} build-and-install-collatz +:class: dropdown + +```bash +pixi install +``` + +You can verify with + +```bash +pixi list -x +``` + +::: + +:::: + [^1]: c.f. From 9ae25cabb7f881db8df28fc08a47fd7d4e96fb13 Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 14 Jul 2026 09:41:27 -0500 Subject: [PATCH 6/8] Add publishing exercise --- content/other-tools/02_pixi_build.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/content/other-tools/02_pixi_build.md b/content/other-tools/02_pixi_build.md index 865caa0..1ecdf4c 100644 --- a/content/other-tools/02_pixi_build.md +++ b/content/other-tools/02_pixi_build.md @@ -368,4 +368,21 @@ pixi list -x :::: +::::{exercise} Build a conda package archive +:label: publish-collatz + +Build `collatz` as a local conda package archive and publish it to a local channel and inspect it. + +:::{solution} publish-collatz +:class: dropdown + +```bash +pixi publish --clean --target-channel /tmp/local-channel +rattler-build package inspect /tmp/local-channel/collatz*.conda +``` + +::: + +:::: + [^1]: c.f. From 9aa2b5af9b9db2915194d94df39bb07b5a6cb504 Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 14 Jul 2026 09:48:00 -0500 Subject: [PATCH 7/8] Update --- content/other-tools/02_pixi_build.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/content/other-tools/02_pixi_build.md b/content/other-tools/02_pixi_build.md index 1ecdf4c..fddd451 100644 --- a/content/other-tools/02_pixi_build.md +++ b/content/other-tools/02_pixi_build.md @@ -228,8 +228,6 @@ pixi publish --clean --target-channel https://prefix.dev/ ## Compiled Packaging -### Configuring the Pixi manifest - Take the example Python package directory tree from [A minimal compiled package with scikit-build](https://scikit-build.org/SIMPLE-Py/compiled) as a starting foundation. ```bash @@ -356,6 +354,7 @@ Build `collatz` as a conda package and install it into your Pixi workspace envir ```bash pixi install +pixi run python -c 'from collatz import collatz_steps; print(collatz_steps(27))' ``` You can verify with @@ -378,7 +377,7 @@ Build `collatz` as a local conda package archive and publish it to a local chann ```bash pixi publish --clean --target-channel /tmp/local-channel -rattler-build package inspect /tmp/local-channel/collatz*.conda +rattler-build package inspect /tmp/local-channel/linux-64/collatz*.conda ``` ::: From 3a4b160b47e7e8b16479b913429dcbbfddebe3f7 Mon Sep 17 00:00:00 2001 From: Matthew Feickert Date: Tue, 14 Jul 2026 10:01:19 -0500 Subject: [PATCH 8/8] Add prefix example --- content/other-tools/02_pixi_build.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/content/other-tools/02_pixi_build.md b/content/other-tools/02_pixi_build.md index fddd451..04e51f9 100644 --- a/content/other-tools/02_pixi_build.md +++ b/content/other-tools/02_pixi_build.md @@ -384,4 +384,30 @@ rattler-build package inspect /tmp/local-channel/linux-64/collatz*.conda :::: +::::{exercise} Install a conda package from a new channel +:label: prefix-channel-collatz + +`collatz` was published on the conda channel . + +```bash +pixi auth login --token prefix.dev +pixi publish --clean --target-channel https://prefix.dev/matthewfeickert +``` + +Create a new workspace and install from that channel. + +:::{solution} prefix-channel-collatz +:class: dropdown + +```bash +pixi init prefix-channel-example && cd prefix-channel-example +pixi workspace channel add https://prefix.dev/matthewfeickert +pixi add collatz +pixi list -x +``` + +::: + +:::: + [^1]: c.f.