2014-10-01 3 views
4

Предположим, у меня есть встроенный целевой Foo:Как заставить цель быть перестроенной, если установлена ​​переменная?

foo:foo.c 
    $(CC) $(CFLAGS) $(ARGS) -c foo.c -o foo 

Теперь ARGS является то, что я прохожу в командной строке:

$ make ARGS:=-DX=1 foo 

Таким образом, мне нужно обойти сообразительности сделать, потому что в foo цель зависит не только от того, какие файлы были изменены, но и от значения ARGS.

Есть ли что-нибудь, чтобы сделать это? Мой взлом (см. Ответ), кажется, не самый элегантный, но он работает. Что-нибудь лучше?

+0

Единственное «лучшее» решение, которое я знаю, это отслеживать дополнительные файлы для этой информации, которые затем используются в качестве дополнительных предварительных условий для конечной цели (количество генераторов make и т. Д. Используют этот трюк). –

+0

Я бы этого не сделал. Если 'foo' зависит от значения' $ (ARGS) ', его следует переделать, когда значение' $ ARGS ''отличается от последнего. Но вы не знаете, что это за значение. Я думаю, что лучше сделать ценность частью цели. – reinierpost

+0

@reinierpost да, вы знаете «что это за значение» :) Взгляните на мой ответ :) –

ответ

1

Мое решение было создать фиктивную фиктивной цели:

.PHONY:dummy 
dummy: 
    @: 

и имеют foo зависят от dummy если ARGS не пусто:

foo:foo.c $(patsubst %,dummy,$(ARGS)) 
+0

Я бы использовал '$ (и $ (ARGS), фиктивный)' там вместо 'patsubst', но это, безусловно, простое решение. О, также возможно, принудительная цель вместо '.PHONY', поскольку реальные цели в зависимости от целей .PHONY, как правило, не очень хорошая идея. Также вашей фальшивой цели не нужна пустая строка рецепта, подобная этой «манекену:;» также будет работать и должна (я считаю) выполнить одну меньшую оболочку. –

+0

@EtanReisner: Спасибо за ваши предложения. Я узнал новый материал: – bitmask

3

Вот общее решение вашей конкретной проблемы.

Вы хотите иметь возможность зависеть от переменной как обязательного условия. То есть вы можете сделать это обязательным условием для любой цели в вашем файле makefile, а когда значение переменной изменится, вы восстановите эти цели.

Вот функция, которая делает это, вы используете эту функцию для объявления переменной, которая будет надежной, а затем вы можете использовать ее как необходимое условие.

Обратите внимание, что если переменная не используется в командной строке, она все равно будет означать, что переменная все еще имеет значение, а именно пустую строку.

define DEPENDABLE_VAR 

.PHONY: phony 
$1: phony 
    @if [[ `cat $1 2>&1` != '$($1)' ]]; then \ 
     echo -n $($1) > $1 ; \ 
    fi 

endef 

#declare ARGS to be dependable 
$(eval $(call DEPENDABLE_VAR,ARGS)) 


foo:foo.c ARGS 
    $(CC) $(CFLAGS) $(ARGS) -c foo.c -o foo 

В самом деле, мы могли бы опустить необходимость «декларация», а просто написать подобную функцию, которая будет делать все переменными надежны по умолчанию. Но мне это не нравится. Я предпочитаю, чтобы пользователи, которые меняют make-файлы, я пишу, явно заявляют о своих намерениях. Это хорошо для них :)

+0

Эй, это похоже на глубокое создание вуду (мне нравится). Я проверю это после моего отпуска. Благодарю. – bitmask

+0

@bitmask nah, не бойтесь, это очень простой хак, на самом деле, это то, о чем говорит Etan. Он просто скрывает все детали от пользователя. Он просто создает файл с именем 'ARGS' и сохраняет последнее значение этой переменной в этом файле (возможно, пустое). Ничего. –

+0

Как отмечает Йенс, этот подход не лишен недостатков. Главный недостаток заключается в том, что если вы чередуете разные значения переменной, вам приходится каждый раз перестраивать материал. Поэтому, если вы это сделаете, это «медленно». Причина, по которой мои «пользователи», похоже, это потому, что им очень легко настроить надежность любой переменной, которую они хотят, она такая же гибкая, как и с файлами. Таким образом, они экономят время, не настраивая отдельные каталоги для различных версий промежуточных файлов и т. Д., Что является склонным к ошибкам и утомительным. –

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

  • Нет связанных вопросов^_^