docs/workspace/multi_platform_configuration.md
Pixi's vision includes being supported on all major platforms. Sometimes that needs some extra configuration to work well. On this page, you will learn what you can configure to align better with the platform you are making your application for.
Here is an example manifest file that highlights some of the features:
=== "pixi.toml"
```toml title="pixi.toml"
[workspace]
# Default workspace info....
# A list of platforms you are supporting with your package.
platforms = ["win-64", "linux-64", "osx-64", "osx-arm64"]
[dependencies]
python = ">=3.8"
[target.win-64.dependencies]
# Overwrite the needed python version only on win-64
python = "3.7"
[activation]
scripts = ["setup.sh"]
[target.win-64.activation]
# Overwrite activation scripts only for windows
scripts = ["setup.bat"]
```
=== "pyproject.toml"
```toml title="pyproject.toml"
[tool.pixi.workspace]
# Default workspace info....
# A list of platforms you are supporting with your package.
platforms = ["win-64", "linux-64", "osx-64", "osx-arm64"]
[tool.pixi.dependencies]
python = ">=3.8"
[tool.pixi.target.win-64.dependencies]
# Overwrite the needed python version only on win-64
python = "~=3.7.0"
[tool.pixi.activation]
scripts = ["setup.sh"]
[tool.pixi.target.win-64.activation]
# Overwrite activation scripts only for windows
scripts = ["setup.bat"]
```
The workspace.platforms defines which platforms your workspace supports.
When multiple platforms are defined, Pixi determines which dependencies to install for each platform individually.
All of this is stored in a lock file.
Running pixi install on a platform that is not configured will warn the user that it is not setup for that platform:
❯ pixi install
WARN Not installing dependency for (default) on current platform: (osx-arm64) as it is not part of this project's supported platforms.
A bare-string entry like "linux-64" is shorthand for "the conda subdir linux-64 with whatever virtual packages Pixi auto-detects on the host".
You can also describe a platform as an inline table to pin the virtual packages the solver should treat as available.
You can for example add a CUDA toolkit version or a glibc minimum version as a virtual package.
!!! info "Replaces [system-requirements]"
These inline-table entries are the recommended way to declare CUDA, glibc, macOS, archspec, and similar constraints. The older [system-requirements] table still parses but is deprecated; see Migrating from [system-requirements] for the equivalent forms.
[workspace]
platforms = [
"osx-arm64",
{ platform = "linux-64", cuda = "12.0", glibc = "2.28" },
{ name = "jetson-nano", platform = "linux-aarch64", cuda = "12.8" },
]
Each inline-table entry has:
platform: the conda subdir the entry targets (e.g. linux-64, osx-arm64). Required.
name: optional workspace-scoped identifier the platform is referenced by elsewhere (in feature.<name>.platforms, in lockfile rows, in CLI commands).
When omitted, Pixi synthesizes a name from platform plus the declared virtual packages, so two entries that declare the same set in different key order share the same identifier.
Friendly keys for the common virtual packages: cuda, archspec, glibc, linux, macos (alias osx), windows.
Each maps onto the matching __name conda virtual package (cuda -> __cuda, glibc -> __glibc, macos -> __osx, etc.).
cuda also accepts a { driver, arch } table that declares the CUDA driver
version (__cuda) together with the GPU compute capability (__cuda_arch):
platforms = [
{ name = "gpu", platform = "linux-64", cuda = { driver = "12.0", arch = "8.6" } },
]
driver is exactly equivalent to the bare cuda = "12.0" form. Per the
conda CEP, __cuda_arch is meaningless without __cuda, so arch requires
driver; declaring arch (or a raw __cuda_arch) alone is rejected.
For virtual packages without a friendly key, a raw __name = "version" entry is also accepted as an escape hatch. Only the virtual packages pixi knows how to override (__win, __osx, __linux, __cuda, __archspec, and the libc family __glibc/__musl/__eglibc) take effect at detection; any other raw __name is stored but ignored when checking host compatibility.
A feature's platforms array is a list of names that must each resolve to a workspace platform (or be a bare conda subdir, which Pixi treats as an alias for that subdir).
This is how you bind a feature to the rich variant:
[workspace]
platforms = [
"osx-arm64",
{ platform = "linux-64", cuda = "12.0" },
]
[feature.gpu]
platforms = ["linux-64-cuda-12-0"] # the synthesized name for the entry above
!!! note "Platform names in pixi.lock"
Rich platforms are written to pixi.lock under short aliases (p1, p2,
...) instead of their full names, to keep the lock file compact. Pixi maps
these back to the manifest entries by their contents (subdir plus declared
virtual packages) when the lock file is read, so the aliases never need to
be understood by hand. The real names stay in pixi.toml.
To get binaries optimized for the machine you are on, let Pixi detect it for you instead of writing the inline table by hand:
pixi workspace platform add --auto-detect
With --auto-detect, Pixi resolves the current subdir and the virtual packages it detects on the host (macOS version, glibc, archspec, CUDA, ...) into a concrete platform entry.
It inserts this platform first in platforms, so it wins platform selection on this machine.
Because it writes a normal entry to pixi.toml, the result is checked in and shared with everyone using the workspace.
# Give the detected platform a custom name instead of the synthesized one.
pixi workspace platform add my-laptop --auto-detect
# Override individual virtual packages on top of what was detected.
pixi workspace platform add --auto-detect --cuda 12.4
Pixi deduplicates by definition (subdir plus declared virtual packages), not by name: if an entry with the same definition already exists it is reused and moved to the front rather than duplicated. Adding a platform whose definition already exists under a different name is rejected: two names for one definition would only produce a redundant duplicate solve.
!!! tip "Trim it for portability"
Auto-detection captures your machine exactly, which is usually more specific than your packages actually need.
After installing, pixi info reports each environment's Minimum platform (the virtual packages some resolved dependency really requires), so you can see which ones are safe to drop with pixi workspace platform edit.
pixi workspace platform is the CLI surface for these entries:
pixi workspace platform add <PLATFORM> [--cuda 12.0] [--cuda-arch 8.6] [--glibc 2.28] ...
appends bare subdirs or rich platforms (or the current machine via
--auto-detect, see above). --cuda-arch requires --cuda (or
an existing __cuda) and serializes as cuda = { driver, arch }.pixi workspace platform edit <NAME> [--cuda 12.1] [--remove-virtual-package __glibc] mutates a custom platform's declared virtual packages.pixi workspace platform move <NAME> --to-top | --to-bottom | --before <NAME> | --after <NAME> reorders an entry; since order is selection priority, this is how you promote or demote a platform.pixi workspace platform list inspects what is declared.pixi workspace platform remove <NAME> drops an entry.The mutating subcommands keep pixi.lock in sync.
With the target specifier, you can overwrite the original configuration specifically for a single platform.
If you are targeting a specific platform in your target specifier that was not specified in your workspace.platforms then Pixi will throw an error.
It might happen that you want to install a certain dependency only on a specific platform, or you might want to use a different version on different platforms.
[dependencies]
python = ">=3.8"
[target.win-64.dependencies]
msmpi = "*"
python = "3.8"
In the above example, we specify that we depend on msmpi only on Windows.
We also specifically want python on 3.8 when installing on Windows.
This will overwrite the dependencies from the generic set of dependencies.
This will not touch any of the other platforms.
You can use pixi's CLI to add these dependencies to the manifest file.
pixi add --platform win-64 posix
This also works for the host and build dependencies.
pixi add --host --platform win-64 posix
pixi add --build --platform osx-64 clang
Which results in this.
[target.win-64.host-dependencies]
posix = "1.0.0.*"
[target.osx-64.build-dependencies]
clang = "16.0.6.*"
Pixi's vision is to enable completely cross-platform workspaces, but you often need to run tools that are not built by your projects.
Generated activation scripts are often in this category, default scripts in unix are bash and for windows they are bat
To deal with this, you can define your activation scripts using the target definition.
[activation]
scripts = ["setup.sh", "local_setup.bash"]
[target.win-64.activation]
scripts = ["setup.bat", "local_setup.bat"]
When this workspace is used on win-64 it will only execute the target scripts not the scripts specified in the default activation.scripts
When several workspace platforms share configuration, you can match them with a * wildcard in the target selector instead of repeating each block.
The pattern is matched against the platform name, so it is most useful together with custom platform names:
[workspace]
platforms = [
{ name = "cuda-win-64", platform = "win-64", cuda = "12" },
{ name = "cuda-linux-64", platform = "linux-64", cuda = "12" },
"win-64",
"linux-64",
]
[target."cuda-*".tasks]
test = "python test.py --cuda"
train = "python train.py --cuda"
Here both cuda-win-64 and cuda-linux-64 pick up the test and train tasks, while the bare win-64 and linux-64 platforms do not.
A few details:
* is the only metacharacter and matches any run of characters. Patterns are matched in full and are case-sensitive (cuda-*, *-64, *cuda*).[target.linux] and [target.linux-64] already combine. Place a specific [target.cuda-win-64] override after the [target."cuda-*"] block.[package.target] and [package.build.target], which resolve by subdir.