CLOVER🍀

That was when it all began.

cargo installコマンドのインストール先を確認する

これは、なにをしたくて書いたもの?

ツールのインストールにcargo installが載っているパターンを見かける機会が増えてきたので、バイナリークレートが
どのような場所にインストールされるのか確認しておこうかなということで。

環境

今回の環境はこちら。

$ rustup --version
rustup 1.29.0 (28d1352db 2026-03-05)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: the currently active `rustc` version is `rustc 1.95.0 (59807616e 2026-04-14)`


$ cargo --version
cargo 1.95.0 (f2d3ce0bd 2026-03-21)

cargo install

cargo installのドキュメントはこちら。

cargo install - The Cargo Book

cargo installは、Rustバイナリーをビルド、インストールするコマンドです。

ローカルにインストールされているバイナリークレートを管理するコマンド、ともされています。

インストール先も書かれていますね。

  • --rootオプション
  • CARGO_INSTALL_ROOT環境変数
  • Cargoの設定値install.root
  • CARGO_HOME環境変数
  • $HOME/.cargoディレクトリー

優先順位は上から順に高い、でしょうね。

cargo installを実行した時に、対象のパッケージがすでにインストールされており、かつそれが最新ではなかった場合は
Cargoはパッケージを再インストールするようです。

If the package is already installed, Cargo will reinstall it if the installed version does not appear to be up-to-date.

また以下のいずれかの値が変更された場合も、再インストールするようです。

  • パッケージのバージョンおよびソース
  • インストールされているバイナリー名のセット
  • 選択しているフィーチャー
  • --profileオプション
  • --targetオプション

このコマンドは、プロジェクトレベルではなくシステムまたはユーザーレベルで動作します。つまり、ローカルの設定は
無視され、設定は$CARGO_HOME/config.tomlを参照することになります。

This command operates on system or user level, not project level. This means that the local configuration discovery is ignored. Instead, the configuration discovery begins at $CARGO_HOME/config.toml.

使ってみる

それでは、cargo installを使ってみましょう。

ast-grepをお題にします。まずはインストール。

$ cargo install ast-grep

すると、依存するクレートがダウンロードされてきて、ビルドが始まります…。ビルド済みのクレートをダウンロードして
インストール…ではなく、ビルドはローカルで行うところがポイントですね。

インストール後は、パスも通ります。

$ ast-grep --version
ast-grep 0.42.1

どこにインストールされたかというと、$HOME/.cargoディレクトリーです。

$ which ast-grep
$HOME/.cargo/bin/ast-grep

どうしてこのディレクトリーにパスが通っているかというと、Rustのインストール時に.bashrcに以下が追加されているから
ですね。

$ grep -F .cargo ~/.bashrc
. "$HOME/.cargo/env"

中身はこんな内容です。

$HOME/.cargo/env

#!/bin/sh
# rustup shell setup
# affix colons on either side of $PATH to simplify matching
case ":${PATH}:" in
    *:"$HOME/.cargo/bin":*)
        ;;
    *)
        # Prepending path in case a system-installed rustc needs to be overridden
        export PATH="$HOME/.cargo/bin:$PATH"
        ;;
esac

ドキュメントの例に従って、ripgrepもインストールしてみます。

$ cargo install ripgrep

インストールされたバイナリークレートの一覧は、cargo install --listで確認できます。

$ cargo install --list
ast-grep v0.42.1:
    ast-grep
    sg
ripgrep v15.1.0:
    rg

ちなみに、$HOME/.cargo/binディレクトリーにはバイナリークレートのビルド結果が配置されています。

