[ C++で開発 ]

MPCの使い方
The Makefile, Project, and Workspace Creator


目次

MPCとは

 MPC:The Makefile, Project, and Workspace Creatorの略。マルチプラットフォーム対応のプロジェクトにおいて、複数のビルドツールに対応するために、各ビルドツールに対応した設定ファイルを自動生成するツールです。MPC用のプロジェクト設定を記述すると、GNU Make用Makefile、Borland Make用Makefile、nmake用Makefile、Microsoft Visual C++6.0〜8.0のプロジェクトファイル、Microsoft embedded Visual C++3.0/4.0用プロジェクトファイル、GNU Automake用ファイル、などの各種ビルドツール用設定ファイルを生成することができます。

 MPC自体はPerl言語で記述されており、実行にはPerlが動作することが必要です。UNIX系のOSならば大抵Perlが利用可能となっています。Windowsの場合は、Perl環境としてCygwinもしくはActive Perlをインストールするのが一般的でしょう。

 このMPCツールは、ACEと呼ばれる並列処理・プロセス間通信をカプセル化しオブジェクト指向ネットワークプログラミング機能を提供するオープンソース・フレームワーク製品のビルド用に使用されています。

MPCの入手と展開、設定

MPCツールは、ACEおよびTAO(The ACE ORB)の商用サポートを行っている米OCI社が開発・無償提供しています。

上記ページの左側メニュー[Download]を辿ると、MPCのアーカイブをダウンロードできます。

※ZIP形式のアーカイブでも入手可能です。

入手したMPCアーカイブを展開します。MPCというディレクトリの下に展開されます。環境変数PATHにこのMPCディレクトリを追加します。

以下の2つのコマンドが使用できるようになります。

  1. mpc.pl
  2. mwc.pl

1.は、基本的には一つの実行ファイルまたはライブラリファイルを作成するための「プロジェクト」を生成するためのツールです。
2.は、ワークスペースを生成するツールです。ワークスペースは、複数の「プロジェクト」または「ワークスペース」を束ねる設定を記述します。

MPCを使ったビルド

単一ディレクトリで一つの実行ファイルを生成する

ex1ディレクトリに2つのソースファイル、1つのヘッダファイルを作成し、これらから1つの実行ファイルをビルドする場合の設定です。

src/
  +-- Time.h
  +-- Time.cpp
  +-- main.cpp

MPC設定ファイルの記述

MPCのプロジェクト設定ファイルを記述します。

timemain.mpc
project(timemain) {
  exename = time_main
}

projectで全体を囲みます。プロジェクト名を()内に記述します。プロジェクト名は省略可能で、その場合は()も省略します。省略時はMPCファイル名から拡張子.mpcを除いた名前がプロジェクト名となります。

ビルドする実行ファイル名を、exename = で指定します。この例ではtime_mainが実行ファイル名となります。(Windowsの場合の拡張子.exeは省略可)

カレント・ディレクトリにあるソースファイル、ヘッダーファイルがデフォルトでプロジェクトに取り込まれます。

ビルドファイルの生成

例としてVC++ 7.1 (Visual Studio 2003)のビルドファイルを生成します。

ex1> mpc.pl -type vc71 timemain.mpc
Generating vc71 output using time.mpc
Generation Time: 0s
ex1> 

以下のVisual C++ 7.1用プロジェクトファイルが生成されます。

同様に、以下の指定で各種ビルドファイルが生成されます。

コマンドオプション 生成されるファイル 対象ビルドツール
mpc.pl -type nmake timemain.mpc
Makefile.timemain.mak
nmake
mpc.pl -type make timemain.mpc
Makefile.timemain
make
mpc.pl -type automake timemain.mpc
Makefile.timemain.am
automake
mpc.pl -type bmake timemain.mpc
Makefile.timemain.bmak
Borland make

※-typeで指定可能なオプションは現時点で、automake ,bds,bmake, cbx, em3, ghs, html, make, nmake, sle, vc6, vc7, vc71, vc8

ソースファイル・ヘッダーファイルを指定する

上記では、timemain.mpcファイルと同じディレクトリにあるソースファイル、ヘッダーファイルがプロジェクトに取り込まれました。これを、ソースファイル、ヘッダーファイルを指定したい場合は、以下のように記述します。

