2016-02-19 33 views
5

Bir belgede burada belge yönlendirme nasıl kullanılacağını bilen var mı?Belgede yeniden yönlendirme ile Makefile tarifi

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

Ben (temelde tek bir satırında bir komut ile biter) olağan ters eğik çizgi yöntemi çalışırken herhangi bir çözüm bulamıyor.

Gerekçe:

I (örneğin, sh docker) bir komut ile vekil isteyen çok hatlı tarifleri bir dizi vardır.

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 

Kaçınılması gereken özüm: çok satırlı makroları tek satırlara dönüştürür.

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

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

Bu (ı make 'kabuk olarak gmake 4.0 ve bash kullanarak) ama benim tarifleri yenilenmesi gerekir, ben çok şey var çalışır. Şerit, yeni satırları makrodan kaldırır, sonra her şey tek bir satırda yazılır.

Benim uç hedeftir: Tek bir kabuk çağırma tüm reçete hatları gönderecek olan Makefiledaki yerde çizgi .ONESHELL: kullanma proxy := docker run ...

+0

sh -c ''komutlarınızı buraya koymaya ne dersiniz? – fanton

+0

Olası kopya [Makefile'de Heredoc?] (Http://stackoverflow.com/questions/5873025/heredoc-in-a-makefile) – e0k

+0

@ e0k Bağlamı ekledim –

cevap

5

, beklendiği gibi orijinal Makefile çalıştığını bulmak gerekir.

+1

Önemli eksik notlar: etkisi global ve tek bir kural ve tarife yerel değil. Makefile'nin herhangi bir yerinde görünürse, her ** hedef için ** tüm ** tarif hatları **, kabuğun tek bir çağrısına sunulacaktır. Benim durumumda sorun çıkarmaz. Ancak, ".SHELLFLAGS = -ec" parametresinin hata yapmanın varsayılan davranışını korumak için gerekli olduğunu da unutmayın. –

+1

Bu çözümü birkaç günlüğüne kullanıyorum ve şu ana kadarki tek dezavantajım yankılandı. Çünkü .ONESHELL ile: ',' ​​'' öncüsü artık tüm tarif için geçerli. Bu, seçici yankılama (eko bir komut ve başka bir değil) artık mümkün kılar. Bunu çözmek için, sadece reçetenizi değiştirebilir, böylece aradığım bir kuralı ihlal edebiliriz: vekil olarak. Her neyse, burası doktora yapabilecek tek çözüm, bu yüzden bunu onaylıyorum. –

3

olmak (yani, çizgilerin bir blok dışında tüm son gelen \ ile biten) bir tarifi , bu kalıbı çatıya göre un değişikliğe uğratılmış geçer bir çok hatlı blok görür. Bu, genel olarak, bu belgeden ayrı olarak bash, adresinde çalışır. Bu sorunu

bir yolu, sonda \ s şerit etmektir, sonra Bash sitesindeki eval elde edilen dize geçirir. Bunu, ${.SHELLFLAGS} ve ${SHELL} ile ürününde yapabilirsiniz. Her iki hedefi de yalnızca birkaç hedefe atılmasını istiyorsanız, hedefe özel formda kullanabilirsiniz. Eugene alıntı bununla

$ make 
First 
here line1 
here anotherline 
Last 

Dikkatli veren

.PHONY: heredoc 

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

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

. Burada hile dikkat edin: Sadece tüm satır kirlerini temizliyorum, sadece satırın sonundakileri değil. YMMV.

+0

Özellikle, "Bir reçetede çok satırlı bir satır görürken (yani, sondan başka bir satır sonu olan bir satır bloğu" görürseniz), bu bloğu değiştirilmemiş bir kabuktan geçirir. " bit: Tek başına bu teknikle çözüldüğü bir belgeyi kullanıyorum. – kostix