目录

  • 一、测试代码
  • 二、.c 文件与Makefile同级
  • 三、.c文件与Makefile不同级
  • 四、链接静态库

一、测试代码

本文以将main.c add.c common.h三个文件编译成一个可执行文件为例,来讲解Makefile的编写。以下是每个文件的代码(很简单,测试用)

1.main.c

 #include <stdio.h>#include "common.h"                                                                                                                                                                                        int main(){int a = 1;int b = 2;printf("add(%d, %d) = %d\n",a, b, add(a,b));return 0;}

2.add.c

int add(int a, int b)
{return a+b;
}

3.common.h

#ifndef __COMMON_H__
#define __COMMON_H__extern int add(int a, int b);#endif

二、.c 文件与Makefile同级

将.c 文件放在Makefile同级目录,然后单独建一个目录.h头文件,如图。

以下是 Makefile 原文:

 CC = gccTARGET = progOBJS = main.o add.oINCLUDE = -I./include$(TARGET):$(OBJS)$(CC) $(OBJS) -o $(TARGET)   %.o:%.c$(CC) $(INCLUDE) -c $^ -o $@                                                                                                                                                                           .PHONY:cleanclean:rm *.o prog

逐行解释:

  • CC = gcc= 号在Makefile中是声明变量并给变量赋值的意思。这里声明了一个 自定义变量 CC,并用gcc编译器赋值。

  • TARGET = prog:声明Makefile目标文件,也就是这个Makefile最终目标是生成一个叫prog的文件。一般这种最终输出的文件都用TARGET来承载

  • INCLUDE = -I./include :用-I 选项指定自己写的头文件的路径。-I和路径之间有没有空格都行,一般没有空格

  • ** (TARGET):(TARGET):(TARGET):(OBJS) **
    ** $(CC) $(OBJS) -o $(TARGET) **:
    格式

要生成的目标文件:生成目标文件所需要依赖的所有文件编译命令
  • %.o:%.c : %是Makefile的一个通配符。这句话的作用是将所有的.c文件自动编译成同名的.o文件。比如,有了这句话,那么1.c就会自动编译成1.o2.c就会自动编译成2.o

  • INCLUDE应该加在哪里
    程序在预处理时就会把头文件的内容展开,所以在调用 -c 选项 将 .c 文件编译成 .o文件时,就要指定头文件路径,否则会报错,提示找不到头文件路径

  • 通配符的作用

符号 描述
$^ 所有依赖文件的集合,用空格分开,如果其中有重复的依赖文件,则只保留一个。比如依赖文件有三个: 1.c, 2.c, 1.c,那么$^拿到的只有 1.c 和 2.c 两个文件,舍弃了一个1.c
$< 依赖文件中的第一个文件。如果依赖文件是以 “%” 定义的,那么 $< 就是依赖文件的集合。一般不会有重复的依赖文件,所以上面的 Makefile,用 $^ 替换掉 $< 也是可以的
$+ 与 $^ 一样,只是如果有重复的依赖文件,不会舍弃重复的依赖文件
$@ 目标文件的集合

三、.c文件与Makefile不同级

.c 文件放在src目录,.h文件放在include 目录,目录结构如图:

