Linux Makefile文件编写详细步骤与实践
Linux Makefile文件编写详细步骤与实践
1.makefile概述
Windows环境下IDE会帮你完成makefile文件的编写,但在UNIX环境下你就必须自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile中也可以执行操作系统的命令。makefile带来的好处就是一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具。
2.makefile文件的基本结构
1.需要由make工具创建的目标体,一般是目标文件或可执行文件,也可以是一个标签,对于标签这种特性,在后续的“伪目标”章节中会有叙述。
2.目标文件或可执行文件所依赖的文件。
3.创建每个目标体时所需要执行的命令,这一行必须以制表符(tab)开头。
target ... : prerequisites ...
command
...
...
3.makefile变量
变量是在makefile中定义的名字,用来代表一个文本字符串,该文本字符串称为该变量的值,引用时用$引用。
两种变量定义形式:
1.递归定义展开方式:VAR=var,在引用该变量的时候进行替换,如果该变量中包含了对其他变量的引用,则在引用该变量的时候一次性将内嵌的变量全部展开。
2.简单扩展方式:VAR:=var,在定义处展开,只展开一次,不包含对其他变量的引用,消除了嵌套引用。
重新编写例程可以为:
OBJS=talent.o hardwork.o
CC=gcc
CFLAGS=-Wall -O -g
success:$(OBJS)
$(CC) $(CFLAGS) $^ -o success
talent.o:talent.c talent.h
$(CC) $(CFLAGS) $^ -o talent.o
hardwork.o:hardwork.c hardwork.h
$(CC) $(CFLAGS) $^ -o hardwork.o
说几个makefile中几个常见的预定义变量及其默认值:
CC:C编译器的名称,默认cc;
CFLAGS :C编译器的选项,无默认值;
CXXFLAGS:C++编译器的选项,无默认值;
makefile中几个常见的自动变量:
$<:第一个依赖文件的名称;
$^:所有不重复的依赖文件,以空格分开;
$@:目标文件的完整名称;
$?:所有时间戳比目标文件新的依赖文件,并以空格分开;
当然还有几个就不介绍啦!
4.一个简单的makefile
/*add.c*/
int add(int a,int b)
{
return (a+b);
}
/*sub.c*/
int sub(int a,int b)
{
return (a-b);
}
/*div.c*/
int div(int a,int b)
{
return (a/b);
}
/*mul.c*/
int mul(int a,int b)
{
return (a*b);
}
#include <stdio.h>
/*func_point.c*/
int process(int (*math_p)(int,int),int x,int y);
extern int add(int,int);
extern int sub(int,int);
extern int mul(int,int);
extern int div(int,int); int main(void)
{
int a=8,b=2; printf("add(8,2)=%d\n",process(add,a,b));
printf("sub(8,2)=%d\n",process(sub,a,b));
printf("mul(8,2)=%d\n",process(mul,a,b));
printf("div(8,2)=%d\n",process(div,a,b)); return 0;
}
int process(int (*math_p)(int x,int y),int x,int y)
{
return(math_p(x,y));
}
#makefile
func_point:func_point.o add.o sub.o mul.o div.o
gcc func_point.o add.o sub.o mul.o div.o -o func_point
add.o:add.c
gcc -c add.c
sub.o:sub.c
gcc -c sub.c
div.o:div.c
gcc -c div.c
mul.o:mul.c
gcc -c mul.c
func_point.o:func_point.c
gcc -c func_point.c
执行make命令的时候,找到缺省的target,即func_point。func_point之后是它的prerequisites文件,首先找到func_point.o这个文件,但这个文件又是后续的target文件,再找到func_point.o目标的prerequisites文件。然后执行func_point.o目标文件下的command,command执行完毕返回上级;找到add.o这个文件,add.o又是后续的目标文件,然后找到add.o目标文件的prerequisites文件,然后执行add.o目标文件的command,执行完毕...依次递归...最后执行func_point目标文件的command。到此为止,这个文件就编译完成了。#后面表示注释。
读者仔细观察,所有的target文件都要比prerequisites文件新。add.o、sub.o、mul.o、div.o比这些文件的prerequisites文件新。如果有任意一个prerequisites文件比target文件新,那target所对应的command就被执行。这就是Makefile的规则,也是Makefile的核心内容。
通常Makefile有一个clean目标,用于清除编译过程中产生的中间文件,保留源代码。现在将目标clean加入到我们的Makefile中。
#makefile
func_point:func_point.o add.o sub.o mul.o div.o
gcc func_point.o add.o sub.o mul.o div.o -o func_point
add.o:add.c
gcc -c add.c
sub.o:sub.c
gcc -c sub.c
div.o:div.c
gcc -c div.c
mul.o:mul.c
gcc -c mul.c
func_point.o:func_point.c
gcc -c func_point.c
clean:
@echo "clean project"
-rm *.o
@echo "clean complete"
如果在当前工作路径下有一个clean文件,我们makefile文件中的clean执行就会被忽略,在我们原来Makefile的最后一行加如下代码就可以了:
.PHONY:clean
clean是一个约定俗称的目标,像这样的约定还有。
all:通常为缺省的目标,执行缺省的编译工作。
install:编译后的安装工作,将相应的文件拷贝到合适的位置。
distclean:清除所有编译中生成的文件,只保留源文件。
好啦!下面我们对刚才的makefile文件进行一下瘦身:
#makefile
OBJ_FILE=func_point.o add.o sub.o div.o mul.o
func_point:$(OBJ_FILE)
gcc $^ -o $@
clean:
@echo "clean project"
-rm *.o
@echo "clean complete"
.PHONY:clean
5.函数的使用
在Makefile中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能。make所支持的函数也不算很多,不过已经足够我们的操作了。函数调用后,函数的返回值可以当做变量来使用。函数调用,很像变量的使用,也是以“$”来标识的,其语法如下:
$(<function>; <arguments>;)或是${<function>; <arguments>;}
这里,<function>;就是函数名,make支持的函数不多。<arguments>;是函数的参数,参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔。函数调用以“$”开头,以圆括号或花括号把函数名和参数括起。
#makefile
SRC_FILE=$(wildcard *.c)
func_point:$(SRC_FILE)
gcc $^ -o $@
clean:
@echo "clean project"
-rm *.o
@echo "clean complete"
.PHONY:clean
/*wildcard是函数的名字,这是系统提供的函数,*.c 是函数的参数。这句话的意思是找出当前工作路径下的所有的以.c结尾的源文件。然后将返回值初始化SRC_FILE变量。
-n选项只打印要执行的命令,而不会真的执行命令,这个选项有助于我们检查Makefile写得是否正确,由于Makefile不是顺序执行的,用这个选项可以先看看命令的执行顺序,确认无误了再真正执行命令。
-C选项可以切换到另一个目录执行那个目录下的Makefile,比如先退到上一级目录再执行我们的Makefile。 -C后边跟那个目录就行了。*/
6.小项目实践
假设math目录下有前面的add.c sub.c mul.c div.c源文件,与math同目录下有func_point.c文件!
math目录下makefile文件如下:
#Makefile
mymath:add.c sub.c div.c mul.c
gcc -c -fPIC add.c sub.c div.c mul.c
gcc -shared -o libmymath.so add.o sub.o mul.o div.o
# gcc func_point.c -lmymath -o test
install:
@sudo mv libmymath.so /usr/lib
#test:func_point.c
# gcc func_point -lmymath clean:
@echo "clean project"
-rm *.o
@echo "clean complete"
.PHONY:clean
与math同级目录下makefile文件如下:
all:
make -C math
make -C math install
make -C math clean
gcc func_point.c -Lmath -lmymath -o test
程序介绍:在math同级目录下运行make命令时,它会把math目录下的add.c sub.c mul.c div.c生成动态链接库,并拷贝到/usr/lib中,后清除中间过程文件,在math同级目录下可运行test可执行程序。
如有错误,欢迎批评改正!
Linux Makefile文件编写详细步骤与实践的更多相关文章
- 【OpenWRT】【RT5350】【三】MakeFile文件编写规则和OpenWRT驱动开发步骤
一.Makefile文件编写 http://www.cnblogs.com/majiangjiang/articles/3218002.html 可以看下上面的博客,总结的比较全了,在此不再复述 二. ...
- Linux makefile 教程 非常详细,且易懂(转)
转自:http://blog.chinaunix.net/uid-27717694-id-3696246.html 原文地址:Linux makefile 教程 非常详细,且易懂 作者:Deem_pa ...
- 转:SYNOPSYS VCS Makefile文件编写与研究
SYNOPSYS VCS Makefile文件编写与研究 这个Makefile是synopsys提供的模板,看上去非常好用,你只要按部就班提供实际项目的参数就可以了.我们来看这个文件的头部说明:mak ...
- 一个简单的makefile文件编写
下午闲来无聊,就打开很久没动过的linux系统想熟悉熟悉在linux上面编译代码,结果一个makefile文件搞到晚上才搞定,哈哈! 先把代码简单贴上来,就写了一个冒泡排序: sort.h: #ifn ...
- 【转】Linux makefile 教程 非常详细,且易懂
From: http://blog.csdn.net/liang13664759/article/details/1771246 最近在学习Linux下的C编程,买了一本叫<Linux环境下的C ...
- Linux makefile 教程 非常详细,且易懂
最近在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到makefile就越看越迷糊,可能是我的理解能不行. 于是google到了以下这篇文章.通俗易懂.然后把它贴出 ...
- Linux makefile 教程 非常详细,且易懂 (转)
概述—— 什么是makefile?或许很多Winodws的程序员都不知道这 个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makef ...
- Linux makefile 教程 非常详细,且易懂【转】
转自: http://blog.csdn.net/liang13664759/article/details/1771246 最近在学习Linux下的C编程,买了一本叫<Linux环境下的C ...
- linux库文件编写入门(笔记)
linux库文件的编写 作者: laomai地址: http://blog.csdn.net/laomai 本文主要参考了如下资料⑴hcj写的"Linux静态/动态链接库的创建和使用&quo ...
随机推荐
- Dynamics CRM 2013 初体验(3):新增加的功能
新系统除了修补系统历史漏洞外当然还会添加些比较有意思的新功能,至于这些新功能是否好用那就得看它是否能经过咱们这些使用者的考验了.Dynamics CRM 2013系统将不再支持Dynamics CRM ...
- Virtualbox下实现Ubuntu虚拟机和win7主机文件共享(很简单,亲自试用,按此步骤一般都会成功)
最近做一个操作系统实验,第一个实验即是实现Ubantu虚拟机与主机之间的共享. 本例用的是VirtualBox虚拟机,若使用Vmware WorkStation虚拟机则方法与下文介绍略有不同,但基本相 ...
- [转]Geoserver实现WFS操作
From:http://liushaobo2005.blog.163.com/blog/static/253056702011541462372/ wfs是OGC的标准规范,主要用于提供对矢量地理数据 ...
- 1、什么是Lucene,Lucene能干什么
1.什么是lucene Lucene是一个全文搜索框架,而不是应用产品.因此它并不像http://www.baidu.com/ 或者google Desktop那么拿来就能用,它只是提供了一种工具让 ...
- 网易云课堂_C++程序设计入门(上)_第3单元:更上一层楼 – 超越C的语法_第3单元作业【3】-在线编程(难度:中;10分)
1 本题要求实现两个重载的swap函数,每个swap函数都可交换3个整数a,b,c的值.将a的值存入b,b的值存入c,c的值存入a, 并且返回三个整数中最大的数的值.例如a,b,c的值为1,2,3,则 ...
- Redis 实践笔记
本文来自:http://www.cnblogs.com/me-sa/archive/2012/03/13/redis-in-action.html 最近在项目中实践了一下Redis,过程中遇到并解决了 ...
- fseek/ftell/rewind/fgetpos/fsetpos函数使用-linux
程序: #include<stdio.h> int main(int argc,char *argv[]) { FILE * stream; fpos_t pos; stream = fo ...
- CSS架构目标
擅长CSS的Web开发人员不仅可以从视觉上复制实物原型,还可以用代码进行完美的呈现.无需使用表格.尽可能少的使用图片.如果你是个名副其实的高手,你可以快速把最新和最伟大的技术应用到你的项目中,比如媒体 ...
- String常用方法总结
字符串的截取: 1. slice(start,end) 返回一个新的字符串,不会改变原来引用值.end省略的时候,截取的是start到字符串结尾.传入start=0或者不传入start,就是复制了整个 ...
- 常用的CSS清除浮动的方法优缺点分析(个人学习笔记)
一.抛一块问题砖(display: block)先看现象: 分析HTML代码结构: <div class="outer"> <div class="di ...