2017-01-04 2 views
0

У меня возникли проблемы с пониманием того, как Makefile имеет дело с расширением переменной, когда правило создает файл, который должен изменять поведение расширения подстановки.Расширение переменной Makefile с помощью подстановочного знака, когда правило создает новый файл

Например, у меня есть следующий Makefile:

TEXT_FILES = $(wildcard *.txt) 

all: create test 

create: 
    @touch hello.txt 

test: 
    @printf "The files are $(TEXT_FILES)\n" 

То, что я ожидал получить при запуске make является

Файлы hello.txt

потому что TEXT_FILES должен оцениваться, когда он вызывается, а не когда определено. Тем не менее, я на самом деле получить (бег сделать в два раза)

Файлы (переменная пуста при выполнении в первый раз)

Файлы hello.txt (найдены в следующий раз)

Как я могу получить желаемое поведение?

+0

Найдено это, возможно, связанный с этим вопрос здесь http://stackoverflow.com/questions/22630996/makefile-sequential-execution Тем не менее, никакого решения. – mbrandalero

+0

Каков ваш * точный * прецедент? Может быть, это XY-проблема. – uzsolt

+0

У меня есть папка с шаблонами в коде C, которые преобразуются 1 - 1 в нечто другое (также в C), но в процессе могут быть созданы дополнительные файлы. Найдено: http://stackoverflow.com/questions/9744865/how-to-force-revaluation-of-variables-in-makefile Очевидно, расширение шаблона происходит задолго до того, как оцениваются правила, поэтому нет способа добиться желаемого поведения – mbrandalero

ответ

1

Это поведение является результатом внутреннего кэша make. По соображениям производительности make будет кэшировать состояние файловой системы, которое, по его мнению, является истинным, основываясь на том, что было раньше, плюс сделанные им изменения (из-за правил, которые были вызваны).

Такие функции, как wildcard, будут запрашивать внутренний кеш, если он доступен.

Однако в вашей ситуации вы не описываете фактическое поведение своих правил: вы не сказали, что это правило создает дополнительный файл. В результате make не будет обновлять свой кеш, а функция wildcard никогда не находит этот секретный файл.

Вы не говорите, что хотите делать точно, но почему бы вам просто не использовать подстановочные средства оболочки вместо функции wildcard? Оболочка, очевидно, не имеет ни малейшего представления о внутренних кэшей сделать в:

TEXT_FILES = *.txt 

all: create test 

create: 
     @touch hello.txt 

test: 
     @echo The files are $(TEXT_FILES) 
+0

Я должен указать, что этот make-файл не является безопасным с точки зрения параллелизма: вы не можете использовать параметр '-j' и использовать его надежно. Вам нужно сделать 'create' необходимым условием' test' для этого. – MadScientist

+0

Это сработало! Благодарю. Таким образом, кажется, что, когда функция '' wildcard '' вычисляется при анализе make, подстановочный знак оболочки '*' оболочки расширяется только после этого, когда расширяется переменная 'TEXT_FILES'. Это верно? – mbrandalero

+1

Не совсем.Функции Make, включая подстановочный знак, расширяются в зависимости от того, где они появляются в make-файле, см. Https://www.gnu.org/software/make/manual/html_node/Reading-Makefiles.html для правил. Поскольку в вашем примере появляется «подстановочный знак», он не разворачивается до тех пор, пока make не собирается запускать этот конкретный рецепт (а не при анализе make-файла). Однако из-за поведения кэширования make, как я описал выше, функция подстановочных знаков соответствует только файлам, которые существовали при запуске или создании значков. Это характерно для функции подстановочных знаков. – MadScientist