2015-03-09 2 views
2

Я хотел бы использовать правило статического шаблона, чтобы указать рецепт по умолчанию для класса целей, но переопределить этот рецепт для нескольких конкретных целей.Переопределить правило статического шаблона в Makefile (без предупреждения)

Вот тривиальный пример, иллюстрирующий то, что я пытаюсь сделать. Для каждого каталога, который содержит файл «test.py» Я хочу, чтобы вызвать команду «run_test.py», кроме случаев, когда каталог называется «один» Я хочу, чтобы вызвать другой набор команд:

TESTS := $(shell find * -name "test.py" | xargs -I {} dirname {}) 

.PHONY: $(TESTS) 

all: $(TESTS) 

$(TESTS): %: 
    python run_test.py [email protected] 

one: 
    python run_test.py [email protected] mode=1 
    python run_test.py [email protected] mode=2 
    python check_results.py [email protected] 

Это работает, но дает предупреждение:

$ make 
Makefile:12: warning: overriding commands for target `one' 
Makefile:9: warning: ignoring old commands for target `one' 

Есть ли другой способ сделать это или устранить предупреждение?

ответ

2

Нет, вы не можете этого сделать. Статическое правило шаблонов действительно не является правилом шаблона: вместо этого это просто сокращение для написания множества явных правил.

Если вы хотите иметь большинство целей используют один рецепт, но немного использовать другой рецепт, вы должны определить реальное шаблонное правило для «большинства» целей, не статическое шаблонного правила, а затем использовать четкие правила для переопределения:

%.o: %.cc 
     g++ -c $< -o [email protected] 

test.o: test.cc 
     g++ -Wall -c $< -o [email protected] 

Почему вы хотите использовать правило статического шаблона вместо обычного правила шаблона?

ETA Вы также могли бы использовать целевые специфические переменные:

CFLAGS = 

test.o: CFLAGS = -Wall 

$(OBJS): %.o: %.cc 
     g++ $(CFLAGS) -c $< -o [email protected] 

ETA2 ОК, это сильно отличается от исходного примера.

У вас есть два очевидных выбора, которые я вижу. Первый - удалить из списка специальные цели; что-то вроде:

SPECIAL_TESTS := one 

TESTS := $(patsubst %/test.py,%,$(shell find * -name "test.py")) 

.PHONY: all $(TESTS) 

all: $(TESTS) 

$(filter-out $(SPECIAL_TESTS),$(TESTS)): 
     python run_test.py [email protected] 

$(SPECIAL_TESTS): 
     python run_test.py [email protected] mode=1 
     python run_test.py [email protected] mode=2 
     python check_results.py [email protected] 

Другой способ сделать это с целевыми конкретных переменных, которые определяют весь рецепт, что-то вроде этого:

TEST_RECIPE = python run_test.py [email protected] 

one: TEST_RECIPE = python run_test.py [email protected] mode=1 \ 
     && python run_test.py [email protected] mode=2 \ 
     && python check_results.py [email protected] 

TESTS := $(patsubst %/test.py,%,$(shell find * -name "test.py")) 

.PHONY: all $(TESTS) 

all: $(TESTS) 

$(TESTS): 
     $(TEST_RECIPE) 
+0

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

+0

Просто потому, что они не являются реальными файлами, это не значит, что вы не можете использовать правила шаблонов ...? Если бы вы привели пример, который был ближе к вашему фактическому случаю использования, было бы легче дать совет. Например, если единственная разница между рецептами - это то, что может содержаться в переменной, вы можете использовать целевые переменные для переопределения поведения некоторых целей. – MadScientist

+0

Спасибо за помощь. Я обновил вопрос на примере, который более точно отражает то, что я пытаюсь выполнить. – moof2k