Я новичок в 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-файлы и почему нужно учиться обращаться с ними, так что я не такой уж эксперт.
Ваша цель сборки %.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
затем вы используете неявное правило, чтобы написать цель только один раз, затем вам нужно написать команды в терминах цели.
Вы должны сделать переменную, прежде чем поместить ее в 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