是否有一种可移植的方法在Makefile中创建可移植的optionnal依赖?

时间:2016-11-23 19:37:45

标签: c makefile internationalization

使用Lua-i18n,我正在尝试更改Makefile,以便用户可以使用他们感兴趣的工具编译项目,即Makefile定义一些将禁用相应代码的C宏。在Makefile中定义它是直截了当的,但是当定位可移植性时,摆脱与这样定义的特征相关联的不必要的编译依赖性是不那么简单的。实际上,该项目旨在尽可能少地修改原始代码,并尽可能少地添加依赖项(可能没有)。

以下是过程中找到的一些相关链接

这是一个似乎可以在带有GNU Make的Fedora 24桌面上运行的解决方案。但是,我想知道这样的解决方案是否适用于任何(合理的现代化)make实现

cflag= -D CODE_SWITCH
resolved_conditional_cflag!= test -n "$(cflag)" && echo "$(cflag)"
conditional_dep= additional_dep.c
mandatory_dep= dep0.c dep1.c
resolved_conditional_dep!= test -n "$(cflag)" && echo "$(conditional_dep)"
all_dep= $(mandatory_dep) $(resolved_conditional_dep)
all: target
    @echo building code with flag $(resolved_conditional_cflag) 
    @echo ${SHELL}
target: $(all_dep)
    @echo building $@ which depends on $(all_dep)
dep0.c:
    @echo building dep0.c
dep1.c:
    @echo building dep1.c
additional_dep.c:
    @echo building $@

我们的想法是用户对行cflag= -D CODE_SWITCH进行注释,而这就是全部,编译器不会处理相关的依赖项。那么,这样的解决方案是否可移植?它依赖于shell扩展!=test命令。我认为最后一个可能是POSIX,但我可能错了。更一般地说,它们可能是我在这里不知道的可移植性问题。

请注意,对于此特定需求,“使用CMake,autotools或其他”并非理想的答案。

1 个答案:

答案 0 :(得分:1)

!=仅适用于GNU make 4.0及以上版本。它也不是POSIX;它被添加到GNU make中以便与BSD make一起使用,并且它被建议包含在POSIX规范中,但它现在还没有被接受。

我不知道有任何方法只使用纯粹的可移植make(POSIX)来根据make宏的内容更改目标的先决条件。

如果您愿意接受GNU make,那么(至少现在)使用$(shell ...)比使用!=更容易。虽然如果你假设GNU make有更好的方法来处理它,根本不需要shell。如果您想使用!=来获得BSD make的可移植性,请务必在您的文档中添加一个需要GNU make 4.0或更高版本的注释。

N.B。,在makefile中不要在变量名和赋值运算符之间放置空格通常是个坏主意。例如最好写FOO != bar,而不是FOO!=barFOO!= bar

修改

Chrono Kitsune讨论的一个选择是使用一些递归;它看起来像这样:

cflag= -D CODE_SWITCH

conditional_dep= additional_dep.c
mandatory_dep= dep0.c dep1.c

all_dep= $(mandatory_dep)
all: target
        @echo building code with flag $(cflag) 
        @echo ${SHELL}
target: $(mandatory_dep)
        @all_dep='$^'; if test -n "$(cflag)"; then \
            all_dep='$^ $(conditional_dep)'; \
            $(MAKE) $(conditional_dep); \
         fi; \
        echo building $@ which depends on $$all_dep
dep0.c:
        @echo building dep0.c
dep1.c:
        @echo building dep1.c
additional_dep.c:
        @echo building $@

另一种选择,如果你不必依赖于评论cflag本身,就会使用递归变量命名;看起来像这样:

SWITCH = enabled

enabled_cflag = -D CODE_SWITCH
enabled_dep = additional_dep.c

mandatory_dep = dep0.c dep1.c

cflag = $($(SWITCH)_cflag)
all_dep = $(mandatory_dep) $($(SWITCH)_dep)

all: target
        @echo building code with flag $(cflag) 
        @echo ${SHELL}
target: $(all_dep)
        echo building $@ which depends on $(all_dep)
dep0.c:
        @echo building dep0.c
dep1.c:
        @echo building dep1.c
additional_dep.c:
        @echo building $@

现在,如果您注释掉SWITCH设置,或者在make命令行上将其设置为空,那么这些元素将会被关闭(因为$($(SWITCH)_cflag)会扩展非存在/空变量_cflag不是enabled_cflag)。大多数make版本都支持递归变量命名(但不是全部)。