如何强制makefile重建目标

Lod*_*dle 159 linux makefile

我有一个生成的makefile,然后调用另一个makefile.由于这个makefile调用更多makefile来完成工作,因此它并没有真正改变.因此,它一直认为项目是建立和最新的.

dnetdev11 ~ # make
make: `release' is up to date.
Run Code Online (Sandbox Code Playgroud)

如何强制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
Run Code Online (Sandbox Code Playgroud)

注意:删除名称以保护无辜者

编辑:最终修正版:

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
Run Code Online (Sandbox Code Playgroud)

syk*_*ora 672

-B开关之作,它的长形式--always-make,讲述make忽略时间戳,使指定的目标.这可能会破坏使用make的目的,但它可能就是您所需要的.

  • 这种方法的警告是,它只是构建了太多东西.特别是使用autotools,我看到它重新运行configure ..我希望可以构建一个基于LD_PRELOAD的解决方案! (5认同)
  • @MarkKCowan我完全同意!正如Dave建议的那样,这个选项正是我所寻求的,而不是一些解决方法. (4认同)
  • 注意:这将按照它所说的进行(笑):从头开始重建目标,忽略所有时间戳。因此,如果您只想重建长链的最后一步(例如,用于测试工作流程的新部分),那么临时的“.PHONY”可能更实用。 (2认同)

Dav*_*ave 24

您可以声明一个或多个目标是虚假的.

伪目标是一个实际上不是文件名的目标; 相反,它只是在您发出明确请求时要执行的配方的名称.使用虚假目标有两个原因:避免与同名文件冲突,并提高性能.

...

伪目标不应该是真实目标文件的先决条件; 如果是,每次make更新该文件时都会运行其配方.只要虚假目标永远不是真实目标的先决条件,只有当虚假目标是指定目标时才会执行虚假目标配方.

  • 这个答案,虽然它被"接受"和高度"upvoted"真的是不合时宜的.首先,它说"声明目标是虚假的",但它说"虚假的目标实际上不是文件的名称".好吧,如果你的目标是一个文件,那么这就是答案中的矛盾.其次,它说"虚假的目标不应该是真实的先决条件" - 嗯,如果它是什么?最初的问题,没有具体说明是否存在.正确的答案是,_not_声明_your_目标是虚假的,而是声明一个额外的虚假目标,然后,依赖于你想要重建的目标. (64认同)
  • 这怎么会得到 51 票反对?!如果你仔细阅读OP的问题,似乎有可能,甚至很可能,“makerelease”实际上创建了一个名为“release”的目录。这意味着输出“release is up to date”正是您所期望的,正确的答案*是将“release”声明为.PHONY。原因是您只想运行“release”配方,而不管“release”文件或目录是否实际存在。这正是 .PHONY 的用途。 (3认同)
  • @MarkGaleck。当答案表明“伪造目标不是一个真正的文件名”时,它直接引用了gcc make手册。这是完全正确的。 (2认同)

Jon*_*ler 16

过去在Sun手册中记录的一个技巧make是使用(不存在的)目标'.FORCE'.您可以通过创建一个包含以下内容的文件force.mk来执行此操作:

.FORCE:
$(FORCE_DEPS): .FORCE
Run Code Online (Sandbox Code Playgroud)

然后,假设您调用现有的makefile makefile,您可以运行:

make FORCE_DEPS=release -f force.mk -f makefile release
Run Code Online (Sandbox Code Playgroud)

由于.FORCE不存在,任何依赖它的东西都会过时并重建.

所有这些都适用于任何版本的make; 在Linux上,你有GNU Make,因此可以使用.PHONY目标.

值得考虑的是为什么make认为发布是最新的.这可能是因为你touch release在执行的命令中有一个命令; 可能是因为存在一个名为'release'的文件或目录,并且没有依赖关系,因此是最新的.那是真正的原因......


eas*_*sel 13

有人建议.PHONY绝对是正确的..PHONY应该用于输入和输出之间的日期比较无效的任何规则.由于你没有任何形式的目标,output: input你应该使用.PHONY所有这些!

总而言之,您可能应该在makefile的顶部为各种文件名定义一些变量,并定义包含输入和输出部分的真实make规则,这样您就可以使用make的好处,即您只能实际编译copmile需要的东西!

编辑:添加示例.未经测试,但这就是你做的.PHONY

.PHONY: clean    
clean:
    $(clean)
Run Code Online (Sandbox Code Playgroud)

  • “.PHONY”目标的位置并不重要。它可以位于`Makefile`中的任何位置。 (2认同)

Han*_*art 11

make clean删除所有已编译的目标文件。


pou*_*def 7

如果我没记错的话,'make'使用时间戳(文件修改时间)来确定目标是否是最新的.强制重新构建的常用方法是使用"touch"命令更新该时间戳.您可以尝试在makefile中调用"touch"来更新其中一个目标(可能是其中一个子makefile)的时间戳,这可能会强制Make执行该命令.


gro*_*oko 6

这种简单的技术将允许 makefile 在不需要强制时正常运行。在makefile的末尾创建一个名为force的新目标。该部队的目标将涉及一个程序文件的默认目标取决于。在下面的示例中,我添加了touch myprogram.cpp。我还添加了一个递归调用make。这将导致每次键入make force时都会生成默认目标。

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make
Run Code Online (Sandbox Code Playgroud)

  • 你不应该在 Makefile 中使用 `make`。请改用“$(MAKE)”。 (2认同)

小智 6

正如 abernier 指出的,GNU make 手册中有一个推荐的解决方案,它使用“假”目标来强制重建目标:

clean: FORCE
        rm $(objects)
FORCE: ; 
Run Code Online (Sandbox Code Playgroud)

无论任何其他依赖项如何,这都将运行干净。

我在手册中的解决方案中添加了分号,否则需要空行。


ham*_*ney 5

我试过了,它对我有用

将这些行添加到 Makefile

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls
Run Code Online (Sandbox Code Playgroud)

保存并立即调用

make new 
Run Code Online (Sandbox Code Playgroud)

它将再次重新编译所有内容

发生了什么?

1) 'new' 调用干净。'clean' do 'rm' 删除所有扩展名为 '.o' 的目标文件。

2) 'new' 调用 'make'。'make' 看到没有 '.o' 文件,所以它再次创建所有的 '.o' 文件。然后链接器将所有 .o 文件链接到一个可执行输出

祝你好运