Расширение не может работать, потому что списки предварительных условий и целей в правилах расширяются при обработке синтаксиса. Другими словами, статически, в «время компиляции» правил 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
Удивительный ответ, спасибо много. Итак, почему мы можем иметь '%' в '$ (BUILD_DIR)', но не '$ @'? Разве '' '' не менее динамический, чем '$ @' (или даже единственная динамическая часть цели)? –
@DmitryNarkevich '%' в целевых/обязательных строках является специальным; это основа правил шаблонов. Например. '% .o:% c:' правило, которое будет использоваться для создания '.o' из' .c', если для данного объекта не найдено другого более конкретного правила. – Kaz
Хм, мне кажется странным, что мы можем получить соответствующую часть цели, но не целую цель. Похоже на надзор! –