2016-06-21 2 views
0

У меня есть некоторые правила, как этотЦелевого имени в Makefile предпосылка

foo_%: $(BIN_DIR) $(LIB_DIR) $(OBJ_DIR) 
    gcc stuff 

Каталога переменные, как это:

BIN_DIR := $(BUILD_DIR)/[email protected]/$(TARGET)/bin 

и правила, чтобы каталоги:

$(BIN_DIR) $(LIB_DIR) $(OBJ_DIR): 
    mkdir -p [email protected] 

хочет (расширенная) foo_% часть для замены [email protected] в названии каталога, но прямо сейчас [email protected] заменяется ничем.

Теперь я мог бы просто заменить [email protected] с % в вар bin_dir:

BIN_DIR := $(BUILD_DIR)/%/$(TARGET)/bin 

, но это опускает foo_ часть, которую я хочу, чтобы включить.

Последняя заявка содержит три заявления mkdir -p в каждом правиле, но я бы предпочел не делать этого!

ответ

1

Расширение не может работать, потому что списки предварительных условий и целей в правилах расширяются при обработке синтаксиса. Другими словами, статически, в «время компиляции» правил makefile. В то время как параметр [email protected] является динамическим; он принимает значения в make-файле «время выполнения», когда дерево правил оценивается. В то время он не может быть заменен на цели и предпосылки.

Поскольку это для обеспечения того, что существуют некоторые каталоги, вы можете переместить make -p в рецепт и сделать это вот так. Обратите внимание, что мы все еще должны изменить BIN_DIR := назначения в нерастягивающем BIN_DIR = назначения:

TARGET := target 
LIB_DIR := lib_dir 
OBJ_DIR := obj_dir 
BUILD_DIR := build_dir 

BIN_DIR = $(BUILD_DIR)/[email protected]/$(TARGET)/bin 

foo: | $(LIB_DIR) $(OBJ_DIR) # see text below for explanation of | symbol 
     mkdir -p $(BIN_DIR) 
     echo other steps 

$(LIB_DIR) $(OBJ_DIR): 
     mkdir -p [email protected] 

Здесь мы используем обработку правила грима для создания $(LIB_DIR) и $(OBJ_DIR). Но $(BIN_DIR) обрабатывается пешеходным путем, просто запустив mkdir -p в рецепте. Расширение [email protected] здесь работает, потому что BIN_DIR - это традиционная переменная make нерасширенного стиля, которая подвергается расширению при ее замене. Он по-прежнему статически расширяется при обработке синтаксиса правила, но дело в том, что он содержит нерасширенный [email protected], который вставлен в линию рецептов make -p. Потому что [email protected] находится в строке рецепта, он работает. Он просто не работает в списке целей или предварительных условий.

Я использовал символ | для обозначения $(LIB_DIR)$(OBJ_DIR) как предварительные условия для заказа. Read about this in the GNU Make manual. Предварительные требования только для заказа обновляются только в том случае, если они отсутствуют. Если они уже существуют, они игнорируются.

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

В любом случае, лучше всего не указывать каталоги в качестве предпосылок, а просто введите в рецепт mkdir -p.Как и в просто:

TARGET := target 
LIB_DIR := lib_dir 
OBJ_DIR := obj_dir 
BUILD_DIR := build_dir 

BIN_DIR = $(BUILD_DIR)/[email protected]/$(TARGET)/bin 

foo: 
     mkdir -p $(LIB_DIR) $(OBJ_DIR) $(BIN_DIR) 
     echo other step 

Run:

 
$ make 
mkdir -p lib_dir obj_dir build_dir/foo/target/bin 
echo other steps 
other steps 
+0

Удивительный ответ, спасибо много. Итак, почему мы можем иметь '%' в '$ (BUILD_DIR)', но не '$ @'? Разве '' '' не менее динамический, чем '$ @' (или даже единственная динамическая часть цели)? –

+0

@DmitryNarkevich '%' в целевых/обязательных строках является специальным; это основа правил шаблонов. Например. '% .o:% c:' правило, которое будет использоваться для создания '.o' из' .c', если для данного объекта не найдено другого более конкретного правила. – Kaz

+0

Хм, мне кажется странным, что мы можем получить соответствующую часть цели, но не целую цель. Похоже на надзор! –

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