Linux学习:Makefile简介及模板
一、基本概念介绍:
Makefile 文件就是告诉make命令需要怎么样的去编译和链接程序。
编写Makefile的基本规则:
1.如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
2.如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。
3.如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。
$@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件。
1 直观方式
举个例子:一个工程有3个头文件,和8个C文件,根据规则编写Makefile如下:
edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o main.o : main.c defs.h
cc -c main.c kbd.o : kbd.c defs.h command.h
cc -c kbd.c command.o : command.c defs.h command.h
cc -c command.c display.o : display.c defs.h buffer.h
cc -c display.c insert.o : insert.c defs.h buffer.h
cc -c insert.c search.o : search.c defs.h buffer.h
cc -c search.c files.o : files.c defs.h buffer.h command.h
cc -c files.c utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o
在这个makefile中,目标文件(target)包含:可执行文件 edit 和 中间目标文件(*.o),依赖文件(prerequisites)就是冒号后面的那些 .c 文件和 .h文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件 edit 的依赖文件。
输入make指令后的执行内容如下:
- make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
- 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。
- 如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。
- 如果edit所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
- 当然,C文件和H文件肯定存在,于是make会生成 .o 文件,然后再用 .o 文件声明make的终极任务,也就是执行文件edit了。
1.1 进阶1:使用变量
在上面的例子中,可以看到[.o]文件的字符串被重复了两次,如果工程需要加入一个新的[.o]文件,需要在各个依赖了该[.o]文件的地方添加,如果工程比较复杂会很麻烦,所以为了makefile的易维护,在makefile中可以使用变量。
比如,声明一个变量叫objects,也就叫 OBJECTS, objs, OBJS, obj, 或是 OBJ,只要能够表示obj文件就行。在makefile一开始就这样定义:
objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o
于是,在makefile中以“$(objects)”的方式来使用这个变量了。
进阶版本1:
objects = main.o kbd.o command.o display.o insert.osearch.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit $(objects)
于是如果有新的 .o 文件加入,只需添加到 objects 变量中即可。
1.2 进阶2:让make自动推导
GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,并且 cc -c xx.c 也会被推导出来。
进阶版本2:
objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o edit : $(objects)
cc -o edit $(objects) main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h .PHONY : clean
clean :
rm edit $(objects)
这种方法,也就是make的“隐晦规则”。上面文件内容中,“.PHONY”表示,clean是个伪目标文件。
即然make可以自动推导命令,那堆[.o]和[.h]的依赖同样可以收拢起来。进阶2.1:
objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o edit : $(objects)
cc -o edit $(objects) $(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h .PHONY : clean
clean :
rm edit $(objects)
上面2.1的版本使makefile变得更简单,但文件依赖关系就显得有点凌乱,鱼和熊掌不可兼得,各取所好。
2 清空目标文件的规则
每个Makefile中都应该写一个清空目标文件(.o和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。一般的风格都是:
clean:
rm edit $(objects)
更为稳健的做法是:
.PHONY : clean
clean :
-rm edit $(objects)
前面说过,.PHONY意思表示clean是一个“伪目标”,不声明伪目标的话,如果当前目录有个名为clean的文件,就会认为目标已存在,导致后面规则不执行了。而在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。
二、模板:
1、编译动态库
#############################################################
# Makefile for shared library.
# 编译动态链接库
#############################################################
#set your own environment option
CC = g++
CC_FLAG = -D_NOMNG -D_FILELINE #set your inc and lib
INC =
LIB = -lpthread -L./ -lsvrtool #make target lib and relevant obj
PRG = libsvrtool.so
OBJ = Log.o #all target
all:$(PRG) $(PRG):$(OBJ)
$(CC) -shared -o $@ $(OBJ) $(LIB) .SUFFIXES: .c .o .cpp
.cpp.o:
$(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o .PRONY:clean
clean:
@echo "Removing linked and compiled files......;
rm -f $(OBJ) $(PRG)
2、编译静态库
#############################################################
# Makefile for static library.
# 编译静态链接库
#############################################################
#set your own environment option
CC = g++
CC_FLAG = -D_NOMNG -D_FILELINE #static library use 'ar' command
AR = ar #set your inc and lib
INC =
LIB = -lpthread -L./ -lsvrtool #make target lib and relevant obj
PRG = libsvrtool.a
OBJ = Log.o #all target
all:$(PRG)
$(PRG):$(OBJ)
${AR} rv ${PRG} $? .SUFFIXES: .c .o .cpp
.cpp.o:
$(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o .PRONY:clean
clean:
@echo "Removing linked and compiled files......"
rm -f $(OBJ) $(PRG)
3、可执行程序
###########################################
#Makefile for simple programs
###########################################
INC=
LIB= -lpthread CC=CC
CC_FLAG=-Wall PRG=threadpooltest
OBJ=CThreadManage.o CThreadPool.o CThread.o CWorkerThread.o threadpooltest.o $(PRG):$(OBJ)
$(CC) $(INC) $(LIB) -o $@ $(OBJ) .SUFFIXES: .c .o .cpp
.cpp.o:
$(CC) $(CC_FLAG) $(INC) -c $*.cpp -o $*.o .PRONY:clean
clean:
@echo "Removing linked and compiled files......"
rm -f $(OBJ) $(PRG)
Linux学习:Makefile简介及模板的更多相关文章
- Linux学习笔记-Linux系统简介
Linux学习笔记-Linux系统简介 UNIX与Linux发展史 UNIX是父亲,Linux是儿子. UNIX发行版本 操作系统 公司 硬件平台 AIX IBM PowerPC HP-UX HP P ...
- Linux学习笔记之 Btrfs文件系统简介及使用
Btrfs 也有一个重要的缺点,当 BTree 中某个节点出现错误时,文件系统将失去该节点之下的所有的文件信息.而 ext2/3 却避免了这种被称为”错误扩散”的问题. Btrfs相关介绍: Btrf ...
- Linux C++ 开发简介
主要介绍将Windows程序迁移到Linux系统相关知识 简介 Windows程序迁移到Linux系统可能需要修改很多代码, 既需要了解Linux平台的开发知识, 也需要了解Windows平台代码如何 ...
- Linux C++ 开发简介(包括Linux守护线程)
阅读目录 简介 操作系统 编辑器 编译器 构建系统 调试 IDE 可执行程序.动态库.静态库 服务 Windows服务简介 创建Windows服务 注册Windows服务 管理Windows服务 Li ...
- 实验楼 linux 学习
实验楼 linux 学习 一.Linux 用户管理 1.查看用户 who am i // who mom likes whoami ====--------====== 输入的第一列表示打 ...
- [转] Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置
from: http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/07/3003278.html 如果要在Linux上做j2ee开发,首先得 ...
- Linux学习之CentOS--CentOS6.4下Mysql数据库的安装与配置【转】
如果要在Linux上做j2ee开发,首先得搭建好j2ee的开发环境,包括了jdk.tomcat.eclipse的安装(这个在之前的一篇随笔中已经有详细讲解了Linux学习之CentOS(七)--C ...
- Makefile简介
1.源程序的编译在Linux下面,如果要编译一个C语言源程序,我们要使用GNU的gcc编译器. 下面我们以一个实例来说明如何使用gcc编译器.假设我们有下面一个非常简单的源程序(hello.c):in ...
- Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置
原文:http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/07/3003278.html 如果要在Linux上做j2ee开发,首先得搭建好j ...
随机推荐
- Grassfire算法- 运动规划(Motion planning)
Grassfire算法: 一.概念 这个算法是做图像处理的抽骨架处理,目的是求出图像的骨架,可以想象一片与物体形状相同的草,沿其外围各点同时点火.当火势向内蔓延,向前推进的火线相遇处各点的轨迹就是中 ...
- TSN(Temporal Segment Networks)
一.算法详解 二.代码解析(pytorch版) 训练代码:https://blog.csdn.net/u014380165/article/details/79058147 测试代码:https:// ...
- 08 Windows编程——画图
源码 #include<Windows.h> #include<tchar.h> #include<stdio.h> #define NUM 1000 LRESUL ...
- int类型按字节打印输出
今天在项目编程中,遇到一个问题,u32类型的参数,要赋值给一个u8 array[3],想用memcpy()函数进行赋值,由于类型大小不一致,一时不知道怎么做,经过查找,得以解决.说明如下; 项 ...
- 【转】ufw 端口
1.扫描端口 用ubuntu自带的网络工具中的端口扫描不够强大,扫描结果可能不全,推荐用nmap,黑客常用的端口扫描利器!安装方法:sudo apt-get install nmap ,想扫描端口nm ...
- PAT Advanced 1073 Scientific Notation (20 分)
Scientific notation is the way that scientists easily handle very large numbers or very small number ...
- No PostCSS Config found in报错解决
前情提要]日前本人将本地项目上传GitHub之后,然后再clone到本地,运行是报错:Error: No PostCSS Config found in... 项目在本地打包运行的时候不报错,上传到 ...
- 0009SpringBoot静态资源访问路径
访问静态资源: 静态资源需要放在哪些路径下才能被访问呢: 通过WebMvcAutoConfiguration.java中 addResourceHandlers()方法查找绑定的路径,一个是通过web ...
- Nginx防盗链模块ngx_http_referer_module
ngx_http_referer_module⽤用来阻⽌止Referer⾸首部⽆无有效值的请求访问,可防⽌止盗链指令:12.1 valid_referers定义 referer ⾸首部的合法可⽤用值, ...
- JS 日期格式化,留作参考
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...