Enumerar objetivos / metas en GNU make que contienen variables en su definición
Tengo un makefile bastante grande que crea un número de objetivos sobre la marcha computando nombres de variables. (eg foo fo (VAR): PRERE (PREREQS)). ¿Hay alguna manera de que gnu make pueda ser convencido de escupir una lista de objetivos después de haber expandido estas variables?
Me gustaría ser capaz de obtener los objetivos para un makefile aribitrary. Estoy tratando de escribir una función de finalización para mi shell.
16 answers
¿Puedes analizar la salida de make -pn
(es decir, make --print-data-base --dry-run
)? Imprime todas las variables, reglas, reglas implícitas y qué comandos se ejecutarán en detalle laborioso.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-03 02:02:12
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'
Tomado de la terminación make arg, que funciona como un encanto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-02 18:55:54
No estoy seguro si esto es solo una cosa de gnu make, pero esto funciona bien:
make help
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-11 21:23:28
Varios respondedores han sugerido usar make -pn
, que imprimirá la base de datos de reglas pero no ejecutará nada more más o menos. El problema con este enfoque es que -n
todavía invoca todas las marcas recursivas, y todavía hace mucho más trabajo del necesario, porque imprime cada comando que habría invocado en una compilación regular. Una solución más eficiente sería crear un makefile trivial, dummy.mk, con estos contenidos:
__all_targets__: ; #no-op
Ahora invoca make como make -p -f Makefile -f dummy.mk __all_targets__
. En cualquier construcción sustancial, la diferencia en la cantidad de producción generada por make es significativa. Por ejemplo:
$ gmake -pn | wc
138985 2632330 69612711
$ gmake -f Makefile -f /tmp/dummy.mk -pn __all_targets__ | wc
21673 93437 878985
El tiempo de ejecución también fue dramáticamente mejor 2 2.063 s para la primera versión, 0.059 s para la segunda.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-12 16:14:51
Echa un vistazo a la finalización de bash para make en GitHub.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-01 08:25:11
Edit: FYI el repositorio git de finalización de bash de debian en otra respuesta ahora incorpora una versión mejorada de este script adaptada a los casos de uso de finalización de bash.
#!/bin/bash
SCRIPT='
/^# Make data base/,/^# Files/d # skip until files section
/^# Not a target/,+1 d # following target isnt
/^\.PHONY:/ d # special target
/^\.SUFFIXES:/ d # special target
/^\.DEFAULT:/ d # special target
/^\.PRECIOUS:/ d # special target
/^\.INTERMEDIATE:/ d # special target
/^\.SECONDARY:/ d # special target
/^\.SECONDEXPANSION/ d # special target
/^\.DELETE_ON_ERROR:/ d # special target
/^\.IGNORE:/ d # special target
/^\.LOW_RESOLUTION_TIME:/ d # special target
/^\.SILENT:/ d # special target
/^\.EXPORT_ALL_VARIABLES:/ d # special target
/^\.NOTPARALLEL:/ d # special target
/^\.ONESHELL:/ d # special target
/^\.POSIX:/ d # special target
/^\.NOEXPORT:/ d # special target
/^\.MAKE:/ d # special target
# The stuff above here describes lines that are not
# explicit targets or not targets other than special ones
# The stuff below here decides whether an explicit target
# should be output.
/^[^#\t:=%]+:([^=]|$)/ { # found target block
h # hold target
d # delete line
}
/^# File is an intermediate prerequisite/ { # nope
s/^.*$//;x # unhold target
d # delete line
}
/^([^#]|$)/ { # end of target block
s/^.*$//;x # unhold target
s/:.*$//p # write current target
d # hide any bugs
}
'
make -npq .DEFAULT 2>/dev/null | sed -n -r "$SCRIPT" \
| sort | uniq
Este es un script mucho más completo que el script de finalización de debian bash porque proporciona resultados para las reglas generadas que es lo que pide la pregunta y la respuesta más votada (script de finalización de debian bash en el servidor debian git) no va lo suficientemente lejos.
Este no es el script original que He vinculado a pero es mucho más simple y es un toque más rápido.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-18 21:37:45
Este es el código para alias basado en la solución Todd Hodes
alias mtargets='make -qp | awk -F":" "/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split(\$1,A,/ /);for(i in A)print A[i]}"'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-20 06:40:23
Esto dará una buena salida:
make -pn | perl -F: -ane 'print "$F[0]\n" if /^\w+\s*:/' | sort
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-08 13:22:19
Hay una solución muy buena con algo de sed y magia egrep aquí: https://gist.github.com/pvdb/777954
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-06 08:42:19
Supongo que llego un poco tarde a esta fiesta, pero si estás buscando un comando específico, podrías probar
make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'
Esto funciona en su mayoría, aunque todavía podría incluir algunas cosas no objetivo como una directiva vpath
. Si no depende de las reglas integradas de make
, puede usar make -qpR
como el primer comando de la canalización.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-06 17:31:04
Solución de rubí:
`make -qp`.split("\n").select{|l| l =~ /^\w/ && l !~ /=/}.map{|l| l.sub(/:.*/,'')}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-09 08:39:55
Estoy trabajando en solaris 10 y turbo C shell. La solución dada no funciona para mi proyecto makefile. incluso después de alterar la línea de comandos anterior a la sintaxis tcsh. Sin embargo, descubrí que puede obtener una solución fácil usando
remake --tasks | grep -v "clean some static output or just grep tabs on start of line" | awk ´{print $1}´
Versión remake:
remake --version
Es
GNU Make 3.82+dbg0.8
Built for sparc-sun-sparc2-9
Y algunos otros datos de versión sin importancia
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-20 05:14:41
Fui a buscar la misma pregunta y se me ocurrió este giro:
make -pn | sed -rn '/^[^# \t\.%].*:/p'
Esto elimina todas las líneas de comentario, reglas de patrón (líneas que comienzan con pestañas), todos los intrínsecos (ejemplo .c.o
y %.o: %.c
patrones).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-03 21:41:12
Encontró esta solución en otro hilo:
sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\""
También puedes añadirlo a tu Makefile
:
list:
sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\\""
Y ejecutar make list
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-03 16:26:45
Claro, pero ¿cuándo quieres que los escupa?
Para informar el nombre del destino cuando se ejecuta la regla, ponga una línea en la regla:
foo$(VAR): $(PREREQS)
@echo now making the foo target: $@
do_other_stuff...
Para escupirlos a todos a la vez, podrías hacer un objetivo falso separado:
.PHONY: show_vars
show_vars:
@echo foo$(VAR)
@echo bar$(PARAM) blah$(FLAG)
# and so on
Y esto se puede hacer un requisito previo de su destino predeterminado:
all: show_vars
...
EDITAR:
Quieres una forma de mostrar todos los posibles objetivos de un makefile arbitrario, que supongo que significa no intrusivamente. Bien...
Para hacerlo exactamente, y ser capaz de hacer frente a sofisticados makefiles, por ejemplo, que involucran reglas construidas por eval
declaraciones, tendría que escribir algo cercano a un emulador Make. Práctico.
Para ver los objetivos de las reglas simples, podría escribir un makefile que actuaría como un escáner de makefile, operando en un makefile arbitrario:
- Obtiene todos los nombres de destino del makefile usando sed.
- 'incluir' el makefile para usarlo para expandir variable.
- Use ' show_%:; echo**` para imprimir todos los destinos
Este sería un trabajo impresionante. ¿Estás seguro de que el objetivo vale la pena el esfuerzo?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-22 19:08:48
grep ^[a-z].*\:$ Makefile | sed s,:,,g
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-20 19:22:54