1 个不稳定版本
使用旧的Rust 2015
0.0.0 | 2018年4月19日 |
---|
#13 in #positional-arguments
6KB
133 行
just
just
是保存和运行项目特定命令的便捷方式。
此说明文件也提供为 书籍。
(中文文档在 这里, 快看过来!)
命令,称为配方,存储在名为 justfile
的文件中,语法受 make
启发。
然后可以使用 just RECIPE
运行它们。
$ just test-all
cc *.c -o main
./test --all
Yay, all your tests passed!
just
具有许多有用的功能,并且在许多方面优于 make
。
-
just
是一个命令运行器,而不是构建系统,因此它避免了make
's 复杂性和怪癖。无需.PHONY
配方! -
支持Linux、MacOS和Windows,无需额外依赖。 (尽管如果您的系统没有
sh
,您将需要 选择不同的shell。) -
错误是具体且具有信息性的,并且语法错误会与其源上下文一起报告。
-
配方可以接受 命令行参数。
-
尽可能情况下,错误是静态解决的。在运行任何内容之前会报告未知配方和循环依赖。
-
just
加载.env
文件,使得填充环境变量变得容易。 -
可以从命令行 列出配方。
-
大多数流行shell的命令行完成脚本 可用。
-
配方可以用 任意语言 编写,如Python或NodeJS。
-
just
可以从任何子目录调用,而不仅仅是包含justfile
的目录。 -
还有 更多!
如果您需要帮助使用 just
,请随时创建一个 issue 或在 Discord 上联系我。欢迎提出功能请求和错误报告!
安装
先决条件
just
应该能在任何具有合理 sh
的系统上运行,包括 Linux、MacOS 和 BSD。
在 Windows 上,just
与 Git for Windows、GitHub Desktop 或 Cygwin 提供的 sh
一起工作。
如果您不想安装 sh
,您可以使用 shell
设置来使用您选择的 shell。
类似于 PowerShell
# use PowerShell instead of sh:
set shell := ["powershell.exe", "-c"]
hello:
Write-Host "Hello, world!"
…或者 cmd.exe
# use cmd.exe instead of sh:
set shell := ["cmd.exe", "/c"]
list:
dir
您也可以使用命令行参数来设置 shell。例如,要使用 PowerShell,请使用 --shell powershell.exe --shell-arg -c
启动 just
。
(PowerShell 默认安装在 Windows 7 SP1 及以后的系统上,而 cmd.exe
相对复杂,因此建议大多数 Windows 用户使用 PowerShell。)
包
操作系统 | 包管理器 | 包 | 命令 |
---|---|---|---|
Alpine Linux | apk-tools | just | apk add just |
Arch Linux | pacman | just | pacman -S just |
Debian 13 (未发布) 和 Ubuntu 24.04 衍生版 | apt | just | apt install just |
Debian 和 Ubuntu 衍生版 | MPR | just |
gitclone https://mpr.makedeb.org/just cdjust makedeb-si
|
Debian 和 Ubuntu 衍生版 | 预构建-MPR | just |
要运行此命令,您必须在系统上设置 预构建-MPR。apt install just
|
Fedora Linux | DNF | just | dnf install just |
FreeBSD | pkg | just | pkg install just |
Gentoo Linux | Portage | guru/dev-build/just |
eselect repository enable guru emerge--sync guru emerge dev-build/just
|
macOS | MacPorts | just | port install just |
Microsoft Windows | Chocolatey | just | choco install just |
Microsoft Windows | Scoop | just | scoop install just |
Microsoft Windows | Windows 包管理器 | Casey/Just | winget install--id Casey.Just--exact |
NixOS | Nix | just | nix-env-iA nixos.just |
openSUSE | Zypper | just | zypperinjust |
Solus | eopkg | just | eopkg install just |
各种 | asdf | just |
asdf plugin add just asdf install just<版本>
|
各种 | Cargo | just | cargoinstall just |
各种 | Conda | just | conda install-c conda-forge just |
各种 | Homebrew | just | brewinstall just |
各种 | Nix | just | nix-env-iA nixpkgs.just |
Void Linux | XBPS | just | xbps-install-S just |
预构建二进制文件
Linux、MacOS 和 Windows 的预构建二进制文件可以在 发布页面 上找到。
您可以在 Linux、MacOS 或 Windows 上使用以下命令下载最新版本,只需将 DEST
替换为您想放置 just
的目录即可
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to DEST
例如,要将 just
安装到 ~/bin
# create ~/bin
mkdir -p ~/bin
# download and extract just to ~/bin/just
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/bin
# add `~/bin` to the paths that your shell searches for executables
# this line should be added to your shells initialization file,
# e.g. `~/.bashrc` or `~/.zshrc`
export PATH="$PATH:$HOME/bin"
# just should now be executable
just --help
请注意,install.sh
在 GitHub Actions 或其他许多机器共享 IP 地址的环境中可能会失败。该脚本调用 GitHub API 以确定要安装的 just
的最新版本,而这些 API 调用是基于每个 IP 地址进行限流的。为了使 install.sh
在此类情况下更可靠,请使用 --tag
传递一个特定的标签进行安装。
GitHub Actions
just
可以通过几种方式在 GitHub Actions 上安装。
使用预先安装在 MacOS 上的包管理器 brew install just
,以及在 Windows 上使用 choco install just
。
- uses: extractions/setup-just@v1
with:
just-version: 1.5.0 # optional semver specification, otherwise latest
- uses: taiki-e/install-action@just
发布 RSS 源
just
发布的 RSS 源可通过 此处 获取。
Node.js 安装
just-install 可用于在 Node.js 应用程序中自动化安装 just
。
just
是一个优秀的、更健壮的 npm 脚本替代品。如果您想将 just
包含在 Node.js 应用程序的依赖项中,just-install
将作为 npm install
命令的一部分安装本地、平台特定的二进制文件。这消除了每个开发者都需要使用上述过程之一独立安装 just
的需求。安装后,just
命令将在 npm 脚本或 npx 中工作。这对希望使项目设置过程尽可能简单的团队来说非常棒。
有关更多信息,请参阅 just-install README 文件。
向后兼容性
随着 1.0 版本的发布,just
坚定了对向后兼容性和稳定性的承诺。
未来的版本不会引入使现有 justfile
无法工作或破坏命令行界面有效调用的向后不兼容的更改。
然而,这并不意味着不能修复明显的错误,即使这样做可能会破坏依赖于其行为的 justfiles
。
将永远不会有一个 just
2.0。任何希望进行向后不兼容更改的更改都将基于每个 justfile
选择性启用,因此用户可以自由迁移。
尚未准备好稳定化的功能位于 --unstable
标志之后。由 --unstable
启用的功能可能会在任何时候以向后不兼容的方式进行更改。通过将环境变量 JUST_UNSTABLE
设置为除 false
、0
或空字符串之外的其他任何值,也可以启用不稳定的功能。
编辑器支持
justfile
语法与 make
非常接近,您可能希望告诉您的编辑器使用 make
语法高亮显示 just
。
Vim 和 Neovim
vim-just
vim-just 插件为 justfile
提供语法高亮显示。
使用您喜欢的包管理器安装它,例如 Plug
call plug#begin()
Plug 'NoahTheDuke/vim-just'
call plug#end()
或使用 Vim 的内置包支持
mkdir -p ~/.vim/pack/vendor/start
cd ~/.vim/pack/vendor/start
git clone https://github.com/NoahTheDuke/vim-just.git
tree-sitter-just
tree-sitter-just 是为 Neovim 编写的 Nvim Treesitter 插件。
Makefile 语法高亮
Vim 内置的 makefile 语法高亮对于 justfile
并不是完美的,但总比没有好。你可以在 ~/.vim/filetype.vim
中添加以下内容
if exists("did_load_filetypes")
finish
endif
augroup filetypedetect
au BufNewFile,BufRead justfile setf make
augroup END
或者将以下内容添加到单个 justfile
中,以在单个文件上启用 make
模式
# vim: set ft=make :
Emacs
just-mode 为 justfile
提供语法高亮和自动缩进。它可在 MELPA 上找到,名为 just-mode。
justl 提供执行和列出配方命令。
你可以在单个 justfile
中添加以下内容以启用单个文件上的 make
模式
# Local Variables:
# mode: makefile
# End:
Visual Studio Code
VS Code 扩展可在此 处 获取。
不再维护的 VS Code 扩展包括 skellock/vscode-just 和 sclu1034/vscode-just。
JetBrains IDEs
由 linux_china 开发的 JetBrains IDEs 插件可在 此处 获取。
Kakoune
由于 TeddyDD 的贡献,Kakoune 支持 justfile
语法高亮。
Helix
自 23.05 版本起,Helix 支持内置的 justfile
语法高亮。
Sublime Text
由 nk9 开发的带有 just
语法和一些其他工具的 Just 包 可在 PackageControl 上找到。
Micro
由于 tomodachi94 的贡献,Micro 支持内置的 Justfile 语法高亮。
其他编辑器
请随意发送您在所选编辑器中启用语法高亮的必要命令,以便我可以在此处包含它们。
快速入门
有关如何在您的计算机上安装 just
的说明,请参阅 安装部分。尝试运行 just --version
以确保它已正确安装。
有关语法的概述,请查看 此速查表。
安装并运行 just
后,在项目的根目录中创建一个名为 justfile
的文件,并包含以下内容
recipe-name:
echo 'This is a recipe!'
# this is a comment
another-recipe:
@echo 'This is another recipe.'
just
在当前目录及其上方查找 justfile
文件,因此您可以从项目的任何子目录中调用它。
对 justfile
的搜索是不区分大小写的,因此任何大小写,如 Justfile
、JUSTFILE
或 JuStFiLe
都可以使用。just
还会查找名为 .justfile
的文件,以防您想隐藏 justfile
。
不使用参数运行 just
将运行 justfile
中的第一个配方
$ just
echo 'This is a recipe!'
This is a recipe!
一个或多个参数指定要运行的配方
$ just another-recipe
This is another recipe.
just
在执行命令之前会将其打印到标准错误,这就是为什么打印了 echo 'This is a recipe!'
的原因。对于以 @
开头的行,这会被抑制,这就是为什么 echo 'This is another recipe.'
没有打印出来的原因。
如果命令失败,食谱将停止运行。在这里,只有当 cargo test
成功时,cargo publish
才会运行
publish:
cargo test
# tests passed, time to publish!
cargo publish
食谱可以依赖于其他食谱。在这里,test
食谱依赖于 build
食谱,因此 build
会先于 test
运行
build:
cc main.c foo.c bar.c -o main
test: build
./test
sloc:
@echo "`wc -l *.c` lines of code"
$ just test
cc main.c foo.c bar.c -o main
./test
testing… all tests passed!
没有依赖的食谱将按照在命令行中给出的顺序运行
$ just build sloc
cc main.c foo.c bar.c -o main
1337 lines of code
依赖项总是先运行,即使它们在依赖于它们的食谱之后传递
$ just test build
cc main.c foo.c bar.c -o main
./test
testing… all tests passed!
示例
可以在 示例目录 中找到各种 justfile
。
特性
默认食谱
当 just
无食谱被调用时,它会运行 justfile
中的第一个食谱。这个食谱可能是项目中运行频率最高的命令,例如运行测试
test:
cargo test
您也可以使用依赖关系来默认运行多个食谱
default: lint build test
build:
echo Building…
test:
echo Testing…
lint:
echo Linting…
如果没有食谱适合作为默认食谱,您可以在 justfile
的开头添加一个食谱,列出可用的食谱
default:
just --list
列出可用的食谱
可以使用 just --list
按字母顺序列出食谱
$ just --list
Available recipes:
build
test
deploy
lint
可以使用 just --list PATH
列出子模块中的食谱,其中 PATH
是由空格或 ::
分隔的模块路径
$ cat justfile
mod foo
$ cat foo.just
mod bar
$ cat bar.just
baz:
$ just --unstable foo bar
Available recipes:
baz
$ just --unstable foo::bar
Available recipes:
baz
just --summary
更简洁
$ just --summary
build test deploy lint
传递 --unsorted
以按 justfile
中出现的顺序打印食谱
test:
echo 'Testing!'
build:
echo 'Building!'
$ just --list --unsorted
Available recipes:
test
build
$ just --summary --unsorted
test build
如果您希望 just
默认列出 justfile
中的食谱,您可以使用此作为默认食谱
default:
@just --list
请注意,您可能需要在上面的行中添加 --justfile {{justfile()}}
。如果没有它,如果您执行了 just -f /some/distant/justfile -d .
或 just -f ./non-standard-justfile
,食谱内部的普通 just --list
不一定会使用您提供的文件。它会尝试在您的当前路径中找到一个 justfile,甚至可能产生 No justfile found
错误。
可以使用 --list-heading
自定义标题文本
$ just --list --list-heading $'Cool stuff…\n'
Cool stuff…
test
build
并且可以使用 --list-prefix
自定义缩进
$ just --list --list-prefix ····
Available recipes:
····test
····build
--list-heading
的参数替换标题和其后的换行符,因此如果非空,它应该包含换行符。这样做是为了让您能够通过传递空字符串来完全抑制标题行
$ just --list --list-heading ''
test
build
工作目录
默认情况下,食谱的运行工作目录设置为包含justfile
的目录。
可以使用[no-cd]
属性来使食谱在just
被调用的目录中设置工作目录。
@foo:
pwd
[no-cd]
@bar:
pwd
$ cd subdir
$ just foo
/
: just bar
/subdir
别名
别名允许使用替代名称在命令行上调用食谱。
alias b := build
build:
echo 'Building!'
$ just b
echo 'Building!'
Building!
设置
设置控制解释和执行。每个设置最多可以在justfile
中指定一次。
例如
set shell := ["zsh", "-cu"]
foo:
# this line will be run as `zsh -cu 'ls **/*.txt'`
ls **/*.txt
设置表
名称 | 值 | 默认值 | 描述 |
---|---|---|---|
allow-duplicate-recipes |
布尔值 | false |
允许在justfile 中出现的后续食谱覆盖具有相同名称的早期食谱。 |
allow-duplicate-variables |
布尔值 | false |
允许在justfile 中出现的后续变量覆盖具有相同名称的早期变量。 |
dotenv-filename |
字符串 | - | 如果存在,则加载具有自定义名称的.env 文件。 |
dotenv-load |
布尔值 | false |
如果存在,则加载.env 文件。 |
dotenv-path |
字符串 | - | 从自定义路径加载.env 文件,如果不存在则报错。覆盖dotenv-filename 。 |
dotenv-required |
布尔值 | false |
如果没有找到.env 文件,则报错。 |
export |
布尔值 | false |
将所有变量作为环境变量导出。 |
fallback |
布尔值 | false |
如果在命令行上找不到第一条食谱,则在父目录中查找justfile 。 |
ignore-comments |
布尔值 | false |
忽略以# 开头的食谱行。 |
positional-arguments |
布尔值 | false |
传递位置参数。 |
shell |
[COMMAND, ARGS…] |
- | 设置用于调用食谱和评估反引号中命令的命令。 |
tempdir |
字符串 | - | 在tempdir 中创建临时目录,而不是系统默认的临时目录。 |
windows-powershell |
布尔值 | false |
在Windows上使用PowerShell作为默认shell。(已弃用。请使用windows-shell 代替。) |
windows-shell |
[COMMAND, ARGS…] |
- | 设置用于调用食谱和评估反引号中命令的命令。 |
布尔设置可以写成
set NAME
这相当于
set NAME := true
允许重复食谱
如果将allow-duplicate-recipes
设置为true
,则定义具有相同名称的多个食谱不会产生错误,并使用最后定义的食谱。默认为false
。
set allow-duplicate-recipes
@foo:
echo foo
@foo:
echo bar
$ just foo
bar
允许重复变量
如果将allow-duplicate-variables
设置为true
,则定义具有相同名称的多个变量不会产生错误,并使用最后定义的变量。默认为false
。
set allow-duplicate-variables
a := "foo"
a := "bar"
@foo:
echo $a
$ just foo
bar
Dotenv设置
如果设置了dotenv-load
、dotenv-filename
、dotenv-path
或dotenv-required
中的任何一个,则just
将尝试从文件中加载环境变量。
如果设置了dotenv-path
,则just
将在给定的路径中查找文件,该路径可以是绝对路径,也可以是相对于工作目录的相对路径。
如果设置了dotenv-filename
,则just
将在相对于工作目录和其所有父目录的给定路径中查找文件。
如果没有设置dotenv-filename
,但设置了dotenv-load
或dotenv-required
,则just
将在相对于工作目录和其所有父目录的路径中查找名为.env
的文件。
dotenv-filename
和 dotenv-path
以及类似,但 dotenv-path
只是在工作目录中检查,而 dotenv-filename
则是在工作目录及其所有父目录中检查。
如果没有找到环境文件,不会发生错误,除非设置了 dotenv-required
。
加载的变量是环境变量,而不是简单的变量,因此必须使用 $VARIABLE_NAME
在脚本和反引号中访问。
例如,如果你的 .env
文件包含
# a comment, will be ignored
DATABASE_ADDRESS=localhost:6379
SERVER_PORT=1337
而你的 justfile
包含
set dotenv-load
serve:
@echo "Starting server with database $DATABASE_ADDRESS on port $SERVER_PORT…"
./server --database $DATABASE_ADDRESS --port $SERVER_PORT
just serve
将输出
$ just serve
Starting server with database localhost:6379 on port 1337…
./server --database $DATABASE_ADDRESS --port $SERVER_PORT
导出
export
设置会导致所有 just
变量作为环境变量导出。默认值为 false
。
set export
a := "hello"
@foo b:
echo $a
echo $b
$ just foo goodbye
hello
goodbye
位置参数
如果 positional-arguments
设置为 true
,则将将配方参数作为位置参数传递给命令。对于逐行配方,参数 $0
将是配方的名称。
例如,运行此配方
set positional-arguments
@foo bar:
echo $0
echo $1
将生成以下输出
$ just foo hello
foo
hello
当使用与 sh
兼容的shell,例如 bash
或 zsh
时,$@
展开为传递给配方的位置参数,从一开始。当在双引号内使用时,作为双引号传递包括空格的参数。也就是说,"$@"
等同于 "$1" "$2"
… 如果没有位置参数,"$@"
和 $@
展开为空(即,它们被删除)。
此示例配方将逐行打印参数
set positional-arguments
@test *args='':
bash -c 'while (( "$#" )); do echo - $1; shift; done' -- "$@"
用 两个 参数运行它
$ just test foo "bar baz"
- foo
- bar baz
可以通过 [positional-arguments]
属性在配方级别上启用位置参数1.29.0。
[positional-arguments]
@foo bar:
echo $0
echo $1
请注意,PowerShell 不以与其他shell相同的方式处理位置参数,因此启用位置参数可能会破坏使用PowerShell的配方。
Shell
shell
设置控制调用配方行和反引号的命令。Shebang配方不受影响。默认shell是 sh -cu
。
# use python3 to execute recipe lines and backticks
set shell := ["python3", "-c"]
# use print to capture result of evaluation
foos := `print("foo" * 4)`
foo:
print("Snake snake snake snake.")
print("{{foos}}")
just
将要执行的命令作为参数传递。许多shell需要额外的标志,通常是 -c
,以便它们评估第一个参数。
Windows Shell
just
在Windows上默认使用 sh
。要在Windows上使用不同的shell,请使用 windows-shell
set windows-shell := ["powershell.exe", "-NoLogo", "-Command"]
hello:
Write-Host "Hello, world!"
有关使用所有平台上的PowerShell的justfile的示例,请参阅 powershell.just
Windows PowerShell
set windows-
使用了过时的 powershell.exe
二进制文件,并且不再推荐使用。请参阅上面的 windows-shell
设置,以获取更灵活地控制 Windows 上使用的 shell 的方法。
just
默认在 Windows 上使用 sh
。若要使用 powershell.exe
,请将 windows-powershell
设置为 true。
set windows-powershell := true
hello:
Write-Host "Hello, world!"
Python 3
set shell := ["python3", "-c"]
Bash
set shell := ["bash", "-uc"]
Z Shell
set shell := ["zsh", "-uc"]
Fish
set shell := ["fish", "-c"]
Nushell
set shell := ["nu", "-c"]
如果您想将默认表格模式改为 light
set shell := ['nu', '-m', 'light', '-c']
Nushell 使用 Rust 编写,并且 支持 Windows / macOS 和 Linux 的跨平台。
文档注释
紧接在配方前面的注释将出现在 just --list
# build stuff
build:
./bin/build
# test stuff
test:
./bin/test
$ just --list
Available recipes:
build # build stuff
test # test stuff
可以使用 [doc]
属性来设置或抑制配方的文档注释
# This comment won't appear
[doc('Build stuff')]
build:
./bin/build
# This one won't either
[doc]
test:
./bin/test
$ just --list
Available recipes:
build # Build stuff
test
变量和替换
支持变量、字符串、连接、路径连接以及使用 {{…}}
进行替换
tmpdir := `mktemp -d`
version := "0.2.7"
tardir := tmpdir / "awesomesauce-" + version
tarball := tardir + ".tar.gz"
publish:
rm -f {{tarball}}
mkdir {{tardir}}
cp README.md *.c {{tardir}}
tar zcvf {{tarball}} {{tardir}}
scp {{tarball}} me@server.com:release/
rm -rf {{tarball}} {{tardir}}
连接路径
可以使用 /
运算符使用斜杠连接两个字符串
foo := "a" / "b"
$ just --evaluate foo
a/b
注意,即使已经存在斜杠,也会添加一个斜杠
foo := "a/"
bar := foo / "b"
$ just --evaluate bar
a//b
也可以构建绝对路径1.5.0
foo := / "b"
$ just --evaluate foo
/b
/
运算符使用斜杠字符,即使在 Windows 上也是如此。因此,应避免使用使用通用命名约定 (UNC) 的路径,即以 \?
开头的路径,因为不支持使用正斜杠的 UNC 路径。
转义 {{
要编写包含 {{
的配方,请使用 {{{{
braces:
echo 'I {{{{LOVE}} curly braces!'
(未匹配的 }}
将被忽略,因此不需要转义。)
另一个选项是将您想要转义的文本全部放在一个插值表达式内
braces:
echo '{{'I {{LOVE}} curly braces!'}}'
另一个选项是使用 {{ "{{" }}
braces:
echo 'I {{ "{{" }}LOVE}} curly braces!'
字符串
双引号字符串支持转义序列
string-with-tab := "\t"
string-with-newline := "\n"
string-with-carriage-return := "\r"
string-with-double-quote := "\""
string-with-slash := "\\"
string-with-no-newline := "\
"
$ just --evaluate
"tring-with-carriage-return := "
string-with-double-quote := """
string-with-newline := "
"
string-with-no-newline := ""
string-with-slash := "\"
string-with-tab := " "
字符串可以包含换行符
single := '
hello
'
double := "
goodbye
"
单引号字符串不识别转义序列
escapes := '\t\n\r\"\\'
$ just --evaluate
escapes := "\t\n\r\"\\"
单引号和双引号字符串的缩进版本,由三个单引号或双引号分隔,都受到支持。缩进的字符串行将删除前导换行符,以及所有非空白行的前导空白
# this string will evaluate to `foo\nbar\n`
x := '''
foo
bar
'''
# this string will evaluate to `abc\n wuv\nxyz\n`
y := """
abc
wuv
xyz
"""
与未缩进的字符串类似,缩进的双引号字符串处理转义序列,而缩进的单引号字符串忽略转义序列。转义序列处理发生在取消缩进之后。取消缩进算法不考虑由转义序列产生的空白或换行符。
以 x
为前缀的字符串将被 shell 展开1.27.0
foobar := x'~/$FOO/${BAR}'
值 | 替换 |
---|---|
$VAR |
环境变量 VAR 的值 |
${VAR} |
环境变量 VAR 的值 |
${VAR:-默认值} |
环境变量 VAR 的值,或者如果未设置 VAR 则为 DEFAULT |
前缀 ~ |
当前用户主目录的路径 |
前缀 ~USER |
用户 USER 主目录的路径 |
此展开在编译时执行,因此无法使用来自 .env
文件和导出的 just
变量。然而,这允许在设置和导入路径等地方使用 shell 展开字符串,这些地方不能依赖于 just
变量和 .env
文件。
忽略错误
通常,如果命令返回非零退出状态,则执行将停止。要在命令失败后继续执行,即使它失败了,请在命令前加上 -
foo:
-cat foo
echo 'Done!'
$ just foo
cat foo
cat: foo: No such file or directory
echo 'Done!'
Done!
函数
just
提供了一些内置函数,这些函数在编写配方时可能很有用。
系统信息
arch()
— 指令集架构。可能的值包括:"aarch64"
、"arm"
、"asmjs"
、"hexagon"
、"mips"
、"msp430"
、"powerpc"
、"powerpc64"
、"s390x"
、"sparc"
、"wasm32"
、"x86"
、"x86_64"
和"xcore"
。num_cpus()
1.15.0 - 逻辑 CPU 数量。os()
—— 操作系统。可能的值包括:"android"
、"bitrig"
、"dragonfly"
、"emscripten"
、"freebsd"
、"haiku"
、"ios"
、"linux"
、"macos"
、"netbsd"
、"openbsd"
、"solaris"
和"windows"
。os_family()
—— 操作系统家族;可能的值包括:"unix"
和"windows"
。
例如
system-info:
@echo "This is an {{arch()}} machine".
$ just system-info
This is an x86_64 machine
可以使用os_family()
函数创建跨平台的justfile
,这些文件可以在各种操作系统上运行。例如,请参阅cross-platform.just文件。
外部命令
-
shell(command, args...)
1.27.0 返回shell脚本command
的标准输出,其中包含零个或多个位置参数args
。用于解释command
的shell与用于评估配方行的shell相同,可以通过set shell := […]
来更改。command
作为第一个参数传递,因此如果命令是'echo $@'
,完整的命令行,包括默认的shell命令shell -cu
和参数args
'foo'
和'bar'
将是'shell' '-cu' 'echo $@' 'echo $@' 'foo' 'bar'
这是为了让
$@
按预期工作,并且$1
指向第一个参数。$@
不包含第一个位置参数,预计将是正在运行的程序名称。
# arguments can be variables or expressions
file := '/sys/class/power_supply/BAT0/status'
bat0stat := shell('cat $1', file)
# commands can be variables or expressions
command := 'wc -l'
output := shell(command + ' "$1"', 'main.c')
# arguments referenced by the shell command must be used
empty := shell('echo', 'foo')
full := shell('echo $1', 'foo')
error := shell('echo $1')
# Using python as the shell. Since `python -c` sets `sys.argv[0]` to `'-c'`,
# the first "real" positional argument will be `sys.argv[2]`.
set shell := ["python3", "-c"]
olleh := shell('import sys; print(sys.argv[2][::-1])', 'hello')
环境变量
env_var(key)
—— 获取名为key
的环境变量,如果不存在则中止。
home_dir := env_var('HOME')
test:
echo "{{home_dir}}"
$ just
/home/user1
env_var_or_default(key, default)
— 获取名为key
的环境变量,如果不存在则返回default
。env(key)
1.15.0 — 是env_var(key)
的别名。env(key, default)
1.15.0 — 是env_var_or_default(key, default)
的别名。
调用信息
is_dependency()
- 如果当前配方作为另一个配方的依赖项运行,而不是直接运行,则返回字符串true
,否则返回字符串false
。
调用目录
invocation_directory()
- 在just
被调用时检索当前目录的绝对路径,在just
在执行命令之前更改它(chdir'd)之前。在 Windows 上,invocation_directory()
使用cygpath
将调用目录转换为与 Cygwin 兼容的/
-分隔的路径。使用invocation_directory_native()
在所有平台上返回原始调用目录。
例如,要调用 rustfmt
在“当前目录”下的文件上(从用户/调用者的角度来看),可以使用以下规则
rustfmt:
find {{invocation_directory()}} -name \*.rs -exec rustfmt {} \;
或者,如果您的命令需要从当前目录运行,您可以使用(例如)
build:
cd {{invocation_directory()}}; ./some_script_that_needs_to_be_run_from_here
invocation_directory_native()
- 在just
被调用时检索当前目录的绝对路径,在just
在执行命令之前更改它(chdir'd)之前。
Justfile 和 Justfile 目录
-
justfile()
- 检索当前justfile
的路径。 -
justfile_directory()
- 检索当前justfile
的父目录的路径。
例如,要相对于当前 justfile
的位置运行命令
script:
./{{justfile_directory()}}/scripts/some_script
源文件和源目录
-
source_file()
1.27.0 - 检索当前源文件的路径。 -
source_directory()
1.27.0 - 检索当前源文件父目录的路径。
source_file()
和 source_directory()
在根 justfile
中的表现与 justfile()
和 justfile_directory()
相同,但会在从导入或子模块内部调用时分别返回当前 import
或 mod
源文件的路径和目录。
Just 可执行文件
just_executable()
-just
可执行文件的绝对路径。
例如
executable:
@echo The executable is at: {{just_executable()}}
$ just
The executable is at: /bin/just
Just 进程 ID
just_pid()
-just
可执行文件的进程 ID。
例如
pid:
@echo The process ID is: {{ just_pid() }}
$ just
The process ID is: 420
字符串操作
append(suffix, s)
1.27.0 将suffix
追加到s
中的空白分隔字符串。append('/src', 'foo bar baz')
→'foo/src bar/src baz/src'
prepend(prefix, s)
1.27.0 将prefix
预先添加到s
中的空白分隔字符串。prepend('src/', 'foo bar baz')
→'src/foo src/bar src/baz'
encode_uri_component(s)
1.27.0 - 对s
中的字符进行百分号编码,除了[A-Za-z0-9_.!~*'()-]
,与 JavaScript 的encodeURIComponent
函数 的行为一致。quote(s)
- 将所有单引号替换为'\''
,并在s
的前后添加单引号。这对于许多外壳(包括大多数 Bourne shell 后代)来说足够用于转义特殊字符。replace(s, from, to)
- 将s
中的所有from
替换为to
。replace_regex(s, regex, replacement)
- 将s
中的所有regex
替换为replacement
。正则表达式由 Rustregex
库 提供。有关用法示例,请参阅 语法文档。支持捕获组。replacement
字符串使用 替换字符串语法。trim(s)
- 移除s
的前后空白字符。trim_end(s)
- 移除s
的尾部空白字符。trim_end_match(s, pat)
- 移除与pat
匹配的s
的后缀。trim_end_matches(s, pat)
- 重复移除与pat
匹配的s
的后缀。trim_start(s)
- 移除s
的首部空白字符。trim_start_match(s, pat)
- 移除与pat
匹配的s
的前缀。trim_start_matches(s, pat)
- 重复移除与pat
匹配的s
的前缀。
大小写转换
capitalize(s)
1.7.0 - 将s
的第一个字符转换为大写,其余转换为小写。kebabcase(s)
1.7.0 - 将s
转换为kebab-case
。lowercamelcase(s)
1.7.0 - 将s
转换为lowerCamelCase
。lowercase(s)
- 将s
转换为小写。shoutykebabcase(s)
1.7.0 - 将s
转换为SHOUTY-KEBAB-CASE
。shoutysnakecase(s)
1.7.0 - 将s
转换为SHOUTY_SNAKE_CASE
。snakecase(s)
1.7.0 - 将s
转换为snake_case
。titlecase(s)
1.7.0 - 将s
转换为Title Case
。uppercamelcase(s)
1.7.0 - 将s
转换为UpperCamelCase
。uppercase(s)
- 将s
转换为大写。
路径操作
可能失败的
absolute_path(path)
- 将工作目录中的相对path
转换为绝对路径。在目录/foo
中,./bar.txt
的绝对路径是/foo/bar.txt
。canonicalize(path)
1.24.0 - 通过解析符号链接并尽可能移除.
、..
和额外的/
来规范化path
。extension(path)
-path
的扩展名。例如,extension("/foo/bar.txt")
是txt
。file_name(path)
- 移除任何前导目录组件后path
的文件名。例如,file_name("/foo/bar.txt")
是bar.txt
。file_stem(path)
- 不带扩展名的path
文件名。例如,file_stem("/foo/bar.txt")
是bar
。parent_directory(path)
-path
的父目录。例如,parent_directory("/foo/bar.txt")
是/foo
。without_extension(path)
- 不带扩展名的path
。例如,without_extension("/foo/bar.txt")
是/foo/bar
。
这些函数可能会失败,例如,如果路径没有扩展名,这将停止执行。
不可失败的
clean(path)
- 通过删除额外的路径分隔符、中间的.
组件和尽可能的..
来简化path
。例如,clean("foo//bar")
等于foo/bar
,clean("foo/..")
等于.
,clean("foo/./bar")
等于foo/bar
。join(a, b…)
- 此函数在 Unix 上使用/
,在 Windows 上使用\
,可能会导致不期望的行为。例如,a / b
,该操作始终使用/
,除非在 Windows 上特别需要\
。将路径a
与路径b
连接起来。例如,join("foo/bar", "baz")
等于foo/bar/baz
。接受两个或更多参数。
文件系统访问
path_exists(path)
- 如果路径指向一个现有实体,则返回true
,否则返回false
。遍历符号链接,如果路径不可访问或指向损坏的符号链接,则返回false
。
错误报告
error(message)
- 终止执行并向用户报告错误message
。
UUID 和哈希生成
blake3(string)
1.25.0 - 返回string
的 BLAKE3 哈希作为十六进制字符串。blake3_file(path)
1.25.0 - 返回path
所在文件的 BLAKE3 哈希作为十六进制字符串。sha256(string)
- 返回string
的 SHA-256 哈希作为十六进制字符串。sha256_file(path)
- 返回path
所在文件的 SHA-256 哈希作为十六进制字符串。uuid()
- 生成一个随机版本 4 UUID。
随机
choose(n, alphabet)
1.27.0 - 生成由alphabet
中随机选择的n
个字符组成的字符串,可能不包含重复字符。例如,choose('64', HEX)
将生成一个随机的64位小写十六进制字符串。
日期时间
datetime(format)
master - 返回带有format
的本地时间。datetime_utc(format)
master - 返回带有format
的UTC时间。
datetime
和 datetime_utc
的参数是 strftime
风格的格式字符串,有关详细信息,请参阅 chrono
库文档。
语义版本
semver_matches(version, requirement)
1.16.0 - 检查语义版本,例如"0.1.0"
是否与requirement
匹配,例如">=0.1.0"
,如果匹配则返回"true"
,否则返回"false"
。
XDG 目录1.23.0
这些函数返回特定于用户的目录路径,例如配置、数据、缓存、可执行文件以及用户的主目录。这些函数遵循 XDG 基础目录规范,并使用 dirs
包实现。
cache_directory()
- 用户特定的缓存目录。config_directory()
- 用户特定的配置目录。config_local_directory()
- 本地用户特定的配置目录。data_directory()
- 用户特定的数据目录。data_local_directory()
- 本地用户特定的数据目录。executable_directory()
- 用户特定的可执行文件目录。home_directory()
- 用户的主目录。
常量
预定义了一些常量
名称 | 值 |
---|---|
HEX 1.27.0 |
"0123456789abcdef" |
HEXLOWER 1.27.0 |
"0123456789abcdef" |
HEXUPPER 1.27.0 |
"0123456789ABCDEF" |
@foo:
echo {{HEX}}
$ just foo
0123456789abcdef
食谱属性
食谱可以注解属性以改变其行为。
名称 | 描述 |
---|---|
[confirm] 1.17.0 |
在执行食谱之前要求确认。 |
[confirm('PROMPT')] 1.23.0 |
在执行具有自定义提示的配方之前需要确认。 |
[doc('DOC')] 1.27.0 |
将配方的文档注释设置为DOC 。 |
[group('NAME')] 1.27.0 |
将配方放入配方组 NAME 。 |
[linux] 1.8.0 |
在Linux上启用配方。 |
[macos] 1.8.0 |
在MacOS上启用配方。 |
[no-cd] 1.9.0 |
在执行配方之前不要更改目录。 |
[no-exit-message] 1.7.0 |
如果配方失败,不要打印错误消息。 |
[no-quiet] 1.23.0 |
全局覆盖静默配方,并始终输出配方。 |
[positional-arguments] 1.29.0 |
为此配方开启位置参数。 |
[private] 1.10.0 |
请参阅私有配方。 |
[unix] 1.8.0 |
在Unix系统上启用配方。(包括MacOS)。 |
[windows] 1.8.0 |
在Windows上启用配方。 |
配方可以具有多个属性,可以是多行
[no-cd]
[private]
foo:
echo "foo"
或者在一行中用逗号分隔1.14.0
[no-cd, private]
foo:
echo "foo"
启用和禁用配方1.8.0
属性[linux]
、[macos]
、[unix]
和[windows]
是配置属性。默认情况下,配方始终启用。具有一个或多个配置属性的配方只有在相应的配置之一激活时才会启用。
这可以用来编写在不同操作系统上运行行为不同的 justfile
。在这个 justfile
中的 run
脚本将编译并运行 main.c
,使用不同的C编译器,并根据操作系统使用正确的输出二进制名称。
[unix]
run:
cc main.c
./a.out
[windows]
run:
cl main.c
main.exe
禁用更改目录1.9.0
just
通常会将当前目录设置为包含 justfile
的目录来执行脚本。可以使用 [no-cd]
属性来禁用此功能。这可以用来创建使用调用目录的相对路径的脚本,或者操作当前目录的脚本。
例如,这个 commit
脚本
[no-cd]
commit file:
git add {{file}}
git commit
可以使用相对于当前目录的路径,因为 [no-cd]
属性阻止 just
在执行 commit
时更改当前目录。
为脚本要求确认1.17.0
just
通常在没有错误的情况下执行所有脚本。[confirm]
属性允许脚本在运行之前在终端要求确认。可以通过将 --yes
传递给 just
来覆盖此功能,这将自动确认标记了此属性的任何脚本。
如果依赖的脚本未确认,则依赖于要求确认的脚本的脚本将不会运行,以及任何要求确认的脚本之后的脚本。
[confirm]
delete-all:
rm -rf *
自定义确认提示1.23.0
默认的确认提示可以通过 [confirm(PROMPT)]
覆盖。
[confirm("Are you sure you want to delete everything?")]
delete-everything:
rm -rf *
脚本组
脚本可以带有组名注解
[group('lint')]
js-lint:
echo 'Running JS linter…'
[group('rust recipes')]
[group('lint')]
rust-lint:
echo 'Running Rust linter…'
[group('lint')]
cpp-lint:
echo 'Running C++ linter…'
# not in any group
email-everyone:
echo 'Sending mass email…'
脚本按组列出
$ just --list
Available recipes:
(no group)
email-everyone # not in any group
[lint]
cpp-lint
js-lint
rust-lint
[rust recipes]
rust-lint
just --list --unsorted
在每个组中按 justfile
的顺序打印脚本
$ just --list --unsorted
Available recipes:
(no group)
email-everyone # not in any group
[lint]
js-lint
rust-lint
cpp-lint
[rust recipes]
rust-lint
可以使用 --groups
来列出组
$ just --groups
Recipe groups:
lint
rust recipes
使用 just --groups --unsorted
来按 justfile
的顺序打印组。
使用反引号进行命令评估
可以使用反引号来存储命令的结果
localhost := `dumpinterfaces | cut -d: -f2 | sed 's/\/.*//' | sed 's/ //g'`
serve:
./serve {{localhost}} 8080
缩进的反引号,由三个反引号分隔,以与缩进字符串相同的方式缩进
# This backtick evaluates the command `echo foo\necho bar\n`, which produces the value `foo\nbar\n`.
stuff := ```
echo foo
echo bar
```
有关取消缩进的详细信息,请参阅字符串部分。
反引号不能以 #!
开头。此语法为未来的升级预留。
条件表达式
if
/else
表达式根据两个表达式是否评估为相同的值来评估不同的分支
foo := if "2" == "2" { "Good!" } else { "1984" }
bar:
@echo "{{foo}}"
$ just bar
Good!
也可以测试不等式
foo := if "hello" != "goodbye" { "xyz" } else { "abc" }
bar:
@echo {{foo}}
$ just bar
xyz
并匹配正则表达式
foo := if "hello" =~ 'hel+o' { "match" } else { "mismatch" }
bar:
@echo {{foo}}
$ just bar
match
正则表达式由 regex crate 提供,其语法在 docs.rs 上有文档说明。由于正则表达式通常使用反斜杠转义序列,建议使用单引号字符串字面量,这样会将斜杠原样传递给正则表达式解析器。
条件表达式会短路,这意味着它们只评估其分支之一。这可以用来确保不应该运行时不会运行反引号表达式。
foo := if env_var("RELEASE") == "true" { `get-something-from-release-database` } else { "dummy-value" }
可以在配方中使用条件。
bar foo:
echo {{ if foo == "bar" { "hello" } else { "goodbye" } }}
请注意,在最后的 }
后面有一个空格!如果没有空格,则插值会提前关闭。
可以链式使用多个条件。
foo := if "hello" == "goodbye" {
"xyz"
} else if "a" == "a" {
"abc"
} else {
"123"
}
bar:
@echo {{foo}}
$ just bar
abc
使用错误停止执行
可以使用 error
函数来停止执行。例如
foo := if "hello" == "goodbye" {
"xyz"
} else if "a" == "b" {
"abc"
} else {
error("123")
}
运行时产生以下错误
error: Call to function `error` failed: 123
|
16 | error("123")
从命令行设置变量
可以从命令行覆盖变量。
os := "linux"
test: build
./test --test {{os}}
build:
./build {{os}}
$ just
./build linux
./test --test linux
可以在配方之前传递任何数量的形式为 NAME=VALUE
的参数。
$ just os=plan9
./build plan9
./test --test plan9
或者您可以使用 --set
标志
$ just --set os bsd
./build bsd
./test --test bsd
获取和设置环境变量
导出 just
变量
以 export
关键字开头赋值将被导出为环境变量。
export RUST_BACKTRACE := "1"
test:
# will print a stack trace if it crashes
cargo test
以 $
开头的参数将被导出为环境变量。
test $RUST_BACKTRACE="1":
# will print a stack trace if it crashes
cargo test
在同一作用域中,导出的变量和参数不会被导出到反引号中。
export WORLD := "world"
# This backtick will fail with "WORLD: unbound variable"
BAR := `echo hello $WORLD`
# Running `just a foo` will fail with "A: unbound variable"
a $A $B=`echo $A`:
echo $A $B
当 export 设置时,所有 just
变量都将作为环境变量导出。
取消导出环境变量1.29.0
可以使用 unexport
关键字取消导出环境变量。
unexport FOO
@foo:
echo $FOO
$ export FOO=bar
$ just foo
sh: FOO: unbound variable
从环境中获取环境变量
环境变量会自动传递给配方。
print_home_folder:
echo "HOME is: '${HOME}'"
$ just
HOME is '/home/myuser'
从环境变量设置 just
变量
可以使用函数 env_var()
和 env_var_or_default()
将环境变量传播到 just
变量。请参阅 环境变量。
配方参数
配方可以有参数。例如,配方 build
有一个名为 target
的参数。
build target:
@echo 'Building {{target}}…'
cd {{target}} && make
要在命令行传递参数,请在配方名称后放置它们
$ just build my-awesome-project
Building my-awesome-project…
cd my-awesome-project && make
要传递参数给依赖项,请将依赖项放在括号中,并附带参数
default: (build "main")
build target:
@echo 'Building {{target}}…'
cd {{target}} && make
变量也可以作为参数传递给依赖项
target := "main"
_build version:
@echo 'Building {{version}}…'
cd {{version}} && make
build: (_build target)
通过将依赖项放在括号中并附带参数,可以将命令的参数传递给依赖项
build target:
@echo "Building {{target}}…"
push target: (build target)
@echo 'Pushing {{target}}…'
参数可能有默认值
default := 'all'
test target tests=default:
@echo 'Testing {{target}}:{{tests}}…'
./test --tests {{tests}} {{target}}
具有默认值的参数可以省略
$ just test server
Testing server:all…
./test --tests all server
或提供
$ just test server unit
Testing server:unit…
./test --tests unit server
默认值可以是任意表达式,但连接或路径连接必须是括号内的
arch := "wasm"
test triple=(arch + "-unknown-unknown") input=(arch / "input.dat"):
./test {{triple}}
配方最后一个参数可能是可变参数,用 +
或 *
在参数名称之前表示
backup +FILES:
scp {{FILES}} me@server.com:
以 +
开头的可变参数接受 一个或多个 参数,并展开为一个包含这些参数的字符串,参数之间用空格分隔
$ just backup FAQ.md GRAMMAR.md
scp FAQ.md GRAMMAR.md [email protected]:
FAQ.md 100% 1831 1.8KB/s 00:00
GRAMMAR.md 100% 1666 1.6KB/s 00:00
以 *
开头的可变参数接受 零个或多个 参数,并展开为一个包含这些参数的字符串,参数之间用空格分隔,如果不存在参数,则为空字符串
commit MESSAGE *FLAGS:
git commit {{FLAGS}} -m "{{MESSAGE}}"
可变参数可以分配默认值。这些默认值会被命令行传递的参数覆盖。
test +FLAGS='-q':
cargo test {{FLAGS}}
{{…}}
替换时,如果包含空格,可能需要加上引号。例如,如果你有以下配方
search QUERY:
lynx https://www.google.com/?q={{QUERY}}
你输入
$ just search "cat toupee"
just
将运行命令 lynx https://www.google.com/?q=cat toupee
,它将被 sh
解析为 lynx
,https://www.google.com/?q=cat
和 toupee
,而不是你想要的 lynx
和 https://www.google.com/?q=cat toupee
。
你可以通过添加引号来修复这个问题
search QUERY:
lynx 'https://www.google.com/?q={{QUERY}}'
以 $
开头的参数将被导出为环境变量。
foo $bar:
echo $bar
依赖关系
依赖关系会在依赖于它们的配方之前运行
a: b
@echo A
b:
@echo B
$ just a
B
A
在 just
的给定调用中,具有相同参数的配方只会运行一次,无论它在命令行调用中出现多少次,或者作为依赖出现多少次
a:
@echo A
b: a
@echo B
c: a
@echo C
$ just a a a a a
A
$ just b c
A
B
C
多个配方可能依赖于执行某种设置的配方,并且当这些配方运行时,该设置只会执行一次
build:
cc main.c
test-foo: build
./a.out --test foo
test-bar: build
./a.out --test bar
$ just test-foo test-bar
cc main.c
./a.out --test foo
./a.out --test bar
只有当配方接收到相同的参数时,才会跳过给定运行中的配方
build:
cc main.c
test TEST: build
./a.out --test {{TEST}}
$ just test foo test bar
cc main.c
./a.out --test foo
./a.out --test bar
在配方末尾运行配方
配方的正常依赖关系始终在配方开始之前运行。也就是说,被依赖的总是先于依赖者运行。这些依赖关系被称为“优先依赖关系”。
配方还可以有后续依赖关系,这些依赖关系在配方之后运行,并使用 &&
引入
a:
echo 'A!'
b: a && c d
echo 'B!'
c:
echo 'C!'
d:
echo 'D!'
运行 b 会打印
$ just b
echo 'A!'
A!
echo 'B!'
B!
echo 'C!'
C!
echo 'D!'
D!
在配方中间运行配方
just
不支持在另一个配方的中间运行配方,但你可以在配方的中间递归地调用 just
。给定以下 justfile
a:
echo 'A!'
b: a
echo 'B start!'
just c
echo 'B end!'
c:
echo 'C!'
运行 b 会打印
$ just b
echo 'A!'
A!
echo 'B start!'
B start!
echo 'C!'
C!
echo 'B end!'
B end!
这有一些限制,因为配方 c
是用全新的 just
调用运行的:赋值将被重新计算,依赖关系可能运行两次,并且命令行参数不会传播到子 just
进程。
用其他语言编写配方
以 #!
开始的配方称为 shebang 配方,通过将配方主体保存到文件中并运行它来执行。这让你可以用不同的语言编写配方
polyglot: python js perl sh ruby nu
python:
#!/usr/bin/env python3
print('Hello from python!')
js:
#!/usr/bin/env node
console.log('Greetings from JavaScript!')
perl:
#!/usr/bin/env perl
print "Larry Wall says Hi!\n";
sh:
#!/usr/bin/env sh
hello='Yo'
echo "$hello from a shell script!"
nu:
#!/usr/bin/env nu
let hello = 'Hola'
echo $"($hello) from a nushell script!"
ruby:
#!/usr/bin/env ruby
puts "Hello from ruby!"
$ just polyglot
Hello from python!
Greetings from JavaScript!
Larry Wall says Hi!
Yo from a shell script!
Hola from a nushell script!
Hello from ruby!
在包括 Linux 和 MacOS 在内的类 Unix 操作系统中,shebang 配方通过将配方主体保存到临时目录中的文件,将该文件标记为可执行,并执行它来执行。然后操作系统将 shebang 行解析为命令行并调用它,包括文件的路径。例如,如果配方以 #!/usr/bin/env bash
开始,操作系统运行的最终命令可能类似于 /usr/bin/env bash /tmp/PATH_TO_SAVED_RECIPE_BODY
。
shebang 行分割依赖于操作系统。当传递带有参数的命令时,你可能需要使用 -S
标志明确告诉 env
进行分割
run:
#!/usr/bin/env -S bash -x
ls
Windows不支持shebang行。在Windows上,just
将shebang行拆分为命令和参数,将配方主体保存到文件中,然后调用拆分的命令和参数,将保存的配方主体路径作为最后一个参数。例如,在Windows上,如果配方以#! py
开始,操作系统最终运行的命令将类似于py C:\Temp\PATH_TO_SAVED_RECIPE_BODY
。
更安全的Bash Shebang配方
如果您正在编写bash
shebang配方,请考虑添加set -euxo pipefail
foo:
#!/usr/bin/env bash
set -euxo pipefail
hello='Yo'
echo "$hello from Bash!"
虽然这不是强制性的,但set -euxo pipefail
将打开一些有用的功能,使bash
shebang配方更类似于正常的逐行just
配方
-
set -e
使得bash
在命令失败时退出。 -
set -u
使得bash
在变量未定义时退出。 -
set -x
使得bash
在运行前打印每行脚本。 -
set -o pipefail
使得bash
在管道中的命令失败时退出。这是bash
特有的,因此在正常的逐行just
配方中没有打开。
这些功能一起可以避免许多shell脚本的陷阱。
Windows上Shebang配方执行
在Windows上,包含/
的shebang解释器路径将使用Cygwin中提供的实用程序cygpath
从Unix风格路径转换为Windows风格路径。
例如,要在Windows上执行此配方
echo:
#!/bin/sh
echo "Hello!"
在执行之前,解释器路径/bin/sh
将使用cygpath
转换为Windows风格路径。
如果解释器路径不包含/
,它将执行而不进行转换。如果cygpath
不可用,或者您希望将Windows风格路径传递给解释器,这很有用。
在配方中设置变量
配方行由shell而不是just
解释,因此不可能在配方中间设置just
变量
foo:
x := "hello" # This doesn't work!
echo {{x}}
虽然可以使用shell变量,但还有一个问题。每个配方行都由一个新的shell实例运行,因此在一行中设置的变量不会在下一行中设置
foo:
x=hello && echo $x # This works!
y=bye
echo $y # This doesn't, `y` is undefined here!
解决这个问题的最佳方法是用shebang配方。Shebang配方主体被提取并作为脚本运行,因此单个shell实例将运行整个内容
foo:
#!/usr/bin/env bash
set -euxo pipefail
x=hello
echo $x
在配方之间共享环境变量
每个配方行的每一行都由一个新的shell执行,因此不可能在配方之间共享环境变量。
使用Python虚拟环境
一些工具,如Python的venv,需要加载环境变量才能工作,这使得它们难以与just
一起使用。作为解决方案,您可以直接执行虚拟环境二进制文件
venv:
[ -d foo ] || python3 -m venv foo
run: venv
./foo/bin/python3 main.py
在配方中更改工作目录
每个配方行都由一个新的shell执行,因此如果您在一行中更改工作目录,它对后续行没有影响
foo:
pwd # This `pwd` will print the same directory…
cd bar
pwd # …as this `pwd`!
有几种方法可以解决这个问题。一种是在要运行的命令同一行上调用cd
foo:
cd bar && pwd
另一种方法是使用shebang配方。Shebang配方主体被提取并作为脚本运行,因此单个shell实例将运行整个程序,因此在一行中执行pwd
将影响后续行,就像shell脚本一样
foo:
#!/usr/bin/env bash
set -euxo pipefail
cd bar
pwd
缩进
配方行可以用空格或制表符缩进,但不能混合使用。配方中所有行的缩进类型必须相同,但同一justfile
中的不同配方可以使用不同的缩进。
每个配方至少必须从recipe-name
缩进一个级别,但之后可以进一步缩进。
下面是一个使用空格缩进,表示为·
,和制表符缩进,表示为→
的配方。
set windows-shell := ["pwsh", "-NoLogo", "-NoProfileLoadTime", "-Command"]
set ignore-comments
list-space directory:
··#!pwsh
··foreach ($item in $(Get-ChildItem {{directory}} )) {
····echo $item.Name
··}
··echo ""
# indentation nesting works even when newlines are escaped
list-tab directory:
→ @foreach ($item in $(Get-ChildItem {{directory}} )) { \
→ → echo $item.Name \
→ }
→ @echo ""
PS > just list-space ~
Desktop
Documents
Downloads
PS > just list-tab ~
Desktop
Documents
Downloads
多行构造
没有初始shebang的配方将逐行评估和运行,这意味着多行构造可能不会按预期工作。
例如,以下justfile
conditional:
if true; then
echo 'True!'
fi
在conditional
配方第二行之前的额外前导空格将产生解析错误
$ just conditional
error: Recipe line has extra leading whitespace
|
3 | echo 'True!'
| ^^^^^^^^^^^^^^^^
为了解决这个问题,您可以一行内编写条件语句,使用斜杠转义换行符,或给配方添加shebang。这里提供了一些多行构造的示例供参考。
if
语句
conditional:
if true; then echo 'True!'; fi
conditional:
if true; then \
echo 'True!'; \
fi
conditional:
#!/usr/bin/env sh
if true; then
echo 'True!'
fi
for
循环
for:
for file in `ls .`; do echo $file; done
for:
for file in `ls .`; do \
echo $file; \
done
for:
#!/usr/bin/env sh
for file in `ls .`; do
echo $file
done
while
循环
while:
while `server-is-dead`; do ping -c 1 server; done
while:
while `server-is-dead`; do \
ping -c 1 server; \
done
while:
#!/usr/bin/env sh
while `server-is-dead`; do
ping -c 1 server
done
配方体外部
括号表达式可以跨越多行
abc := ('a' +
'b'
+ 'c')
abc2 := (
'a' +
'b' +
'c'
)
foo param=('foo'
+ 'bar'
):
echo {{param}}
bar: (foo
'Foo'
)
echo 'Bar!'
以反斜杠结尾的行将继续到下一行,就好像这些行通过空格连接一样1.15.0
a := 'foo' + \
'bar'
foo param1 \
param2='foo' \
*varparam='': dep1 \
(dep2 'foo')
echo {{param1}} {{param2}} {{varparam}}
dep1: \
# this comment is not part of the recipe body
echo 'dep1'
dep2 \
param:
echo 'Dependency with parameter {{param}}'
反斜杠行续行也可以用于插值。反斜杠后面的行必须缩进。
recipe:
echo '{{ \
"This interpolation " + \
"has a lot of text." \
}}'
echo 'back to recipe body'
命令行选项
just
支持一些有用的命令行选项,用于列出、转储和调试配方和变量
$ just --list
Available recipes:
js
perl
polyglot
python
ruby
$ just --show perl
perl:
#!/usr/bin/env perl
print "Larry Wall says Hi!\n";
$ just --show polyglot
polyglot: python js perl sh ruby
一些命令行选项可以使用环境变量设置。例如
$ export JUST_UNSTABLE=1
$ just
等同于
$ just --unstable
查阅just --help
以查看哪些选项可以由环境变量设置。
私有配方
名称以_
开头的配方和别名将不会从just --list
中省略
test: _test-helper
./bin/test
_test-helper:
./bin/super-secret-test-helper-stuff
$ just --list
Available recipes:
test
也不会从just --summary
中省略
$ just --summary
test
可以使用[private]
属性1.10.0来隐藏配方或别名,而无需更改名称
[private]
foo:
[private]
alias b := bar
bar:
$ just --list
Available recipes:
bar
这对于仅作为其他配方依赖的辅助配方非常有用。
静默配方
配方名称前可以加@
来反转每行前的@
的含义
@quiet:
echo hello
echo goodbye
@# all done!
现在只有以@
开始的行将被回显
$ just quiet
hello
goodbye
# all done!
可以使用set quiet
将Justfile中的所有配方都设置为静默
set quiet
foo:
echo "This is quiet"
@foo2:
echo "This is also quiet"
[no-quiet]
属性覆盖此设置
set quiet
foo:
echo "This is quiet"
[no-quiet]
foo2:
echo "This is not quiet"
Shebang配方默认是静默的
foo:
#!/usr/bin/env bash
echo 'Foo!'
$ just foo
Foo!
在shebang配方名称中添加@
会使just
在执行之前打印配方
@bar:
#!/usr/bin/env bash
echo 'Bar!'
$ just bar
#!/usr/bin/env bash
echo 'Bar!'
Bar!
just
在配方行失败时通常会打印错误消息。可以使用 [no-exit-message]
1.7.0 属性来抑制这些错误消息。这对于包装工具的配方特别有用。
git *args:
@git {{args}}
$ just git status
fatal: not a git repository (or any of the parent directories): .git
error: Recipe `git` failed on line 2 with exit code 128
添加此属性以抑制工具以非零代码退出时的退出错误消息。
[no-exit-message]
git *args:
@git {{args}}
$ just git status
fatal: not a git repository (or any of the parent directories): .git
使用交互式选择器选择要运行的配方
--choose
子命令使得 just
调用一个选择器以选择要运行的配方。选择器应从标准输入读取包含配方名称的行,并将一个或多个这些名称以空格分隔打印到标准输出。
由于目前没有使用 --choose
运行需要参数的配方的方法,因此这些配方不会提供给选择器。私有配方和别名也会被跳过。
可以使用 --chooser
标志来覆盖选择器。如果没有给出 --chooser
,那么 just
首先检查 $JUST_CHOOSER
是否已设置。如果没有设置,则选择器默认为流行的模糊查找器 fzf
。
可以将参数包含在选择器中,例如 fzf --exact
。
选择器的调用方式与配方行相同。例如,如果选择器是 fzf
,它将以 sh -cu 'fzf'
调用,如果覆盖了 shell 或 shell 参数,选择器调用将尊重这些覆盖。
如果您希望 just
默认使用选择器选择配方,您可以使用此作为默认配方
default:
@just --choose
在其他目录中调用 justfile
如果传递给 just
的第一个参数包含一个 /
,则发生以下情况
-
在最后一个
/
处拆分参数。 -
最后一个
/
之前的部分被视为目录。just
将在该处开始搜索justfile
,而不是在当前目录中。 -
最后一个斜杠之后的部分被视为普通参数,如果它是空的,则忽略。
这可能看起来有点奇怪,但如果您想在子目录中的 justfile
中运行命令,则很有用。
例如,如果您在一个包含名为 foo
的子目录的目录中,该子目录包含一个具有默认配方 build
的 justfile
,以下都是等效的
$ (cd foo && just build)
$ just foo/build
$ just foo/
在第一个配方之后寻找的附加配方在相同的 justfile
中。例如,以下两者都是等效的
$ just foo/a b
$ (cd foo && just a b)
并且都会在 foo/justfile
中调用配方 a
和 b
。
导入
一个 justfile
可以使用 import
语句包含另一个的内容。
如果您有以下 justfile
import 'foo/bar.just'
a: b
@echo A
并且以下文本在 foo/bar.just
b:
@echo B
foo/bar.just
将被包含在 justfile
中,并且将定义 recipe b
$ just b
B
$ just a
B
A
import
路径可以是绝对路径,也可以相对于包含它的 justfile
位置。在导入路径中,开头的 ~/
被替换为当前用户的家目录。
Justfiles 对顺序不敏感,因此包含的文件可以引用在 import
语句之后定义的变量和 recipe。
导入的文件本身可以包含 import
,这些导入会递归处理。
当设置 allow-duplicate-recipes
时,父模块中的 recipe 会覆盖导入中的 recipe。类似地,当设置 allow-duplicate-variables
时,父模块中的变量会覆盖导入中的变量。
可以在 import
关键字后放置一个 ?
来使导入可选。
import? 'foo/bar.just'
对于可选导入缺失的源文件不会产生错误。
从 1.19.0 版本开始
justfile
可以使用 mod
语句声明模块。由于 mod
语句目前不稳定,因此您需要使用 --unstable
标志,或者设置 JUST_UNSTABLE
环境变量来使用它们。
如果您有以下 justfile
mod bar
a:
@echo A
在 bar.just
中的以下文本
b:
@echo B
bar.just
将作为子模块包含在 justfile
中。在某个子模块中定义的 recipe、别名和变量不能在其他子模块中使用,并且每个模块使用自己的设置。
子模块中的 recipe 可以作为子命令调用
$ just --unstable bar b
B
或使用路径语法
$ just --unstable bar::b
B
如果模块名为 foo
,Just 会搜索位于 foo.just
、foo/mod.just
、foo/justfile
和 foo/.justfile
的模块文件。在后两种情况下,模块文件可以有任意的大小写。
模块语句可以是以下形式
mod foo 'PATH'
它从 PATH
加载模块的源文件,而不是从常规位置。在 PATH
中,开头的 ~/
被替换为当前用户的家目录。
只有根 justfile
才会加载环境文件,并且加载的环境变量在子模块中可用。影响环境文件加载的子模块设置将被忽略。
没有 [no-cd]
属性的子模块中的 recipe 将以包含子模块源文件的目录作为工作目录运行。
justfile()
和 justfile_directory()
总是返回根 justfile
的路径和包含它的目录,即使在从子模块 recipe 调用时也是如此。
可以在 mod
关键字后放置一个 ?
来使模块可选。
mod? foo
对于可选模块缺失的源文件不会产生错误。
没有源文件的可选模块不会冲突,因此您可以有多个具有相同名称的 mod 语句,只要最多只有一个源文件存在即可。
mod? foo 'bar.just'
mod? foo 'baz.just'
请参阅模块稳定跟踪问题获取更多信息。
隐藏justfile
just
会查找名为justfile
和.justfile
的justfile
,这可以用来隐藏justfile
。
Just 脚本
通过在justfile
的顶部添加shebang行并使其可执行,可以将just
用作脚本的解释器。
$ cat > script <<EOF
#!/usr/bin/env just --justfile
foo:
echo foo
EOF
$ chmod +x script
$ ./script foo
echo foo
foo
当执行带有shebang的脚本时,系统会将脚本的路径作为参数传递给shebang中的命令。因此,如果shebang是#!/usr/bin/env just --justfile
,则命令将是/usr/bin/env just --justfile PATH_TO_SCRIPT
。
使用上述shebang,just
会将工作目录更改为脚本的所在位置。如果您希望保持工作目录不变,请使用#!/usr/bin/env just --working-directory . --justfile
。
注意:操作系统之间的shebang行拆分并不一致。以下示例仅在macOS上进行了测试。在Linux上,您可能需要将-S
标志传递给env
#!/usr/bin/env -S just --justfile
default:
echo foo
格式化和转储justfile
每个justfile
都有关于空白符和新行的规范格式。
您可以使用当前不稳定的--fmt
标志用规范格式覆盖当前justfile
$ cat justfile
# A lot of blank lines
some-recipe:
echo "foo"
$ just --fmt --unstable
$ cat justfile
# A lot of blank lines
some-recipe:
echo "foo"
使用just --fmt --check --unstable
调用运行--fmt
的检查模式。如果格式正确,just
将退出并返回0,如果格式不正确,则退出并打印diff。
您可以使用--dump
命令将格式化的justfile
输出到stdout
$ just --dump > formatted-justfile
使用--dump
命令与--dump-format json
可以打印justfile
的JSON表示。
回退到父justfile
如果在justfile
中找不到配方,并且已设置fallback
设置,则just
将查找父目录中的justfile
,直到达到根目录。just
将在遇到fallback
设置为false
或未设置justfile
时停止。
例如,假设当前目录包含此justfile
set fallback
foo:
echo foo
并且父目录包含此justfile
bar:
echo bar
$ just bar
Trying ../justfile
echo bar
bar
避免参数拆分
给定此justfile
foo argument:
touch {{argument}}
以下命令将创建两个文件,some
和 argument.txt
$ just foo "some argument.txt"
用户shell会将"some argument.txt"
视为单个参数,但当just
将touch {{argument}}
替换为touch some argument.txt
时,引号没有被保留,并且touch
将接收两个参数。
有几种方法可以避免这种情况:使用引号、位置参数和导出参数。
使用引号
可以在{{argument}}
插值周围添加引号
foo argument:
touch '{{argument}}'
这保留了just
在运行之前捕获变量名错误的能力,例如如果您要写入{{argument}}
,但如果argument
的值包含单引号,则不会执行您想要的操作。
位置参数
positional-arguments
设置会导致所有参数都以位置参数的形式传递,允许它们通过$1
、$2
、…、和$@
访问,然后可以双引号以避免shell进一步分割
set positional-arguments
foo argument:
touch "$1"
这会阻止just
捕获错误,例如如果您输入$2
而不是$1
,但对于所有可能的argument
值都有效,包括包含双引号的价值。
导出参数
当设置export
时,将导出所有参数
set export
foo argument:
touch "$argument"
或者可以使用$
前缀来导出单个参数
foo $argument:
touch "$argument"
这会阻止just
捕获错误,例如如果您输入$argumant
,但对于所有可能的argument
值都有效,包括包含双引号的价值。
配置Shell
有几种方法可以配置shell以使用行级配方,这是当配方不以#!
shebang开头时的默认设置。它们的优先级从高到低为
--shell
和--shell-arg
命令行选项。传递这两个选项之一将导致just
忽略当前justfile中的任何设置。设置Windows-shell:= [...]
set windows-powershell
(已弃用)设置shell:= [...]
由于set windows-shell
的优先级高于set shell
,您可以使用set windows-shell
在Windows上选择shell,并使用set shell
在选择所有其他平台上的shell。
时间戳
just
可以在每个配方命令之前打印时间戳
recipe:
echo one
sleep 2
echo two
$ just --timestamp recipe
[07:28:46] echo one
one
[07:28:46] sleep 2
[07:28:48] echo two
two
默认情况下,时间戳格式为 HH:MM:SS
。格式可以通过 --timestamp-format
进行更改。
$ just --timestamp recipe --timestamp-format '%H:%M:%S%.3f %Z'
[07:32:11:.349 UTC] echo one
one
[07:32:11:.350 UTC] sleep 2
[07:32:13:.352 UTC] echo two
two
--timestamp-format
的参数是一个 strftime
风格的格式字符串,有关详细信息,请参阅 chrono
库文档。
变更日志
最新版本的变更日志可在 CHANGELOG.md 中找到。以前版本的变更日志可在 版本页面 上找到。使用 just --changelog
也可以让 just
二进制文件打印其变更日志。
杂项
文件更改时重新运行食谱
watchexec
可在文件更改时重新运行任何命令。
当任何文件更改时重新运行 foo
食谱
watchexec just foo
有关更多信息,包括如何指定应监视哪些文件以进行更改,请参阅 watchexec --help
。
并行运行任务
可以使用 GNU parallel 并行运行任务
parallel:
#!/usr/bin/env -S parallel --shebang --ungroup --jobs {{ num_cpus() }}
echo task 1 start; sleep 3; echo task 1 done
echo task 2 start; sleep 3; echo task 2 done
echo task 3 start; sleep 3; echo task 3 done
echo task 4 start; sleep 3; echo task 4 done
Shell 别名
为了实现闪电般的命令执行速度,请将 alias j=just
添加到您 shell 的配置文件中。
在 bash
中,别名命令可能不会保留下一节中描述的 shell 完成功能。要将别名命令的完成功能与 just
相同,请将以下行添加到您的 .bashrc
中
complete -F _just -o bashdefault -o default j
Shell 完成脚本
Bash、Elvish、Fish、Nushell、PowerShell 和 Zsh 的 shell 完成脚本可在 发布存档 中找到。
just
二进制文件还可以使用 just --completions SHELL
在运行时生成相同的完成脚本
$ just --completions zsh > just.zsh
有关如何安装它们的说明,请参阅您 shell 的文档。
macOS 注意: macOS 的最新版本使用 zsh 作为默认 shell。如果您使用 Homebrew 安装 just
,它将自动将最新的 zsh 完成脚本复制到 Homebrew zsh 目录中,这是 zsh 内置版本默认不知道的。如果可能的话,最好使用此脚本副本,因为它将在您通过 Homebrew 更新 just
时更新。此外,许多其他 Homebrew 软件包使用相同的完成脚本位置,并且内置的 zsh 也不知道这些。为了在这种情况下利用 zsh 中的 just
完成功能,您可以在调用 compinit
之前将 fpath
设置为 Homebrew 位置。请注意,Oh My Zsh 默认运行 compinit
。因此,您的 .zshrc
文件可能如下所示
# Init Homebrew, which adds environment variables
eval "$(brew shellenv)"
fpath=($HOMEBREW_PREFIX/share/zsh/site-functions $fpath)
# Then choose one of these options:
# 1. If you're using Oh My Zsh, you can initialize it here
# source $ZSH/oh-my-zsh.sh
# 2. Otherwise, run compinit yourself
# autoload -U compinit
# compinit
手册页
just
可以使用 just --man
命令打印其自己的手册页。手册页是用 roff
编写的,这是一种古老的标记语言,也是 Unix 最早的实际应用之一。如果您已安装了 groff
,则可以使用以下命令查看手册页:just --man | groff -mandoc -Tascii | less
。
语法
可以在 GRAMMAR.md 中找到 justfile
的非规范性语法。
just.sh
在 just
成为一个复杂的 Rust 程序之前,它是一个微小的 shell 脚本,调用 make
。您可以在 contrib/just.sh 中找到旧版本。
全局和用户 justfile
如果您希望某些菜谱在各个地方都可用,您有几种选择。
全局 Justfile
just --global-justfile
或简写为 just -g
,会按顺序搜索以下路径以查找 justfile:
$XDG_CONFIG_HOME/just/justfile
$HOME/.config/just/justfile
$HOME/justfile
$HOME/.justfile
您可以将跨多个项目使用的菜谱放在全局 justfile 中,以便轻松从任何目录调用它们。
用户 justfile 小贴士
您还可以采用以下工作流程中的某些方法。以下提示假设您已在 ~/.user.justfile
中创建了一个 justfile
,但您可以将此 justfile
放在系统上的任何方便的位置。
菜谱别名
如果您想通过名称调用 ~/.user.justfile
中的菜谱,并且不介意为每个菜谱创建别名,请将以下内容添加到您的 shell 初始化脚本中:
for recipe in `just --justfile ~/.user.justfile --summary`; do
alias $recipe="just --justfile ~/.user.justfile --working-directory . $recipe"
done
现在,如果您在 ~/.user.justfile
中有一个名为 foo
的菜谱,您只需在命令行中键入 foo
即可运行它。
我花了很长时间才意识到可以创建这样的菜谱别名。尽管我有些迟钝,但我非常高兴能带来这项在 justfile
技术方面的重大进步。
转发别名
如果您不想为每个菜谱创建别名,您可以创建一个单独的别名:
alias .j='just --justfile ~/.user.justfile --working-directory .'
现在,如果您在 ~/.user.justfile
中有一个名为 foo
的菜谱,您只需在命令行中键入 .j foo
即可运行它。
我非常确信实际上没有人使用这个功能,但它确实存在。
¯\_(ツ)_/¯
自定义
您可以使用附加选项自定义上述别名。例如,如果您希望您的 justfile
中的菜谱在您的家目录中运行,而不是当前目录中
alias .j='just --justfile ~/.user.justfile --working-directory ~'
Node.js package.json
脚本兼容性
以下导出语句使 just
菜谱能够访问本地 Node 模块二进制文件,并使 just
菜谱命令的行为更像 Node.js package.json
文件中的 script
条目。
export PATH := "./node_modules/.bin:" + env_var('PATH')
Windows 上的路径
在 Windows 上,返回路径的函数将返回以 \
分隔的路径。当不使用 PowerShell 或 cmd.exe
时,应将这些路径引起来,以防止将 \
解释为字符转义。
ls:
echo '{{absolute_path(".")}}'
远程 Justfiles
如果您想在多个justfiles
中包含一个mod
或import
源文件,而不需要重复它,您可以使用可选的mod
或import
,以及一个用于获取模块源的配方。
import? 'foo.just'
fetch:
curl https://raw.githubusercontent.com/casey/just/master/justfile > foo.just
给定上述justfile
,运行just fetch
后,foo.just
中的配方将可用。
替代方案和现有技术
命令执行者并不少见!一些与just
或多或少类似的替代品包括
- make:启发
just
的Unix构建工具。有几个现代的make
后裔,包括FreeBSD Make和GNU Make。 - task:用Go编写的基于YAML的命令执行器。
- maid:用JavaScript编写的基于Markdown的命令执行器。
- microsoft/just:用JavaScript编写的基于JavaScript的命令执行器。
- cargo-make:Rust项目的命令执行器。
- mmake:带有许多改进的
make
包装器,包括远程包含。 - robo:用Go编写的基于YAML的命令执行器。
- mask:用Rust编写的基于Markdown的命令执行器。
- makesure:用AWK和shell编写的简单且便携的命令执行器。
- haku:用Rust编写的类似make的命令执行器。
贡献
just
欢迎您的贡献!just
在最大限度的许可CC0公共领域奉献和后备许可下发布,因此您的更改也必须在此许可下发布。
Janus
Janus是一个检查对just
的更改是否会破坏或更改现有justfile
的解释的工具。它收集并分析GitHub上的公共justfile
。
在合并特别大或令人不快的更改之前,应该运行Janus以确保没有破坏。无需担心自己运行Janus,Casey会乐意为您运行需要它的更改。
最低支持的Rust版本
最低支持的Rust版本,或MSRV,是当前的稳定Rust。它可能能在较旧的Rust版本上构建,但这不能保证。
新版本
just
的新版本发布频繁,以便用户能够快速获得新功能。
发布提交信息使用以下模板
Release x.y.z
- Bump version: x.y.z → x.y.z
- Update changelog
- Update changelog contributor credits
- Update dependencies
- Update version references in readme
常见问题解答
Just避免了Make的哪些怪癖?
make
有一些行为可能是令人困惑、复杂或使其不适合作为通用命令执行器使用的。
一个例子是,在某种情况下,make
实际上不会在配方中运行命令。例如,如果您有一个名为test
的文件,以及以下makefile
test:
./test
make
将拒绝运行您的测试
$ make test
make: `test' is up to date.
make
假设 test
脚本会生成一个名为 test
的文件。由于该文件存在且脚本没有其他依赖,make
认为没有要做的事情,因此退出。
公平地说,当使用 make
作为构建系统时,这种行为是可取的,但作为命令执行器时则不是。您可以使用 make
内置的 PHONY
目标名称 来禁用这种特定目标的行为,但其语法冗长且难以记忆。将伪目标显式列表(与配方定义分开编写)也引入了意外定义新非伪目标的风险。在 just
中,所有配方都被视为伪目标。
make
的其他一些特性包括赋值中 =
和 :=
的区别,错误信息混淆,如果您搞错了 makefile,则需要 $$
来在配方中使用环境变量,以及不同版本的 make
之间的不兼容性。
Just 和 Cargo 构建脚本之间的关系是什么?
cargo
构建脚本 有一个非常具体的用途,即控制 cargo
如何构建 Rust 项目。这可能包括向 rustc
调用添加标志,构建外部依赖项,或运行某种类型的代码生成步骤。
另一方面,just
用于开发过程中可能运行的杂项命令。例如,以不同配置运行测试、代码检查、将构建工件推送到服务器、删除临时文件等。
此外,尽管 just
用 Rust 编写,但它可以用于任何语言或构建系统的项目。
进一步思考
我个人发现为几乎每个项目编写 justfile
非常有用,无论项目大小。
在大型项目中有多个贡献者时,拥有一个包含所有工作所需命令的文件非常方便。
可能存在不同的命令来测试、构建、代码检查、部署等,将它们都放在一个地方很有用,可以减少告诉人们要运行哪些命令以及如何输入的时间。
此外,有一个容易放置命令的地方,你可能会想出其他有用的东西,这些都是项目集体智慧的一部分,但尚未写下来,例如用于某些版本控制工作流程的部分的神秘命令、安装项目所有依赖项或所有可能需要传递给构建系统的随机标志。
配方的一些想法
-
部署/发布项目
-
发布模式与调试模式之间的构建
-
以调试模式或启用日志记录的方式运行
-
复杂的 Git 工作流程
-
更新依赖项
-
运行不同的测试集,例如快速测试与慢速测试,或以详细输出运行它们
-
任何复杂的命令集,您真的应该写下来,如果只是为了记住它们
即使是小型个人项目,也能通过名称记住命令而不是在Shell历史记录中进行反向搜索,这已经很方便了。如果能够进入一个用随机语言编写的旧项目,并知道你需要的所有命令都在justfile
中,那将是一大福音。如果你输入just
,可能会发生一些有用(至少是有趣的)事情。
关于菜谱的想法,可以查看这个项目的justfile
,或者野外的一些justfile
。
无论如何,我想这就是关于这份非常冗长的README的所有内容了。
希望您喜欢使用just
,并在您的计算活动中取得巨大的成功和满足感!
😸
依赖关系
~0.9–2MB
~25K SLoC