ヴェズルフェルニルの研究ノート

座右の銘「ただ一人犀の角のように歩め」的な研究活動ノート

【Rust】別ターゲット用にプログラムをクロスコンパイルする

ここ最近、毎日Rustを使ってRaspberry Pi用プログラムを書いている。センサー・デバイスから取得した計測データをSQLiteデータベースに保存して、同時にWebSocket経由でサーバーへ転送するようなものだ。ターゲットはRaspberry Piだが、Rustプログラムの開発ホスト機としてMacを使っている。

前記事にRustのインストールと開発環境の構築手順を書いたが、

blog.ketus-ix.work

この記事の中で、下のようなRustコンポーネントの一覧を取得するコマンドを紹介した。

% rustup component list
cargo-x86_64-apple-darwin (installed)
clippy-x86_64-apple-darwin (installed)
llvm-bitcode-linker-x86_64-apple-darwin
llvm-tools-x86_64-apple-darwin
rls-x86_64-apple-darwin
rust-analysis-x86_64-apple-darwin
rust-analyzer-x86_64-apple-darwin
rust-docs-x86_64-apple-darwin (installed)
rust-src
rust-std-aarch64-apple-darwin
rust-std-aarch64-apple-ios
rust-std-aarch64-apple-ios-sim
rust-std-aarch64-linux-android
rust-std-aarch64-pc-windows-gnullvm
rust-std-aarch64-pc-windows-msvc
rust-std-aarch64-unknown-fuchsia
rust-std-aarch64-unknown-linux-gnu
rust-std-aarch64-unknown-linux-musl
rust-std-aarch64-unknown-linux-ohos
rust-std-aarch64-unknown-none
rust-std-aarch64-unknown-none-softfloat
rust-std-aarch64-unknown-uefi
rust-std-arm-linux-androideabi
rust-std-arm-unknown-linux-gnueabi
rust-std-arm-unknown-linux-gnueabihf
rust-std-arm-unknown-linux-musleabi
rust-std-arm-unknown-linux-musleabihf
rust-std-armebv7r-none-eabi
rust-std-armebv7r-none-eabihf
rust-std-armv5te-unknown-linux-gnueabi
rust-std-armv5te-unknown-linux-musleabi
rust-std-armv7-linux-androideabi
rust-std-armv7-unknown-linux-gnueabi
rust-std-armv7-unknown-linux-gnueabihf
rust-std-armv7-unknown-linux-musleabi
rust-std-armv7-unknown-linux-musleabihf
rust-std-armv7-unknown-linux-ohos
rust-std-armv7a-none-eabi
rust-std-armv7r-none-eabi
rust-std-armv7r-none-eabihf
rust-std-i586-pc-windows-msvc
rust-std-i586-unknown-linux-gnu
rust-std-i586-unknown-linux-musl
rust-std-i686-linux-android
rust-std-i686-pc-windows-gnu
rust-std-i686-pc-windows-gnullvm
rust-std-i686-pc-windows-msvc
rust-std-i686-unknown-freebsd
rust-std-i686-unknown-linux-gnu
rust-std-i686-unknown-linux-musl
rust-std-i686-unknown-uefi
rust-std-loongarch64-unknown-linux-gnu
rust-std-loongarch64-unknown-none
rust-std-loongarch64-unknown-none-softfloat
rust-std-nvptx64-nvidia-cuda
rust-std-powerpc-unknown-linux-gnu
rust-std-powerpc64-unknown-linux-gnu
rust-std-powerpc64le-unknown-linux-gnu
rust-std-riscv32i-unknown-none-elf
rust-std-riscv32im-unknown-none-elf
rust-std-riscv32imac-unknown-none-elf
rust-std-riscv32imafc-unknown-none-elf
rust-std-riscv32imc-unknown-none-elf
rust-std-riscv64gc-unknown-linux-gnu
rust-std-riscv64gc-unknown-none-elf
rust-std-riscv64imac-unknown-none-elf
rust-std-s390x-unknown-linux-gnu
rust-std-sparc64-unknown-linux-gnu
rust-std-sparcv9-sun-solaris
rust-std-thumbv6m-none-eabi
rust-std-thumbv7em-none-eabi
rust-std-thumbv7em-none-eabihf
rust-std-thumbv7m-none-eabi
rust-std-thumbv7neon-linux-androideabi
rust-std-thumbv7neon-unknown-linux-gnueabihf
rust-std-thumbv8m.base-none-eabi
rust-std-thumbv8m.main-none-eabi
rust-std-thumbv8m.main-none-eabihf
rust-std-wasm32-unknown-emscripten
rust-std-wasm32-unknown-unknown
rust-std-wasm32-wasi
rust-std-wasm32-wasip1
rust-std-wasm32-wasip1-threads
rust-std-x86_64-apple-darwin (installed)
rust-std-x86_64-apple-ios
rust-std-x86_64-fortanix-unknown-sgx
rust-std-x86_64-linux-android
rust-std-x86_64-pc-solaris
rust-std-x86_64-pc-windows-gnu
rust-std-x86_64-pc-windows-gnullvm
rust-std-x86_64-pc-windows-msvc
rust-std-x86_64-unknown-freebsd
rust-std-x86_64-unknown-fuchsia
rust-std-x86_64-unknown-illumos
rust-std-x86_64-unknown-linux-gnu
rust-std-x86_64-unknown-linux-gnux32
rust-std-x86_64-unknown-linux-musl
rust-std-x86_64-unknown-linux-ohos
rust-std-x86_64-unknown-netbsd
rust-std-x86_64-unknown-none
rust-std-x86_64-unknown-redox
rust-std-x86_64-unknown-uefi
rustc-x86_64-apple-darwin (installed)
rustc-dev-aarch64-apple-darwin
rustc-dev-aarch64-pc-windows-msvc
rustc-dev-aarch64-unknown-linux-gnu
rustc-dev-aarch64-unknown-linux-musl
rustc-dev-arm-unknown-linux-gnueabi
rustc-dev-arm-unknown-linux-gnueabihf
rustc-dev-armv7-unknown-linux-gnueabihf
rustc-dev-i686-pc-windows-gnu
rustc-dev-i686-pc-windows-msvc
rustc-dev-i686-unknown-linux-gnu
rustc-dev-loongarch64-unknown-linux-gnu
rustc-dev-powerpc-unknown-linux-gnu
rustc-dev-powerpc64-unknown-linux-gnu
rustc-dev-powerpc64le-unknown-linux-gnu
rustc-dev-riscv64gc-unknown-linux-gnu
rustc-dev-s390x-unknown-linux-gnu
rustc-dev-x86_64-apple-darwin
rustc-dev-x86_64-pc-windows-gnu
rustc-dev-x86_64-pc-windows-msvc
rustc-dev-x86_64-unknown-freebsd
rustc-dev-x86_64-unknown-illumos
rustc-dev-x86_64-unknown-linux-gnu
rustc-dev-x86_64-unknown-linux-musl
rustc-dev-x86_64-unknown-netbsd
rustc-docs-x86_64-unknown-linux-gnu
rustfmt-x86_64-apple-darwin (installed)

この出力情報から、コマンド "rustup" によって複数ターゲット用のクロスコンパイラをインストールできることが判る。

Rustでは公式サイトによってクロスコンパイラが配布されており、別ターゲットを対象としたクロスプラットフォーム開発環境が簡単に構築できるようになっている。これはRustの大きな利点であり、最近のプロジェクト(特に組み込み系)でRustが採用されるケースが増える要因となっている。

Rustを使うと、クロスコンパイル環境さえ構築すれば、Mac, WindowsLinux,組み込みLinux搭載機、Androidモバイル機、さらにOS無しマイコン環境さえも一つのプロジェクトで対応できるようになる。

本記事では、Rustによるクロスコンパイル環境の構築方法を紹介する。

ターゲット機としてRaspberry Pi OS 64-bit(Raspberry Pi 4用)を想定しているが、コンパイラやリンカの設定方法が変わるだけで、Linux搭載機がターゲットなら同じ手順でクロスコンパイル環境を構築できる。

cross パッケージによるクロスコンパイル

cross パッケージのインストール

% cargo install cross

プロジェクトのクロスビルド

% cd PROJECT_DIR
% cross build --target aarch64-unknown-linux-gnu

ビルドによって生成された実行可能ファイルはプロジェクト・ディレクリ内の以下のパスに置かれる。

  • オプションなし(または--debugオプション付き)で "cross build --target" コマンドを実行した場合〔Debugビルド〕

 target/aarch64-unknown-linux-gnu/debug/<project_name>

  • --releaseオプション付きで "cross build --target" コマンドを実行した場合〔Releaseビルド〕

 target/aarch64-unknown-linux-gnu/release/<project_name>

コマンド "cross build" はDockerコンテナを利用してプログラムのクロスコンパイルを行っており、Dockerがインストール済みで、"docker" コマンドが非root権限ユーザーによって実行できる状態であることが本コマンドを使える前提条件となる。

プロジェクト・プログラムの実行

cargo環境に cross パッケージを導入済みの場合、別ターゲット用にビルドしたプログラムを開発ホスト機上で実行することができる。

% cross run --target aarch64-unknown-linux-gnu

このコマンドはQEMUを使ってプログラムをエミュレート実行している。

ターゲット用リンカを使うクロスコンパイル

ターゲット用リンカのインストール

% brew tap messense/macos-cross-toolchains
% brew install aarch64-unknown-linux-gnu
$ sudo apt install gcc-aarch64-linux-gnu

ターゲット用ツールチェインのインストール

% rustup target add aarch64-unknown-linux-gnu

ターゲット用ビルド設定の作成

プロジェクト・ディレクトリ内に以下のような内容の.cargo/config.tomlというファイルを作成する。

% cd PROJECT_DIR
% mkdir .cargo
% vi .cargo/config.toml
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"

プロジェクトのクロスビルド

上記の手順操作が済んでいる状態で、プロジェクト・ディレクトリ内で下のようなコマンドを実行すると、当該プログラムを指定ターゲット用にビルドすることができる。

% cargo build --target aarch64-unknown-linux-gnu

zigbuild パッケージによるクロスコンパイル

Zigというプログラミング言語が在るが、このZigにLLVMベース・ツールチェインが統合されたZig ccというものがある。

zig.guide

このZig ccをcargo環境で使えるようにした cargo-zigbuild というRustパッケージが存在する。

github.com

この cargo-zigbuild パッケージを利用すると、Rustのクロスコンパイル環境を構築できる。

zigbuild パッケージのインスール

