Just:告別 Makefile 的現(xiàn)代命令行任務(wù)運(yùn)行器
本文推薦的一個(gè)輕量級(jí)命令行工具--Just,它提供了一種簡單高效的方式來管理項(xiàng)目任務(wù),類似于傳統(tǒng)的 Make 工具,但具有更簡潔的語法和更現(xiàn)代化的功能。
我目前在一些小項(xiàng)目中開始使用它來管理一些日常的任務(wù),非常方便,它是基于Rust開發(fā)的工具,
所以它在Windows系統(tǒng)中使用也非常方便。
Just簡介
Just是一個(gè)簡單而強(qiáng)大的命令運(yùn)行器,它允許你將項(xiàng)目中常用的命令保存在一個(gè)名為justfile的文件中。
與傳統(tǒng)的Make工具類似, 但是Just提供了更簡潔的語法和更靈活的功能。
主要包括:
- 跨平臺(tái)支持(
Linux、macOS、Windows) - 錯(cuò)誤信息清晰具體
- 支持命令行參數(shù)和環(huán)境變量
- 自動(dòng)補(bǔ)全功能
- 無需聲明
.PHONY目標(biāo) - 可從項(xiàng)目任意子目錄調(diào)用
如果你平時(shí)也用Makefile來管理項(xiàng)目,那么上手Just會(huì)非常快。
Just支持多種操作系統(tǒng),包括 Linux、MacOS 和 Windows,并且無需額外依賴,它的目標(biāo)是讓命令管理變得簡單、直觀且易于維護(hù)。
它常用命令組織在名為justfile的文件中,通過簡潔的語法定義任務(wù)(稱為"配方"),然后通過 just 命令運(yùn)行這些任務(wù)。
主要組成部分
justfile是Just的核心,它包含了所有可運(yùn)行的命令(也稱為配方)。
一個(gè)典型的justfile包括以下幾個(gè)部分:
- 配方定義:每個(gè)配方定義了一個(gè)可執(zhí)行的命令序列。
- 變量定義:用于存儲(chǔ)和復(fù)用的值。
- 設(shè)置:用于控制
Just行為的配置選項(xiàng)。 - 注釋:用于解釋配方或變量的作用。
以下是一個(gè)簡單的justfile示例:
# 這是一個(gè)注釋
build:
echo "Building project..."
cargo build
test:
echo "Running tests..."
cargo test
在這個(gè)例子中,build和test是兩個(gè)配方,分別用于構(gòu)建和測試項(xiàng)目。
基本語法
justfile的語法非常直觀,而且和Makefile非常類似。
最簡單的例子如下:
# 這是一個(gè)注釋
hello:
@echo "Hello, Just!"
命令行中運(yùn)行結(jié)果:
$ just
Hello, Just!
變量的使用
變量是我們編寫配方時(shí)最常用的功能,Just支持多種變量的類型。
變量可以通過:= 進(jìn)行賦值,并在配方中通過{{變量名}}的方式進(jìn)行引用。
- 普通變量
version := "1.0.0"
test:
@echo {{version}}
運(yùn)行結(jié)果:
$ just test
1.0.0
- 路徑拼接
config_dir := "config"
config_file := config_dir / "settings.toml"
test:
@echo {{config_dir}}
@echo {{config_file}}
運(yùn)行結(jié)果:
$ just test
config
config/settings.toml
- 變量插值
version := "1.0.0"
deploy:
scp build/app-{{version}}.tar.gz server:/apps
執(zhí)行時(shí),scp命令中的{{version}}會(huì)替換成version變量的實(shí)際值。
- 命令行覆蓋變量
寫在justfile中的變量并不是固定的,可以通過命令行來傳入不同的值,比如第一個(gè)示例中:
version := "1.0.0"
test:
@echo {{version}}
$ just test
1.0.0
$ just version=2.0.0 test
2.0.0
- 環(huán)境變量
path := env_var('PATH')
# 訪問環(huán)境變量
show_path:
echo "PATH Var: {{path}}"
通過內(nèi)置的env_var函數(shù)可以訪問環(huán)境變量。
條件判斷
條件判斷可以讓我們編寫配方時(shí)更加靈活,比如針對(duì)不同的平臺(tái)編譯不同的二進(jìn)制。
build_type := if os() == "windows" { "exe" } else { "bin" }
build:
@echo "可執(zhí)行文件的后綴: {{build_type}}"
我是windows系統(tǒng),執(zhí)行結(jié)果如下:
$ just build
可執(zhí)行文件的后綴: exe
如果條件分支比較多,可以使用else if,比如:
arch := if arch() == "x86_64" {
"amd64"
} else if arch() == "aarch64" {
"arm64"
} else {
error("Unsupported architecture")
}
內(nèi)置函數(shù)
Just中內(nèi)置了很多函數(shù),方便我們?cè)诰帉懭蝿?wù)時(shí),獲取一些必要的信息。
比如上面示例中使用的os()和arch(),都是內(nèi)置函數(shù)。
| 函數(shù) | 描述 | 備注 |
|---|---|---|
| arch() | 指令集結(jié)構(gòu) | "aarch64", "arm", "asmjs", "hexagon", "mips", "msp430", "powerpc", "powerpc64", "s390x", "sparc", "wasm32", "x86", "x86_64", 和 "xcore" |
| os() | 操作系統(tǒng) | "android", "bitrig", "dragonfly", "emscripten", "freebsd", "haiku", "ios", "linux", "macos", "netbsd", "openbsd", "solaris", 和 "windows" |
| os_family() | 操作系統(tǒng)系列 | "unix" 和 "windows" |
| env_var(key) | 獲取名稱為 key 的環(huán)境變量 | 如果不存在則終止 |
| env_var_or_default(key, default) | 獲取名稱為 key 的環(huán)境變量 | 如果不存在則返回 default |
| invocation_directory() | 獲取 just 被調(diào)用時(shí)當(dāng)前目錄所對(duì)應(yīng)的絕對(duì)路徑 | - |
| justfile() | 取得當(dāng)前 justfile 的路徑 | - |
| justfile_directory() | 取得當(dāng)前 justfile 文件父目錄的路徑 | - |
| just_executable() | just 可執(zhí)行文件的絕對(duì)路徑 | - |
| quote(s) | 用單引號(hào)包裹字符串并轉(zhuǎn)義內(nèi)部單引號(hào) | |
| replace(s, from, to) | 替換字符串中的所有匹配項(xiàng) | |
| replace_regex(s, regex, repl) | 使用正則表達(dá)式替換字符串 | |
| trim(s) | 移除首尾空白字符 | |
| trim_end(s) | 移除尾部空白字符 | |
| trim_end_match(s, substr) | 移除匹配的后綴 | |
| trim_end_matches(s, substr) | 重復(fù)移除匹配的后綴 | |
| trim_start(s) | 移除首部空白字符 | |
| trim_start_match(s, substr) | 移除匹配的前綴 | |
| trim_start_matches(s, substr) | 重復(fù)移除匹配的前綴 | |
| capitalize(s) | 首字母大寫其余小寫 | "hello"->"Hello" |
| kebabcase(s) | 轉(zhuǎn)換為 kebab-case | "fooBar"->"foo-bar" |
| lowercamelcase(s) | 轉(zhuǎn)換為 lowerCamelCase | "Foo_bar"->"fooBar" |
| lowercase(s) | 轉(zhuǎn)換為全小寫 | "HeLLo"->"hello" |
| shoutykebabcase(s) | 轉(zhuǎn)換為 SHOUTY-KEBAB-CASE | "fooBar"->"FOO-BAR" |
| shoutysnakecase(s) | 轉(zhuǎn)換為 SHOUTY_SNAKE_CASE | "fooBar"->"FOO_BAR" |
| snakecase(s) | 轉(zhuǎn)換為 snake_case | "fooBar"->"foo_bar" |
| titlecase(s) | 轉(zhuǎn)換為 Title Case | "hello world"->"Hello World" |
| uppercamelcase(s) | 轉(zhuǎn)換為 UpperCamelCase | "foo_bar"->"FooBar" |
| uppercase(s) | 轉(zhuǎn)換為全大寫 | "hello"->"HELLO" |
| absolute_path(path) | 將相對(duì)路徑轉(zhuǎn)為絕對(duì)路徑 | |
| extension(path) | 獲取文件擴(kuò)展名 | |
| file_name(path) | 獲取文件名(含擴(kuò)展名) | |
| file_stem(path) | 獲取文件名(不含擴(kuò)展名) | |
| parent_directory(path) | 獲取父目錄路徑 | |
| without_extension(path) | 獲取不含擴(kuò)展名的路徑 | |
| clean(path) | 簡化路徑(移除冗余部分) | |
| join(a, b…) | 拼接路徑(自動(dòng)處理分隔符) | |
| path_exists(path) | 檢查路徑是否存在 | |
| error(message) | 終止執(zhí)行并顯示錯(cuò)誤消息 | |
| sha256(string) | 計(jì)算字符串的SHA-256哈希值(十六進(jìn)制) | |
| sha256_file(path) | 計(jì)算文件的SHA-256哈希值(十六進(jìn)制) | |
| uuid() | 生成隨機(jī)UUID |
執(zhí)行系統(tǒng)命令
justfile中,可以通過反引號(hào)來執(zhí)行系統(tǒng)命令,比如:
current_branch := `git branch --show-current`
deploy:
echo "Deploying branch {{current_branch}}"
與Makefile的比較
最后,整理了justfile與傳統(tǒng)的Makefile相比,在特性方面的不同和改進(jìn),供參考:
| 特性 | Just | Make |
|---|---|---|
| 語法 | 簡潔直觀 | 較為復(fù)雜 |
| 跨平臺(tái) | 原生支持 | 需要兼容層 |
| 錯(cuò)誤處理 | 清晰詳細(xì) | 有時(shí)晦澀 |
| 變量作用域 | 統(tǒng)一簡單 | 多種類型 |
| 自動(dòng)補(bǔ)全 | 完善支持 | 有限 |
| .PHONY 聲明 | 不需要 | 需要 |
| 環(huán)境變量 | 內(nèi)置支持 | 需要額外處理 |
| 現(xiàn)代功能 | 條件、函數(shù)等 | 有限 |
Just的優(yōu)勢(shì)主要體現(xiàn)在:
- 避免 Make 的"up to date"問題
- 更友好的錯(cuò)誤信息
- 內(nèi)置函數(shù)和環(huán)境變量支持
- 更簡潔的變量系統(tǒng)
- 無需聲明偽目標(biāo)
如果你的項(xiàng)目也有Makefile的需求,不妨試試用justfile來試試!

浙公網(wǎng)安備 33010602011771號(hào)