$ ll $HOME/.cargo/bin
合計 100808
drwxrwxr-x 2 xxxxx xxxxx     4096  510 21:33 ./
drwxrwxr-x 4 xxxxx xxxxx     4096  510 21:32 ../
-rwxrwxr-x 1 xxxxx xxxxx 54318448  510 21:28 ast-grep*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 cargo -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 cargo-clippy -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 cargo-fmt -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 cargo-miri -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 clippy-driver -> rustup*
-rwxrwxr-x 1 xxxxx xxxxx 27567112  510 21:33 rg*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 rls -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 rust-analyzer -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 rust-gdb -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 rust-gdbgui -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 rust-lldb -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 rustc -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 rustdoc -> rustup*
lrwxrwxrwx 1 xxxxx xxxxx        6  510 21:16 rustfmt -> rustup*
-rwxr-xr-x 1 xxxxx xxxxx 20838840  510 21:16 rustup*
-rwxrwxr-x 1 xxxxx xxxxx   503936  510 21:28 sg*

インストール時にダウンロードされたクレートのソースコードは、$HOME/.cargo/registry/src/index.crates.io-[xxxx]という
ディレクトリーにあるみたいです。

インストールしたバイナリークレートをアンインストールする場合は、cargo uninstallです。

$ cargo uninstall ripgrep
    Removing $HOME/.cargo/bin/rg


$ cargo uninstall ast-grep
    Removing $HOME/.cargo/bin/ast-grep
    Removing $HOME/.cargo/bin/sg

さて、インストール先を変えてみましょう。cargo installのヘルプを確認。

$ cargo install --help
Install a Rust binary

Usage: cargo install [OPTIONS] [CRATE[@<VER>]]...

Arguments:
  [CRATE[@<VER>]]...  Select the package from the given source

Options:
      --version <VERSION>        Specify a version to install
      --index <INDEX>            Registry index to install from
      --registry <REGISTRY>      Registry to use
      --git <URL>                Git URL to install the specified crate from
      --branch <BRANCH>          Branch to use when installing from git
      --tag <TAG>                Tag to use when installing from git
      --rev <SHA>                Specific commit to use when installing from git
      --path <PATH>              Filesystem path to local crate to install from
      --root <DIR>               Directory to install packages into
  -f, --force                    Force overwriting existing crates or binaries
  -n, --dry-run                  Perform all checks without installing (unstable)
      --no-track                 Do not save tracking information
      --list                     List all installed packages and their versions
      --message-format <FMT>     Error format [possible values: human, short, json, json-diagnostic-short, json-diagnostic-rendered-ansi, json-render-diagnostics]
      --debug                    Build in debug mode (with the 'dev' profile) instead of release mode
  -v, --verbose...               Use verbose output (-vv very verbose/build.rs output)
  -q, --quiet                    Do not print cargo log messages
      --color <WHEN>             Coloring [possible values: auto, always, never]
      --config <KEY=VALUE|PATH>  Override a configuration value
  -Z <FLAG>                      Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
  -h, --help                     Print help

Manifest Options:
      --ignore-rust-version  Ignore `rust-version` specification in packages
      --locked               Assert that `Cargo.lock` will remain unchanged
      --offline              Run without accessing the network
      --frozen               Equivalent to specifying both --locked and --offline

Target Selection:
      --bin [<NAME>]      Install only the specified binary
      --bins              Install all binaries
      --example [<NAME>]  Install only the specified example
      --examples          Install all examples

Feature Selection:
  -F, --features <FEATURES>  Space or comma separated list of features to activate
      --all-features         Activate all available features
      --no-default-features  Do not activate the `default` feature

Compilation Options:
  -j, --jobs <N>                Number of parallel jobs, defaults to # of CPUs.
      --keep-going              Do not abort the build as soon as there is an error
      --profile <PROFILE-NAME>  Install artifacts with the specified profile
      --target [<TRIPLE>]       Build for the target triple
      --target-dir <DIRECTORY>  Directory for all generated artifacts
      --timings                 Output a build timing report at the end of the build

Run `cargo help install` for more detailed information.

--rootオプションでインストール先が変えられるということでした。というわけで、ディレクトリーを指定してインストール。

$ cargo install --root ~/cargo-test ast-grep ripgrep

指定したディレクトリーが存在しない場合は、Cargoが作成します。

インストールが終了すると、最後に「PATHに追加すること」と言われます。

     Summary Successfully installed ast-grep, ripgrep!
warning: be sure to add `$HOME/cargo-test/bin` to your PATH to be able to run the installed binaries

