Makefile: Separated sources and objects - c

I've been trying for some time to separate the source files of my project from the generated object files.
Indeed, I would like my project to be structured this way:
obj/
main.o
src1.o
[...]
src/
main.c
src1.c
[...]
Makefile
The Makefile I currently have is as follows:
NAME = a.out
OBJ_DIR = "obj"
SRC_DIR = "src"
MAIN_SRC = main.c
PROJ_SRC = src1.c \
src2.c \
src3.c
MAIN_OBJ = $(MAIN_SRC:%.c=%.o)
PROJ_OBJ = $(PROJ_SRC:%.c=%.o)
CC = gcc
RM = rm -rf
$(NAME): $(MAIN_OBJ) $(PROJ_OBJ)
$(CC) $(MAIN_OBJ) $(PROJ_OBJ) -o $(NAME)
all: $(NAME)
clean:
$(RM) $(MAIN_OBJ) $(PROJ_OBJ)
fclean: clean
$(RM) $(NAME)
I tried to use pattern rules, without success.
MAIN_OBJ = $(MAIN_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
PROJ_OBJ = $(PROJ_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
[...]
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
Does anyone have a solution to my problem?

MAIN_SRC and PROJ_OBJ do not have directory prefix, so that expressions
$(MAIN_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
$(PROJ_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
do not replace anything.
Fix:
MAIN_OBJ := $(MAIN_SRC:%.c=$(OBJ_DIR)/%.o)
PROJ_OBJ := $(PROJ_SRC:%.c=$(OBJ_DIR)/%.o)
And then your pattern rule should work.
You may like to have make create that $(OBJ_DIR) for you:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CC) $(CFLAGS) -c -o $# $<
$(OBJ_DIR) :
mkdir -p $#
A more advanced example for you with automatic header dependency generation.

bro!
If your project "main" 's architecture is just liking this:
main
|
|__Makefile
|__obj
|__src
|__main.c
|__src1.c
|__src2.c
[...]
Just add this to your "Makefile" to store your object out of source files directory:
# Object files
# String substituion for every C/C++ file
# e.g: ./src/src1.cpp turns into ./obj/src1.o
OBJS := $(patsubst %.c, ${OBJ_DIR}/%.o, $(notdir $(SRC_DIR)))
And just add this to your "Makefile" to compile:
# Compile: Generate object files from source files
# $# := {NAME}
# $< := THE first file
# $^ all the dependency
# C Sources
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(C_FLAGS) -c $< -o $#
END!

Related

Is there a way to have all my object files in the same directory using Make?

So, I decided to learn make as my first step into large projects, and I have to say that it is not that hard if you are just doing simple tasks and got addicted to it.
However I usually work with a scheme for my directories:
.
├── build
├── include
│   └── func.h
├── lib
│   └── func.c
├── Makefile
└── src
└── main.c
I usually have all my object files spread in the build directory. However, I could only map the source files to the build folder (like ./build/src/main.o where I prefer ./build/main.o).
I Tried Reading The Documentation to no avail!
this is what I came up with so far:
# C Compiler
CC = gcc
#------------- Directories
SOURCE_DIR = src lib
OBJECTS_DIR = build
INCLUDE_DIR = . ./include
#----------------------------
VPATH = $(SOURCE_DIR)
#------------- Files
SOURCE = $(foreach dir, $(SOURCE_DIR), $(wildcard $(dir)/*.c))
# Fake Objects (Just so I can map them to c files)
FOBJECTS = $(addprefix $(OBJECTS_DIR)/, $(SOURCE:.c=.o))
OBJECTS = $(addprefix $(OBJECTS_DIR)/, $(notdir $(FOBJECTS)))
DEPS = $(foreach dir, $(INCLUDE_DIR), $(wildcard $(dir)/*.h))
#----------------------------
#------------- Flags
OPT = -O0
IFLAGS = $(foreach dir, $(INCLUDE_DIR), -I$(dir))
LFLAGS = -lm
CFLAGS = -Wall
FLAGS = $(OPT) $(IFLAGS) $(LFLAGS) $(CFLAGS)
#----------------------------
BINARY = bin
all : $(BINARY)
$(BINARY) : $(OBJECTS)
$(CC) -o $# $(OBJECTS)
$(OBJECTS) : $(FOBJECTS)
mv -t $(OBJECTS_DIR) $(FOBJECTS)
rm -rf -- $(OBJECTS_DIR)/*/
$(OBJECTS_DIR)/%.o : %.c $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
exec : $(BINARY)
#./$(BINARY)
clean :
rm -rf $(OBJECTS) $(BINARY)
I keep getting this error:
gcc -O0 -I. -I./include -lm -Wall -c -o build/src/main.o src/main.c
Assembler messages:
Fatal error: can't create build/src/main.o: No such file or directory
make: *** [Makefile:39: build/src/main.o] Error 1
I know the reason is the Fake Objects I created but creating the perfect rule for this is hard
As I said, you probably do not want to put all .o in the same directory because comingling .o files from unrelated projects isn't the best organization. If the .o files were related, you'd probably put the .c files in the same subdir.
But, if you did want all .o in a single build directory, one way is to create the build/* subdirs:
# C Compiler
CC = gcc
#------------- Directories
SOURCE_DIR = src lib
OBJECTS_DIR = build
INCLUDE_DIR = . ./include
OBJ_MK = $(addprefix $(OBJECTS_DIR)/, $(SOURCE_DIR))
#----------------------------
VPATH = $(SOURCE_DIR)
#------------- Files
SOURCE = $(foreach dir, $(SOURCE_DIR), $(wildcard $(dir)/*.c))
# Fake Objects (Just so I can map them to c files)
FOBJECTS = $(addprefix $(OBJECTS_DIR)/, $(SOURCE:.c=.o))
OBJECTS = $(addprefix $(OBJECTS_DIR)/, $(notdir $(FOBJECTS)))
DEPS = $(foreach dir, $(INCLUDE_DIR), $(wildcard $(dir)/*.h))
#----------------------------
#------------- Flags
OPT = -O0
IFLAGS = $(foreach dir, $(INCLUDE_DIR), -I$(dir))
LFLAGS = -lm
CFLAGS = -Wall
FLAGS = $(OPT) $(IFLAGS) $(LFLAGS) $(CFLAGS)
#----------------------------
BINARY = bin
all : $(OBJ_MK) $(BINARY)
$(BINARY) : $(OBJECTS)
$(CC) -o $# $(OBJECTS)
$(OBJECTS) : $(FOBJECTS)
mv -t $(OBJECTS_DIR) $(FOBJECTS)
rm -rf -- $(OBJECTS_DIR)/*/
$(OBJECTS_DIR)/%.o : %.c $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
exec : $(BINARY)
#./$(BINARY)
clean :
rm -rf $(OBJECTS) $(BINARY)
rm -rf $(OBJ_MK)
$(OBJ_MK):
mkdir $#
The make output is:
mkdir build/src
mkdir build/lib
gcc -O0 -I. -I./include -lm -Wall -c -o build/src/main.o src/main.c
gcc -O0 -I. -I./include -lm -Wall -c -o build/lib/func.o lib/func.c
mv -t build build/src/main.o build/lib/func.o
rm -rf -- build/*/
gcc -o bin build/main.o build/func.o
However, the above actually makes the build more complex because its "natural" tendency was to create the subdirs. To override that required extra mv and rm commands.
To use the subdirectory method, the build is actually simpler, and we can do:
# C Compiler
CC = gcc
#------------- Directories
SOURCE_DIR = src lib
OBJECTS_DIR = build
INCLUDE_DIR = . ./include
OBJ_MK = $(addprefix $(OBJECTS_DIR)/, $(SOURCE_DIR))
#----------------------------
VPATH = $(SOURCE_DIR)
#------------- Files
SOURCE = $(foreach dir, $(SOURCE_DIR), $(wildcard $(dir)/*.c))
# Fake Objects (Just so I can map them to c files)
OBJECTS = $(addprefix $(OBJECTS_DIR)/, $(SOURCE:.c=.o))
DEPS = $(foreach dir, $(INCLUDE_DIR), $(wildcard $(dir)/*.h))
#----------------------------
#------------- Flags
OPT = -O0
IFLAGS = $(foreach dir, $(INCLUDE_DIR), -I$(dir))
LFLAGS = -lm
CFLAGS = -Wall
FLAGS = $(OPT) $(IFLAGS) $(LFLAGS) $(CFLAGS)
#----------------------------
BINARY = bin
all : $(OBJ_MK) $(BINARY)
$(BINARY) : $(OBJECTS)
$(CC) -o $# $(OBJECTS)
$(OBJECTS_DIR)/%.o : %.c $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
exec : $(BINARY)
#./$(BINARY)
clean :
rm -rf $(OBJECTS) $(BINARY)
rm -rf $(OBJ_MK)
$(OBJ_MK):
mkdir $#
The make output is:
mkdir build/src
mkdir build/lib
gcc -O0 -I. -I./include -lm -Wall -c -o build/src/main.o src/main.c
gcc -O0 -I. -I./include -lm -Wall -c -o build/lib/func.o lib/func.c
gcc -o bin build/src/main.o build/lib/func.o
If you really want all the objects in a single directory, you almost have it right but you added some very strange rules that I don't understand; what is this for:
$(OBJECTS) : $(FOBJECTS)
mv -t $(OBJECTS_DIR) $(FOBJECTS)
rm -rf -- $(OBJECTS_DIR)/*/
? This is what's causing your problem. You're saying that every individual object file depends on all the "intermediate" object files, so then make tries to build these "intermediate" object files. The only way it knows to do that is with the pattern rule you provided, but that doesn't build those files.
Remove that rule altogether and it will probably work. You just want:
VPATH = $(SOURCE_DIR)
OBJECTS = $(addprefix $(OBJECTS_DIR)/, $(notdir $(SOURCE:.c=.o)))
all : $(BINARY)
$(BINARY) : $(OBJECTS)
$(CC) -o $# $(OBJECTS)
$(OBJECTS_DIR)/%.o : %.c $(DEPS)
$(CC) $(FLAGS) -c -o $# $<
etc. The compiler will build the object files directly into their final destination. You don't need the FOBJECTS thing or the rule that uses it.

Subdirectories and GCC problem with MakeFile

I'm writing a makefile for a very small personal project written in C.
My project is divided into subdirectories, but the directives for these utilme are not found even if (I think) the code is right:
TARGET = example.out
ENV = /usr/bin/env
MKDIR = mkdir
RMV = rm
CP = cp
CC = gcc
CFLAGS = -lm
BINDIR = ./bin
OBJDIR = ./obj
SRCDIR = ./src
SRCS = master.o request/request.o util/util.o # these are all .c files (./src/...)
# ---
.PHONY: build
build: prepare $(SRCS)
$(ENV) $(CC) $(addprefix $(OBJDIR)/, $(SRCS)) -o $(BINDIR)/$(TARGET)
# ---
.PHONY: prepare
prepare:
#$(ENV) $(MKDIR) -p $(BINDIR) $(OBJDIR)
#$(ENV) $(CP) data.txt $(BINDIR)/data.txt
# ---
.PHONY: clean
clean:
#$(ENV) $(RM) -rf $(BINDIR) $(OBJDIR)
# ---
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(ENV) $(CC) $(CFLAGS) -c $<
It says:
make: *** No rule to make target 'master.o', needed by 'build'. Stop.
And if I change $(OBJDIR)/%.o: $(SRCDIR)/%.c to %.o: $(SRCDIR)/%.c, it says:
make: *** No rule to make target 'request/request.o', needed by 'build'. Stop.
You have effectively no rule to create master.o from master.c.
In the following rule:
$(OBJDIR)/%.o: $(SRCDIR)/%.c
./obj/%.o does not match master.o
And if master.c is in src (as indicated by the comment) the default rules don't match either.
So in order to match the rule, the target must be ./obj/master.o
The same goes for all the other .o files and you will run into trouble with the subdirectories. To get around that you can create the target directory in the recipe directly:
$(OBJDIR)/%.o: $(SRCDIR)/%.c
mkdir -p $(dir $#)
$(CC) -c -o $# $(CFLAGS) $<
the default behaviour of gcc is to place the .o-file beneath the .c-file. to place it into the object file directory, you have to use an -o $# argument:
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(ENV) $(CC) $(CFLAGS) -c $< -o $#
And the build rule shoud depend on $(addprefix $(OBJDIR)/, $(SRCS))
if this is what is used in the command.
build: prepare $(addprefix $(OBJDIR)/, $(SRCS))
$(ENV) $(CC) $(addprefix $(OBJDIR)/, $(SRCS)) -o $(BINDIR)/$(TARGET)

Unexpected prerequisite skip in GNU Make 4.2.1

I'm trying to create a generic Makefile to use with most of my projects. It should work as follows: only rebuild and link those .o files whose .c or .h dependency has changed. The .o and .d files are stored in a separate directory called 'build'.
With the help of the official GNU Make manual and some googling I've managed to achieve the desired behavior except for one thing: when I run make re I get the error:
Assembler messages: Fatal error: can't create build/ft_build_buffer.o: No such file or directory — the reason for this is that the 'build' directory only gets created whenever the .d files are generated, but for some reason the re rule simply skips this step and goes on to compile .o files straight away! Note: if I run make clean && make fclean && make all (which should be the exact same thing) everything works fine.
A few other things: I've tried using the -MMD option to generate dependencies on the fly but on my machine that causes the .d files to only contain .c dependencies. Of course I could just make all .c files depend on all .h files but that seems like a very sloppy solution.
Feel free to share any other advice/improvements that will make this file more clean and readable, thanks! :)
# Define the C compiler to use.
CC := gcc
# Define any compile-time flags.
CFLAGS := -I./include -Wall -Wextra -Werror -g
#CFLAGS := -I./include -march=native -O2 -pipe
# Define the executable file.
BIN := ft_hexdump
# Define build directory.
BUILD_DIR := build
# Define source files directory.
SRC_DIR := src
# Define the C source files.
SRCS := $(wildcard $(SRC_DIR)/*.c)
# Define the C object files.
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
# Define the prerequisite files.
DEPS := $(OBJS:%.o=%.d)
.PHONY: all clean fclean re
.DELETE_ON_ERROR:
all: $(BIN)
-include $(DEPS)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $^ -o $#
$(BUILD_DIR)/%.o: $(BUILD_DIR)/%.d
$(CC) $(CFLAGS) -c $(SRC_DIR)/$*.c -o $#
$(BUILD_DIR)/%.d: $(SRC_DIR)/%.c
#mkdir -p $(#D)
#set -e; rm -f $#; \
$(CC) $(CFLAGS) $(INCLUDE) -MM $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
clean:
-rm -rf $(BUILD_DIR)
fclean: clean
-rm -f $(BIN)
re: fclean all
Here is the modified working version as suggested by #M.M
# Define the C compiler to use.
CC := gcc
# Define any compile-time flags.
CFLAGS := -I./include -Wall -Wextra -Werror -g
#CFLAGS := -I./include -march=native -O2 -pipe
# Define the executable file.
BIN := ft_hexdump
# Define build directory.
BUILD_DIR := build
# Define source files directory.
SRC_DIR := src
# Define the C source files.
SRCS := $(wildcard $(SRC_DIR)/*.c)
# Define the C object files.
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
# Define the prerequisite files.
DEPS := $(OBJS:%.o=%.d)
.PHONY: all clean fclean re
.DELETE_ON_ERROR:
all: $(BIN)
-include $(DEPS)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $^ -o $#
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
#mkdir -p $(#D)
$(CC) $(CFLAGS) -MMD -c $(SRC_DIR)/$*.c -o $#
clean:
-rm -rf $(BUILD_DIR)
fclean: clean
-rm -f $(BIN)
re:
$(MAKE) fclean
$(MAKE) all

make: create a test binary for each file in test directory

I have a simple structure as below for a small library I'm building.
I want make build to build the library (libproj.a) from sources under ./source
I want make build_test to build every source file under ./test prefixed with test_ into it's own binary
I can build the library libproj.a just fine, but can't figure out how to build the tests. I'm currently getting the following linker error when attempting to build /cygdrive/d/Source/proj/build/obj/test_proj.o:test_proj.c:(.text+0x15): undefined reference to 'test'.
Directory structure
+---build
| +---lib
| +---obj
| \---test
+---include
| \---proj
+---source
\---test
Makefile
PROJECT = proj
LIBNAME = lib$(PROJECT).a
CFLAGS = -Wall -Wextra -O0
DIR_ROOT = $(abspath .)
DIR_SRC_LIB = $(DIR_ROOT)/source
DIR_SRC_TEST = $(DIR_ROOT)/test
DIR_BLD_OBJ = $(DIR_ROOT)/build/obj
DIR_BLD_LIB = $(DIR_ROOT)/build/lib
DIR_BLD_TEST = $(DIR_ROOT)/build/test
LST_OBJ_LIB = $(patsubst $(DIR_SRC_LIB)/%.c, $(DIR_BLD_OBJ)/%.o, $(wildcard $(DIR_SRC_LIB)/*.c))
LST_OBJ_TEST = $(patsubst $(DIR_SRC_TEST)/%.c, $(DIR_BLD_OBJ)/%.o, $(wildcard $(DIR_SRC_TEST)/*.c))
LST_BIN_TEST = $(patsubst $(DIR_SRC_TEST)/%.c, $(DIR_BLD_TEST)/%, $(wildcard $(DIR_SRC_TEST)/test_*.c))
INCLUDES = -I $(DIR_ROOT)/include
clean:
$(RM) $(LST_OBJ_LIB)
$(RM) $(LST_OBJ_TEST)
build:
$(info build)
build-test: $(LST_BIN_TEST)
$(info build-test)
run-test:
$(info run-test)
install:
$(info install)
$(LIBNAME): $(LST_OBJ_LIB)
$(AR) rvs $(DIR_BLD_LIB)/$# $^
$(DIR_BLD_OBJ)/%.o: $(DIR_SRC_LIB)/%.c
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
$(DIR_BLD_TEST)/%: $(DIR_BLD_OBJ)/%.o $(LIBNAME)
$(CC) $(LDFLAGS) -L $(DIR_BLD_LIB) -l $(PROJECT) $< -o $#
$(DIR_BLD_OBJ)/%.o: $(DIR_SRC_TEST)/%.c
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
My guess is that this line:
$(CC) $(LDFLAGS) -L $(DIR_BLD_LIB) -l $(PROJECT) $< -o $#
is wrong. You're passing to the compiler (I'm assuming gcc) the libraries before the object files. If your compiler acts as gcc does, the code in the libraries is getting discarded because it hasn't been referenced yet when it parses them see -l option documentation.
It should be
$(CC) $(LDFLAGS) -L $(DIR_BLD_LIB) $< -l $(PROJECT) -o $#
(Note the changed position of $<)
Furthermore, remeber that the order of libraries is important: see this excellent explanation.

Need help writing a Makefile that creates all the objective files into a new subdir

I am trying to make a Makefile for a big project.
The project structure is (I've ommitted the header files):
root/feature1/feat1.c
root/feature2/feat2.c
root/srcfile1.c
root/srcfile2.c
I wanted to start easy so I created a simpler project with the source files in the root dir.
I need to create all the object files in one directory, let's say, objdir.
The project structure of the simple project is:
root/main.c
root/word.c
By looking in other questions I have come up with this:
CC = gcc
FLAGS = -c
MKDIR_P = mkdir -p
OUT = words
OBJDIR = objdir
SRCDIR = .
_OBJS = main.o word.o
OBJS = $(patsubst %,$(OBJDIR)/%,$(_OBJS))
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) -c -o $# $<
all: directories program
directories: ${OBJDIR}
${OBJDIR}:
${MKDIR_P} ${OBJDIR}
program: $(OBJS)
$(CC) -o $# $^ $(LIBS)
clean:
rm -f $(OBJS)
When running it with make -f ./myMakefile all (changed the filename as in the same dir, there is Netbeans' Makefile), I am getting this output:
gcc -o objdir/main.o main.c
/tmp/ccatfAHu.o: In function `main':
main.c:(.text+0x15): undefined reference to `CreateWord'
main.c:(.text+0x26): undefined reference to `CreateWord'
collect2: error: ld returned 1 exit status
make: *** [objdir/main.o] Error 1
Giving the make all command, it tries to produce the targes directories and program.
The dir objdir is created and in it, there are the main.o and word.o files.
What am I doing wrong with the makefile of the simpleproject?
EDIT:
Added the -c flag at the $(OBJDIR)/%.o rule.
Removed the $(FLAGS) from $(CC) -o $# $^ $(FLAGS) $(LIBS).
Now, if we move to my project problem, I need to access all the source files from all the directories:
/repo-root
/repo-root/feature1/feat1.c
/repo-root/feature2/feat2.c
In this rule:
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) -o $# $<
you're missing the -c flag. Instead of building an object file, Make is trying to build an executable named objdir/main.o, and main.c doesn't have all of the needed code. Just do this:
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) -c -o $# $<
Try this
#source files to compile relative to the src dir
CSOURCE = main.c
CSOURCE += func1.c
SRCDIR = .
vpath %.c $(SRCDIR)/
CC = gcc
MKDIR_P = mkdir -p
OBJDIR = objdir
BINDIR = bindir
#list of objects
OBJS = $(addprefix $(OBJDIR)/, $(CSOURCE:.c=.o))
#output name for executable
APP = example
all: ${OBJDIR} $(OBJS) bin
#rule to create bin and objects dir
${BINDIR}:
${MKDIR_P} ${BINDIR}
${OBJDIR}:
${MKDIR_P} ${OBJDIR}
#rule to compile c files
$(OBJDIR)/%.o: %.c
$(CC) -c $< -o $#
#to create executable
bin: $(BINDIR) $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(BINDIR)/$(APP)
#to clean executable and objects
clean:
rm -rf $(OBJS) $(BINDIR) $(OBJDIR)
Updated root make file, Use this in the root/ directory
WORKDIR = $(shell pwd)
MODULES = feature1 feature2
CSOURCE = main.c
CSOURCE += func1.c
SRCDIR = .
vpath %.c $(SRCDIR)/
CC = gcc
MKDIR_P = mkdir -p
OBJDIR = $(WORKDIR)/objdir
BINDIR = $(WORKDIR)/bindir
OBJS = $(addprefix $(OBJDIR)/, $(CSOURCE:.c=.o))
APP = example
all: ${OBJDIR} modules $(OBJS) bin
modules:
for mod in $(MODULES); do \
echo "Building $$mod ....."; \
$(MAKE) -C $(WORKDIR)/$$mod all; \
done
${BINDIR}:
${MKDIR_P} ${BINDIR}
${OBJDIR}:
${MKDIR_P} ${OBJDIR}
$(OBJDIR)/%.o: %.c
$(CC) -c $< -o $#
bin: $(BINDIR) $(OBJS)
$(CC) $(CFLAGS) $(OBJDIR)/*.o -o $(BINDIR)/$(APP)
clean:
rm -rf $(OBJS) $(BINDIR) $(OBJDIR)
feature make file, use this in the root/feature1 directory and root/feature2 directory
WORKDIR = $(shell cd ..; pwd)
CSOURCE = func2.c
SRCDIR = .
vpath %.c $(SRCDIR)/
CC = gcc
MKDIR_P = mkdir -p
OBJDIR = $(WORKDIR)/objdir
OBJS = $(addprefix $(OBJDIR)/, $(CSOURCE:.c=.o))
all: ${OBJDIR} $(OBJS)
${OBJDIR}:
${MKDIR_P} ${OBJDIR}
$(OBJDIR)/%.o: %.c
$(CC) -c $< -o $#
clean:
rm -rf $(OBJS) $(OBJDIR)
When you want to add new directory say feature3, you can just add it in main makefile module list and copy the feature1 makefile to feature3 and update source file list
Hope this helps

Resources