【问题标题】:Compile all CPP files using makefile under MinGWMinGW下使用makefile编译所有CPP文件
【发布时间】:2012-10-18 01:32:50
【问题描述】:

我的C++项目的目录结构是

/..
   makefile     <- the makefile is in root
   /include     <- subdirectory that has to be included while compiling
   /obj         <- target place for all *.o and final executable
   /src         <- sources

而我当前的 makefile 是:

CC=g++
CFLAGS=-c -Wall -std=c++11

INC=-Iinclude
SRC=src
TGT=obj

all: myapp

myapp: myapp.o
    $(CC) $(TGT)/myapp.o -o $(TGT)/myapp

myapp.o:
    $(CC) $(CFLAGS) $(INC) $(SRC)/myapp.cpp -o $(TGT)/myapp.o

clean:
    rm -rf $(TGT)
    mkdir $(TGT)

这适用于我的第一个文件。我是一个 makefile 新手 - 请帮我编译 /src 目录下的所有文件并将它们链接到 /obj 目录中的可执行文件。

makefile 必须在 Windows 下工作,我使用的是 MinGW 和 MSYS

【问题讨论】:

    标签: c++ makefile mingw gnu-make


    【解决方案1】:

    添加源文件列表:

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

    以及对应的目标文件列表:

    OBJS = $(addprefix $(TGT)/, $(notdir $(SOURCES:.cpp=.o)))
    

    和目标可执行文件:

    $(TGT)/myapp: $(OBJS)
        $(CXX) $(LDFLAGS) $(OBJS) -o $@
    

    构建对象的规则:

    $(TGT)/%.o: $(SRC)/%.cpp
        $(CXX) $(CXXFLAGS) -c $< -o $@
    

    现在您必须指定 g++ 的选项:

    INCLUDES = -Iinclude
    CXXFLAGS = -Wall -std=c++11 $(INCLUDES)
    

    一切都在一起:

    SRC=src
    TGT=obj
    INCLUDES = -Iinclude
    CXXFLAGS = -Wall -std=c++11 $(INCLUDES)
    SOURCES = $(wildcard $(SRC)/*.cpp)
    OBJS = $(addprefix $(TGT)/, $(notdir $(SOURCES:.cpp=.o)))
    
    $(TGT)/%.o: $(SRC)/%.cpp
        $(CXX) $(CXXFLAGS) -c $< -o $@
    
    $(TGT)/myapp: $(OBJS)
        $(CXX) $(LDFLAGS) $(OBJS) -o $@
    

    重要的是,$(CXX) ... 前面必须有一个“制表符”字符,而不是空格。

    【讨论】:

    • -Idir 部分可以参数化吗?您的解决方案似乎简洁。不过有两件事要改变:make-script 应该将*.o 和最终的可执行文件都放在 TGT 目录中......
    • 参数化是什么意思?当然,你可以把它放在一个单独的变量中,并将这个变量添加到CXXFLAGS。查看修改后的答案。
    • @elmes 请尝试修改后的Makefile,我调整为单独的目标目录。
    【解决方案2】:

    你可以使用VPATH for separating source and object files:

    src/myapp.c
    obj/Makefile
    

    将您现有的Makefile 移至obj/,省略对$(TGT)$(SRC) 的引用并添加以下内容:

    VPATH=../src
    

    请注意,如果您尝试使用multi-architecture builds, VPATH is not ideal


    顺便说一句,你没有利用builtin rules。你在哪里

    CC=g++
    CFLAGS=-c -Wall -std=c++11
    myapp: myapp.o
        $(CC) $(TGT)/myapp.o -o $(TGT)/myapp
    
    myapp.o:
        $(CC) $(CFLAGS) $(INC) $(SRC)/myapp.cpp -o $(TGT)/myapp.o
    

    你可以改用:

    CXXFLAGS=-Wall -std=c++11
    CXXFLAGS+=$(INC)
    LDLIBS+=-lstdc++
    
    myapp: myapp.o
    

    因此,总而言之,您的新 obj/Makefile 应该如下所示:

    VPATH=../src
    INC=-I../include
    CXXFLAGS=-Wall -std=c++11
    CXXFLAGS+=$(INC)
    LDLIBS+=-lstdc++
    
    myapp: myapp.o
    

    如有必要,您可以从 obj/ 创建另一个 Makefile 以递归到这个新的:

    all: obj/myapp
    
    obj/myapp:
        mklink obj/Makefile ../Makefile
        $(MAKE) --directory=obj/
    

    【讨论】:

    • 正如我所说,我是 makefile 的新手。您能否创建一个适合问题中描述的场景的工作示例?
    • 好的,示例中唯一缺少的是 VPATH。所以你去。
    • 但是为什么makefile必须驻留在obj目录中。它不是保存它的好地方,因为我想轻松清除该目录
    • 您可以在构建时在 obj/ 中创建指向 Makefile 的符号链接(使用 mklink)。
    • shrug 对我来说似乎很简单,但我会保持 obj/ 目录不变,这样它会更简单。
    猜你喜欢
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 2012-04-04
    • 1970-01-01
    相关资源
    最近更新 更多