带有条件生成的文件的makefile

时间:2016-04-28 22:56:11

标签: c++ makefile prerequisites

如何向make传达脚本可以有条件地修改文件,以便make等待stat所有文件,直到该脚本完成运行?

考虑以下玩具示例系列文件:

// version
2
// foo.h - note the space between the 1 and the semicolon
static constexpr int VERSION = 1 ;
//update.py
import sys 

with open(sys.argv[1]) as f:
    cur = int(f.readlines()[0].split()[5])

with open('version') as f:
    exp = int(f.readlines()[0].strip())

if cur < exp:
    with open(sys.argv[1], 'w') as f:
        print >> f, 'static constexpr int VERSION = {} ;'.format(exp)
// main.cxx
#include "foo.h"
#include <iostream>

int main() {
    std::cout << VERSION << std::endl;
}
// makefile
all : a.out updater

a.out : main.o
    g++ -o a.out main.o

main.o : main.cxx
    g++ -std=c++11 -o main.o -c main.cxx -MP -MMD -MF main.d

.PHONY : updater
updater :
    python update.py foo.h

-include main.d

这里的意图是我有一个文件foo.h,它由脚本update.py 有条件地更新(如果你增加{{1}中的数字},version将被更新 - 否则什么都不会发生。我想以某种方式将这一概念传达给foo.h - 为了确定是否需要重新make直到stat,我才会foo.h main.o完成运行。我如何确保订购?

注意:update.py这里只是一个占位符,表示一系列不易表达的复杂先决条件。简单地添加version不是解决方案。

2 个答案:

答案 0 :(得分:2)

如果您希望仅当脚本修改main.o时重建a.outfoo.h,这可能是递归Make:

all : updater
    @$(MAKE) a.out                      

...

main.o : main.cxx foo.h
   ...

答案 1 :(得分:1)

首先,如果您不希望make更新main.o等,直到foo.h更新后,您必须列出foo.h作为先决条件:

main.o : main.cxx foo.h
        g++ -std=c++11 -o main.o -c main.cxx -MP -MMD -MF main.d

(虽然我当然不会这样写,但我总是会使用这样的变量:

CXX = g++
CXXFLAGS = -std=c++11
DEPFLAGS = -MP -MMD -MF $*.d

main.o : main.cxx foo.h
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(DEPFLAGS) -o $@ -c $<

但那是我......)

其次,您必须有一条规则来更新foo.h。正如你的建议,它应该是.PHONY所以它总是运行,即使它并不总是更新foo.h

.PHONY: updater
updater:
        python update.py foo.h

现在您必须连接这两个规则,因此您必须创建一个将foo.h链接到updater的规则:

foo.h : updater ;

请注意这里的分号,即 critical 。它的工作方式是这样的:updater是虚假的,所以它总是会运行,这意味着依赖它的任何目标都会一直运行。很明显,您无法列出main.o : main.cxx updater,因为每次都会重建main.o

因此,您可以引入一个中间规则foo.h : updater。无论如何,您需要这样做,因为您需要列出foo.h作为先决条件,因此您需要一个目标来构建它。

然而,这本身并没有帮助,因为make看到没有构建foo.h的方法,所以它没有意识到在updater运行时它构建了foo.h。你可以通过为foo.h创建一个空配方来解决这个问题。这就是;的用途:

foo.h : updater ;

为此目标foo.h创建一个空配方,这足以让make检查文件foo.h是否已被修改。修改后(updater),然后重建main.o。如果未修改main.o,则不会重建//Provisional value int hi_score = INT_MIN;//#include <limits.h> int selectIndex = -1; for(i = 0; i < nNumbers; i++){ int dupCount = 0; if(selectIndex != -1 && array[selectIndex] == array[i]) continue;//skip because It has already been calculated for(j = 0; j < nNumbers; j++){//Examine all because unsorted if((array[i] == array[j])) ++dupCount; } if(dupCount > 1){// need ? int score = dupCount * dupCount * dupCount * array[i]; if(hi_score <= score){ hi_score = score; selectIndex = i; } } } if(selectIndex != -1) printf("%d\n", array[selectIndex]); (除非有其他原因需要重建)。