如何动态包含makefile?
是否可以动态包含 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
Is it possible to include Makefiles dynamically? For example depending on some environment variable? I have the following Makefiles:
makefile
app1.1.mak
app1.2.mak
And there is an environment variable APP_VER
which could be set to 1.1.0.1, 1.1.0.2, 1.2.0.1, 1.2.0.2.
But there will be only two different makefiles for 1.1 and 1.2 lines.
I have tried to write the following 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)
But it does not work:
$ make all
"makefile$(echo", line 0: make: Cannot open makefile$(echo
make: Fatal errors encountered -- cannot continue.
UPDATE:
As far as I understand make
includes files before it calculates macros.
That's why it tries to execute the following statement
include makefile.mak
instead of
include makefile1.1.mak
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您有两个问题:您获取版本的方法太复杂,并且您的
include
行有缺陷。试试这个:如果 APP_VER 是一个环境变量,那么这将起作用。如果您还想包含名为
makefile
的 makefile(即,如果makefile
不是我们正在编写的文件),请尝试以下操作:请注意,这被视为一个坏主意。如果 makefile 依赖于环境变量,则它将对某些用户起作用,而对其他用户不起作用,这被认为是不良行为。
编辑:
这应该可以做到:
You have two problems: your method of obtaining the version is too complicated, and your
include
line has a flaw. Try this:If
APP_VER
is an environmental variable, then this will work. If you also want to include the makefile calledmakefile
(that is, ifmakefile
is not the one we're writing), then try this:Please note that this is considered a bad idea. If the makefile depends on environmental variables, it will work for some users and not others, which is considered bad behavior.
EDIT:
This should do it:
试试这个:
Try this:
修改大纲解决方案
有四个 makefile:
app.dummy.mak
makefile 可以为空 - 如果您愿意,可以为 /dev/null 的符号链接。 app.1.1.mak 和 app.1.2.mak 均与当前内容相同。主 makefile 略有变化:
如果您输入
make
,它将读取(空)虚拟 makefile,然后尝试构建dummy
目标,因为它首先出现。 ,它将再次运行make
,并在命令行上使用APP_VER=1.1
或APP_VER=1.2
:要构建虚拟目标 无法在 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 调用程序”来解决问题,该标准化的“make 调用程序”会整理 APP_VER 值并调用 make 。 > 正确。假设该脚本名为
build
:该脚本验证 APP_VER 是否已设置,如果未设置,则给出适当的默认值。然后,它处理该值以导出 MAK_VER(如果不正确则出错)。当然,您需要在达到版本 10 后修改该测试,因为您计划取得成功,以便在适当的时候达到两位数的版本号。
给定正确的版本信息,您现在可以使用任何命令行参数调用 makefile。
makefile 可以非常简单:
appdummy.mak 文件现在包含一条规则:
它只是指出进行构建的正确方法。
请注意,如果将 VCS 下的产品版本号保存在文件中,然后脚本从该文件中读取版本号,则可以避免使用 APP_VER 环境变量。该脚本还可以完成各种其他工作,确保安装正确的工具、设置其他环境变量等等。
Modifying the outline solution
Have four makefiles:
The
app.dummy.mak
makefile can be empty - a symlink to /dev/null if you like. Both app.1.1.mak and app.1.2.mak are unchanged from their current content.The main makefile changes a little:
If you type
make
, it will read the (empty) dummy makefile, and then try to build thedummy
target because it appears first. To build the dummy target, it will runmake
again, withAPP_VER=1.1
orAPP_VER=1.2
on the command line:Macros set on the command line cannot be changed within the makefile, so this overrides the line in the makefile. The second invocation of
make
, therefore, will read the correct version-specific makefile, and then buildall
.This technique has limitations, most noticeably that it is fiddly to arrange for each and every target to be treated like this. There are ways around it, but usually not worth it.
Project organization
More seriously, I think you need to review what you're doing altogether. You are, presumably, using a version control system (VCS) to manage the source code. Also, presumably, there are some (significant) differences between the version 1.1 and 1.2 source code. So, to be able to do a build for version 1.1, you have to switch from the version 1.1 maintenance branch to the version 1.2 development branch, or something along those lines. So, why isn't the makefile just versioned for 1.1 or 1.2? If you switch between versions, you need to clean out all the derived files (object files, libraries, executables, etc) that may have been built with the wrong source. You have to change the source code over. So why not change the makefile too?
A build script to invoke make
I also observe that since you have the environment variable APP_VER driving your process, that you can finesse the problem by requiring a standardized 'make invoker' that sorts out the APP_VER value and invokes
make
correctly. Imagine that the script is calledbuild
:This script validates that APP_VER is set, giving an appropriate default if it is not. It then processes that value to derive the MAK_VER (or errors out if it is incorrect). You'd need to modify that test after you reach version 10, of course, since you are planning to be so successful that you will reach double-digit version numbers in due course.
Given the correct version information, you can now invoke your makefile with any command line arguments.
The makefile can be quite simple:
The appdummy.mak file now contains a rule:
It simply points out the correct way to do the build.
Note that you can avoid the APP_VER environment variable if you keep the product version number under the VCS in a file, and the script then reads the version number from the file. And there could be all sorts of other work done by the script, ensuring that correct tools are installed, other environment variables are set, and so on.