Грешка в Makefile C++11

Научавам за makefiles. Това, което се опитах е да напиша моя собствена след малко четене. Проблемът е, че винаги получавам грешки, свързани със стандарта c++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.

И ето мейк файла:

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: *** Няма правило за създаване на target 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