巨大的 c++ 项目手动生成文件

Huge c++ project makefile by hand

我正在使用 CODEO (Eclipse + overlay) 为 ELinOS RTOS 构建应用程序。 问题是,我失去了使用 eclipse CDT 自动生成 Makefile 的能力,并且我已经生成了一个通用的 Makefile。

我没有输入这个巨大的 Makefile(很多很多包含和源目录),而是尝试使用 addprefix patsubst 和一些 wildcard 但没有成功,主要是因为我不喜欢通用的 makefile !

关于库,用到的就那么几个,手写吧

这是我的代码的结构。

Top directory
|
---> common ---> inc/
|                src/
---> pack_AAA ---> comp_AAA ---> inc/
|            |                   src/
|            ----> comp_AAB ---> inc/
|                                src/
---> comp_BBB ---> inc/
|                  src/
---> main.cpp

我只想枚举顶级文件夹(commonpack_AAAcomp_BBB 等等,主要是因为不是每个 TOP 文件夹都必须编译,我的 Makefile 在这些顶级文件夹之一中)。 下面有数量不定的子目录。叶子总是 inc/(.hpp 文件)和 src/(您可能猜到了,.cpp 文件)文件夹。

此外,TOP 文件夹的数量不会改变,所以我介意声明它们,但子文件夹会。

目标文件可以放在他们想要的任何地方(单独的顶级 build/ 目录,在 src/ 内......)只要生成的可执行文件,我们称之为 HUGE_PROJECT 在顶层目录

提前致谢!

索克斯

这是我必须开始的生成的 makefile

-include makefile.init

RM := rm -rf

PROG = HUGE_PROJECT_EXECUTABLE

MODULES := common comp_AAA comp_BBB pack_AAA pack_BBB pack_CCC
SRC_DIRS   := $(addprefix ../../,$(MODULES))
#BUILD_DIR := $(addprefix ../../build/,$(MODULES))

