|
如题。在昨天的帖子(http://bbs.keinsci.com/forum.php ... 5906&extra=page%3D1)里提到如果软件太新,编译或运行时就可能出问题。现在把这个问题写下来,以后可能其他人也会碰到。
在主力服务器上编译软件,为了运行效率一般用Intel编译器。而自己电脑一来不适合干重活,二来装编译器太麻烦,因此一般用自带的GCC。比较保守的服务器用发行版如CentOS,现在还在用 GCC 4.x,而桌面用发行版(Ubuntu/Fedora)早已飙到了6.x。昨天在Fedora 25下编译BerkeleyGW一直报错,一开始是预处理错误,改了预处理选项之后是编译错误。查了好久才发现原来是GCC 6.x的预处理器cpp默认行为和4.x不一样了。
为了适应不同的硬件和软件环境,软件源码中会包含大量预处理指令。gfortran没有单独的预处理器,借用的是C语言预处理器cpp。问题是C语言的处理器对FORTRAN源码有些水土不服,比如//在C++中会被当作注释直接移除,而FORTRAN中是有效代码。所幸cpp有-C选项,可以保留所有注释。但问题也就出在这里。
对于GCC 4.x,cpp -C只会展开宏和处理一些条件编译指令,不会画蛇添足。但对于GCC 6.x,cpp -C会在源码中插入glibc的权责声明。这些声明用的是C风格的区块注释。Fortran源码中插入C的注释,自然就报错了。
翻遍GCC手册也没找到选项能禁用这一特性。最后想了个权宜之计:写一个python程序移除C风格注释;再修改Makefile,在预处理命令和编译命令之间新加一步操作。
#--------------------------- workarond for GCC > 4.x -----------------------
#clang C-preprocessing treats files incorrectly if they have .F90 extension
ifeq ($(findstring clang,$(FCPP)),clang)
f90_CPP = cp $(basename $<).f90 $(basename $<)_cp.F90; $(FCPP) $(INCLUDE) $(CPPOPT) $(basename $<)_cp.F90 > $(basename $<).p.f; $(REMOVE) $(basename $<)_cp.F90
else
f90_CPP = $(FCPP) $(INCLUDE) $(CPPOPT) $< > $(basename $<).p.f; $(PREFIX)/rmcmt.py $(basename $<).p.f
endif
F90_CPP = $(FCPP) -P $(INCLUDE) $(CPPOPT) $< > $(basename $<).p.f; $(PREFIX)/rmcmt.py $(basename $<).p.f
#-----------------------------------------------------------------------------------
修改之后,编译通过。
后记:以后碰到新事物,先让别人去探探地雷
|
评分 Rate
-
查看全部评分 View all ratings
|