代码之家  ›  专栏  ›  技术社区  ›  Lodle

如何强制生成文件重建目标

  •  138
  • Lodle  · 技术社区  · 16 年前

    我有一个生成文件,它生成然后调用另一个生成文件。因为这个makefile调用更多的makefile来完成工作,所以它不会真正改变。因此,它一直认为该项目是建立和最新的。

    dnetdev11 ~ # make
    make: `release' is up to date.
    

    如何强制生成文件重建目标?

    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 回复  |  直到 6 年前
        1
  •  27
  •   matthias krull Taqveem    10 年前

    你可以宣布你的一个或多个目标是 phony .

    虚伪的目标不是真正的文件名,而是它 只是在显式地 请求。使用虚假目标有两个原因:避免 与同名文件冲突,以提高性能。

    虚假目标不应是真正目标文件的先决条件;如果 是的,每次make更新它的配方都会运行 文件。只要一个虚假的目标从来不是一个真实的先决条件 目标,只有当伪目标配方 目标是指定的目标

        2
  •  561
  •   anddam    14 年前

    这个 -B 切换到make,其长形式为 --always-make 告诉 make 忽略时间戳并生成指定的目标。这可能会破坏使用make的目的,但它可能是您需要的。

        3
  •  15
  •   Jonathan Leffler    16 年前

    一个技巧曾经记录在Sun手册中, make 将使用(不存在的)目标“.force”。您可以通过创建包含以下内容的文件force.mk来完成此操作:

    .FORCE:
    $(FORCE_DEPS): .FORCE
    

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

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

    自从 .FORCE 不存在,任何依赖它的东西都将过时并重新构建。

    所有这些都适用于任何版本的 制作 ;在Linux上,您拥有gnu make,因此可以使用前面讨论过的.phony目标。

    这也是值得考虑的原因 制作 认为发布是最新的。这可能是因为你有 touch release 命令;这可能是因为存在一个名为“release”的文件或目录,并且没有依赖项,所以是最新的。那就是真正的原因…

        4
  •  13
  •   easel    9 年前

    有人建议,这是假的,这是绝对正确的。.phony应用于输入和输出之间的日期比较无效的任何规则。因为你没有任何目标 output: input 你应该用。对所有人都是假的!

    综上所述,您可能应该在makefile的顶部为各种文件名定义一些变量,并定义具有输入和输出部分的real make规则,这样您就可以利用make的好处,即您实际上只需要编译copmile所需的内容!

    编辑:添加示例。未经测试,但这就是你的做法。虚伪

    .PHONY: clean    
    clean:
        $(clean)
    
        5
  •  5
  •   poundifdef    16 年前

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

        6
  •  4
  •   groko    10 年前

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

    yourProgram: yourProgram.cpp
           g++ -o yourProgram yourProgram.cpp 
    
    force:
           touch yourProgram.cpp
           make
    
        7
  •  2
  •   Hanan Shteingart    7 年前

    make clean 删除所有已编译的对象文件。

        8
  •  2
  •   hamaney    6 年前

    我试过了,它对我有用

    将这些行添加到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”确保没有“.o”文件,因此它再次创建所有的“.o”。然后链接器将所有.o文件链接到一个可执行输出中

    祝你好运

        9
  •  1
  •   Daniel    12 年前

    按照Miller的说法 Recursive Make Considered Harmful 你应该避免打电话 $(MAKE) 你说什么?在您展示的例子中,它是无害的,因为这不是真正的makefile,只是一个包装脚本,它也可能是用shell编写的。但是你说你在更深层的递归层次上继续这样做,所以你可能遇到了开眼的文章中显示的问题。

    当然,有了GNU,避免起来很麻烦。即使他们意识到这个问题,这也是他们有据可查的做事方式。

    奥托什 makepp 已创建作为此问题的解决方案。您可以在每个目录级别上编写makefile,但是它们都被绘制到项目的完整视图中。

    但是传统的makefile是递归写入的。所以有个解决办法 $(make) 只将子请求传回makepp主进程。只有当你在你的潜艇之间做多余的或者更糟的矛盾的事情,你必须请求 --traditional-recursive-make (这当然打破了makepp的优势)。我不知道你的其他makefile,但是如果它们写得很干净,那么makepp必要的重新构建应该自动进行,而不需要其他人在这里建议的任何黑客。

        10
  •  1
  •   CZahrobsky    8 年前

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

    nmake /A 
    

    重建一切

        11
  •  0
  •   Kostas    13 年前

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

    但是,如果目标不是假的目标,但您只是出于某种原因(例如,当您使用uuu time_uuuuuu预处理宏时),您应该使用此处答案中描述的强制方案。

        13
  •  0
  •   mrflash818    10 年前

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

    如果你 触摸 所有要编译的源文件, 触摸 命令将文件的时间戳更改为系统时间 触摸 命令已执行。

    源文件timstamp是 make 用于“知道”文件已更改,需要重新编译

    例如:如果项目是C++项目,那么 touch *.cpp 然后运行 制作 同样,make应该重新编译整个项目。

        14
  •  -1
  •   leonhart    11 年前

    在我的Linux系统(Centos6.2)上,声明target.phony和创建一个对force的假依赖之间存在显著的差异,当规则确实创建了一个与目标匹配的文件时。每次必须重新生成文件时,都需要 对文件的假依赖强制,对假依赖的假依赖为.phony。

    错误:

    date > $@
    

    正确的:

    FORCE
        date > $@
    FORCE:
        .PHONY: FORCE