当我们写程序过程中存在多个文件之间有复杂的包含关系时,若修改了其中一个源文件,就重新编译所有文件,一般是不必要的,并且当文件很多时,就显得非常笨拙。所有包含该文件的文件需要重新编译,而其它无关系的文件则不需要编译,但往往判断的这个过程会很令程序员头疼,并且一不小心就会出现某些需要重新编译的文件被遗漏的情况,这样就会使程序无法正常工作。

make就可以解决上述问题,它会在必要时编译所有受改动影响的源文件。

但是make自身是不能完成这项任务的,我们需要为其提供一个文件,告诉它如何去处理文件之间的关系,这个文件就是makefile文件。

就是在makefile文件中按照一定的格式把要生成的文件在编译时所需要的源文件以及编译规则写出来。这样,make会根据makefile文件按照规则在需要时重新编译所有受改动影响的源文件。可以同时存在多个不同的makefile文件分别管理项目的不同部分。makefile文件一般和其它源文件放在同一目录下。

make -f  makefile文件名

-f 选项就是指定将哪个文件作为makefile文件。如果没有使用-f选项,标准版本make命令将首先在当前目录下找名字为makefile的文件,找不到会继续查找Makefile的文件。(特殊的GNU Make则会按照GNUmakefile、makefile、Makefile的顺序搜索)

makefile文件由一组依赖关系和规则构成。完整的makefile文件例子会在后面列出。

makefile中的每个依赖关系由 一个目标文件(一般为要创建的可执行文件)和一组该目标所依赖的源文件组成。

makefile文件依赖关系的写法()如下:

mypro:  main.o  myc1.o

main.o:  main.c  a.h  b.h

myc1.o:  myc1.c  b.h

mypro1:  mypro1.c

最开始是目标文件名称,然后一个冒号,后面是目标文件所依赖的源文件(冒号和后面的源文件之间以及不同源文件之间用空格或制表符间隔)

特别需要注意的是,虽然makefile文件中已经写入了多个目标文件,但是如果只是这样执行 make 则make命令只会创建makefile文件中的第一个目标,即mypro

若要一次性创建makefile中的所有文件,需要在makefile文件的第一个目标定义为all(我们称之为伪目标),即:

all:  mypro  mypro1

mypro:  main.o  myc1.o

main.o:  main.c  a.h  b.h

myc1.o:  myc1.c  b.h

mypro1:  mypro1.c

或者执行make命令时,加上all参数 :  make  all

makefile文件的规则:

规则就是指当make创建目标文件时的方式,比如在编译myc1.o文件时,如何进行编译(如可能需要指定头文件的目录等)。

在此应特别注意:makefile文件中的 空格 和 制表符 是有区别的。规则所在的行必须以 制表符 开头,不可以用空格。并且makefile文件中不能以空格结尾,可能会使make命令执行失败(这属于历史遗留问题)

另外,makefile文件中可以使用宏定义。

下面举例完整的makefile文件:

定义一个命名为Makefile123的makefile文件

#cat Makefile123

all: mypro

#This is a makefile

#the compiler

CC = gcc

#the path

INCLUDE = .

#where to install

INSTDIR = /usr/local/bin

install: mypro

@if [ -d $(INSTDIR) ]; \

then \

cp mypro $(INSTDIR) &&\

chmod a+x $(INSTDIR)/mypro &&\

chmod og-w $(INSTDIR)/mypro &&\

echo "Installed in $(INSTDIR)" ;\

else \

echo "Sorry, $(INSTDIR) does not exist" ; \

fi

mypro: main.o c1.o

gcc -o mypro main.o a.o

main.o: main.c m.h

$(CC) -I$(INCLUDE) -c main.c

c1.o: c1.c

$(CC) -c c1.c

clean:

-rm main.o c1.o

1、make中的特殊符号:

•告诉make命令忽略所有错误

@  告诉make执行某条命令前不要将该条命令显示在准输出上

#  是makefile中的注释符号

CC = gcc 以及 INCLUDE = . 和INSTDIR = /usr/local/bin 是makefile中自行建立的的宏定义,引用方式为$(CC)、$(INCLUDE)和$(INSTDIR)

2、注意all只指定了一个目标mypro,所以只执行 make -f Makefile123时,则默认只创建目标mypro

我们可以看到在Makefile123文件中存在两个目标clean 和 install。

install依赖于mypro ,执行make -f Makefile123 install时,make会自行判断创建文件的正确顺序

该文件中目标install的规则由一串shell脚本命令组成,此处注意,make命令在执行规则时会调用一个shell,并且每个规则都使用一个新的shell,所以在代码结尾加上反斜杠\,使得所有shell脚本命令在逻辑上处于一行。 &&符号保证保证前面的命令执行成功后面的才会继续执行。

