условные файлы - PullRequest
       30

условные файлы

0 голосов
/ 06 июня 2011

Примечание: используя MinGW make (должен быть GNU make)

У меня есть пара -include операторов в моем make-файле для импорта зависимостей, которые были сгенерированы с использованием g++ -MM.Однако я хотел бы делать это только при необходимости.У меня есть несколько различных целей сборки, и я не хочу, чтобы все их соответствующие файлы зависимостей были включены, так как это занимает некоторое время (предположим, я запускаю make clean: в этом случае нет необходимости включать их)

Вот формат моего make-файла.

DEPS_debug = $(patsubst %.cpp,build_debug/%.d,$(SRC))
OBJ_debug = $(patsubst %.cpp,build_debug/%.o,$(SRC))
all: program_debug
    -include $(DEPS_debug) #make: include: Command not found
program_debug: $(OBJ_debug)
    $(CC) $(CFLAGS) $(OBJ_debug) -o $@

Ответы [ 3 ]

3 голосов
/ 06 июня 2011

Если вы действительно не хотите включать эти файлы без необходимости, у вас есть несколько вариантов:

Вы можете поставить условное обозначение, как предлагает Диего Севилья (но я бы рекомендовал использовать MAKECMDGOALS, чтобывы можете написать более гибкую версию, специфичную для целей, например, вы включите foo.d, если и только если вы делаете foo.o).

Вы можете использовать make recursive (heresy!), вызывая$(MAKE) для каждого целевого объекта, используя make-файл, который включает в себя зависимости этой цели.

Но на самом деле , включая , файл занимает незначительное время, это перестройка файла(автоматически для любого включенного файла, который устарел), который требует времени.Если вам нужно избегать ненужной перестройки, вы можете использовать очень умный трюк .Когда foo.d должен быть восстановлен?Только когда что-то о foo изменилось.Но в этом случае foo.o также должен быть восстановлен.Поэтому не используйте отдельное правило для foo.d, просто перестройте его как побочный эффект создания foo.o.Таким образом, вы можете включить все файлы зависимостей и не тратить время на их восстановление, если они не нужны.

РЕДАКТИРОВАТЬ:
Я поражен, что просто , включая эти файлы могут добавить 2-3 секунды к make clean.Мой последний абзац не подходит, поэтому позвольте мне расширить первые два параметра.

Если all - единственная цель, для которой эти файлы должны быть включены, а вы make all из командной строки (а не, например, make all tests tarball install kitchenSink), тогда это будет сделано:

ifeq ($(MAKECMDGOALS),all)
-include $(DEPS_debug)
endif

Обратите внимание, что это будет не включать foo.d, если вы make foo.o.Вы можете написать более сложное условное выражение, например,

$(foreach targ,$(MAKECMDGOALS),$(eval $(call include_deps $(targ)))...

, но оно довольно продвинутое, поэтому давайте сначала поработаем с простой версией.

Если вы предпочитаете избегать условного выражения и использовать рекурсивныйMake, самый простой способ - разделить make-файл на две части:

make-файл:

all:
    $(MAKE) -f makefile.all

clean:
    rm whatever

...other rules

makefile.all:

DEPS_debug = $(patsubst %.cpp,build_debug/%.d,$(SRC))
OBJ_debug = $(patsubst %.cpp,build_debug/%.o,$(SRC))
-include $(DEPS_debug)

all: program_debug
program_debug: $(OBJ_debug)
    $(CC) $(CFLAGS) $(OBJ_debug) -o $@
1 голос
/ 06 июня 2011

Отступ строки с помощью табуляции заставляет make думать, что это команда, передаваемая оболочке (как вы узнали). Это не работает таким образом.

- перед include подавляет ошибки, которые могут возникнуть из-за того, что DEPS_debug не существует (например, при запуске clean или release без предварительного вызова генерации файла зависимостей). Поскольку DEPS_debug не является зависимостью от этих правил (clean / release), ваши файлы зависимостей не генерируются при их вызове, и все в порядке. Я не вижу проблемы, с которой вы столкнулись - у вас нет , чтобы сделать включение условным.

Возможно, вы хотели бы изменить свой подход, хотя. Вместо того, чтобы иметь отдельную цель *.d с отдельным проходом препроцессора -M, вы можете попробовать что-то вроде -MMD -MP, который генерирует файлы зависимостей, встроенные во время генерации кода, в вашем стандартном * .c -> * .o пройти.

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

1 голос
/ 06 июня 2011

include s не зависят от правил, так как они являются указанием make-файла, а не указанием компиляции.Однако вы можете использовать условные файлы makefile, основанные на специальных переменных makefile, таких как MAKECMDGOALS, для которых задана цель по умолчанию:

ifeq ($(MAKECMDGOALS),all)
    -include whatever
endif

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

...