Makefiles: конкретные «нет входных файлов», автоматические переменные

Я новичок в makefiles, и они озадачивают меня. У меня есть следующая иерархия папок:

Папка с именем lib содержит буксирные папки: include (с файлом mylib.h) а также src (с файлом mylib.cpp). Он также содержит Makefile, который по какой-то причине выдает мне ошибку.

Полный make-файл:

CFLAGS = -Wall -fPIC
OBJECTS = mylib.o

all: libmine.so

libmine.so: $(OBJECTS)
g++ -shared $(CFLAGS) \
-o libmine.so \
$(OBJECTS)

%.o:        src/%.cpp include/%.h
g++ $(CFLAGS) \
-I include \
-o %.o \
-c src/%.cpp

clean:
rm src/*.o
rm libmine.so

Ошибка

mr209@Quantum:~/Desktop/hw1/lib$ make
g++ -Wall -fPIC \
-I include \
-o %.o \
-c src/%.cpp
g++: error: src/%.cpp: No such file or directory
g++: fatal error: no input files
compilation terminated.
make: *** [mylib.o] Error 4

Но файл является подарок. Таким образом, make делает странные вещи, заставляя его не быть в состоянии найти .cpp файл.

Чтобы сделать libmine.so, g++ придется что-то делать с mylib.oи для общего .o файл Я написал несколько строк кода.

Вот о чем я думал: чтобы сделать libmine.so, g++ придется что-то делать с mylib.o, Таким образом, в libфайл с именем mylib.o должен появиться. Используя общий %.0 Правило, этот файл сделан из mylib.cpp в src а также mylib.h в include (отсюда первая строка %.o правило). Файл сделан с использованием g++, который должен смотреть в include для дополнительных заголовков, производит mylib.o как вывод и компилирует src/mylib.cpp, но -c гарантирует, что .o файл производится.

Очевидно, что-то идет не так, и я не могу понять, что. Всего 2 дня назад я узнал, что такое Make-файлы и почему нужно учиться обращаться с ними, так что я не такой уж эксперт.

2

Решение

Ваша цель сборки %.o неправильно написано. Вы не можете использовать % в разделе команд, поэтому имена файла назначения и зависимого файла никогда не будут совпадать.

Правильное изменение заключается в следующем:

%.o: src/%.cpp include/%.h
g++ $(CFLAGS) \
-I include \
-o $@ \
-c src/$(@:%.o=%.cpp)

Просто чтобы объяснить изменения, -o нужен целевой файл, который почти всегда записывается как $@ в Makefiles, так как это имя цели.

Во-вторых, исходный файл должен быть определен с точки зрения цели, рассматриваемый оператор является оператором замены шаблона. $(@:%.o=%.cpp), так что это сделать, это взять цель — которая будет соответствовать имени файла <blah>.o, то это образец соответствия заменяет .o с .cpp,

Так что в случае с целью mylib.oпеременная $@ является mylib.oи результат выполнения $(@:%.o=%.cpp) это повернуть mylib.o в mylib.cpp, В результате это ожидаемый файл, который компилируется, и ожидаемая цель — сборка.

Правила, использующие % Шаблоны в них — это так называемые неявные правила, которые используются для уменьшения сложности написанного кода — если у вас была куча файлов, которые совместно использовали целевой шаблон: blah.o: src/blah.cpp src/blah.hзатем вы используете неявное правило, чтобы написать цель только один раз, затем вам нужно написать команды в терминах цели.

2

Другие решения

Вы должны сделать переменную, прежде чем поместить ее в g ++
лайк :

FT_C= $(src/%.cpp)
FT_O=$(FT_C:.c=.o)

а также

g++ $(CFLAGS) -I include -o $(FT_O) -c $(FT_C)

и не кладите свой .h в сборник ‘-I’ здесь для этого.

Посмотрите этот пример, если вы хотите понять, что я имею в виду:

https://github.com/emericspiroux/wolf3d/blob/master/libft/Makefile

0