【问题标题】:Makefile not giving the expected compilation resultsMakefile 没有给出预期的编译结果
【发布时间】:2021-12-09 16:50:18
【问题描述】:

我对 Make 很陌生。我正在尝试编写一个 Makefile 来构建一个中型 Linux C/C++ 应用程序,如下所示。

通过将所有源文件放在一个位置并明确列出源文件来制作一个简单的 Makefile 对我来说可以,但我希望它更通用。

我的所有源文件(C 和 C++)都在不同子目录的 src 文件夹中。我在 incinc/common 文件夹中有头文件,然后在 lib 文件夹中有库。

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

【问题讨论】:

标签: c++ linux gcc makefile g++


【解决方案1】:

我看不出您显示的输出如何从您在此处显示的 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 目标都依赖于 ALL 源文件,而不仅仅是该目标文件的源文件。此外,自动变量$&lt; 总是扩展到first 先决条件,这里总是foo.c。因此,您将编译 foo.c 四次,创建每个目标文件。

调试 makefile 时的第一个重要规则是仔细查看进行打印的输出(命令行)。如果它们不正确,那么您的 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) 是不够的。

【讨论】:

    猜你喜欢
    • 2020-05-29
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-09
    • 2021-01-06
    • 2018-12-08
    相关资源
    最近更新 更多