我有一个生成的makefile,然后调用另一个makefile . 由于这个makefile调用更多makefile来完成工作,因此它并没有真正改变 . 因此,它一直认为项目是 Build 和最新的 .
dnetdev11 ~ # make
make: `release' is up to date.
如何强制makefile重建目标?
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
注意:删除名称以保护无辜者
编辑:最终修正版:
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
14 回答
有人建议.PHONY绝对是正确的 . .PHONY应该用于输入和输出之间的日期比较无效的任何规则 . 由于你没有
output: input
形式的任何目标,所以你应该使用.PHONY!总而言之,您可能应该在makefile的顶部为各种文件名定义一些变量,并定义包含输入和输出部分的真实make规则,这样您就可以使用make的好处,即您只能实际编译copmile需要的东西!
编辑:添加示例 . 未经测试,但这就是你做的.PHONY
您可以将一个或多个目标声明为phony .
要生成的
-B
开关,其长格式为--always-make
,告诉make
忽略时间戳并生成指定的目标 . 这可能会破坏使用make的目的,但它可能就是您所需要的 .过去在
make
的Sun手册中记录的一个技巧是使用(不存在的)目标'.FORCE' . 您可以通过创建一个包含以下内容的文件force.mk来执行此操作:然后,假设您的现有makefile被称为
makefile
,您可以运行:由于
.FORCE
不存在,任何依赖它的东西都会过时并重建 .所有这些都适用于任何版本的
make
;在Linux上,你有GNU Make,因此可以使用.PHONY目标 .同样值得考虑为什么
make
认为发布是最新的 . 这可能是因为您在执行的命令中有一个touch release
命令;可能是因为存在一个名为'release'的文件或目录,它没有依赖关系,因此是最新的 . 那是真正的原因......如果我没记错的话,'make'使用时间戳(文件修改时间)来确定目标是否是最新的 . 强制重新构建的常用方法是使用“touch”命令更新该时间戳 . 您可以尝试在makefile中调用“touch”来更新其中一个目标(可能是其中一个子makefile)的时间戳,这可能会强制Make执行该命令 .
这种简单的技术将允许makefile在不需要强制时正常工作 . 在 makefile 的末尾创建一个名为 force 的新目标 . force 目标将触摸默认目标所依赖的文件 . 在下面的示例中,我添加了 touch myprogram.cpp . 我还添加了一个递归调用 make . 这将导致每次键入 make force 时都会生成默认目标 .
make clean
删除所有已编译的目标文件 .我试过这个,它对我有用
将这些行添加到Makefile
保存,现在打电话
它将再次重新编译所有内容
发生了什么?
1)'新'呼叫干净 . 'clean'do'rm'删除所有扩展名为“.o”的目标文件 .
2)'新'调用'make' . 'make'看到没有'.o'文件,所以它再次创建所有'.o' . 然后链接器将所有.o文件链接到一个可执行输出
祝好运
根据米勒的Recursive Make Considered Harmful,你应该避免调用
$(MAKE)
!在你展示的情况下,它实际上是一个makefile,只是一个包装脚本,可能也是用Shell编写的 . 但是你说你在更深的递归级别上继续这样,所以你可能遇到了这个问题令人大开眼界的文章 .当然,使用GNU会让它变得很麻烦 . 即使他们意识到这个问题,也是他们记录的做事方式 .
OTOH,makepp是作为此问题的解决方案而创建的 . 您可以在每个目录级别编写makefile,但它们都可以一起绘制到项目的完整视图中 .
但传统的makefile是递归写的 . 所以有一种解决方法,
$(MAKE)
什么也不做,只是将子请求传回主makepp进程 . 只有你在你的子制造之间做了多余的,或者更糟糕的,相互矛盾的事情,你必须要求--traditional-recursive-make
(这当然打破了makepp的这个优势) . 我不会写得很干净,makepp必须自动重建,而不需要别人提出任何黑客攻击 .如果您不需要保留已成功编译的任何输出
重建所有
它实际上取决于目标是什么 . 如果它是虚假目标(即目标与文件无关),则应将其声明为.PHONY .
但是,如果目标不是虚假目标,但您只是想因某些原因重建它(例如,当您使用__TIME__预处理宏时),则应使用此处答案中描述的FORCE方案 .
http://www.gnu.org/software/make/manual/html_node/Force-Targets.html#Force-Targets
已经提到了,但我想我可以添加到使用
touch
如果要编译所有源文件,则
touch
命令会将文件的时间戳更改为执行touch
命令的系统时间 .源文件timstamp是
make
用于"know"文件已更改的内容,需要重新编译例如:如果项目是c项目,那么执行
touch *.cpp
,然后再次运行make
,make应该重新编译整个项目 .在我的Linux系统(Centos 6.2)上,当规则实际上创建了与目标匹配的文件时,声明目标.PHONY和创建对FORCE的假依赖之间存在显着差异 . 当每次都必须重新生成文件时,它既需要文件上的假依赖FORCE,也需要.PHONY作为伪依赖 .
错误:
对: