Linux 如何强制生成文件重建目标
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/816370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you force a makefile to rebuild a target
提问by Lodle
I have a makefile that builds and then calls another makefile. Since this makefile calls more makefiles that does the work it doesnt really change. Thus it keeps thinking the project is built and upto date.
我有一个生成文件,然后调用另一个生成文件。由于这个 makefile 调用了更多的 makefile 来完成工作,因此它并没有真正改变。因此,它一直认为该项目已构建且是最新的。
dnetdev11 ~ # make
make: `release' is up to date.
How do i force the makefile to rebuild the target?
如何强制生成文件重建目标?
clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean
build = svn up ~/xxx \
$(clean) \
~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace \
$(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1) \
release:
$(build )
debug:
$(build DEBUG=1)
clean:
$(clean)
install:
cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib
Note: Names removed to protect the innocent
注:删除姓名以保护无辜者
Edit: Final Fixed version:
编辑:最终固定版本:
clean = $(MAKE) -f xxx_compile.workspace.mak clean;
build = svn up; \
$(clean) \
./cbp2mak/cbp2mak -C . xxx_compile.workspace; \
$(MAKE) -f xxx_compile.workspace.mak $(1); \
.PHONY: release debug clean install
release:
$(call build,)
debug:
$(call build,DEBUG=1)
clean:
$(clean)
install:
cp ./source/xxx_utillity/release/xxx_util /usr/bin
cp ./dlls/Release/xxxcore.so /usr/lib
采纳答案by Dave
You could declare one or more of your targets to be phony.
您可以将一个或多个目标声明为phony。
A phony target is one that is not really the name of a file; rather it is just a name for a recipe to be executed when you make an explicit request. There are two reasons to use a phony target: to avoid a conflict with a file of the same name, and to improve performance.
...
A phony target should not be a prerequisite of a real target file; if it is, its recipe will be run every time make goes to update that file. As long as a phony target is never a prerequisite of a real target, the phony target recipe will be executed only when the phony target is a specified goal
虚假目标不是真正的文件名;相反,它只是在您提出明确请求时要执行的配方的名称。使用虚假目标有两个原因:避免与同名文件发生冲突,以及提高性能。
...
虚假目标不应成为真实目标文件的先决条件;如果是,则每次 make 更新该文件时都会运行它的配方。只要虚假目标永远不是真实目标的先决条件,虚假目标配方将仅在虚假目标是指定目标时执行
回答by poundifdef
If I recall correctly, 'make' uses timestamps (file modification time) to determine whether or not a target is up to date. A common way to force a re-build is to update that timestamp, using the 'touch' command. You could try invoking 'touch' in your makefile to update the timestamp of one of the targets (perhaps one of those sub-makefiles), which might force Make to execute that command.
如果我没记错的话,'make' 使用时间戳(文件修改时间)来确定目标是否是最新的。强制重新构建的常用方法是使用“touch”命令更新该时间戳。您可以尝试在 makefile 中调用 'touch' 来更新目标之一(可能是这些子 makefile 之一)的时间戳,这可能会强制 Make 执行该命令。
回答by easel
Someone else suggested .PHONY which is definitely correct. .PHONY should be used for any rule for which a date comparison between the input and the output is invalid. Since you don't have any targets of the form output: input
you should use .PHONY for ALL of them!
其他人建议使用 .PHONY,这绝对是正确的。.PHONY 应用于输入和输出之间的日期比较无效的任何规则。由于您没有任何形式的目标,output: input
您应该对所有目标使用 .PHONY!
All that said, you probably should define some variables at the top of your makefile for the various filenames, and define real make rules that have both input and output sections so you can use the benefits of make, namely that you'll only actually compile things that are necessary to copmile!
综上所述,您可能应该在 makefile 的顶部为各种文件名定义一些变量,并定义具有输入和输出部分的真正 make 规则,以便您可以利用 make 的好处,即您只会实际编译需要 copmile 的东西!
Edit: added example. Untested, but this is how you do .PHONY
编辑:添加示例。未经测试,但这就是你的方式 .PHONY
.PHONY: clean
clean:
$(clean)
回答by sykora
The -B
switch to make, whose long form is --always-make
, tells make
to disregard timestamps and make the specified targets. This may defeat the purpose of using make, but it may be what you need.
-B
make的开关,其长格式是--always-make
,告诉make
忽略时间戳并制作指定的目标。这可能会违背使用 make 的目的,但它可能正是您所需要的。
回答by Jonathan Leffler
One trick that used to be documented in a Sun manual for make
is to use a (non-existent) target '.FORCE'. You could do this by creating a file, force.mk, that contains:
曾经记录在 Sun 手册中的一个技巧make
是使用(不存在的)目标“.FORCE”。您可以通过创建一个文件 force.mk 来做到这一点,其中包含:
.FORCE:
$(FORCE_DEPS): .FORCE
Then, assuming your existing makefile is called makefile
, you could run:
然后,假设您现有的 makefile 被调用makefile
,您可以运行:
make FORCE_DEPS=release -f force.mk -f makefile release
Since .FORCE
does not exist, anything that depends on it will be out of date and rebuilt.
由于.FORCE
不存在,任何依赖于它的东西都将过时并重建。
All this will work with any version of make
; on Linux, you have GNU Make and can therefore use the .PHONY target as discussed.
所有这些都适用于任何版本的make
; 在 Linux 上,您拥有 GNU Make,因此可以使用所讨论的 .PHONY 目标。
It is also worth considering why make
considers release to be up to date. This could be because you have a touch release
command in amongst the commands executed; it could be because there is a file or directory called 'release' that exists and has no dependencies and so is up to date. Then there's the actual reason...
还值得考虑为什么make
认为发布是最新的。这可能是因为您touch release
在执行的命令中有一个命令;这可能是因为有一个名为“release”的文件或目录存在并且没有依赖关系,因此是最新的。那么真正的原因就...
回答by Kostas
It actually depends on what the target is. If it is a phony target (i.e. the target is NOT related to a file) you should declare it as .PHONY.
这实际上取决于目标是什么。如果它是一个虚假目标(即目标与文件无关),您应该将其声明为 .PHONY。
If however the target is not a phony target but you just want to rebuild it for some reason (an example is when you use the __TIME__ preprocessing macro), you should use the FORCE scheme described in answers here.
但是,如果目标不是虚假目标,而您只是出于某种原因想重建它(例如,当您使用 __TIME__ 预处理宏时),则应使用此处的答案中描述的 FORCE 方案。
回答by abernier
回答by Daniel
As per Miller's Recursive Make Considered Harmfulyou should avoid calling $(MAKE)
! In the case you show, it's harmless, because this isn't really a makefile, just a wrapper script, that might just as well have been written in Shell. But you say you continue like that at deeper recursion levels, so you've probably encountered the problems shown in that eye-opening essay.
根据米勒的递归使被认为有害,您应该避免调用$(MAKE)
!在你展示的情况下,它是无害的,因为这不是一个真正的 makefile,只是一个包装脚本,它也可能是用 Shell 编写的。但是你说你在更深的递归层次上继续这样,所以你可能遇到了那篇令人大开眼界的文章中显示的问题。
Of course with GNU make it's cumbersome to avoid. And even though they are aware of this problem, it's their documented way of doing things.
当然,使用 GNU 使其避免起来很麻烦。尽管他们意识到了这个问题,但这是他们记录在案的做事方式。
OTOH, makeppwas created as a solution for this problem. You can write your makefiles on a per directory level, yet they all get drawn together into a full view of your project.
OTOH,makepp就是为了解决这个问题而创建的。您可以在每个目录级别上编写您的 makefile,但它们都被整合到您的项目的完整视图中。
But legacy makefiles are written recursively. So there's a workaround where $(MAKE)
does nothing but channel the subrequests back to the main makepp process. Only if you do redundant or, worse, contradictory things between your submakes, you must request --traditional-recursive-make
(which of course breaks this advantage of makepp). I don't know your other makefiles, but if they're cleanly written, with makepp necessary rebuilds should happen automatically, without the need for any hacks suggested here by others.
但是遗留的 makefile 是递归编写的。所以有一个解决方法,$(MAKE)
除了将子请求引导回主 makepp 进程之外,什么都不做。只有当你在你的子制作之间做了多余的或更糟糕的事情时,你才必须请求--traditional-recursive-make
(这当然打破了 makepp 的这个优势)。我不知道你的其他 makefile,但如果它们写得很干净,makepp 必要的重建应该会自动发生,而不需要其他人在这里建议的任何黑客。
回答by UncleBob
On my Linux system (Centos 6.2), there is a significant difference between declaring the target .PHONY and creating a fake dependency on FORCE, when the rule actually does create a file matching the target. When the file must be regenerated every time, it required both the fake dependency FORCE on the file, and .PHONY for the fake dependency.
在我的 Linux 系统 (Centos 6.2) 上,声明目标 .PHONY 和创建对 FORCE 的假依赖之间存在显着差异,而规则实际上确实创建了与目标匹配的文件。当每次都必须重新生成文件时,它需要文件的假依赖 FORCE 和假依赖的 .PHONY。
wrong:
错误的:
date > $@
right:
对:
FORCE
date > $@
FORCE:
.PHONY: FORCE
回答by groko
This simple technique will allow the makefile to function normally when forcing is not desired. Create a new target called forceat the end of your makefile. The forcetarget will touch a file that your default target depends on. In the example below, I have added touch myprogram.cpp. I also added a recursive call to make. This will cause the default target to get made every time you type make force.
这种简单的技术将允许 makefile 在不需要强制时正常运行。在makefile的末尾创建一个名为force的新目标。该部队的目标将涉及一个程序文件的默认目标取决于。在下面的示例中,我添加了touch myprogram.cpp。我还添加了一个递归调用make。这将导致每次键入make force时都会生成默认目标。
yourProgram: yourProgram.cpp
g++ -o yourProgram yourProgram.cpp
force:
touch yourProgram.cpp
make