如何动态地包含makefile?

如何动态地包含makefile?,makefile,aix,Makefile,Aix,是否可以动态包含makefile?例如,取决于某些环境变量?我有以下生成文件: makefile app1.1.mak app1.2.mak 还有一个环境变量APP\u VER,可以设置为1.1.0.1、1.1.0.2、1.2.0.1、1.2.0.2。 但是对于1.1和1.2行,只有两个不同的makefile 我已尝试编写以下生成文件: MAK_VER=$$(echo $(APP_VER) | sed -e 's/^\([0-9]*\.[0-9]*\).*$$/\1/') include

是否可以动态包含makefile?例如,取决于某些环境变量?我有以下生成文件:

makefile
app1.1.mak
app1.2.mak
还有一个环境变量
APP\u VER
,可以设置为1.1.0.1、1.1.0.2、1.2.0.1、1.2.0.2。
但是对于1.1和1.2行,只有两个不同的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
试试这个:

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)
include app$(APP_VER).mak

您有两个问题:获取版本的方法太复杂,并且
include
行有缺陷。试试这个:

include app$(APP_VER).mak
如果
APP\u 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.1.mak
  • 附录1.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\u VER=1.1
APP\u 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\u VER驱动您的流程,因此您可以通过要求一个标准化的“make invoker”来解决问题,该“make invoker”可以整理APP\u 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 "$@"
此脚本验证是否设置了应用程序版本,如果未设置,则提供适当的默认值。然后,它处理该值以导出MAK\u 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\u VER环境变量。脚本还可以完成各种其他工作,确保安装了正确的工具,设置了其他环境变量,等等。

$export APP\u VER=1.1;生成所有“makefile”,第0行:make:无法打开makefile遇到make:致命错误--无法继续。上面发布的makefile有效(不会生成您显示的错误)。在不深入了解具体情况的情况下,关键部分是前三行,它们将shell命令的输出收集到一个变量中,“动态”创建makefile名称,然后将其包含在内。您的意思是说
APP\u VER
可能设置为“1.1”或“1.2”,还是可能设置为“1.1version”或“1.2vladimir”“简单makefile”是否与
makefile
相同,或者与另一个可以设置为1.1.0.1、1.1.0.2、1.2.0.1、1.2.0.2的测试版相同。但是对于1.1和1.2行,只有两个不同的makefile。请阅读更新。APP\u VER可以设置为1.1.0.1、1.1.0.2、1.2.0.1、1.2.0.2等。但是我需要不同的make文件用于1.1和1.2行。不幸的是,我的make版本(用于AIX)既不支持subst函数也不支持word函数。@Vladimir Bezugliy:它支持
$(shell…
)吗?不支持。我决定使用以下方法:INNER\u MAKEFILE=$(MAKEDIR)/MAKEFILE$(APP\u VER)。在AIX上,您要么需要设置环境变量,要么需要一些技术,例如将正确的特定于版本的makefile链接到始终包含的固定名称。(除非你在两者之间切换,否则效果很好