文章

项目环境管理的小天使—Pixi

pixi

项目环境管理的小天使—Pixi

Pixi 简介

Pixi 是一个基于 Conda 生态的跨平台包管理与开发环境管理工具。

它可以用来管理:

  • Python 环境
  • C/C++ 编译器
  • CMake、Ninja 等构建工具
  • Eigen、Assimp、FCL、OpenCV 等 C/C++ 库
  • 项目任务,例如构建、测试、运行命令

可以把 Pixi 理解为:

一个面向项目的环境管理工具,类似于 Conda + Makefile + npm scripts 的组合。

Pixi 适合用于:

  • C/C++ 项目
  • CMake 项目
  • Python 项目
  • 机器人开发项目
  • 科学计算项目
  • 多语言混合项目
  • 需要可复现环境的项目

Pixi 主要解决的问题

传统安装依赖时,可能会使用:

1
2
sudo apt install cmake ninja-build libeigen3-dev libassimp-dev
pip install numpy

这种方式的问题是:

  1. 依赖安装到系统目录,容易污染系统环境;
  2. 不同项目之间的依赖版本可能冲突;
  3. 换电脑后很难完全复现环境;
  4. Windows、Linux、macOS 的安装方式不统一;
  5. 系统仓库中的软件版本可能较旧;
  6. aptpip、源码编译混合使用时不容易管理。

使用 Pixi 后,可以把依赖统一写入 pixi.toml

1
2
3
4
5
6
7
8
9
10
11
[workspace]
channels = ["conda-forge"]
platforms = ["linux-64"]

[dependencies]
cmake = ">=3.30"
ninja = "*"
eigen = "*"
assimp = "*"
python = "3.12.*"
numpy = "*"

其他人拿到项目后,只需要执行:

1
pixi install

即可安装一致的开发环境。


Pixi 项目结构

一个典型 Pixi 项目结构如下:

1
2
3
4
5
6
my_project/
├── pixi.toml
├── pixi.lock
├── CMakeLists.txt
├── include/
└── src/

各部分作用如下:

文件或目录作用
pixi.tomlPixi 的项目配置文件,用来声明依赖、平台和任务
pixi.lock锁定实际安装的依赖版本,用于环境复现
.pixi/Pixi 创建的本地环境目录,一般不提交到 Git
CMakeLists.txtCMake 项目的构建配置文件
src/源代码目录
include/头文件目录

推荐提交到 Git:

1
2
pixi.toml
pixi.lock

推荐忽略:

1
2
.pixi/
build/

pixi.toml 配置文件

pixi.toml 是 Pixi 项目的核心配置文件。

它通常包含三部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[workspace]
name = "path-planner"
channels = ["conda-forge"]
platforms = ["linux-64"]

[dependencies]
cmake = ">=3.28"
ninja = "*"
eigen = "*"
assimp = "*"

[tasks]
configure = "cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release"
build = "cmake --build build"
clean = "cmake -E remove_directory build"

主要部分说明:

配置项作用
[workspace]描述项目名称、平台、包源等信息
[dependencies]声明项目依赖
[tasks]定义常用命令,例如构建、测试、运行

workspace 配置

[workspace] 用来描述整个项目。

示例:

1
2
3
4
5
[workspace]
name = "path-planner"
version = "0.1.0"
channels = ["conda-forge"]
platforms = ["linux-64"]

常见字段:

字段作用
name项目名称
version项目版本
channels使用的 Conda 包源
platforms支持的平台

常用平台:

1
2
3
4
5
6
platforms = [
    "linux-64",
    "win-64",
    "osx-64",
    "osx-arm64"
]

dependencies 配置

[dependencies] 用来声明项目依赖。

示例:

1
2
3
4
5
6
7
[dependencies]
cmake = ">=3.28"
ninja = "*"
eigen = ">=3.4"
assimp = "*"
python = "3.12.*"
numpy = "*"

版本写法:

