找回密码
 注册
查看: 5986|回复: 2

[转载]openFOAM基础--编译applications和libraries

[复制链接]
发表于 2009-2-10 23:43:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
openFOAM是一个库,用户在编程时需要调用此库,当然用的语言是面向对象的c++语言。在使用openFOAM时我们应该将关注点放在顶层使用类以及数值算法上,这就需要对openFOAM Library的调用机制有一个详细的了解。并且由于我们在使用c++语言编程,因此需要对c++的编译过程有所了解。

关于编译器,我们可以直接使用LINUX自带的make程序,但openFOAM又提供了一个编译程序wmake,它建立在make的基础上,但比make更强大和简单。并且wmake不仅可以用于openFOAM library,而且可以用于任何c++代码。

openFOAM中的类,本质上是c++的class,都定义在.c文件中,这些文件在用编译器进行编译之后会生成.so文件(可执行的二进制文件),形成库(library)。openFOAM在提供时都已经生成了.so文件,因此当我们编译一个调用了某class(该class所在文件为 nc.c)的程序app.c时,nc.c不会被重新编译,而是调用直接调用nc.so文件。这种机制称为“动态链接”。而如果对某.c文件进行了修改,则重新编译之后才会生效。

c++中,我们在使用一个变量或者对象时,必须确保该变量或对象已经存在,这就需要进行声明。在使用类时同样需要事先声明,这些对类的声明都包装在.h文件中,我们称之为头文件(header file)。头文件中声明的类一定要能在库中找到,这就要求声明的类与.c文件中定义的类相一致。头文件都必须以#include "xx.h"的形式被“包含”在使用了该头文件的c文件中(.c或.h文件)。一个c文件要想使用某个类,则必须在文件的开始将声明了该类的.h文件包含进来。这样一来,我们在编译一个程序的时候,可以通过“递归搜索”找到一系列的.h文件名,我们把这些.h文件称为dependences,而这一系列文件名也就是一个dependence list。编译器会判断这个list中的各个.h文件在最后一次进行编译之后是否被修改过,如果修改了,则从新编译,如果没有被修改,那么不再编译。然后,编译器会根据.h文件中的声明和程序中的调用情况在库中找到想要的代码,进而链接出可执行文件来。一方面,只有有了.h文件,我们在写程序代码时才能保证用到的类都是声明过的;另一方面,只有有了.h文件中的声明,我们才能在库中找到自己需要的东西,从这个角度来讲,h文件可以看作是库的接口。

(.h文件的用途不仅仅是用来做class declaration。当某程序代码需要调用本身的时候,通常为了增加程序的可读性,也会选择.h文件来组织文件结构。)

编译工作都是由wmake完成的。有了前面的这些概念介绍,我们可以再来看一看wmake的功能和特点:
  1、自动生成和维护dependency list
  2、多平台编译和链接,
  3、多语言编译和链接,e.g. C, C++, Java.
  4、多功能(multi-option)编译和链接,e.g. debug, optimised, parallel and profiling
  5、Support for source code generation programs, e.g. lex, yacc, IDL, MOC.
  6、Simple syntax for source file lists.
  7、自动生成新代码的源文件列表
  8、Simple handling of multiple shared or static libraries.
  9、Extensible to new machine types.
  10、Extremely portable, works on any machine with: make; sh, ksh or csh; lex, cc.
  11、Has been tested on Apollo, SUN, SGI, HP (HPUX), Compaq (DEC), IBM (AIX),
Cray, Ardent, Stardent, PC Linux, PPC Linux, NEC, SX4, Fujitsu VP1000.

很多功能我们先不管它,现在我们知道wmake可以用来编译和链接程序、并且给出一个可执行文件就行了。我们关注的有这些内容:
    1)在程序中包含的头文件。wmake需要能找到他们。“包含哪些头文件”在代码中已经说明,“这些头文件在哪”则需要进行说明。
    2) 程序需要载入的库,wmake也需要能找到他们。(光有.h文件是不够的,我们最终用的是库,.h文件中声明的东西都在这里面)“包含哪些库”和“这些库在哪”都需要进行说明。
    3)生成的可执行文件。“生成到哪”需要说明。
