[email protected]и $<mean? - программирование" />

Что означают символы makefile [email protected]и $<mean?

CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o [email protected]

.cpp.o:
    $(CC) $(CFLAGS) $< -o [email protected]

Что делают [email protected] и $< точно?

Ответ 1

[email protected] - имя создаваемого файла, а $< - первое обязательное условие (обычно это исходный файл). Вы можете найти список всех этих специальных переменных в GNU Make manual.

Например, рассмотрим следующее объявление:

all: library.cpp main.cpp

В этом случае:

  • [email protected] оценивается как all
  • $< соответствует library.cpp
  • $^ оценивается как library.cpp main.cpp

Ответ 2

[email protected] и $< называются автоматическими переменными. Переменная [email protected] представляет имя файла, который был создан (то есть цель), а $< представляет первую предпосылку, необходимую для создания выходного файла.
Например:

hello.o: hello.c hello.h
         gcc -c $< -o [email protected]

Здесь hello.o - выходной файл. Это то, что расширяет [email protected]. Первая зависимость - hello.c. Это то, что расширяет $<.

Флаг -c генерирует файл .o; см. man gcc для более подробного объяснения. -o указывает выходной файл для создания.

Дополнительную информацию вы можете прочитать в этой статье о Linux Makefiles.

Также вы можете проверить руководства по GNU make. Это облегчит создание Make файлов и их отладку.

Если вы выполните эту команду, она выведет базу данных makefile:

make -p 

Ответ 3

От Управление проектами с помощью GNU Make, 3rd Edition (в соответствии с лицензией GNU Free Documentation License):

Автоматические переменные устанавливаются make после согласования правила. Oни обеспечить доступ к элементам из целевых и предварительных списков, чтобы вам не нужно явно указывать имена файлов. Они очень полезны для избежания дублирования кода, но имеют решающее значение при определении более общие правила шаблонов.

Существует семь "основных" переменных:

  • [email protected]: имя файла, представляющего цель.

  • $%: Элемент имени файла спецификации члена архива.

  • $<: имя файла первого предварительного условия.

  • $?: имена всех предварительных условий, которые новее, чем цель, разделенных пробелами.

  • $^: имена файлов всех предварительных условий, разделенных пробелами. Эта список имеет дубликаты имен файлов, поскольку для большинства целей, таких как компиляция, копирование и т.д., дубликаты не нужны.

  • $+: Подобно $^, это имена всех разделяемых предварительных условий пробелами, за исключением того, что $+ содержит дубликаты. Эта переменная была созданный для конкретных ситуаций, таких как аргументы для компоновщиков, где дублирующие значения имеют смысл.

  • $*: Строка имени целевого файла. Основанием обычно является имя файла без его суффикса. Его использование вне правил шаблона не рекомендуется.

Кроме того, каждая из перечисленных выше переменных имеет два варианта: совместимость с другими марками. Один вариант возвращает только каталог часть значения. Это указывается путем добавления "D" к символ, $(@D), $(<D) и т.д. Другой вариант возвращает только файл часть значения. Это указывается добавлением "F" к символ, $(@F), $(<F) и т.д. Обратите внимание, что эти имена вариантов больше, чем один символ длинный и поэтому должен быть заключен в круглые скобки. GNU make обеспечивает более читаемую альтернативу с dir и notdir функции.

Ответ 4

[email protected] и $< являются специальными макросами.

Где:

[email protected] - это имя файла цели.

$< - это имя первой зависимости.

Ответ 5

Makefile создает исполняемый файл hello, если изменился какой-либо из main.cpp, hello.cpp, factorial.cpp. Самый маленький возможный Makefile для достижения этой спецификации мог бы быть:

hello: main.cpp hello.cpp factorial.cpp
    g++ -o hello main.cpp hello.cpp factorial.cpp
  • pro: очень легко читать
  • con: кошмар обслуживания, дублирование зависимостей на С++
  • con: проблема эффективности, мы перекомпилируем все С++, даже если был изменен только один

Чтобы улучшить вышеизложенное, мы компилируем только те файлы С++, которые были отредактированы. Затем мы просто связываем результирующие объектные файлы вместе.

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

main.o: main.cpp
    g++ -c main.cpp

hello.o: hello.cpp
    g++ -c hello.cpp

factorial.o: factorial.cpp
    g++ -c factorial.cpp
  • pro: исправляет проблему с эффективностью
  • con: новый кошмар для обслуживания, потенциальная опечатка на правилах объектных файлов.

Чтобы улучшить это, мы можем заменить все правила объектных файлов одним правилом .cpp.o:

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

.cpp.o:
    g++ -c $< -o [email protected]
  • pro: вернуться к созданию короткого файла makefile, несколько легко читаемому

Здесь правило .cpp.o определяет, как построить anyfile.o из anyfile.cpp.

  • $< соответствует первой зависимости, в данном случае anyfile.cpp
  • [email protected] соответствует цели, в данном случае anyfile.o.

Другие изменения, присутствующие в Makefile, следующие:

  • Упрощение преобразования компиляторов из g++ в любой компилятор С++.
  • Упрощение изменения параметров компилятора.
  • Упрощение изменения параметров компоновщика.
  • Упрощение изменения исходных файлов на С++ и вывод.
  • Добавлено правило "все" по умолчанию, которое действует как быстрая проверка, чтобы убедиться, что все исходные файлы присутствуют до того, как сделана попытка создать ваше приложение.

Ответ 6

Например, если вы хотите скомпилировать исходники, но объекты в другом каталоге:

вам нужно сделать:

gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...

но в большинстве случаев (с другими макросами) результат будет:

gcc -c -o <all OBJ path> <all SRC path>

так что это ничего не скомпилирует ^^ и вы не сможете поместить ваши файлы объектов в другой каталог :(

решение состоит в том, чтобы использовать эти специальные макросы

[email protected] $<

это создаст файл .o(obj/file.o) для каждого файла .c в SRC (src/file.c)

$(OBJ):$(SRC)
   gcc -c -o [email protected] $< $(HEADERS) $(FLAGS)

это означает:

    [email protected] = $(OBJ)
    $< = $(SRC)

но строки за строками INSTEAD всех строк OBJ, за которыми следуют все строки SRC