iT邦幫忙

2023 iThome 鐵人賽

DAY 5
0
AI & Data

Rust 加 MLOps,你說有沒有搞頭?系列 第 5

[Day 05] - Rust 原廠要你命 3000 🧨,Makefile 跑起來啦寶貝

  • 分享至 

  • xImage
  •  

今日份 Ferris

今天要在昨天的模板中加入 Makefile 來幫助我們更好地使用 Rust 提供的各種開發工具,所以附上因為過度使用 make 吸收太多 M 能量而進化成魔人普烏的小螃蟹 Ferris (我到底在說什麼哈哈哈):
https://ithelp.ithome.com.tw/upload/images/20230920/20141304wPK7zGY2ih.png

Rust 工具鏈

安裝 Rust 程式語言的同時會安裝好幾個重要的工具和程式,它們在開發和管理 Rust 項目中扮演著關鍵的角色。
其中每個工具都可以獨當一面,現在結合於一身,根本就是超級武器霸王,程式語言界的要你命 3000!
https://ithelp.ithome.com.tw/upload/images/20230920/20141304HxIKs60Yxk.png

以下將簡單介紹這些工具,並提供一些範例,以更好地理解它們的作用。

  • rustc - Rust 的官方編譯器。
    它的主要職責是將 Rust 程式碼轉換為機器碼,以便在不同平台上運行。
    讓我們看一個簡單的範例,首先在 main.rs 中輸入以下程式碼:

    fn main() {
        println!("Hello, Rust!");
    }
    

    接著就可以使用 rustc 將上面的程式碼編譯成可執行文件:

    rustc main.rs
    

    然後運行生成的可執行文件 ./main,它將輸出 "Hello, Rust!"。

  • rustfmt - Rust 程式碼格式化工具。
    用於自動調整和統一 Rust 程式碼的風格,以使程式碼更易於閱讀並符合慣例。
    例如我們有以下程式碼:

    fn main() {println!("Hello, Rust!");}
    

    運行 rustfmt 就能將其自動調整為更易於閱讀的格式。

  • rustup - Rust 工具鏈管理器。
    用於安裝和管理不同版本的 Rust 工具鏈的工具。
    這對於在多個 Rust 專案之間切換或在不同 Rust 版本之間運行程式碼非常有用。
    前幾天已經示範過如何使用 rustup 安裝 Rust。

  • clippy - Rust 的 Linter。
    用於檢查 Rust 程式碼中的潛在問題和風格問題,並提供改進建議。
    假設有一個名為 main.rs 的 Rust 原始碼文件:

    fn main() {
        let mut my_string = "Hello, World".to_string();
        my_string.push_str("!");
        println!("{}", my_string);
    }
    

    透過 clippy 檢查後可能會生成類似以下的輸出:

    warning: you seem to be trying to use a string literal to build a `String`. Consider using the `to_string` method to create a `String` from a string literal.
     --> src/main.rs:2:24
      |
    2 |     let mut my_string = "Hello, World".to_string();
      |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    warning: unnecessary use of `String::push_str`
     --> src/main.rs:3:5
      |
    3 |     my_string.push_str("!");
      |     ^^^^^^^^^^^^^^^^^^^^^^^^
      |
      = note: `#[warn(clippy::string_lit_as_bytes)]` on by default
      = note: `#[warn(clippy::string_add)]` on by default
    

    在這個範例中,clippy 檢測到了兩個警告:

    • 第一個警告建議使用 to_string 方法來從字符串文字創建 String。
    • 第二個警告指出使用 push_str 是不必要的,因為它附加一個字符串文字而不是 String 變量。

    遵循 clippy 的建議,我們可以改進程式碼,減少潛在的問題並提高程式碼品質。

  • cargo - Rust 的 Package manager 和 Build tool。
    是我們最常會用到的工具,它將上面的各項工具整合,讓我們能更輕鬆地創建、構建、測試和發布 Rust 專案。
    以下是一些常見的 cargo 命令及其詳細說明:

    1. cargo new <project_name>:用於創建一個新的 Rust 專案。
      它會生成一個包含基本結構的資料夾,特別是 src 資料夾,其中包含主要的 Rust 原始碼文件 main.rs。
    2. cargo build:用於構建 Rust 專案。
      它會編譯專案的原始碼並生成可執行文件。
      如果專案依賴於外部函式庫,這裡也會下載和編譯這些外部函式庫。
    3. cargo run:用於構建和運行 Rust 專案。
      它將自動執行 cargo build 以編譯程式碼,然後運行生成的可執行文件。
    4. cargo test:用於運行 Rust 項目的測試套件。
      如果專案包含單元測試或整合測試,使用此命令可以執行這些測試。
    5. cargo fmt:使用前面介紹的 rustfmt,使不同開發者的程式碼風格保持一致。
    6. cargo clippy:使用前面介紹的 clippy,旨在檢測程式碼中的潛在問題、錯誤和不良實踐。
    7. cargo check:用於快速檢查 Rust 專案的程式碼,不需要進行完整的編譯和構建。
      這有助於快速檢測程式碼中的錯誤,而不浪費時間進行編譯。
    8. cargo update:用於將專案的依賴函式庫更新至最新版本。
      它會檢查依賴庫的最新版本並更新 Cargo.toml 文件中的相應版本號。
    9. cargo publish:若是正在開發 Rust 函式庫,這個命令可以把函式庫發布到 crates.io (Rust 的官方套件託管中心)。

    總的來說,cargo 是 Rust 開發的核心工具之一,它使得管理依賴函式庫、構建程式碼、運行測試等工作變得簡單且高效。

