Clang/C++11 を使う

2016年11月18日

はじめに

OpenFOAM で Clang/C++11 を使う。

使用バージョン

OpenFOAM 4.1 (Ubuntu バイナリ版)

セットアップ

OpenFOAM で Clang を使う場合、ソースからコンパイルするのが筋だろうが、時間がかかるので、ここではバイナリ版の設定を修正する。

$WM_PROJECT_DIR/etc/bashrc

#export WM_COMPILER=Gcc
export WM_COMPILER=Clang

$WM_PROJECT_DIR/wmake/rules/linux64Clang/c++

#c++WARN     = -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof -Wno-c++11-extensions
c++WARN     = -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof -Wno-c++11-extensions -Wno-unused-comparison

...

#c++FLAGS    = $(GFLAGS) $(c++WARN) $(c++OPT) $(c++DBUG) $(ptFLAGS) $(LIB_HEADER_DIRS) -fPIC
c++FLAGS    = $(GFLAGS) $(c++WARN) $(c++OPT) $(c++DBUG) $(ptFLAGS) $(LIB_HEADER_DIRS) -fPIC -std=c++11

"c++WARN" に "-Wno-unused-comparison"、"c++FLAGS" に "-std=c++11" を追加している。以前のバージョンでははじめから "-Wno-unused-comparison" が入っていたので、これがあると問題があると判断されたのかもしれない。

バイナリを Clang 用にコピーする。

$ cd $WM_PROJECT_DIR/platforms
$ sudo cp -r linux64GccDPOpt linux64ClangDPOpt
$ cd $WM_PROJECT_DIR/wmake/platforms
$ sudo cp -r linux64Gcc linux64Clang

コンパイルエラーの比較

potentialFoam でコンパイルエラーの違いを確認してみる。

createFields.H

volScalarField p
(
    IOobject
    (
        pName,
        runTime.timeName(),
        mesh,
        IOobject::READ_IF_PRESENT,
        IOobject::NO_WRITE
    )
    //),
    //mesh,
    //dimensionedScalar(pName, sqr(dimVelocity), 0),
    //pBCTypes
);

Gcc, Clang 双方のバイナリがある状態なので、双方のコンパイラを切り替えられる。Gcc に切り替える場合は次のようにする。

$ WM_COMPILER=Gcc

Gcc によるエラー。

$ wmake
...
In file included from potentialFoam.C:81:0:
createFields.H: In function ‘int main(int, char**)’:
createFields.H:73:1: error: no matching function for call to ‘Foam::GeometricField<double, Foam::fvPatchField, Foam::volMesh>::GeometricField(Foam::IOobject)’
 );
 ^
createFields.H:73:1: note: candidates are:
In file included from /opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.H:651:0,
                 from /opt/openfoam4/src/OpenFOAM/lnInclude/GeometricScalarField.H:38,
                 from /opt/openfoam4/src/OpenFOAM/lnInclude/GeometricFields.H:34,
                 from /opt/openfoam4/src/finiteVolume/lnInclude/volFields.H:37,
                 from /opt/openfoam4/src/finiteVolume/lnInclude/surfaceInterpolationScheme.C:27,
                 from /opt/openfoam4/src/finiteVolume/lnInclude/surfaceInterpolationScheme.H:304,
                 from /opt/openfoam4/src/finiteVolume/lnInclude/surfaceInterpolate.H:41,
                 from /opt/openfoam4/src/finiteVolume/lnInclude/fvc.H:39,
                 from /opt/openfoam4/src/finiteVolume/lnInclude/fvCFD.H:8,
                 from potentialFoam.C:37:
/opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.C:663:1: note: Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField(const Foam::IOobject&, const Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh> >&, const wordList&, const wordList&) [with Type = double; PatchField = Foam::fvPatchField; GeoMesh = Foam::volMesh; Foam::wordList = Foam::List<Foam::word>]
 Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
 ^
/opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.C:663:1: note:   candidate expects 4 arguments, 1 provided
/opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.C:620:1: note: Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField(const Foam::IOobject&, const Foam::GeometricField<Type, PatchField, GeoMesh>&, const wordList&, const wordList&) [with Type = double; PatchField = Foam::fvPatchField; GeoMesh = Foam::volMesh; Foam::wordList = Foam::List<Foam::word>]
 Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
 ^

...

/opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.C:200:1: note:   candidate expects 5 arguments, 1 provided
/opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.C:176:1: note: Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField(const Foam::IOobject&, const Mesh&, const Foam::dimensionSet&, const Foam::word&) [with Type = double; PatchField = Foam::fvPatchField; GeoMesh = Foam::volMesh; Foam::GeometricField<Type, PatchField, GeoMesh>::Mesh = Foam::fvMesh]
 Foam::GeometricField<Type, PatchField, GeoMesh>::GeometricField
 ^
/opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.C:176:1: note:   candidate expects 4 arguments, 1 provided
make: *** [Make/linux64ClangDPInt32Opt/potentialFoam.o] エラー 1

Clang によるエラー。

In file included from potentialFoam.C:81:
./createFields.H:59:16: error: no matching constructor for initialization of
      'volScalarField' (aka 'GeometricField<scalar, fvPatchField,
      Foam::volMesh>')
volScalarField p
               ^
/opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.H:367:9: note: candidate
      constructor not viable: no known conversion from 'Foam::IOobject' to
      'const GeometricField<double, fvPatchField, Foam::volMesh>' for 1st
      argument
        GeometricField
        ^
/opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.H:374:9: note: candidate
      constructor not viable: no known conversion from 'Foam::IOobject' to
      'const tmp<GeometricField<double, fvPatchField, Foam::volMesh> >' for 1st
      argument
        GeometricField

...

/opt/openfoam4/src/OpenFOAM/lnInclude/GeometricField.H:305:9: note: candidate
      constructor not viable: requires at least 4 arguments, but 1 was provided
        GeometricField
        ^
1 error generated.
make: *** [Make/linux64ClangDPInt32Opt/potentialFoam.o] エラー 1

Clang のほうがいくらかすっきりしている。

C++11 のテスト

同じく potentialFoam で、C++11 のコードを書いてみる。

まず、従来のコード。

const volScalarField::Boundary &bf = p.boundaryField();
Info<< bf.types() << endl;

上記を、C++11 では次のように簡単に書ける。

auto &bf = p.boundaryField();
Info<< bf.types() << endl;