2013-09-06 1 views
4

Пытается найти изящный метод решения некоторых сложных зависимостей. У меня есть что-то вроде следующей в моей Makefile:Реальные цели с зависимостями PHONY

.PHONY: FOO 
FOO: foo 
foo: 
    build foo 

.PHONY: BAR 
BAR: bar 
bar: FOO 
    build bar 

Идея здесь заключается в том, что я хочу абстрактный реальные файлы (Foo, Bar) с фальшивыми целями (Foo Bar). Конечно, в моем реальном Makefile это сложнее, поэтому абстракция важна. Проблема здесь, однако, заключается в том, чтобы сделать фальшивую целевую FOO зависимостью для бара, затем Make всегда пытается перестроить панель, даже если оба foo и bar обновлены. Это, по-видимому, потому, что он всегда относится к FOO как устаревший. Но это поведение не совсем корректно.

Похоже, у меня есть только 3 варианта: 1) Создайте бар непосредственно в зависимости от foo. В моем реальном Makefile это сложнее и пытается указать реальные файлы, поскольку зависимости крайне нежелательны. 2) Используйте переменные в дополнение ко всем фононам. Это делает весь Makefile более сложным. 3) Удалите foo/Foo как зависимость от бара и добавьте рекурсивный make из FOO как часть правила в строке. Это очень плохая форма.

Есть ли еще более элегантное решение, о котором я не знаю?

Спасибо.

+0

Я не уверен, что вижу, почему вы хотите сделать эту абстракцию вообще. Одна из лучших частей 'make' - это то, как хорошо справляются с реальными целями и отметками времени. –

+2

Если вы не сможете более четко объяснить, почему вы хотите, чтобы цель была PHONY, я не вижу, как мы можем помочь. Чего вы пытаетесь достичь, сделав это PHONY? Что ломается или работает неправильно, если вы не используете PHONY? Весь смысл PHONY состоит в том, чтобы гарантировать, что рецепт, связанный с целью, всегда запускается, поэтому идея о том, что это поведение «не совсем правильно», ... не совсем корректна :-) – MadScientist

+0

Имена файлов сложны (под- каталоги, длинные имена и т. д.). Использование имен файлов непосредственно во всех правилах делает вещи довольно нечитаемыми. С точки зрения конечного пользователя цели становятся нецелесообразными для ввода в командной строке из-за этой сложности. Я мог бы полностью заменить цели PHONY на переменные - я полагаю, - что упростит Makefile, но у вас все еще есть те же проблемы с командной строкой make (то есть цели, которые пользователь должен указать, являются сложными) , –

ответ

0

Как вы полагаете, переменные - это то, что вам нужно, и могут реально помочь в удобочитаемости. Они позволяют сделать штрих-файл правильно зависит от Foo-файла, а не на вашей удобной мишенью .PHONY:

foo.file = horrendously/long/path/to/the/real/foo.file 
bar.file = horrendously/long/path/to/the/real/bar.file 

.PHONY: FOO 
FOO: $(foo.file) 
$(foo.file): 
     touch [email protected] 

.PHONY: BAR 
BAR: $(bar.file) 
$(bar.file): $(foo.file) 
     touch [email protected] 

И здесь мы идем: ответ

$ make BAR 
touch horrendously/long/path/to/the/real/foo.file 
touch horrendously/long/path/to/the/real/bar.file 

$ make BAR 
make: Nothing to be done for `BAR'. 
1

GNU Make в к этой ситуации order-only dependencies. Это позволяет вам обеспечить заказ целей без наличия «устаревшего» отношения. Из вашего вопроса, похоже, именно это вы ищите.

Так что ваш Makefile фрагмент из выше будет выглядеть следующим образом:

.PHONY: FOO 
FOO: foo 
foo: 
    build foo 

.PHONY: BAR 
BAR: bar 
bar: | FOO 
    build bar 

Это позволит Foo всегда быть построено до бара, но не мандат, что когда Foo обновляется, что бар должен быть построен. foo будет создан только тогда, когда вызывается make BAR, и файлы foo не существуют.

+1

Ницца. Я только что использовал ваше предложение в гневе, в случае, когда FOO был подлинным PHONY, то есть целью, которая делает что-то важное, но не генерирует файл с именем FOO (или foo).Я подозреваю, что зависимость от заказа не работает для Miguel, хотя, поскольку он не перестраивает файл bar, если foo устарел. –

Смежные вопросы