% brew install zig
% cargo install cargo-zigbuild
$ snap install zig --classic --beta
$ cargo install cargo-zigbuild

プロジェクトのクロスビルド

% cd PROJECT_DIR
% cargo zigbuild --target aarch64-unknown-linux-gnu

【補足説明】

クロスビルドによって生成したRustプログラムの実行可能ファイルをターゲット機へ転送するには、SSH経由で行うのが良く利用される方法だろう。

scpを使う方法

% scp target/aarch64-unknown-linux-gnu/debug/hello_rust <remote_user>@<target_remote_host>://tmp/

rsyncを使う方法

% rsync -av -e ssh target/aarch64-unknown-linux-gnu/debug/hello_rust <remote_user>@<target_remote_host>://tmp/

転送したプログラムの動作確認は、ターゲット機のコンソールから直接実行するか、あるいは、以下のようにSSH経由でターゲット機にログインした上で転送済みの実行可能ファイルを起動すれば良い。

% ssh <remote_user>@<target_remote_host>
% cd /tmp
% ./hello_rust
Hello, world!

【参照リンク】

qiita.com

qiita.com

zenn.dev

Rustのインストールと開発環境の構築

本業仕事で新しいIoTプロジェクトに関わっている。このプロジェクトのターゲット機はRaspberry Piを搭載しており、小生はファームウェアの開発を行っているが、そのプログラミング言語としてRustを使っている。

本格的にRustを使ってソフトウェア開発を行うのがこれが初めてだ。ハード制御を行うファームウェアC/C++を使って開発するのが一般的だが(最近は組み込みもPythonやNode.jsを使って開発できないこともないが、速度的制約をクリアしなければならなかったり細かなハード制御が必要だったりすると、やはりC/C++の方が実現し易い)、Rustを使っても同様の目的が達成できるんじゃないかと思っていた。実際にRustによるLinux稼働ファームウェアの開発を進めていて、この選択は正解だったと実感している。

RustはC/C++よりプログラミング・コストが低く、発達したエコシステムにより豊富なライブラリが揃っており、それらを使うとハード寄りのディープな目的もほとんど達成できる。速度面でもC/C++に劣らず、細やかな非同期処理、スレッド制御、メモリ管理も可能だ。

最近登場している開発系ツールはRustで書かれているものが多い。Rustを使ってWeb開発もできるし、PythonやNode.jsより応答性能の高いものが作れる。Rust用機械学習ライブラリも登場しているし、Rustで書かれたリアルタイムOSやESP32などのマイコン開発用フレームワークも存在する。組み込み開発もいまはRustでやるのが最適解なのかもしれない。あらゆる分野でRustが使われるトレンドが起きているようだ。

今回のプロジェクトだけでなく、自己研究でのIoTやエッジ・組み込みLinux利用開発でも積極的にRustを使っていくつもりだ。

自分の備忘録として、MacUbuntu機へRustの開発環境を構築する手順を書き残しておく。

Rustのインストール

Rustのインストール方法として、公式サイトではrustupを使うことが推薦されている。

www.rust-lang.org

asdfを使ってRustをインストールすることもできるが、asdfによって導入できるのはrustc(Rustコンパイラ)だけで、rustupは使えない。rustupを使うと複数のバージョンのRustをインストールでき(asdfのような言語バージョン管理ツールの機能も兼ね備えている)、cargoというパッケージマネージャも一緒に導入できる。Rustでのパッケージ管理はこのcargoを使うことが前提となる。

現状、Rustのインストールはrustupを使って行うのが最良の方法と言えるだろう。

% brew install rustup
% echo 'export PATH="/usr/local/opt/rustup/bin:$PATH"' >> ~/.zshrc
% source ~/.zshrc

bashの場合は、"~/.zshrc" の部分を "~/.bashrc" に変える。

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

本インストール・コマンドの実行時に後述の "rustup-init" コマンドも一緒に実行される。

Rustの初期設定

rustupをインストールしたら、最初に下のコマンドを実行して、Rust環境の初期設定を行っておく。

% rustup-init

Welcome to Rust!

This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.

Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:

  /Users/LOGNAME/.rustup

This can be modified with the RUSTUP_HOME environment variable.

The Cargo home directory is located at:

  /Users/LOGNAME/.cargo

This can be modified with the CARGO_HOME environment variable.

The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:

  /Users/LOGNAME/.cargo/bin

This path will then be added to your PATH environment variable by
modifying the profile files located at:

  /Users/LOGNAME/.profile
  /Users/LOGNAME/.zshenv

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:


   default host triple: x86_64-apple-darwin
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with standard installation (default - just press enter)
2) Customize installation
3) Cancel installation
>

info: profile set to 'default'
info: default host triple is x86_64-apple-darwin
info: syncing channel updates for 'stable-x86_64-apple-darwin'
info: latest update on 2024-06-13, rust version 1.79.0 (129f3b996 2024-06-10)
info: downloading component 'cargo'
  6.9 MiB /   6.9 MiB (100 %)   4.8 MiB/s in  1s ETA:  0s
info: downloading component 'clippy'
info: downloading component 'rust-docs'
 15.4 MiB /  15.4 MiB (100 %)   4.8 MiB/s in  3s ETA:  0s
info: downloading component 'rust-std'
 23.4 MiB /  23.4 MiB (100 %)   6.7 MiB/s in  3s ETA:  0s
info: downloading component 'rustc'
 55.5 MiB /  55.5 MiB (100 %)   5.1 MiB/s in  9s ETA:  0s
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
 15.4 MiB /  15.4 MiB (100 %)   2.5 MiB/s in  5s ETA:  0s
info: installing component 'rust-std'
 23.4 MiB /  23.4 MiB (100 %)   9.8 MiB/s in  2s ETA:  0s
info: installing component 'rustc'
 55.5 MiB /  55.5 MiB (100 %)  10.6 MiB/s in  5s ETA:  0s
info: installing component 'rustfmt'
info: default toolchain set to 'stable-x86_64-apple-darwin'

  stable-x86_64-apple-darwin installed - rustc 1.79.0 (129f3b996 2024-06-10)


Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).

To configure your current shell, you need to source
the corresponding env file under $HOME/.cargo.

This is usually done by running one of the following (note the leading DOT):
. "$HOME/.cargo/env"            # For sh/bash/zsh/ash/dash/pdksh
source "$HOME/.cargo/env.fish"  # For fish

※上はIntel Mac上での "rustup-init" コマンドの実行例。他のプラットホーム上では "x86_64-apple-darwin" などの表示が変わってくる。

"rustup-init" コマンドによる初期設定が済んだら、下のような記述を.zshrcbashの場合は.bashrc)に追加した上で、それを有効にする。

% vi ~/.zshrc
. "$HOME/.cargo/env"
% source ~/.zshrc

その上で、コマンド "rustc" と "cargo" が利用できることを確認しておく。

% rustc --version
rustc 1.79.0 (129f3b996 2024-06-10)
% cargo --version
cargo 1.79.0 (ffa9cf99a 2024-06-03)

rustupによってインストールしたRust環境のファイル群はディレクト$HOME/.cargoの中に格納されている。

補足情報

Macで "rustup-init" コマンドを実行したときに、下のような警告が表示されることがある。

% rustup-init
warning: it looks like you have an existing installation of Rust at:
warning: /usr/local/bin
warning: It is recommended that rustup be the primary Rust installation.
warning: Otherwise you may have confusion unless you are careful with your PATH
warning: If you are sure that you want both rustup and your already installed Rust
warning: then please reply `y' or `yes' or set RUSTUP_INIT_SKIP_PATH_CHECK to yes
warning: or pass `-y' to ignore all ignorable checks.
error: cannot install while Rust is installed

Continue? (y/N)

Homebrewによってすでにrustパッケージが導入済みときに、この警告が表示される。

この場合は、以下のコマンドによってrustパッケージが存在することを確認し、それをアンインストールしてから、 "rustup-init" コマンドを再度実行すれば良い。

% which rustc
/usr/local/bin/rustc
% brew info rust
==> rust: stable 1.79.0 (bottled), HEAD
Safe, concurrent, practical language
https://www.rust-lang.org/
Installed
/usr/local/Cellar/rust/1.78.0 (3,320 files, 294.3MB) *
  Poured from bottle using the formulae.brew.sh API on 2024-06-07 at 08:29:53
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/r/rust.rb
License: Apache-2.0 or MIT
==> Dependencies
Required: libgit2 ✔, libssh2 ✔, llvm ✘, openssl@3 ✘, pkg-config ✔
==> Requirements
Required: macOS >= 10.12 (or Linux) ✔
==> Options
--HEAD
    Install HEAD version
==> Caveats
zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
==> Analytics
install: 36,888 (30 days), 122,724 (90 days), 431,118 (365 days)
install-on-request: 26,090 (30 days), 89,554 (90 days), 325,780 (365 days)
build-error: 346 (30 days)
% brew uninstall rust

Rustによるプロジェクト作成とビルド

Rustによるプロジェクト(プログラム)の作成とビルドができることを確認しておこう。

プロジェクトの作成

新しいRustプロジェクトの作成は、以下のような "cargo" コマンドを使って行える。

プロジェクト・ディレクトリを新規作成する場合

% cargo new hello_rust
   Creating binary (application) `hello_rust` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

既存ディレクトリ内でプロジェクトを作成する場合

% mkdir hello_rust
% cd hello_rust
% cargo init
    Creating binary (application) package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Rustプロジェクトを作成すると、一緒にCargo.tomlというファイルも生成され、この中にプロジェクトの依存パッケージ情報が記述されている(Rustでは、パッケージを "Crate" と呼称する)。

プロジェクト・ソースの作成

コマンド "cargo new PROJECT_NAME" や "cargo init" によってプロジェクトを作成すると、プロジェクト・ディレクトリ内にsrcというディレクトリが生成されており、Rustプログラムのソースファイルはこのディレクトリの中に作成していくことが決まり事になっている。

また、下のような一つのソースファイルも自動的に生成される。

  • src/main.rs
fn main() {
    println!("Hello, world!");
}

プロジェクトのビルドと実行

プロジェクト・ディレクトリ内で下のコマンドを実行することで、そのプロジェクトのビルドが行える。

% cargo build
   Compiling hello_rust v0.1.0 (/Users/LOGNAME/hello_rust)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.18s

下のコマンドによって、プロジェクト・プログラムを起動・実行することができる。

% cargo run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/hello_rust`
Hello, world!

コマンド "cargo run" はプロジェクトのビルドと実行を続けて行っている。

