В настоящее время я борюсь с make, любой совет или учебник очень ценятся. Структура папок моего проекта выглядит так:
/project
bar.hpp
/folder1
main.cpp // #include "foo.hpp" #include "bar.hpp"
foo.cpp // #include "foo.hpp" #include "bar.hpp"
foo.hpp // #include "bar.hpp"
Makefile
Это компилируется при вызове из папки1.
g++-10 -std=c++2a -O3 -fno-pic -no-pie -Wall -I../ main.cpp foo.cpp
Я написал следующий Makefile, но он не работает так, как я ожидал:
CXX = g++-10
CXXFLAGS = -std=c++2a -O3 -fno-pic -no-pie -Wall
CPPFLAGS = -I../
.PHONY : all clean distclean
EXE = a.out
SRC = main.cpp foo.cpp
OBJ = $(SRC: .cpp=.o)
INC = $(wildcard *.hpp) ../bar.hpp
all : $(EXE)
clean :
$(RM) *.o
distclean : clean
$(RM) $(EXE)
$(EXE) : $(OBJ)
$(CXX) $(CXXFLAGS) $^ -o $@
$(OBJ) : $(INC) // I hope this means that all object files depend on all header files?
%.o : %.cpp $(INC)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
Я вызываю make all из папки1, но это не работает.
Я попытался найти учебники по созданию С++, но не смог найти ни одного с подробными неявными и шаблонными правилами.
Это ошибка, которую я получаю
g++-10 -std=c++2a -O3 -fno-pic -no-pie -Wall main.cpp foo.cpp -o a.out
main.cpp:1:10: fatal error: bar.hpp: No such file or directory
1 | #include "bar.hpp"
| ^~~~~~~~~
compilation terminated.
In file included from foo.cpp:1:
foo.hpp:1:10: fatal error: bar.hpp: No such file or directory
1 | #include "bar.hpp"
| ^~~~~~~~~
compilation terminated.
Я попытался в папке1 запустить эти команды, и они правильно компилируются.
g++-10 -std=c++2a -O3 -fno-pic -no-pie -Wall -c foo.cpp -o foo.o -I../
g++-10 -std=c++2a -O3 -fno-pic -no-pie -Wall -c main.cpp -o main.o -I../
g++-10 -std=c++2a -O3 -fno-pic -no-pie -Wall -o main main.o foo.o
g++-10 -std=c++2a -O3 -fno-pic -no-pie -Wall main.cpp foo.cpp -o a.out Он пытается выполнить эту строку и говорит, что bar.hpp не может быть найденный. Я не понимаю, почему он пытается построить a.out из файлов .cpp, пропуская файлы .o.
Эта строка неверна:
OBJ = $(SRC: .cpp=.o)
Добавляя пробел перед .cpp
, вы говорите, что OBJ
должен заменить все слова в переменной SRC
, которые заканчиваются на « .cpp
», на окончание .o
. Но в переменной SRC
нет слов, оканчивающихся на « .cpp
», поэтому никаких изменений не производится, и значение OBJ
совпадает со значением SRC
.
Итак, ваше правило:
a.out : main.cpp foo.cpp
поэтому файлы .o
не создаются, потому что ваша цель не зависит от них.
Уберите пробел:
OBJ = $(SRC:.cpp=.o)
Большое спасибо, есть ли какой-нибудь учебник или справочник, чтобы понять правила, подобные этому? Также излишне ли добавлять $(INC) в определение шаблона %o : %.cpp $(INC)?
Есть руководство по созданию GNU. При написании ваших make-файлов вы должны использовать описание операций именно так, как показано здесь: добавление пробелов там, где их раньше не было, может изменить смысл вещей. Да, это избыточно, потому что вы уже указали $(OBJ) : $(INC)
, поэтому вам это не нужно в правиле шаблона.
Вы говорите, что это не работает. Не могли бы вы поделиться сообщением об ошибке? Это может помочь нам диагностировать проблему