Makefile这玩意在上学时就应该学,可是一直沉浸于IDE的诱惑,所谓“死于安乐”,直到现在一把年纪才开始接触这种基础东西。

创建C程序

先写个c程序,保存在main.c里:

view plain
  1. //
  2. // file: main.c
  3. //
  4. #include <stdio.h>
  5. int main()
  6. {
  7. int c = 0;
  8. printf("Tommy: %d\n", c+5);
  9. return 0;
  10. }

看看我这时的目录结构

view plain
  1. ~/code/makefile$ ls
  2. main.c

这时敲个“make”命令试试?

view plain
  1. ~/code/makefile$ make
  2. make: *** 没有指明目标并且找不到 makefile。 停止。

创建makefile文件

显然,我们要建个名为“makefile”的文件。先建一个空的名为makefile的文件:

view plain
  1. ~/code/makefile$ touch makefile
  2. tommy@tommy-zheng-ThinkPad-T61:~/code/makefile$ ls
  3. main.c  makefile

这时再试试“make”命令:

view plain
  1. ~/code/makefile$ make
  2. make: *** 无目标。 停止。

加入target
错误“无目标”告诉我们需要在makefile里添加一些东西:

view plain
  1. # 注释 file: makefile
  2. target:

再执行“make”命令:

view plain
  1. ~/code/makefile$ make
  2. make: 没有什么可以做的为 `target'。

可以看到前面“无目标”的错误已经解决了。

加入命令

继续往makefile里添加东西:

view plain
  1. # 注释 file: makefile
  2. target:
  3. gcc -o tommy main.c # 注意,最前面是tab,不是空格!

好了,执行make命令:

view plain
  1. ~/code/makefile$ make
  2. gcc -o tommy main.c
  3. ~/code/makefile$ ls
  4. main.c  makefile  tommy

main.c被编译了,一个可执行文件“tommy”产生了。我们执行一下试试:

view plain
  1. ~/code/makefile$ ./tommy
  2. Tommy: 5

我们的makefile写完了!!!

好吧,之前的makefile实在是太简单,以至于没什么实际的用途。现在再深入研究下。

Target
在前面的makefile里,有一个叫"target"的东西。其实它可以是任何名字,而且一个makefile里可以有多个target。比如下面的makefile:

view plain
  1. # 注释 file: makefile
  2. tommy:
  3. gcc -o tommy main.c # 注意,最前面是tab,不是空格!
  4. dosomething:
  5. echo just for fun.

给make命令一个参数:

view plain
  1. ~/code/makefile$ make dosomething
  2. echo just for fun.
  3. just for fun.

可以看到,make可以用来执行任何一个target底下的命令,而这种命令并不局限于gcc这种编译的命令。每个target用冒号隔开。如果make命令没有指定哪个target,那第一个target下的命令会被执行。

Dependencies

make命令一次只能处理一个target,但如果我想一次处理多个target怎么办?这时可以为一个target在冒号后面指定它所依赖的target。修改下makefile:

view plain
  1. # 注释 file: makefile
  2. tommy:
  3. gcc -o tommy main.c # 注意,最前面是tab,不是空格!
  4. dosomething: dofirst dosecond # 先执行另两个target的命令
  5. echo just for fun.
  6. dofirst:
  7. echo first.
  8. dosecond:
  9. echo second.
  10. donothing:
  11. echo nothing.

make一下看看:

view plain
  1. ~/code/makefile$ make dosomething
  2. echo first.
  3. first.
  4. echo second.
  5. second.
  6. echo just for fun.
  7. just for fun.

可以看到,dofirst和dosecond在dosomething之前都被make了,但tommy和donothing都没有执行。

编译多个C文件

现在增加两个文件f.h和f.c,同时改一下main.c:

view plain
  1. // file: f.h
  2. int add(int, int);
  3. // file: f.c
  4. int add(int a, int b)
  5. {
  6. return a + b;
  7. }
  8. //
  9. // file: main.c
  10. //
  11. #include <stdio.h>
  12. #include "f.h"
  13. int main()
  14. {
  15. printf("Tommy-add: %d\n", add(2, 4));
  16. return 0;
  17. }

看看我的目录结构:

view plain
  1. ~/code/makefile$ ls
  2. f.c  f.h  main.c  makefile

基于前面的“Dependencies”得到的结论,我们可以改写makefile,来让main函数调用f函数:

view plain
  1. # file: makefile
  2. tommy: main.o f.o
  3. gcc -o tommy main.o f.o
  4. main.o:
  5. gcc -c main.c -o main.o
  6. f.o:
  7. gcc -c f.c -o f.o

看下生成的结果:

view plain
  1. ~/code/makefile$ make
  2. gcc -c main.c -o main.o
  3. gcc -c f.c -o f.o
  4. gcc -o tommy main.o f.o
  5. ~/code/makefile$ ls
  6. f.c  f.h  f.o  main.c  main.o  makefile  tommy
  7. ~/code/makefile$ ./tommy
  8. Tommy-add: 6

可以看到我们的生成了我们想要的东西。

clean与install
经常可以看到“make clean”和“make install”的命令。我们也可以提供它们:

view plain
  1. # file: makefile
  2. tommy: main.o f.o
  3. gcc -o tommy main.o f.o
  4. main.o:
  5. gcc -c main.c -o main.o
  6. f.o:
  7. gcc -c f.c -o f.o
  8. clean:
  9. rm *.o
  10. install:
  11. mv tommy /usr/local

最后再研究下makefile里的宏。其实就是定义一个变量,之后再使用它:

view plain
  1. # file: makefile
  2. INSTALL_PATH = /usr/local
  3. TEMP_FILES = *.o
  4. tommy: main.o f.o
  5. gcc -o tommy \
  6. main.o f.o # 这里演示反斜杠用于换行,注意反斜杠后没有空格,行首是tab而非空格
  7. main.o:
  8. gcc -c main.c -o main.o
  9. f.o:
  10. gcc -c f.c -o f.o
  11. clean:
  12. rm $(TEMP_FILES)
  13. install:
  14. mv tommy $(INSTALL_PATH)

转载于:https://www.cnblogs.com/zhanglanyun/archive/2011/10/20/2218834.html

makefile从无到有相关推荐

  1. Makefile:GCC CFLAGS变量和LDFLAGS变量

    LOCAL_CFLAGS参数说明 其实 CFLAGS += -D__MT2625_ENABLED__ 这个CFLAGS是gcc编译的选项,在makefile中用CFLAGS这个变量来表示这个编译选项. ...

  2. Makefile 编译与链接选项及CFLAGS与LDFLAGS示例说明

    GCC编译选项CFLAGS参数 GCC链接选项LDFLAGS参数 实例 最近看了makefile的手册之后,发现还是不知道怎么写makefile,而且就连看也看的是云里雾里,就我现在工作当中看到的一些 ...

  3. 浅显易懂 Makefile 入门 (12)— Makefile 常见的错误信息

    1. 常见的错误信息 make 执行过程中所产生错误并不都是致命的,特别是在命令行之前存在 -.或者 make 使用 -k 选项执行时. make 执行过程的致命错误都带有前缀字符串 ***.错误信息 ...

  4. 浅显易懂 Makefile 入门 (10)— 嵌套执行 make、export 的使用

    1. 嵌套执行 make 在一个大的工程文件中,不同的文件按照功能被划分到不同的模块中,每个模块可能都会有自己的编译顺序和规则,如果在一个 Makefile 文件中描述所有模块的编译规则,就会很乱,执 ...

  5. 浅显易懂 Makefile 入门 (09)— include 文件包含、MAKECMDGOALS

    1. include文件包含 当 make 读取到 include 关键字的时候,会暂停读取当前的 Makefile,而是去读 include 包含的文件,读取结束后再继读取当前的 Makefile ...

  6. 浅显易懂 Makefile 入门 (08)— 默认 shell (/bin/sh)、命令回显、make参数(-n 只显示命令但不执行,-s 禁止所有回显)、单行命令、多行命令、并发执行

    1. shell 相关 1.1 默认 shell Makefile 所使用的命令是由 shell 命令行组成,他们是一条一条执行的. 多个命令之间要使用分号隔开,Makefile 中的任何命令都要以 ...

  7. 浅显易懂 Makefile 入门 (07)— 其它函数(foreach 、if、call、origin )

    1. foreach 函数 foreach 函数定义如下: $(foreach <var>,<list>,<text>) 函数的功能是:把参数 <list&g ...

  8. 浅显易懂 Makefile 入门 (06)— 文件名操作函数(dir、notdir、suffix、basename、addsuffix、addperfix、join、wildcard)

    编写 Makefile 的时候,很多情况下需要对文件名进行操作.例如获取文件的路径,去除文件的路径,取出文件前缀或后缀等等. 注意:下面的每个函数的参数字符串都会被当作或是一个系列的文件名来看待. 1 ...

  9. 浅显易懂 Makefile 入门 (03)— 目标文件搜索(VPATH 和 vpath 的区别和使用)、隐含规则

    1. 目标文件搜索(VPATH和vpath) 如果需要的文件是存在于不同的路径下(即源文件与 Makefile 文件不在同一个路径下),在编译的时候就用到了 Makefile 中为我们提供的目录搜索文 ...

最新文章

  1. tensorflow中的向量范数
  2. 清除应用数据后,应用对应的widget的数据无法刷新
  3. 移远NB-IOT模块的BC28与M26与BC26对比
  4. Android java.lang.UnsatisfiedLinkError
  5. Xcode全局替换内容,一键Replace
  6. struts2教程(9)--OGNL表达式使用
  7. 40行代码AC_HDU 1575 TrA 矩阵快速幂(附快速幂+矩阵快速幂的讲解)
  8. 操作系统原理之文件系统(第五章)
  9. 【英语学习】【Level 07】U06 First Time L1 My very first trip
  10. 中消协:视频平台不应向VIP老会员收取超前点播费
  11. 使用Unity开发RPG游戏完整指南(全)
  12. logback.xml 配置总结
  13. android源码下编译自有工程通用make模板
  14. NB-IoT移远BC95使用小结
  15. 基恩士扫码枪SR2000系列通讯
  16. springboot微信点餐系统的设计与实现 毕业设计-附源码221541
  17. 安卓音视频开发!为了跳槽强刷1000道Android真题,大厂直通车!
  18. 将uiimageview设置成纯圆形
  19. Word文档中,文字下面的波浪线怎么去掉
  20. NXP PN53x系列芯片介绍

热门文章

  1. 经验原石_经验分享:挑战翡翠原石,新手实战前应做哪些准备
  2. OpenCV之鼠标操作
  3. 保险科技服务商豆包网完成9500万新一轮融资,博将资本领投
  4. Hadoop之MapReduce理论篇01
  5. 深度学习框架中的魔鬼:探究人工智能系统中的安全问题
  6. laravel 模型事件几种用法
  7. Oracle中函数/过程返回结果集的几种方式
  8. xmldocument的使用
  9. ios 对日期的处理(包括计算昨天时间、明天时间)
  10. eclipse部署web没部署成功的问题