makefile с условно сгенерированным файлом

Как мне передать 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 (если вы увеличите число в version, foo.h будет обновляться — иначе ничего не будет). Я хотел бы передать это понятие make как-то — это не stat foo.h чтобы определить, нужно ли переделывать main.o до тех пор update.py заканчивает работу Как мне обеспечить этот заказ?

Замечания: version это просто заполнитель для сложной серии предпосылок, которые нелегко выразить. Просто добавив foo.h : version это не решение

0

Решение

Во-первых, если вы не хотите, чтобы сделать, чтобы обновить 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 ;

Обратите внимание на точку с запятой здесь, это критический. Вот как это работает: 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 не будет восстановлен (если нет другой причины перестроить его).

1

Другие решения

Если вы хотите восстановить main.o а также a.out когда и только когда скрипт модифицируется foo.hэто может быть работа для рекурсивный Make:

all : updater
@$(MAKE) a.out

...

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

По вопросам рекламы [email protected]