#Original non-recursive & working example
OBJS = $(patsubst %.cpp,%.o,$(wildcard ./src/*.cpp))
DEPS = $(patsubst %.cpp,%.d,$(wildcard ./src/*.cpp))

#bad attempt
#SRCS       := $(foreach sdir,$(SRC_DIRS),$(wildcard $(sdir)/*.cpp))
#OBJS       := $(patsubst %.cpp,%.o,$(SRCS))
#INCLUDES  := $(addprefix -I,$(SRC_DIR))


ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(DEPS)),)
-include $(DEPS)
endif
endif

-include makefile.defs

# All Target
all: $(PROG).tgz

$(PROG).tgz: $(PROG).mkefs $(PROG)
    @echo 'Building file: $@'
    @echo 'Invoking: Embeddable file system generator'
    mkefs -a -s -o"$@" -f"$<"
    @echo 'Finished building: $@'
    @echo ' '

$(PROG): $(OBJS) $(USER_OBJS)
    @echo 'Building target: $@'
    @echo 'Invoking: ELinOS C/C++ Linker'
    $(CXX)  -o "$(PROG)" $(SRCS) $(USER_OBJS) $(LIBS)
    @echo 'Finished building target: $@'
    @echo ' '

clean:
    -$(RM) $(OBJS) $(DEPS) $(PROG) $(PROG).tgz
    -@echo ' '

./src/%.o: ./src/%.cpp
    @echo 'Building file: $<'
    @echo 'Invoking: ELinOS C/C++ Compiler'
    $(CXX) -I./include -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
    @echo 'Finished building: $<'
    @echo ' '

.PHONY: all clean dependents
.SECONDARY:

-include makefile.targets

这是我最终得到的 Makefile。 我不得不隐藏组件名称。

#Executables
RM := rm -rf
CXX=YOUR_CXX_COMPILER
CC=YOUR_CC_COMPILER

PROG=YOUR_PROGRAM

#Root directory of your program (all files should be in it)
ROOT_DIR := ../../

#####################################

########################################
#      Define here all directories     #
#   containing src/ and inc/ folders   #
########################################

#pack_AAA folders
#Modules containing both src/ and inc/.
AAA_MODULES         := moduleA moduleB
#Modules with an include folder only + module with both
AAA_DIRS_INC        := moduleD moduleEF $(AAA_MODULES)

#pack_BBB modules list
BBB_MODULES         := comp_A comp_B comp_C comp_B/comp_D comp_B/comp_E

MMM_MODULES     := comp_F comp_G comp_H

PPP_MODULES     := . I

CCC_MODULES     := J comp_K comp_L \
                    comp_L/comp_M \ 
                    $(addprefix pack_BBB/,$(BBB_MODULES)) \
                    $(addprefix pack_MMM/,$(MMM_MODULES)) \
                    $(addprefix comp_PPP/,$(PPP_MODULES))

#pack_DDD
DDD_MODULES         := M comp_N comp_N/comp_O

#comp_EEE
EEE_MODULES     := . P Q

OTHER_MODULES       := R S comp_T

#All folders containing src/ subdir
SRC_MODULES         := $(OTHER_MODULES) \
                    $(addprefix comp_EEE/,$(EEE_MODULES)) \
                    $(addprefix pack_DDD/,$(DDD_MODULES)) \
                    $(addprefix pack_AAA/,$(AAA_MODULES)) \
                    $(addprefix pack_CCC/, $(CCC_MODULES))

#All folders containing inc/ subdir
INCLUDE_MODULES     := $(OTHER_MODULES) \
                    $(addprefix comp_EEE/,$(EEE_MODULES)) \
                    $(addprefix pack_DDD/,$(DDD_MODULES)) \
                    $(addprefix pack_AAA/,$(AAA_DIRS_INC)) \
                    $(addprefix pack_CCC/, $(CCC_MODULES))

#####################################

#WRAPPERS
ROOT_DIR_WRAPPERS       := $(ROOT_DIR)../WRAPPERS/

LIST_WRAPPERS           := WA WB WC WD

SRC_WRAPPERS            := $(addprefix pack_Wrappers/csc_Wrapper,$(LIST_WRAPPERS))

#DRIVERS
LIST_DRIVERS            := DA DB DC DD
DIR_DRIVERS             := $(addprefix pack_Drivers/csc_Driver,$(LIST_DRIVERS))

SRC_DIRS_WRAPPERS       := $(addsuffix /src,$(SRC_WRAPPERS))

INCLUDE_DIRS_WRAPPERS   := $(addsuffix /inc,$(SRC_WRAPPERS)) \
                            $(addsuffix /inc,$(DIR_DRIVERS)) \
                            Common


#####################################
#LIB_1 INCLUDE
ROOT_DIR_LIB_1          := $(ROOT_DIR)../../ObjetsCompiles/LIB_1/
INCLUDE_DIRS_LIB_1      := dir1 dir2 dir3

#####################################
#LIB_2 INCLUDE
ROOT_DIR_LIB_2      := $(ROOT_DIR)../../ObjetsCompiles/LIB_2/include
INCLUDE_DIRS_LIB_2  := . dir1 dir2 dir3/subdir dir4


#####################################
#Add "." to find main.cpp
SRC_DIRS        := $(addsuffix /src,$(SRC_MODULES)) .
INCLUDE_DIRS_SRC:= $(addsuffix /inc,$(INCLUDE_MODULES)) pack_ZZZ/comp_Without_Inc_Folder

#All include dirs, LIB_1 + LIB_2
INCLUDE_DIRS    := $(addprefix -I$(ROOT_DIR),$(INCLUDE_DIRS_SRC)) \
                    $(addprefix -I$(ROOT_DIR_LIB_1),$(INCLUDE_DIRS_LIB_1)) \
                    $(addprefix -I$(ROOT_DIR_LIB_2),$(INCLUDE_DIRS_LIB_2))

INCLUDE_DIRS_CC := $(addprefix -I$(ROOT_DIR_WRAPPERS),$(INCLUDE_DIRS_WRAPPERS)) \
                    $(addprefix -I$(ROOT_DIR_LIB_2),$(INCLUDE_DIRS_LIB_2))

#All objects (all .cpp & all .c)
OBJS            := $(foreach dir,$(SRC_DIRS), \
                    $(patsubst %.cpp,%.o,$(wildcard $(ROOT_DIR)$(dir)/*.cpp))) \
                    $(foreach dirs,$(SRC_DIRS_WRAPPERS), \
                    $(patsubst %.c,%.o,$(wildcard $(ROOT_DIR_WRAPPERS)$(dirs)/*.c)))

#All dependencies (same list as OBJS)
DEPS            := $(foreach dir,$(SRC_DIRS), \
                    $(patsubst %.cpp,%.d,$(wildcard $(ROOT_DIR)$(dir)/*.cpp))) \
                    $(foreach dirs,$(SRC_DIRS_WRAPPERS), \
                    $(patsubst %.c,%.d,$(wildcard $(ROOT_DIR_WRAPPERS)$(dirs)/*.c)))

#Exclude files from build
#Win32 socket files + some misc
EXCLUDED_FILES_LIST     := pack_AAA/comp_BBB/src/SocketWindowsOnLinuxForExample.cpp \
                        pack_BBB/comp_CCC/src/SomeOtherThingForWindows.cpp
EXCLUDED_FILES_PATH     := $(addprefix $(ROOT_DIR),$(EXCLUDED_FILES_LIST))

#Remove some objects (compilation is done, but no link)
EXCLUDED_OBJS   := $(patsubst %.cpp,%.o,$(EXCLUDED_FILES_PATH))
EXCLUDED_DEPS   := $(patsubst %.cpp,%.d,$(EXCLUDED_FILES_PATH))

#Update OBJS & DEPS list with excluded files
OBJS := $(filter-out $(EXCLUDED_OBJS),$(OBJS))
DEPS := $(filter-out $(EXCLUDED_DEPS),$(DEPS))

#FLAGS for DEBUG and RELEASE compilation
CPPFLAGS    := -D__CPPFLAG1__ -D__CPPFLAG2__
CFLAGS_D    := -O0 -g2 -Wall -c -fmessage-length=0
CXXFLAGS_D  := -O0 -g2 -Wall -c -fmessage-length=0 -m32 -mcpu=powerpc -Winline
CFLAGS_R    := -O2 -g0 -Wall -c -fmessage-length=0
CXXFLAGS_R  := -O2 -g0 -Wall -c -fmessage-length=0 -m32 -mcpu=powerpc -Winline

# L
LD_PATH     := -L../../path_library_1 -L../../path_library_2
LD_LIBS     := -lpthread_rt -lROHC -lpthread -lnative -lrtdm -lrt
MAP         := $(PROG).map
# -s (to strip)
LD_FLAGS_D  := -Wl,--wrap,pthread_create -Wl,--wrap,pthread_kill -Wl,-Map,$(MAP)
LD_FLAGS_R  := -s -Wl,--wrap,pthread_create -Wl,--wrap,pthread_kill -Wl,-Map,$(MAP)

##################################################
#TARGETS

default: release

#Debug flags (-00 + -g2)
debug: CFLAGS       := $(CFLAGS_D)
debug: CXXFLAGS     := $(CXXFLAGS_D)
debug: LD_FLAGS     := $(LD_FLAGS_D)
debug: all

#Release flags (-s + -02 + -g0)
release: CFLAGS     := $(CFLAGS_R)
release: CXXFLAGS   := $(CXXFLAGS_R)
release: LD_FLAGS   := $(LD_FLAGS_R)
release: all

all: $(PROG)

# Tool invocations
$(PROG): $(OBJS)
    @echo 'Building target: $@'
    @$(CXX)  $(LD_FLAGS) $(LD_PATH) -o "$(PROG)" $(OBJS) $(LD_LIBS)
    @echo 'Finished building target: $@'
    @echo ' '

# CXX compiler used by most of the code
%.o: %.cpp
    @echo 'Building file: $<'
    @$(CXX) $(CPPFLAGS) $(INCLUDE_DIRS) $(CXXFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"

# CC compiler used by Wrappers only
%.o: %.c
    @echo 'Building file: $<'
    @$(CC) $(INCLUDE_DIRS_CC) $(CFLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"

# Other Targets
clean:
    -$(RM) $(OBJS) $(DEPS) $(PROG) $(MAP)
    -@echo ' '

.PHONY: all clean dependents
.SECONDARY: