Я изучаю make-файлы. То, что я пытался написать свой собственный после небольшого чтения. Проблема в том, что я всегда получаю ошибки, связанные со стандартом c ++ 11, хотя я помещаю необходимый флаг компилятора в make-файл. Вот ошибка:
/usr/include/c++/4.6/bits/c++0x_warning.h:32:2: error:
#error This file requires compiler and library support for the upcoming
ISO C++ standard, C++0x. This support is currently experimental, and
must be enabled with the -std=c++0x or -std=gnu++0x compiler options.
А вот и make-файл:
CC = g++
LD = g++
NAME = app
OBJ_DIR = obj
SRC_DIR = src
CXX_FLAGS = -std=c++0x
SRC = $(shell find $(SRC_DIR) -type f -regex ".*\.cpp")
OBJ = $(subst $(SRC_DIR), $(OBJ_DIR), $(addsuffix .o, $(basename $(SRC))))
all: $(NAME)
$(NAME): $(OBJ)
$(LD) $< -o $@ $(CXX_FLAGS)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CC) $< -o $@ $(CXX_FLAGS)
clean:
rm $(NAME) $(OBJ_DIR) -rf
Обратите внимание, что я поставил CXX_FLAGS после проверки других вопросов о переполнении стека, но безрезультатно. Я все еще получаю ту же ошибку. Это как make игнорирует мой флаг. Есть ли этому решение?
И да, я могу скомпилировать с флагом -std = c ++ 0x без make, так что мой компилятор, очевидно, не проблема.
Есть ли в каталоге obj
существовать?
Лучший способ написать это было бы:
OBJ = $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC))
Можете добавить $(info OBJ = $(OBJ))
и т.д. после этих строк, чтобы распечатать их. В основном результаты этих операций не соответствуют вашим шаблонным правилам, поэтому make использует стандартные шаблонные правила.
Я настоятельно не одобряю такого рода вещи (используя find
) хоть. Я всегда, всегда печатаю исходные файлы, которые хочу скомпилировать. Добавление нового файла занимает не более нескольких секунд, и это гарантирует, что вы не начнете выбрасывать в свою программу случайный мусор, когда вы меньше всего этого ожидаете.
Ваша команда компиляции также неверна: вы забыли -c
флаг, который важен. Я рекомендую людям просто использовать ту же команду, что и правила по умолчанию (запустить make -p -f/dev/null
чтобы увидеть правила по умолчанию).
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(COMPILE.cc) $(OUTPUT_OPTION) $<
Это требует от вас использования стандартных переменных флагов (т.е. CXX
не CC
а также CXXFLAGS
не CXX_FLAGS
) но это хорошая идея в любом случае.
Это на самом деле не использует ваше правило для создания объектного файла. Прокомментируйте его, и вы увидите, что он по-прежнему вызывает «g ++ -c».
Частично проблема заключается в том, что команда subst, которую вы используете для определения OBJ, интерпретирует свои аргументы как литералы. Перепишите это как
OBJ = $(subst src, obj, $(addsuffix .o, $(basename $(SRC))))
и вы по крайней мере получите желаемый OBJ.
У вас есть пробелы на концах строк, которые определяют SRC_DIR
а также OBJ_DIR
, Это означает, что subst
не буду ничего делать, так как ищет "src "
скорее, чем "src"
,
В свою очередь это означает, что он будет пытаться построить src/whatever.o
скорее, чем obj/whatever.o
и, поскольку для этого нет правила, оно будет возвращаться к правилу по умолчанию, а не к вашему.
Как только вы это исправите, вам нужно будет добавить -c
к команде компиляции, чтобы создать объектный файл, а не исполняемый файл.