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 処理フロー

plantuml

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 で管理
  • 拡張性: 新しい言語やビルドタイプの追加が容易

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