c-makefile:在另一个目录中构建.o文件



编辑:这是最后一个Makefile,它在构建目录中构建所有.o文件,并生成一个可执行文件。

CXX         = g++
CXXFLAGS    = -g -Wall
SRC_DIR     = ./src
BUILD_DIR   = ./build

SRC         = $(wildcard $(SRC_DIR)/*.cpp)
OBJS        = $(SRC:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o)
LIBS        = -lusb-1.0 -lpulse-simple -lpulse
EXEC        = AndroidMicLinux

all: $(EXEC)
$(BUILD_DIR)/%.o : $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -o $@ -c $<
$(EXEC) : $(OBJS)
$(CXX) -o $(EXEC) $(OBJS) $(LIBS)
clean:
rm -f $(OBJS) $(EXEC)

这个生成文件有很多问题。其中大多数都与变量的展开有关。如果你简单地想象变量的扩展,你很可能会看到问题。请记住,make只是进行文本替换以展开变量。没有";魔术;发生在这里。

例如:

SRC     = $(wildcard $(SRC_DIR)/*.cpp)

假设您有文件./src/foo.cpp./src/bar.cpp。这意味着$(SRC)将扩展到这两个文件。好的然后你有:

OBJS    = $(BUILD_DIR)/$(notdir $(SRC:.cpp=.o))

这是怎么回事?首先我们扩展BUILD_DIR:

OBJS    = ./build/$(notdir $(SRC:.cpp=.o))

然后对CCD_ 5进行扩展,得到CCD_。然后应用CCD_ 7,得到CCD_。这被替换为函数,所以结果是:

OBJS    = ./build/foo.o bar.o

你可以看出这是错误的。你不能只是把一个字符串放在函数之前,然后期望这个字符串附加到函数的每个单词!你需要明确告诉make你想这么做。也许你想要这样的东西:

OBJS    = $(SRCS:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o)

下一条规则:

%.o : %.c
$(CC) -o $(OBJS) -c $(SRC)

首先,配方是错误的。这会扩展到什么?

g++ -o ./build/foo.o ./build/bar.o -c ./src/foo.cpp ./src/bar.cpp

很明显,这是一个完全无效的编译行。您只需要一个对象文件和源文件,而不是所有。这就是自动变量的用途:

%.o : %.c
$(CC) -o $@ -c $<

然而,这仍然是错误的:这种模式规则永远不会匹配。为什么?因为当make尝试构建./build/foo.o时,%模式与字符串./build/foo匹配。因此,当make查看先决条件%.c是否存在时,它将检查./build/foo.c。首先,文件名以.cpp结尾,而不是以.c结尾,所以应该是%.cpp。但除此之外,源文件与目标文件位于不同的目录中,因此不能仅使用%。你必须这样写:

$(BUILD_DIR)/%.o : $(SRC_DIR)/%.cpp
$(CC) -o $@ -c $<

我还将指出,约定使用CC作为C编译器;如果您正在编译C++,则应该使用CXX变量。此外,您设置了一个FLAGS变量,但您的编译规则实际上并没有使用它;你不能只把它放在链接规则中。而且,对于C++编译器标志,约定是使用CXXFLAGS作为变量。

最新更新