1

我在一个 FORTRAN 代码项目中工作,其中编译决策在两个文件中进行:一个头文件 ( definitions.h),它包含在相关的 FORTRAN 文件中,以及makefile. 例如,编译器、一些库集和允许的并行化类型(MPI、OpenMP 或无)在 中选择makefile,并且代码的某些部分的包含由#define标头中的指令控制。

  1. 我不喜欢编辑两个不同的文件来设置编译。有更好的方法吗?

  2. 此外,makefiledefinitions.h文件都处于修订控制之下。这意味着我那些粗心的开发人员提交并推送了两个文件的新版本,他们只更改了启用的编译选项,因此污染了版本控制历史。理想情况下,至少makefile不必编辑最大的文件( )来设置编译选项。

  3. 在某些情况下,会发生不一致。通常,在 中选择的某些库组合与指令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 预处理器在解析标头后获取变量的值。

4

1 回答 1

0

如果您的策略是在不带标志或参数的情况下运行 Make,您仍然可以通过将相关开关放在 makefile 将执行的附加文件(不受版本控制)中来省去一些麻烦include

正如您所说,使用 Make 解析源文件既丑陋又困难。维护是一场噩梦。我建议将两个版本的definitions.h版本控制在不同的目录中;选择库的相同Make逻辑可以选择头文件。

我不知道当你的头文件与库“不兼容”时你会遇到什么样的错误,但如果库有不同的接口,你可能可以通过放入一些特定于库的调用来故意调用编译器错误头文件。(如果他们没有不同的接口,你似乎有一些糟糕的依赖于实现的行为。)

最后,如果“几分钟”对于等待这样的编译器错误来说太长了,那么你肯定经常犯这样的错误——你可能想看看你的程序。(此外,如果您只修改了一个或两个文件,那么构建不应该花费那么长时间 - 是的,每天构建,但不是您每小时执行几次的那种。)

于 2013-03-20T19:29:50.507 回答