Rust開発環境の整備

Rustによるプログラム開発に有益なツールが多く在るが、その中から厳選してみた。それらのインストール方法を以下に記しておく。

追加コンポーネントのインストール

% rustup component add rls rust-analysis rust-src rust-analyzer

コンポーネントの機能は以下のとおり。

  • rls 旧版のRust Language Server(古いバージョンのRustで使われる)
  • rust-analysis Rust標準ライブラリのメタデータ
  • rust-src Rust標準ライブラリのソースコードのローカルコピー(rlsrust-analyzerなどで参照される)
  • rust-analyzer 新版のRust Language Server(最近のバージョンのRustでは、こちらが使われる)

以下のコンポーネントも有益だが、本記事執筆時点のRustの最新バージョンでは、これらは "rustup-init" コマンドによる初期設定時にインストール済みになっていた。

  • clippy Rust公式のリンター(変数名ルールなどの静的解析を行う)
  • rust-docs 公式Rustドキュメントのローカルコピー("rustup doc" コマンド実行時に、ローカルの公式ドキュメントを参照できるようになる)
  • rustfmt コード・フォーマッタ(ソースコードの可読性整形を行う)

インストール済みのRustコンポーネントは下のコマンドによって確認できる。

% rustup component list
cargo-x86_64-apple-darwin (installed)
clippy-x86_64-apple-darwin (installed)
llvm-bitcode-linker-x86_64-apple-darwin
llvm-tools-x86_64-apple-darwin
rls-x86_64-apple-darwin
rust-analysis-x86_64-apple-darwin
rust-analyzer-x86_64-apple-darwin
rust-docs-x86_64-apple-darwin (installed)
rust-src
rust-std-aarch64-apple-darwin
rust-std-aarch64-apple-ios
rust-std-aarch64-apple-ios-sim
rust-std-aarch64-linux-android
rust-std-aarch64-pc-windows-gnullvm
rust-std-aarch64-pc-windows-msvc
rust-std-aarch64-unknown-fuchsia
rust-std-aarch64-unknown-linux-gnu
rust-std-aarch64-unknown-linux-musl
rust-std-aarch64-unknown-linux-ohos
rust-std-aarch64-unknown-none
rust-std-aarch64-unknown-none-softfloat
rust-std-aarch64-unknown-uefi
rust-std-arm-linux-androideabi
rust-std-arm-unknown-linux-gnueabi
rust-std-arm-unknown-linux-gnueabihf
rust-std-arm-unknown-linux-musleabi
rust-std-arm-unknown-linux-musleabihf
rust-std-armebv7r-none-eabi
rust-std-armebv7r-none-eabihf
rust-std-armv5te-unknown-linux-gnueabi
rust-std-armv5te-unknown-linux-musleabi
rust-std-armv7-linux-androideabi
rust-std-armv7-unknown-linux-gnueabi
rust-std-armv7-unknown-linux-gnueabihf
rust-std-armv7-unknown-linux-musleabi
rust-std-armv7-unknown-linux-musleabihf
rust-std-armv7-unknown-linux-ohos
rust-std-armv7a-none-eabi
rust-std-armv7r-none-eabi
rust-std-armv7r-none-eabihf
rust-std-i586-pc-windows-msvc
rust-std-i586-unknown-linux-gnu
rust-std-i586-unknown-linux-musl
rust-std-i686-linux-android
rust-std-i686-pc-windows-gnu
rust-std-i686-pc-windows-gnullvm
rust-std-i686-pc-windows-msvc
rust-std-i686-unknown-freebsd
rust-std-i686-unknown-linux-gnu
rust-std-i686-unknown-linux-musl
rust-std-i686-unknown-uefi
rust-std-loongarch64-unknown-linux-gnu
rust-std-loongarch64-unknown-none
rust-std-loongarch64-unknown-none-softfloat
rust-std-nvptx64-nvidia-cuda
rust-std-powerpc-unknown-linux-gnu
rust-std-powerpc64-unknown-linux-gnu
rust-std-powerpc64le-unknown-linux-gnu
rust-std-riscv32i-unknown-none-elf
rust-std-riscv32im-unknown-none-elf
rust-std-riscv32imac-unknown-none-elf
rust-std-riscv32imafc-unknown-none-elf
rust-std-riscv32imc-unknown-none-elf
rust-std-riscv64gc-unknown-linux-gnu
rust-std-riscv64gc-unknown-none-elf
rust-std-riscv64imac-unknown-none-elf
rust-std-s390x-unknown-linux-gnu
rust-std-sparc64-unknown-linux-gnu
rust-std-sparcv9-sun-solaris
rust-std-thumbv6m-none-eabi
rust-std-thumbv7em-none-eabi
rust-std-thumbv7em-none-eabihf
rust-std-thumbv7m-none-eabi
rust-std-thumbv7neon-linux-androideabi
rust-std-thumbv7neon-unknown-linux-gnueabihf
rust-std-thumbv8m.base-none-eabi
rust-std-thumbv8m.main-none-eabi
rust-std-thumbv8m.main-none-eabihf
rust-std-wasm32-unknown-emscripten
rust-std-wasm32-unknown-unknown
rust-std-wasm32-wasi
rust-std-wasm32-wasip1
rust-std-wasm32-wasip1-threads
rust-std-x86_64-apple-darwin (installed)
rust-std-x86_64-apple-ios
rust-std-x86_64-fortanix-unknown-sgx
rust-std-x86_64-linux-android
rust-std-x86_64-pc-solaris
rust-std-x86_64-pc-windows-gnu
rust-std-x86_64-pc-windows-gnullvm
rust-std-x86_64-pc-windows-msvc
rust-std-x86_64-unknown-freebsd
rust-std-x86_64-unknown-fuchsia
rust-std-x86_64-unknown-illumos
rust-std-x86_64-unknown-linux-gnu
rust-std-x86_64-unknown-linux-gnux32
rust-std-x86_64-unknown-linux-musl
rust-std-x86_64-unknown-linux-ohos
rust-std-x86_64-unknown-netbsd
rust-std-x86_64-unknown-none
rust-std-x86_64-unknown-redox
rust-std-x86_64-unknown-uefi
rustc-x86_64-apple-darwin (installed)
rustc-dev-aarch64-apple-darwin
rustc-dev-aarch64-pc-windows-msvc
rustc-dev-aarch64-unknown-linux-gnu
rustc-dev-aarch64-unknown-linux-musl
rustc-dev-arm-unknown-linux-gnueabi
rustc-dev-arm-unknown-linux-gnueabihf
rustc-dev-armv7-unknown-linux-gnueabihf
rustc-dev-i686-pc-windows-gnu
rustc-dev-i686-pc-windows-msvc
rustc-dev-i686-unknown-linux-gnu
rustc-dev-loongarch64-unknown-linux-gnu
rustc-dev-powerpc-unknown-linux-gnu
rustc-dev-powerpc64-unknown-linux-gnu
rustc-dev-powerpc64le-unknown-linux-gnu
rustc-dev-riscv64gc-unknown-linux-gnu
rustc-dev-s390x-unknown-linux-gnu
rustc-dev-x86_64-apple-darwin
rustc-dev-x86_64-pc-windows-gnu
rustc-dev-x86_64-pc-windows-msvc
rustc-dev-x86_64-unknown-freebsd
rustc-dev-x86_64-unknown-illumos
rustc-dev-x86_64-unknown-linux-gnu
rustc-dev-x86_64-unknown-linux-musl
rustc-dev-x86_64-unknown-netbsd
rustc-docs-x86_64-unknown-linux-gnu
rustfmt-x86_64-apple-darwin (installed)

追加パッケージのインストール

% cargo install cargo-edit
% cargo install cargo-watch
$ sudo apt install -y libssl-dev
$ cargo install cargo-edit
$ cargo install cargo-watch
  • cargo-edit (Rustでのプロジェクトの依存パッケージ変更はCargo.tomlを編集することで行うが)Rustパッケージ(Crate)の追加/削除を "cargo add CRATE_NAME" や "cargo rm CRATE_NAME" というコマンドで行えるようになる
  • cargo-watch ソースファイルの変更を検知して、"cargo run" コマンドを自動的に実行してくれる

インストール済みのRustパッケージは下のコマンドによって確認できる。

% cargo install --list
cargo-edit v0.12.3:
    cargo-add
    cargo-rm
    cargo-set-version
    cargo-upgrade
cargo-watch v8.5.2:
    cargo-watch

Visual Studio Code拡張機能のインストール

VSCodeでのRustプログラム開発に有益な拡張機能として、rust-analyzerをインストールしておくことを薦める。

これは上述のコンポーネントrust-analyzerVSCode版だ。

少し前までRust(Rust言語対応ユーティリティ機能)とrust-analyzer(Language Support Server)という2つの拡張機能が存在しており、この両方をインストールすることが推薦されていたが、現在この2つはrust-analyzerの一つに統合されている。本記事執筆時点では、VSCodeのRust用拡張機能として最低限rust-analyzerだけをインストールしておけば良いだろう。

【追記】〔2024-07-23〕

VSCodeのRust用拡張機能として、CodeLLDBもインストールする必要があるのを書き忘れていた。

これはVSCode上でのRustソースコードデバッグ実行に使われるものだ。

小生のVSCode環境にはSwiftという拡張機能が導入済みで、このSwiftCodeLLDBに依存しており、すでにCodeLLDBがインストール済みだったので上のことに気づかなかった。

【追記】〔2024-07-24〕

備忘録として、cargoコマンドの使い方も書いておく。

新規プロジェクトの作成

cargo new PROJECT_NAME

本コマンドは通常パッケージ用プロジェクトを作成する。

コマンド "cargo new --bin PROJECT_NAME" によって、バイナリパッケージ用プロジェクトを作成できる。

既存ディレクトリ上でのプロジェクトの作成

cd PROJECT_DIR
cargo init

プロジェクトのビルド

cargo build

オプションなし(または--debugオプション付き)で本コマンドを実行すると、Debug用実行可能ファイルがビルドされる。コマンド "cargo build --relaese" だと、Relaese用実行可能ファイルがビルドされる。

コマンド "cargo build --example EXAMPLE_NAME" によって、examplesディレクトリ内の指定サンプルプログラムをビルドできる。

プロジェクトのビルドと実行

cargo run

コマンド "cargo run --example EXAMPLE_NAME" によって、examplesディレクトリ内の指定サンプルプログラムをビルド・実行できる。

プロジェクトのビルド可能確認

cargo check

