2016-02-19 30 views
5

Qualcuno sa come utilizzare un reindirizzamento del documento qui presente su una ricetta?Ricetta del makefile con un reindirizzamento di questo documento

test: 
    sh <<EOF 
    echo I Need This 
    echo To Work 
    ls 
    EOF 

non riesco a trovare alcuna soluzione di provare il metodo di barra rovesciata solito (che termina in fondo con un comando in una sola riga).

Rationale:

Ho una serie di ricette multilinea che voglio attraverso un altro comando (per esempio, sh, docker).

onelinerecipe := echo l1 
define twolinerecipe := 
echo l1 
echo l2 
endef 
define threelinerecipe := 
echo l1 
echo l2 
echo l3 
endef 

# sh as proxy command and proof of concept 
proxy := sh 

test1: 
    $(proxy) <<EOF 
    $(onelinerecipe) 
    EOF 

test2: 
    $(proxy) <<EOF 
    $(twolinerecipe) 
    EOF 

test3: 
    $(proxy) <<EOF 
    $(threelinerecipe) 
    EOF 

La soluzione mi piacerebbe evitare: trasformare le macro multilinea in singole linee.

define threelinerecipe := 
echo l1; 
echo l2; 
echo l3 
endef 

test3: 
    $(proxy) <<< "$(strip $(threelinerecipe))" 

questo funziona (io uso gmake 4.0 e bash come shell di marca) ma richiede cambiare le mie ricette e ho un sacco. Strip rimuove le nuove linee, dalla macro, quindi tutto è scritto in una singola riga.

Il mio obiettivo finale è: proxy := docker run ...

+0

Che ne dici di sh -c ''metti qui i tuoi comandi''? – fanton

+0

Possibile duplicato di [Heredoc in un Makefile?] (Http://stackoverflow.com/questions/5873025/heredoc-in-a-makefile) – e0k

+0

@ e0k Ho aggiunto il contesto –

risposta

5

Utilizzando la linea .ONESHELL: da qualche parte nel tuo Makefile invierà tutte le linee della ricetta in un unico guscio invocazione, si dovrebbe trovare il vostro Makefile originale funziona come previsto.

+1

Note mancanti importanti: il suo effetto è globale e non locale a una singola regola e ricetta. Se appare in qualsiasi punto del makefile, allora ** tutte ** le linee di ricetta ** per ogni ** target saranno fornite per una singola chiamata della shell. Non presenta problemi nel mio caso. Notate anche che '.SHELLFLAGS = -ec' è necessario per mantenere il comportamento predefinito di make in caso di errore. –

+1

Utilizzo questa soluzione da alcuni giorni e l'unico inconveniente che ho riscontrato finora è l'eco dei problemi. Perché con '.ONESHELL:', il comando '@' è ora valido per l'intera ricetta. Questo rende l'eco selettivo (echo un comando e non un altro) non più possibile. Per risolvere questo, puoi solo cambiare la tua ricetta, infrangendo così una regola che stavo cercando: proxy in modo trasparente. Ad ogni modo, questa è l'unica soluzione che consente qui-doc, quindi la convalido. –

3

Quando fanno vede un blocco multi-linea ad una ricetta (cioè un blocco di righe tutto termina in \, a parte l'ultimo), passa quel blocco non-modifed al guscio. Generalmente funziona in bash, a parte i documenti qui.

Un modo per aggirare questo è eliminare eventuali finali \ s, quindi passare la stringa risultante per bash s' eval. Effettuare questa operazione in fare giocando con ${.SHELLFLAGS} e ${SHELL}. Puoi usarli entrambi in un modulo specifico per la destinazione se vuoi che entri in gioco solo per pochi bersagli.

.PHONY: heredoc 

heredoc: .SHELLFLAGS = -c eval 
heredoc: SHELL = bash -c 'eval "$${@//\\\\/}"' 

heredoc: 
    @echo First 
    @cat <<-there \ 
     here line1 \ 
     here anotherline \ 
    there 
    @echo Last 

dando

$ make 
First 
here line1 
here anotherline 
Last 

Attento con quel citando, Eugene. Nota il trucco qui: Sto rimuovendo tutti i backslash, non solo quelli all'estremità della linea. YMMV.

+0

In particolare, grazie per "When make vede un blocco a più righe in una ricetta (cioè un blocco di linee che finiscono tutte in \, a parte l'ultimo), passa quel blocco non modificato alla shell." bit: ho provato a usare un here-doc in cui è stato risolto con quella tecnica da solo. – kostix