У нас есть длинный и сложный Makefile в нашей системе сборки. Есть ли хороший способ отследить, какие именно цели выполняются для данного вызова make?
Как отслеживать цели Makefile для устранения неполадок?
Ответы (3)
Используйте make -d
или make --debug[=flags]
параметры:
‘-d’
Печать отладочной информации в дополнение к обычной обработке. Информация об отладке сообщает, какие файлы рассматриваются для переделки, какое время файла сравнивается и с какими результатами, какие файлы на самом деле необходимо переделать, какие неявные правила учитываются и какие применяются — все интересно о том, как make решает, что делать. Параметр
-d
эквивалентен‘--debug=a’
(см. ниже).
‘--debug[=options]’
Печать отладочной информации в дополнение к обычной обработке. Могут быть выбраны различные уровни и типы выхода. Без аргументов вывести «базовый» уровень отладки. Возможные аргументы приведены ниже; учитывается только первый символ, а значения должны быть разделены запятыми или пробелами.
a
(все) Включены все типы вывода отладки. Это эквивалентно использованию «-d».
b
(базовый) Базовая отладка печатает каждую цель, которая была признана устаревшей, и независимо от того, была ли сборка успешной или нет.
v
(подробно) Уровень выше‘basic’
; включает сообщения о том, какие make файлы были проанализированы, пререквизиты, которые не нужно было пересобирать, и т. д. Эта опция также включает‘basic’
сообщения.
i
(неявный) Выводит сообщения, описывающие поиск неявных правил для каждой цели. Эта опция также включает‘basic’
сообщений.
j
(jobs) Выводит сообщения с подробными сведениями о вызове определенных подкоманд.
m
(makefile) По умолчанию вышеуказанные сообщения не отображаются при попытке пересоздать make-файлы. Эта опция также включает сообщения при перестроении make-файлов. Обратите внимание, что опция‘all’
включает эту опцию. Эта опция также включает‘basic’
сообщений.
Другой вариант — использовать remake — исправленную версию GNU Make, которая добавляет улучшенные отчеты об ошибках, возможность трассировка выполнения и отладчик.
ElectricMake может создать версию журнала сборки с разметкой XML с много информации, которая поможет в этой ситуации:
- Полные командные строки для всех команд, вызываемых во время сборки (даже тех, которые были помечены как «тихие» команды с модификатором
@
). - Происхождение (makefile и номер строки) вызванных команд.
- Время выполнения команд.
- Отношения зависимости между целями в сборке.
- Структурная взаимосвязь между целями и рекурсивными производителями в сборке.
- Файлы, читаемые/записываемые командами, вызванными в сборке.
Вот пример этого вывода:
<job id="J0824ab08" thread="5e72bb0" node="linbuild1-2" type="rule" name="../../i686_Linux/testmain/testmain.d" file="../config/rules.mak" line="109">
<command line="110">
<argv>echo Rebuilding '../../i686_Linux/testmain/testmain.d'</argv>
<output src="prog">Rebuilding ../../i686_Linux/testmain/testmain.d
</output>
</command>
<command line="111-114">
<argv>set -e; g++ -MM -w -DUSE_PROFILING -DUSE_LOGGING -DHAVE_UNIX -DHAVE_LINUX -I.. testmain.cpp \
| sed 's!\(testmain\)\.o[ :]*!../../i686_Linux/testmain/\1.o '../../i686_Linux/testmain/testmain.d' : !g' \
> '../../i686_Linux/testmain/testmain.d'; \
[ -s '../../i686_Linux/testmain/testmain.d' ] || touch '../../i686_Linux/testmain/testmain.d'</argv>
</command>
<opList>
<op type="read" file="/home/ericm/src/testmain/testmain.cpp"/>
<op type="read" file="/home/ericm/src/minidumper/ExceptionReport.h"/>
<op type="read" file="/home/ericm/src/util/ECAssert.h"/>
<op type="create" file="/home/ericm/i686_Linux/ecloud/testmain/testmain.d" found="0"/>
</opList>
<timing invoked="1.919926" completed="3.600491" node="linbuild1-2"/>
<waitingJobs idList="J0824ae38"/>
</job>
Как быстро перемещаться Незнакомый Makefile показывает пример использования аннотированного журнала сборки, чтобы ориентироваться в Makefile.
Аннотация ElectricAccelerator интеллектуального анализа данных показано, как можно использовать аннотированный журнал сборки для создания спецификации для сборки.
ElectricMake совместим с GNU Make, поэтому он может обрабатывать make-файлы, которые работают с GNU make.
Отказ от ответственности. Я архитектор и ведущий разработчик ElectricAccelerator.
Вы можете получить некоторую информацию о том, какие цели создаются и почему, переопределив переменную SHELL в GNU make:
__ORIGINAL_SHELL:=$(SHELL)
SHELL=$(warning Building $@$(if $<, (from $<))$(if $?, ($? newer)))$(TIME) $(__ORIGINAL_SHELL)
Например, в trace-targets.mk
:
__ORIGINAL_SHELL:=$(SHELL)
SHELL=$(warning Building $@$(if $<, (from $<))$(if $?, ($? newer)))$(TIME) $(__ORIGINAL_SHELL)
all: aa.stamp ba.stamp
%.stamp:
echo stamp > $(@)
stamp-clean:
rm -vf *.stamp
clean: stamp-clean
.PHONY: %.phony
%.phony:
echo $(@)
aa.stamp: ab.stamp
ab.stamp: ac.stamp
ba.stamp: bb.stamp
bb.stamp: bc.phony
Запуск trace-targets.mk
после очистки:
$ make -f trace-targets.mk
trace-targets.mk:9: Building ac.stamp
echo stamp > ac.stamp
trace-targets.mk:9: Building ab.stamp (from ac.stamp) (ac.stamp newer)
echo stamp > ab.stamp
trace-targets.mk:9: Building aa.stamp (from ab.stamp) (ab.stamp newer)
echo stamp > aa.stamp
trace-targets.mk:18: Building bc.phony
echo bc.phony
bc.phony
trace-targets.mk:9: Building bb.stamp (from bc.phony) (bc.phony newer)
echo stamp > bb.stamp
trace-targets.mk:9: Building ba.stamp (from bb.stamp) (bb.stamp newer)
echo stamp > ba.stamp
Затем снова запустим trace-targets.mk
без очистки:
$ make -f trace-targets.mk
trace-targets.mk:18: Building bc.phony
echo bc.phony
bc.phony
trace-targets.mk:9: Building bb.stamp (from bc.phony) (bc.phony newer)
echo stamp > bb.stamp
trace-targets.mk:9: Building ba.stamp (from bb.stamp) (bb.stamp newer)
echo stamp > ba.stamp
Практически, что я делаю в своих make-файлах, так это добавляю этот фрагмент:
ifneq ($(filter all targets,$(VERBOSE)),)
__ORIGINAL_SHELL:=$(SHELL)
SHELL=$(warning Building $@$(if $<, (from $<))$(if $?, ($? newer)))$(TIME) $(__ORIGINAL_SHELL)
endif
Затем я запускаю свои make-файлы следующим образом, чтобы увидеть трассировку:
make VERBOSE=all
# or
make VERBOSE=targets
Причина all/targets в том, что у меня есть и другие подробные сведения, подобные этому:
ifneq ($(filter all vars,$(VERBOSE)),)
dump_var=$(info var $(1)=$($(1)))
dump_vars=$(foreach var,$(1),$(call dump_var,$(var)))
else
dump_var=
dump_vars=
endif
# used like
$(call dump_vars,SHELL VERBOSE)
И иногда я хочу выборочно включать/отключать аспекты отладки.
Если у вас много make-файлов, возможно, имеет смысл поместить их в общий файл и включить из других.
Предоставлено Джоном Грэмом-Каммингом, который описал этот метод в Отслеживание выполнения правила в GNU Make.
SHELL
и OLD_SHELL
должны быть переопределены в каждом отдельном файле Makefile проекта с помощью следующей команды (предварительные условия не в списке): find . -name "Makefile" -exec sed -i '1s/^/OLD_SHELL := $(SHELL)\nSHELL = $(warning Building $@)$(OLD_SHELL) -x\n/' {} \;
- person TheAhmad; 01.11.2020