timemain.mpc
project(timemain) {
  exename = time_main

  Source_Files {
    Time.cpp
    main.cpp
  }

  Header_Files {
    Time.h
  }
}

Source_Files { }の中に、ビルド対象のソースファイルを記述します。
Header_Files { }の中に、ビルド対象のヘッダーファイルを記述します。

コンパイルオプションの指定

コンパイルオプションもプロジェクトファイルに記述して生成することができます。注意点は、コンパイラやOSに固有な設定と共通な設定があるので、これらを使い分けることです。

timemain.mpc
project(timemain) {
  exename = time_main
  includes += /lib/boost_1_34_1
  macros += _CRT_SECURE_NO_WARNINGS

  libpaths += /lib/boost_1_34_1/lib
  specific(vc9) {
    lit_libs += boost_date_time-vc90-mt
  } else {
    lit_libs += boost_date_time
  }

  Source_Files {
    Time.cpp
    main.cpp
  }

  Header_Files {
    Time.h
  }
}
includes) コンパイラのインクルードパスを定義
macros) コンパイラのデファイン定義

libpaths) リンカのライブラリパスを定義

specific(vc)) VC++9のときの
lit_libs) リンク・ライブラリ

実行ファイルのディレクトリを指定

ソースファイルのあるディレクトリとは別に実行ファイルを生成するディレクトリを指定することができます。exeoutに出力先ディレクトリを記述します。

timemain.mpc
project(timemain) {
  exename = time_main
  exeout = ../bin
    :
}

単一ディレクトリで1つのライブラリファイルを生成する

ex1ディレクトリにあるソースファイル、ヘッダファイルを作成し、これらから1つの共有ライブラリファイルをビルドする場合の設定です。

timelib.mpc
project(timelib) {
  sharedname = time

  Source_Files {
    Time.cpp
  }

  Header_Files {
    Time.h
  }

}

ビルドする共有ライブラリファイル名を、sharedname = で指定します。拡張子やUNIX系で使用するファイル名先頭の"lib"は記述しません。この例では、VC++プロジェクトファイルではtime.dll(またはtimed.dll)が共有ライブラリファイル名となります。makeファイルでは、libtime.soが共有ライブラリファイル名となります。

ライブラリファイルのディレクトリを指定

ソースファイルのあるディレクトリとは別にライブラリファイルを生成するディレクトリを指定することができます。liboutに出力先ディレクトリを記述します。

timelib.mpc
project(timelib) {
  sharedname = time
  libout = ../lib
    :
}

mpcファイルを記述しないときのデフォルト動作

 ちょっとしたプログラムを作る場合、mpcファイルの記述すら面倒な場合があります。そのときは、mpcファイルを記述しなくても、MPCのデフォルトの動作で対象のビルドツールのプロジェクトファイルを生成させることができます。

 main関数を定義したソースファイルが含まれている場合、そのディレクトリにあるソースファイルを全部コンパイル・リンクして一つの実行ファイルを生成するプロジェクトを生成します。プロジェクト名は、そのディレクトリ名に基づき、実行ファイル名は、main関数を定義したソースファイル名に基づきます。

 main関数を定義したソースファイルが含まれていない場合、そのディレクトリにあるソースファイルを全部コンパイル・リンクして一つの共有ライブラリファイルを生成するプロジェクトを生成します。

 なお、インクルードパス、ライブラリパス、リンクするライブラリ名などは、mpc.plのコマンドラインから-value_projectオプションで指定できますが、ここまでするなら素直にmpcファイルを記述するべきです。

追加のインクルードパス、ライブラリパス、リンクするライブラリを指定する

各種ライブラリを使ったプロジェクトの場合、追加のインクルードパス、ライブラリパス、リンクするライブラリ、ビルド前や後に実行するコマンドなどを指定する必要があります。

Boostライブラリを使用する場合

MPCは標準でBoostライブラリを使うための設定を保持しています。ただしデフォルトではBoostの設定が無効になっているので、これを有効にする必要があります。有効にするにはいくつかの方法がありますが、ここではその中から2つ紹介します。

  1. MPCをインストールしたディレクトリ下のconfig/global.featuresの定義を変更する
  2. MPCコマンドラインオプションで都度指定する

