Help us understand the problem. What is going on with this article?

【OpenFOAM】wmakeって何してるの

このエントリーはオープンCAE Advent Calendar 2020 の1日目です。

はじめに

 OpenFOAMのアプリケーションおよびライブラリはwmakeというコマンドでコンパイルされます。このコマンドの中で何が起きているのか、詳細に把握していなかったので調べて整理してみました。

概要

wmakeでは以下の動作を行っているみたいです。

  • wmakeを実行すると・・・
  • make -f wmake/makefiles/generalが実行される
    • wmake/makefiles/generalMakefileとして読み込む
      • コンパイラオプションなどを指定
      • いくつかの情報をMake/filesMake/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
Figure 3.1: Header files, source files, compilation and linking

 このように『どのクラスをリンクするか』や『どのファイルをインクルードするか』などの複雑な情報を実行ファイルごとに記述しコンパイルするために、OpenFOAMではwmakeというコマンドが用意されています。

wmakeを実行してみる

 取り合えずwmakeを実行してみます。今回は例としてpimpleFoamをコピーしてcpPimpleFoamというソルバーを作成する場合を考えます。

bash
$ 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

出力されたファイルの内容は以下の通りです。

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というオブジェクトファイルを生成しています。

1つ目のg++(log.wmake)
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が生成されていることを確認できます。

bash
$ 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

このオブジェクトファイルは実行することはできません。

bash
$ 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ファイルからコンパイルされたものになります。

 以下のように実行ファイルが生成されていることがわかります。

bash
$ ls $FOAM_USER_APPBIN
cpPimpleFoam

 また、以下のように実行することができます。

bash
$ 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ディレクトリの中身で記述をします。

bash
$ tree
.
├── Make
│   ├── files
│   └── options
├── UEqn.H
├── correctPhi.H
├── createFields.H
├── pEqn.H
└── pimpleFoam.C

この中には以下のような二つのファイルが入っています。

Make/files

Make/files
pimpleFoam.C # 最初のg++でどのファイルをコンパイルするか

EXE = $(FOAM_USER_APPBIN)/cpPimpleFoam # 最後のg++で生成する実行ファイルのパス

 最初の行では『どのファイルをコンパイルするか』を指定しています。
ここではオブジェクトファイルにコンパイルするファイルはpimpleFoam.Cのみですので、今回はpimpleFoam.oのみが生成されたということになります。

 ここには複数の境界条件や乱流モデルなどに関する*.Cを列挙することもできます。例えばincomprssible/adjointShapeOptimizationFoamMake/filesは以下のようになっています。

$FOAM_SOLVERS/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

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の最初の行は以下のようになっています。

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にあることが分かります。

bash
$ 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です。

Make/options
(略)
EXE_LIBS = \
    -lfiniteVolume \
    -lfvOptions \
    -lmeshTools \
    -lsampling \
    -lturbulenceModels \
    -lincompressibleTurbulenceModels \
    -lincompressibleTransportModels \
    -ldynamicMesh \
    -ldynamicFvMesh \
    -ltopoChangerFvMesh \
    -latmosphericModels \
    -L/home/myLib \
    -lmyModel1 \
    -lmyModel2

もう一度2つのg++を見てみる

 というわけで、Makeディレクトリの中では以下のコメントアウトしていない内容について指定したことが分かります。

log.wmake
# 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

 その中身を見てみます。

/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_INCEXE_LIBSは以下のように組み込まれます。半永久的に追加したいライブラリなどがある場合はここに追加してもよいかもしれません。

wmake/makefiles/general
(略)
#------------------------------------------------------------------------------
# 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で指定します。それぞれの好みに合わせて指定するとよいかと思います。

/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はコンパイル時に出力するエラーの種類です。動作は問題ないけど警告するエラーなどについてデバッグ時の妨げになるようであればここでオプションを追加して非表示にしたりします。

/installdir/OpenFOAM-v2006/wmake/rules/General/Gcc/c++
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++のオプションの前半が網羅されているかと思います。

/installdir/OpenFOAM-v2006/wmake/rules/linux64Gcc/c++
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はここで指定されています。

/installdir/OpenFOAM-v2006/wmake/rules/linux64Gcc/c++Opt
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/generalMakefileとして読み込む
      • コンパイラオプションなどを指定
      • いくつかの情報をMake/filesMake/optionsで補完
    • Make/filesを読み込む
      • コンパイルするファイルを指定
      • 実行ファイル名を指定
    • Make/optionsを読み込む
      • includeファイルのあるディレクトリを指定
      • 共有ライブラリ(lib*.so)を指定
  • 複数回のg++が実行される(Makefileの内容による)
    • g++でコンパイル (× オブジェクト数)
      • オブジェクト(*.o)を生成
    • g++でリンク
      • 生成したオブジェクト(*.o)と指定した共有ライブラリ(lib*.so)をリンク
      • 実行ファイルを生成

最後に

 間違っている点等がございましたら指摘いただけると助かります。

inabower
OpenFOAMを扱ってます。 情報の比較的少ないマルチリージョンに関して少しずつまとめていけたらと思っています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away