Ошибка Makefile С++ 11

Я изучаю make-файлы. Что я пробовал, так это написать свой собственный после небольшого чтения. Проблема в том, что я всегда получаю ошибки, связанные со стандартом С++ 11, даже если я ставлю нужный флаг компилятора в makefile. Вот ошибка:

/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.

А вот и makefile:

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, так что мой компилятор явно не проблема.


person darxsys    schedule 08.05.2013    source источник
comment
make должен распечатывать каждую команду по мере ее выполнения. Какой g++ вызов непосредственно предшествует ошибке?   -  person cdhowie    schedule 08.05.2013
comment
@cdhowie g++ -c -o src/normal.o src/normal.cpp Похоже, он игнорирует мой флаг.   -  person darxsys    schedule 08.05.2013
comment
Так что проблема вовсе не в флаге C++11. Ваш фактический вопрос заключается в том, почему мое правило makefile не используется. Если бы это было так, я бы ожидал, что строка будет g++ src/normal.c -o obj/normal.o -std=c++0x   -  person cdhowie    schedule 08.05.2013
comment
Случайное предположение: вам нужно $(CXX_FLAGS) перед $‹   -  person Mats Petersson    schedule 08.05.2013
comment
Ладно, я новичок. Спасибо за исправление. Любые идеи? @MatsPetersson нет. Пробовал это.   -  person darxsys    schedule 08.05.2013
comment
@MatsPetersson Нет. Его правило вообще не используется.   -  person cdhowie    schedule 08.05.2013
comment
Да, увидел этот комментарий сразу после моего комментария... :(   -  person Mats Petersson    schedule 08.05.2013
comment
Я бы предложил добавить такое правило: test: echo $(SRC); echo $(OBJ) (с новыми строками, где это уместно), а затем выполнить make test. Возможно, содержимое этих переменных не соответствует вашим ожиданиям.   -  person cdhowie    schedule 08.05.2013
comment
Вы говорите, что вывод make: g++ -c -o src/normal.o src/normal.cpp Если это так, он игнорирует больше, чем ваш флаг, он пытается поместить normal.o в src, поэтому он не соответствует правило. Почему OBJ оказался src/normal.o, я не знаю.   -  person Joel Klinghed    schedule 08.05.2013


Ответы (3)


Каталог 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), но в любом случае это хорошая идея.

person MadScientist    schedule 08.05.2013

На самом деле это не использование вашего правила для создания объектного файла. Закомментируйте его, и вы увидите, что он по-прежнему вызывает "g++ -c".

Часть проблемы заключается в том, что команда subst, которую вы используете для определения OBJ, интерпретирует свои аргументы как литералы. Перепишите это как

OBJ = $(subst src, obj, $(addsuffix .o, $(basename $(SRC))))

и вы как минимум получите желаемый OBJ.

person Clark    schedule 08.05.2013
comment
Почему? как я могу это изменить? - person darxsys; 08.05.2013
comment
строка, определяющая OBJ, работает неправильно... все еще пытаюсь понять, почему - person Clark; 08.05.2013
comment
Это действительно интересно. После этого я получаю: make: *** Нет правила для создания цели obj/normal.o', needed by app'. Останавливаться. - person darxsys; 08.05.2013

У вас есть пробелы на концах строк, определяющих SRC_DIR и OBJ_DIR. Это означает, что subst ничего не сделает, так как ищет "src ", а не "src".

В свою очередь, это означает, что он попытается построить src/whatever.o, а не obj/whatever.o, и, поскольку для этого нет правила, он вернется к правилу по умолчанию, а не к вашему.

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

person Mike Seymour    schedule 08.05.2013
comment
Да, это была ключевая проблема. Пробелы в определении obj_dir и src_dir - person darxsys; 11.05.2013