1.は、global.featuresファイルの中に「boost = 0」の記述があるので、これを「boost = 1」に修正します。

2.は、コマンドラインで-features boost=1 を指定します。
 または、「boost = 1」を記述したテキストファイル(例:myproj.features)を作成し、コマンドラインで-feature_file myproj.features を指定します。

Boostを使用するプロジェクト定義で、boostの基底プロジェクトを継承するように記述します。

timelib.mpc
project(timelib) : boost_base {
  sharedname = time
}

boostの基底プロジェクトは、リンクするライブラリ種類に応じて複数用意されているので、適切なものを選択します。複数ライブラリを使用するときは、それぞれ継承するプロジェクトに指定します。

基底プロジェクト名 基底プロジェクト名 基底プロジェクト名
boost_base
boost_program_options
boost_test_exec_monitor
boost_date_time
boost_python
boost_thread
boost_filesystem
boost_regex
boost_unit_test_framework
boost_iostreams
boost_serialization
boost_wave
boost_prg_exec_monitor
boost_signals

これらboostの基底プロジェクトを使用すると、インクルードパス、ライブラリパス、リンクするライブラリ名に以下の環境変数を使用するプロジェクトが生成されます。

プロジェクトを実行するときは、これらの環境変数を定義しておきます。

CentOS 5で、boostをyum経由でインストール(またはrpmパッケージをインストール)した場合

rpmパッケージでインストールしたboostは、/usr/includeの下にboost/xxx.hppが置かれ、/usr/libの下にlibboost-xxxが置かれます。また、ライブラリ名はlibboost_regex.soのようにバージョン番号はファイル名には付きません。したがって、上記環境変数を設定していなくても、コンパイル・リンクが通ってしまいます。

複数のディレクトリでそれぞれ実行ファイルを生成する

クライアント・サーバのプログラムを作成するときなど、クライアント用実行ファイル、サーバ用実行ファイルと複数の実行ファイルを生成する場合の例を見てみます。

プロジェクトを束ねるディレクトリをcsappとして、そのディレクトリ配下にclientおよびserverディレクトリを作成します。

csapp
  +--- client
  |       +--- src
  |              +--- client.cpp
  +--- server
          +--- src
                 +--- server.cpp

clientとserverそれぞれのディレクトリ下にプロジェクトファイルを記述します。

client.mpc
project(client) {
  exename = client

  Source_Files {
    client.cpp
  }
}
server.mpc
project(server) {
  exename = server

  Source_Files {
    server.cpp
  }
}

csapp直下にワークスペースファイルを記述します。

csapp.mwc
workspace {
}

UNIXのbash上でGNU Makefileを生成するコマンド実行例を以下に示します。

csapp$ mwc.pl -type make -recurse csapp.mwc
Generating 'make' output using default input
Generation Time: 0s
csapp$

複数のディレクトリでそれぞれライブラリを生成する、インクルードファイルをソースとは別に置く

複数のライブラリファイルからなるクラスライブラリを構築するディレクトリ構成の場合の例を見てみます。

この例でのディレクトリ構成想定事項は以下のとおりです。

以下にABCライブラリのディレクトリ構成とMPCのワークスペースファイル・プロジェクトファイルを記述します。

abclib
  |
  +--- include
  |       +--- abc
  |              +--- alfa
  |              +--- bravo
  |              +--- charlie
  +--- src
  |       +--- abc
  |              +--- alfa
  |              |      +--- alfa.mpc
  |              +--- bravo
  |              |      +--- bravo.mpc
  |              +--- charlie
  |                     +--- charlie.mpc
  +--- abclib.mwc
  |
  +--- lib
  |
  +--- makeinclude
           +--- abclib.mpb

makeincludeには、各MPCファイルで共通する設定を記述した共通ファイルを置きます。

alfaライブラリのMPCファイル

alfa.mpc
project(alfa) : abclib {
  sharedname = alfa

  Source_Files {
    Alfa.cpp
  }

  Header_Files {
    Alfa.h
  }
}

このalfaライブラリ生成用プロジェクトファイルは、abclibという基底プロジェクトの設定を継承します。

動的共有ライブラリ・ファイルとしてalfaという基幹名で生成します。UNIX系ならlibalfa.soとなります。

