'Makefile with multiple source folders
I'm trying to write a make file for my C++ project
I have the following source structure
project folder content:
main.cpp
lib/
include/
src/
as the name says 'main.cpp' contain the main() function, include hold the *.h files and src hold *.cpp file (and in case other subfolders with other sources)
what I would like to achieve is a makefile that as target compile main.cpp and all his included sources recursivelly , without specify all the sources names or mantaining the make file adding a source every time I create or add it
any help or a good tutorial to solve this problem would be very appreciated
Solution 1:[1]
Not sure what flavour of Makefile you use, or what OS you're building, however here are some ideas for a GNU Make and a unix-like environment
- Use a single make (instead of recursively invoking make on subdirectories).
- Use prefix rules to generate *.cpp to *.o
Now consider an src.mk present on each source subdirectory that fills an SRC variable with the actual *.cpp on each directory:
SRC+= $(addprefix $(ROOT)/src/, \ Source1.cpp \ Source2.cpp \ )... and in the Makefile you can have an
-include src.mk OBJ=$(SRC:.cpp=.o) executable: $(OBJ)Now the next thing is to be able to generate the
src.mk: you can have a prefix rule for that and rely on a shell script:%/src.mk: %/ gensrc $(dir $@)The
gensrcis a shell script that adds-include subdir/src.mkfor each subdir of the argument and creates SRC variable with the*.cppin the argument directory.
Hope this gives you some ideas.
Solution 2:[2]
bro!
If your main project architecture just like this:
fitBody
|
|__main.cpp
|__Makefile
|__build
|__lib
|__XYZ
|__include
|__fitbody.h
|__src
|__fitbody.cpp
[...]
Update Jan. 31 2022 PM 17:27
Just use this 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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | jsantander |
| Solution 2 |
