課題2: Cargo実践とプロジェクト構築

マンダトリー要件

問題1:環境構築の確認(10点)

以下のコマンドを実行し、出力をキャプチャして提出しなさい。

# 1. バージョン確認(各2点)
rustc --version
cargo --version
rustup --version

# 2. インストール済みターゲットの確認(2点)
rustup target list --installed

# 3. インストール済みコンポーネントの確認(2点)
rustup component list --installed

提出物

  • environment.txt: 上記コマンドの出力結果
  • 問題2:Hello Worldプロジェクト(15点)

  • プロジェクトの作成(5点)
   cargo new hello_rust
   

  • main.rsの修正(5点)
以下の要件を満たすプログラムを作成: - コマンドライン引数を受け取る - 引数がない場合は "Hello, World!" を表示 - 引数がある場合は "Hello, [名前]!" を表示

   // 期待される動作
   // $ cargo run
   // Hello, World!

   // $ cargo run -- Alice
   // Hello, Alice!
   

  • ビルドと実行(5点)
- デバッグビルドを実行 - リリースビルドを実行 - それぞれのバイナリサイズを比較

提出物

  • src/main.rs: 修正したソースコード
  • build_comparison.txt: ビルド結果の比較(サイズ、コンパイル時間)
  • 問題3:ライブラリプロジェクト(25点)

    calculatorという名前のライブラリクレートを作成しなさい。

  • プロジェクト作成(5点)
   cargo new --lib calculator
   

  • 基本機能の実装(10点)

src/lib.rs:

   /// 2つの数値を加算します
   pub fn add(a: i32, b: i32) -> i32 {
       // TODO: 実装
   }

   /// 2つの数値を減算します
   pub fn subtract(a: i32, b: i32) -> i32 {
       // TODO: 実装
   }

   /// 2つの数値を乗算します
   pub fn multiply(a: i32, b: i32) -> i32 {
       // TODO: 実装
   }

   /// 2つの数値を除算します(0除算はエラー)
   pub fn divide(a: i32, b: i32) -> Result<i32, String> {
       // TODO: 実装
       // ヒント:b == 0の場合はErr("Division by zero")を返す
   }
   

  • テストの実装(10点)

各関数に対して最低2つのテストケースを作成:

   #[cfg(test)]
   mod tests {
       use super::*;

       #[test]
       fn test_add() {
           assert_eq!(add(2, 3), 5);
           assert_eq!(add(-1, 1), 0);
       }

       #[test]
       fn test_divide() {
           assert_eq!(divide(10, 2), Ok(5));
           assert!(divide(10, 0).is_err());
       }

       // TODO: subtract, multiplyのテストも追加
   }
   

提出物

  • calculator/src/lib.rs: 実装とテスト
  • test_results.txt: cargo testの実行結果
  • 問題4:依存関係の管理(20点)

    json_readerプロジェクトを作成し、JSONファイルを読み込む機能を実装しなさい。

  • プロジェクト作成と依存関係追加(5点)
   cargo new json_reader
   cd json_reader
   

Cargo.tomlに以下を追加:

   [dependencies]
   serde = { version = "1.0", features = ["derive"] }
   serde_json = "1.0"
   

  • データ構造の定義(5点)

src/main.rs:

   use serde::{Deserialize, Serialize};

   #[derive(Debug, Serialize, Deserialize)]
   struct Person {
       name: String,
       age: u32,
       email: String,
   }

   // TODO: 実装
   

  • JSON読み込みの実装(10点)

以下の機能を実装: - JSONファイルから Person を読み込む - 読み込んだデータを表示 - エラーハンドリング

テスト用JSONperson.json):

   {
     "name": "Alice",
     "age": 30,
     "email": "alice@example.com"
   }
   

期待される出力:

   Name: Alice
   Age: 30
   Email: alice@example.com
   

提出物

  • json_reader/Cargo.toml: 依存関係設定
  • json_reader/src/main.rs: 実装
  • json_reader/person.json: テストデータ
  • execution_result.txt: 実行結果
  • 問題5:コード品質ツール(15点)

    前の問題(calculator)に対して、以下のツールを実行しなさい。

  • Rustfmt(5点)
   cargo fmt
   
フォーマット前後のdiffを記録

  • Clippy(5点)
   cargo clippy
   
