このエントリーはオープンCAE Advent Calendar 2020 の1日目です。
はじめに
OpenFOAMのアプリケーションおよびライブラリはwmake
というコマンドでコンパイルされます。このコマンドの中で何が起きているのか、詳細に把握していなかったので調べて整理してみました。
概要
wmake
では以下の動作を行っているみたいです。
- **
wmake
**を実行すると・・・ - **
make -f wmake/makefiles/general
**が実行される-
wmake/makefiles/general
をMakefile
として読み込む- コンパイラオプションなどを指定
- いくつかの情報を
Make/files
とMake/options
で補完
-
Make/files
を読み込む- コンパイルするファイルを指定
- 実行ファイル名を指定
-
Make/options
を読み込む- includeファイルのあるディレクトリを指定
- 共有ライブラリ(
lib*.so
)を指定
-
- 複数回の
g++
が実行される(Makefile
の内容による)-
g++
でコンパイル (× オブジェクト数)- オブジェクト(
*.o
)を生成
- オブジェクト(
-
g++
でリンク- 生成したオブジェクト(
*.o
)と指定した共有ライブラリ(lib*.so
)をリンク - 実行ファイルを生成
- 生成したオブジェクト(
-
実行環境
- OS : Ubuntu20.04 LTS / WSL2 Windows10
- OpenFOAM : v2006
- GCC : Ubuntu 9.3.0-17ubuntu1~20.04
OpenFOAMのファイル構造
本題に進む前に軽くOpenFOAMの特徴的なファイル構造について説明します。
OpenFOAMは多くのクラスと実行ファイルを持つツールボックスです。
『実行ファイル同士で共通した機能が多い』『実行ファイルや継承クラスを自作することをユーザーが前提としている』などの特徴から、クラスと実行ファイルをそれぞれ別でコンパイルする仕組みになっています。実行ファイルの作成の際に必要なクラスをリンクすることになります。
OpenFOAM v6 User Guide: 3.2 Compiling applications & libraries
cfd.direct/openfoam/user-guide/v6-compiling-applications/
A class is defined through a set of instructions such as object construction, data storage and class member functions. The file that defines these functions — the class definition — takes a .C extension, e.g. a class nc would be written in the file nc.C. This file can be compiled independently of other code into a binary executable library file known as a shared object library with the .so file extension, i.e. nc.so. When compiling a piece of code, say newApp.C, that uses the nc class, nc.C need not be recompiled, rather newApp.C calls the nc.so library at runtime. This is known as dynamic linking.
Figure 3.1: Header files, source files, compilation and linking
このように『どのクラスをリンクするか』や『どのファイルをインクルードするか』などの複雑な情報を実行ファイルごとに記述しコンパイルするために、OpenFOAMではwmake
というコマンドが用意されています。
wmakeを実行してみる
取り合えずwmake
を実行してみます。今回は例としてpimpleFoamをコピーしてcpPimpleFoam
というソルバーを作成する場合を考えます。
$ cp -r $FOAM_SOLVERS/incompressible/pimpleFoam ./cpPimpleFoam
$ cd ./cpPimpleFoam
$ sed -i -e "s/APPBIN)\/pimpleFoam/USER\_APPBIN)\/cpPimpleFoam/g" Make/files
$ # 下2行はWSLの場合に必要 (windowsはファイル名の大文字小文字を区別できないのでCorrectPhi.HをcorrectPhi.Hと間違えてしまう)
$ cp $FOAM_SRC/finiteVolume/cfdTools/general/CorrectPhi/CorrectPhi.H cpCorrectPhi.H
$ sed -i -e "s/CorrectPhi.H/cpCorrectPhi.H/" pimpleFoam.C
$ # pimpleFoamと同じ機能のものをコンパイルする
$ wmake > log.wmake
出力されたファイルの内容は以下の通りです。
Making dependency list for source file pimpleFoam.C
g++ -std=c++11 -m64 -pthread \
-DOPENFOAM=2006 -DWM_DP -DWM_LABEL_SIZE=32 \
-Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor \
-Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -Wno-unknown-pragmas \
-O3 -DNoRepository -ftemplate-depth-100 \
-I/installdir/OpenFOAM-v2006/src/finiteVolume/lnInclude -I/installdir/OpenFOAM-v2006/src/meshTools/lnInclude -I/installdir/OpenFOAM-v2006/src/sampling/lnInclude -I/installdir/OpenFOAM-v2006/src/TurbulenceModels/turbulenceModels/lnInclude -I/installdir/OpenFOAM-v2006/src/TurbulenceModels/incompressible/lnInclude -I/installdir/OpenFOAM-v2006/src/transportModels -I/installdir/OpenFOAM-v2006/src/transportModels/incompressible/singlePhaseTransportModel -I/installdir/OpenFOAM-v2006/src/dynamicMesh/lnInclude \
-I/installdir/OpenFOAM-v2006/src/dynamicFvMesh/lnInclude -iquote. -IlnInclude -I/installdir/OpenFOAM-v2006/src/OpenFOAM/lnInclude -I/installdir/OpenFOAM-v2006/src/OSspecific/POSIX/lnInclude \
-fPIC \
-c pimpleFoam.C \
-o Make/linux64GccDPInt32Opt/pimpleFoam.o
g++ -std=c++11 -m64 -pthread \
-DOPENFOAM=2006 -DWM_DP -DWM_LABEL_SIZE=32 \
-Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor \
-Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -Wno-unknown-pragmas \
-O3 -DNoRepository -ftemplate-depth-100 \
-I/installdir/OpenFOAM-v2006/src/finiteVolume/lnInclude -I/installdir/OpenFOAM-v2006/src/meshTools/lnInclude -I/installdir/OpenFOAM-v2006/src/sampling/lnInclude -I/installdir/OpenFOAM-v2006/src/TurbulenceModels/turbulenceModels/lnInclude -I/installdir/OpenFOAM-v2006/src/TurbulenceModels/incompressible/lnInclude -I/installdir/OpenFOAM-v2006/src/transportModels -I/installdir/OpenFOAM-v2006/src/transportModels/incompressible/singlePhaseTransportModel -I/installdir/OpenFOAM-v2006/src/dynamicMesh/lnInclude \
-I/installdir/OpenFOAM-v2006/src/dynamicFvMesh/lnInclude -iquote. -IlnInclude -I/installdir/OpenFOAM-v2006/src/OpenFOAM/lnInclude -I/installdir/OpenFOAM-v2006/src/OSspecific/POSIX/lnInclude \
-fPIC \
-Xlinker --add-needed \
-Xlinker --no-as-needed \
Make/linux64GccDPInt32Opt/pimpleFoam.o \
-L/installdir/OpenFOAM-v2006/platforms/linux64GccDPInt32Opt/lib \
-lfiniteVolume -lfvOptions -lmeshTools -lsampling -lturbulenceModels -lincompressibleTurbulenceModels -lincompressibleTransportModels \
-ldynamicMesh -ldynamicFvMesh -ltopoChangerFvMesh -latmosphericModels -lOpenFOAM -ldl -lm \
-o /installdir/inabower-v2006/platforms/linux64GccDPInt32Opt/bin/cpPimpleFoam
このうち一行目以外は実際に実行されたコマンドです。
つまり**wmake
によりg++
がオプションを変えて2回実行された**ことがわかります。
g++とは
まずg++
(GNU C++ Compiler)について少し説明します。
これはGCC (GNU Compiler Colelction)の一つであり、先述の2つのg++
はそれぞれ**『コンパイラでオブジェクトファイルを生成』と『リンカで実行ファイルを生成』**という動作をしています。これらの説明については以下のサイトがわかりやすかったです。
コンパイラは何をしているのか
http://nenya.cis.ibaraki.ac.jp/TIPS/compiler.html
みなさんがコンパイラだと思っている gccは、 実は、コンパイラドライバ(compiler driver)と呼ばれるプログラムであり、 Cなどのプログラミング言語で書かれたソースプログラムから実行形式を 作り出すための処理を行う
gccは、**「必要に応じてコンパイラや アセンブラ、リンケージエディタなどのプログラムを呼び出す」**という 処理を行っている。gccコマンド自体が直接コンパイルを行っているわけではない。
実際にそれぞれの動作を確認してみましょう。
1. コンパイラ
C++で記述されたファイルから機械語に翻訳されたオブジェクトファイルを作成します。
先ほどのg++
ではpimpleFoam.C
というファイルからMake/linux64GccDPInt32Opt/pimpleFoam.o
というオブジェクトファイルを生成しています。
g++ -std=c++11 -m64 -pthread \
-DOPENFOAM=2006 -DWM_DP -DWM_LABEL_SIZE=32 \ # OpenFOAM側で使用するDEFINE
-Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor \ # コンパイル時に表示するエラーの選択
-Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -Wno-unknown-pragmas \ # 表示しないエラーの選択
-O3 \ # 最適化オプション
-DNoRepository -ftemplate-depth-100 \ # OpenFOAM側で使用するDEFINEと再帰の上限
-I/installdir/OpenFOAM-v2006/src/finiteVolume/lnInclude -I/installdir/OpenFOAM-v2006/src/meshTools/lnInclude -I/installdir/OpenFOAM-v2006/src/sampling/lnInclude -I/installdir/OpenFOAM-v2006/src/TurbulenceModels/turbulenceModels/lnInclude -I/installdir/OpenFOAM-v2006/src/TurbulenceModels/incompressible/lnInclude -I/installdir/OpenFOAM-v2006/src/transportModels -I/installdir/OpenFOAM-v2006/src/transportModels/incompressible/singlePhaseTransportModel -I/installdir/OpenFOAM-v2006/src/dynamicMesh/lnInclude \
-I/installdir/OpenFOAM-v2006/src/dynamicFvMesh/lnInclude -iquote. -IlnInclude -I/installdir/OpenFOAM-v2006/src/OpenFOAM/lnInclude -I/installdir/OpenFOAM-v2006/src/OSspecific/POSIX/lnInclude \
-fPIC \
-c pimpleFoam.C \
-o Make/linux64GccDPInt32Opt/pimpleFoam.o
実際に以下のようにMake
ディレクトリの下にpimpleFoam.o
が生成されていることを確認できます。
$ tree
.
├── Make
│ ├── files
│ ├── linux64GccDPInt32Opt
│ │ ├── options
│ │ ├── pimpleFoam.C.dep
│ │ ├── pimpleFoam.o
│ │ ├── sourceFiles
│ │ └── variables
│ └── options
├── UEqn.H
├── correctPhi.H
├── cpCorrectPhi.H
├── createFields.H
├── log.wmake
├── pEqn.H
└── pimpleFoam.C
このオブジェクトファイルは実行することはできません。
$ Make/linux64GccDPInt32Opt/pimpleFoam.o
bash: Make/linux64GccDPInt32Opt/pimpleFoam.o: cannot execute binary file: Exec format error
pimpleFoam
としての動作をしてほしい場合には次の『リンカ』による実行ファイルの作成が必要になります。
2. リンカ
オブジェクトファイルをリンクすることで実行ファイルを作成します。
先ほどのMake/linux64GccDPInt32Opt/pimpleFoam.o
(-5行目)を含む多くのオブジェクトファイルから$FOAM_USER_APPBIN/bin/cpPimpleFoam
(最終行)という実行ファイルを生成しています。計算時にcpPimpleFoam
と実行すると、この$FOAM_USER_APPBIN/bin/cpPimpleFoam
が実行されます。
g++ -std=c++11 -m64 -pthread \
-DOPENFOAM=2006 -DWM_DP -DWM_LABEL_SIZE=32 \ # OpenFOAM側で使用するDEFINE
-Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor \ # コンパイル時に表示するエラーの選択
-Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -Wno-unknown-pragmas \ # 表示しないエラーの選択
-O3 -DNoRepository -ftemplate-depth-100 \
-I/installdir/OpenFOAM-v2006/src/finiteVolume/lnInclude -I/installdir/OpenFOAM-v2006/src/meshTools/lnInclude -I/installdir/OpenFOAM-v2006/src/sampling/lnInclude -I/installdir/OpenFOAM-v2006/src/TurbulenceModels/turbulenceModels/lnInclude -I/installdir/OpenFOAM-v2006/src/TurbulenceModels/incompressible/lnInclude -I/installdir/OpenFOAM-v2006/src/transportModels -I/installdir/OpenFOAM-v2006/src/transportModels/incompressible/singlePhaseTransportModel -I/installdir/OpenFOAM-v2006/src/dynamicMesh/lnInclude \
-I/installdir/OpenFOAM-v2006/src/dynamicFvMesh/lnInclude -iquote. -IlnInclude -I/installdir/OpenFOAM-v2006/src/OpenFOAM/lnInclude -I/installdir/OpenFOAM-v2006/src/OSspecific/POSIX/lnInclude \
-fPIC \ # ここまで1つ目のg++と同じ
-Xlinker --add-needed \ # リンカオプション
-Xlinker --no-as-needed \ # リンカオプション
Make/linux64GccDPInt32Opt/pimpleFoam.o \
-L/installdir/OpenFOAM-v2006/platforms/linux64GccDPInt32Opt/lib \
-lfiniteVolume -lfvOptions -lmeshTools -lsampling -lturbulenceModels -lincompressibleTurbulenceModels -lincompressibleTransportModels \
-ldynamicMesh -ldynamicFvMesh -ltopoChangerFvMesh -latmosphericModels -lOpenFOAM -ldl -lm \
-o $FOAM_USER_APPBIN/bin/cpPimpleFoam
なおここでリンクしているpimpleFoam.o
以外のオブジェクトファイルは**共有ライブラリ(shared objerct)**と呼ばれ、lib*.so
というファイル名で作成されています。これらは主に$FOAM_SRC
ディレクトリの*.C
ファイルからコンパイルされたものになります。
以下のように実行ファイルが生成されていることがわかります。
$ ls $FOAM_USER_APPBIN
cpPimpleFoam
また、以下のように実行することができます。
$ cpPimpleFoam
/*---------------------------------------------------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2006 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
(略 : 以下OpenFOAMのエラーメッセージ)
Makeディレクトリについて
wmake
の際の設定をMake
ディレクトリの中身で記述をします。
$ tree
.
├── Make
│ ├── files
│ └── options
├── UEqn.H
├── correctPhi.H
├── createFields.H
├── pEqn.H
└── pimpleFoam.C
この中には以下のような二つのファイルが入っています。
Make/files
pimpleFoam.C # 最初のg++でどのファイルをコンパイルするか
EXE = $(FOAM_USER_APPBIN)/cpPimpleFoam # 最後のg++で生成する実行ファイルのパス
最初の行では**『どのファイルをコンパイルするか』**を指定しています。
ここではオブジェクトファイルにコンパイルするファイルはpimpleFoam.C
のみですので、今回はpimpleFoam.o
のみが生成されたということになります。
ここには複数の境界条件や乱流モデルなどに関する*.C
を列挙することもできます。例えばincomprssible/adjointShapeOptimizationFoam
のMake/files
は以下のようになっています。
adjointOutletPressure/adjointOutletPressureFvPatchScalarField.C # 1回目のg++でコンパイル
adjointOutletVelocity/adjointOutletVelocityFvPatchVectorField.C # 2回目のg++でコンパイル
adjointShapeOptimizationFoam.C # 3回目のg++でコンパイル
EXE = $(FOAM_APPBIN)/adjointShapeOptimizationFoam # 4回目のg++でリンク
この場合はwmake
の際にg++
は4回実行されることになります。これらの境界条件はこのソルバーでのみ使用するものであるため、ここでオブジェクトファイルにしているようです。
ただし通常OpenFOAMでは一つの境界条件を複数のソルバーで使用できるように境界条件などについては共有ライブラリという形で別々にコンパイルされ、適宜リンクされることが多いです。どれをリンクするかについては次のMake/options
に記載されます。
Make/options
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \
-I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/dynamicFvMesh/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-lfvOptions \
-lmeshTools \
-lsampling \
-lturbulenceModels \
-lincompressibleTurbulenceModels \
-lincompressibleTransportModels \
-ldynamicMesh \
-ldynamicFvMesh \
-ltopoChangerFvMesh \
-latmosphericModels
EXE_INC:#includeするファイル
最初のEXE_INC =
では**『インクルードする*.H
ファイルの場所』**を列挙していきます。
例えば今回コンパイルするpimpleFoam.C
の最初の行は以下のようになっています。
#include "fvCFD.H"
#include "dynamicFvMesh.H"
#include "singlePhaseTransportModel.H"
#include "turbulentTransportModel.H"
#include "pimpleControl.H"
#include "cpCorrectPhi.H"
#include "fvOptions.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
(以下略)
この最初のfvCFD.H
は以下のように/installdir/OpenFOAM-v2006/src/finiteVolume/lnInclude/
つまり$(LIB_SRC)/finiteVolume/lnInclude
にあることが分かります。
$ find $FOAM_SRC -name fvCFD.H
/installdir/OpenFOAM-v2006/src/finiteVolume/lnInclude/fvCFD.H # ↓と同じもの(正確にはシンボリックリンク)
/installdir/OpenFOAM-v2006/src/finiteVolume/cfdTools/general/include/fvCFD.H # オリジナル
このように、wmake
でコンパイルするファイルの中の全ての#include "*.H"
がどれを指すかが分かるようにする必要があります。なお複数ディレクトリで重複ファイル名のものがある場合はEXE_INC =
の順番がそのまま検索優先順位になります。
EXE_LIBS:リンクする共有ライブラリの名前
次のEXE_LIBS =
では**『リンクする共有ライブラリの名前』**を指定しています。検索ディレクトリはデフォルトで$FOAM_LIBBIN
になりますので、例えば-lfiniteVolume
は/installdir/OpenFOAM-v2006/platforms/linux64GccDPInt32Opt/lib/libfiniteVolume.so
を指すことになります。
もし他のディレクトリのライブラリを指定したい場合は以下のよう追加すればOKです。
(略)
EXE_LIBS = \
-lfiniteVolume \
-lfvOptions \
-lmeshTools \
-lsampling \
-lturbulenceModels \
-lincompressibleTurbulenceModels \
-lincompressibleTransportModels \
-ldynamicMesh \
-ldynamicFvMesh \
-ltopoChangerFvMesh \
-latmosphericModels \
-L/home/myLib \
-lmyModel1 \
-lmyModel2
もう一度2つのg++を見てみる
というわけで、Make
ディレクトリの中では以下のコメントアウトしていない内容について指定したことが分かります。
# g++ -std=c++11 -m64 -pthread \
# -DOPENFOAM=2006 -DWM_DP -DWM_LABEL_SIZE=32 \
# -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor \
# -Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -Wno-unknown-pragmas \
# -O3 -DNoRepository -ftemplate-depth-100 \
#### includeするファイルのある場所 (Make/options前半) ####
-I/installdir/OpenFOAM-v2006/src/finiteVolume/lnInclude \
-I/installdir/OpenFOAM-v2006/src/meshTools/lnInclude \
-I/installdir/OpenFOAM-v2006/src/sampling/lnInclude \
-I/installdir/OpenFOAM-v2006/src/TurbulenceModels/turbulenceModels/lnInclude \
-I/installdir/OpenFOAM-v2006/src/TurbulenceModels/incompressible/lnInclude \
-I/installdir/OpenFOAM-v2006/src/transportModels \
-I/installdir/OpenFOAM-v2006/src/transportModels/incompressible/singlePhaseTransportModel \
-I/installdir/OpenFOAM-v2006/src/dynamicMesh/lnInclude \
-I/installdir/OpenFOAM-v2006/src/dynamicFvMesh/lnInclude
# -iquote. \
# -IlnInclude \
# -I/installdir/OpenFOAM-v2006/src/OpenFOAM/lnInclude \
# -I/installdir/OpenFOAM-v2006/src/OSspecific/POSIX/lnInclude \
# -fPIC \
#### コンパイルする.Cファイル (Make/files前半) ####
-c pimpleFoam.C \
#### 生成するオブジェクトファイル ####
-o Make/linux64GccDPInt32Opt/pimpleFoam.o
# g++ -std=c++11 -m64 -pthread \
# -DOPENFOAM=2006 -DWM_DP -DWM_LABEL_SIZE=32 \
# -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor \
# -Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -Wno-unknown-pragmas \
# -O3 -DNoRepository -ftemplate-depth-100 \
#### includeするファイルのある場所 (Make/options前半) ####
-I/installdir/OpenFOAM-v2006/src/finiteVolume/lnInclude \
-I/installdir/OpenFOAM-v2006/src/meshTools/lnInclude \
-I/installdir/OpenFOAM-v2006/src/sampling/lnInclude \
-I/installdir/OpenFOAM-v2006/src/TurbulenceModels/turbulenceModels/lnInclude \
-I/installdir/OpenFOAM-v2006/src/TurbulenceModels/incompressible/lnInclude \
-I/installdir/OpenFOAM-v2006/src/transportModels \
-I/installdir/OpenFOAM-v2006/src/transportModels/incompressible/singlePhaseTransportModel \
-I/installdir/OpenFOAM-v2006/src/dynamicMesh/lnInclude \
-I/installdir/OpenFOAM-v2006/src/dynamicFvMesh/lnInclude
# -iquote. -IlnInclude \
# -I/installdir/OpenFOAM-v2006/src/OpenFOAM/lnInclude \
# -I/installdir/OpenFOAM-v2006/src/OSspecific/POSIX/lnInclude \
# -fPIC \
# -Xlinker --add-needed \
# -Xlinker --no-as-needed \
#### 前のg++で生成したオブジェクトファイル (Make/files前半) ####
Make/linux64GccDPInt32Opt/pimpleFoam.o \
# -L/installdir/OpenFOAM-v2006/platforms/linux64GccDPInt32Opt/lib \
#### 共有ライブラリのリスト (Make/options後半 EXE_LIBS) ####
-lfiniteVolume \
-lfvOptions \
-lmeshTools \
-lsampling \
-lturbulenceModels \
-lincompressibleTurbulenceModels \
-lincompressibleTransportModels \
-ldynamicMesh \
-ldynamicFvMesh \
-ltopoChangerFvMesh \
-latmosphericModels \
# -lOpenFOAM -ldl -lm \
#### 実行ファイルの名前 (Make/files後半 EXE) ####
-o /installdir/inabower-v2006/platforms/linux64GccDPInt32Opt/bin/cpPimpleFoam
それでは最後にこれらのg++オプションがどういう仕組みで生成されているかについて見ていきます。
makefileとmakeコマンド
wmake
と実行するとwmake
というスクリプトが実行されます。
これは以下のようにwhich
コマンドで確認することができます。
$ which wmake
/installdir/OpenFOAM-v2006/wmake/wmake
その中身を見てみます。
Script="${0##*/}" # Need 'Script' for wmakeFunctions messages
scriptsDir="${0%/*}"/scripts # wmake/scripts directory
. "$scriptsDir"/wmakeFunctions # Source wmake functions
(略)
# Default make is the "make" in the path
make="make"
(略)
exec $make -f $WM_DIR/makefiles/general \
${optDebug:+c++DBUG="$optDebug"} \
MAKE_DIR=$MakeDir OBJECTS_DIR=$objectsDir $targetType
exit 0 # clean exit
最後のexec
により実行される内容は私の環境では以下のようになります。
make -f /installdir/OpenFOAM-v2006/wmake/makefiles/general \
MAKE_DIR=Make OBJECTS_DIR=Make/linux64GccDPInt32Opt
というわけで、wmake
では**『wmake/makefiles/general
というmakefileについてmake
を実行している』ことが分かります。このmakefileの中にこの記事で説明してきた2つのg++**に関する内容が記述されることが予想されます。
makefiles/general
このファイルは多くのファイルを経由して変数をセットした上でmakefileとして機能する雛型のようなファイルです。
例えば先述のMake/options
で指定したEXE_INC
やEXE_LIBS
は以下のように組み込まれます。半永久的に追加したいライブラリなどがある場合はここに追加してもよいかもしれません。
(略)
#------------------------------------------------------------------------------
# Include paths, use -iquote to ensure that (.) is searched first
#------------------------------------------------------------------------------
LIB_HEADER_DIRS = \
$(EXE_INC) \
-iquote. \
-IlnInclude \
$(PROJECT_INC) \
$(GINC) \
$(SYS_INC)
(略)
#------------------------------------------------------------------------------
# Define link statements for executables
#------------------------------------------------------------------------------
(略)
$(EXE)$(EXT_EXE): $(OBJECTS)
@$(WM_SCRIPTS)/makeTargetDir $(EXE)
$(call QUIET_MESSAGE,ld,$(EXE)$(EXT_EXE))
$E $(LINKEXE) $(OBJECTS) -L$(LIB_PLATFORMS) \
$(EXE_LIBS) $(PROJECT_LIBS) $(SYS_LIBS) \
$(LINK_LIBS) $(GLIBS) -o $(EXE)$(EXT_EXE)
(略)
そのため、以下ではwmakeの際のオプションをどこで指定しているかについて軽く紹介します。
各自でコンパイル時の設定を変更したい場合の参考にしてください。
コンパイラ
ここまでg++でコンパイルする前提で紹介してきましたが他のコンパイラを指定することもできます。これは大本の/installdir/OpenFOAM-v2006/etc/bashrc
で指定します。それぞれの好みに合わせて指定するとよいかと思います。
# [WM_COMPILER] - Compiler:
# = Gcc | Clang | Icc | Cray | Amd | Arm | Pgi | Fujitsu |
# Gcc<digits> | Clang<digits>
export WM_COMPILER=Gcc
以降もここまでと同様にGccを指定したという前提で紹介していきます。
コンパイラオプション
① 一般設定
まず/installdir/OpenFOAM-v2006/wmake/rules/General/Gcc/c++
が読み込まれます。
例えばC++17でコンパイルしたい場合などはここで-std=c++11
を-std=c++17
に変更したりします。
また、c++WARN
はコンパイル時に出力するエラーの種類です。動作は問題ないけど警告するエラーなどについてデバッグ時の妨げになるようであればここでオプションを追加して非表示にしたりします。
SUFFIXES += .C .cc .cpp .cxx
CC = g++ -std=c++11
c++ARCH =
c++DBUG =
c++OPT = -O2
ptFLAGS = -DNoRepository -ftemplate-depth-100
# - Standard warnings
# - Less restrictive warnings (may be needed for flex++, CGAL, etc.)
c++WARN = \
-Wall -Wextra -Wold-style-cast \
-Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof \
-Wno-attributes -Wno-unknown-pragmas \
$(FOAM_EXTRA_CXXFLAGS)
c++LESSWARN = \
-Wno-old-style-cast -Wno-unused-local-typedefs -Wno-array-bounds \
-Wno-deprecated-declarations \
-fpermissive
② アーキテクチャ個別の設定
①の設定はここで読み込まれることになります。①と②で、最初に示したg++のオプションの前半が網羅されているかと思います。
include $(GENERAL_RULES)/Gcc/c++
c++ARCH = -m64 -pthread
include $(DEFAULT_RULES)/c++$(WM_COMPILE_OPTION)
c++FLAGS = $(c++ARCH) $(GFLAGS) $(c++WARN) $(c++OPT) $(c++DBUG) $(ptFLAGS) $(LIB_HEADER_DIRS) -fPIC
Ctoo = $(WM_SCHEDULER) $(CC) $(c++FLAGS) -c $< -o $@
cxxtoo = $(Ctoo)
cctoo = $(Ctoo)
cpptoo = $(Ctoo)
include $(GENERAL_RULES)/Gcc/link-c++
最適化オプション
最適化オプション-O3
はここで指定されています。
c++DBUG =
c++OPT = -O3
ROUNDING_MATH = -frounding-math
環境変数$WM_COMPILE_OPTION=Opt
がデフォルトであるため通常は-O3
となります。もしこれが原因と思われるエラーに遭遇した場合にはここを変更してもよいかもしれません。
GCCの最適化 / gentoo linux wiki
wiki.gentoo.org/wiki/GCC_optimization
-O3
: これは取りうる最も高い最適化レベルです。コンパイル時間とメモリ使用量を犠牲にして最適化を実施します。ただし-O3
は性能を改善する保証がありません。実際多くのケースで、バイナリサイズが大きくなり、メモリ使用量が増えることで逆にシステムが遅くなります。-O3
はいくつかのパッケージを壊すことがわかっています。これらの理由により-O3
は推奨されません。一方、このレベルはコード内のループをベクトル化する-ftree-vectorize
を有効化し、AVX YMMレジスタも利用されます。
まとめ
wmake
では以下の動作を行っているみたいです。
- **
wmake
**を実行すると・・・ - **
make -f wmake/makefiles/general
**が実行される-
wmake/makefiles/general
をMakefile
として読み込む- コンパイラオプションなどを指定
- いくつかの情報を
Make/files
とMake/options
で補完
-
Make/files
を読み込む- コンパイルするファイルを指定
- 実行ファイル名を指定
-
Make/options
を読み込む- includeファイルのあるディレクトリを指定
- 共有ライブラリ(
lib*.so
)を指定
-
- 複数回の
g++
が実行される(Makefile
の内容による)-
g++
でコンパイル (× オブジェクト数)- オブジェクト(
*.o
)を生成
- オブジェクト(
-
g++
でリンク- 生成したオブジェクト(
*.o
)と指定した共有ライブラリ(lib*.so
)をリンク - 実行ファイルを生成
- 生成したオブジェクト(
-
最後に
間違っている点等がございましたら指摘いただけると助かります。