Makefile 总结
--- 2014.9.17 (miaoguoxiang)
第一部份:makefile应用场合分类及对应目录名称
1: 基本应用 basic_make
2: 自动推导依赖关系应用 auto_make
3: 变量、函数与通配符的使用应用 variable_make
4: 文件查找应用 find_for_make
5: dos下源文件转UNIX下的混合编程应用 dos_unix_make
6: 引用其他Makefile应用 refer_make
7: 静态编译应用 static_make
8: 嵌套makefile文件应用 multiple_make
第二部份:基本测试环境
源文件:main.c 2.c 3.c
头文件:a.h b.h c.h
依赖关系:
/*main.c*/
#include "a.h"
/*2.c*/
#include "a.h"
#include "b.h"
/*3.c*/
#include "b.h"
#include "c.h"
可执行文件约定名词:myapp
makefile 中的依赖关系表示为
myapp:main.o 2.o 3.o
main.o:main.c a.h
2.o:2.c a.h b.h
3.o:3.c b.h c.h
第三部份:分组讲解
1: basic_make
说明:处理多文件编译的基本技术,makefile主要分四个基本部份:
1)定义变量部份:CC=gcc/*指定编译器*/ INSTDIR=/*指定安装位置*/ INCLUDE=/*指定保护三文件位置*/ CFLAGS=/*指定编辑器参数*/
2)依赖关系部份:基本的依赖关系并引导以tab开头的命令选项
3)清除中间文件命令部份:clean: 后接shell引导命令
4)安装位置命令:install:myapp 后接shell安装位置设置命令
主文件如下:
----------------------------------------------------------
all:myapp /*指定多个目标需用all,否则,make命令将只创建它在makefile中找到的第一个目标*/
CC = gcc
INSTDIR = ~/practice_makefile/basic_make/install_1
INCLUDE = .
CFLAGS = -g -Wall -ansi
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
2.o: 2.c a.h b.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c
3.o: 3.c b.h c.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c
clean:
-rm main.o 2.o 3.o
install: myapp
@if [ -d $(INSTDIR) ]; \
then \
cp myapp $(INSTDIR);\
chmod a+x $(INSTDIR)/myapp;\
chmod og-w $(INSTDIR)/myapp;\
echo "Installed in $(INSTDIR)";\
else \
echo "Sorry, $(INSTDIR) does not exist";\
fi
---------------------------------------------------------
2: auto_make
说明:这部份的主要作用是简化makefile的编写工作,主要应用于make能够自动推导依赖关系,如将第一部份的makefile文件去除第二部份,改为如下:
-----------------------------------
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
2.o: 2.c a.h b.h
3.o: 3.c b.h c.h
-----------------------------------
make可以自动的推导出依赖关系,并进行编译
同时,还可以应用单独的make命令进行GCC的编译,如下面的输入文件foo.C文件:
----------------------------------------------------------------
#include <stdio.h>
int main()
{
printf("This is test only \"make\" to compile.\n");
}
----------------------------------------------------------------
执行命令:$make foo
3: variable_make
说明:这部份主要的作用是简化Makefile文件的编写工作,主要包含宏、通配符、变量、函数四部份
1)常用的宏如下:
$? 当前目标所依赖的文件列表中比当前目标文件还要新的文件
$@ 当前目标的名字
$< 当前依赖文件的名字
$* 不包括后缀名的当前依赖文件的名字
$^ 所有依赖文件的名字
@ 不要将Make里面的命令回显到标准输出上
2)常用的通配符如下:
% 匹配任意个数字符
* ? ... 与shell一样
~ 与shell,当前用户的家目录
3)定义变量的方法与常用的变量:
定义变量:CFLAGS = -g -Wall -ansi
/* = 、?=、define 为延时变量
:= 为立即变量*/
取变量值:$(CFLAGS)
4)函数的调用格式与常用的函数:
格式:$(function_name argument)
常用函数如下:
字符串函数:subst,patsubst,strip,findstring,filter,filter-out,sort
文件名函数:dir,notdir,suffix,basename,addsuffix,addprefix
其他函数:foreach,ifcondition
这部份对比basic_make文件中的更改为:
----------------------------
src = $(shell ls *.c) /*用shell命令选取所有C源文件*/
objs = $(patsubst %.c, %.o, $(src)) /*将src选取的源文件的后缀名由.c改为.o*/
myapp: $(objs)
$(CC) -o $@ $^
---------------------------
4: find_for_make
说明:这个的应用比较具有实用价值,工程中将.c文件与.h文件分别放在两个目录中。make将会自动去往两个子目录进行文件查找,需要应用的到的两个变量(或关系)名如下:
1)VPATH = src:../headers
2)vpath %.h ../headers
/*需要注意依赖命令编译时要将*.c改为$<*/
本测试程序的目录结构如下:
find_for_make
|-main.c
|-Makefile
|-directory_c
|-2.c
|-2.c
|-directory_h
|-a.h
|-b.h
|-c.h
本测试程序的makefile主内容如下:
------------------------------------
vpath %.c ./directory_c
vpath %.h ./directory_h
------------------------------------
5: dos下源文件转UNIX值下的混合编程应用dos_unix_make
说明:dos下的C或者C++源文件常常不是以.c结尾的。可能会是以.cpp结尾的。其实dos下的源文件可以直接拿到unix下与unix源文件进行一起编译。
格式如下:
.cpp.o: 或者 %.cpp: %o /*意思是遇到所有.cpp文件均将其转为.o的文件*/
本测试程序的2.cpp和3.cpp是从windows7中转过来的。如下是makefile主要内容:
--------------------------------------------------------
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
$(CC) -xc++ -I$(INCLUDE) $(CFLAGS) -c main.c
2.o: 2.cpp a.h b.h
%.cpp: %o
$(CC) -xc++ -I$(INCLUDE) $(CFLAGS) -c $<
3.o: 3.cpp b.h c.h
%.cpp: %o
$(CC) -xc++ -I$(INCLUDE) $(CFLAGS) -c $<
--------------------------------------------------------
6: refer_make
说明:这个部份主要应用于借助已有的makefile文件,来为当前要创建的makefile文件来省掉一些工作。有点类似于C或C++里面的包含文件。格式如下:
include filename
本测试部份将makefile分为两个文件,Makefile和Makefile_refer,将Makefile_refer作为被引用的文件。在Makefile中的引用语句如下:
include ./Makefile_refer
7: static_make
说明:适用于有很多的.o和.c文件的大编译项目,总的思想是用通配符与宏运用静态编译的规则将.c文件转为.o文件。规则如下:
<targets...>:<target-pattern>:<prereq-patterns...>
<commands>
...
本测试部份主要部份如下:
---------------------------------------------------
#This is static compiler test
objects = 2.o 3.o
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
$(objects):%.o:%.c
$(CC) -c $(CFLAGS) -I$(INCLUDE) $< -o $@
---------------------------------------------------
8: multiple_make
说明:个人认为嵌套的makefile文件是最有用的。当安装文件时什么“正在进入的目录...”,“正在离开目录...”的云云提示,就是嵌套文件的工作反馈。嵌套make文件也可以叫宏控制makefile文件。我们可以把不同模块或者不同功能的源文件放在一个目录中,并为其编写makefile文件,然后在父目录进行makefile的总控。
规则如下:
subsystem:
cd subdir && $(MAKE)
本测试部份的目录结构如下:
multiple_make
|-Makefile
|-subdir1
|-main.c 2.c 3.c a.h b.h c.h Makefile
|-subdir2
|-main.c 2.c 3.c a.h b.h c.h Makefile
本测试部份的各子目录的Makefile的内容基本不做变化,总控Makefile内容如下:
-----------------------------------------------------------------------
DIRS = subdir1 subdir2
all:
for i in $(DIRS); do \
(cd $$i && echo "making $$i" && $(MAKE) ) || exit 1; \
done
clean:
for i in $(DIRS); do \
(cd $$i && echo "cleaning $$i" && $(MAKE) clean) || exit 1; \
done
----------------------------------------------------------------------
--- 2014.9.17 (miaoguoxiang)
第一部份:makefile应用场合分类及对应目录名称
1: 基本应用 basic_make
2: 自动推导依赖关系应用 auto_make
3: 变量、函数与通配符的使用应用 variable_make
4: 文件查找应用 find_for_make
5: dos下源文件转UNIX下的混合编程应用 dos_unix_make
6: 引用其他Makefile应用 refer_make
7: 静态编译应用 static_make
8: 嵌套makefile文件应用 multiple_make
第二部份:基本测试环境
源文件:main.c 2.c 3.c
头文件:a.h b.h c.h
依赖关系:
/*main.c*/
#include "a.h"
/*2.c*/
#include "a.h"
#include "b.h"
/*3.c*/
#include "b.h"
#include "c.h"
可执行文件约定名词:myapp
makefile 中的依赖关系表示为
myapp:main.o 2.o 3.o
main.o:main.c a.h
2.o:2.c a.h b.h
3.o:3.c b.h c.h
第三部份:分组讲解
1: basic_make
说明:处理多文件编译的基本技术,makefile主要分四个基本部份:
1)定义变量部份:CC=gcc/*指定编译器*/ INSTDIR=/*指定安装位置*/ INCLUDE=/*指定保护三文件位置*/ CFLAGS=/*指定编辑器参数*/
2)依赖关系部份:基本的依赖关系并引导以tab开头的命令选项
3)清除中间文件命令部份:clean: 后接shell引导命令
4)安装位置命令:install:myapp 后接shell安装位置设置命令
主文件如下:
----------------------------------------------------------
all:myapp /*指定多个目标需用all,否则,make命令将只创建它在makefile中找到的第一个目标*/
CC = gcc
INSTDIR = ~/practice_makefile/basic_make/install_1
INCLUDE = .
CFLAGS = -g -Wall -ansi
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
2.o: 2.c a.h b.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c
3.o: 3.c b.h c.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c
clean:
-rm main.o 2.o 3.o
install: myapp
@if [ -d $(INSTDIR) ]; \
then \
cp myapp $(INSTDIR);\
chmod a+x $(INSTDIR)/myapp;\
chmod og-w $(INSTDIR)/myapp;\
echo "Installed in $(INSTDIR)";\
else \
echo "Sorry, $(INSTDIR) does not exist";\
fi
---------------------------------------------------------
2: auto_make
说明:这部份的主要作用是简化makefile的编写工作,主要应用于make能够自动推导依赖关系,如将第一部份的makefile文件去除第二部份,改为如下:
-----------------------------------
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
2.o: 2.c a.h b.h
3.o: 3.c b.h c.h
-----------------------------------
make可以自动的推导出依赖关系,并进行编译
同时,还可以应用单独的make命令进行GCC的编译,如下面的输入文件foo.C文件:
----------------------------------------------------------------
#include <stdio.h>
int main()
{
printf("This is test only \"make\" to compile.\n");
}
----------------------------------------------------------------
执行命令:$make foo
3: variable_make
说明:这部份主要的作用是简化Makefile文件的编写工作,主要包含宏、通配符、变量、函数四部份
1)常用的宏如下:
$? 当前目标所依赖的文件列表中比当前目标文件还要新的文件
$@ 当前目标的名字
$< 当前依赖文件的名字
$* 不包括后缀名的当前依赖文件的名字
$^ 所有依赖文件的名字
@ 不要将Make里面的命令回显到标准输出上
2)常用的通配符如下:
% 匹配任意个数字符
* ? ... 与shell一样
~ 与shell,当前用户的家目录
3)定义变量的方法与常用的变量:
定义变量:CFLAGS = -g -Wall -ansi
/* = 、?=、define 为延时变量
:= 为立即变量*/
取变量值:$(CFLAGS)
4)函数的调用格式与常用的函数:
格式:$(function_name argument)
常用函数如下:
字符串函数:subst,patsubst,strip,findstring,filter,filter-out,sort
文件名函数:dir,notdir,suffix,basename,addsuffix,addprefix
其他函数:foreach,ifcondition
这部份对比basic_make文件中的更改为:
----------------------------
src = $(shell ls *.c) /*用shell命令选取所有C源文件*/
objs = $(patsubst %.c, %.o, $(src)) /*将src选取的源文件的后缀名由.c改为.o*/
myapp: $(objs)
$(CC) -o $@ $^
---------------------------
4: find_for_make
说明:这个的应用比较具有实用价值,工程中将.c文件与.h文件分别放在两个目录中。make将会自动去往两个子目录进行文件查找,需要应用的到的两个变量(或关系)名如下:
1)VPATH = src:../headers
2)vpath %.h ../headers
/*需要注意依赖命令编译时要将*.c改为$<*/
本测试程序的目录结构如下:
find_for_make
|-main.c
|-Makefile
|-directory_c
|-2.c
|-2.c
|-directory_h
|-a.h
|-b.h
|-c.h
本测试程序的makefile主内容如下:
------------------------------------
vpath %.c ./directory_c
vpath %.h ./directory_h
------------------------------------
5: dos下源文件转UNIX值下的混合编程应用dos_unix_make
说明:dos下的C或者C++源文件常常不是以.c结尾的。可能会是以.cpp结尾的。其实dos下的源文件可以直接拿到unix下与unix源文件进行一起编译。
格式如下:
.cpp.o: 或者 %.cpp: %o /*意思是遇到所有.cpp文件均将其转为.o的文件*/
本测试程序的2.cpp和3.cpp是从windows7中转过来的。如下是makefile主要内容:
--------------------------------------------------------
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
$(CC) -xc++ -I$(INCLUDE) $(CFLAGS) -c main.c
2.o: 2.cpp a.h b.h
%.cpp: %o
$(CC) -xc++ -I$(INCLUDE) $(CFLAGS) -c $<
3.o: 3.cpp b.h c.h
%.cpp: %o
$(CC) -xc++ -I$(INCLUDE) $(CFLAGS) -c $<
--------------------------------------------------------
6: refer_make
说明:这个部份主要应用于借助已有的makefile文件,来为当前要创建的makefile文件来省掉一些工作。有点类似于C或C++里面的包含文件。格式如下:
include filename
本测试部份将makefile分为两个文件,Makefile和Makefile_refer,将Makefile_refer作为被引用的文件。在Makefile中的引用语句如下:
include ./Makefile_refer
7: static_make
说明:适用于有很多的.o和.c文件的大编译项目,总的思想是用通配符与宏运用静态编译的规则将.c文件转为.o文件。规则如下:
<targets...>:<target-pattern>:<prereq-patterns...>
<commands>
...
本测试部份主要部份如下:
---------------------------------------------------
#This is static compiler test
objects = 2.o 3.o
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
$(objects):%.o:%.c
$(CC) -c $(CFLAGS) -I$(INCLUDE) $< -o $@
---------------------------------------------------
8: multiple_make
说明:个人认为嵌套的makefile文件是最有用的。当安装文件时什么“正在进入的目录...”,“正在离开目录...”的云云提示,就是嵌套文件的工作反馈。嵌套make文件也可以叫宏控制makefile文件。我们可以把不同模块或者不同功能的源文件放在一个目录中,并为其编写makefile文件,然后在父目录进行makefile的总控。
规则如下:
subsystem:
cd subdir && $(MAKE)
本测试部份的目录结构如下:
multiple_make
|-Makefile
|-subdir1
|-main.c 2.c 3.c a.h b.h c.h Makefile
|-subdir2
|-main.c 2.c 3.c a.h b.h c.h Makefile
本测试部份的各子目录的Makefile的内容基本不做变化,总控Makefile内容如下:
-----------------------------------------------------------------------
DIRS = subdir1 subdir2
all:
for i in $(DIRS); do \
(cd $$i && echo "making $$i" && $(MAKE) ) || exit 1; \
done
clean:
for i in $(DIRS); do \
(cd $$i && echo "cleaning $$i" && $(MAKE) clean) || exit 1; \
done
----------------------------------------------------------------------