今回は絶対パスを指定して実行してみましょう。

$ ~/cargo-test/bin/ast-grep --version
ast-grep 0.42.1
$ tree ~/cargo-test
$HOME/cargo-test
└── bin
    ├── ast-grep
    ├── rg
    └── sg

2 directories, 3 files

指定したディレクトリー配下のファイルはこれだけです。

$ tree $HOME/cargo-test -a
$HOME/cargo-test
├── .crates.toml
├── .crates2.json
└── bin
    ├── ast-grep
    ├── rg
    └── sg

2 directories, 5 files

$HOME/cargo-test/.crates.tomlの内容は、こんな感じでした。

$HOME/cargo-test/.crates.toml

[v1]
"ast-grep 0.42.1 (registry+https://github.com/rust-lang/crates.io-index)" = [
    "ast-grep",
    "sg",
]
"ripgrep 15.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = ["rg"]

指定のパスにインストールされたバイナリークレートを確認。

$ cargo install --list --root ~/cargo-test
ast-grep v0.42.1:
    ast-grep
    sg
ripgrep v15.1.0:
    rg

環境変数CARGO_INSTALL_ROOTで指定する場合は、こうでしょうか。

$ CARGO_INSTALL_ROOT=~/cargo-test cargo install ast-grep ripgrep

ちなみに、--rootオプションやCARGO_INSTALL_ROOT環境変数でインストール先を切り替えても、クレートの
ソースコードをダウンロードする先は$HOME/.cargo/registry/src/index.crates.io-[xxxx]のままから変わりませんでした。

ここを変えたい場合はCARGO_HOME環境変数を設定したりするのかなと思いますが、そこまではやらない気もします…。

というわけで、確認はこれくらいにしましょう。

AWSのローカルエミュレーター、Flociを試す

これは、なにをしたくて書いたもの?

AWSのエミュレーターといえばLocalStackが有名ですが、2025年12月に発表されたこちらのエントリーで事情が変わりました。

The Road Ahead for LocalStack: Upcoming Changes to the Delivery of Our AWS Cloud Emulators

よって代替を探す人が増えていると思います。

またAmazon S3の代替限定ですが、MinIOもメンテナンスが終了しましたね。

GitHub - minio/minio: MinIO is a high-performance, S3 compatible object store, open sourced under GNU AGPLv3 license. · GitHub

LocalStackの代替

LocalStackの代替を探すと、FlociとMiniStackが見つかると思います。

Floci — Fast, Free AWS Emulator

MiniStack — The Best AWS Emulator | Free Open-Source LocalStack Alternative

FlociはJava(Quarkus)で、MiniStackはPythonでそれぞれ実装されています。

どちらもLocalStackよりも実装しているAWSサービスが多いのですが、今回はFlociを使ってみます。

なお、LocalStackではAWS CLIやAWS SAMなどのツールに対してもLocalStackとシームレスに統合できるツールを提供して
いましたが、こちらについては代替はなさそうですね。

AWS Native Tools

Floci

FlociはJava(Quarkus)で実装され、GraalVM Mandrelでビルドされたネイティブイメージとして動作します。

Floci — Fast, Free AWS Emulator

GitHubリポジトリーはこちら。

GitHub - floci-io/floci: Light, fluffy, and always free - The AWS Local Emulator alternative · GitHub

多くのサービスをカバーし、LocalStackよりも軽量であることを謳っています。

利用に必要なのはDocker Engineですね。FlociはDockerイメージとして提供されています。

ドキュメントはこちら。

Quick Start - Floci

Docker Images - Floci

Overview - Floci

LocalStackからの移行ガイドもあります。

Migrate from LocalStack - Floci

ちょっとおもしろいのは、Microsoft Azure用のエミュレーターも開発していることでしょうか。

Floci-AZ

こちらはFloci本体に比べるとまだまだ利用されていないようですが、気になる存在ですね。

環境

今回の環境はこちら。

