2013-02-24 9 views
11

Podsumowanie:
używam GNU make (3.81) na systemie UNIX jak i Zabrakło mi do problemu gdzie funkcja $(wildcard, pattern) nie jest w stanie znajdź plik wygenerowany przez (przypuszczalnie/pozornie?) wcześniej wykonaną recepturę, podczas gdy inne programy (np. ls) są w stanie zweryfikować jego istnienie. Chciałbym wiedzieć, dlaczego funkcja wieloznaczna nie zwraca niczego, gdy jest rozwinięta (do pustego ciągu) i jak mogę ją znaleźć, aby znaleźć wygenerowany plik.GNU make funkcja wieloznaczny nie znajdzie czasu wykonywania wygenerowanych plików

Przypadek testowy: Poniższy przypadek testowy ilustruje problem.
Makefile treść:

.PHONY: build clean 

test: 
    @echo "Creating test file 'test'." 
    @echo "this is a test file" > test 

build: test 
    @echo "Directory contents:" 
    @ls 
    @echo "Test file contents:" 
    @cat test 
    @echo "Wildcard output:" 
    @echo $(wildcard test) 

clean: 
    @rm -f test 

przebiegu makefile dwukrotnie (wtedy czyszczenia) pokazuje, że tylko na drugi bieg robi to wykryć utworzony plik.
wyjściowa:

Creating test file 'test'. 
Directory contents: 
makefile test 
Test file contents: 
this is a test file 
Wildcard output: 

Directory contents: 
makefile test 
Test file contents: 
this is a test file 
Wildcard output: 
test 

Aby odtworzyć:
Zapisz makefile w pustym katalogu, a następnie uruchomić "make build; make build; make clean".

Badania:
Kolejność, w której przesłanki cel są przetwarzane jest independent of the order in which they appear in the list after the colon zatem wyraźne zależności między wstępnych muszą być wprowadzone, jeśli chcesz określić kolejność, w jakiej są one przetwarzane.

Jednak nie sądzę, abym mógł rozebrać te zależności; build zależy od test, a test odpowiada plikowi, który nie istnieje i jest generowany przez jego recepturę. Przypuszczałem, że będzie on obecny do czasu przetworzenia przepisu na build.

Z mojej wiedzy na temat tworzenia makefile, funkcja wieloznaczna wewnątrz przepisu nie powinna być rozwijana, dopóki nie zostanie przetworzona. Jednak wyraźnie widzę różnicę między wyjściami wbudowanej funkcji make a wyjściami zwykłych narzędzi dostępnych przez powłokę, więc to przypuszczenie jest prawdopodobnie błędne, ale nie spotkałem się z żadnym dobrym wyjaśnieniem tego, co powinno tak się tu dzieje, nawet w podręczniku GNU make.

N.B. Celem tego pytania jest po prostu zrozumienie działania funkcji wieloznacznej związanej z tym problemem; istnieje praktyczny przypadek użycia, z którego wydestylowałem tę rozwodnioną wersję, ale bardziej interesuje mnie ta sprawa.

Odpowiedz

4

GNU make rozszerza wszystkie poleceń za cel przed wykonaniem dowolny z nich. W tym kontekście "expand" oznacza "zamień wszystkie odwołania zmiennych na ich wartości (rekursywnie) i oceń wszelkie odwołania do funkcji." $(wildcard) to oczywiście odwołanie do funkcji. Ponieważ rozwijanie następuje przed wykonaniem któregokolwiek z poleceń, oczywiście plik test nie może zostać znaleziony - nie został jeszcze utworzony. Po drugim uruchomieniu kompilacji istnieje już test, dzięki czemu może ją znaleźć.

chodzi wyciągu że kolejność, w której wymagania są przetwarzane: technicznie GNU make nie udziela żadnych gwarancji co do kolejności, ale praktycznie mówiąc prereqs są przetwarzane od lewej do prawej, i pomimo prób podejmowanych przez purystów, aby zmienić że (dla wyłącznego celu wkręcania się w ludzi, którzy nie mają całkowicie określonych zależności), prawdopodobieństwo, że GNU spowoduje, że faktycznie zmieni ten szczegół implementacji jest znikomo małe. Jednak można tylko polegać na tym zamówieniu w wersji seryjnej. Jeśli uruchomisz kompilację równolegle, wtedy sprawy stają się nieco trudniejsze: GNU make czy nadal przetwarza żądania wstępne w kolejności od lewej do prawej, ale nie czeka już na zakończenie, zanim zacznie następny, więc w efekcie może wydawać się przetwarzane w sposób losowy lub "dowolny", zależnie od zależności między prereq, dlatego dobrze jest określić te zależności.

Powiązane problemy