Работа с отравлением зависимостей в make-файлах - PullRequest
2 голосов
/ 15 ноября 2011

Я работаю над переписыванием старой сборки, которая изначально была «спроектирована» (или нет, в зависимости от обстоятельств), чтобы она была рекурсивной.В предисловии придет день, когда мы перейдем к чему-то более современному, выразительному и мощному (например, 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;это происходит независимо от того, используете ли вы := или +=.

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

1 Ответ

1 голос
/ 15 ноября 2011

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

A.so_CFLAGS = flags specific to building A.so
%.so %.o:
    @echo "${@}: ${CFLAGS} ${$@_CFLAGS} : ${filter %.o,${^}} ${filter %.c,${^}}"

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

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

В качестве дополнительного примечания, вы можете рассмотреть возможность использования automake вместо его реинжиниринга.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...