警告があれば修正し、その内容を記録

  • ドキュメント生成(5点)
   cargo doc --open
   
各関数にドキュメントコメントを追加:
   /// 2つの数値を加算します。
   ///
   /// # Examples
   ///
   /// 
/// use calculator::add; /// assert_eq!(add(2, 3), 5); ///
   pub fn add(a: i32, b: i32) -> i32 {
       a + b
   }
   

提出物

  • clippy_report.txt: Clippyの実行結果と修正内容
  • calculator/src/lib.rs: ドキュメントコメント追加版

問題6:プロジェクト構造(15点)

multi_moduleプロジェクトを作成し、適切なモジュール構造を実装しなさい。

要件

multi_module/
├── Cargo.toml
└── src/
    ├── main.rs
    ├── lib.rs
    ├── math/
    │   ├── mod.rs
    │   ├── basic.rs    # add, subtract
    │   └── advanced.rs # power, sqrt
    └── string/
        ├── mod.rs
        └── utils.rs    # reverse, to_uppercase

実装内容

  • math::basicモジュール:add, subtract関数
  • math::advancedモジュール:power, sqrt関数
  • string::utilsモジュール:reverse, to_uppercase関数
  • lib.rs:各モジュールを公開
  • main.rs:各関数を使用してデモ

提出物

  • multi_module/ディレクトリ全体
  • module_structure.txt: ツリー構造の説明

---

ボーナス課題

> ボーナス: 以下はオプションです。マンダトリー要件を完了してから挑戦してください。

ボーナス1:ワークスペースの構築(10点)

複数のクレートを含むワークスペースを作成しなさい。

構造

my_workspace/
├── Cargo.toml          # ワークスペース設定
├── core/               # 共通ライブラリ
│   ├── Cargo.toml
│   └── src/lib.rs
├── cli/                # CLIツール
│   ├── Cargo.toml
│   └── src/main.rs
└── web/                # Webサーバー
    ├── Cargo.toml
    └── src/main.rs

要件

  • coreクレート:共通のデータ構造と関数
  • cliクレート:coreを使用するCLIツール
  • webクレート:coreを使用するWebサーバー(簡易版)
  • ワークスペース全体のビルドとテスト

提出物

  • my_workspace/ディレクトリ全体
  • workspace_guide.md: 各クレートの説明と使い方

ボーナス2:CLIツールの完成(10点)

clapクレートを使用して、本格的なCLIツールを作成しなさい。

機能要件

# ファイル情報を表示するツール
$ fileinfo --help
A simple file information tool

USAGE:
    fileinfo [OPTIONS] <FILE>

ARGS:
    <FILE>    The file to analyze

OPTIONS:
    -s, --size       Show file size
    -t, --type       Show file type
    -m, --modified   Show last modified time
    -a, --all        Show all information
    -h, --help       Print help information

実装内容

  • clapを使用したコマンドライン引数パース
  • ファイルのメタデータ取得
  • 適切なエラーハンドリング
  • カラー出力(colored クレート使用)

提出物

  • fileinfo/プロジェクト全体
  • usage_examples.txt: 使用例
  • ボーナス3:ビルド最適化の実験(10点)

    様々なビルド設定を試し、性能を比較しなさい。

    実験内容

  • サンプルプログラム作成
- フィボナッチ数列(再帰版) - 大きな配列のソート - 文字列処理

  • ビルドプロファイルの比較
   [profile.release-small]
   inherits = "release"
   opt-level = "z"
   lto = true
   codegen-units = 1
   strip = true

   [profile.release-fast]
   inherits = "release"
   opt-level = 3
   lto = "fat"
   codegen-units = 1
   

  • 測定項目
- コンパイル時間 - バイナリサイズ - 実行時間 - メモリ使用量

提出物

  • benchmark/プロジェクト
  • optimization_report.md: 実験結果とグラフ
  • Cargo.toml: 各種プロファイル設定
  • ボーナス4:CI/CDパイプラインの構築(10点)

    GitHub Actionsを使用して、完全なCI/CDパイプラインを構築しなさい。

    要件

  • リント・フォーマットチェック
- rustfmt - clippy

  • マルチプラットフォームビルド
- Linux (x86_64) - macOS (x86_64, aarch64) - Windows (x86_64)

  • テスト
