#c #makefile #compilation #linker #gnu-make
#c #makefile #Сборник #компоновщик #gnu-make
Вопрос:
В настоящее время я борюсь с 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
Это компилируется при вызове из folder1.
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
lt; -o $@
Я вызываю make all из folder1, но это не работает.Я попытался найти учебные пособия по c make, но не смог найти ни одного с подробными неявными и шаблонными правилами.
Это ошибка, которую я получаю
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.
Я попытался в folder1 запустить эти команды, и он компилируется правильно.
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
Комментарии:
1. Вы говорите, что это не работает. Не могли бы вы поделиться сообщением об ошибке? Это может помочь нам диагностировать проблему
2. g -10 -std=c 2a -O3 -fno-pic -no-pie -Wall main.cpp foo.cpp -o a.out Он пытается выполнить эту строку и говорит, что bar.hpp не может быть найден. Я не понимаю, почему он пытается создать файл.out из файлов .cpp, пропуская файлы .o.
Ответ №1:
Эта строка неверна:
OBJ = $(SRC: .cpp=.o)
Добавив пробел перед .cpp
тем, что вы говорите, это OBJ
должно заменить все слова в переменной SRC
, которые заканчиваются на « .cpp
«, на окончание .o
. Но в переменной нет слов SRC
, которые заканчиваются на « .cpp
«, поэтому никаких изменений не вносится, а значение OBJ
совпадает со значением SRC
.
Итак, ваше правило:
a.out : main.cpp foo.cpp
таким .o
образом, файлы не создаются, потому что ваша цель не зависит от них.
Удалите пробел:
OBJ = $(SRC:.cpp=.o)
Комментарии:
1. Большое вам спасибо, есть ли какой-нибудь учебник или ссылка для понимания подобных правил? Также является ли излишним добавлять $(INC) в определение шаблона %o: %.cpp $(INC)?
2. Вот руководство GNU make. При написании ваших make-файлов вы должны использовать описание операций точно так, как показано там: добавление пробелов там, где их раньше не было, может изменить смысл вещей. Да, это избыточно, потому что вы уже указали
$(OBJ) : $(INC)
, что оно вам не нужно в правиле шаблона.