Как вы получаете список целей в make файле?
Я использовал rake немного (программа make Ruby), и у нее есть возможность получить список всех доступных целей, например
> rake --tasks
rake db:charset # retrieve the charset for your data...
rake db:collation # retrieve the collation for your da...
rake db:create # Creates the databases defined in y...
rake db:drop # Drops the database for your curren...
...
но, похоже, в GNU make нет возможности сделать это.
По-видимому, код почти для него, начиная с 2007 года - http://www.mail-archive.com/[email protected]/msg06434.html.
В любом случае, я сделал небольшой взлом, чтобы извлечь цели из make файла, который вы можете включить в make файл.
list:
@grep '^[^#[:space:]].*:' Makefile
Он предоставит вам список определенных целей. Это просто начало - например, он не отфильтровывает зависимости.
> make list
list:
copy:
run:
plot:
turnin:
Ответы
Ответ 1
Это попытка улучшить отличный подход @nobar следующим образом:
- использует более надежную команду для извлечения целевых имен, которая, как мы надеемся, предотвращает любые ложные срабатывания (а также устраняет ненужные
sh -c
) - не всегда нацеливается на make файл в текущем каталоге; уважает make-
-f <file>
явно указанные в -f <file>
- исключает скрытые цели - по договоренности, это цели, имя которых не начинается ни с буквы, ни с цифры
- справляется с одной фальшивой целью
- ставит перед командой
@
чтобы предотвратить ее отображение перед выполнением
Любопытно, что GNU make
не имеет возможности перечислять только имена целей, определенных в make файле. Опция -p
производит вывод, который включает все цели, но скрывает их в большом количестве другой информации.
Поместите следующее правило в make файл для GNU make
для реализации целевого именованного list
который просто перечисляет все целевые имена в алфавитном порядке, то есть: вызывайте как make list
:
.PHONY: list
list:
@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^[email protected]$$'
Важно: при вставке этого убедитесь, что последняя строка имеет отступ ровно на 1 фактический символ табуляции. (пробелы не работают).
Обратите внимание, что сортировка результирующего списка целей является наилучшим вариантом, поскольку не сортировка не приводит к полезному упорядочению в том порядке, в котором порядок появления целей в make файле не сохраняется.
Кроме того, подцели правила, содержащего несколько целей, неизменно выводятся по отдельности и, следовательно, вследствие сортировки обычно не появляются рядом друг с другом; Например, правило, начинающееся с az:
не будет иметь цели a
и z
перечисленные рядом друг с другом в выходных данных, если есть дополнительные цели.
Объяснение правила:
После запуска make list
распечатывает все цели, каждая на своей строке; вместо этого вы можете xargs
в xargs
список, разделенный пробелами.
Ответ 2
В Bash (по крайней мере) это можно сделать автоматически с завершением вкладки:
make
space tab tab
Ответ 3
Я объединил эти два ответа: fooobar.com/questions/52739/... и fooobar.com/questions/52739/...
и сделал некоторое экранирование, чтобы это можно было использовать изнутри make файла.
.PHONY: no_targets__ list
no_targets__:
list:
sh -c "$(MAKE) -p no_targets__ | awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {split(\$$1,A,/ /);for(i in A)print A[i]}' | grep -v '__\$$' | sort"
.
$ make -s list
build
clean
default
distclean
doc
fresh
install
list
makefile ## this is kind of extraneous, but whatever...
run
Ответ 4
Это, очевидно, не будет работать во многих случаях, но если ваш Makefile
был создан CMake, вы можете запустить make help
.
$ make help
The following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
... install
etc
Ответ 5
Если у вас установлено bash завершение для make
, завершение script будет определять функцию _make_target_extract_script
. Эта функция предназначена для создания sed
script, которая может использоваться для получения целей в качестве списка.
Используйте его следующим образом:
# Make sure bash completion is enabled
source /etc/bash_completion
# List targets from Makefile
sed -nrf <(_make_target_extract_script --) Makefile
Ответ 6
Как указывает mklement0, в GNU-make отсутствует функция для перечисления всех целей Makefile, а в его ответе и др. Есть способы сделать это.
Однако в оригинальном посте также упоминается rake, чей переключатель задач делает что-то немного другое, чем просто перечисление всех задач в файле rakefile. Rake предоставит вам только список задач, с которыми связаны описания. Задачи без описания не будут перечислены. Это дает автору возможность предоставлять настраиваемые описания справки, а также опускать справку для определенных целей.
Если вы хотите имитировать поведение рейка, когда вы предоставляете описания для каждой цели, для этого есть простой метод: вставлять описания в комментарии для каждой цели, которую вы хотите перечислить.
Вы можете поместить описание рядом с целью или, как я часто это делаю, рядом со спецификацией PHONY над целью, например:
.PHONY: target1 # Target 1 help text
target1: deps
[... target 1 build commands]
.PHONY: target2 # Target 2 help text
target2:
[... target 2 build commands]
...
.PHONY: help # Generate list of targets with descriptions
help:
@grep '^.PHONY: .* #' Makefile | sed 's/\.PHONY: \(.*\) # \(.*\)/\1 \2/' | expand -t20
Что даст
$ make help
target1 Target 1 help text
target2 Target 2 help text
...
help Generate list of targets with descriptions
Вы также можете найти пример короткого кода в этом разделе и здесь.
Опять же, это не решает проблему перечисления всех целей в Makefile. Например, если у вас есть большой Makefile, который, возможно, был сгенерирован или кто-то другой написал, и вы хотите быстрый способ перечислить свои цели, не просматривая его, это не поможет.
Однако, если вы пишете Makefile и вам нужен способ генерировать текст справки согласованным, самодокументируемым способом, этот метод может оказаться полезным.
Ответ 7
@nobar answer показывает, как использовать вкладку завершения для отображения целей makefile.
-
Это отлично работает для платформ, которые предоставляют эту функциональность по умолчанию (например, Debian, Fedora).
-
На других платформах (например, Ubuntu) вы должны явно загружать эту функцию, как это подразумевается @hek2mgl ответить:
-
. /etc/bash_completion
устанавливает несколько функций завершения табуляции, в том числе для make
- В качестве альтернативы для установки только завершения табуляции для
make
:
-
. /usr/share/bash-completion/completions/make
- Для платформ, которые не предлагают эту функциональность вообще, например OSX, вы можете загрузить следующие команды (адаптировано из здесь) для его реализации:
_complete_make() { COMPREPLY=($(compgen -W "$(make -pRrq : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($1 !~ "^[#.]") {print $1}}' | egrep -v '^[^[:alnum:]]' | sort | xargs)" -- "${COMP_WORDS[$COMP_CWORD]}")); }
complete -F _complete_make make
- Примечание. Это не так сложно, как функциональность завершения табуляции, которая поставляется с дистрибутивами Linux: в первую очередь, она неизменно нацелена на make файл в текущем каталоге, даже если командная строка нацелена на другую makefile с
-f <file>
.
Ответ 8
Этот был полезен для меня, потому что я хотел видеть требуемые цели сборки (и их зависимости) целевой целью. Я знаю, что цель не может начинаться с "." персонаж. Я не знаю, какие языки поддерживаются, поэтому я пошел с выражениями выражения egrep.
cat Makefile | egrep "^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$"
Ответ 9
Это далеко не чисто, но я сделал эту работу для меня.
make -p 2&>/dev/null | grep -A 100000 "# Files" | grep -v "^$" | grep -v "^\(\s\|#\|\.\)" | grep -v "Makefile:" | cut -d ":" -f 1
Я использую make -p
, который выгружает внутреннюю базу данных, ditch stderr, использует быстрый и грязный grep -A 100000
, чтобы сохранить нижнюю часть вывода. Затем я очищаю вывод с помощью пары grep -v
и, наконец, использую cut
, чтобы получить то, что перед двоеточием, а именно цели.
Этого достаточно для моих вспомогательных скриптов на большинстве моих Make файлов.
EDIT: добавлено grep -v Makefile
, это внутреннее правило
Ответ 10
Здесь много работоспособных решений, но, как мне нравится говорить, "если это стоит сделать один раз, это стоит сделать снова". Я высказал предположение о предложении использования (вкладка) (вкладка), но, как некоторые отмечали, у вас может не быть поддержки завершения, или, если у вас много включаемых файлов, вы можете захотеть более простой способ узнать, где определена цель.
Я не проверял нижеприведенное с суб-марками... Я думаю, что это не сработает. Как известно, рекурсивный делает вредным.
.PHONY: list ls
ls list :
@# search all include files for targets.
@# ... excluding special targets, and output dynamic rule definitions unresolved.
@for inc in $(MAKEFILE_LIST); do \
echo ' =' $$inc '= '; \
grep -Eo '^[^\.#[:blank:]]+.*:.*' $$inc | grep -v ':=' | \
cut -f 1 | sort | sed 's/.*/ &/' | sed -n 's/:.*$$//p' | \
tr $$ \\\ | tr $(open_paren) % | tr $(close_paren) % \
; done
# to get around escaping limitations:
open_paren := \(
close_paren := \)
Что мне нравится, потому что:
- список целей по включаемому файлу.
- выводить необработанные динамические определения целевых объектов (заменяет разделители переменных по модулю)
- выводить каждую цель на новой строке
- кажется более понятным (субъективное мнение)
Объяснение:
- файл foreach в MAKEFILE_LIST
- вывести имя файла
- строки grep, содержащие двоеточие, которые не имеют отступов, не являются комментариями и не начинаются с точки
- исключить выражения непосредственного присваивания (: =)
- вырезать, сортировать, делать отступы и прерывать зависимости правил (после двоеточия)
- переменные Munge для ограничения расширения
Пример вывода:
= Makefile =
includes
ls list
= util/kiss/snapshots.mk =
rotate-db-snapshots
rotate-file-snapshots
snap-db
snap-files
snapshot
= util/kiss/main.mk =
dirs
install
%MK_DIR_PREFIX%env-config.php
%MK_DIR_PREFIX%../srdb
Ответ 11
Это модификация очень полезного ответа jsp (fooobar.com/questions/52738/...). Мне нравится идея получить не только список целей, но и их описание. jsp Makefile помещает описание в качестве комментария, который, как я обнаружил, часто повторяется в команде echo target description. Поэтому вместо этого я извлекаю описание из команды echo для каждой цели.
Пример Makefile:
.PHONY: all
all: build
: "same as 'make build'"
.PHONY: build
build:
@echo "Build the project"
.PHONY: clean
clean:
@echo "Clean the project"
.PHONY: help
help:
@echo -n "Common make targets"
@echo ":"
@cat Makefile | sed -n '/^\.PHONY: / h; /\(^\[email protected]*echo\|^\t:\)/ {H; x; /PHONY/ s/.PHONY: \(.*\)\n.*"\(.*\)"/ make \1\t\2/p; d; x}'| sort -k2,2 |expand -t 20
Вывод make help
:
$ make help
Common make targets:
make all same as 'make build'
make build Build the project
make clean Clean the project
make help Common make targets
Заметки:
- То же, что и в ответе jsp, могут быть указаны только цели PHONY, которые могут или не могут работать в вашем случае
- Кроме того, в нем перечислены только те цели PHONY, которые имеют команду
echo
или :
в качестве первой команды рецепта. :
означает "ничего не делать". Я использую его здесь для тех целей, которые не требуют эха, таких как all
цели выше. - Для цели
help
есть дополнительный трюк, который добавляет ":" в вывод команды make help
.
Ответ 12
Мой любимый ответ на этот вопрос был опубликован Крисом Дауном в Unix & Linux Stack Exchange. Я процитирую.
Вот как модуль завершения bash для make
получает свой список:
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'
Распечатывает список целей, разделенных новой строкой, без подкачки.
Пользователь Brainstone предлагает подключиться к sort -u
, чтобы удалить повторяющиеся записи:
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}' | sort -u
Источник: Как перечислить все цели в make? (Unix & Linux SE)
Ответ 13
Еще один дополнительный ответ на выше.
протестировано на MacOSX с использованием только cat и awk на терминале
cat Makefile | awk '!/SHELL/ && /^[A-z]/ {print $1}' | awk '{print substr($0, 1, length($0)-1)}'
будет вывод файла make, как показано ниже:
target1
target2
target3
в Makefile это должен быть тот же оператор, убедитесь, что вы экранируете переменные, используя переменную $$, а не переменную $.
объяснение
кот - выплевывает содержимое
| - труба анализирует вывод на следующий awk
awk - запускает регулярное выражение, исключая "shell" и принимая только строки "Az", затем выводит первый столбец за $ 1
awk - еще раз удаляет последний символ ":" из списка
это грубый вывод, и вы можете делать более интересные вещи с помощью только AWK. Старайтесь избегать sed, поскольку он не так согласован в вариантах BSD, т.е. некоторые из них работают на * nix, но не работают на BSD, таких как MacOSX.
Больше
Вы должны иметь возможность добавить это (с изменениями) в файл для make, в папку завершения bash по умолчанию /usr/local/etc/bash-completion.d/, что означает, что когда вы "сделаете вкладку с вкладкой "... она завершит цели, основанные на одном сценарии лайнера.
Ответ 14
Я обычно делаю:
grep install_targets Makefile
Это вернулось бы с чем-то вроде:
install_targets = install-xxx1 install-xxx2 ... etc
Я надеюсь, что это помогает
Ответ 15
не уверен, почему предыдущий ответ был настолько сложным:
list:
cat Makefile | grep "^[A-z]" | awk '{print $$1}' | sed "s/://g"