本コマンドによってプロジェクトのビルドは行われず、コンパイル確認だけが行われる。

プロジェクトのビルド削除(クリーン)

cargo clean

パッケージ(Crate)のインストール

cargo add CRATE_NAME

cargo-editがインストールされている場合に使えるコマンド

パッケージ(Crate)のアンインストール

cargo rm CRATE_NAME

cargo-editがインストールされている場合に使えるコマンド

パッケージ(Crate)の検索

cargo search CRATE_NAME

Rust Crateの公式配布サイトcrates.ioから、指定した名前を含むCrateが検索される。

crates.io

依存Crateの更新

cargo update

本コマンドによって、プロジェクトの全依存Crateが最新版へ更新される。

テストの実行

cargo test

ディレクトtests内にプロジェクトの単体テスト用ソースファイルが作成されている場合に、本コマンドによってそれらがビルド・実行される。

プロジェクト・ドキュメントの作成

cargo doc

プロジェクトのファイル群からドキュメントを生成する。

ソースファイル中に一定のルールに則って記述されたコメントが、本コマンドによるドキュメント情報収集の対象となる。

バイナリパッケージのインストール

cargo install PACKAGE_NAME

バイナリパッケージのアンインストール

cargo uninstall PACKAGE_NAME

【参照リンク】

qiita.com

zenn.dev

code.visualstudio.com

Flutterのインストールと開発環境の構築〔iOS/Androidアプリ編〕

前記事にFlutterのインストールと開発環境構築方法について書いたが、これに続いて、FlutterによるiOSおよびAndroidアプリ開発用の追加的な環境構築手順を書いていく。

blog.ketus-ix.work

スマホアプリ開発を再開するにあたって、当面の目標として、ONVIF仕様IPカメラ(監視・防犯カメラ)とMatter規格スマートデバイス用のアプリを作りたいと考えている。

www.onvif.org csa-iot.org

元組み込み屋だったこともあって、小生はやはりハードウェア/デバイス絡みの開発に興味を惹かれてしまう。スマホと連携できるデバイスやガジェットが増えているので、そういうものを利用するモバイルアプリを作りたい。

技術スキル維持と開発トレンド追随のためにも、今後もスマホアプリ開発は続けていくつもりだ。いままでは主にFlutterを使ってきたが、(フレームワーク設計思想がFlutterと似ている)React Nativeも使ってみたいと思っている。

必要なツールのインストール

CocoaPodsのインストール

前記事のコマンド "flutter doctor" の出力情報で指摘されていたとおり、Xcodeとの連携のためにCocoaPodsも必要になる。

CocoaPodsの公式サイトによると、下のコマンドによってインストールできる。

% sudo gem install cocoapods

このコマンドはMacにデフォルトで入っているRubygemRubyのパッケージ管理コマンド)を使ってCocoaPodsのインストールを行っているが、言語バージョン管理ツールを使っている場合はそちらを利用した方が良い。

  • anyenvを使っている場合
% anyenv install rbenv
% exec $SHELL -l
% rbenv install --list
% rbenv install 3.3.1
% rbenv rehash
% rbenv global 3.3.1
% cd
% which ruby
/Users/LOGNAME/.anyenv/envs/rbenv/shims/ruby
/usr/bin/ruby
% ruby --version
ruby 3.3.1 (2024-04-23 revision c56cd86388) [x86_64-darwin21]
% which gem
/Users/LOGNAME/.anyenv/envs/rbenv/shims/gem
/usr/bin/gem
% gem install cocoapods
% pod --version
1.15.2
  • asdfを使っている場合
% asdf plugin add ruby
% asdf install ruby latest
% asdf reshim
% asdf global ruby latest
% cd
% which ruby
/Users/LOGNAME/.asdf/shims/ruby
/usr/bin/ruby
% ruby --version
ruby 3.3.1 (2024-04-23 revision c56cd86388) [x86_64-darwin22]
% which gem
/Users/LOGNAME/.asdf/shims/gem
/usr/bin/gem
% gem install cocoapods
% pod --version
1.15.2

XcodeとCocoaPodsはMac上でのmacOSiOSアプリ開発に必要なものだ。これらのアプリはXcodeが使えるMacでしか開発することはできない。

Android Studioのインストール

Android StudioAndroid Studioの公式サイトから入手できる。

下のようなコマンドによって、Homebrewを使ってAndroid Studioをインストールすることもできる。

% brew install --cask android-studio

Android Studioをインストールしたら、一度起動して、表示されるガイド画面に従って操作を行い初期セットアップを終わらせおく。

Android SDK Command-line Toolsのインストール

Android Studio起動後のWelcome画面上のプルダウンメニュー [More Actions] > [SDK Manager] を選ぶ(あるいは、メニュー [Settings]を選択する)。

すると、下のような画面が開く。

この画面内の項目 [Languages & Frameworks] > [Android SDK] の [SDK Tools] タブ画面から、 [Android SDK Command-line Tools (lastest)] チェックボタンを有効にして、[OK] ボタンを押す 。

この操作によって、有効にしたコンポーネントの追加インストールが開始される。

Javaのインストール

Androidアプリの開発に使用されるので、JavaJava JRE)もインストールする必要がある。

本記事執筆時点の最新Stable版Flutter SDKでは、Javaバージョン11以上20未満の使用が推薦されているようだ。

下のようなコマンドによって、Homebrewを使ってJavaをインストールできる。

% brew install openjdk@17

SDKMANを使ってJavaをインストールする方法もある。この方法については下の記事を参照してほしい。

blog.ketus-ix.work

asdfを使っている場合は、下のコマンドによってasdfを使ってJavaをインストールできる。

% asdf plugin add java
% asdf install java temurin-jre-17.0.11+9
% asdf reshim
% asdf global java temurin-jre-17.0.11+9
% exec $SHELL -l
% cd
% which java
/Users/LOGNAME/.asdf/shims/java
/usr/bin/java
% java -version
openjdk version "17.0.11" 2024-04-16
OpenJDK Runtime Environment Temurin-17.0.11+9 (build 17.0.11+9)
OpenJDK 64-Bit Server VM Temurin-17.0.11+9 (build 17.0.11+9, mixed mode)

Flutter開発環境の状態確認

上記の手順操作がすべて済んだら、下のコマンドによってFlutter開発環境の状態を確認してみよう(FVMを使っている場合のコマンドは "fvm flutter doctor")。

% flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.6, on macOS 13.4.1 22F770820d darwin-x64, locale ja-JP)
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
    ! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.1)
[✓] VS Code (version 1.90.1)
[✓] Connected device (2 available)
[✓] Network resources

! Doctor found issues in 1 category.

前記事と本記事のここまでの手順操作がすべて済んでいれば、多分上のような表示になるんじゃないだろうか。

上の出力情報中で指定されている問題点 "Some Android licenses not accepted. " は、以下の操作によって解決できるだろう。

警告文中のアドバイスのとおり、下のコマンドを実行する(FVMを使用している場合のコマンドは "fvm flutter doctor --android-licenses")。

% flutter doctor --android-licenses

これによって、Android Studio内のコンポーネントのライセンス条文が順次表示され、その同意/拒否を求められるので、すべてに "y" とタイプする。

この操作が済めば、コマンド "flutter doctor" の実行結果は下のような出力表示になるはずだ。

% flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.6, on macOS 13.4.1 22F770820d darwin-x64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.1)
[✓] VS Code (version 1.90.1)
[✓] Connected device (2 available)
[✓] Network resources

• No issues found!

これで、 FlutterによるiOSAndroidアプリの開発環境はすべて整った。

VSCodeでいずれかのFlutterプロジェクト・ディレクトリを開くと、ターゲットデバイスとしてiOSAndroidの選択肢が増えていることが確認できるだろう。

なお、本記事執筆時点ではAndroidのターゲットデバイスは上のようになっているが、これは導入したAndroid Studioのリリースバージョンによって変化する。

iOSアプリのビルドと動作確認

Visual Studio Code使用

VSCodeでFlutterプロジェクトのディレクリを開き、ターゲットデバイスから [Start iOS Simulator] を選択する。

すると、iOSシュミレータが起動する。

この状態でVSCodeのメニュー [Run (実行)] > [Start Debugging (デバッグの開始)] または [Run Without Debugging (デバッグなしで実行)] を選ぶと、プロジェクトのビルドが行われ、ビルドが成功すれば、iOSシュミレータ上でアプリが起動する。

ターミナル使用

ターミナルから同じ操作を行うこともできる。

まず、下のコマンドによってiOSシュミレータを起動する。

% open -a Simulator

この状態で、Flutterプロジェクト・ディレクリ内で下のコマンドを実行すると、プロジェクトのビルドが行われ、ビルドが成功すれば、iOSエミュレータ上でアプリが起動する。

% cd FLUTTER_PROJECT_DIR
% flutter run

iOS仮想デバイスの追加

iOSシュミレータを使って、新しいiOS仮想デバイスを作成することができる。

iOSシュミレータのメニュー [File] > [New Simulator] を選ぶと、下のような画面が開く。

この画面のメニューからデバイス種別とiOSバージョンを選んで、[Create] ボタンを押せば、仮想デバイスが作成される。

作成されたデバイスはメニュー [File] > [Open Simulator] の項目として追加されているので、同メニュー項目を選べば、そのデバイスが起動する。

この状態でVSCodeのメニュー [Run (実行)] > [Start Debugging (デバッグの開始)] または [Run Without Debugging (デバッグなしで実行)] を選ぶと、開いているiOSバイス上でプロジェクト・アプリが起動する。

Androidアプリのビルドと動作確認

Visual Studio Code使用

VSCodeでFlutterプロジェクトのディレクリを開き、ターゲットデバイスからいずれかのAndroidバイス(本記事執筆時点では、 [Start Pixel Fold API 35 mobile emulator] か [Start Pixel Fold API 35 mobile emulator (cold boot)] )を選択する。

すると、Androidエミュレータが起動する。

この状態でVSCodeのメニュー [Run (実行)] > [Start Debugging (デバッグの開始)] または [Run Without Debugging (デバッグなしで実行)] を選ぶと、プロジェクトのビルドが行われ、ビルドが成功すれば、Androidエミュレータ上でアプリが起動する。

ターミナル使用

ターミナルから同じ操作を行うこともできる。

まず、下のコマンドによってAndroidエミュレータを起動する。

% flutter emulators --launch Pixel_Fold_API_35

この状態で、Flutterプロジェクト・ディレクリ内で下のコマンドを実行すると、プロジェクトのビルドが行われ、ビルドが成功すれば、Androidエミュレータ上でアプリが起動する。

