I'm using CODEO (Eclipse + overlay) to build an app for the ELinOS RTOS. Thing is, I lose the ability to auto-generate the Makefile using eclipse CDT and I have a generic Makefile alreayd generated.
Instead of typing this huge Makefile (Lots and lots of include and sources directories), I tried things with addprefix
patsubst
and some wildcard
but that didn't work out, mainly because I suck with generic makefile !
Regarding libraries, only a few are used, so I'll write them by hand.
Here is how my code is structured.
Top directory
|
---> common ---> inc/
| src/
---> pack_AAA ---> comp_AAA ---> inc/
| | src/
| ----> comp_AAB ---> inc/
| src/
---> comp_BBB ---> inc/
| src/
---> main.cpp
I'd like to enumerate only the top folders (common
, pack_AAA
, comp_BBB
and so on, mostly because not every TOP folder has to be compiled, my Makefile
is in one of these top folder).
Below there is a variable amount of subdirectories. Leafs are ALWAYS inc/
(.hpp files) and src/
(as you might guess, .cpp files) folders.
Moreover, the amount of TOP folders won't change, so I mind declaring them, but subfolders will.
Objects files can be anywhere they want (separate top build/
directory, within src/
...) as long as the resulting executable, let's call it HUGE_PROJECT
is in the top directory
Thanks in advance !
SOKS
Here is the generated makefile that I have to start with
-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
Here is the Makefile I ended up with. I had to hide components name.
#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: