我在FORTRAN代码项目中工作,其中编译决策采用两个文件:头文件(definitions.h
),它包含在相关的FORTRAN文件中,以及makefile
。例如,在makefile
中选择了编译器,一些库集以及允许的并行化类型(MPI,OpenMP或无),并且{{1}控制了代码的某些部分的包含标题中的指令。
我不喜欢编辑两个不同的文件来设置编译。有更好的方法吗?
此外,#define
和makefile
文件均受版本控制。这意味着我的粗心开发人员提交并推送两个文件的新版本,他们只更改了启用的编译选项,因此污染了版本控制历史记录。理想情况下,至少不需要编辑最大的文件(definitions.h
)来设置编译选项。
在某些情况下,会出现不一致的情况。通常,makefile
中选择的某些库组合与makefile
指令选择的某些代码段不兼容。有没有办法正确检查?
例如,为了停止编译,如果#define
(LIB1=LIBFOO
)和makefile
定义为bar
(在头文件中),我试图停止编译跟随1
makefile
但是(a)这是非常难看的,(b)显然它根本不起作用。如何解决这个问题?
我在3.上工作,我觉得我有一个答案:我添加一个新的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
目标,.PHONY
,这是其他相关目标的必备条件,并且读取
ini_check
请注意,现在我使用C预处理器在解析标头后获取变量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..."
的值。
答案 0 :(得分:0)
如果你的策略是运行没有标志或参数的Make,你仍然可以通过将相关的开关放在一个附件文件(不是版本控制下)中来保存自己一些悲伤,makefile将{{ 1}}。
正如您所说,使用Make解析源文件,正如您所说,既丑又难。维持这是一场噩梦。我建议在版本控制下将两个版本的include
保存在不同的目录中;相同的make选择库的逻辑可以选择头文件。
我不知道当你的头文件与库“不兼容”时你会得到什么样的错误,但如果库有不同的接口,你可以通过放置一些库来故意调用编译器错误 - 头文件中的特定调用。 (如果它们没有不同的接口,那么您似乎有一些不良的依赖于实现的行为。)
最后,如果“几分钟”太长而无法等待这样的编译器错误,那么你必须经常犯这样的错误 - 你可能想查看你的程序。 (另外,如果你只修改了一个或两个文件,那么构建不应该花那么长时间 - 每天构建,是的,但不是你每小时做几次的那种。)