Makefile应用综合实例
大项项目软件都具有专门的代码存放结构,包括源码文件、头文件信息、库文件信息、目标文件、调试目录、宏定义和编译选项等多项内容,为了管理,有经验的开发者往往使用变量来替换这些复杂的信息。
现在举个综合例子:项目软件:crm ;文件主目录:/root/crmpro 。
主目录包含的各子目录定义,如下:
./src : 存放项目源代码文件(*.c )
./include :存放项目的头文件信息
./lib :存放项目生成的或者第三方的库文件
./libsrc :存放项目生成库文件的源码文件
./obj :存放项目生成的目标文件信息
./ release :存放生成后的执行文件crm
./ debug :存放调试信息
文件目录结构如下:
|-- Makefile
|-- release
|-- obj
|--debug
|-- include
| |-- def1.h
| |-- def2.h
| |--defuser.h
|-- lib
| |--liblog.a
|--libsrc
| |--user.c
| |--admin.c
| |--Makefile1 //use “make” to build a lib file:../lib/liblog.a
|-- src
|-- main.c
|-- f1.c
|-- f2.c
代码文件中函数调用与包含关系:
f1.c-->def1.h
f2.c-->def2.h
user.c-->defuser.h
admin.c -->defuser.h
liblog.a-->user.c admin.c
mian.c-->f1.c f2.c liblog.a
test-->
项目文件目录含义:
bin:存放生成执行程序test
obj:存放所有*.c源码编译后的文件
lib:存放静态库libadmin.a(admin.c) libuser.a (user.c)
源文件清单如下:
/*def1.h*/
void func_one();
/*def2.h*/
void func_two();
/*defuser.h*/
void list_user();
void list_admin();
/*f1.c*/
#include "stdio.h"
#include "../include/def1.h"
void func_one()
{
printf("This isfunc_one() ,it is in f1.c!\n");
}
/*f2.c*/
#include "stdio.h"
#include "../include/def2.h"
void func_two()
{
printf("This isfunc_two(),it is in f2.c!\n");
}
/*user.c*/
#include "stdio.h"
#include "../include/defuser.h"
Void list_user()
{
printf("This is list_user(),itis in user.c!,and user.c is libuser.a\n");
}
/*admin.c*/
#include "stdio.h"
#include "../include/defuser.h"
Void list_user()
{
printf("This islist_admin(),it is in user.c!,and admin.c is libadmin.a\n");
}
/*main.c*/
#include "stdio.h"
#include "../include/def1.h"
#include "../include/def2.h"
#Incluce “../include/defuser.h
int main()
{
printf("main() isruning!\n");
func_one();
func_two();
list_user();
list_admin();
return 1;
}
#编辑Makefile文件,如下:
/*Makefile*/
# Readme:
# use: make
# use: make test
# use: make clean
# use: make rebuild
#use "make config" or "make dir" to
# build a source files struct.and then,
# put your source files into the DIR src
# link libs to the DIR lib
CC=gcc
MAKE_DIR=$(PWD)
INCLUDE_DIR=$(MAKE_DIR)/include/
SRC_DIR=$(MAKE_DIR)/src/
SRC_LIB_DIR=$(MAKE_DIR)/libsrc/
LIB_DIR=$(MAKE_DIR)/lib/
OBJ_DIR=$(MAKE_DIR)/obj/
RELEASE_DIR=$(MAKE_DIR)/release/
DEBUG_DIR=$(MAKE_DIR)/debug/
OUTPUT_DIR=
INCLUDE=-I$(INCLUDE_DIR) -I$(SRC_DIR)
LIB=-L$(LIB_DIR) -L$(OBJ_DIR)
vpath %.c $(SRC_DIR)
vpath %.h $(INCLUDE_DIR)
vpath %.o $(OBJ_DIR)
vpath %.a $(LIB_DIR)
SRC_FILES:=$(wildcard $(SRC_DIR)*.c)
OBJ_FILES:=$(patsubst %.c,%.o,$(SRC_FILES))
LIB_FILES_NAME:=$(notdir $(wildcard $(LIB_DIR)*.a))
LIB_NAME=$(subst lib,-l,$(basename $(LIB_FILES_NAME)))
OUTPUT_FILE=crm
FLAG_DEBUG=-c -g -Wall -ansi
FLAG_COMPLE=-c -O -Wall –ansi
FLAG_LINK=
DEBUG=1
ifeq ($(DEBUG),1)
OUTPUT_DIR:=$(DEBUG_DIR)
FLAG_COMPLE:=$(FLAG_DEBUG)
FLAG_LINK:=
else
OUTPUT_DIR:=$(RELEASE_DIR)
FLAG_COMPLE:=$(FLAG_COMPLE)
FLAG_LINK:=
endif
OUT=$(OUTPUT_DIR)$(OUTPUT_FILE)
$(OUT): $(OBJ_FILES)
@echo -e"building: $(notdir $@) \n\t please wait ...\n"
@$(CC) $(FLAG_LINK)$(addprefix $(OBJ_DIR),$(notdir $^)) $(LIB) $(LIB_NAME) -o $@
%.o:%.c
@echo -e"building: $(notdir $@) \n\t please wait ...\n"
@$(CC) $(FLAG_COMPLE) $< $(INCLUDE) -o$(OBJ_DIR)$(notdir $@)
.PHONY: all rebuild clean cleanall test
clean:
@rm -rf $(OBJ_DIR)*.o
@rm -rf $(OUT)
@clear
rebuild: cleanall
cleanall:
@rm -rf $(OBJ_DIR)*
@rm -rf $(RELEASE_DIR)*
@rm -rf $(DEBUG_DIR)*
test:
$(OUT)
/*bin/Makefile1*/
#reademe
#use: make -f Makefile1
#Makefile1 is in the dir(/root/crmpro/libsrc)
#make to build a libfile:../lib/liblog.a
INCLUDE_DIR=../include/
LIB_DIR=../lib/
SRC_FILES:=$(wildcard *.c)
OBJ_FILES:=$(patsubst %.c,%.o,$(SRC_FILES))
%.o:%.c
gcc -c $< -o $@-I$(INCLUDE_DIR)
liblog.a:$(OBJ_FILES)
ar -rcs $@ $^
mv $@ $(LIB_DIR)
rm $(OBJ_FILES)
注意:上述案例已经成功测试通过,助于加深对Makefile文件的理解!当你复制这些源代码文件时,注意去除文件中的空格,否则make命令时会出错!