.
|-- build
| |-- make.rule
| `-- makefile
`-- source
|-- bar
| |-- inc
| | `-- bar.h
| `-- src
| |-- bar.c
| `-- makefile
|-- foo
| |-- inc
| | |-- define.h
| | |-- foo.h
| | `-- other.h
| `-- src
| |-- foo.c
| `-- makefile
`-- huge
`-- src
|-- main.c
`-- makefile
build/make.rule
.PHONY:all clean
MKDIR = mkdir
RM = rm
RMFLAGS = -rf
CC = gcc
AR = ar
ARFLAGS = crs
DIR_OBJS = objs
DIR_EXES = $(ROOT)/build/exes
DIR_DEPS = deps
DIR_LIBS = $(ROOT)/build/libs
DIRS = $(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(DIR_LIBS)
RMS = $(DIR_OBJS) $(DIR_DEPS)
ifneq ($(EXE),"")
EXE := $(addprefix $(DIR_EXES)/,$(EXE))
RMS += $(EXE)
endif
ifneq ($(LIB),"")
LIB := $(addprefix $(DIR_LIBS)/,$(LIB))
RMS += $(LIB)
endif
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
OBJS := $(addprefix $(DIR_OBJS)/,$(OBJS))
DEPS = $(SRCS:.c=.dep)
DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))
ifneq ($(EXE),"")
all: $(EXE)
endif
ifneq ($(LIB),"")
all: $(LIB)
endif
ifneq ($(MAKECMDGOALS),clean)
include $(DEPS)
endif
ifneq ($(INC_DIRS),"")
INC_DIRS := $(strip $(INC_DIRS))
INC_DIRS := $(addprefix -I,$(INC_DIRS))
endif
ifneq ($(LINK_LIBS),"")
LINK_LIBS := $(strip $(LINK_LIBS))
LINK_LIBS := $(addprefix -l, $(LINK_LIBS))
endif
$(DIRS):
$(MKDIR) $@
$(EXE):$(DIR_EXES) $(OBJS)
$(CC) -L$(DIR_LIBS) -o $@ $(filter %.o,$^) $(LINK_LIBS)
$(LIB): $(DIR_LIBS) $(OBJS)
$(AR) $(ARFLAGS) $@ $(filter %.o,$^)
$(DIR_OBJS)/%.o: $(DIR_OBJS) %.c
$(CC) $(INC_DIRS) -o $@ -c $(filter %.c,$^)
$(DIR_DEPS)/%.dep: $(DIR_DEPS) %.c
@echo "making $@..."
@set -e; \
$(RM) $(RMFLAGS) $@.tmp; \
$(CC) $(INC_DIRS) -E -MM $(filter %.c,$^) > $@.tmp; \
sed 's,\(.*\)\.o[:]*,objs/\1.o $@:,g' < $@.tmp > $@; \
$(RM) $(RMFLAGS) $@.tmp
clean:
$(RM) $(RMFLAGS) $(RMS)
build/makefile
.PHONY: all clean
DIRS = $(ROOT)/source/foo/src \
$(ROOT)/source/bar/src \
$(ROOT)/source/huge/src
RM = rm
RMFLAGS = -rf
RMS = $(ROOT)/build/exes $(ROOT)/build/libs
all:
@set -e; \
for dir in $(DIRS); \
do \
cd $$dir && $(MAKE); \
done
@echo ""
@echo ":-) completed"
@echo ""
clean:
@set -e; \
for dir in $(DIRS); \
do \
cd $$dir && $(MAKE) clean; \
done
$(RM) $(RMFLAGS) $(RMS)
@echo ""
@echo ":-) completed"
@echo ""
source/huge/src/main.c
#include "foo.h"
int main()
{
foo();
bar();
return 0;
}
source/huge/src/makefile
EXE = huge
LIB =
INC_DIRS = $(ROOT)/source/foo/inc \
$(ROOT)/source/foo/inc
LINK_LIBS = foo bar
include $(ROOT)/build/make.rule
source/huge/foo/src/foo.c
#include <stdio.h>
#include "foo.h"
void foo()
{
printf("%s this is foo()\n", HELLO);
}
source/huge/foo/src/makefile
EXE =
LIB = libfoo.a
INC_DIRS = $(ROOT)/source/foo/inc
LINK_LIBS =
include $(ROOT)/build/make.rule
source/huge/foo/inc/foo.h
#ifndef __FOO_H
#define __FOO_H
#include "define.h"
void foo();
#endif
source/huge/foo/inc/other.h
#ifndef __OTHER_H
#define __OTHER_H
#define HELLO "hii"
#endif
source/huge/foo/inc/define.h
#ifndef __DEFINE_H
#define __DEFINE_H
#include "other.h"
#endif
source/huge/bar/src/bar.c
#include <stdio.h>
#include "bar.h"
void bar()
{
printf("this is bar() \n");
}
source/huge/bar/src/makefile
EXE =
LIB = libbar.a
INC_DIRS = $(ROOT)/source/bar/inc
LINK_LIBS =
include $(ROOT)/build/make.rule
source/huge/bar/inc/bar.h
#ifndef __BAR_H
#define __BAR_H
void bar();
#endif