rust uutils を linux 環境で build する - 「rust なにそれ?おいしいの?」という状況で始める
関連ページGNU coreutils が rust uutils に置き換えられそうという話題rust uutils (coreutils) を試す その 1rust uutils (coreutils) を試す その 2先の日記で Ubuntu で GNU coreutils を rust uutils に置き換える話題を取り上げた。rust uutils を build する方法を書いていこうと思う。まず重要な注意は「rust の deb package をインストールしてはいけない。インストールしても古いバージョンだと言われて全く使えない。」いきなり雲行きが怪しい展開だ。自分は「rust は頻繁に更新される。/home/$USER/.cargo, /home/$USER/.rustup 以下に配置されるべきもの。」と理解している。こんなツールと環境から coreutils 相当の機能を build するのか...rust で書けば「セキュリティの観点で堅牢」という喧伝は良く聞く、頻繁に外部から流れ込む /home/$USER/ 以下配置の toolchain で build すること自体は問題にしないのか?以降 Ubuntu あるいは deb package を使う派生ディストリビューションで shell に bash を使っている前提で書く。主記憶は 2Gibyte 以上が必須だ(できれば 4Gibyte 有るのが望ましい)。警告: Raspberry Pi model 3 の様に 1Gibyte しか主記憶がなく eMMC や SD card をストレージとして使っている環境での build は全くお勧めしない。swap を追加(増量)してあってもだ。実行した場合は約 2 時間の間 Swap In/Out とも 0 ~ 8Mbytes/secの転送量で継続する。eMMC か SD card の寿命を縮めるか、トドメを刺すだけだ。最低限必要な package を install する。sudo apt install build-essential curl gitrust を install する基本的な手順は Other Rust Installation Methods に従う。手順を従順に実行すると shell に bash を使っているなら ~/.profile と ~/.bashrc が書き換わる。用心をするならバックアップをしておこう。cd ~cp -p .profile .profile-$(date +%s).backupcp -p .bashrc .bashrc-$(date +%s).backup以下作業ディレクトリ ~/rustup-install, ~/git/uu-coreutils を作る。都合が有れば変えて欲しい。rust をインストールするスクリプトをダウンロードして実行する。本家のページではいきなり sh に pipe で流し込む作法だ。危なすぎると思う。一旦ファイルに取り置いてそれから実行する。mkdir -p ~/rustup-installcd ~/rustup-installcurl -o rustup-install.sh https://sh.rustup.rs# if you want to see what will be happen.less ./rustup-install.shsource ./rustup-install.sh実行すると次の様な警告が出る場合がある。既に deb package 版の rust をインストールしている状況だと思われる。y を返答する。info: downloading installerwarn: It looks like you have an existing installation of Rust at:warn: /usr/binwarn: It is recommended that rustup be the primary Rust installation.warn: Otherwise you may have confusion unless you are careful with your PATH.warn: If you are sure that you want both rustup and your already installed Rustwarn: then please reply `y' or `yes' or set RUSTUP_INIT_SKIP_PATH_CHECK to yeswarn: or pass `-y' to ignore all ignorable checks.error: cannot install while Rust is installedContinue? (y/N) y次の質問には標準的なインストールをするので 1 と返答する。~/.profile, ~/.bashrc の書き換えに懸念があるなら 3 を返答し思い止まろう。Current installation options: default host triple: x86_64-unknown-linux-gnu default toolchain: stable (default) profile: default modify PATH variable: yes1) Proceed with standard installation (default - just press enter)2) Customize installation3) Cancel installation>1~/.profile, ~/.bashrc がどのように変更されたか確認する。以下は自分の環境の例だ。一番最後に . "$HOME/.cargo/env" が追加されている。.profile の末尾を確認tail ~/.profile.profile の変更結果例# set PATH so it includes user's private bin if it existsif [ -d "$HOME/bin" ] ; then PATH="$HOME/bin:$PATH"fi# set PATH so it includes user's private bin if it existsif [ -d "$HOME/.local/bin" ] ; then PATH="$HOME/.local/bin:$PATH"fi. "$HOME/.cargo/env".bashrc の末尾を確認tail ~/.bashrc.bashrc の変更結果例# this, if it's already enabled in /etc/bash.bashrc and /etc/profile# sources /etc/bash.bashrc).if ! shopt -oq posix; then if [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fifi. "$HOME/.cargo/env"$HOME/.cargo/env には $HOME/.cargo/bin を PATH 環境変数に加える処理が書かれている。なんだな、sh (bash) script も rust 風に書かないと気が済まないのだろうか?$HOME/.cargo/env の内容:#!/bin/sh# rustup shell setup# affix colons on either side of $PATH to simplify matchingcase ":${PATH}:" in *:"$HOME/.cargo/bin":*) ;; *) # Prepending path in case a system-installed rustc needs to be overridden export PATH="$HOME/.cargo/bin:$PATH" ;;esacインストールされたか確認する。インストール直後は実行ファイル配置場所の環境変数 PATH を手で更新する必要がある。バージョン出力は今の時点なので、さらに新しくなっているだろう。source ~/.cargo/envrustc --versionrustc 1.85.1 (4eb161250 2025-03-15)cargo --versioncargo 1.85.1 (d73d2caf9 2024-12-31)rust uutils/coreutils を git clone して、build する。mkdir -p ~/gitcd ~/gitgit clone https://github.com/uutils/coreutils uu-coreutilscd uu-coreutilscargo build --releasecargo build --debug で debug build できる。Visual Studio の作法とよく似ている。出力先も target/release, target/debug で振り分けされる。生成物を確認しよう。cd target/releasels -latotal 12340drwxrwxr-x 7 furuta furuta 4096 3月 20 11:30 .drwxrwxr-x 4 furuta furuta 4096 3月 20 11:34 ..drwxrwxr-x 56 furuta furuta 4096 3月 20 11:28 build-rw-rw-r-- 1 furuta furuta 0 3月 20 11:28 .cargo-lock-rwxrwxr-x 2 furuta furuta 12507368 3月 20 11:30 coreutils-rw-rw-r-- 1 furuta furuta 12947 3月 20 11:30 coreutils.ddrwxrwxr-x 2 furuta furuta 65536 3月 20 11:30 depsdrwxrwxr-x 2 furuta furuta 4096 3月 20 11:28 examplesdrwxrwxr-x 321 furuta furuta 20480 3月 20 11:28 .fingerprintdrwxrwxr-x 2 furuta furuta 4096 3月 20 11:28 incremental./coreutilscoreutils 0.0.30 (multi-call binary)Usage: coreutils [function [arguments...]] coreutils --listOptions: --list lists all defined functions, one per rowCurrently defined functions: [, b2sum, b3sum, base32, base64, basename, basenc, cat, cksum, comm, cp, csplit, cut, date, dd, df, dir, dircolors, dirname, du, echo, env, expand, expr, factor, false, fmt, fold, hashsum, head, join, link, ln, ls, md5sum, mkdir, mktemp, more, mv, nl, numfmt, od, paste, pr, printenv, printf, ptx, pwd, readlink, realpath, rm, rmdir, seq, sha1sum, sha224sum, sha256sum, sha3-224sum, sha3-256sum, sha3-384sum, sha3- 512sum, sha384sum, sha3sum, sha512sum, shake128sum, shake256sum, shred, shuf, sleep, sort, split, sum, tac, tail, tee, test, touch, tr, true, truncate, tsort, unexpand, uniq, unlink, vdir, wc, yes早速使って見よう。GNU coreutils ls とタイムスタンプ表示が違う。おそらく LANG, LC_TIME 環境変数の扱い方の差がある。./coreutils ls -latotal 12340drwxrwxr-x 7 furuta furuta 4096 Mar 20 11:30 .drwxrwxr-x 4 furuta furuta 4096 Mar 20 11:34 ..-rw-rw-r-- 1 furuta furuta 0 Mar 20 11:28 .cargo-lockdrwxrwxr-x 321 furuta furuta 20480 Mar 20 11:28 .fingerprintdrwxrwxr-x 56 furuta furuta 4096 Mar 20 11:28 build-rwxrwxr-x 2 furuta furuta 12507368 Mar 20 11:30 coreutils-rw-rw-r-- 1 furuta furuta 12947 Mar 20 11:30 coreutils.ddrwxrwxr-x 2 furuta furuta 65536 Mar 20 11:30 depsdrwxrwxr-x 2 furuta furuta 4096 Mar 20 11:28 examplesdrwxrwxr-x 2 furuta furuta 4096 Mar 20 11:28 incrementalUNIX 系 OS を使い始めて恐らく一番始めに覚えるであろう ls コマンドの動作が違うのか... 他にも色々と試してみるか。