利用VS Code阅读源码及调试OpenFOAM
1 准备工作
- win10上安装VSCode
- VSCode安装
remote-wsl
插件用于连接Linux子系统,remote-ssh
插件用于连接远程Linux服务器 - 连接到wsl或远程Linux服务器后,安装
C/C++
插件
以上步骤可以自行搜索了解细节。如果是原生Linux系统,则可直接安装VSCode,然后安装C/C++
插件即可。
下图展示连接局域网内的Ubuntu服务器(左下角有提示),并且安装了C/C++
插件。
2 阅读源码篇
以icoFoam
求解器为例。
- 在VSCode中按
win+`
键(左上角同~
键)打开集成的终端。
-
加载OpenFOAM环境,拷贝求解器:
如果终端配置文件中使用的是source xxx/bashrc
或. xxx/bashrc
,则不需要额外激活OF环境; 如果是通过alias管理多版本OF,则输入对应的alias激活OF环境,如of6
1
2
3$ mkdir -p $WM_PROJECT_USER_DIR/solver
$ cp -r $FOAM_SOLVERS/incompressible/icoFoam $WM_PROJECT_USER_DIR/solver/
$ cd $WM_PROJECT_USER_DIR/solver/icoFoam -
修改
Make/files
:1
2
3icoFoam.C
EXE = $(FOAM_USER_APPBIN)/myicoFoam -
通过
wmake
查看真实调用的编译命令,从中提取-I
路径用于后续配置:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17$ wmake | tee log.wmake
Making dependency list for source file icoFoam.C
g++ -std=c++11 -m64 -Dlinux64 -DWM_ARCH_OPTION=64 -DWM_DP -DWM_LABEL_SIZE=32 -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -O3 -DNoRepository -ftemplate-depth-100 -I/opt/openfoam6/src/finiteVolume/lnInclude -I/opt/openfoam6/src/meshTools/lnInclude -IlnInclude -I. -I/opt/openfoam6/src/OpenFOAM/lnInclude -I/opt/openfoam6/src/OSspecific/POSIX/lnInclude -fPIC -c icoFoam.C -o Make/linux64GccDPInt32Opt/icoFoam.o
g++ -std=c++11 -m64 -Dlinux64 -DWM_ARCH_OPTION=64 -DWM_DP -DWM_LABEL_SIZE=32 -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -O3 -DNoRepository -ftemplate-depth-100 -g -I/opt/openfoam6/src/finiteVolume/lnInclude -I/opt/openfoam6/src/meshTools/lnInclude -IlnInclude -I. -I/opt/openfoam6/src/OpenFOAM/lnInclude -I/opt/openfoam6/src/OSspecific/POSIX/lnInclude -fPIC -Xlinker --add-needed -Xlinker --no-as-needed Make/linux64GccDPInt32Opt/icoFoam.o -L/opt/openfoam6/platforms/linux64GccDPInt32Opt/lib \
-lfiniteVolume -lmeshTools -lOpenFOAM -ldl \
-lm -o /home/of/OpenFOAM/of-6/platforms/linux64GccDPInt32Opt/bin/myicoFoam
$ cat log.wmake | sed 's/ /\n/g' | grep '\-I' | sort | uniq | sed 's/\-I//g'
.
lnInclude
/opt/openfoam6/src/finiteVolume/lnInclude
/opt/openfoam6/src/meshTools/lnInclude
/opt/openfoam6/src/OpenFOAM/lnInclude
/opt/openfoam6/src/OSspecific/POSIX/lnInclude
$ pwd
/home/of/OpenFOAM/of-6/solver/icoFoam可以看到,这里的路径主要都是
lnInclude
,其中的文件都是软链接,指向各个文件的真实路径。
-
File → Open Folder
,打开最后返回的路径:/home/of/OpenFOAM/of-6/solver/icoFoam
。 -
按
F1
或Ctrl+Shift+p
打开命令面板,然后输入C++ UI
,找到C/C++ Configurations (UI)
,打开。在其中的includePath中添加前面得到的-I
路径:
至此,就能实现代码提示和跳转了:
3 调试篇
以自定义求解器myicoFoam
求解器为例。
3.1 单版本调试
参考视频:VS Code调试OpenFOAM
- 在VSCode中按
win+`
键(左上角同~
键)打开集成的终端。
-
加载OpenFOAM环境,拷贝求解器:
注:假设这里是在
~/.bashrc
中直接source来激活OpenFOAM环境;对于多版本OF调试,即通过alias激活对应环境的情况,后面再讨论。1
2
3
4# $HOME/.bashrc设置
# alias of6=". /opt/openfoam6/etc/bashrc"
source /opt/openfoam6/etc/bashrc #默认打开终端就激活OF环境
alias of8=". /opt/openfoam8/etc/bashrc"1
2
3$ mkdir -p $WM_PROJECT_USER_DIR/solver
$ cp -r $FOAM_SOLVERS/incompressible/icoFoam $WM_PROJECT_USER_DIR/solver/
$ cd $WM_PROJECT_USER_DIR/solver/icoFoam -
修改
Make/files
:1
2
3icoFoam.C
EXE = $(FOAM_USER_APPBIN)/myicoFoam -
修改
Make/options
:1
2
3
4
5
6
7
8EXE_INC = \
-g \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-lmeshTools注意:这里必须额外添加
-g
选项。 -
通过
wmake
查看真实调用的编译命令,从中提取-I
指向的路径用于后续配置includePath:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20$ wmake | tee log.wmake
Making dependency list for source file icoFoam.C
g++ -std=c++11 -m64 -Dlinux64 -DWM_ARCH_OPTION=64 -DWM_DP -DWM_LABEL_SIZE=32 -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -O3 -DNoRepository -ftemplate-depth-100 -g -I/opt/openfoam6/src/finiteVolume/lnInclude -I/opt/openfoam6/src/meshTools/lnInclude -IlnInclude -I. -I/opt/openfoam6/src/OpenFOAM/lnInclude -I/opt/openfoam6/src/OSspecific/POSIX/lnInclude -fPIC -c icoFoam.C -o Make/linux64GccDPInt32Opt/icoFoam.o
g++ -std=c++11 -m64 -Dlinux64 -DWM_ARCH_OPTION=64 -DWM_DP -DWM_LABEL_SIZE=32 -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -O3 -DNoRepository -ftemplate-depth-100 -g -I/opt/openfoam6/src/finiteVolume/lnInclude -I/opt/openfoam6/src/meshTools/lnInclude -IlnInclude -I. -I/opt/openfoam6/src/OpenFOAM/lnInclude -I/opt/openfoam6/src/OSspecific/POSIX/lnInclude -fPIC -Xlinker --add-needed -Xlinker --no-as-needed Make/linux64GccDPInt32Opt/icoFoam.o -L/opt/openfoam6/platforms/linux64GccDPInt32Opt/lib \
-lfiniteVolume -lmeshTools -lOpenFOAM -ldl \
-lm -o /home/of/OpenFOAM/of-6/platforms/linux64GccDPInt32Opt/bin/myicoFoam
$ cat log.wmake | sed 's/ /\n/g' | grep '\-I' | sort | uniq | sed 's/\-I//g'
.
lnInclude
/opt/openfoam6/src/finiteVolume/lnInclude
/opt/openfoam6/src/meshTools/lnInclude
/opt/openfoam6/src/OpenFOAM/lnInclude
/opt/openfoam6/src/OSspecific/POSIX/lnInclude
$ pwd
/home/of/OpenFOAM/of-6/solver/icoFoam
$ which myicoFoam
/home/of/OpenFOAM/of-6/platforms/linux64GccDPInt32Opt/bin/myicoFoam注意wmake实际调用的命令中新增了
-g
选项,说明把该选项写在Make/options
的EXE_INC
中是有效的(虽然EXE_INC
的原本目的是用来指定includePath)。这里要用到的路径是后面4个lnInclude
路径以及pwd
返回的icoFoam求解器路径。此外,通过which
命令来获取编译得到的myicoFoam
路径,因为调试的时候通常是在算例目录下。
2021-01-08 20:13:05 更新(点击展开)
更准确的做法应该是通过环境变量WM_COMPILE_OPTION
来控制。 即在拷贝求解器后只需要修改Make/files
更改一下可执行文件的路径以及名称,然后终端运行WM_COMPILE_OPTION=Debug
将默认的Opt
编译模式切换成Debug
模式。然后wmake即可以调试模式编译求解器。
说明:
终端运行echo $WM_COMPILE_OPTION
可以发现该变量的值默认为Opt
, 其定义的位置在OpenFOAM的环境加载文件中(即$WM_PROJECT_DIR/etc/bashrc
中), 可以取值Opt
、Debug
以及Prof
,分别表示优化(optimised),调试(debug)和分析(profiling)。 wmake会根据变量$WM_COMPILE_OPTION
的值来加载不同的选项。 $WM_PROJECT_DIR/wmake/rules/linux64Gcc/c++
文件中包含语句include $(DEFAULT_RULES)/c++$(WM_COMPILE_OPTION)
, 分别可能加载c++Opt
、c++Debug
和c++Prof
文件中的选项设置。这3个文件所包含的内容如下:
1 | # $WM_PROJECT_DIR/wmake/rules/linux64Gcc/c++Opt |
可以看到c++Debug
文件中开启了-ggdb3
,类似于-g
选项,用于开启编译功能。
c++Prof
中开启-pg
选项,编译后的程序可以使用gperf之类的工具进行性能分析。
而默认的c++Opt
中-O3
则最大限度地优化程序。
-
拷贝测试算例,并通过
File → Open Folder
在VSCode中打开测试算例:1
2
3
4
5
6$ mkdir -p $WM_PROJECT_USER_DIR/run
$ run
$ cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity .
$ cd cavity
$ pwd
/home/of/OpenFOAM/of-6/run/cavity -
Ctrl+Shift+D
打开左侧的调试面板(Run
),点击create a launch.json file
创建launch.json
文件
-
修改
launch.json
文件:1
2
3
4...
"program": "/home/of/OpenFOAM/of-6/platforms/linux64GccDPInt32Opt/bin/myicoFoam",
...
"stopAtEntry": true,program
的值即为自定义求解器的路径,通过which myicoFoam
获得,而stopAtEntry
设为true
能在main函数处默认设置一个断点。 -
按
F1
或Ctrl+Shift+p
打开命令面板,然后输入C++ UI
,找到C/C++ Configurations (UI)
,打开。在其中的includePath中添加前面得到的-I
路径以及求解器源码路径(注意与前一节有点差别)。
-
生成网格,按F5键开始调试。
3.2 多版本调试
以上是单OpenFOAM版本,实际场景中经常会安装多个版本,通过alias在各个版本之间切换,那以上调试方法还适用吗?
通过各种尝试折腾,终于想到了一个巧妙的解决方案,即通过包装一个新的gdb脚本来实现,具体方案如下。
讨论两个版本的情况:
-
$HOME/.bashrc
配置如下:1
2alias of6=". /opt/openfoam6/etc/bashrc"
alias of8=". /opt/openfoam8/etc/bashrc" -
创建一个目录专门用于存放脚本,比如
~/OFdebug
:1
2
3
4$ mkdir -p ~/OFdebug
$ cd OFdebug
$ touch of6-gdb.sh && chmod +x of6-gdb.sh
$ touch of8-gdb.sh && chmod +x of8-gdb.sh两个脚本的内容分别为:
of6-gdb.sh
:1
2
3
. /opt/openfoam6/etc/bashrc
/usr/bin/gdb "$@" # 将脚本接受的参数传给gdb命令of8-gdb.sh
:1
2
3
. /opt/openfoam8/etc/bashrc
/usr/bin/gdb "$@" # 将脚本接受的参数传给gdb命令 -
修改
launch.json
文件,通过miDebuggerPath
指定编译器自定义的gdb脚本路径,比如使用of6来调试:1
2
3...
"miDebuggerPath": "/home/of/OFdebug/of6-gdb.sh",
... -
调试cavity算例:
1
2
3
4
5
6of6 # 激活环境
run
cd cavity
foamCleanTutorials # 清理算例
blockMesh # 生成网格
# ... 开始调试
4 相关参考
在研究gdb调试之前,主要尝试的就是gdbOF[1],能方便地将求解过程中的变量导出到文件,具体应用可以看[2]的介绍。目前OpenFOAMwiki上介绍适配的最高版本是OF5.x。
gdbOF is an attachable to GNU debugger (gdb) tool that includes macros to debug OpenFOAM’s solvers and applications in an easier way.
另一个角度,[3]介绍了如何使用gdbserver调试。
使用 VS Code 调试远程服务器上的 OpenFOAM 代码。
花了不少时间折腾,写作不易,希望能帮到学习OpenFOAM的小伙伴!