以下是 Makefile 原文:

 CC = gccTARGET = progSOURCE = $(wildcard ./src/*.c)      #获取src目录下所有.c文件OBJS = $(patsubst %.c, %.o, $(SOURCE))INCLUDE = -I./include$(TARGET):$(OBJS)  $(CC) $(OBJS) -o $(TARGET)     #另一种写法: $(CC) -o $(TARGET) $(OBJS)%.o:%.c$(CC) $(INCLUDE) -c $^ -o $@   #另一种写法:  $(CC) $(INCLUDE) -c -o $@ $^                                                                                                                                                                       .PHONY:cleanclean:rm $(OBJS) $(TARGET)

这里只有第3、4行需要注意,相当于用这两行内容可以找到指定目录下的文件

  • 第3行 wilcard是获取src目录下所有的.c文件
  • 第4行patsubst是列出 SOURCE中 .c文件对应的所有 .o 文件

四、链接静态库

在前面的基础上,新建目录lib,创建sub.c

sub.c编译成静态库libsub.a,代码如下:

int sub(int a, int b)
{return a - b;                                                                                                                                                                                          }

编译成静态库的命令

gcc -c sub.c -o sub.o
ar crv libsub.a sub.o
补充: 如果静态库依赖于多个源文件,则依次编译得到.o,然后将所有的.o编译成 .a 静态库。
eg. 要将1.c、2.c、3.c编译成一个静态库,则ar crv libXXX.a  1.o 2.o 3.o

当然,除了用命令编译,也可以写成在lib目录下写一个Makefile,我就是这么做的,如下。(这个Makefile只用于编译静态库)

CC = gcc
TARGET = libsub.a
OBJS = sub.o
$(TARGET):$(OBJS)ar crv $(TARGET) $(OBJS)
%.o:%.c$(CC) -c -o $@ $<
.PHONY:cleanclean:rm *.o $(TARGET)

接下来,就是修改我们最开始的那个Makefile

 CC = gccTARGET = progSOURCE = $(wildcard ./src/*.c) #获取src目录下所有.c文件OBJS = $(patsubst %.c, %.o, $(SOURCE))INCLUDE = -I./includeLIBS = -lsubLIBPATH = -L./lib$(TARGET):$(OBJS)$(CC) $(OBJS) -o $(TARGET)  $(LIBPATH) $(LIBS)%.o : %.c$(CC) $(INCLUDE) -c -o $@ $<                                                                                                                                                                           .PHONY:cleanclean:rm $(OBJS) $(TARGET)

第5、6行,编译时需要用 -L 指定静态库的路径,用 -l 指定静态库。
注意: 链接静态库是编译的最后一步链接做的事情。所以要加在第10行,而且只能加在末尾,如果直接跟在 $(CC)后面,make时会提示找不到静态库里的函数

Makefile 编写教程(由简至难)相关推荐

  1. 简单Makefile编写教程

    Makefile编写 1. make和Makefile的介绍 1.1 make工具 利用make工具可以自动完成编译工作.这些工作包括: 如果仅仅修改了某几个源文件,则只重新编译这几个源文件: 如果某 ...

  2. Linux编写makefile详细教程

    Linux下编写 makefile 详细教程 近期在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到makefile就越看越迷糊,可能是我的理解能不行. 于是goo ...

  3. Makefile经典教程(掌握这些足够)

    http://blog.csdn.net/ruglcc/article/details/7814546 拉轰的专栏 少壮不努力 老大徒伤悲 目录视图 摘要视图 订阅 新版极客头条上线,每天一大波干货  ...

  4. linux下MaKefile编写

    Linux下编写 makefile 详细教程 近期在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到makefile就越看越迷糊,可能是我的理解能不行. 于是goo ...

  5. Makefile经典教程

    支持原创,请移步陈浩大神博客: http://blog.csdn.net/haoel/article/details/2886 makefile很重要 什么是makefile?或许很多Winodws的 ...

  6. Makefile 入门教程

    1.Makefile简介 Makefile 定义了软件开发过程中,项目工程编译链.链接的方法和规则. 由 IDE 自动生成或者开发者手动书写. Unix(MAC OS.Solaris)和Linux(R ...

  7. Billy Belceb病毒编写教程---Win32篇

    正在处理中,请稍后-- Billy Belceb病毒编写教程---Win32篇                                      翻译:onlyu                ...

  8. [翻译]Billy Belceb 病毒编写教程for Win32

    Billy Belceb病毒编写教程---Win32篇                                      翻译:onlyu                            ...

  9. Linux下的makefile编写 ——陈皓《跟我一起写Makefile》学习笔记(一)

    Linux下的makefile编写 前言 本人记笔记习惯使用OneNote,在学习LinuxC++过程中发现deepin上没有大佬开发或者移植,本人技术也不精,所以决定写博客记笔记(只是习惯问题,并没 ...

  10. Linux下Makefile编写语法

    原创 Linux下Makefile编写语法 2016-07-29 08:31:53 Datrilla 阅读数 1386更多 分类专栏: Linux Makefile 版权声明:本文为博主原创文章,遵循 ...

最新文章

  1. aspx文件、aspx.cs文件、aspx.designer.cs文件之讲解
  2. 后量子密码芯片研究取得重大突破,论文入选ISSCC 2022和CHES 2022
  3. Oracle数据库中调用Java类开发存储过程、函数的方法
  4. ubuntu中的fi语法_Shell脚本语法--if/then/elif/else/fi
  5. Redis 为什么这么快
  6. ssl2331OJ1373-鱼塘钓鱼 之3【dp】
  7. leetcode1438. 绝对差不超过限制的最长连续子数组
  8. java49_java培训 java49条基础知识
  9. 填写数独 洛谷P1784
  10. 【PAT乙】1064 朋友数 (20分) set用法
  11. 基于物品的协同过滤算法实现图书推荐系统
  12. 408计算机考试科目英语数学,关于计算机考研408的那些事儿
  13. 从高排到低变成小楼梯儿歌_新学期50首幼儿园常规儿歌,收藏了就能用上!
  14. 强化学习读书笔记(一)
  15. 逻辑回归实例,特征预处理
  16. 微光集市-JWT和Token在本项目中的应用(版本5.0)
  17. Ubuntu 21.04(arm64) 基于sanp安装Nextcloud,挂载本地硬盘
  18. c++语言中string类型,c++string类型占几个字节
  19. editplus中文乱码问题解决
  20. Python自动化开发【1】:Python简介和入门

热门文章

  1. 机器学习基石 作业二
  2. 北京市内可以攀登的八座山
  3. JavaScript入门基础
  4. VS2018+TensorFlow安装
  5. 原生Ajax实现formdata
  6. qqkey获取原理_HIT我守护的一切手游电脑版苹果版有吗 HIT我守护的一切iOS电脑版模拟器...
  7. Docker基础教程
  8. java语法有哪些_java编程基础语法都有哪些
  9. python 更新pip镜像源
  10. 裴礼文数学分析中的典型问题与方法第2章一元函数的连续性练习