Makefile

為了更好地利用上面介紹的工具,我們可以把開發常見的流程與指令整合在 Makefile 中,進一步提升我們的工作效率。
而今天我們要加到模板中的 Makefile 內容如下:

.PHONY: version run test format lint release all

# Define ANSI escape codes for colors and formatting
RESET_COLOR = \033[0m
BOLD = \033[1m
RED = \033[91m
GREEN = \033[92m
YELLOW = \033[93m
BLUE = \033[94m

version:
	@echo "$(BOLD)Rust CLI Versions:$(RESET_COLOR)"
	@echo "------------------"
	@echo "$(BLUE)rustc (compiler):$(RESET_COLOR)            $$(rustc --version | sed 's/rustc //' | tr -d '\n')"
	@echo "$(BLUE)cargo (package manager):$(RESET_COLOR)     $$(cargo --version | sed 's/cargo //' | tr -d '\n')"
	@echo "$(BLUE)rustfmt (code formatter):$(RESET_COLOR)    $$(rustfmt --version | sed 's/rustfmt //' | tr -d '\n')"
	@echo "$(BLUE)clippy (linter):$(RESET_COLOR)             $$(clippy-driver --version | sed 's/clippy //' | tr -d '\n')"
	@echo "$(BLUE)rustup (toolchain manager):$(RESET_COLOR)  $$(rustup --version 2>/dev/null | sed 's/rustup //' | tr -d '\n')"

format:
	@echo "$(BLUE)$(BOLD)Formatting code...$(RESET_COLOR)"
	@cargo fmt --quiet

lint:
	@echo "$(YELLOW)$(BOLD)  Running linter...$(RESET_COLOR)"
	@cargo clippy --quiet

test:
	@echo "$(GREEN)$(BOLD)    Running Rust tests...$(RESET_COLOR)"
	@cargo test --quiet 2>&1 | \
		grep -E '^test result' | \
		sed 's/^/    /' | \
		sed -E 's/(ok)/\x1b[32m\1\x1b[0m/g; s/(FAILED)/\x1b[31m\1\x1b[0m/g'

run:
	@echo "$(RED)$(BOLD)Running the Rust program...$(RESET_COLOR)"
	@cargo run --quiet

release:
	@echo "$(BOLD)Building in release mode...$(RESET_COLOR)"
	@cargo build --release

all: format lint test run
	@echo "$(RESET_COLOR)$(BOLD)All tasks completed.$(RESET_COLOR)"

讓我們分解這個 Makefile 的主要部件:

  • .PHONY
    .PHONYMakefile 中的一個特殊目標 (target),用於聲明某些目標為 "虛擬"(phony) 的,也就是說它們不代表實際的文件名。
    這是為了確保即使存在同名的文件,Makefile 仍會執行相應的命令。
  • ANSI 轉義碼
    ANSI 轉義碼用於控制終端中的文本顏色和格式。
    在此 RESET_COLORBOLDREDGREENYELLOWBLUE 都屬於此類轉義碼。
  • 目標
    每個目標在 Makefile 中都對應於一個特定的任務或操作,可以通過執行 make 命令並指定目標名稱來執行。
    以下是每個目標的解釋:
    • version:使用彩色輸出顯示各種與 Rust 相關的工具的版本信息。
    • format:運行 cargo fmt 命令來格式化 Rust 程式碼。
    • lint:運行 cargo clippy 命令對 Rust 程式碼執行檢查。
    • test:使用 cargo test 命令執行 Rust 測試,並使其縮排與以彩色輸出測試結果。
    • run:使用 cargo run 命令運行 Rust 程序並顯示其輸出。
    • release:使用 cargo build --release 命令以發布模式構建 Rust 項目。
    • all:是一個元目標,它依賴於 formatlinttestrun,實際上會依序執行這些操作,並在最後顯示一條消息表示所有任務已完成。

命令之前的 @ 符號用於抑制在終端中顯示命令本身,確保只顯示輸出結果。

實際範例

Makefile 加入模板之後,已經可以用它來開啟每個專案了,流程如下:

  1. 用模板建立新的 GitHub Repository:
    https://ithelp.ithome.com.tw/upload/images/20230920/20141304dPBMnGK8aY.png
  2. 使用 Codespace 開啟,或 clone 到本機。
  3. 使用 cargo init --name=<...> 原地初始化新專案,這裡以 cargo init --name=hello-world 為例,此時資料夾結構如下:
    .
    ├── .devcontainer
    │   ├── devcontainer.json
    │   └── Dockerfile
    ├── Makefile
    ├── Cargo.toml
    ├── src
    │   └── main.rs
    └── setup.sh
    

    也可以用 cargo new 建立新專案,並 cd 進去,但要記得把 Makefile 放進生成的資料夾中。

  4. 此時 main.rs 檔案中有最基本的 hello world 程式碼,可以利用 make all 測試一下我們的 Makefile
    https://ithelp.ithome.com.tw/upload/images/20230920/20141304RqRDHNeVka.png
    另外也可以用 make version 看看各個工具的版本:
    https://ithelp.ithome.com.tw/upload/images/20230920/20141304En7OLqcujK.png

總的來說,這個 Makefile 提供了一個方便的方式來管理和自動化 Rust 專案中的常見任務,如格式化、檢查、測試、運行以及以發布模式構建專案,並使用彩色文本輸出提供了用戶友好和視覺上吸引人的界面。

今日小結

今天我們在模板中加入了 Makefile,它可以幫助我們節省時間,並確保每個操作都按照預期運行。
尤其是 make all 中的流程確保了程式碼的可讀性、可維護性、可靠性和性能。
經常執行這些工作並解決問題可以幫助減少錯誤,提高程式碼品質,並維護良好的程式碼基礎。

在 MLOps 中持續整合 (Continuous Integration) 也是很重要的一環,所以明天我們要以此為基礎設定 GitHub Action。
明天見啦!
/images/emoticon/emoticon24.gif


上一篇
[Day 04] - 走到哪用到哪 🏃,Rust MLOps GitHub 模板與在容器中開發
下一篇
[Day 06] - 無敵風火輪 🌪️ GitHub Action 讓 Rust CI 轉起來
系列文
Rust 加 MLOps,你說有沒有搞頭?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言