2

我正在学习makefile。我尝试的是在阅读后写自己的。问题是,我总是遇到与 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忽略了我的标志。有针对这个的解决方法吗?

是的,我可以在没有 make 的情况下使用 -std=c++0x 标志进行编译,所以我的编译器显然不是问题。

4

3 回答 3

1

目录是否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) $<

这确实需要您使用标准标志变量(即CXXnotCCCXXFLAGSnot CXX_FLAGS),但无论如何这是一个好主意。

于 2013-05-08T16:39:35.950 回答
1

SRC_DIR在定义和的行的末尾有空格OBJ_DIR。这意味着subst不会做任何事情,因为它正在寻找"src "而不是"src".

反过来,这意味着它将尝试构建src/whatever.o而不是构建obj/whatever.o,并且由于没有规则,它将回退到默认规则而不是您的规则。

一旦你解决了这个问题,你需要添加-c到编译命令中,以生成一个目标文件而不是一个可执行文件。

于 2013-05-08T16:47:02.953 回答
1

它实际上并没有使用您的规则来构建目标文件。把它注释掉,你会看到它仍然调用“g++ -c”。

部分问题是您用于定义 OBJ 的命令 subst 将其参数解释为文字。重写为

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

你至少会得到想要的OBJ。

于 2013-05-08T16:17:00.897 回答