Bash sözdizimini Makefile hedeflerinde nasıl kullanabilirim?


209

Sık sık Bash sözdizimini çok yararlı buluyorum , örn diff <(sort file1) <(sort file2).

Bu tür Bash komutlarını bir Makefile'de kullanmak mümkün mü? Böyle bir şey düşünüyorum:

file-differences:
    diff <(sort file1) <(sort file2) > $@

GNU Make 3.80'de bu , komutları yürütmek shellyerine onu kullandığından bir hata verecektir bash.


Bu benim sorunumdu, bu soruyu bulmam en az bir saatimi aldı! Gelecekteki okuyucuların bulabilmesi için hata mesajımı burada bırakıyorum: /bin/sh: -c: line 0: syntax error near unexpected token (''
David

Yanıtlar:


381

GNU Make belgelerinden,

5.3.1 Choosing the Shell
------------------------

The program used as the shell is taken from the variable `SHELL'.  If
this variable is not set in your makefile, the program `/bin/sh' is
used as the shell.

Öyleyse SHELL := /bin/bashmakefile'ınızın üstüne koyun ve gitmek için iyi olmalısınız.

BTW: Bunu en azından GNU Make için bir hedef için de yapabilirsiniz. Her hedefin kendi değişken atamaları olabilir, örneğin:

all: a b

a:
    @echo "a is $$0"

b: SHELL:=/bin/bash   # HERE: this is setting the shell for b only
b:
    @echo "b is $$0"

Yazdırılacak:

a is /bin/sh
b is /bin/bash

Daha fazla ayrıntı için belgelerdeki "Hedefe Özgü Değişken Değerleri" konusuna bakın. Bu çizgi Makefile'de herhangi bir yere gidebilir, hedefin hemen önünde olmak zorunda değildir.


43
500 lütuf bir teklif bekliyor man. Zamanlamalar hakkında konuşun. : P
SiddharthaRT

3
@inLoveWithPython infoAslında, ama sanırım Andy'ye gerçekten yardımcı oldu. Böyle günlerim olduğunu biliyorum ...
derobert

3
şüphe durumunda, @derobert tam anlamıyla: SHELL=/bin/bashMakefile'nin ilk satırı olarak (veya yorumdan hemen sonra).
Yauhen Yakimovich


2
SHELL değişkenini yalnızca belirli bir hedef için değiştirmek, ancak diğerlerini dokunmadan değiştirmek mümkün müdür?
antred

18

bashDoğrudan arayabilir , -cbayrağı kullanabilirsiniz :

bash -c "diff <(sort file1) <(sort file2) > $@"

Tabii ki, $ @ değişkenine yönlendiremeyebilirsiniz, ancak bunu yapmaya çalıştığımda -bash: $@: ambiguous redirectbir hata mesajı olarak aldım , bu yüzden bu konuya girmeden önce buna bakmak isteyebilirsiniz ( bash 3.2 kullanarak. bir şey, belki sizinki farklı çalışır).


4

Taşınabilirlik önemliyse, Makefile'nizdeki belirli bir kabuğa bağımlı olmak istemeyebilirsiniz. Tüm ortamlarda bash bulunmaz.


4

Varsayılan kabuğu kullanmak yerine bash'ı doğrudan Makefile'nizden arayabilirsiniz:

bash -c "ls -al"

onun yerine:

ls -al

1
makeSHELL ortam değişkeninin değerini göz ardı ettiğini unutmayın .
choroba

2

SHELL değişkeninizi bash'a işaret edecek şekilde ayarlamadan bunu yapmanın bir yolu vardır. SHELL, sonraki makyaj dosyaları tarafından miras alınmadığı veya ortamdan alınmadığı için çok sayıda dosyanız varsa bu yararlı olabilir. Ayrıca, kodunuzu derleyen herkesin sistemlerini bu şekilde yapılandırdığından emin olmanız gerekir.

sudo dpkg-reconfigure dashKomut istemine 'no' komutunu çalıştırır ve cevaplarsanız, sisteminiz varsayılan kabuk olarak tire kullanmaz. Daha sonra bash'ı işaret edecektir (en azından Ubuntu'da). Ancak sistem kabuğunuz olarak tire kullanmanın biraz daha verimli olduğunu unutmayın.


1
Ad altında çağrıldığında sh, bash uyumluluk modunda çalışır ( set -o posix). OP'nin kullanmaya çalıştığı işlevsellik, işlem ikamesi, bu modda kullanılamaz.
Charles Duffy

1

Aynı şekilde çalışan bir yol da hedefinizin ilk satırına şu şekilde koymaktır:

your-target: $(eval SHELL:=/bin/bash)
    @echo "here shell is $$0"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.