% cd FLUTTER_PROJECT_DIR
% flutter run

Android仮想デバイスの追加

Android StudioのVirtual Device Mangerを使って、新しいAndroid仮想デバイスを作成することができる。

Android Studio起動後のWelcome画面上のプルダウンメニュー [More Actions] > [Virtual Device Manager] を選ぶ。

すると、下のようなVirtual Device Managerの画面が開く。

この画面の左上の [ ] ボタンを押すと、下のような画面が順次表示される。

各画面でデバイスAPIの種類を選択し、最後にデバイス名を入力をして [Finish] ボタンを押せば、新しい仮想デバイスが作成される。

Virtual Device Mangerによって作成したデバイスVSCode側にも反映される。

Virtual Device Mangerでデバイス名の左側の [ ] ボタンを押すか、VSCode側のコマンドパレット・メニューからデバイスを選択すると、Androidエミュレータでその仮想デバイスが起動する。

この状態でVSCodeのメニュー [Run (実行)] > [Start Debugging (デバッグの開始)] または [Run Without Debugging (デバッグなしで実行)] を選ぶと、開いているAndroidバイス上でプロジェクト・アプリが起動する。

  

経験則的な情報だが、GPUを搭載していないPC(CPU内蔵GPU Intel Graphicsのみ搭載機)ではAndroidエミュレータは極端に動作が遅くなり、実用に耐えられないほど反応が悪くなる。そういうPCでは実質的にAndroidアプリの開発はできないと思った方が良い。

 

Flutterコマンド

iOS/Androidアプリの開発において、利用する可能性の高いFlutterのコマンドを列記しておく。

プロジェクトの作成

% flutter create PROJECT_NAME
% mkdir FLUTTER_PROJECT_DIR
% cd FLUTTER_PROJECT_DIR
% flutter create .

プロジェクトのビルド

% flutter build TARGET_ENV

TARGET_ENV = web | macos | linux | windows | ios | android

プロジェクト・ビルドの削除

% flutter clean

パッケージ(ライブラリ)の更新

% cd FLUTTER_PROJECT_DIR
% flutter pub get

pubspec.yamlの編集後、本コマンドを実行することでプロジェクトが利用しているパッケージの更新が行える。

パッケージの追加

% flutter pub add PACKAGE

pubspec.yamlの内容も更新される。

パッケージの削除

% flutter pub remove PACKAGE

pubspec.yamlの内容も更新される。

パッケージ依存関係の表示

% flutter pub deps

ターゲットデバイス一覧の表示

% flutter devices

iOS/Androidエミュレータの場合は、これらが事前に起動している状態でなければデバイス情報は表示されない。

エミュレータ一覧の表示

% flutter emulators

エミュレータの起動

% flutter emulators --launch EMULATOR_NAME

Xcodeが導入済みで)iOSシュミレータと(Android Studioが導入済みで)Androidエミュレータが存在する状態では、コマンド "flutter emulators" の出力は以下のようになる。

% flutter emulators
3 available emulators:

apple_ios_simulator                                                                                              • iOS Simulator
• Apple  • ios
Pixel_Fold_API_35                                                                                                • Pixel Fold API 35
• Google • android

この場合、下のようなコマンドによってiOSシュミレータを起動できる。

% flutter emulators --launch apple_ios_simulator

また、下のようなコマンドによってAndroidエミュレータを起動できる。

% flutter emulators --launch Pixel_Fold_API_35

アプリの実行

% flutter run

すべてのターゲットデバイス向けにコマンド "flutter pub get" や "flutter pub build" 、アプリのインストールまでの一連の操作処理が実行される。

リリースモードでのアプリの実行

% flutter run --release

デバッグモードでのアプリの実行

% flutter run --debug

ビルド無しでアプリの実行

% flutter run --no-build

ターゲットデバイスを指定してアプリの実行

% flutter run -d DEVICE_ID

DEVICE_ID = コマンド "flutter devices" で表示されるデバイスIDを指定。

iOSシュミレータとAndoridエミュレータを起動している状態では、コマンド "flutter devices" の出力は以下のようになる。

% flutter devices
Found 4 connected devices:
  sdk gphone64 x86 64 (mobile) • emulator-5554                        • android-x64    • Android 15 (API 35) (emulator)
  iPhone 14 Pro Max (mobile)   • 42BB6078-C13C-4A30-A42F-E60DE8CFB18D • ios            • com.apple.CoreSimulator.SimRuntime.iOS-16-4 (simulator)
  macOS (desktop)              • macos                                • darwin-x64     • macOS 13.4.1 22F770820d darwin-x64
  Chrome (web)                 • chrome                               • web-javascript • Google Chrome 126.0.6478.63

No wireless devices were found.

この場合、下のようなコマンドによってプロジェクト・アプリをiOSシュミレータ上で起動できる。

% flutter run -d 42BB6078-C13C-4A30-A42F-E60DE8CFB18D

また、下のようなコマンドによってプロジェクト・アプリをAndroidエミュレータ上で起動できる。

% flutter run -d emulator-5554 

起動デバイススクリーンショットを取得

% flutter screenshot

コマンド "flutter screenshot --out FILE_PATH" によってスクリーンショット・ファイルの出力先パスを指定できる。

 

iOSシュミレータとAndroidエミュレータを使うことになるが、アプリ開発はほとんどこの環境で行うことができる。物理デバイス搭載の固有機能を利用するアプリでは実機での動作確認も必要となるが、実機を使った開発方法についてはまた別の記事で書くことになるだろう。

【参照リンク】

zenn.dev

https://book-reviews.blog/launch-the-flutter-application-on-iOS-and-Android-emulator/book-reviews.blog

Flutterのインストールと開発環境の構築〔基本編〕

近況報告になるが、去年末から本業仕事でIoT系プロジェクトに関わっていたが、最近それが一段落した。この仕事のターゲット機はESP32を搭載しているが、小生はそのファームウェアの開発を行った。また、AWS上で稼働するNestJSベースのWebアプリ・サーバープログラムの改造も手伝ったりした。こちらで得た技術知見もブログ記事に書いていこうと思っている。

本業に復帰する前の一昨年から去年前半まで(コロナ禍の最盛期)はIT開発は副業としてやっていたが、主に関わっていたのはスマホアプリ開発フレームワークプログラミング言語)はFlutter(Dart)を使っていた。Flutterを好んで使っていたのは、一つのプログラムコードでデスクトップ、Web、スマホアプリの全部に対応できるからだ。モダンなオブジェクト指向+宣言型の言語パラダイムも理解し易くて(小生の場合、使いこなしている自信レベルの習得に2ヶ月だった)、いまでもスマホアプリ開発用のフレームワーク・言語としてFlutter/Dartがベストの選択だと思っている。

一年近くブランクができてしまったので、再スタートのつもりで改めてスマホアプリ開発に取り組みたい。クリーンインストール新調したMacUbuntu機にFlutterによるスマホアプリ開発環境を構築したので、その作業内容を記事に書いていく。

小生がFlutterを使い始めたの頃はすでにSDKバージョン3.xはリリースされていたが、まだ2.xが主流だった。いまは3.xが主流になっており、色々と変わってしまっている点があるようだ。

Flutterのインストール

Flutter(Flutter SDK)は素のまま直接インストールすることもできるが、言語バージョン管理ツールを利用した方がプログラム毎のプロジェクト管理がやり易くなる。

Flutter用のバージョン管理ツールとして、FVM(Flutter Version Management)またはasdfが広く使われているようだ。

fvm.app

asdf-vm.com

FVMによるFlutterのインストール

FVMのインストール

% brew tap leoafarias/fvm
% brew install fvm
$ curl -fsSL https://fvm.app/install.sh | bash

Flutterバージョンのインストール

% fvm releases
% fvm install 3.19.6
% fvm list
Cache directory:  /Users/LOGNAME/fvm/versions
Directory Size: 73.02 MB

┌─────────┬─────────┬─────────────────┬──────────────┬──────────────┬────────┐
│ Version │ Channel │ Flutter Version │ Dart Version │ Release Date │ Global │
├─────────┼─────────┼─────────────────┼──────────────┼──────────────┼────────┤
│ 3.19.6  │         │ Need setup      │              │              │        │
└─────────┴─────────┴─────────────────┴──────────────┴──────────────┴────────┘


本記事執筆時点のFlutter SDKの最新Stable版は3.19.6-stableなのでこれをインストールしているが、任意のバージョンを指定してインストールすることもできる。

グローバルなFlutterバージョンの設定

プロジェクトディレクトリ外でもFlutter SDKのコマンドが利用できるように、グローバルなFlutterのバージョンを設定しておくことを薦める。

% fvm global 3.19.6
% cd
% fvm flutter --version
Flutter 3.19.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 54e66469a9 (2 weeks ago) • 2024-04-17 13:08:03 -0700
Engine • revision c4cd48e186
Tools • Dart 3.3.4 • DevTools 2.31.1

asdfによるFlutterのインストール

asdfのインストール手順については下の記事を参照してほしい。

blog.ketus-ix.work

Flutterバージョンのインストール

% asdf plugin add flutter
% asdf list all flutter
% asdf install flutter latest
% asdf reshim
% asdf list flutter
  3.19.6-stable

コマンド "asdf install flutter latest" はFluter SDKの最新Stable版をインストールする場合だが、下のようなコマンドによって指定したバージョンをインストールすることもできる。

% asdf install flutter 3.16.8-stable

補足情報

Homebrew環境のasdfでFlutter 3.0以降をインストールしようすると、下のようなエラーになることがある。

% asdf install flutter latest
/Users/LOGNAME/.asdf/plugins/flutter/bin/install: line 25: jq: command not found
/Users/LOGNAME/.asdf/plugins/flutter/bin/install: line 26: jq: command not found
/Users/LOGNAME/.asdf/plugins/flutter/bin/install: line 27: [: -gt: unary operator expected
Cannot find the download url for the version: 3.19.6-stable

この場合は、jqというパッケージをインストールすると解決できる。

% brew install jq

グローバルなFlutterバージョンの設定

プロジェクトディレクトリ外でもFlutter SDKのコマンドが利用できるように、グローバルなFlutterのバージョンを設定しておくことを薦める。

% asdf global flutter 3.19.6-stable
% cd
% flutter --version
Flutter 3.19.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 54e66469a9 (2 weeks ago) • 2024-04-17 13:08:03 -0700
Engine • revision c4cd48e186
Tools • Dart 3.3.4 • DevTools 2.31.1

必要なツールのインストール

Google Chromeのインストール

FlutterによるWebアプリの動作確認に使われるので、Google Chromeが必要となる。Google Chromeの公式サイトから入手できる。

下のようなコマンドによって、Homebrewを使ってGoogle Chromeをインストールすることもできる。

% brew install --cask google-chrome

なお、Chrome派生の他のWebブラウザVivaldiなど)を使っている場合は、環境変数CHROME_EXECUTABLEにその実行ファイルのパスを指定しておけば、そちらが使われる。