以上各个需要进行说明的地方都是通过程序目录下的make/options和make/files文件实现的。后面会有详细的介绍。我们逐项看一看上面的三条内容:

(一)

wmake首先要生成dependency list,然后搜索这些文件。对openFOAM而言,wmake搜索的顺序如下:
  1)$WM_PROJECT_DIR/src/OpenFOAM/lnInclude
  2)当前目录下的lnInclude文件夹
  3)当前文件夹
  4)platform dependent paths set in files in the $WM PROJECT DIR/wmake/rules/-
$WM ARCH/ directory, e.g. /usr/X11/include and $(MPICH ARCH PATH)/include
  5)其他在make/opptions文件中用-I命令给出的路径。(*编译时需要在主程序目录中有make文件夹,内有options、files文件,用以指明wmake命令的参数)。路径指出方法为:
    EXE_INC = \
       -I<directoryPath1> \
       -I<directoryPath2> \
       ... \
       -I<directoryPathN>
  

(二)

然后,wmake需要进行“链接”。链接的过程也就是根据头文件中的声明在库中寻找有用代码,然后植入应用程序的过程。当然我们不可能在整个计算机中进行寻找,这样一来就要限定范围:一是搜寻的范围,二是到底载入哪些库。这些事情并不一定全要用户指定,因为有些事情wmake默认就帮我们做了,下面还是先看看基本情况。

搜索范围:wmake在链接到共享对象库(shared object library)时按以下路径顺序进行搜索(指定路径的命令为-L):
  1)$FOAM_LIBBIN 路径
  2)platform dependent paths set in files in the $WM DIR/rules/$WM ARCH/ directory,
e.g. /usr/X11/lib and $(MPICH ARCH PATH)/lib
  3)其他由 Make/options 文件指定的路径。

载入的库:如果想载入某库,则要被链接的文件(.so文件,在windows下为.dll文件)需要用-l命令指出时,此时需要去掉前缀(prefix)lib和后缀.so。举例:libnew.so文件在被链接时的命令为"-lnew"。默认情况下,wmake会载入下面的 libraries:
  1)$FOAM LIBBIN 目录下的libOpenFOAM.so
  2)platform dependent libraries specified in set in files in the $WM DIR/rules/$WM ARCH/
directory, e.g. libm.so from /usr/X11/lib and liblam.so from $(LAM ARCH PATH)/lib
  3)其他在Make/options 文件中指定的库

可以想见,要想链接某库,则其必须在库路径的搜索范围内。除了默认搜索的路径和默认载入的库,其他路径或库都可以在Make/options 文件中(同前所述)用下面的方法定义:
  EXE_LIBS = \
     -L<libraryPath1> \
     -L<libraryPath2> \
     ... \
     -L<libraryPathN> \
     -l<library1> \
     -l<library2> \
     ... \
     -l<libraryN>

有了编译和链接,就可以生成可执行文件了。可执行文件是在Make/Files 文件中用"EXE="指出的,标准习惯取为与工程名(亦即主程序名、主程序文件名)同名。至于存放目录也有约定俗成的习惯:openFOAM提供的标准应用程序(standard released applications)放在$FOAM_APPBIN,用户自己开发的应用程序放在FOAM_USER_APPBIN。至于用户如何组织自己的代码存放,完全可以参考openFOAM提供的标准库的存放方式。好的习惯可以使程序层次更加清晰,便于管理。

此外,从上面的介绍可以看出c++面向对象编程思想中需要借鉴的习惯,那就是:将代码都封装到类中,然后编译为库,用头文件来做接口,在使用时以头文件为纽带、编译时用限制参数选择库,对库中有用的内容进行调用。
本文转自http://blog.pfan.cn/bioexplore/33160.html
发表于 2009-9-29 00:13:12 | 显示全部楼层
好眼熟..这个不是我三年前写的么,现在看来写的太罗嗦了

btw:转载的出处不是本人的博客
发表于 2010-4-4 08:55:14 | 显示全部楼层
呵呵,来索要版权了。版主快出来回应
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表