写法含义
cmake = "*"任意版本
cmake = ">=3.28"版本大于等于 3.28
python = "3.12.*"使用 Python 3.12 系列
eigen = ">=3.4"Eigen 版本大于等于 3.4

添加依赖:

1
pixi add cmake ninja eigen

添加指定版本依赖:

1
pixi add "cmake>=3.28"

删除依赖:

1
pixi remove eigen

查看依赖:

1
pixi list

搜索依赖:

1
pixi search fcl

tasks 配置

[tasks] 用来定义项目常用命令。

例如:

1
2
3
4
5
6
[tasks]
configure = "cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release"
build = "cmake --build build --parallel"
test = "ctest --test-dir build --output-on-failure"
run = "./build/path_planner"
clean = "cmake -E remove_directory build"

执行任务:

1
2
3
4
5
pixi run configure
pixi run build
pixi run test
pixi run run
pixi run clean

使用 task 的好处:

  • 不需要重复输入很长的命令;
  • 构建流程固定,方便复现;
  • 团队成员使用同一套命令;
  • 适合 CI 自动化构建。

带依赖关系的 task

Pixi 的任务可以设置依赖关系。

示例:

1
2
3
4
5
6
7
8
9
10
[tasks.configure]
cmd = "cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release"

[tasks.build]
cmd = "cmake --build build --parallel"
depends-on = ["configure"]

[tasks.test]
cmd = "ctest --test-dir build --output-on-failure"
depends-on = ["build"]

执行:

1
pixi run test

会自动按照顺序执行:

1
configure → build → test

Pixi 环境目录

Pixi 会在项目目录下创建隔离环境。

默认环境位置一般是:

1
.pixi/envs/default/

这个环境中包含:

  • 可执行程序
  • 头文件
  • 动态库
  • 静态库
  • Python 包
  • CMake 配置文件

例如:

1
2
3
.pixi/envs/default/include/
.pixi/envs/default/lib/
.pixi/envs/default/bin/

当使用下面命令时:

1
pixi run build

Pixi 会自动进入对应环境并执行命令。


pixi.lock 锁文件

pixi.toml 描述依赖要求,例如:

1
cmake = ">=3.28"

pixi.lock 记录最终实际安装的精确版本。

二者区别如下:

文件作用
pixi.toml描述项目需要哪些依赖
pixi.lock锁定实际解析出来的依赖版本
.pixi/实际安装的环境目录

通常建议:

  • 提交 pixi.toml
  • 提交 pixi.lock
  • 不提交 .pixi/

这样其他人可以复现相同环境。


Pixi 常用命令

初始化项目

1
pixi init

安装环境

1
pixi install

添加依赖

1
pixi add cmake ninja eigen

添加指定版本依赖

1
2
pixi add "python=3.12"
pixi add "cmake>=3.28"

添加 PyPI 依赖

1
pixi add --pypi requests

删除依赖

1
pixi remove eigen

查看已安装依赖

1
pixi list

搜索依赖

1
pixi search fcl

执行命令

1
2
pixi run cmake --version
pixi run python --version

执行 task

1
2
pixi run build
pixi run test

进入 Pixi 环境

1
pixi shell

退出环境

1
exit

更新依赖

1
pixi update

pixi install、pixi add 和 pixi update 的区别

命令作用
pixi add添加新的依赖
pixi install根据现有配置安装环境
pixi update更新已有依赖

示例:

添加依赖:

1
pixi add eigen

根据配置安装环境:

1
pixi install

更新依赖:

1
pixi update

一般使用流程是:

1
2
3
4
pixi init
pixi add cmake ninja eigen
pixi install
pixi run build

Conda 包和 PyPI 包

Pixi 可以同时管理 Conda 包和 PyPI 包。

Conda 包写在:

1
2
3
4
[dependencies]
python = "3.12.*"
numpy = "*"
cmake = "*"

PyPI 包写在:

1
2
[pypi-dependencies]
requests = "*"

添加 Conda 包:

1
pixi add numpy

