Я работаю над переписыванием старой сборки, которая изначально была «спроектирована» (или нет, в зависимости от обстоятельств), чтобы она была рекурсивной.В предисловии придет день, когда мы перейдем к чему-то более современному, выразительному и мощному (например, scons);однако этот день еще не наступил.
В рамках этих усилий я нахожусь в процессе объединения общих переменных / макросов и целей / рецептов в несколько кратких файлов правил, которые будут включены как часть.первичной сборки.В каждом подразделе сборки будет использоваться небольшой make-файл, который добавляет цели и зависимости с небольшим количеством переменных, добавляемых в эти подфайлы.Makefile верхнего уровня будет включать все make-файлы, позволяя всему вносить свой вклад в дерево зависимостей.
Я должен признать, что совсем не уверен, что люди будут использовать здравый смысл при модификации make-файлов.В качестве примера того, что меня беспокоит:
CFLAGS = initial cflags
all: A.so
%.so %.o:
@echo "${@}: ${CFLAGS} : ${filter 5.o,${^}} ${filter %.c,${^}"
%.c :
true
%.o : %.c
A.so : B.so a1.o a2.o a3.o
B.so : b1.o b2.o b3.o
A.so : CFLAGS += flags specific to building A.so
При условии, что я не испортил этот пример, ситуация такова: A.so
будет ссылаться на B.so
, а A.so
для объектов нужны специальные флаги;однако объекты B.so
и B
унаследуют изменения в CFLAGS
.
Я бы предпочел иметь одну цель для построения большинства, если не всех объектных файлов, даже до степени измененияCFLAGS специально для тех объектов, которым требуются немного другие флаги, чтобы способствовать повторному использованию более общих целей (облегчает отладку, если есть только одна цель / рецепт, о котором нужно беспокоиться).
После того, как я закончу повторразрабатывая эту сборку, я не уверен, что кто-то не сделает такую глупость;что еще хуже, он может пройти рецензирование, если меня нет рядом с ним.
У меня возникла идея сделать что-то вроде этого:
% : CFLAGS = initial cflags
...что предотвратит отравление зависимостей, если кто-то не обновит его:
% : CFLAGS += some naive attempt at altering CFLAGS for a specific purpose
Однако, если есть, только 1000 целей (очень консервативная оценка) и приблизительно 1 КБ в памяти, выделенной для переменных, то мыоколо 1 МБ служебных данных, что может существенно повлиять на время, которое требуется для поиска значения CFLAGS при работе с рецептами (конечно, в зависимости от архитектуры gmake).
Короче говоря, я предполагаю, что мой вопрос: что вменяемое / хорошееспособ предотвратить отравление зависимостей в make-файле?Есть ли лучшая стратегия, чем я обрисовал в общих чертах?
edit
Если кто-то попытается пойти по пути определения переменных, как описано вышеЯ столкнулся с нюансом, который поначалу был не совсем очевиден.
% : INCLUDES :=
# ...
SOMEVAR := /some/path
% : INCLUDES += -I${SOMEVAR}
...
SOMEVAR :=
Когда переменная создается с использованием :=
, все справа от :=
должно оцениваться немедленно, тогда как если онотолько что использованный =
будет задерживать оценку, пока целевой рецепт не оценит INCLUDES
.
Однако, SOMEVAR
ничего не оценивает при оценке целевого рецепта.Если вы измените определение на:
% : INCLUDES := whatever
# ...
SOMEVAR := /some/path
% : INCLUDES := ${INCLUDES} -I${SOMEVAR}
...
SOMEVAR :=
... тогда это заставит SOMEVAR
быть оцененным немедленно, вместо того, чтобы задерживать оценку, но INCLUDES
не оценивает его ранее определенное определение, а скорееглобальное определение.
$(flavor ...)
говорит, что INCLUDES
равно simple
, а $(origin ...)
возвращает file
;это происходит независимо от того, используете ли вы :=
или +=
.
Короче говоря, если вы используете +=
для переменных в области действия, оно будет использовать только определение переменной, определенной для этой цели;это не смотрит на глобалы.Если вы используете :=
, он использует только глобальные переменные.