任务
在构建一个包时,通常不仅仅是运行代码。 格式化、代码检查、编译、测试、基准测试等步骤常常是项目的一部分。 使用 pixi 任务,这些操作应该变得更加容易。
以下是一些快速示例:
[tasks]
# 作为列表的命令,以便你可以在其中添加文档。
configure = { cmd = [
"cmake",
# 使用跨平台的 Ninja 生成器
"-G",
"Ninja",
# 源代码在根目录
"-S",
".",
# 我们希望在 .build 目录中构建
"-B",
".build",
] }
# 依赖于其他任务
build = { cmd = ["ninja", "-C", ".build"], depends-on = ["configure"] }
# 使用环境变量
run = "python main.py $PIXI_PROJECT_ROOT"
set = "export VAR=hello && echo $VAR"
# 跨平台文件操作
copy = "cp pixi.toml pixi_backup.toml"
clean = "rm pixi_backup.toml"
move = "mv pixi.toml backup.toml"
依赖于#
就像包可以依赖于其他包一样,我们的任务也可以依赖于其他任务。 这允许通过一个命令运行完整的流水线。
一个明显的例子是 编译 在 运行 应用程序之前。
查看我们的 cpp_sdl
示例 了解实际的例子。
在这个包中,我们有一些任务相互依赖,这样可以确保当你运行 pixi run start
时,一切都会按预期设置。
pixi task add configure "cmake -G Ninja -S . -B .build"
pixi task add build "ninja -C .build" --depends-on configure
pixi task add start ".build/bin/sdl_example" --depends-on build
这将导致以下行被添加到 pixi.toml
文件中:
[tasks]
# 配置 CMake
configure = "cmake -G Ninja -S . -B .build"
# 构建可执行文件,但确保首先配置了 CMake。
build = { cmd = "ninja -C .build", depends-on = ["configure"] }
# 启动构建的可执行文件
start = { cmd = ".build/bin/sdl_example", depends-on = ["build"] }
任务将依次执行:
- 首先执行
configure
,因为它没有依赖项。 - 然后执行
build
,因为它只依赖于configure
。 - 最后执行
start
,因为它的所有依赖项都已执行。
如果其中一个命令失败(退出时返回非零代码),它将停止,并且下一个命令将不会被执行。
使用这种逻辑,你还可以创建别名,因为你不必在任务中指定任何命令。
这将导致以下内容添加到 pixi.toml
中:
现在,可以通过一个命令运行两个工具。
工作目录#
Pixi 任务支持定义工作目录。
cwd
代表当前工作目录(Current Working Directory)。
该目录是相对于 pixi 包根目录(即 pixi.toml
文件所在的目录)。
假设一个 pixi 项目结构如下:
要添加一个任务来运行 bar.py
文件,可以使用:
这将添加以下行到 清单文件 中:
缓存#
当你为任务指定了 inputs
和/或 outputs
时,pixi 会重用该任务的结果。
对于缓存,pixi 会检查以下条件是否成立:
- 环境中的包没有发生变化。
- 选定的输入和输出与上次运行任务时相同。我们会计算所有由 glob 表达式选中的文件的指纹,并与上次运行任务时的指纹进行比较。
- 命令与上次运行任务时相同。
如果满足所有这些条件,pixi 将不会重新运行任务,而是使用现有的结果。
输入和输出可以通过 glob 表达式来指定,这样它们会扩展为所有匹配的文件。
[tasks]
# 只有当 `main.py` 文件发生变化时,这个任务才会运行。
run = { cmd = "python main.py", inputs = ["main.py"] }
# 这个任务会记住 `curl` 命令的结果,如果文件 `data.csv` 已经存在,则不会再次运行。
download_data = { cmd = "curl -o data.csv https://example.com/data.csv", outputs = ["data.csv"] }
# 只有当 `src` 目录发生变化时,这个任务才会运行,并且会记住 `make` 命令的结果。
build = { cmd = "make", inputs = ["src/*.cpp", "include/*.hpp"], outputs = ["build/app.exe"] }
注意:如果你想调试 glob 表达式,可以使用 --verbose
标志查看选中的文件。
环境变量#
你可以为任务设置环境变量。 这些变量被视为该任务的“默认”值,你可以从 shell 中覆盖它们。
如果你运行pixi run echo
,它会输出 hello
。
当你在运行任务之前设置了环境变量 ARGUMENT
时,它将使用该值。
这些变量不会在任务之间共享,因此你需要为每个任务单独定义你希望使用的变量。
扩展而非覆盖
如果你在映射的值和键中使用相同的环境变量,它将覆盖该变量。
例如,覆盖 PATH
:
这将输出 /tmp/path:/usr/bin:/bin
,而不是原始的 /usr/bin:/bin
。
清洁环境#
你可以确保任务的环境是“仅 Pixi”环境。
在这种情况下,pixi 只会包含运行命令所需的最小环境变量,这些变量取决于你的平台。
环境将包含由 conda 环境设置的所有变量,如 "CONDA_PREFIX"
。
然而,它还会包含一些来自 shell 的默认值,如:
"DISPLAY"
、"LC_ALL"
、"LC_TIME"
、"LC_NUMERIC"
、"LC_MEASUREMENT"
、"SHELL"
、"USER"
、"USERNAME"
、"LOGNAME"
、"HOME"
、"HOSTNAME"
、"TMPDIR"
、"XPC_SERVICE_NAME"
、"XPC_FLAGS"
此设置也可以通过命令行中的 pixi run --clean-env TASK_NAME
来设置。
clean-env
在 Windows 上不支持
在 Windows 上创建一个“干净的环境”比较困难,因为 conda-forge
没有提供 Windows 编译器,且 Windows 需要大量的基础变量。
由于边缘情况太多,这使得该功能不值得实现,可能会导致不可用。
我们的任务执行器:deno_task_shell#
为了支持不同的操作系统(Windows、OSX 和 Linux),pixi 集成了一个可以在所有这些系统上运行的 shell。
这个 shell 是 deno_task_shell
。
任务 shell 是一个有限实现的 Bourne-shell 接口。
内置命令#
除了运行实际的可执行文件如 ./myprogram
、cmake
或 python
,该 shell 还提供了一些内置命令。
cp
:复制文件。mv
:移动文件。rm
:删除文件或目录。 示例:rm -rf [FILE]...
- 常用来递归删除文件或目录。mkdir
:创建目录。 示例:mkdir -p DIRECTORY...
- 常用来创建目录及其所有父目录,且若目录已存在则不报错。pwd
:打印当前/工作目录的名称。sleep
:延迟指定的时间。 示例:sleep 1
睡眠 1 秒,sleep 0.5
睡眠半秒,或sleep 1m
睡眠 1 分钟。echo
:显示一行文本。cat
:连接文件并输出到标准输出。当没有提供参数时,它读取并输出标准输入。exit
:导致 shell 退出。unset
:取消环境变量。xargs
:从标准输入构建参数并执行命令。
语法#
- 布尔列表: 使用
&&
或||
来分隔两个命令。&&
:如果&&
前的命令成功,则继续执行下一个命令。||
:如果||
前的命令失败,则继续执行下一个命令。
- 顺序列表: 使用
;
来运行两个命令,而不检查第一个命令是否成功或失败。 - 环境变量:
- 设置环境变量:
export ENV_VAR=value
- 使用环境变量:
$ENV_VAR
- 取消设置环境变量:
unset ENV_VAR
- 设置环境变量:
- Shell 变量: Shell 变量类似于环境变量,但不会被导出到派生的命令中。
- 设置变量:
VAR=value
- 使用变量:
VAR=value && echo $VAR
- 设置变量:
- 管道: 将一个命令的标准输出传递给后续命令的标准输入。
|
:echo Hello | python receiving_app.py
|&
:使用这个符号可以将标准错误输出也作为输入。
- 命令替换: 使用
$()
将一个命令的输出作为另一个命令的输入。python main.py $(git rev-parse HEAD)
- 否定退出码: 在任何命令前加上
!
将否定其退出码,1变为0,反之亦然。 - 重定向: 使用
>
将标准输出重定向到文件。echo hello > file.txt
会将hello
放入file.txt
并覆盖现有内容。python main.py 2> file.txt
会将标准错误输出放入file.txt
。python main.py &> file.txt
会将标准错误和标准输出都放入file.txt
。echo hello >> file.txt
会将hello
追加到现有的file.txt
文件中。
- Glob 扩展: 使用
*
来扩展所有选项。echo *.py
会显示所有以.py
结尾的文件名。echo **/*.py
会显示当前目录及所有子目录中以.py
结尾的文件名。echo data[0-9].csv
会显示所有在data
后面跟着一个数字且以.csv
结尾的文件名。
更多信息请参阅 deno_task_shell
文档。