Xcodeのインストール

macOSデスクトップ・アプリの開発はXcodeを使わないとできない。XcodeiOSアプリにも対応しているので、Xcodeをインストールすればこの両方を開発できる。

最新版のXcodeApp Storeから入手できる。ただし、最新版Xcodeはインストール可能なmacOSのバージョンがその時点の最新版に限定されている。

Xcode

Xcode

  • Apple
  • 開発ツール
  • 無料
apps.apple.com

最新版より古いバージョンはApple DeveloperのXcode公式サイトから入手できる。

developer.apple.com

あるいは、Xcodesというユーティリティアプリを使ってXcodeをインストールこともできる。Xcodesについては下の記事を参照してほしい。

blog.ketus-ix.work

XcodesによってXcodeをインストールした場合は、同アプリのファイル名は /Applications/Xcode-VERSION.appになってしまうので、対象バージョンのコンテキストメニューから [Xcode.appとしてシンボリックリンクを作成] を実行しておくと良いだろう。

Xcodeをインストールしたら、下のコマンドを実行しておくこと。

% sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer

Flutter開発環境の状態確認

Flutter SDKにはFlutter開発環境の状態を調べてくれるコマンドがある。下のコマンドがそれだ(FVMを使っている場合のコマンドは "fvm flutter doctor")。

% flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.6, on macOS 12.7.4 21H1123 darwin-x64, locale ja-JP)
[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.

[!] Xcode - develop for iOS and macOS (Xcode 14.2)
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.
[✓] Chrome - develop for the web
[!] Android Studio (not installed)
[✓] VS Code (version 1.89.0)
[✓] Connected device (2 available)
[✓] Network resources

! Doctor found issues in 3 categories.

ここまでの手順操作が済んでいれば、多分上のような表示になるだろう。

問題として指摘されている "Android toolchain - Unable to locate Android SDK."、"Android Studio (not installed)" はAndroidアプリの開発に必要なコンポーネントなので、FlutterでAndroidアプリの開発を行わない場合は無視しても構わない。"Xcode - CocoaPods not installed." で指摘されているCocoaPodsはiOSアプリの開発に必要なもので、この状態でもmacOSデスクトップ・アプリの開発は行える。FlutterでiOSアプリの開発を行わない場合はこの指摘は無視しても構わない(これらのインストール方法については次の記事で説明する)。

Flutterプロジェクトの環境構築

新規プロジェクトの作成

FVMを使っている場合

% mkdir flutter_project
% cd flutter_project
% fvm use 3.19.6

No pubspec.yaml detected in this directory
✔ Would you like to continue? · yes                                                                                                                                                                                                                 
[WARN] Project is not a git repository. 
 But will set .gitignore as IDEs may use it,to determine what to index and display on searches,
You should add the fvm version directory ".fvm/" to .gitignore.
✔ Would you like to do that now? · yes                                                                                                                                                                                                              
✓ Added .fvm/ to .gitignore

✗ Could not resolve dependencies. (0.9s)

Expected to find project root in current working directory.

The error could indicate incompatible dependencies to the SDK.
✔ Would you like to continue pinning this version anyway? · yes                                                                                                                                                                                     
✓ Project now uses Flutter SDK : SDK Version : 3.19.6

% fvm flutter create .
Recreating project ....
  pubspec.yaml (created)
  README.md (created)
  lib/main.dart (created)
  test/widget_test.dart (created)
  windows/runner/flutter_window.cpp (created)
  windows/runner/utils.h (created)
  windows/runner/utils.cpp (created)
  windows/runner/runner.exe.manifest (created)
  windows/runner/CMakeLists.txt (created)
  windows/runner/win32_window.h (created)
  windows/runner/Runner.rc (created)
  windows/runner/win32_window.cpp (created)
  windows/runner/resources/app_icon.ico (created)
  windows/runner/main.cpp (created)
  windows/runner/resource.h (created)
  windows/runner/flutter_window.h (created)
  windows/flutter/CMakeLists.txt (created)
  windows/.gitignore (created)
  windows/CMakeLists.txt (created)
  ios/Runner.xcworkspace/contents.xcworkspacedata (created)
  ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (created)
  ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (created)
  ios/Runner/Info.plist (created)
  ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png (created)
  ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md (created)
  ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json (created)
  ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png (created)
  ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png (created)
  ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png (created)
  ios/Runner/Base.lproj/LaunchScreen.storyboard (created)
  ios/Runner/Base.lproj/Main.storyboard (created)
  ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata (created)
  ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (created)
  ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (created)
  ios/Flutter/Debug.xcconfig (created)
  ios/Flutter/Release.xcconfig (created)
  ios/Flutter/AppFrameworkInfo.plist (created)
  ios/.gitignore (created)
  flutter_project.iml (created)
  web/favicon.png (created)
  web/index.html (created)
  web/manifest.json (created)
  web/icons/Icon-maskable-512.png (created)
  web/icons/Icon-192.png (created)
  web/icons/Icon-maskable-192.png (created)
  web/icons/Icon-512.png (created)
  macos/Runner.xcworkspace/contents.xcworkspacedata (created)
  macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (created)
  macos/RunnerTests/RunnerTests.swift (created)
  macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png (created)
  macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png (created)
  macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png (created)
  macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png (created)
  macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png (created)
  macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (created)
  macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png (created)
  macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png (created)
  macos/Runner/DebugProfile.entitlements (created)
  macos/Runner/Base.lproj/MainMenu.xib (created)
  macos/Runner/MainFlutterWindow.swift (created)
  macos/Runner/Configs/Debug.xcconfig (created)
  macos/Runner/Configs/Release.xcconfig (created)
  macos/Runner/Configs/Warnings.xcconfig (created)
  macos/Runner/Configs/AppInfo.xcconfig (created)
  macos/Runner/AppDelegate.swift (created)
  macos/Runner/Info.plist (created)
  macos/Runner/Release.entitlements (created)
  macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (created)
  macos/Runner.xcodeproj/project.pbxproj (created)
  macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (created)
  macos/Flutter/Flutter-Debug.xcconfig (created)
  macos/Flutter/Flutter-Release.xcconfig (created)
  macos/.gitignore (created)
  android/app/src/profile/AndroidManifest.xml (created)
  android/app/src/main/res/mipmap-mdpi/ic_launcher.png (created)
  android/app/src/main/res/mipmap-hdpi/ic_launcher.png (created)
  android/app/src/main/res/drawable/launch_background.xml (created)
  android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png (created)
  android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (created)
  android/app/src/main/res/values-night/styles.xml (created)
  android/app/src/main/res/values/styles.xml (created)
  android/app/src/main/res/drawable-v21/launch_background.xml (created)
  android/app/src/main/res/mipmap-xhdpi/ic_launcher.png (created)
  android/app/src/main/AndroidManifest.xml (created)
  android/app/src/debug/AndroidManifest.xml (created)
  android/settings.gradle (created)
  android/gradle/wrapper/gradle-wrapper.properties (created)
  android/gradle.properties (created)
  android/.gitignore (created)
  android/app/build.gradle (created)
  android/app/src/main/kotlin/com/example/flutter_project/MainActivity.kt (created)
  android/build.gradle (created)
  android/flutter_project_android.iml (created)
  ios/RunnerTests/RunnerTests.swift (created)
  ios/Runner/Runner-Bridging-Header.h (created)
  ios/Runner/AppDelegate.swift (created)
  ios/Runner.xcodeproj/project.pbxproj (created)
  ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (created)
  analysis_options.yaml (created)
  .idea/runConfigurations/main_dart.xml (created)
  .idea/libraries/Dart_SDK.xml (created)
  .idea/libraries/KotlinJavaRuntime.xml (created)
  .idea/modules.xml (created)
  .idea/workspace.xml (created)
  linux/main.cc (created)
  linux/my_application.h (created)
  linux/my_application.cc (created)
  linux/flutter/CMakeLists.txt (created)
  linux/.gitignore (created)
  linux/CMakeLists.txt (created)
Resolving dependencies... (1.4s)
Got dependencies.
Wrote 128 files.

All done!
You can find general documentation for Flutter at: https://docs.flutter.dev/
Detailed API documentation is available at: https://api.flutter.dev/
If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev

In order to run your application, type:

  $ cd .
  $ flutter run

Your application code is in ./lib/main.dart.

コマンド "fvm use 3.19.6" によって、指定バージョンのFlutter SDKがプロジェクトディレクトリ内の.fvmディレクトリへインストールされる。また、コマンド "fvm flutter create ." によってプロジェクトディレクトリ内にpubspec.yamlファイルが作成され、プロジェクトの基本構成ファイル一式(サンプルソースやビルド用ファイルなど)が追加される。

補足情報

FVMでインストールしたFlutterを使用する場合、Flutter SDK側のコマンド実行はすべて "fvm flutter ..." という形式になってしまう。

下のような記述を.bashrc.zshrcに追加しておくと、"fvm" を省略できるので便利だろう。

alias dart='fvm dart'
alias flutter='fvm flutter'

asdfを使っている場合

% mkdir flutter_project
% cd flutter_project
% asdf local flutter 3.19.6-stable
% flutter --version
% flutter create .

既存プロジェクトの使用

既存のFlutterプロジェクトにはpubspec.yamlというファイルが含まれており、これにプロジェクトが利用しているFlutter SDKのパッケージ情報が記載されている。

FVMを使っている場合

% cd FLUTTER_PROJECT_DIR
% fvm use 3.19.6
% fvm flutter --version
% fvm flutter pub get

asdfを使っている場合

% cd FLUTTER_PROJECT_DIR
% asdf local flutter 3.19.6-stable
% flutter --version
% flutter pub get

"flutter pub get" はFlutterの公式パッケージ配布サイトpub.devからパッケージを取得するコマンドで、このコマンドはpubspec.yamlの内容を参照しながらプロジェクトのすべての依存パッケージをインストールする。

pub.dev

Visual Studio CodeのFlutter環境設定

Flutterによるプログラム開発もVisual Studio Codeを使って行っていた。iOS/Androidアプリの開発ではXcodeAndroid Studioも併用していたが、これらはアプリのビルド設定の調整やシュミレータや実機ターゲットでのプログラムのデバッグ・動作確認の目的にしか使っていなかった。

VSCode上でのFlutter開発の準備

VSCodeを使ってFlutterプログラムの開発を行うにあたって、"Dart" と "Flutter" という2つの拡張機能を入れておく。

他にもFlutter開発向けの拡張機能が在るが、最初は最低限この2つを入れておけば良いだろう。

VSCodeでの新規プロジェクトの作成

FVMを使っている場合

VSCodeのメニュー [Manage (管理)](左下の歯車マーク) > [Settings (設定)] によって設定画面を開き、左上の [Open Settings (JSON)](書類マーク)ボタンを押す。

すると、下のような画面が開く。

このファイルの既存の内容に下のような記述を追加して、編集内容を保存する。

  • /Users/LOGNAME/Application Support/Code/User/setttings.json
  {
      "workbench.colorCustomizations": {},
      "telemetry.telemetryLevel": "off",
      "editor.minimap.enabled": false,
-     "workbench.startupEditor": "none"
+     "workbench.startupEditor": "none",
+     "dart.flutterSdkPath": "/Users/LOGNAME/fvm/versions/3.19.6"
  }

※"3.19.6" の部分は作成するプロジェクトで使用予定の(FVMでインストール済みの)Flutter SDKのバージョン、"LOGNAME" はログインユーザ名。

その後、VSCodeを再起動するか、コマンドパレット・メニュー "Developer: Reload Window" を実行する。

VSCodeが再起動したら、コマンドパレットに"Flutter" と入力し、メニューから "Flutter: New Project" を選択すると、さらにメニューが表示されるので、そのメニューから "Application"を選ぶ。

すると、ファイル選択ダイアログが開くので、プロジェクトの保存場所を選んでから、新しいプロジェクトの名前を入力する。

上記の手順に従ってVSCode上でFlutterのプロジェクトを作成すると、プロジェクトディレクトリが作成され、その中にpubspec.yamlとプロジェクトの基本構成ファイル一式が追加される。

続けて、メニュー [Terminal (ターミナル)] > [New Terminal (新しいターミナル)] によってターミナルパネルを開き、下のコマンドを実行する。

% fvm use 3.19.6

※"3.19.6" の部分は最初のsettings.json内で指定したバージョンと同一であること。

これによって、指定バージョンのFlutter SDKがプロジェクトディレクトリ内の.fvmディレクトリへインストールされ、同時に下のような内容の .vscode/settings.json ファイルも作成される。

  • .vscode/setttings.json
{
  "dart.flutterSdkPath": ".fvm/versions/3.19.6"
}

このファイルの内容を下のように編集した上で保存する。

  • .vscode/settings.json
  {
-   "dart.flutterSdkPath": ".fvm/versions/3.19.6"
+   "dart.flutterSdkPath": ".fvm/versions/3.19.6",
+   "search.exclude": {
+     "**/.fvm": true
+   },
+   "files.watcherExclude": {
+     "**/.fvm": true
+   }
  }

エクスプローラパネル内のファイル lib/main.dart を選択している状態で右下ステータスバー上の "{ }"("Dart" の左横)をクリックして、表示されるメニュー項目に "3.19.6 - Flutter SDK"("3.19.6" の部分は上のコマンド "fvm use VERSION" のバージョン文字列と一致)が存在することを確認する。存在している場合は、同項目右横のピン・マークを押す。

すると、ステータスバー上にそのバージョン番号が表示される。

この最後の操作はオプションだが、プロジェクトで使用しているFlutter SDKのバージョンが常に表示されている方が判り易くなる。

asdfを使っている場合

VSCodeのメニュー [Manage (管理)](左下の歯車マーク) > [Settings (設定)] によって設定画面を開き、左上の [Open Settings (JSON)](書類マーク)ボタンを押す。すると、/Users/LOGNAME/Application Support/Code/User/setttings.jsonというファイルが画面に表示される。

このファイルの既存の内容に下のような記述を追加して、編集内容を保存する。

  • /Users/LOGNAME/Application Support/Code/User/setttings.json
  {
      "workbench.colorCustomizations": {},
      "telemetry.telemetryLevel": "off",
      "editor.minimap.enabled": false,
-     "workbench.startupEditor": "none"
+     "workbench.startupEditor": "none",
+     "dart.flutterSdkPath": "/Users/LOGNAME/.asdf/installs/flutter/3.19.6-stable"
  }

※"3.19.6-stable" の部分は作成するプロジェクトで使用予定の(asdfでインストール済みの)Flutter SDKのバージョン、"LOGNAME" はログインユーザ名。

その後、VSCodeを再起動するか、コマンドパレット・メニュー "Developer: Reload Window" を実行する。

VSCodeが再起動したら、コマンドパレットに"Flutter" と入力し、メニューから "Flutter: New Project" を選択すると、さらにメニューが表示されるので、そのメニューから "Application"を選ぶ。

すると、ファイル選択ダイアログが開くので、プロジェクトの保存場所を選んでから、新しいプロジェクトの名前を入力する。

上記の手順に従ってVSCode上でFlutterのプロジェクトを作成すると、プロジェクトディレクトリが作成され、その中にpubspec.yamlとプロジェクトの基本構成ファイル一式が追加される。

続けて、メニュー [Terminal (ターミナル)] > [New Terminal (新しいターミナル)] によってターミナルパネルを開き、下のコマンドを実行する。

% asdf local flutter 3.19.6-stable

※"3.19.6-stable" の部分は最初のsettings.json内で指定したバージョンと同一であること。

さらに、下のような内容の .vscode/settings.json ファイルを作成する(本ファイルが存在しない場合は、コマンドパレット・メニュー "Prefereces: Open Workspace Settings (JSON)" によって作成できる)。

  • .vscode/setttings.json
{
  "dart.flutterSdkPath": "/Users/LOGNAME/.asdf/installs/flutter/3.19.6-stable"
}

※"3.19.6-stable" の部分はプロジェクトで使用するFlutter SDKのバージョン(上のコマンド "asdf local flutter VERSION" で指定したバージョン文字列)と一致していること。"LOGNAME" はログインユーザ名。

エクスプローラパネル内のファイル lib/main.dart を選択している状態で右下ステータスバー上の "{ }"("Dart" の左横)をクリックして、表示されるメニュー項目に "3.19.6 - Flutter SDK" ("3.19.6" の部分は上のコマンド "asdf local flutter VERSION" のバージョン番号と一致)が存在することを確認する。存在している場合は、同項目右横のピン・マークを押す。すると、ステータスバー上にそのバージョン番号が表示される。

この最後の操作はオプションだが、プロジェクトで使用しているFlutter SDKのバージョンが常に表示されている方が判り易くなる。

VSCodeでの既存プロジェクトの使用

FVMを使っている場合

VSCodeを起動して、既存プロジェクトのディレクトリを開く。

メニュー [Terminal (ターミナル)] > [New Terminal (新しいターミナル)] によってターミナルパネルを開き、下のコマンドを実行する。

% fvm use 3.19.6

※"3.19.6" の部分はプロジェクトで使用予定の(FVMでインストール済みの)Flutter SDKのバージョン。

これによって、指定バージョンのFlutter SDKがプロジェクトディレクトリ内の.fvmディレクトリへインストールされ、同時に下のような内容の .vscode/settings.json ファイルも作成される。

  • .vscode/setttings.json
{
  "dart.flutterSdkPath": ".fvm/versions/3.19.6"
}

.vscode/settings.json の内容を下のように編集する。

  • .vscode/settings.json
  {
-   "dart.flutterSdkPath": ".fvm/versions/3.19.6"
+   "dart.flutterSdkPath": ".fvm/versions/3.19.6",
+   "search.exclude": {
+     "**/.fvm": true
+   },
+   "files.watcherExclude": {
+     "**/.fvm": true
+   }
  }

エクスプローラパネル内のファイル lib/main.dart を選択している状態で右下ステータスバー上の "{ }"("Dart" の左横)をクリックして、表示されるメニュー項目に "3.19.6 - Flutter SDK" ("3.19.6" は上のコマンド "flutter use VERSION" のバージョン文字列と一致)が存在することを確認する。存在している場合は、同項目右横のピン・マークを押す。すると、ステータスバー上にそのバージョン番号が表示される。

この操作はオプションだが、プロジェクトで使用しているFlutter SDKのバージョンが常に表示されている方が判り易くなる。

コマンドパレットでメニュー "Flutter: Get Packages" を実行する。これによって、プロジェクトのすべての依存パッケージがインストールされる。

asdfを使っている場合

VSCodeを起動して、既存プロジェクトのディレクトリを開く。

メニュー [Terminal (ターミナル)] > [New Terminal (新しいターミナル)] によってターミナルパネルを開き、下のコマンドを実行する。

% asdf local flutter 3.19.6-stable

※"3.19.6-stable" の部分はプロジェクトで使用予定(asdfでインストール済みの)Flutter SDKのバージョン。

さらに、下のような内容のファイル .vscode/settings.jsonを作成する(本ファイルが存在しない場合は、コマンドパレット・メニュー "Prefereces: Open Workspace Settings (JSON)" によって作成できる)。

  • .vscode/setttings.json
{
  "dart.flutterSdkPath": "/Users/LOGNAME/.asdf/installs/flutter/3.19.6-stable"
}

※"3.19.6-stable" の部分は上のコマンド "asdf local flutter VERSION" で指定したバージョン文字列と一致していること。"LOGNAME" はログインユーザ名。

エクスプローラパネル内のファイル lib/main.dart を選択している状態で右下ステータスバー上の "{ }"("Dart" の左横)をクリックして、表示されるメニュー項目に "3.19.6 - Flutter SDK" ("3.19.6" の部分は上のコマンド "asdf local flutter VERSION" のバージョン番号と一致)が存在することを確認する。存在している場合は、同項目右横のピン・マークを押す。すると、ステータスバー上にそのバージョン番号が表示される。

この操作はオプションだが、プロジェクトで使用しているFlutter SDKのバージョンが常に表示されている方が判り易くなる。

コマンドパレットでメニュー "Flutter: Get Packages" を実行する。これによって、プロジェクトのすべての依存パッケージがインストールされる。

Flutterプロジェクトのビルドと動作確認

VSCodeでのFlutterプロジェクトのビルドと起動実行は簡単だ。

最初に、Flutterプロジェクトのディレクトリを開いている状態でステータスバー上のターゲットデバイス表示を押す。すると、下のようなメニューが開くので、プログラムの実行対象デバイスを選択する。

本記事の内容に従って手順操作を行っていれば、Flutterのターゲットデバイスとして上のように "Chrome" と "macOS" の2つしか表示されないはずだ。

ターゲットデバイスを選択すると、それがステータスバー上に表示される。

この状態でメニュー [Run (実行)] > [Start Debugging (デバッグの開始) F5] または [Run Without Debugging (デバッグなしで実行) ^ F5] を選ぶと、プロジェクトのビルドが行われ、ビルドが成功すれば、プログラムが起動する。

 

次の記事で、FlutterによるiOSAndroidアプリ開発環境の追加的な構築手順について書くつもりだ。

【参照リンク】

zenn.dev   

XcodesによるXcodeのインストール

Macを使ってmacOSiOS用プログラムを開発するにはXcodeが必要になる。Apple IDアカウントを作成してApple Developerサイトでユーザー登録をすれば、誰でもXcodeを入手することができる。

ただし、Xcodeはバージョン毎に使用可能なmacOSのバージョンが決まっており、最新版を入手すれば良いというものではない。自分が使っているmacOSのバージョンを調べて、それに合ったバージョンのXcodeを入手する必要がある。また、Xcodeはかなり大きなサイズのアプリなので、Apple Developerからダウンロードするのに時間がかかる。MacXcodeを導入する作業は結構面倒だったりする。

じつは、Xcodeのインストールをサクッとやれるアプリが存在する。(紛らわしい名前だが)Xcodesという奴だ。

github.com

Xcodesを見つけてから、小生はXcodeのインストールは常にこれを使って行っている。

本記事では、このXcodesについて紹介する。

コマンド版Xcodesのインストール

XcodesにはCLIコマンド版とGUIアプリ版が存在する。どちらもHomebrewを使ってインストールできる。

コマンド版Xcodesは下のコマンドによってインストールできる。

% brew install xcodes aria2

aria2が存在すると、これが利用されることでXcodesのダウンロード速度が大幅に向上するので、一緒にインストールしておくことを勧める。

コマンド版Xcodesの使用方法

Xcodesを使用するにはApple IDアカウントが必要になる。Xcodesを初めて使うときに、Apple IDアカウントのユーザー名とパスワードの入力を求められる。

コマンド版Xcodesの使い方は簡単で、多分以下の3つのコマンドくらいしか使わないだろう(他のコマンドについてはXcodesのサイトを参照してほしい)。

入手可能なXcodeバージョンの一覧表示

% xcodes list

指定バージョンのXcodeのインストール

% xcodes install VERSION

既存のXcodeバージョンのアンイストール

% xcodes uninstall VERSION

Xcodesによって取得したXcode/Applicationsフォルダ内に "Xcode-VERSION.app" というファイル名で追加される。

アプリ版Xcodesのインストール

アプリ版Xcodesは下のコマンドによってインストールできる。

% brew install --cask xcodes

アプリ版Xcodesの使用方法

/Applications/Xcodes.appを起動すると、下のような画面が表示される。

指定バージョンのXcodeのインストール

アプリ版Xcodesの使い方も簡単だ。取得したいXcodeのバージョンを選んでその右横の[インストール]ボタンを押せば、そのダウンロードとインストールが開始される。

Xcodesが動作中のmacOSバージョンに未対応のバージョンのXcodeをインストールしようとすると、下のような警告が表示されるが、この警告を無視して[インストール]を押せば、入手可能なすべてのバージョンのXcodeをインストールすることができる(Apple Developerから入手したXcodeはそのバージョンが未対応のmacOSバージョンにはインストールできない)。

既存のXcodeバージョンのアンイストール

インストール済みのXcodeを削除したい場合は、そのバージョンのコンテキストメニュー(右クリックが有効なら、右クリックによって表示されるメニュー)から[アンインストール]を選ぶと、それをアンイストールできる。

ls コマンドと vim の表示カラー設定をSolarizedにする

MacLinuxのターミナルでもっとも多く使うコマンドといえば "ls"ではないだろうか。そして、一番良く使うCLIアプリといえば vimだろう。

この2つには表示カラー設定機能が備わっており、これを利用してカラー設定を追加すると作業上の情報視認性が向上する。

こういう目的に使われるカラー・テーマとして有名なSolarizedを利用して、lsコマンドとvimの表示カラー設定を行ってみた。

ls コマンドの表示カラー設定

GNU版 ls と dircolors のインストール〔Macのみ〕

Macに入っているデフォルトのlsコマンドはBSD版であり、同コマンドの表示カラー設定はGNU版のlsdircolorsでないとできない。

これらはcoreutilsというパッケージに収納されているので、Macではこれをインストールしておく。

% brew install coreutils

GNU版のlsglsdircolorsgdircolorsというコマンドでそれぞれ利用できるようになる。

ls コマンド用カラー・テーマの取得

lsコマンド用のカラー設定として、下のサイトで配布されているカラー・テーマを取得する。

github.com

$ git clone https://github.com/seebi/dircolors-solarized.git ~/.dircolors

ls コマンドのカラー設定

~/.bash_profileまたは~/.bashrczshなら、~/.zprofile~/.zshrc)に下のような記述を追加する。

