具有多个源文件夹的生成文件

Makefile with multiple source folders

本文关键字:文件 文件夹 源文件      更新时间:2023-10-16

我正在尝试为我的C++项目编写一个制作文件

我有以下源结构

项目文件夹内容:

main.cpp
lib/
include/
src/

顾名思义,"main.cpp"包含main()函数,包括保留*.h文件和src保留*.cpp文件(以及其他来源的子文件夹)

我想实现的是一个作为目标编译 main 的 makefile.cpp 以及他所有包含的源递归,而无需指定所有源名称或保留每次创建或添加时添加源的 make 文件

解决此问题的任何帮助或好教程将不胜感激

不确定你使用什么风格的Makefile,或者你正在构建什么操作系统,但是这里有一些关于GNU Make和类似Unix环境的想法

  1. 使用单个 make(而不是在子目录上递归调用 make)。
  2. 使用前缀规则生成 *.cpp 到 *.o
  3. 现在考虑每个源子目录上存在的 src.mk,该在每个目录上用实际的 *.cpp 填充 SRC 变量:

    SRC+= $(addprefix $(ROOT)/src/, 
        Source1.cpp 
        Source2.cpp 
    )
    
  4. 。在生成文件中,您可以有一个

    -include src.mk
    OBJ=$(SRC:.cpp=.o)
    executable: $(OBJ)
    
  5. 现在接下来的事情是能够生成src.mk:您可以为此制定前缀规则并依赖 shell 脚本:

    %/src.mk: %/
         gensrc $(dir $@)
    
  6. gensrc是一个 shell 脚本,它为参数的每个子目录添加-include subdir/src.mk,并使用参数目录中的*.cpp创建 SRC 变量。

希望这能给你一些想法。

兄弟!

如果你main项目架构就像这样:

fitBody
|
|__main.cpp
|__Makefile
|__build
|__lib
    |__XYZ
|__include
             
    |__fitbody.h
|__src
             
    |__fitbody.cpp
    [...]

更新 1月31 2022 下午 17:27

只需使用此Makefile

# (1)Compiler
CXX = clang++
# (2)Compile options
CXX_FLAGS = -Wall -Wextra -std=c++11 -g
# (3)Build task directory path
# I do care about out-of-source builds
BUILD_DIR ?= ./build
# (4)Source files directory path
SRC_DIRS ?= ./
SRC_DIRS_SRC ?= ./src
# (5)Library files directory path
LIBDIR :=
# (6)Add library files
LIBS := ./lib
# (7)Target file, excutable file.
TARGET ?= main
# (8)Source files(code), to be compiled
# Find source files we want to compile 
# *expression must around by single quotos
SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s')
SRCS_SRC := $(shell find $(SRC_DIRS_SRC) -name '*.cpp' -or -name '*.c' -or -name '*.s')
# (9)Object files
# String substituion for every C/C++ file
# e.g: ./src/bank.cpp turns into ./build/bank.cpp.o
OBJS := $(patsubst %.cpp, ${BUILD_DIR}/%.cpp.o, $(notdir $(SRCS)))
OBJS_SRC := $(patsubst %.cpp, ${BUILD_DIR}/%.cpp.o, $(notdir $(SRCS_SRC)))
# (10)Dependency files
# which will generate a .d file next to the .o file. Then to use the .d files,
# you just need to find them all:
DEPS := $(OBJS:.o=.d)
DEPS_SRC := $(OBJS_SRC:.o=.d)
# (11)Include files directory path
# Every folder in ./src find include files to be passed via clang 
INC_DIRS := ./inc
# (12)Include files add together a prefix, clang make sense that -I or -L flag
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
LIBS_FLAGS := $(addprefix -L,$(LIBS)) 
# (13)Make Makefiles output Dependency files
# That -MMD and -MP flags together to generate Makefiles 
# That generated Makefiles will take .o as .d to the output
# That "-MMD" and "-MP" To generate the dependency files, all you have to do is
# add some flags to the compile command (supported by both Clang and GCC):
CPP_FLAGS ?= $(INC_FLAGS) -MMD -MP
# (14)Link: Generate executable file from the object file
# make your target depend on the object files:
${BUILD_DIR}/${TARGET} : $(OBJS) 
    $(CXX) $^ -o $@ $(LIBS_FLAGS)
# (15)Compile: Generate object files from source files
# $@ := {TARGET}
# $< := THE first file
# $^ all the dependency
# C++ Sources
$(BUILD_DIR)/%.cpp.o : $(SRC_DIRS)/%.cpp 
    $(MKDIR_P) $(dir $@)
    $(CXX) $(CPP_FLAGS) $(CXX_FLAGS) -c $< -o $@
$(BUILD_DIR)/%.cpp.o : $(SRC_DIRS_SRC)/%.cpp 
    $(CXX) $(CPP_FLAGS) $(CXX_FLAGS) -c $^ -o $@
.PHONY:  all clean 
all: ${BUILD_DIR}/${TARGET}
clean:
    $(RM) $(DEPS) $(DEPS_MAIN) $(OBJS) $(OBJS_MAIN) ${BUILD_DIR}/${TARGET} 
-include $(DEPS) $(DEPS_MAIN)
MKDIR_P ?= mkdir -p