如何組織大型 Rust 程式碼庫

banq發表於2024-07-19

隨著 Rust 專案規模的擴大,需要付出不少努力才能保持其清潔狀態,不會妨礙您和您的同事的工作效率。

這就是為什麼我決定分享我用來管理大型 Rust 程式碼庫並避免複雜性和技術債務的簡單規則。

要牢記的最終目標是,任何使用您的程式碼庫的人都應該能夠開啟根資料夾並感到輕鬆自在:一切都應該“各歸其位”。

1、提供開發容器
我非常喜歡沙盒和不可變的開發環境,這就是為什麼我的第一條規則是您應該至少提供Dockerfile構建和除錯程式碼庫所需的所有依賴項。

理想情況下,您應該提供一個開發容器,以便任何使用相容程式碼編輯器的人都可以立即開始處理您的程式碼庫。

2、使用工作區
隨著專案的發展,您需要將其拆分為多個包,以減少編譯時間並保持程式碼整潔。為此,Rust 提供了Cargo WorkspacesCargo.lock ,它們是共享相同檔案和目錄的包集target。

我的典型工作空間的組織方式如下:

$ ls my_project
cmd/
    executable-1/
    executable-2/
crates/
    package_1/
    package_2/
    package_3/
Cargo.toml
Cargo.lock
target/

以根目錄為工作區的Cargo.toml檔案。

資料夾中包含專案的cmd不同可執行檔案(帶有檔案的包),例如,等等。main.rsproject-serverproject-worker

crates資料夾(或者,資料夾)中包含libs所有庫、實用程式和其他非可執行檔案。

最後,還可以有幾個輔助資料夾,例如scripts提供各種支援和維護指令碼或docker包含要嵌入 Docker 映象的資產。

3、在工作區級別宣告依賴項
隨著您的專案發展到十幾個包,您不可能讓所有包的依賴項保持同步。這就是為什麼您應該在工作空間中宣告依賴項( version, ...)並在包中使用它們。featuresCargo.tomlxx = { workspace = true }

Cargo.toml

[workspace.dependencies]
something = { version = <font>"=1.0.0", features = ["a", "b", "c"] }

# ...

在您的工作區成員中:

crates/package1/Cargo.toml

[dependencies]
something = { workspace = true }

# ...
它還有助於儲存專案中使用的所有第三方包及其版本的清單。

4、不要使用 Cargo 的預設資料夾結構
預設情況下,cargo使用以下資料夾結構:

my_package/
    src/
        my_package.rs
    Cargo.toml
    README.md

但是,隨著包數量的增加,src一遍又一遍地開啟所有這些子資料夾來訪問程式碼很快就會變得令人厭煩。

這就是為什麼我建議“扁平化”你的包並將程式碼直接放在包的根資料夾中,與檔案一起Cargo.toml:

my_package/
    my_package.rs
    Cargo.toml
    README.md

Cargo.toml

# ...

[lib]
path = <font>"./my_package.rs"

您可以在deno's codebase.中看到它的實際執行。

此規則的唯一例外是如果您有檔案build.rs。在這種情況下,最好保留cargo的標準佈局。

my_package/
    src/
        my_package.rs
    build.rs
    Cargo.toml
    README.md

5、不要在mod.rsandlib.rs檔案中放入任何程式碼
正如我之前所寫mod.rs,你應該避免在和檔案中放置任何程式碼lib.rs。這些檔案應該專門用於調整不同型別和函式的可見性,而應該使用描述性檔名(client.rs,,email.rs... payments.rs)來命名你的程式碼。

為什麼?
Search file因為隨著您的專案不斷增長,包含數十到數百個包和數千個模組,當所有內容都隱藏在數千個不同的檔案中時,使用程式碼編輯器的功能mod.rs將無法找到任何程式碼lib.rs。

6、提供 Makefile
最後,在工作區的根目錄下提供一個是很好的做法Makefile。此檔案的目的不是為了節省您的一些按鍵,而是為了規範構建、測試和維護專案所需的重要且重複的任務,以便任何貢獻者都可以參與維護。

###################################################################################################
# Dev
###################################################################################################
.PHONY: update_dependencies
update_dependencies:
    # ...

.PHONY: audit_dependencies
audit_dependencies:
    # ...

.PHONY: clean
clean:
    # ...

###################################################################################################
# Build
###################################################################################################
.PHONY: build
build:
    # ...

.PHONY: docker_build
docker_build:
    # ...

當一切都被編碼後,專案的維護就不再是少數巫師呼叫沒人能理解的奇怪命令列的特權了。

 

相關文章