# makefile テンプレート自動選択機構

本ドキュメントでは、makefw フレームワークにおける makefile テンプレートの自動選択機構について説明します。

# 1 概要

makefw では、すべての最終階層 makefile を統一テンプレート (`__template.mk`) に統一し、ディレクトリパスと言語の自動判定により、適切なビルドテンプレートを自動的に選択します。

これにより、以下のメリットが得られます：

- 完全な統一: すべての makefile が同一内容になり、メンテナンスが容易
- 自動判定: ディレクトリパスと .csproj の有無で自動的に適切なテンプレートを選択
- 柔軟性: プロジェクト固有の設定は makepart.mk で管理

# 2 アーキテクチャ

## 2.1 ファイル構成

    makefw/makefiles/
    +-- __template.mk           # 統一テンプレート（すべての最終階層 makefile で使用）
    +-- prepare.mk              # 準備処理（コンパイラ設定、makepart.mk 読み込み）
    +-- makemain.mk             # テンプレート自動選択ロジック
    +-- auto-select.mk          # パス判定による分岐（makemain.mk と同じ）
    +-- makelibsrc_c_cpp.mk     # C/C++ ライブラリビルド用テンプレート
    +-- makelibsrc_dotnet.mk    # .NET ライブラリビルド用テンプレート
    +-- makesrc_c_cpp.mk        # C/C++ 実行体ビルド用テンプレート
    +-- makesrc_dotnet.mk       # .NET 実行体ビルド用テンプレート

## 2.2 処理フロー

# 3 統一テンプレート (__template.mk)

すべての最終階層 makefile で使用する標準テンプレートです。

    find-up = \
        $(if $(wildcard $(1)/$(2)),$(1),\
            $(if $(filter $(1),$(patsubst %/,%,$(dir $(1)))),,\
                $(call find-up,$(patsubst %/,%,$(dir $(1))),$(2))\
            )\
        )
    WORKSPACE_FOLDER := $(strip $(call find-up,$(CURDIR),.workspaceRoot))

    include $(WORKSPACE_FOLDER)/makefw/makefiles/prepare.mk

    ##### makepart.mk の内容は、このタイミングで処理される #####

    include $(WORKSPACE_FOLDER)/makefw/makefiles/makemain.mk

## 3.1 重要なポイント

1. 統一性: すべての最終階層 makefile が完全に同一
2. 編集禁止: 固有の設定は makepart.mk に記述
3. 処理順序: prepare.mk → makepart.mk → makemain.mk

# 4 自動選択ロジック (makemain.mk)

ディレクトリパスと .csproj の有無により、適切なビルドテンプレートを自動選択します。

    #
    #

    ifneq (,$(findstring /libsrc/,$(CURDIR)))
        # .csproj があれば .NET ライブラリ、なければ C/C++ ライブラリ
        ifneq ($(wildcard *.csproj),)
            include $(WORKSPACE_FOLDER)/makefw/makefiles/makelibsrc_dotnet.mk
        else
            include $(WORKSPACE_FOLDER)/makefw/makefiles/makelibsrc_c_cpp.mk
        endif
    else ifneq (,$(findstring /src/,$(CURDIR)))
        # .csproj があれば .NET 実行体、なければ C/C++ 実行体
        ifneq ($(wildcard *.csproj),)
            include $(WORKSPACE_FOLDER)/makefw/makefiles/makesrc_dotnet.mk
        else
            include $(WORKSPACE_FOLDER)/makefw/makefiles/makesrc_c_cpp.mk
        endif
    else
        $(error Cannot auto-select makefile template. Current path must contain /libsrc/ or /src/: $(CURDIR))
    endif

## 4.1 判定ルール

ディレクトリパス | .csproj | 選択されるテンプレート
--- | --- | ---
`/libsrc/` を含む | 無し | `makelibsrc_c_cpp.mk`
`/libsrc/` を含む | 有り | `makelibsrc_dotnet.mk`
`/src/` を含む | 無し | `makesrc_c_cpp.mk`
`/src/` を含む | 有り | `makesrc_dotnet.mk`
上記以外 | - | エラー

# 5 サブディレクトリの OS フィルタリング

サブディレクトリ名に基づく OS フィルタリングの詳細は、サブディレクトリの OS フィルタリング を参照してください。

# 6 使用例

## 6.1 C/C++ ライブラリ

    ディレクトリ: prod/calc/libsrc/calcbase/
    ファイル構成:
      - makefile (__template.mk の内容)
      - add.c, subtract.c, multiply.c, divide.c
      - makepart.mk (固有設定、必要な場合のみ)

    判定結果:
      パス: /libsrc/ を含む → ライブラリ
      .csproj: 無し → C/C++
      → makelibsrc_c_cpp.mk を使用

## 6.2 .NET ライブラリ

    ディレクトリ: prod/calc.net/libsrc/CalcLib/
    ファイル構成:
      - makefile (__template.mk の内容)
      - CalcLib.csproj
      - Calculator.cs
      - makepart.mk (固有設定、必要な場合のみ)

    判定結果:
      パス: /libsrc/ を含む → ライブラリ
      .csproj: 有り → .NET
      → makelibsrc_dotnet.mk を使用

