[英]Makefile not giving the expected compilation results
我对 Make 很陌生。 我正在尝试编写一个 Makefile 来构建一个中型 Linux C/C++ 应用程序,如下所示。
通过将所有源文件放在一个位置并明确列出源文件来制作一个简单的 Makefile 对我来说没问题,但我希望它更通用。
我的所有源文件(C 和 C++)都位于不同子目录的src
文件夹中。 我在inc
和inc/common
文件夹中有头文件,然后在lib
文件夹中有 libs。
Makefile 在同一级别上运行:
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
CXX := /bin/arm-linux-gnueabi-g++
EXE := $(BIN_DIR)/runfile
SRC := $(shell find $(SRC_DIR) -name *.cpp -or -name *.c)
OBJ := $(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(addsuffix .o,$(basename $(SRC))))
CPPFLAGS := -Iinc -Iinc/common -MMD -MP
CXXFLAGS := -std=c++11 -Wall
LDFLAGS := -Llib
LDLIBS :=
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $@
clean:
@$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
当我运行它时,我遇到了很多错误,如下所示,包括打开依赖文件的问题。 我想我快到了,但看不到我的错误:
compilation terminated.
/bin/arm-linux-gnueabi-g++ -Iinc -Iinc/common -MMD -MP -std=c++11 -Wall -c -o obj/main.d.o
cc -Llib obj/main.d.o -o obj/main.d
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: error adding symbols: file in wrong format
我不知道如何从您在此处显示的 makefile 生成您显示的输出,但无论如何。
这个不对:
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
模式规则是一个模板,它告诉 make “如果你想构建一个匹配这个模式的目标,那么你可以从匹配这个模式的先决条件中构建它”。
在这里,您将所有源文件列为每个目标文件的先决条件。 假设SRC
设置为foo.c bar.c biz.c baz.c
,那么这将扩展为:
obj/%.o : foo.c bar.c biz.c baz.c | obj
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
你告诉 make 每一个.o
目标都依赖于所有的源文件,而不仅仅是那个目标文件的源文件。 此外,自动变量$<
总是扩展到第一个先决条件,这里总是foo.c
。 因此,您将foo.c
编译四次,创建每个目标文件。
调试 makefile 时的第一个重要规则是仔细查看 make 打印的输出(命令行)。 如果它们不正确,那么您的 makefile 就不正确。 如果你这样做,你会看到所有的编译行都在编译相同的源代码,比如:
g++ -c foo.c -o obj/foo.o
g++ -c foo.c -o obj/bar.o
g++ -c foo.c -o obj/biz.o
g++ -c foo.c -o obj/baz.o
这显然行不通,这就是尝试将所有这些对象文件链接在一起时出现链接错误的原因:它们都具有相同的内容。
你需要这个:
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
@mkdir -p $(@D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
它告诉 make 如何从单个源文件构建目标文件。
您还需要创建目标文件将进入的实际输出目录。 如果目标文件出现在子目录中,仅创建$(OBJ_DIR)
是不够的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.