提到Makefile我就想起了中美合拍的《西游记》,偶,不对,提到Makefile不得不说是一种非常牛叉的编译工具了,他比cmake要易懂直观很多,可是,当我们编写大型软件时候,往往伴随着每次重新编译整个软件的问题消耗大量的编译时间,有没有一种方法可以只编译修改过得文件呢?这篇文章我们就来解决这个问题。
.
└── software
├── debug
│ ├── Makefile
│ ├── module1
│ │ └── src
│ └── module2
│ └── src
├── main.c
├── module1
│ ├── include
│ │ └── m1_api.h
│ └── src
│ └── m1.c
└── module2
├── include
│ └── m2_api.h
└── src
└── m2.c
12 directories, 8 files
#include
#include "m1_api.h"
#include "m2_api.h"
int main()
{
m1_func(NULL);
m2_func(NULL);
return 0;
}
#ifndef _MODULE1_API_H
#define _MODULE1_API_H
typedef struct {
int id;
int fd;
int tid;
int pid;
}m1_t;
void m1_func(m1_t *t);
#endif /*_MODULE1_API_H*/
#include
#include "m1_api.h"
void m1_func(m1_t *t)
{
printf("%s\n", __func__);
}
#ifndef _MODULE2_API_H
#define _MODULE2_API_H
typedef struct {
int id;
int fd;
int tid;
int pid;
}m2_t;
void m2_func(m2_t *t);
#endif /*_MODULE2_API_H*/
#include
#include "m2_api.h"
void m2_func(m2_t *t)
{
printf("%s\n", __func__);
}
SOFTROOT = /home/XXX/test/make/demo1/software
DEBUGROOT = $(SOFTROOT)/debug
TARGET = software.exe
我的用户名就不写出来了,换成自己的就行(目录自己修改),
CC = gcc
RM = rm -rf
ECHO = echo
SRCS :=
INCLUDES :=
LIBS :=
OBJS :=
DEPS :=
CFLAGS :=
SRCS += $(SOFTROOT)/module1/src/m1.c
SRCS += $(SOFTROOT)/module2/src/m2.c
SRCS += $(SOFTROOT)/main.c
INCLUDES += -I$(SOFTROOT)/module1/include
INCLUDES += -I$(SOFTROOT)/module2/include
这里的目标文件我们根据源文件和编译输出路径来转化,不由用户自己规定
OBJS += $(subst $(SOFTROOT),$(DEBUGROOT),$(patsubst %.c,%.o,$(SRCS)))
DEPS += $(subst $(SOFTROOT),$(DEBUGROOT),$(patsubst %.c,%.d,$(SRCS)))
整体思路:先将.c替换成.o(或者.d),然后将源文件路径替换为编译文件夹的路径。
$(OBJS):
@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi;
@$(ECHO) "\033[1;31mCompile\033[0m: $(notdir $@)"
@$(CC) -o $@ $(CFLAGS) -c $(patsubst %.o,%.c,$(subst $(DEBUGROOT),$(SOFTROOT),$@))
$(DEPS):
@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi; \
set -e; $(RM) $@
@$(ECHO) "\033[1;31mCreate\033[0m: $(notdir $@)"
@$(CC) -MM $(CFLAGS) -c $(patsubst %.d,%.c,$(subst $(DEBUGROOT),$(SOFTROOT),$@)) -o [email protected]
@sed 's,\($(notdir $(basename $@))\).o[ :]*,$(dir $@)\1.o $@ :,g' < [email protected] > $@;\
$(RM) [email protected]
-include $(DEPS)
注意最后一句-include。
可以适量的添加makefile查找源文件的路径,制定查找路径
vpath %.c $(dir %(SRCS))
SOFTROOT = /home/rongtao/test/make/demo1/software
DEBUGROOT = $(SOFTROOT)/debug
TARGET = software.exe
CC = gcc
RM = rm -rf
ECHO = echo
SRCS :=
INCLUDES :=
LIBS :=
OBJS :=
DEPS :=
CFLAGS :=
SRCS += $(SOFTROOT)/module1/src/m1.c
SRCS += $(SOFTROOT)/module2/src/m2.c
SRCS += $(SOFTROOT)/main.c
INCLUDES += -I$(SOFTROOT)/module1/include
INCLUDES += -I$(SOFTROOT)/module2/include
OBJS += $(subst $(SOFTROOT),$(DEBUGROOT),$(patsubst %.c,%.o,$(SRCS)))
DEPS += $(subst $(SOFTROOT),$(DEBUGROOT),$(patsubst %.c,%.d,$(SRCS)))
CFLAGS += $(INCLUDES)
all:$(OBJS)
@$(ECHO) "\033[1;31mFinish\033[0m"
@$(CC) $(CFLAGS) $(OBJS) -o $(TARGET)
$(OBJS):
@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi;
@$(ECHO) "\033[1;31mCompile\033[0m: $(notdir $@)"
@$(CC) -o $@ $(CFLAGS) -c $(patsubst %.o,%.c,$(subst $(DEBUGROOT),$(SOFTROOT),$@))
$(DEPS):
@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi; \
set -e; $(RM) $@
@$(ECHO) "\033[1;31mCreate\033[0m: $(notdir $@)"
@$(CC) -MM $(CFLAGS) -c $(patsubst %.d,%.c,$(subst $(DEBUGROOT),$(SOFTROOT),$@)) -o [email protected]
@sed 's,\($(notdir $(basename $@))\).o[ :]*,$(dir $@)\1.o $@ :,g' < [email protected] > $@;\
$(RM) [email protected]
-include $(DEPS)
vpath %.c $(dir %(SRCS))
clean:
@$(ECHO) "\033[1;31mClean\033[0m"
@$(RM) $(DEPS) $(OBJS) $(TARGET)
源代码请搜索CSDN与本文同名的资源下载即可“Makefile不编译已经编译过的文件”。