clean目标后面没有依赖文件,则执行 make -f Makefile123 clean时,clean对应的规则总会执行,而不是像其他目标一样只有在依赖文件发生变化时执行规则。

linux下makefile中cp,make与makefile 的理解相关推荐

  1. Linux下 QT中 log4cplus 最基本配置及使用

    Linux下 QT中 log4cplus 最基本配置及使用 鉴于网上很多使用方法不是很详细,对小白不友好,并且以此作为记录,方便下次配置. 本文是基于我自己下载的版本写的,请各位根据自己下载的版本更改 ...

  2. linux cp mv区别,浅谈Linux下mv和cp命令的区别

    1.功能上的区别 mv:用户可以使用该命令为文件或目录重命名或将文件由一个目录移入另一个目录中. cp: 该命令的功能是将给出的文件或目录拷贝到另一文件或目录中. 2.从inode角度来区分 mv:会 ...

  3. Linux下C++中可使用的3种Hook方法

    Hook即钩子,截获API调用的技术,是将执行流程重定向到你自己的代码,类似于hack.如使程序运行时调用你自己实现的malloc函数代替调用系统库中的malloc函数.这里介绍下Linux下C++中 ...

  4. linux 设备数 of,linux下devicetree中惯用的of函数

    linux下devicetree中常用的of函数 从device_node中获取信息: int of_property_read_u8_array(const struct device_node * ...

  5. [转] linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决,Linux使用退格键时出现^H解决方法

    [转] linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决,Linux使用退格键时出现^H解决方法 参考文章: (1)[转] linux下shell ...

  6. linux中命令对c文件进行编译,Linux下C语言编译基础及makefile的编写

    这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将会学到以下内容: 源程序编译 Makefile的编写 程序库的链接 程序的调试 头文件和系统求助 1.源程序的编译 在L ...

  7. Linux中设置tab4个空格,linux下vim中tab设置为4个空格例子

    在大多数的文件中使用4个空格的tab,在Makefile中使用真正8个宽度的tab, 同事基于文件的类型自动缩进. 编辑 vim ~/.vimrc 如文件不存在新建,文件已存在,追加在尾部 添加 &q ...

  8. linux 下URL中 UTF-8编码、GB2312编码与汉字之间的转换

    下面是UTF-8编码的转换代码 #include <string.h> #include <stdio.h> #include <stdlib.h>/* 16进制字 ...

  9. Linux 下mv和cp命令

    注意事项:mv与cp的结果不同,mv好像文件"搬家",文件个数并未增加.而cp对文件进行复制,文件个数增加了. 一.cp命令 cp命令用来将一个或多个源文件或者目录复制到指定的目的 ...

最新文章

  1. refreshcontrol 实现下拉刷新的功能
  2. php智能客服,智能客服系统
  3. 特使招募-航天三院-智能车竞赛
  4. 函数指针和函数指针数组及其应用
  5. 在哪个瞬间你感觉自己是一个产品经理?
  6. oracle12c导11g,Oracle12c的数据库如何向11g导入
  7. linux系统如何启用ftp服务
  8. char,nchar,varchar与nvarchar区别
  9. 深度学习之于传统计算机视觉
  10. 把复杂变简单,能产生颠覆的力量
  11. sublime跳转到函数定义
  12. IDEA常用快捷键汇总
  13. 奔跑的小人,在屏幕上从左向右移动”的代码实现“小人在屏幕上从右向左移动” 按下键“A”,小人向左移动;按下键“D”,小人向右移动; 按下键“W”,小人向上移动;按下键“X”,小人向下移动; 通过主函数
  14. 获取并处理中文维基百科语料
  15. android即时通讯ui框架,android IM即时通信之聊天界面UI框架
  16. Can't locate Time/HiRes.pm in @INC错误的处理方法 perl安装不全
  17. OpenGL学习笔记:矩阵变换
  18. Qt组件-QLabel
  19. QUIC 协议的简单分析
  20. java中日志的级别说明

热门文章

  1. 属性类:Properties
  2. Hash(LCP) || 后缀数组 LA 4513 Stammering Aliens
  3. Atom与markdown
  4. 企业生产场景如何对CentOS进行分区
  5. Java中利用MessageFormat对象实现类似C# string.Format方法格式化
  6. Netty实现原理浅析
  7. ARP防治攻略————服务器防护
  8. 玩转带外触发的单目相机之一
  9. 简单论述市场营销管理的基本过程
  10. C语言中的静态函数的作用