$ docker version
Client: Docker Engine - Community
 Version:           29.4.3
 API version:       1.54
 Go version:        go1.26.2
 Git commit:        055a478
 Built:             Wed May  6 17:07:36 2026
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          29.4.3
  API version:      1.54 (minimum version 1.40)
  Go version:       go1.26.2
  Git commit:       56be731
  Built:            Wed May  6 17:07:36 2026
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v2.2.3
  GitCommit:        77c84241c7cbdd9b4eca2591793e3d4f4317c590
 runc:
  Version:          1.3.5
  GitCommit:        v1.3.5-0-g488fc13e
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

AWS CLI。

$ aws --version
aws-cli/2.34.45 Python/3.14.4 Linux/6.8.0-111-generic exe/x86_64.ubuntu.24

クレデンシャルの設定。

$ export AWS_ACCESS_KEY_ID=test
$ export AWS_SECRET_ACCESS_KEY=test
$ export AWS_DEFAULT_REGION=us-east-1
$ export AWS_ENDPOINT_URL=http://localhost:4566

Flociを動かしてみる

では、Flociを動かしてみましょう。

$ docker container run -it --rm --name floci -p 4566:4566 floci/floci:latest

起動しました。確かに、LocalStackの感覚からすると恐ろしい速度で起動します…。

 _____  _      ___   ____   __
|  ___|| |    / _ \ / ___| | |
| |_   | |   | | | || |    | |
|  _|  | |___| |_| || |__  | |
|_|    |_____|\___/ \____| |_|

   AWS Local Emulator  ·  Always Free

            Powered by Quarkus 3.34.6
2026-05-10 08:53:37,251 INFO  [io.github.hectorvent.floci.core.common.docker.ContainerDetector] (main) Container detection result: true
2026-05-10 08:53:37,252 INFO  [io.github.hectorvent.floci.core.common.dns.EmbeddedDnsServer] (vert.x-eventloop-thread-0) Embedded DNS server started on 172.17.0.2:53, resolving [localhost.floci.io, localhost.localstack.cloud, localhost.floci.io]172.17.0.2
2026-05-10 08:53:37,252 INFO  [io.github.hectorvent.floci.services.scheduler.ScheduleDispatcher] (main) Scheduler dispatcher started (tick every 10s)
2026-05-10 08:53:37,253 INFO  [io.github.hectorvent.floci.lifecycle.EmulatorLifecycle] (main) === AWS Local Emulator Starting ===
2026-05-10 08:53:37,253 INFO  [io.github.hectorvent.floci.lifecycle.EmulatorLifecycle] (main) Storage mode: memory
2026-05-10 08:53:37,253 INFO  [io.github.hectorvent.floci.lifecycle.EmulatorLifecycle] (main) Persistent path: /app/data
2026-05-10 08:53:37,253 INFO  [io.github.hectorvent.floci.core.common.ServiceRegistry] (main) Enabled services: [ssm, sqs, s3, dynamodb, sns, lambda, apigateway, iam, kafka, elasticache, rds, events, scheduler, logs, monitoring, secretsmanager, apigatewayv2, kinesis, kms, cognito-idp, states, cloudformation, acm, athena, glue, firehose, email, es, ec2, ecs, appconfig, appconfigdata, ecr, tagging, bedrock-runtime, eks, pipes, elasticloadbalancing, codebuild, codedeploy, autoscaling, backup, transfer, route53]
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) ---------------------------------------------------------------------
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) Legacy REST API date formats enabled (this is currently the default).
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main)
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) For maximum compatibility and to ease upgrades from older versions
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) of Registry, the date format used in the REST API is not compliant
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) with OpenAPI standards (due to a bug in older versions).  Please
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) make sure you upgrade all of your client applications to use the
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) latest client version.  The next release will fix the date format
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) bug, which will result in older clients no longer being compatible
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) with the REST API.
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main)
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) If you would like to fix the date format bug in THIS version of
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) Registry (great!) please set the following ENV variable + value:
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main)
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) REGISTRY_APIS_V2_DATE_FORMAT=yyyy-MM-dd'T'HH:mm:ss'Z'
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main)
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) Doing this will result in a REST API that is OpenAPI compliant, but
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) please remember to upgrade all your client applications first!
2026-05-10 08:53:37,254 INFO  [io.apicurio.registry.rest.JacksonDateTimeCustomizer] (main) ---------------------------------------------------------------------
2026-05-10 08:53:37,254 INFO  [io.github.hectorvent.floci.core.storage.StorageFactory] (main) Creating memory storage for service lambda (file: /app/data/lambda-esm.json)
2026-05-10 08:53:37,254 INFO  [io.github.hectorvent.floci.services.lambda.SqsEventSourcePoller] (main) SqsEventSourcePoller initialized, 0 ESM(s) active
2026-05-10 08:53:37,254 INFO  [io.github.hectorvent.floci.services.lambda.DynamoDbStreamsEventSourcePoller] (main) DynamoDbStreamsEventSourcePoller initialized
2026-05-10 08:53:37,254 INFO  [io.github.hectorvent.floci.core.storage.StorageFactory] (main) Creating memory storage for service pipes (file: /app/data/pipes.json)
2026-05-10 08:53:37,254 INFO  [io.github.hectorvent.floci.lifecycle.EmulatorLifecycle] (main) === AWS Local Emulator Ready ===
2026-05-10 08:53:37,254 INFO  [io.github.hectorvent.floci.core.common.BouncyCastleInitializer] (main) BouncyCastle provider already registered by Quarkus
2026-05-10 08:53:37,254 INFO  [io.github.hectorvent.floci.services.ec2.Ec2MetadataServer] (vert.x-eventloop-thread-0) EC2 IMDS server listening on port 9,169
2026-05-10 08:53:37,255 INFO  [io.quarkus] (main) floci 1.5.13 native (powered by Quarkus 3.34.6) started in 0.034s. Listening on: http://0.0.0.0:4566
2026-05-10 08:53:37,255 INFO  [io.quarkus] (main) Profile prod activated.
2026-05-10 08:53:37,255 INFO  [io.quarkus] (main) Installed features: [cdi, config-yaml, rest, rest-jackson, security, smallrye-context-propagation, vertx]