## 6.3 C/C++ 実行体

    ディレクトリ: prod/calc/src/add/
    ファイル構成:
      - makefile (__template.mk の内容)
      - add.c
      - makepart.mk (固有設定、必要な場合のみ)

    判定結果:
      パス: /src/ を含む → 実行体
      .csproj: 無し → C/C++
      → makesrc_c_cpp.mk を使用

## 6.4 .NET 実行体

    ディレクトリ: prod/calc.net/src/CalcApp/
    ファイル構成:
      - makefile (__template.mk の内容)
      - CalcApp.csproj
      - Program.cs
      - makepart.mk (固有設定、必要な場合のみ)

    判定結果:
      パス: /src/ を含む → 実行体
      .csproj: 有り → .NET
      → makesrc_dotnet.mk を使用

# 7 プロジェクト固有設定 (makepart.mk)

各プロジェクト固有の設定は、`makepart.mk` ファイルに記述します。

## 7.1 makepart.mk の配置場所

makepart.mk は、以下の階層に配置できます：

1. カレントディレクトリ - 最も優先される
2. 親ディレクトリ（複数） - ワークスペースルートまで遡って検索
3. 複数の階層 - 親階層から順次読み込まれる

## 7.2 makepart.mk の読み込みタイミング

prepare.mk 内で、親階層からワークスペースルートに向かって順次読み込まれます。

    MAKEPART_MK := $(shell \
        dir=`pwd`; \
        while [ "$$dir" != "/" ]; do \
            if [ -f "$$dir/makepart.mk" ]; then \
                echo "$$dir/makepart.mk"; \
            fi; \
            if [ -f "$$dir/.workspaceRoot" ]; then \
                break; \
            fi; \
            dir=$${dir%/*}; \
            if [ -z "$$dir" ]; then dir=/; fi; \
        done \
    )

    _reverse = $(if $(1),$(call _reverse,$(wordlist 2,$(words $(1)),$(1))) $(firstword $(1)))
    MAKEPART_MK := $(strip $(call _reverse,$(MAKEPART_MK)))
    $(foreach makepart, $(MAKEPART_MK), $(eval include $(makepart)))

## 7.3 makepart.mk の記述例

例1: 動的ライブラリの指定

    LIBS += calcbase

    ifeq ($(OS),Windows_NT)
        # Windows: DLL エクスポート定義
        CFLAGS   += /DCALC_EXPORTS
        CXXFLAGS += /DCALC_EXPORTS
    endif

    LIB_TYPE = shared

例2: テスト共通設定

    LINK_TEST = 1

    ifeq ($(OS),Windows_NT)
        # Windows: CALC_STATIC マクロを定義
        CFLAGS   += /DCALC_STATIC
        CXXFLAGS += /DCALC_STATIC
    endif

    LIBSDIR += \
        $(WORKSPACE_FOLDER)/testfw/lib \
        $(WORKSPACE_FOLDER)/test/lib

# 8 導入方法

既存プロジェクトに makefile テンプレート自動選択機構を導入する手順を説明します。

## 8.1 1. 最終階層 makefile の更新

すべての最終階層 makefile を `__template.mk` の内容で置き換えます。

    cp makefw/makefiles/__template.mk prod/calc/libsrc/calcbase/makefile

## 8.2 2. 固有設定の移行

既存の makefile に固有設定（LIBS, CFLAGS など）がある場合、`makepart.mk` に移行します。

変更前 (makefile):

    find-up = ...
    WORKSPACE_FOLDER := $(strip $(call find-up,$(CURDIR),.workspaceRoot))

    include $(WORKSPACE_FOLDER)/makefw/makefiles/prepare.mk

    LIBS += calcbase
    LIB_TYPE = shared

    include $(WORKSPACE_FOLDER)/makefw/makefiles/makelibsrc.mk

変更後:

**makefile (__template.mk の内容):**

    find-up = ...
    WORKSPACE_FOLDER := $(strip $(call find-up,$(CURDIR),.workspaceRoot))

    include $(WORKSPACE_FOLDER)/makefw/makefiles/prepare.mk

    ##### makepart.mk の内容は、このタイミングで処理される #####

    include $(WORKSPACE_FOLDER)/makefw/makefiles/makemain.mk

makepart.mk (固有設定):

    LIBS += calcbase

    LIB_TYPE = shared

## 8.3 3. 動作確認

    cd prod/calc/libsrc/calcbase
    make clean
    make

# 9 トラブルシューティング

## 9.1 エラー: “Cannot auto-select makefile template”

原因: ディレクトリパスに `/libsrc/` も `/src/` も含まれていない

解決策:
1. ディレクトリ構造を見直し、`libsrc` または `src` の下に配置する
2. または、makefile で直接テンプレートを指定する（自動選択を使わない）

## 9.2 ビルドが失敗する

確認事項:
1. `makepart.mk` の内容が正しいか
2. `WORKSPACE_FOLDER` が正しく設定されているか（`.workspaceRoot` ファイルの配置）
3. 依存ライブラリが正しくビルドされているか

デバッグ方法:

    make debug  # 変数の内容を表示

# 10 まとめ

makefile テンプレート自動選択機構により、以下が実現されます：

- 統一性: すべての makefile が同一内容
- 自動化: ディレクトリパスと言語の自動判定
- 保守性: 固有設定は makepart.mk で管理
- 拡張性: 新しい言語やビルドタイプの追加が容易

この機構により、プロジェクト全体のビルドシステムが統一され、メンテナンスが大幅に容易になります。