このプロジェクトを構成するソースファイルは、Alfa.cppで、ヘッダーファイルはAlfa.hです。
※ヘッダーファイルAlfa.hは別ディレクトリにあるので、このファイル名のみの記述でよいのかどうかは要調査。

ライブラリ共通のMPCベースファイル

abclib.mpb
project {
  includes += $(ABCLIB_ROOT)/include
  libout = $(ABCLIB_ROOT)/lib

  specific(make) {
    compile_flags += -Wall
  }
}

公開ヘッダーファイルはソースとは別ディレクトリに置くため、コンパイル時にはインクルードパスの指定が必要です。このインクルードパスはプロジェクトで共通なので、各プロジェクトファイルにコピー&ペーストするよりは共通ファイルに一元化すべきです。

同様にライブラリパスも共通です。

また、コンパイルオプションで共通するものもここに記載します。

ワークスペースファイル

abclib.mwc
workspace {
}

Makefileの生成

UNIXのbash上でGNU Makefileを生成するコマンド実行例を以下に示します。

abclib$ mwc.pl -type make -include ./makeinclude abclib.mwc
Generating 'make' output using abclib.mwc
Generation Time: 0s
abclib$

-typeオプションでmake、すなわちGNUmake用Makefileを生成します。

各mpcファイルまたは共通のmpbファイルに、プロジェクトトップディレクトリを表すABCLIB_ROOT変数を使用してincludeディレクトリ等を指定しています。-relativeオプションを指定しなければ、この変数はそのまま生成されるMakefile等のプロジェクトファイルに変数のまま反映されます。そのため、ビルド実行時にこの環境変数をセットする必要があります。

Makefile.alfa(抜粋)
CPPFLAGS = $(PICFLAGS) $(GENFLAGS) -Wall -D_REENTRANT -I"$(ABCLIB_ROOT)/include"

一方、-relativeオプションで変数の内容を指定しておくと、この変数はMakefile等のプロジェクトファイルでは相対ディレクトリに展開されます。

abclib$ mwc.pl -type make -include ./makeinclude -relative ABCLIB_ROOT=. abclib.mwc
Generating 'make' output using abclib.mwc
Generation Time: 0s
abclib$
Makefile.alfa(抜粋)
CPPFLAGS = $(PICFLAGS) $(GENFLAGS) -Wall -D_REENTRANT -I"../../../include"

カスタムコマンドの定義

CORBAのIDLコンパイラや、QtのMOCコンパイラなど、特定のツール固有のコマンドを実行するカスタムコマンドを定義します。

Define_Custom文を使って、MPCのプロジェクトファイル中に定義します。

ACE/TAOの場合、MPCが標準で組み込まれているので、ACE/TAOのMPCを使うとユーザ側でカスタムコマンドを定義せずに済みます。しかし、MPCを別にインストールしていたり、ACE/TAOのパッケージ版を使用してMPCが含まれていなかったりした場合、自前でIDLコンパイルのカスタムコマンドを定義する方法を知っていると対処が容易です。

IDLコンパイラ

TAO IDLコンパイラのカスタムコマンド定義

    Define_Custom(IDL) {
        automatic = 1
        command = tao_idl
        inputext = .idl

        source_pre_extension = C, S
        header_pre_extension = C, S
        inline_pre_extension = C, S
        source_outputext = .cpp, .cxx, .cc, .C
        header_outputext = .h, .hpp, .hxx, .hh
        inline_outputext = .inl
        keyword idlflags = commandflags
    }
IDL_Filesのカスタムコマンド定義。
automatic=1指定で、IDL_Filesで指定したファイルからの生成物は、自動的にSource_Files, Header_Files, Template_Filesなどに追加する。
カスタムコマンドはtao_idl。
対象入力ファイルの拡張子は.idl。

生成ソースファイルの拡張子直前にはCおよびSが付加
生成ヘッダファイルの拡張子直前にはCおよびSが付加
生成インラインファイルの拡張子直前にはCおよびSが付加
生成ソースファルの拡張子
生成ヘッダファイルの拡張子
生成インラインファイルの拡張子
IDLカスタムコマンドのコマンドオプションは、idlflagsで指定可能とする。

tao_idlの生成物に合わせて、source_pre_extension他を指定しています。この名前のルールでMakefileが出力されます。

