2010-12-29 1 views
0

Это моя проблема: я могу построить двоичный файл одним из двух способов, и у каждого есть проверки, которые могут выполняться на них (под их собственными целевыми целями); Я хотел бы, чтобы цель check выполнялась в зависимости от того, какая цель подходит, в зависимости от того, какая цель сборки была запущена при предыдущем вызове make: может ли это быть сделано внутренне, не касаясь файлов или какого-либо другого «внешнего» способа записи, цель которой была создана?Makefile: can (GNU) внутренне сообщают, нужно ли обновлять цель?

Иллюстрацией может помочь:

.PHONY: all modified 
all: $(obj) 
    $(CXX) ... -o $(BIN) 

modified: $(obj) $(extra_objs) 
    $(CXX) ... -o $(BIN) 


.PHONY: check check_all check_modified 
check_all: all 
    ... 

check_modified: modified 
    ... 

check: 
    # ??? Some makefile variable I don't know about? 

так, что я могу спросить это оболочки:

make X  # <-- X = {all, modified} 
...   # <-- this is important: this is not a question of target dependency 
make check # <-- have `check' run `check_X' target 

Я полагаю, что единственный путь для конкретного make вызова знать, какая цель была запущена прежде чем определить, нуждается ли он в обновлении или нет. Id est, если all обновлен, затем запустите check_all, если modified обновлен, а затем запустите check_modified и по умолчанию check_all.

Итак, могу ли я спросить make «внутренне», будет ли обновлена ​​цель X, если я попрошу ее запустить? «Внутренний» означает отсутствие вызова $(MAKE) -n или touch Y, а затем запрос оболочки if [ -f Y ] ....

Как вы можете видеть, это не совсем вопрос зависимости, потому что это явно создаст зависимость, когда все, что я хочу сделать, это проверить, была ли она запущена раньше. Итак, любые идеи или (альтернативные предложения)?

UPDATE:

ОК, я думаю, ответ: Нет. Лучшее, что я, вероятно, может сделать это:

.PHONY: check 
check: $(if $(wildcard $(firstword $(extra_objs))),check_modified,check_all) 

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

(Примечание: я столкнулся с проблемой, что:

.PHONY: check 
check: 
    $(MAKE) -q modified && $(MAKE) check_modified || $(MAKE) check_all 

не будет точно работать на код, который я имел выше, потому что all и modified являются фальшивыми и так будет всегда нуждаются в обновлении, насколько make обеспокоен , так что некоторые правила, которые один из! Но это простой и сжатый способ решения проблемы для целей, названных в честь файла, который они создали, поэтому я упомянул его для справки.)

ответ

0

Вы можете записать тип сборки в файле и прочитать, что позже, чтобы забрать право «проверять» цель, как так:

all: $(obj) 
    $(CXX) ... -o $(BIN) 
    echo [email protected] > $(BIN)-kind 

modified: $(obj) $(extra_objs) 
    $(CXX) ... -o $(BIN) 
    echo [email protected] > $(BIN)-kind 

check: $(if $(wildcard $(BIN)-kind),check_$(shell cat $(BIN)-kind)) 
+0

Ну, это намного лучше, чем shell-скрипты в целевом рецепте! Интересно, что замена '$ (BIN) -kind' на' $ (MAKE) -q all' в '$ (wildcard ...)' также делает то же самое (для чего мне это нужно) и не полагается о существовании внешнего файла. По внешнему виду (в моей системе) '$ (wildcard $ (MAKE) -q all)' оценивает '' все '' if '$ (MAKE) -q all' возвращает ноль и вычисляет пустую строку, иначе , Но я не могу найти документацию по этому поведению в руководстве GNU make: не определено? – Zorawar

+0

'$ (wildcard $ (MAKE) -q all)' оценивает те, если они есть, «make», «-q» и «all», которые являются файлами в текущем каталоге. Если это дает вам правильное поведение, это чертовски совпадение :-) – slowdog

+0

Да, я не рассчитывал на то, что это действительно полезно! Я забыл точно, какую цель я указал в Makefile, который у меня был, но я думаю, что это, должно быть, было не фальшивым ... – Zorawar

1

Возможно, нерест другой марки внутренне с флагом -q помогает?

Использование: сделать [опции] [цель] ...

Варианты:

[...]

-q, не --question Run не команды; статус выхода говорит, если до дата.

+0

Ах, не заметил этого флага: гораздо проще, чем мои предложения выше! Тем не менее, было бы неплохо, если бы мне не пришлось вызывать 'make' изнутри make-файла. – Zorawar

0

Чтобы ответить на название вашего вопроса см double colon rules. Цитируя руководство пользователя:

Правила двойной толчки несколько неясны и не часто очень полезны; они обеспечивают механизм для случаев, когда метод, используемый для обновления цели, различается в зависимости от того, какие необходимые файлы вызвали обновление, и такие случаи встречаются редко.

Звуки (почти) только то, что вам нужно.

+0

Это не помогает тому, что руководство называет эту функцию неясной! О'кей, немного похожего на googling кажется, что правило двойной толстой кишки точно не поможет мне. В принципе, похоже, что это позволит мне обновить цель double-colon'd в зависимости от того, какое предварительное условие было обновлено, и это именно то, что говорится в руководстве. Таким образом, проверка «двойным двоеточием» сначала запускает все свои зависимости (чего я не хочу делать), и поскольку это фальшивка всегда будет делать это (что только раздражает ситуацию). – Zorawar