- ユニットテスト - 統合テスト - ドキュメントテスト

  • リリース自動化
- タグプッシュ時にバイナリをビルド - GitHub Releasesにアップロード

提出物

  • .github/workflows/ci.yml: CI設定
  • .github/workflows/release.yml: リリース設定
  • ci_cd_guide.md: パイプラインの説明

ボーナス5:カスタムCargoコマンド(10点)

cargo-customという独自のCargoサブコマンドを作成しなさい。

機能例

cargo custom analyze   # プロジェクトの統計を表示
cargo custom clean-all # targetと依存キャッシュを削除
cargo custom graph     # 依存関係グラフを生成

実装ガイド

  • バイナリ名をcargo-customにする
  • 第1引数が"custom"であることを確認
  • サブコマンドに応じた処理を実装

提出物

  • cargo-custom/プロジェクト
  • README.md: インストールと使用方法

---

評価基準

マンダトリー部分(80点)

項目 配点 評価ポイント
問題1:環境構築 10点 正しいインストールと確認
問題2:Hello World 15点 基本的なプロジェクト操作
問題3:ライブラリ 25点 関数実装とテストの質
問題4:依存関係 20点 外部クレートの正しい使用
問題5:品質ツール 15点 ツールの理解と活用
問題6:構造化 15点 モジュール設計の適切性

ボーナス部分(20点)

項目 配点 評価ポイント
ボーナス1:ワークスペース 10点 複数クレートの管理
ボーナス2:CLIツール 10点 実用的なツール作成
ボーナス3:最適化実験 10点 詳細な性能分析
ボーナス4:CI/CD 10点 自動化パイプライン
ボーナス5:カスタムコマンド 10点 Cargoエコシステムの理解

: ボーナスは最大20点まで加算されます。

---

提出方法

ファイル構成

rust-foundations-02/
├── problem1/
│   └── environment.txt
├── problem2/
│   ├── hello_rust/
│   └── build_comparison.txt
├── problem3/
│   ├── calculator/
│   └── test_results.txt
├── problem4/
│   ├── json_reader/
│   └── execution_result.txt
├── problem5/
│   ├── calculator/         # 修正版
│   └── clippy_report.txt
├── problem6/
│   ├── multi_module/
│   └── module_structure.txt
└── bonus/
    ├── bonus1-workspace/
    ├── bonus2-cli/
    ├── bonus3-benchmark/
    ├── bonus4-ci/
    └── bonus5-cargo-custom/

Git管理

以下をコミットに含めないこと(.gitignore):

# ビルド成果物
target/
Cargo.lock  # ライブラリの場合は含めない

# IDE
.idea/
.vscode/
*.swp

提出期限

  • マンダトリー:第2章学習後、1週間以内
  • ボーナス:第5章修了時まで

---

ヒント

問題2のヒント

コマンドライン引数の取得:

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    // args[0]はプログラム名
    // args[1]以降が引数
}

問題3のヒント

divide関数の実装:

pub fn divide(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err("Division by zero".to_string())
    } else {
        Ok(a / b)
    }
}

問題4のヒント

ファイル読み込み:

use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let data = fs::read_to_string("person.json")?;
    let person: Person = serde_json::from_str(&data)?;
    println!("{:?}", person);
    Ok(())
}

ボーナス2のヒント

clapの基本的な使い方:

use clap::Parser;

#[derive(Parser)]
#[command(name = "fileinfo")]
#[command(about = "A simple file information tool")]
struct Args {
    /// The file to analyze
    file: String,

    /// Show file size
    #[arg(short, long)]
    size: bool,
}

fn main() {
    let args = Args::parse();
    // args.file, args.sizeを使用
}

---

学習の確認

この課題を通じて、以下を理解できたか確認してください:

  • [ ] Rustupによるツールチェーン管理
  • [ ] Cargoの基本コマンド(build, run, test, doc)
  • [ ] プロジェクト構造のベストプラクティス
  • [ ] 外部クレートの使用方法
  • [ ] コード品質ツール(rustfmt, clippy)
  • [ ] モジュールシステム
  • [ ] ワークスペースの概念
  • [ ] CI/CDの基本

次の章では、Rustの基本構文(変数、型、関数)を学びます。