注記)実際のACE/TAOに含まれるカスタム定義はもっと複雑になっています。

応用編

詳解編

workspaceの記述方法

問題解決

MPCを使うにあたって出くわした問題とその解決についてのメモです。

Windows OS / Cygwin

Cygwin g++でmake時に-ldlが見つからないリンクエラー

Cygwin環境では、ライブラリlibdlがありません。Cygwinでは、libdlが提供する関数はlibcygwinに含まれているので、/usr/lib/libcygwin.aにシンボリックリンクを作成する方法で回避します。

$ cd /usr/lib
$ ln -s libcygwin.a libdl.a
$ 

Windows OS / VC++

VC++でデバッグ用/リリース用リンクファイル名を切り替えたい

Linux / GCC

デバッグビルド・リリースビルドの切り替えをしたい

VC++では、プロジェクト設定に「デバッグビルド」、「リリースビルド」の構成が定義され、ビルド時にどちらでビルドするかを選択することができます。

一方、make(Makefile)プロジェクトでは、デフォルトでは最適化オプション"-O"が指定され、デバッグオプション"-g"は指定されません。

生成されるMakefile.xxx の中で以下の変数でオプションが定義されます。

Makefile.xxx
LIBSUFFIX     =
GENFLAGS      = -O

この設定は、MPCのmake用テンプレート設定ファイルに定義されているものです。

makedll.mpt
...
configurations = Release
...
Debug {
  lib_modifier = d
  genflags = -g
}
Release {
  optimize = 1
  genflags = -O
}

Makefileを生成する元ネタ定義であるconfigurations属性がReleaseに設定されているので、生成されるMakefileはReleaseで定義されているgenflagsの値が適用されます。

MPC実行時に、デバッグビルド用Makefileかリリースビルド用Makefileどちらを生成するかを指定する

mwc.plコマンドを実行するときに、-value_templateオプションを指定して、configurations属性を上書きする

$ mwc.pl -type make -value_template configurations=Debug ...
$ 

生成されるMakefile.xxxは以下になります(抜粋)。

Makefile.xxx
LIBSUFFIX     = d
GENFLAGS      = -g
MPC実行時に、デバッグビルド/リリースビルド両用Makefileを生成し、make実行時にどちらでビルドするかを指定する

デバッグビルドとリリースビルドと頻繁に使い分ける場合、都度MPCでMakefileを生成し直すのは手間です。そこで、Makefileにはデバッグビルド、リリースビルド双方の設定を生成して、makeを実行するときにデバッグビルドかリリースビルドかを指定できるようにします。

$ mwc.pl -type make -value_template "configurations=Debug Release" ...
$ 

生成されるMakefile.xxxは以下になります(抜粋)。makeマクロ変数CFGの値に応じて、デバッグビルドかリリースビルドかを切り替えられるようになっています。

Makefile.xxx
CFG = Debug
ifeq ($(CFG), Debug)
...
LIBSUFFIX     = d
GENFLAGS      = -g
...
endif
ifeq ($(CFG), Release)
...
LIBSUFFIX     = 
GENFLAGS      = -O
...
endif
$ make 
// Debugビルドが行われる
$ make CFG=Debug
// Debugビルドが行われる
$ make CFG=Release
// リリースビルドが行われる

上記では、デフォルト(CFG変数を指定しない場合)ではデバッグビルドですが、デフォルトでリリースビルドにしたい場合は、MPCの-value_templateオプションのconfigurations=の後の並びを変えて、デフォルトにしたい構成を先に書きます。

$ mwc.pl -type make -value_template "configurations=Release Debug" ...
$ 
Makefile.xxx
CFG = Release
ifeq ($(CFG), Release)
...
endif
ifeq ($(CFG), Debug)
...
endif
デバッグビルド/リリースビルドで生成するライブラリファイルは、ファイル名は同一で出力先ディレクトリを分けたい

MPCが用意するGNU make用のMakefile設定は、デバッグビルドしたライブラリは、ファイル名に'd'が付きます。(例:libfoo.soがリリースビルドであれば、そのデバッグビルドはlibfood.soとなる)
これを、ファイル名は変えたくない場合、出力先ディレクトリを変えることで対応できる方法を考えてみます。

