如何动态包含makefile?

时间:2010-11-03 16:44:03

标签: makefile aix

是否可以动态包含Makefile?例如,取决于一些环境变量?我有以下Makefile:

makefile
app1.1.mak
app1.2.mak

还有一个环境变量APP_VER,可以设置为1.1.0.1,1.1.0.2,1.2.0.1,1.2.0.2。 但是1.1和1.2行只有两个不同的makefile。

我曾尝试编写以下Makefile:

MAK_VER=$$(echo $(APP_VER) | sed -e 's/^\([0-9]*\.[0-9]*\).*$$/\1/')  
include makefile$(MAK_VER).mak  

all: PROD  
        echo MAK_VER=$(MAK_VER)  

但它不起作用:

$ make all
"makefile$(echo", line 0: make: Cannot open makefile$(echo
make: Fatal errors encountered -- cannot continue.

更新

据我所知,make在计算宏之前包含文件 这就是为什么它试图执行以下语句

include makefile.mak

而不是

include makefile1.1.mak

3 个答案:

答案 0 :(得分:2)

您有两个问题:获取版本的方法过于复杂,而您的include行存在缺陷。试试这个:

include app$(APP_VER).mak

如果APP_VER是环境变量,那么这将有效。如果你还想要包含名为makefile的makefile(也就是说,如果makefile不是我们正在写的那个),那么试试这个:

include makefile app$(APP_VER).mak

请注意,这被视为坏主意。如果makefile依赖于环境变量,它将适用于某些用户,而不适用于其他用户,这被认为是不良行为。

修改:

这应该这样做:

MAK_VER := $(subst ., ,$(APP_VER))
MAK_VER := $(word 1, $(MAK_VER)).$(word 2, $(MAK_VER))

include makefile app$(MAK_VER).mak

答案 1 :(得分:0)

试试这个:

MAK_VER=$(shell echo $(APP_VER) | sed -e 's/^\([0-9]*\.[0-9]*\).*$$/\1/')
MAK_FILE=makefile$(MAK_VER).mak

include $(MAK_FILE)

all:
    echo $(MAK_VER)
    echo $(MAK_FILE)

答案 2 :(得分:0)

修改大纲解决方案

有四个makefile:

  • 生成文件
  • app1.1.mak
  • app1.2.mak
  • appdummy.mak

app.dummy.mak makefile可以为空 - 如果你愿意,可以是/ dev / null的符号链接。 app.1.1.mak和app.1.2.mak都不会改变其当前内容。

主makefile稍有改动:

MAK_VER = dummy
include makefile$(MAK_VER).mak  

dummy:  
        ${MAKE} MAK_VER=$$(echo $(APP_VER) | sed -e 's/^\([0-9]*\.[0-9]*\).*$$/\1/') all

all: PROD
        ...as now...

如果键入make,它将读取(空)虚拟makefile,然后尝试构建dummy目标,因为它首先出现。要构建虚拟目标,它将再次运行make,在命令行上使用APP_VER=1.1APP_VER=1.2

make APP_VER=1.1 all

在命令行中设置的宏不能在makefile中更改,因此这将覆盖makefile中的行。因此,make的第二次调用将读取正确的特定于版本的makefile,然后构建all

这种技术有局限性,最明显的是,安排每个目标都像这样处理是很繁琐的。有很多方法,但通常不值得。


项目组织

更严重的是,我认为你需要回顾一下你正在做什么。据推测,您可以使用版本控制系统(VCS)来管理源代码。此外,据推测,1.1版和1.2版源代码之间存在一些(重大)差异。因此,为了能够为版本1.1进行构建,您必须从版本1.1维护分支切换到版本1.2开发分支,或者沿着这些行转换。那么,为什么makefile只为1.1或1.2版本化?如果在版本之间切换,则需要清除可能使用错误源构建的所有派生文件(目标文件,库,可执行文件等)。您必须更改源代码。那么为什么不改变makefile呢?

用于调用make

的构建脚本

我还观察到,由于你有环境变量APP_VER驱动你的过程,你可以通过要求标准化的'make invoker'来排除APP_VER值并正确调用make来解决问题。想象一下,该脚本名为build

#!/bin/sh
: ${APP_VER:=1.2.0.1}  # Latest version is default
case $APP_VER in
[0-9].[0-9].*)
    MAK_VER=`echo $APP_VER | sed -e 's/^\(...\).*/\1/'`
    ;;
*)  echo "`basename $0 .sh`: APP_VER ($APP_VER) should start with two digits followed by dots" 1>&2;
    exit 1;;
esac
exec make MAK_VER=$MAK_VER "$@"

此脚本验证APP_VER已设置,如果不是,则给出相应的默认值。然后它处理该值以导出MAK_VER(如果不正确则输出错误)。当然,当您达到第10版时,您需要修改该测试,因为您计划如此成功,以便在适当的时候达到两位数的版本号。

鉴于版本信息正确,您现在可以使用任何命令行参数调用您的makefile。

makefile非常简单:

MAK_VER = dummy

include app$(MAK_VER).mak  

all: PROD
        ...as now...

appdummy.mak文件现在包含一条规则:

error:
        echo "You must invoke this makefile via the build script" 1>&2
        exit 1

它只是指出了构建的正确方法。

请注意,如果将产品版本号保留在文件中的VCS下,则可以避免使用APP_VER环境变量,然后脚本会从文件中读取版本号。并且脚本可以完成各种其他工作,确保安装正确的工具,设置其他环境变量等等。