いままでRustのパッケージはすべてGuixのパッケージと一対一対応していた。そのため、あるRustパッケージをビルドするためには、 #:cargo-inputs として引数に渡されている依存パッケージをすべてビルドする必要があった(たしかビルドしないというオプションはあったはずだが)。一方Rustのビルドプロセス上、すべての依存はソースコードを利用してコンパイルされるため、依存パッケージがバイナリへビルドされている必要は全くなかった。また、Rustパッケージに対応するGuixパッケージの数も依存の数に応じてどんどん増えていってしまうなど、管理上の問題も多数あった。

しかし2025年にその方針が改められ、バイナリが真に必要なRustパッケージ以外はすべてソースコードのみの依存とすることとなった。これは革命的で、これによってRustのパッケージに対応するGuixパッケージは「ユーザにアプリケーションとして利用されるもの」「Rustパッケージ以外にライブラリとして利用されるもの」くらいになる。これに伴ってRustパッケージの作成もかなり簡単になったので、その方法をここで説明する。

前提条件

チャンネルは既に保持しているものとする。もし持っていない場合は、Guixのパッケージをつくってみよう-その1: 簡単なフォントのパッケージを作るなどを参考に作成してほしい。

要約

  • Rustのパッケージの依存先のみを管理するファイルである mychannel/packages/rust-crates.scm を用意する (初回のみ)。
  • 対象となるパッケージの Cargo.lock (/path/to/Cargo.lock) を入手する。
  • guix import --insert=/path/to/mychannel/packages/rust-crates.scm crate --lockfile=/path/to/Cargo.lock <パッケージ名> を実行する。
  • guix import --insert=/path/to/mychannel/packages/rust-apps.scm crate <パッケージ名> を実行する。
  • (cargo-inputs <パッケージ名>)(cargo-inputs <パッケージ名> #:module '(mychannel packages rust-crates)) に置き換える。
  • #:install-source? #f を設定する。
  • Guix特有の問題に起因するビルドフェーズの修正や、一部テストの無効化などの調整を行う。

Rustのパッケージの依存先のみを管理するファイルを用意する

新しいパッケージング手法では、Rustパッケージの持つあらゆる依存はすべて一つのファイルに保持される。そのファイルにソースコードだけを保持する origin (packagesource フィールドに渡すオブジェクト)、及び各パッケージがどの origin を利用するか(シンボルをキー、依存対象の origin のリストを値とする辞書的なもの)を定義しておき、パッケージ側はそこに定義された依存関係をシンボル名で検索(cargo-inputs)して inputs に渡す形で利用する。

新しい手法でRustのパッケージを作成するためには、このファイルをあらかじめ用意しておく必要がある。テンプレートはGuix公式レポジトリの/guix/etc/teams/rust/rust-crates.tmplにあるので、これをコピーし、あなたのチャンネルの mychannel/packages/rust-crates.scm に配置し、 define-module のモジュール名や署名などを適宜書き換える。このファイルは初めてRustパッケージを作成するときに一度だけ用意すればよく、以後は使い回してよい。以下は rust-crates.tmpl の抜粋である。

  ;;; GNU Guix --- Functional package management for GNU
  ;;; Copyright © 2025 Hilton Chain <hako@ultrarare.space>
  ;;;
  ;;; This file is part of GNU Guix.
  ;;;
  ;;; GNU Guix is free software; you can redistribute it and/or modify it
  ;;; under the terms of the GNU General Public License as published by
  ;;; the Free Software Foundation; either version 3 of the License, or (at
  ;;; your option) any later version.
  ;;;
  ;;; GNU Guix is distributed in the hope that it will be useful, but
  ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  ;;; GNU General Public License for more details.
  ;;;
  ;;; You should have received a copy of the GNU General Public License
  ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

  (define-module (gnu packages rust-crates)
    #:use-module (guix gexp)
    #:use-module (guix packages)
    #:use-module (guix download)
    #:use-module (guix git-download)
    #:use-module (guix build-system cargo)
    #:use-module (gnu packages rust-sources)
    #:export (lookup-cargo-inputs))

  ;;;
  ;;; This file is managed by ‘guix import’.  Do NOT add definitions manually.
  ;;;

  ;;;
  ;;; Rust libraries fetched from crates.io and non-workspace development
  ;;; snapshots.
  ;;;

  (define qqqq-separator 'begin-of-crates)

  (define ssss-separator 'end-of-crates)


  ;;;
  ;;; Cargo inputs.
  ;;;

  (define-cargo-inputs lookup-cargo-inputs)

qqqq-separatorssss-separator の間1origin が定義され、依存関係を探す辞書として lookup-cargo-inputs がエクスポートされる形となっている。依存が追加されるとどのような見た目となるのかは後述する。

依存をソースコードとしてインポートする

まず依存を取得するために、対象の Cargo.lock をなんらかの方法で取得する必要がある。 gitレポジトリなら対象のレポジトリをクローンし、対象のバージョンのタグをチェックアウトする。そこに含まれているであろう Cargo.lock をそのまま用いても問題はないが、 公式のCookbookのRustパッケージの項では、以下のようなコマンドで取得するほうが面倒がないとのことだ。

guix shell rust rust:cargo cargo-audit cargo-license
cargo generate-lockfile
# 以下は取得後のチェック
cargo audit
cargo license

取得できたら、以下のようなコマンドを発行する。 /path/to/mychannel/packages/rust-crates.scm は先ほどRustのパッケージの依存先のみを管理するファイルを用意するで用意したファイルのパスで、 /path/to/Cargo.lock は今取得した Cargo.lock へのパスである。この動作は --lockfile オプションによるものだ。

guix import --insert=/path/to/mychannel/packages/rust-crates.scm crate --lockfile=/path/to/Cargo.lock <パッケージ名>

このコマンドを実行すると、以下のように各依存のソースコードの取得方法及び対象パッケージの依存関係についての情報が追加される。なお、 <パッケージ名> は依存関係の辞書である lookup-cargo-inputs のキーとなるシンボルとしてのみ利用される。

  ;; 前略

  (define qqqq-separator 'begin-of-crates)

  (define rust-<依存パッケージ名>-<依存パッケージのバージョン>
    (crate-source "<依存パッケージ名>" "<依存パッケージのバージョン>"
                  "<ハッシュ値>"))

  ;; 同じようなdefine式が名前順で列挙される
  ;; ...


  ;; (中略)

  (define ssss-separator 'end-of-crates)


  ;;;
  ;;; Cargo inputs.
  ;;;

  (define-cargo-inputs lookup-cargo-inputs
    (<パッケージ名> =>
                  (list rust-<依存パッケージ名>-<依存パッケージのバージョン>
                        ;; 依存先が名前順で列挙される
                        ;; ...
                        ))
    ;; パッケージ名も名前順で列挙される
    ;; ...
    )

TODOコメントが入ることがそれなりにあるが、数がかなり多いのと、特に対処の必要がないケースが多いため、ビルドに失敗したタイミングで確認するのが楽だと思う。一応説明しておくと、現時点でTODOコメントは2種類ある。

Define standalone package if this is a workspace.
crates.ioからではなくgitを取得している場合に出る。 GitレポジトリがRustのworkspaceを用いている場合、ほしいクレートを明示的に指定しないとクレートとして利用できないため、独立したパッケージとして記述しなければならないということのようだが、私自身そうしなければならない状況になったことがなく、最終的にどうするのかはあまりよくわからない(どうも公式マニュアルを見るとそういうパッケージは (gnu packages rust-sources) モジュールに押し込んでいるようだ)。
Check bundled sources.
末尾が -sys-src で終わっているパッケージに出る。 -sys パッケージはC言語など別の言語のライブラリに依存している可能性が高く、 -src パッケージは別の言語のファイルを含む可能性が高いので確認したほうがよい、ということのようだ。

重ねてになるが、別にこの時点で気にする必要はない。

とりあえずここで一度コミットしておくと後に戻りやすい。

本体をGuixパッケージとしてインポートする

これで依存関係の記述が完成したので、いよいよ対象のRustパッケージそれ自体をGuixパッケージとして生成する。といっても先ほどとほぼ同じで、以下のコマンドを実行するだけである。違いは --lockfile の指定がない点と、 --insert する先が違う点のみだ。

guix import --insert=/path/to/mychannel/packages/rust-apps.scm crate <パッケージ名>

rust-crates.scm のほうとは違い、一つのファイルにする必要性があるわけではないので、 --insert については好きなファイルを指定してよい。すると、次のようなパッケージ定義がファイルの末尾に挿入される。以下は texlab というパッケージの例だ。

(define-public texlab
  (package
    (name "texlab")
    (version "4.3.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "texlab" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "0laxg7qprbixp20cqdy824vrxq692c2x92aqigw5a84s0b69dbrn"))))
    (build-system cargo-build-system)
    (inputs (cargo-inputs 'texlab))
    (home-page "https://github.com/latex-lsp/texlab")
    (synopsis "LaTeX Language Server")
    (description "This package provides @code{LaTeX} Language Server.")
    (license license:gpl3)))

ここでは (cargo-inputs 'texlab) として、 辞書のキーとなるパッケージ名が埋め込まれている。

対象のパッケージがcrates.ioに登録されていない場合もある。その場合は、 source フィールドを以下のようにすればよい。 URLやタグについては対象のレポジトリを確認しながら適宜変更すること。タグの先頭に v がなかったり、別のものが付いていたりすることもある。

(source
 (origin
   (method git-fetch)
   (uri (git-reference
          (url "https://github.com/user/repo")
          (commit (string-append "v" version))))
   (file-name (git-file-name name version))
   (sha256
    (base32 "0laxg7qprbixp20cqdy824vrxq692c2x92aqigw5a84s0b69dbrn"))))

ハッシュ値についてはわざわざ調べなくても、とりあえずビルドしてみると正しいハッシュ値と共にエラーが出るので、それをそのまま貼り付けると楽だ。

さて、このままだと動かない点がいくつかあるので、それを説明する。

モジュール定義を書く(各ファイルに対して初回のみ)

パッケージ定義のファイルにはモジュール定義が必要だ。さらに言うと、このパッケージ定義に必要な依存も use-module しなければならない。そのために以下をファイルの先頭に記述する。 (mychannel packages filename) の部分はあなたのチャンネルのルートからの相対パスに合わせてほしい。

(define-module (mychannel packages filename)
  #:use-module (guix packages)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (guix download)
  #:use-module (guix git-download)
  #:use-module (guix build-system cargo))

cargo-inputs にモジュールを指定する

先ほど lookup-cargo-inputs を定義したが、それをどのモジュールにあるか教えなければ当然依存関係を辞書から引くことすらできない。そこで、 inputs フィールドを以下のように変更しなければならない。なお、デフォルトではGuix公式チャンネルの (gnu packages rust-crates) を用いるようになっている。

(define-public texlab
  (package
    (name "texlab")
    (version "4.3.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "texlab" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "0laxg7qprbixp20cqdy824vrxq692c2x92aqigw5a84s0b69dbrn"))))
    (build-system cargo-build-system)
    (inputs (cargo-inputs 'texlab #:module '(mychannel packages rust-crates)))
    (home-page "https://github.com/latex-lsp/texlab")
    (synopsis "LaTeX Language Server")
    (description "This package provides @code{LaTeX} Language Server.")
    (license license:gpl3)))

#:install-source? を無効にする

アプリケーション側のパッケージにはそもそもソースコードのインストールは不要なので、あらかじめ無効にしておいたほうがよい。もし同じクレートに依存する別のパッケージがあったとして、それはそのパッケージをインポートするときに別で rust-crates.scm に追加されるので関係がない。これを行わないと package フェーズでエラーが発生する場合がある(理由は不明)。

(define-public texlab
  (package
    (name "texlab")
    (version "4.3.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "texlab" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "0laxg7qprbixp20cqdy824vrxq692c2x92aqigw5a84s0b69dbrn"))))
    (build-system cargo-build-system)
    (arguments
     (list #:install-source? #f))
    (inputs (cargo-inputs 'texlab #:module '(mychannel packages rust-crates)))
    (home-page "https://github.com/latex-lsp/texlab")
    (synopsis "LaTeX Language Server")
    (description "This package provides @code{LaTeX} Language Server.")
    (license license:gpl3)))

できたパッケージを調整する

これで共通で出るエラーはすべて解消されるはずだが、大半の場合そのままではビルドできないので、以下によくある対処を記載する。特に依存先のパッケージが見つからない/インターネット接続がないと言われるインストールで失敗する/Cargo.tomlがvirtual manifestと言われるについては対処が必要なことがかなり多く、確認も簡単なため、あらかじめ確認しておくことをおすすめする。

Cargo.toml がないと言われる

モノレポを採用しているレポジトリなど、一部のパッケージでは Cargo.toml がレポジトリのルートに対して少し深い階層に位置している場合がある。その場合、 modify-phasesunpack 直後に挟み、カレントディレクトリを変更してあげる必要がある。以下のようにして relative/path/to/source-directory へとディレクトリを切り替える。

(define-public texlab
  (package
    (name "texlab")
    (version "4.3.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "texlab" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "0laxg7qprbixp20cqdy824vrxq692c2x92aqigw5a84s0b69dbrn"))))
    (build-system cargo-build-system)
    (arguments
     (list #:install-source? #f
           #:phases (modify-phases %standard-phases
                      (add-after 'unpack 'change-directory-to-rust-source
                        (lambda _
                          (chdir "relative/path/to/source-directory"))))))
    (inputs (cargo-inputs 'texlab #:module '(mychannel packages rust-crates)))
    (home-page "https://github.com/latex-lsp/texlab")
    (synopsis "LaTeX Language Server")
    (description "This package provides @code{LaTeX} Language Server.")
    (license license:gpl3)))

依存先のパッケージが見つからない/インターネット接続がないと言われる

Cargo.toml[dependencies][patch.crates.io] などでgitレポジトリのコミット指定を用いている場合によく起こる。 Cargo.toml を確認し、 { ..., git = ..., ... }{ ..., rev = "8d0029b4cf8f3b995728614f96c03f6e3dcf4f9e, ... } のような記述があればそれが原因だ。

これを解消するにはビルドが走る前にあらかじめ Cargo.toml を編集し、gitレポジトリへの依存を削除する必要がある。文字列を正規表現で置換することになるので、実際の Cargo.toml と見比べながら書くことになる。以下にGuix公式のCookbookの例を引用する(ハイライトはこちらで付けている)。

(define-public niri
  (package
   (name "niri")
   (version "25.02")
   (source (origin
             (method git-fetch)
             (uri (git-reference
                   (url "https://github.com/YaLTeR/niri")
                   (commit (string-append "v" version))))
             (file-name (git-file-name name version))
             (sha256
              (base32
               "0vzskaalcz6pcml687n54adjddzgf5r07gggc4fhfsa08h1wfd4r"))))
   (build-system cargo-build-system)
   (arguments
    (list #:install-source? #f
          #:phases
          #~(modify-phases %standard-phases
              (add-after 'unpack 'use-guix-vendored-dependencies
                (lambda _
                  (substitute* "Cargo.toml"
                    (("# version =.*")
                     "version = \"*\"")
                    (("git.*optional")
                     "version = \"*\", optional")
                    (("^git = .*")
                     "")))))))
   (native-inputs
    (list pkg-config))
   (inputs
    (cons* clang
           libdisplay-info
           libinput-minimal
           libseat
           libxkbcommon
           mesa
           pango
           pipewire
           wayland
           (cargo-inputs 'niri)))
   (home-page "https://github.com/YaLTeR/niri")
   (synopsis "Scrollable-tiling Wayland compositor")
   (description
    "Niri is a scrollable-tiling Wayland compositor which arranges windows in a
scrollable format.  It is considered stable for daily use and performs most
functions expected of a Wayland compositor.")
   (license license:gpl3+)))

文法としては=arguments= に引数リストを渡すのだが、今回はビルド手順である :phases を修正するため、 #:phases の後ろに modify-phases 式を渡している。 #:install-source? #f はここでは関係ないので無視してよい。 modify-phases の文法について詳細に説明するのがこの記事の趣旨ではないので、私が前に書いたGuixパッケージ定義を作成する記事(これも軽く触れているだけだが)に委ねるとして、 substitute* について軽く説明する。

substitute* は指定したファイルに含まれる特定の文字列を正規表現で指定し、置換する。文法としては以下のようなものだ。

(substitute* "ファイル名"               ; '("ファイル名1" "ファイル名2") のように複数ファイル指定も可能。
                                        ; また、 (find-files "." "\\.go$") のように式も記述可能。
  (("^正規表現.*")
   "置換先文字列")                      ; (which "sh") のような式も記述可能
  ;; 必要であれば複数記述も可能
  ;; (("正規表現")
  ;;  "置換先文字列")
  )

これらを元に Cargo.toml の置換対象としたい部分やそれ以外の部分をじっくりみて、きちんと求めたところだけマッチする正規表現を記述する。今回の場合は gitrev を削除するだけなので、おそらく 置換先文字列 は空文字列のことがほとんどだろう。

インストールで失敗する/Cargo.tomlがvirtual manifestと言われる

Cargo.toml には仮想マニフェスト(virtual manifest)という概念がある。これは、ルートの Cargo.toml[package] セクションがないものを言う。なにも指定しなければGuixはルートのパッケージをインストールしようとするが、仮想マニフェストを採用している場合はパッケージが存在しないためエラーが発生する。

これを解消するには、バイナリやライブラリとしてインストールしたいクレートのディレクトリを #:cargo-install-paths 引数で指定する必要がある。 main.rs を含むディレクトリはバイナリを生成するなどのルールがRustにはあるので、そこからあたりを付けるのがいいだろう。

(define-public texlab
  (package
    (name "texlab")
    (version "4.3.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "texlab" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "0laxg7qprbixp20cqdy824vrxq692c2x92aqigw5a84s0b69dbrn"))))
    (build-system cargo-build-system)
    (arguments
     (list
      #:install-source? #f
      #:cargo-install-paths ''("crates/texlab")))
    (inputs (cargo-inputs 'texlab #:module '(mychannel packages rust-crates)))
    (home-page "https://github.com/latex-lsp/texlab")
    (synopsis "LaTeX Language Server")
    (description "This package provides @code{LaTeX} Language Server.")
    (license license:gpl3)))

ビルドでコンパイルエラーが出る

頻繁に更新されているパッケージだと、依存解決でのエラーではなく、通常のコンパイルエラーが出ることがある。 Rustのエラーには大抵GitHubのIssueへのリンクが付いている。そのリンクへ飛ぶとわかるのだが、ほとんどの場合Rustのバージョンが古いことがエラーの原因だ。

Guixの cargo-build-system のデフォルトRustは最新のものからそれなりに遅れていることが多い。これはデフォルトのRustを変更すると cargo-build-system を用いたすべてのパッケージがビルドし直しになるため、頻繁に変更しないようになっているからと思う。 gcc のバージョンも同様にゆっくり変更されている。

たとえば2025/10/20現在、Rustの最新の安定版は1.90だが、Guixのデフォルトは1.85だ。ただしRustパッケージ自体は公式で1.88まで作成されているため、 #:use-module (gnu packages rust) した上で以下のように #:rust 引数を記述することで比較的新しいRustをコンパイルに用いることは可能である。以下は公式チャンネルにある rabbitmqadmin のパッケージ定義の引用である(ハイライトはこちらで付けている)。

(define-public rabbitmqadmin
  (package
    (name "rabbitmqadmin")
    (version "2.9.0")
    (source
     (origin
       (method git-fetch)
       (uri (git-reference
             (url "https://github.com/rabbitmq/rabbitmqadmin-ng")
             (commit (string-append "v" version))))
       (file-name (git-file-name name version))
       (sha256
        (base32 "04czi8s6nflvp1n2p1fl2wk6jqi0gsi7j52m4dnr6hvzf1mcn91n"))))
    (build-system cargo-build-system)
    (arguments
     (list #:rust rust-1.88
           #:tests? #f         ;Tests require local instance of RabbitMQ broker.
           #:install-source? #f))
    (inputs (cons* mimalloc openssl (cargo-inputs 'rabbitmqadmin)))
    (home-page "https://www.rabbitmq.com/docs/management-cli")
    (synopsis "Manage RabbitMQ broker via the management plugin")
    (description
      "@command{rabbitmqadmin} is a tool to manage RabbitMQ broker via
management plugin.

It supports many of the operations available in the management UI:

@itemize
@item Listing objects like virtual hosts, users, queues, streams, permissions,
policies, and so on.
@item Creating objects.
@item Deleting objects.
@item Access to cluster and node metrics.
@item Run health checks.
@item Listing feature flag state.
@item Listing deprecated features in use across the cluster.
@item Definition export, transformations, and import.
@item Operations on shovels.
@item Operations on federation upstreams and links.
@item Closing connections.
@item Rebalancing of queue leaders across cluster nodes.
@end itemize")
    (license (list license:asl2.0 license:expat))))

とはいえ、本当に最新版のRustでないと動作しない場合も存在する。そのために有志の人が作成してくれている guix-rustup を利用できる。これはGuix公式チャンネルとは違ってRustをいちからビルドせず、単にRustの公式バイナリを利用するため、 Guixの思想上あまり推奨される方法ではないが、最後の手段として知っておくと役に立つかもしれない。たとえば texlab に最新の rust-1.90.0 を用いたい場合、チャンネルの依存に guix-rustup を追加2た上で以下のように記述する。

;; define-module内に以下を記述する必要あり
;; #:use-module (rustup build toolchain)
;; #:use-module (gnu packages llvm)

(define-public texlab
  (package
    (name "texlab")
    (version "4.3.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "texlab" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "0laxg7qprbixp20cqdy824vrxq692c2x92aqigw5a84s0b69dbrn"))))
    (build-system (make-cargo-build-system "1.90.0"))
    (arguments
     (list #:install-source? #f))
    (inputs (cons*
             clang-toolchain
             (cargo-inputs 'texlab #:module '(mychannel packages rust-crates))))
    (home-page "https://github.com/latex-lsp/texlab")
    (synopsis "LaTeX Language Server")
    (description "This package provides @code{LaTeX} Language Server.")
    (license license:gpl3)))

特筆すべきは2点で、一つは build-system(make-cargo-build-system "1.90.0") と書いているところだ。これによりRustの1.90.0が用いられる。もう一つは inputs として clang-toolchain が必要な点だ。 これは guix-rustup 側の仕様のようだ

テストが失敗する

テストの失敗理由はいろいろあり、基本的には解決するように動くべきだが、テスト自体にネットワークが必要な場合など、Guixでは不可避なものもあるし、とりあえず動かしたい場合もある。そのような場合、 #:cargo-test-flags--skip= のような引数を指定することで成功しないテストを無効化することができる。失敗したテストのパスはビルド失敗時に表示されるはずなので、それをコピーすればよい。

(define-public texlab
  (package
    (name "texlab")
    (version "4.3.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "texlab" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "0laxg7qprbixp20cqdy824vrxq692c2x92aqigw5a84s0b69dbrn"))))
    (build-system cargo-build-system)
    (arguments
     (list
      #:install-source? #f
      #:cargo-test-flags '("--"
                           "--skip=path::to::test::to::skip1"
                           "--skip=path::to::test::to::skip2")))
    (inputs (cargo-inputs 'texlab #:module '(mychannel packages rust-crates)))
    (home-page "https://github.com/latex-lsp/texlab")
    (synopsis "LaTeX Language Server")
    (description "This package provides @code{LaTeX} Language Server.")
    (license license:gpl3)))

また、これは最後の手段だが、 #:tests? #f でテストの実行自体を無効にすることもできる。

(define-public texlab
  (package
    (name "texlab")
    (version "4.3.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "texlab" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "0laxg7qprbixp20cqdy824vrxq692c2x92aqigw5a84s0b69dbrn"))))
    (build-system cargo-build-system)
    (arguments
     (list
      #:install-source? #f
      #:tests? #f))
    (inputs (cargo-inputs 'texlab #:module '(mychannel packages rust-crates)))
    (home-page "https://github.com/latex-lsp/texlab")
    (synopsis "LaTeX Language Server")
    (description "This package provides @code{LaTeX} Language Server.")
    (license license:gpl3)))

その他

よくわからないエラーが出たら最終的には modify-phases を用いてビルドプロセスを修正するしかない。公式のGuixチャンネルなどから modify-phases の例を探していろいろ使いかたを調べるのがよいだろう。 私が前に書いたGuixパッケージ定義を作成する記事でも軽く触れているが、ゆくゆくは詳しく書けるとよいなと思っている。

まとめ

ここまで、Rustパッケージの作成方法と詰まる部分を説明してきた。あらためてまとめると概ね以下のような手順になる。

  • Rustのパッケージの依存先のみを管理するファイルである mychannel/packages/rust-crates.scm を用意する (初回のみ)。
  • 対象となるパッケージの Cargo.lock (/path/to/Cargo.lock) を入手する。
  • guix import --insert=/path/to/mychannel/packages/rust-crates.scm crate --lockfile=/path/to/Cargo.lock <パッケージ名> を実行する。
  • guix import --insert=/path/to/mychannel/packages/rust-apps.scm crate <パッケージ名> を実行する。
  • (cargo-inputs <パッケージ名>)(cargo-inputs <パッケージ名> #:module '(mychannel packages rust-crates)) に置き換える。
  • #:install-source? #f を設定する。
  • Guix特有の問題に起因するビルドフェーズの修正や、一部テストの無効化などの調整を行う。

大きなパッケージだとここまですんなり行くことはあまりないが、小さめのものならここにある手順だけでほとんどまかなうことができると思う。ぜひnいろいろなパッケージを定義して、自身のチャンネルに追加したり、公式のチャンネルに貢献したりしてほしい。また、困ったことがあれば私個人にでもGuix-jpにでも気軽に連絡してほしい。

また、公式サイトである以下のページも参考にできる。


  1. importerの実装を見る限りでは、これらのシンボルを認識して間に挿入しているわけではなさそうだ。 ↩︎

  2. バイナリからインストールするパッケージを作成するguix-rustupのREADMEを参考にするとよい。 READMEのほうは .config/guix/channels.scm 用の例のため、 .guix-channel に書く際には name のクオートの有無や introduction の形式など細かな違いがあるので注意すること。 ↩︎