首页 文章

如何强制makefile重建目标

提问于
浏览
134

我有一个生成的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 回答

  • 0

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

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

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

    .PHONY: clean    
    clean:
        $(clean)
    
  • 1

    您可以将一个或多个目标声明为phony .

    伪目标是一个实际上不是文件名的目标;相反,它只是在您发出明确请求时要执行的配方的名称 . 使用虚假目标有两个原因:避免与同名文件冲突,并提高性能 . ...假目标不应该是真实目标文件的先决条件;如果是,每次make更新该文件时都会运行其配方 . 只要虚假目标永远不是真实目标的先决条件,只有当虚假目标是指定目标时才会执行虚假目标配方 .

  • -1

    要生成的 -B 开关,其长格式为 --always-make ,告诉 make 忽略时间戳并生成指定的目标 . 这可能会破坏使用make的目的,但它可能就是您所需要的 .

  • 0

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

    .FORCE:
    $(FORCE_DEPS): .FORCE
    

    然后,假设您的现有makefile被称为 makefile ,您可以运行:

    make FORCE_DEPS=release -f force.mk -f makefile release
    

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

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

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

  • 14

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

  • 13

    这种简单的技术将允许makefile在不需要强制时正常工作 . 在 makefile 的末尾创建一个名为 force 的新目标 . force 目标将触摸默认目标所依赖的文件 . 在下面的示例中,我添加了 touch myprogram.cpp . 我还添加了一个递归调用 make . 这将导致每次键入 make force 时都会生成默认目标 .

    yourProgram: yourProgram.cpp
           g++ -o yourProgram yourProgram.cpp 
    
    force:
           touch yourProgram.cpp
           make
    
  • 2

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

  • 25

    我试过这个,它对我有用

    将这些行添加到Makefile

    clean:
        rm *.o output
    
    new: clean
        $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls
    

    保存,现在打电话

    make new
    

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

    发生了什么?

    1)'新'呼叫干净 . 'clean'do'rm'删除所有扩展名为“.o”的目标文件 .

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

    祝好运

  • 5

    根据米勒的Recursive Make Considered Harmful,你应该避免调用 $(MAKE) !在你展示的情况下,它实际上是一个makefile,只是一个包装脚本,可能也是用Shell编写的 . 但是你说你在更深的递归级别上继续这样,所以你可能遇到了这个问题令人大开眼界的文章 .

    当然,使用GNU会让它变得很麻烦 . 即使他们意识到这个问题,也是他们记录的做事方式 .

    OTOH,makepp是作为此问题的解决方案而创建的 . 您可以在每个目录级别编写makefile,但它们都可以一起绘制到项目的完整视图中 .

    但传统的makefile是递归写的 . 所以有一种解决方法, $(MAKE) 什么也不做,只是将子请求传回主makepp进程 . 只有你在你的子制造之间做了多余的,或者更糟糕的,相互矛盾的事情,你必须要求 --traditional-recursive-make (这当然打破了makepp的这个优势) . 我不会写得很干净,makepp必须自动重建,而不需要别人提出任何黑客攻击 .

  • 540

    如果您不需要保留已成功编译的任何输出

    nmake /A
    

    重建所有

  • 0

    它实际上取决于目标是什么 . 如果它是虚假目标(即目标与文件无关),则应将其声明为.PHONY .

    但是,如果目标不是虚假目标,但您只是想因某些原因重建它(例如,当您使用__TIME__预处理宏时),则应使用此处答案中描述的FORCE方案 .

  • 4

    已经提到了,但我想我可以添加到使用 touch

    如果要编译所有源文件,则 touch 命令会将文件的时间戳更改为执行 touch 命令的系统时间 .

    源文件timstamp是 make 用于"know"文件已更改的内容,需要重新编译

    例如:如果项目是c项目,那么执行 touch *.cpp ,然后再次运行 make ,make应该重新编译整个项目 .

  • 1

    在我的Linux系统(Centos 6.2)上,当规则实际上创建了与目标匹配的文件时,声明目标.PHONY和创建对FORCE的假依赖之间存在显着差异 . 当每次都必须重新生成文件时,它既需要文件上的假依赖FORCE,也需要.PHONY作为伪依赖 .

    错误:

    date > $@
    

    对:

    FORCE
        date > $@
    FORCE:
        .PHONY: FORCE
    

相关问题