添加 PyPI 包:

1
pixi add --pypi requests

一般建议:

  • NumPy、SciPy、PyTorch、OpenCV 等底层依赖复杂的包,优先使用 Conda 包;
  • 纯 Python 包可以使用 PyPI 包。

Pixi 和 Conda 的区别

Pixi 和 Conda 都使用 Conda 包生态,但使用方式不同。

Conda 常见方式:

1
2
conda create -n planner python=3.12 cmake eigen
conda activate planner

Pixi 常见方式:

1
2
3
cd path_planner
pixi install
pixi run build

对比:

对比项CondaPixi
环境组织方式命名环境项目环境
配置文件environment.ymlpixi.toml
锁文件通常需要额外工具原生支持 pixi.lock
任务系统无内置任务系统内置 [tasks]
使用方式偏环境管理偏项目管理

Pixi 和 apt 的区别

对比项Pixiapt
安装范围项目级或用户级系统级
是否需要 sudo通常不需要通常需要
版本隔离支持较弱
锁文件支持通常没有
跨平台Linux、Windows、macOS主要是 Debian/Ubuntu
环境复现较弱

系统驱动、内核模块、USB 规则、系统服务等仍然应该使用系统包管理器。


Pixi 和 pip 的区别

对比项Pixipip
Python 包支持支持
C/C++ 系统库支持通常不适合
编译器支持不支持
多语言项目支持主要面向 Python
锁文件支持需要额外工具
二进制依赖管理较强取决于 wheel

Pixi 和 Conan / vcpkg 的关系

Pixi、Conan 和 vcpkg 都可以管理 C/C++ 相关依赖,但定位不同。

Conan / vcpkg 更关注:

  • C/C++ 库依赖
  • ABI 管理
  • 编译选项
  • 源码构建
  • 与 CMake 集成

Pixi 更关注:

  • 整个开发环境
  • 编译器
  • CMake / Ninja
  • Python
  • 预编译 C/C++ 库
  • 任务运行

可以组合使用:

1
2
Pixi 管理编译器、CMake、Python、Conan
Conan 管理项目中的 C++ 库

示例:

1
2
3
4
5
6
7
8
[dependencies]
cmake = "*"
ninja = "*"
cxx-compiler = "*"
python = "3.12.*"

[pypi-dependencies]
conan = "*"

Pixi 在 CMake 项目中的用法

对于 C++ / CMake 项目,可以使用如下配置:

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
[workspace]
name = "path-planner"
channels = ["conda-forge"]
platforms = ["linux-64"]

[dependencies]
cmake = ">=3.28"
ninja = "*"
cxx-compiler = "*"
eigen = "*"
assimp = "*"

[tasks.configure]
cmd = """
cmake -S . -B build \
  -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
"""

[tasks.build]
cmd = "cmake --build build --parallel"
depends-on = ["configure"]

[tasks.clean]
cmd = "cmake -E remove_directory build"

使用流程:

1
2
pixi install
pixi run build

CMake 中查找 Pixi 安装的库

CMakeLists.txt 中可以正常使用:

1
2
find_package(Eigen3 REQUIRED)
find_package(assimp REQUIRED)

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cmake_minimum_required(VERSION 3.20)

project(path_planner LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Eigen3 REQUIRED)
find_package(assimp REQUIRED)

add_executable(path_planner
    src/main.cpp
)

target_link_libraries(path_planner
    PRIVATE
        Eigen3::Eigen
        assimp::assimp
)

如果 CMake 找不到库,可以查看 Pixi 环境路径:

1
pixi run echo $CONDA_PREFIX

查找 CMake 配置文件:

1
pixi run find "$CONDA_PREFIX" -iname "*config.cmake"

查找 FCL 配置文件:

1
pixi run find "$CONDA_PREFIX" -iname "*fcl*config*.cmake"

C/C++ 编译器配置

跨平台项目推荐使用:

1
2
3
[dependencies]
c-compiler = "*"
cxx-compiler = "*"

