Domanda

Sto utilizzando il codice simile al seguente in un Makefile:

empty:=
space:= $(empty) $(empty)
path_escape = $(subst $(space),\$(space),$(1))

TOP=$(call path_escape,$(abspath .))
TARGET=$(TOP)/foo

$(info TOP='$(TOP)')
$(info TARGET='$(TARGET)')

all: $(TARGET)

$(TARGET):
    touch '$(notdir $@)'

.PHONY: $(TARGET)

Se io uso questo in una directory senza spazi, diciamo space-test, funziona benissimo:

$ make
TOP='/tmp/space-test'
TARGET='/tmp/space-test/foo'
touch 'foo'

Tuttavia, se lo uso in una directory con gli spazi, dire space test, quindi $(notdir) fa la cosa sbagliata:

TOP='/tmp/space\ test'
TARGET='/tmp/space\ test/foo'
touch 'space foo'

Quello che sta succedendo qui è che $(notdir) interpreta /tmp/space test/foo come due percorsi e restituisce la "parte del file" di sia (vale a dire, space e foo). La parte strana di questo è che TARGET sia correttamente sfuggito; in qualche modo, all'interno della regola o $(notdir) all'interno, le fughe backslash vengono ignorati.

Che cosa sto facendo male qui?

È stato utile?

Soluzione

La funzione $(notdir) in GNU Make prende una lista di argomenti, separati da spazi. Alcune funzioni supportano spazi fuga con \\, ma $(notdir) non è uno di loro.

Questo dovrebbe funzionare:

s? = $(subst $(empty) ,?,$1)
?s = $(subst ?, ,$1)
notdirx = $(call ?s,$(notdir $(call s?,$1)))

$(TARGET):
    touch '$(call notdirx,$@)'

Questo definisce una versione "spazio-safe" di notdir chiamato notdirx. E 'abbastanza semplice: s? trasforma prima tutti gli spazi in punti interrogativi (sperando che non possono essere presenti nei nomi di file), e ?s converte indietro. Tra possiamo tranquillamente chiamare la funzione notdir originale.

Per un riassunto eccellente su GNU Make e gli spazi nei nomi dei file, vedere GNU make incontra i nomi di file con spazi tra loro .

Altri suggerimenti

Supponendo di avere una shell Unix, si potrebbe sborsare:

notdirx = $(shell basename '$1')
dirx = $(shell dirname '$1')

Una strategia simile potrebbe applicarsi ad altre funzioni. Basta ricordare le virgolette intorno alla variabile che contiene il testo da spazi infetti che si vuole trattare come un unico argomento. Questo vi proteggerà anche da altri caratteri speciali (ad eccezione di virgolette!). Ecco un esempio di doppio backslash sfuggire eventuali spazi nel risultato di un glob wildcard:

$(shell ls -1 '*.foo' | sed 's/ /\\\\ /g')

di Windows sta mettendo in parentesi i nomi delle directory ora, anche:. C:\Program Files (x86)\ Non è ancora chiaro per me quali sono le implicazioni di questo quando si utilizza make

Questo è solo un salto nel buio:

TOP='"/home/chris/src/tests/make/space test"'
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top