Makefile笔记整理
  1. 什么是Makefile?
    makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
  2. make的作用?
    Makefile制定的规则,由make工具来执行,make就是工程管理工具:帮助我们实现项目的自动编译
  3. Makefile的规则
    粗略地Makefile的规则:
    Target…:prerequisites…
    [TAB]command
    target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label).
    prerequisites就是,要生成那个target所需要的文件或是目标。
    command也就是make需要执行的命令
    #其中第一条规则中的目标,将会成为终极目标,其他目标是为终极目标服务的,因为最终目的,就是为了生成这个目标.
    #其他规则之间,没有必然顺序联系
    4,Makefile的命名?
  4. 默认的情况下,make命令会在当前文件夹下按顺序找寻文件名称为“GNUmakefile”、“makefile”、“Makefile”的文件,找到了解释这个文件。在这三个文件名称中,最好使用 “Makefile”这个文件名称,由于,这个文件名称第一个字符为大写,这样有一种显目的感 觉。最好不要用“GNUmakefile”,这个文件是GNU的make识别的。有另外一些make仅仅对全小写的“makefile”文件名称敏感,可是基本上来说,大多数的make都支持“makefile”和“Makefile”这两种默认文件名称
  5. 当想要自己指定makefile文件名时候,例如my_mkfile 执行命令make -f my_mkfile
  6. Makefile中赋值方式
    =  延时变量,只有被使用时才展开定义 也就是说,变量的值将会是整个makefile中最后被指定的值,如:x=fool,y=(x)bar,x=xyz,这个例子中,y的最终值是xyzbar,而不是foolbar:=立即变量,定义时的赋值立即有效变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值,如x=fool,y=(x)bar,x=xyz,这个例子中,y的最终值是xyzbar,而不是foolbar := 立即变量,定义时的赋值立即有效 变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值,如x = fool,y=(x)bar,x=xyz,这个例子中,y的最终值是xyzbar,而不是foolbar:= 立即变量,定义时的赋值立即有效变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值,如x=fool,y=(x)bar,x := xyz,y的最终值是foolbar
    ?= 条件变量,当变量为空时才赋值
    += 追加赋值,类似字符串string
  7. 引用一个实例讲解接下来的知识点
    1.print.h
    #include<stdio.h>
    Void printhello();
  8. print.c
    #include”print.h”
    Void printhello()
    {
    Printf(“hello,world”);
    }
  9. main.c
    #include”print.h”
    Int main()
    {
    Printhello();
    return 0;
    }
    编译这个程序:gcc main.c print.c
    如果是大工程,这样就会很繁琐
    6.最简单的Makefile
    Helloworld:main.c print.c
    gcc -o helloworld main.c print.c
    有一个问题就是,假如我们更改了main.c 或者print.c其中一个文件,重新make的时候会导致所有的文件跟着一起更新,如果是大工程,就会耗费系统资源和时间,对于这些源文件,我们应该分别处理,执行:预处理 编译 汇编 ,先分别编译它们,最后再把它们链接在一起
    7.引入.o文件
    Helloworld:main.o print.o
    gcc –o main.o print.o
    main.o:main.c
    gcc –c main.c
    print.c:print.o
    gcc –c print.c
    8,引入标签clean
    每个Makefile中都应该写一个清空目标文件(.o和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。这是一个“修养”。
    clean的规则不要放在文件的开头,不然,这就会变成make的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean从来都是放在文件的最后”。
    Helloworld:main.o print.o
    gcc –o main.o print.o
    main.o:main.c
    gcc –c main.c
    print.c:print.o
    gcc –c print.c
    clean:
    rm –rf main.o print.o helloworld
    9.引入伪目标
    执行make的时候会将clean误认为是目标文件,所以如果在同目录下有clean文件,makeclean就不会执行成功,所以指定一下clean标签
    Helloworld:main.o print.o
    gcc –o main.o print.o
    main.o:main.c
    gcc –c main.c
    print.c:print.o
    gcc –c print.c
    .PHONY:clean
    clean:
    rm –rf main.o print.o helloworld
    好了,一个成型的makefile到此完成
    10,引入变量
    变量名字可以包含字符、数字(可以用在开头)、下划线,但不可以是: # = 或空字符。 变量是大小写敏感的。
    如果源文件过多,我们每次添加或删除一个不必要的源文件可能或造成不必要的纰漏
    Object = main.o print.o
    Target = helloworld
    (Target):(Target):(Target):(Object)
    gcc –o helloworld main.o print.o
    main.o:main.c
    gcc –c main.c
    print.c:main.c
    gcc –c print.c
    .PHONY:clean
    Clean:
    rm –f $(Target) $(Object)
    11,引入特殊变量
    $@:当前规则中的目标
    $$:当前执行的进程编号
    $^:当前规则中的所有依赖
    $*:模式规则中的所有%匹配的部分
    $<:当前依赖中的第一个
    $?:模式规则中所有比所在规则中的目标更新的文件组成列表
    Object = main.o print.o
    Target = helloworld
    (Target):(Target):(Target):(Object)
    gcc $^ –o $@
    main.o:main.c
    gcc –c $<
    print.c:main.c
    gcc –c $<
    .PHONY:clean
    Clean:
    rm –f $(Target) $(Object)
    12,引入通配符
    这样的Makefile还不算完善,因为我们每假如新的文件都要去修改Makefile,如果一下子加1000个.c文件就会很是繁琐
    *:表示所有文件的前缀
    %:%为Makefile规则通配符,一般用于规则描述
    -:发生错误时继续执行
    @使命令在被执行前不被回显。比如我们不想c语言中的printf被打印出来吧
    Object = *.o
    Target = helloworld
    (Target):(Target):(Target):(Object)
    @echo start -----
    gcc $^ –o $@
    @echo end
    %.c:%.o
    gcc –c $<

.PHONY:clean
Clean:
-rm –f $(Target) $(Object)
13,引入函数
Wildcard:获取工作目录下的所有.c文件
Notdir:去除所有的目录信息,src = $(notdir wildcarcd),src中文件名列表将只有文件名
Patsubst:src = (patsubst(patsubst%.c ,%.o ,(patsubst(SRC)),意思是找到所有的.c结尾文件然后替换成.o
SRC = $(wildcard *.c)
File = $(notdir $(SRC))
Object = (patsubst(patsubst %c,%.o,(patsubst(File))
Target = helloworld
(Target):(Target):(Target):(object)
Gcc $^ -o $@
%.o:%.c
Gcc –c $<
.PHONY:clean
Clean:
-rm $(Target) $(object)
14,隐含规则
make会按照这种“惯例”心照不喧地来运行,那怕我们的Makefile中没有书写这样的规则。例如,把[.c]文件编译成[.o]文件这一规则,你根本就不用写出来,make会自动推导出这种规则,并生成我们需要的[.o]文件。
SRC = $(wildcard *.c)
File = $(notdir $(SRC))
Object = (patsubst(patsubst %c,%.o,(patsubst(File))
Target = helloworld
(Target):(Target):(Target):(object)
Gcc $^ -o $@
.PHONY:clean
Clean:
-rm $(Target) $(object)

可以使用make -p 打印出make的所有隐含规则
15.引入.d文件
在一个工程中,因为头文件被源文件所包含,所以头文件的更新应该使得它所依赖的文件也被更新,
使用gcc -MM可以查看到源文件生成对应的.o文件需要依赖那些文件

于是我们在Makefile中引入.d文件,其实文件名称是自己定义,无所谓
%.d:%.c
gcc -MM $< > $@
我们将依赖关系重定向到.d文件中,这样就可以实现改变头文件会导致所依赖的源文件重新编译

16,多目录Makefile
一般管理代码会将代码放入不同目录下进行管理,方便维护
文件存放说明:
bin: 存放编译生成的二进制文件
src: 存放源文件 (add.c multis.c sub.c main.c)
obj: 存放编译生成的目标文件
include: 存放头文件 (add.h multis.h sub.h)
Makefile 文件和 bin、src、include处于同一级目录
Makefile的写法
CUR_DIR = $(shell pwd)
INC_DIR = $(CUR_DIR)/include
BIN_DIR = $(CUR_DIR)/bin
SRC_DIR = $(CUR_DIR)/src
OBJ_DIR = $(CUR_DIR)/obj
SRC = $(wildcard $(SRC_DIR)/*.c)
OBJ = (patsubst(patsubst %.c,(patsubst(OBJ_DIR)/%.o,$(notdir $(SRC)))
TARGET = main
BIN_TARGET = (BINDIR)/(BIN_DIR)/(BIND​IR)/(TARGET)
CC = gcc
CFLAGS = -g –Wall –I(INC_DIR)
(BINTARGET):(BIN_TARGET):(BINT​ARGET):(OBJ)
$(CC) $(OBJ) –o $@
@echo “Compile done”
(OBJDIR)/(OBJ_DIR)/%.o:(OBJD​IR)/(SRC_DIR)/%.c
@echo “Compiling $< ==>”
$(CC) $(CFLAGS) –c $< -o $@
.PHONY:clean
Clean:
@rm –f $(OBJ)
@echo “clean object files done”
@rm –f *~
@echo “clean tempreator files done”
@rm –f $(TARGET)
@echo “Clean target files done”
@echo “Clean done”

注释:
CFLAGS:指定头文件路径
LIBS:告诉连接器要链接那些库文件
LDFLAGS:gcc等编译器会用到的一些优化参数也可以在里面指定库文件的位置
Export:导出变量将被子make继承,有点类似C语言中的全局变量
CROSS_COMPILE:指的是交叉编译器(或前缀),这里是arm-linux(-gcc)。可以在Makefile中指定,也可以在
make clean仅仅是清除之前编译的可执行文件及配置文件。

make distclean要清除所有生成的文件
CXXFLAGS用于C++代码
AR:归档文件
AS:汇编器
LD:连接器

obj-y += foo.o 该例子告诉Kbuild在这目录里,有一个名为foo.o的目标文件。foo.o将从foo.c 或foo.S文件编译得到
"obj-y += subdir/"表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。
strip 去掉字符串中多余的空格符(若干单词,使用若干空字符分割) “STR”开头和结尾的空字符,并将其中多个连续空字符合并为一个空字符。
arm-linux-objcopy 复制选项,支持格式转换
arm-linux-objdump 反编译选项
o 编译及链接,会生成一个exe可执行文件
-Wall 指定产生全部的警告信息
-O/-O2/-O3 数字越高,代表优化的更多,可以使生成的执行文件的提高执行效率
-c 编译不链接,会生成一个*.obj文件,若后面加了-o,则表示指定输出文件名称
-static 静态链接,生成的文件会非常大, 好处在于不需要动态链接库,也可以运行
-S 只激活预处理和编译,就是指把文件编译成为汇编代码
-g选项是指可以用gdb调试

如何写好Makefile相关推荐

  1. java makefile jar包_java makefile学习实践(编译的javac命令写在makefile中,运行命令java写在shell脚本中)...

    学习makefile教程,ubuntu中文网 1.写一个简单的java项目,不需要外部jar,用的简单的 importjava.util.ArrayList;是可以从CLASSPATH环境变量中找到的 ...

  2. 从头開始写项目Makefile(三):变量的使用

    [版权声明:转载请保留出处:blog.csdn.net/gentleliu. Mail:shallnew at 163 dot com] 细致研究我们的之前Makefile发现.我们还有改进的地方.就 ...

  3. 跟我一起写 Makefile(整理版)

                      跟我一起写 Makefile                     作者:陈皓           (博客地址:http://blog.csdn.net/haoe ...

  4. (转)跟我一起写 Makefile(一)(陈皓)

    本问转载自陈皓大神的跟我一起写 Makefile(一) 概述 -- 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要 ...

  5. 跟我一起写 Makefile(六)

    书写命令 ---- 每条规则中的命令和操作系统Shell的命令行是一致的.make会一按顺序一条一条的执行命令,每条命令的开头必须以[Tab]键开头,除非,命令是紧跟在依赖规则后面的分号后的.在命令行 ...

  6. 跟我一起写 Makefile(一)【转】

    转自:http://blog.csdn.net/haoel/article/details/2886 跟我一起写 Makefile 陈皓 概述 -- 什么是makefile?或许很多Winodws的程 ...

  7. linux 8051 编译,[编译] 3、在Linux下搭建51单片机的开发烧写环境(makefile版)

    星期二, 10. 七月 2018 01:01上午 - beautifulzzzz 一.SDCC(Small Device C Compiler)编译环境搭建 SDCC是一个小型设备的C语言编译器,该编 ...

  8. 跟我一起写makefile: 概述、介绍、规则

    跟我一起写makefile 概述.介绍.规则 转自:https://seisman.github.io/how-to-write-makefile/rules.html 概述 什么是makefile? ...

  9. 教你写Makefile

    转载文 Makefile 值得一提的是,在Makefile中的命令,必须要以[Tab]键开始. 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都 ...

最新文章

  1. nginx 同一个IP上配置多个HTTPS主机
  2. open ssl里面的自定义get***函数失效
  3. strcpy和strcat
  4. 阿里人工智能实验室招聘计算机视觉算法专家-交互图像方向
  5. 持续交付 devops_使用DevOps开始加速软件交付
  6. python正则表达式匹配模式屠夫之桥_小甲鱼零基础入门Python学习视频+全套源码课件 Python视频教程 96讲...
  7. 前端 常用css总结
  8. new blob文件设置编码_前端下载文件amp;下载进度
  9. 在线CSV转XML工具
  10. 同时生成 Release版和Debug版DLL的方法
  11. Curl 下载安装和配置
  12. EXCEL startup.exe 宏病毒
  13. 14.Yum详解,yum安装,查找,info,反向查找,组,依赖,缓存等所有操作
  14. 损耗的基础知识(中)
  15. Python机器学习13——主成分分析
  16. Redis 大键值对 Big Key 懒惰删除机制
  17. Unity幸运转盘项目实战
  18. 利用SUMO模拟事故
  19. 阿里云产品经理刘宇:Serverless 的前世今生
  20. 用EASYGUI 实现msgbox。

热门文章

  1. 智慧城市交通的要素:路口监管可视化系统的解决方案
  2. 未转变者服务器买车指令,未转变者服务器指令大全
  3. mysql 格式化时间 年月日时分秒与年月日字符串作比较
  4. PLC快速联网,实现设备远程监测管理
  5. 华为OD入职一年介绍和建议
  6. 2023暑期实习历程总结
  7. 母亲节,献给母亲的沙画(太感人了!)
  8. coreldraw软件完整最新版2022矢量图形设计软件
  9. K歌之王 阴天快乐 陈奕迅
  10. 手把手教你玩转Vue