如果明确要求 Linux 下的 GCC,可以使用:

1
2
3
[dependencies]
gcc_linux-64 = "13.*"
gxx_linux-64 = "13.*"

一般建议:

场景推荐写法
跨平台 C/C++ 项目c-compilercxx-compiler
明确要求 GCC 版本gcc_linux-64gxx_linux-64
明确要求 Clang使用对应的 clang 包

FCL 项目示例

如果项目使用 CMake、Eigen、Assimp 和 FCL,可以尝试如下配置:

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
[workspace]
name = "path-planner"
channels = ["conda-forge"]
platforms = ["linux-64"]

[dependencies]
cmake = ">=3.28"
ninja = "*"
cxx-compiler = "*"
eigen = ">=3.4"
assimp = "*"
fcl = "*"

[tasks.configure]
cmd = """
cmake -S . -B build \
  -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
"""

[tasks.build]
cmd = "cmake --build build --parallel"
depends-on = ["configure"]

[tasks.run]
cmd = "./build/path_planner"
depends-on = ["build"]

[tasks.clean]
cmd = "cmake -E remove_directory build"

使用:

1
2
3
pixi install
pixi run build
pixi run run

CMake 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cmake_minimum_required(VERSION 3.20)

project(path_planner LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Eigen3 REQUIRED)
find_package(assimp REQUIRED)
find_package(fcl REQUIRED)

add_executable(path_planner
    src/main.cpp
)

target_link_libraries(path_planner
    PRIVATE
        Eigen3::Eigen
        assimp::assimp
        fcl
)

FCL 的 CMake target 名称可能因包而异,可能是:

1
fcl

也可能是:

1
FCL::fcl

可以通过下面命令检查:

1
pixi run find "$CONDA_PREFIX" -iname "*fcl*config*.cmake"

Pixi 的优点

Pixi 的主要优点:

  1. 项目环境隔离,不容易污染系统;
  2. 支持锁文件,方便环境复现;
  3. 不只管理 Python,也能管理 C/C++ 工具和库;
  4. 通常不需要 sudo;
  5. 支持 Linux、Windows、macOS;
  6. 内置 task 系统,方便统一构建命令;
  7. 适合团队协作和 CI 构建。

Pixi 的局限

Pixi 的局限:

  1. Conda 仓库中不一定有所有库;
  2. 某些库的包名、CMake 名称和系统包名可能不同;
  3. 预编译包不一定满足特殊编译需求;
  4. 不能替代系统包管理器;
  5. 对嵌入式交叉编译、内核驱动等场景不一定合适。

例如 Eigen 的名称可能不同:

1
2
3
apt: libeigen3-dev
conda-forge: eigen
CMake: Eigen3

推荐使用场景

Pixi 适合:

  • C++ 与 Python 混合项目
  • CMake 项目
  • 机器人路径规划项目
  • 科学计算项目
  • 需要复现环境的项目
  • 多平台开发项目
  • 团队协作项目
  • CI 自动化构建

Pixi 不一定适合:

  • 只安装一个简单系统软件
  • 对编译参数有复杂定制的项目
  • 所需依赖不在 Conda 生态中
  • 嵌入式交叉编译项目
  • 内核模块或驱动开发

总结

Pixi 是一个面向项目的开发环境管理工具。

它的核心作用是:

1
依赖隔离 + 环境复现 + 跨平台 + 任务管理

对于 CMake / C++ / Python 混合项目,Pixi 可以管理:

1
编译器、CMake、Ninja、Eigen、Assimp、FCL、Python、NumPy

典型使用流程:

1
2
3
pixi init
pixi add cmake ninja cxx-compiler eigen assimp
pixi run build

推荐提交:

1
2
pixi.toml
pixi.lock

推荐忽略:

1
2
.pixi/
build/

其他人克隆项目后,只需要执行:

1
2
pixi install
pixi run build

即可复现环境并构建项目。

本文由作者按照 CC BY 4.0 进行授权