まず、makedll.mpt をカスタマイズします。

make2dll.mpt
...
configurations = Release Debug
...
Debug {
  output_dir_ext = _debug
  genflags = -g
}
Release {
  output_dir_ext = _opt
  optimize = 1
  genflags = -O
}

次に、make.mpdをカスタマイズします。

make2l.mpd
...
SHTARGETDIR   = <%if(dllout)%><%dllout%><%output_dir_ext%><%else%><%libout%><%output_dir_ext%>
<%endif%><%slash%><%targetoutdir%>

この2つのカスタマイズしたファイルを読み込ませ、mwcを実行します。

$ mwc.pl -type make -template make2 -ti dll:make2dll -value_template \
 "configurations=Release Debug" ...

リンクオプションを指定したい

リンクオプションは、makeの場合、生成されるMakefileの中でLDFLAGS=で設定されます。通常はリンクするライブラリのパスとライブラリ名が反映されますが、他にもリンク時に指定したいオプションがあった場合、ここに反映するため、linkflagsを指定します。

MPCファイルの記述
project {
  specific(make) {
    linkflags += -pg
  }
  ...
}
linkflagsが反映される仕組み

Makefileを生成するための雛形となるmake.mpdの中に、linkflagsが定義されていれば指定するようになっています。

MPC/templates/make.mpd抜粋
LDFLAGS =<%if(libpaths)%>...中略...<%if(linkflags)%> <%linkflags%><%endif%>...後略

makeの生成に関する設定が書かれたmakedll.mptには、コンパイラ種類によってデフォルトのlinkflagsが定義されています。

MPC/templates/makedll.mpt抜粋
...
SunCC {
    linkflags = -library=Cstd -library=Crun
    ...
}
acc {
    linkflags = -Wl,+s
    ...
}

LinuxでのGCCの場合、linkflagsは設定されていません。

Emacsのflymake対応ターゲットをMakefileに追加したい

Emacsでflymakeモードを有効にしているとき、Emacsはソースファイルを開いた場所でmakeをcheck-syntaxターゲットで実行し、エラーチェックを行います。そこで、MPCで生成するMakefileにcheck-syntaxターゲットを追加する方法を探しました。

上述の変更対応で実現できました。

環境変数CUSTOM_TARGETSの定義
$ export CUSTOM_TARGETS=check-syntax
$ 
make.mpdの修正
$(MPC_ROOT)/templates/make.mpd
--- make.mpd.orig       2008-11-16 22:19:39.000000000 +0900
+++ make.mpd    2009-02-24 00:14:59.000000000 +0900
@@ -301,6 +301,9 @@
        -$(RM) <%targetoutdir%><%obj_dir%>
 <%endif%>
 
+check-syntax:
+       $(COMPILE.cc) $(EXPORTFLAGS) -Wall -Wextra -pedantic -fsyntax-only ${CHK_SOURCES}
+
 <%if(prebuild)%>
 __prebuild__:
        @<%eval(prebuild)%>

Makefile.xxx はテンプレートファイルmake.mpdが雛形を定義しているので、これにターゲットを追加します。

(オプション)環境変数ではなく、恒久的にcheck-syntaxを有効にするため、MakeWorkspaceCreator.pmを修正する

環境変数CUSTOM_TARGETS指定は忘れてしまってflymakeが無効になるのも面倒なので、MPCの提供ファイル自体を修正してしまいます。

$(MPC_ROOT)/modules/MakeWorkspaceCreator.pm
--- MakeWorkspaceCreator.pm.orig        2008-11-16 22:19:39.000000000 +0900
+++ MakeWorkspaceCreator.pm     2009-02-24 00:04:56.000000000 +0900
@@ -23,7 +23,7 @@
 # Data Section
 # ************************************************************
 
-my($targets) = 'clean depend generated realclean $(CUSTOM_TARGETS)';
+my($targets) = 'clean depend generated realclean check-syntax $(CUSTOM_TARGETS)';

Makefileはテンプレートファイルはなく、PerlスクリプトのMakeWorkspaceCreator.pmが直接生成しているので、Perlスクリプトを修正します。

共通

コマンドラインオプション指定を省略したい

ワークスペースファイル(.mwc)にコマンドラインオプションを記述する

