我在一个 FORTRAN 代码项目中工作,其中编译决策在两个文件中进行:一个头文件 ( definitions.h
),它包含在相关的 FORTRAN 文件中,以及makefile
. 例如,编译器、一些库集和允许的并行化类型(MPI、OpenMP 或无)在 中选择makefile
,并且代码的某些部分的包含由#define
标头中的指令控制。
我不喜欢编辑两个不同的文件来设置编译。有更好的方法吗?
此外,
makefile
和definitions.h
文件都处于修订控制之下。这意味着我那些粗心的开发人员提交并推送了两个文件的新版本,他们只更改了启用的编译选项,因此污染了版本控制历史。理想情况下,至少makefile
不必编辑最大的文件( )来设置编译选项。在某些情况下,会发生不一致。通常,在 中选择的某些库组合与指令
makefile
选择的某些代码部分不兼容#define
。有什么方法可以正确检查吗?例如,为了停止编译如果
LIB1=LIBFOO
(在 中makefile
)并且bar
被定义为1
(在头文件中),我在makefile
ifeq ($(LIB1), LIBFOO) bar_status:=`grep -i '^[[:space:]]*\#define[[:space:]]*bar[[:space:]]*[[:digit:]]' definitions.h | tail -n1 | grep -ic '^[[:space:]]*#define[[:space:]]*bar[[:space:]]*1[[:space:]]*'` ifeq ($(bar_status), 1) $(error ERROR: You are trying to compile the code with bar enabled in definitions.h, but this is incompatible with the library LIBFOO selected in the makefile) endif endif
但是(a)这非常丑陋,并且(b)显然它根本不起作用。如何解决这个问题?
我在 3. 上工作,我想我有一个答案:我添加了一个新.PHONY
目标 ,ini_check
这是其他相关目标的必要条件,并读取
ifeq ($(LIB1), LIBFOO)
bar_value:=$(shell echo bar | cat definitions.h - | gcc -E -undef - 2>/dev/null | tail -n1)
endif
ini_check:
ifeq ($(LIB1), LIBFOO)
ifeq ($(bar_value), 1)
$(error ERROR: You are trying to compile the code with bar enabled in definitions.h, but this is incompatible with the library LIBFOO selected in the makefile)
endif
endif
@echo "Done with the initial check, starting compilation..."
bar
请注意,现在我使用 C 预处理器在解析标头后获取变量的值。