В чем разница между процентом и звездочкой (звездочкой) в makefile preconditions

В чем разница между процентом и звездочкой (звездочкой) в makefile preconditions

Я пытаюсь понять, почему в некоторых Makefile есть предварительные условия %.txt, а в других — *.txt.

Я создал такую ​​структуру папок.

$ tree .
.
├── hi1.txt
├── hi2.txt
├── hi3.txt
└── Makefile

Сначала я попробовал это.

foo.txt: *.txt
    echo $^

И он делает то, что я ожидаю.

$ make
echo hi1.txt hi2.txt hi3.txt
hi1.txt hi2.txt hi3.txt

Но потом я увидел, что некоторые Makefiles используют его %.txtкак подстановочный знак. Так что я попробовал это следующим.

foo.txt: %.txt
    echo $^

Однако это приводит к ошибке.

$ make
make: *** No rule to make target '%.txt', needed by 'foo.txt'.  Stop.

Может ли кто-нибудь объяснить, почему это происходит?

GNU Make 4.3

решение1

В makeзнак процента используется для сопоставления с образцом, и для этого требуется один в целевом объекте, а также (по крайней мере) один в предварительных условиях:

%.o: %.c
        $(CC) $(CFLAGS) -c -o $@ $<

С помощью этого make-файла мы указываем, что для сборки чего-либо, имя файла которого заканчивается на .o, вам нужен файл с тем же префиксом, но заканчивающийся на , .cа не на.o

Чтобы иметь возможность построить эти правила, вам, очевидно, нужно иметь возможность ссылаться на цель, а также на предпосылки; вот где появляются переменные $@и . означает «цель этого правила», а означает «первое перечисленное предварительное условие этого правила». Если вам нужно построить команду, которая использует$<$@$<всепредварительных условий (например, для компоновки исполняемого файла), то вы можете использовать переменную $^:

%: %.o lib.o
        $(CC) $(LDFLAGS) -o $@ $^

Если вы объедините два приведенных выше примера фрагментов makefile в один makefile и у вас есть файл 'lib.c' с некоторым общим кодом, который вы хотите использовать в нескольких программах на языке C в том же каталоге, то вы можете добавить любой случайный .cфайл, скажем foo.c, , и скомпилировать его в программу foo, которая также будет связана с кодом в lib.c, без необходимости внесения каких-либо изменений в ваш makefile.

Обратите внимание, что также возможны шаблоны с одной и той же целью, если предварительные условия различны; например, будет работать следующее:

%.o: %.c
        $(CC).....
%.o: %.cpp
        $(CXX).....

то есть, он будет работать так, как и ожидалось, пока у вас нет исходных файлов C++ в этом каталоге, которые случайно имеют то же имя (без расширения), что и исходный файл C. Если это так, версия C++ будет проигнорирована, и вместо нее будет скомпилирован исходный файл C (потому что правило C указано первым в makefile)

Для получения более подробной информации см.соответствующий разделв руководстве GNU make.

Связанный контент