2010-08-19 9 views
12

make sintaxis es delimitado por nueva línea, pero $ (shell ...) reemplaza las líneas nuevas con espacios en blanco. Entonces, ¿cuál es la manera fea menos que ver

$ (eval $ (shell-programa que se emite-MAKE-fragmento))

que no funciona la forma en que uno podría desear.

Respuesta

13

Esto probablemente va a hacer por lo que tiene en mente:

makefile_fragment: 
    program-that-emits-makefile-fragment > [email protected] 

include makefile_fragment 

es suficiente? Hay trucos adicionales que puede usar si los necesita, como hacer que la regla agregue contexto alrededor de lo que produce el programa, o canalizar la salida a través de sed para deslizarla en una línea, y luego analizarla con barras invertidas.

+3

+10 si pudiera. Esa es una solución elegante y bastante portátil. –

+0

No funciona .. _para mí_. Acabo de obtener variaciones sobre 'make:" makefile_fragment "está actualizado. –

+0

alex gray: prueba [agregar una dependencia en el' Makefile' en sí mismo] (http://make.mad-scientist.net/constructed-include- files /) - 'makefile_fragment: $ (MAKEFILE_LIST)' – rampion

4

La cuestión ya haya sido comunicada a la GNU hacer mantenedores:

http://savannah.gnu.org/bugs/?28230

estaba cerrado con el siguiente comentario:

Como Felipe menciona, este es el/comportamiento documentado previsto .
Recomiendo usar "incluir" en lugar de eval; haga que su script escriba un archivo, luego incluya ese archivo.

AÑADIDO: Hay una solución! He aquí una GNUmakefile muestra (reemplace 8 espacios por pestañas, sí, hay dos líneas en blanco después de define newline):

define newline 


endef 

$(eval $(subst #,$(newline),$(shell { echo 'war:'; echo '  echo "not love?"'; echo '  echo "Give peace a chance!"'; } | tr '\n' '#'))) 

De manera más general, de que es $(eval $(subst #,$(newline),$(shell myscript | tr '\n' '#')))

Tienes que escoger un personaje que no aparece en el resultado del script; # parece un buen candidato.

+0

Escribir archivos es un poco feo --- tiene que usar el archivo temporal para evitar algo, limpiar, etc. Lo siguiente funciona siempre que las líneas emitidas por el la secuencia de comandos no contiene espacios en blanco. $ (línea foreach, $ (shell make-frag-maker), $ (eval $ (línea))) – Bryan

+0

@colmode: Si no te gusta el truco de inclusión, aquí hay otra. No estoy seguro de que me guste: se siente muy hacky, pero por otro lado es así, ¿qué más esperaba? Un buen punto es que es bastante transparente; un punto a favor de los includes es que deberían ser un poco más fáciles de depurar. – Gilles

+0

Personalmente, preferiría el enfoque de "incluir". La portabilidad puede no importar en el caso específico del OP, pero "incluir" evita el uso de construcciones no portátiles (como '$ (shell) y' $ (eval) ') y, por lo tanto, en mi humilde opinión, la mejor solución. –

0

Aquí hay una forma de hacerlo mediante el secuestro del carácter de% de sustitución, por lo que no necesitamos confiar en un carácter que no aparece en el resultado de myscript.

define nl 


enddef 
$(foreach line, $(shell myscript | sed -e 's/%/\\%/' -e 's/$$/%/'), \ 
    $(eval $(patsubst %, $(line), $(nl)))) 
+0

No funciona para mí, incluso después de s/enddef/endef /: 'GNUmakefile: 5: *** separador faltante. Detener. (GNU Make 3.81) – Gilles

+0

Curioso. Acabo de pegarlo en el archivo MAKE desde este post y funciona para mí. La misma versión de marca, también. ¿Es posible que este error de análisis provenga de la ejecución de eval, es decir, es un error en el resultado de myscript? – Bryan