この記述は、MPCのFAQに記載されているものですが、MPC 3.6.0で確認したところ、以下を記述しても有効になりません。

abclib.mwc
workspace {
    cmdline += -value_template "configurations=Release Debug" -include $(HOME)/MPC
}
MPC設定ファイルに記述する

MPCは設定ファイルを読み込みます。デフォルトでは、MPCのディレクトリにある設定ファイルを読み込みますが、プロジェクト固有の設定ファイルを読み込むように設定しておくことで、プロジェクト固有の指定を行います。

(1) $MPC_ROOT/config/base.cfgファイルを新規に作成し、以下内容を記述する

$PROJECT_ROOT=$PROJECT_ROOT/MPC/config

(2) プロジェクトのディレクトリを環境変数PROJECT_ROOTに設定する

(3) $PROJECT_ROOT/MPC/config ディレクトリにMPC.cfgファイルを作成する

ここで、環境変数PROJECT_ROOTは名前は別に何でも構いません。

MPC.cfgの書き方

default_type = make     // コマンドラインの -type make を指定

指定できる設定は、以下

command_line
default_type
dynamic_types
includes
logging
main_functions
verbose_ordering

詳しくは、MPCのドキュメント参照

ソースファイル毎にコンパイルオプションを変えたい

Source_Files {} を複数定義して、Source_Files内にbuildflagsで固有にコンパイルオプションを指定します。

alfa.mpc
project(alfa) : abclib {
  sharedname = alfa

  Source_Files {
    buildflags += -finstrument-functions
    AlfaX.cpp
  }

  Source_Files {
    AlfaY.cpp
    AlfaZ.cpp
  }
}

複数ライブラリをビルドする際、ビルド順番で依存するライブラリが後のためリンクエラーとなる

複数のプロジェクトを収容するワークスペースを構築する際、プロジェクトのビルド順番はMPC実装依存(アルファベット順にみえる)です。そこで、ライブラリを構築するプロジェクトファイル(*.mpc)に、依存するプロジェクト名をafter += で記述します。

bravo.mpc
project(bravo) : abclib {
  sharedname = bravo
  libs += alfa
  after += alfa

  Source_Files {
    BravoFoo.cpp
    BravoBar.cpp
  }
}

デバッグビルドをすると、ライブラリ名が変わるため、リンクエラーになってしまう

ライブラリ alfa をリンクするように指定すると、デバッグビルドを行うと alfad と末尾に'd'付くライブラリをリンクしようとしてファイルが見つからずリンクエラーとなります。また、デバッグビルドの場合、自分のライブラリ名もsharedname=bravoと指定していてもデバッグビルドでは、bravodと末尾に'd'が付いた名前になっています。

これは、同じディレクトリに異なるビルドオプションで生成したライブラリを共存させるため、および同じビルドオプションで生成したライブラリ同士をリンクするための機構です。特にWindows VC++では、デバッグとリリースで互換性のないライブラリができるので(newとdeleteが置き換えられるのは有名な話)、この機構が必要になっています。

bravo.mpc
project(bravo) : abclib {
  sharedname = bravo
  libs += alfa
  ...
}
デバッグビルド、リリースビルドに関わらず、リンクするライブラリファイル名は同じにしたい

外部のライブラリは、デバッグビルド版が提供されていないことがよくあります。その場合は、リンク指定をlibsではなく、lit_libsで指定します。

bravo.mpc
project(bravo) : abclib {
  sharedname = bravo
  lit_libs += alfa
  ...
}
デバッグビルド、リリースビルドに関わらず、生成するライブラリファイル名は同じにしたい

mwc.pl/mpc.plのコマンドラインオプション-value_templateで、lib_modifier属性をブランクに設定します。

$ mwc.pl -type make -value_template lib_modifier= ...
$ 

デバッグビルド指定とともに使うときは、

$ mwc.pl -type make -value_template configurations=Debug -value_template lib_modifier= ...
$ 

のように複数回-value_templateオプションを指定します。

除外ディレクトリの指定

特定のディレクトリを除外したい場合は、

コマンドラインオプションで指定する

mwc.plの-excludeオプションで、除外したいディレクトリまたはmpcファイル名を指定します。複数除外するときはカンマで区切って列挙します。

abclib.mwc
workspace {
}