タグはlatestを指定していますが、バージョンを固定することもできます。更新はだいぶ早そうですが…。また-compatという
タグはAWS CLIおよびboto3を含むイメージのようです。

Installation - Floci

AWS CLIでアクセスしてみましょう。以下のように出力される場合は、認証情報が設定されていないので環境変数なりで
設定しておきましょう。

$ aws --endpoint-url http://localhost:4566 s3 ls

aws: [ERROR]: An error occurred (NoCredentials): Unable to locate credentials. You can configure credentials by running "aws login".

Amazon S3バケットを使ってみます。

## バケット作成
$ aws --endpoint-url http://localhost:4566 s3 mb s3://test-bucket
make_bucket: test-bucket


## 確認
$ aws --endpoint-url http://localhost:4566 s3 ls
2026-05-10 17:56:46 test-bucket


## アップロード
$ echo 'Hello Floci' > hello.txt
$ aws --endpoint-url http://localhost:4566 s3 cp hello.txt s3://test-bucket/hello.txt
upload: ./hello.txt to s3://test-bucket/hello.txt


## 確認
$ aws --endpoint-url http://localhost:4566 s3 ls test-bucket/
2026-05-10 17:58:17         12 hello.txt

$ aws --endpoint-url http://localhost:4566 s3 cp s3://test-bucket/hello.txt -
Hello Floci

よさそうですね。

毎回--endpoint-urlと設定するのが嫌な場合は、環境変数AWS_ENDPOINT_URLを設定しておくとよいでしょう。

$ export AWS_ENDPOINT_URL=http://localhost:4566


$ aws s3 ls
2026-05-10 17:56:46 test-bucket

こんなところでしょうか。

おわりに

AWSのローカルエミュレーター、Flociを試してみました。

LocalStackやMinIOの利用が難しくなったので、他のツールを見てみないとと思っていたのですが、LocalStackの代替に
ついてはFlociでよさそうですね。MiniStackも気になるところなので、どこかで試してみましょうか…。