Multiple Packages in Workspace
In this tutorial, we will show you how to integrate multiple Pixi packages into a single workspace.
Warning
pixi-build
is a preview feature, and will change until it is stabilized.
Please keep that in mind when you use it for your projects.
Why is This Useful?#
The packages coming from conda channels are already built and ready to use. If you want to depend on a package you therefore typically get that package from such a channel. However, there are situations where you want to depend on the source of a package. This is the case for example if you want to develop on multiple packages within the same repository. Or if you need the changes of an unreleased version of one of your dependencies.
Let's Get Started#
In this tutorial we will showcase how to develop two packages in one workspace.
For that we will use the python_rich
Python package developed in chapter Building a Python package and let it depend on the python_binding
C++ package developed in chapter Building a C++ package.
We will start with the original setup of python_rich
and copy python_binding
into a folder called packages
.
The source directory structure now looks like this:
.
├── packages
│ └── cpp_math
│ ├── CMakeLists.txt
│ ├── pixi.toml
│ └── src
│ └── math.cpp
├── pixi.lock
├── pixi.toml
├── pyproject.toml
└── src
└── python_rich
└── __init__.py
Within a Pixi manifest, you can manage a workspace and/or describe a package.
In the case of python_rich
we choose to do both, so the only thing we have to add is the dependency on the cpp_math
.
[workspace]
channels = [
"https://prefix.dev/pixi-build-backends",
"https://prefix.dev/conda-forge",
]
platforms = ["win-64", "linux-64", "osx-arm64", "osx-64"]
preview = ["pixi-build"]
[dependencies]
cpp_math = { path = "packages/cpp_math" }
python_rich = { path = "." }
We only want to use the workspace
table of the top-level manifest.
Therefore, we can remove the workspace section in the manifest of cpp_math
.
-[workspace]
-channels = [
- "https://prefix.dev/pixi-build-backends",
- "https://prefix.dev/conda-forge",
-]
-platforms = ["osx-arm64", "osx-64", "linux-64", "win-64"]
-preview = ["pixi-build"]
-
-[dependencies]
-cpp_math = { path = "." }
-
-[tasks]
-start = "python -c 'import cpp_math as b; print(b.add(1, 2))'"
There is actually one problem with python_rich
.
The age of every person is off by one year!
┏━━━━━━━━━━━━━━┳━━━━━┳━━━━━━━━━━━━━┓
┃ name ┃ age ┃ city ┃
┡━━━━━━━━━━━━━━╇━━━━━╇━━━━━━━━━━━━━┩
│ John Doe │ 30 │ New York │
│ Jane Smith │ 25 │ Los Angeles │
│ Tim de Jager │ 35 │ Utrecht │
└──────────────┴─────┴─────────────┘
We need to add one year to the age of every person.
Luckily cpp_math
exposes a function add
which allows us to do exactly that.
from dataclasses import dataclass, fields
from rich.console import Console
from rich.table import Table
import cpp_math
@dataclass
class Person:
name: str
age: int
city: str
def main() -> None:
console = Console()
people = [
Person("John Doe", 30, "New York"),
Person("Jane Smith", 25, "Los Angeles"),
Person("Tim de Jager", 35, "Utrecht"),
]
table = Table()
for column in fields(Person):
table.add_column(column.name)
for person in people:
updated_age = cpp_math.add(person.age, 1)
table.add_row(person.name, str(updated_age), person.city)
console.print(table)
If you run pixi run start
, the age of each person should now be accurate:
┏━━━━━━━━━━━━━━┳━━━━━┳━━━━━━━━━━━━━┓
┃ name ┃ age ┃ city ┃
┡━━━━━━━━━━━━━━╇━━━━━╇━━━━━━━━━━━━━┩
│ John Doe │ 31 │ New York │
│ Jane Smith │ 26 │ Los Angeles │
│ Tim de Jager │ 36 │ Utrecht │
└──────────────┴─────┴─────────────┘
Conclusion#
In this tutorial, we created a Pixi workspace containing two packages.
The manifest of python_rich
describes the workspace as well as the package, with cpp_math
only the package
section is used.
Feel free to add more packages, written in different languages to this workspace!
Thanks for reading! Happy Coding 🚀
Any questions? Feel free to reach out or share this tutorial on X, join our Discord, send us an e-mail or follow our GitHub.