eval $(gdircolors ~/.dircolors/dircolors.256dark)
alias ls='gls --color=auto'

"eval $(gdircolors ...)" でカラー設定の読み込み、"alias ls=" でlsコマンドのglsへの置き換えを行っている。

eval $(dircolors ~/.dircolors/dircolors.256dark)
alias ls='ls --color=auto'

前者によって読み込まれた内容はLS_COLORSという環境変数に設定され、lsMacではgls)コマンドはこの環境変数の値を参照することで表示色の変更を行っている。

ターミナルを再起動するかコマンド "source ~/.bashrc" を実行すれば、上記の設定が有効になる。

その後、コマンド "ls -la"とかを実行すれば、この設定が反映されていることが確認できるだろう。

vim の表示カラー設定

vim 用カラー・テーマの取得

vim用のカラー設定として、下のサイトで配布されているカラー・テーマを取得する。

github.com

$ git clone https://github.com/altercation/vim-colors-solarized.git /tmp/vim-colors-solarized
$ mkdir -p ~/.vim/colors
$ mv /tmp/vim-colors-solarized/colors/solarized.vim ~/.vim/colors

vim のカラー設定

vimのカラー設定はファイル~/.vimrcに以下のような記述を追加することで行える。

$ vi ~/.vimrc
syntax enable
set background=dark
colorscheme solarized
let g:solarized_termcolors=256

コマンドviで適当なファイルを開いてやれば、上記の設定が反映されていることが確認できるだろう。

上ではカラー設定としてSolarized Darkを使っているが、~/.vimrc内の"set background=dark" を "set background=light" に変更すればSolarized Lightを使うこともできる。

【参照リンク】

qiita.com

【Homebrew】アップグレード時に "missing xcrun" エラー

Homebrewをアップグレードしようとしたら、下のようなエラーが起きて、できない現象に遭遇した。

% brew upgrade
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

Homebrewの状態を確認すると、下のようになっていた。

% brew config
HOMEBREW_VERSION: >=2.5.0 (shallow or no git repository)
ORIGIN: (none)
HEAD: (none)
Last commit: never
Core tap ORIGIN: https://github.com/Homebrew/homebrew-core
Core tap HEAD: (none)
Core tap last commit: never
Core tap branch: (none)
HOMEBREW_PREFIX: /Users/LOGNAME/homebrew
HOMEBREW_REPOSITORY: /Users/LOGNAME/homebrew
HOMEBREW_CELLAR: /Users/LOGNAME/homebrew/Cellar
HOMEBREW_CASK_OPTS: []
HOMEBREW_DISPLAY: /private/tmp/com.apple.launchd.1YkqUDCCsg/org.xquartz:0
HOMEBREW_EDITOR: vim
HOMEBREW_MAKE_JOBS: 24
HOMEBREW_NO_AUTO_UPDATE: set
Homebrew Ruby: 2.6.8 => /Users/LOGNAME/homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/bin/ruby
CPU: 24-core 64-bit ivybridge
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
Clang: N/A
Git: N/A
Curl: 8.4.0 => /usr/bin/curl
macOS: 12.7.4-x86_64
CLT: N/A
Xcode: 14.2 => /Applications/Xcode-14.2.0.app/Contents/Developer

Homebrew環境でCommand Line Toolsが見つからなくなっているのが原因のようだ。

下のコマンドによってCommand Line Toolsを再インストールしたら、この問題を解決できた。

% xcode-select --install
% brew config
HOMEBREW_VERSION: 3.6.10
ORIGIN: https://github.com/Homebrew/brew
HEAD: eaf887656ffb8e9e35ccf08081814d4735637564
Last commit: 1 year, 5 months ago
Core tap ORIGIN: https://github.com/Homebrew/homebrew-core
Core tap HEAD: 522d42deab7e61f770e75b03661e53ba08d5aca0
Core tap last commit: 1 year, 5 months ago
Core tap branch: master
HOMEBREW_PREFIX: /Users/LOGNAME/homebrew
HOMEBREW_REPOSITORY: /Users/LOGNAME/homebrew
HOMEBREW_CELLAR: /Users/yuhri/homebrew/Cellar
HOMEBREW_CASK_OPTS: []
HOMEBREW_DISPLAY: /private/tmp/com.apple.launchd.1YkqUDCCsg/org.xquartz:0
HOMEBREW_EDITOR: vim
HOMEBREW_MAKE_JOBS: 24
HOMEBREW_NO_AUTO_UPDATE: set
Homebrew Ruby: 2.6.8 => /Users/LOGNAME/homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/bin/ruby
CPU: 24-core 64-bit ivybridge
Clang: 14.0.0 build 1400
Git: 2.37.1 => /Library/Developer/CommandLineTools/usr/bin/git
Curl: 8.4.0 => /usr/bin/curl
macOS: 12.7.4-x86_64
CLT: 14.2.0.0.1.1668646533
Xcode: 14.2 => /Applications/Xcode-14.2.0.app/Contents/Developer

Mac Pro 2013の内蔵SSDを交換するために、Time Machineバックアップと移行アシスタントを使ってシステム復元を行ったら、このような現象に遭遇してしまった。

Homebrewのアップグレードに限らず、他のコマンドの実行時にも起きることがある現象らしい。また、macOSをアップデートしたりしても起きることがあるそうだ。

【参照リンク】

qiita.com