C语言make和Makefile介绍及使用

1:make和Makefile的介绍:

概念

在软件的工程中的源文件是不计其数的,其按照类型,功能,模块分别放在若干个目录中,哪些文件需要编译,那些文件需要后编译,那些文件需要重新编译,甚至进行 更复杂的功能操作,这就引入了我们的系统编译的工具:

在linux和unix中,有一个强大的使用程序,叫make,可以用它来管理多模块程序的编译和链接,直至生成可执行文件

make使用程序读取一个说明文件,称为Makefile,Makefile文件中描述了整个软件工程的 编译规则和各个文件之间的依赖关系;

Makefile就像是一个Shell脚本一样,其中可以执行操作系统的命令,它带来的好处就是我们能够实现“自动化编译”,一旦写好,只要一个make命令,整个软件功能就完全自动编译,极大的提高了软件开发的效率;

make是一个命令工具,是一个解释Makefile中指令的命令工具,一般来说大多数IDE都有这个命令

使用make可以是重新编译的次数达到最小化;

2:make和Makefile

1:make的使用语法:

make使用语法:
    make [选项][目标][宏定义]
    选项列表:
        -d  显示调试信息(debug)
        -f<文件> 指定从那个文件中读取以来关系,默认文件是"Makefile"或者"makefile","-"表示从标准输入(file)
        -h  显示所有选项的简要说明(help)
        -n 不运行任何Makefile命令,只去现实它们(no)
        -s 安静的方式运行,不显示任何信息(silence)
    可以使用-h来获取更多的选项:

2:Makefile的编写原则和规则

当make命令不带选项运行的时候,它从Makefile中读取指定规则
当制定规则不同与Makefile(makefile)的其他文件中时候,就要运行带有-f选项的make命令。如make.fray.Makefile
make -f make.fray.Makefile

Makefile的编写规则一:

目标列表:关联性列表
<TAB>命令列表

目标列表:是用一个或者多个空格分开的目标文件的清单

关联性列表:同样是一个或者多个空格分开的目标文件,是目标列表所以来的多个目标文件的清单;

命令列表:用于创建目标文件的将要执行的命令清单,这个命令列表被换行符号分开,命令列表中的每个命令必须要以<TAB>字符开始;

如:##Sample
    power:power.c
        gcc -o power power.c

如:#Sample
    power:power.o demo.o
        gcc -o power power.o demo.o
    power.o:power.c
        gcc -o power.o -c power.c
    demo.o:demo.c
        gcc -o demo.o -c demo.c

注意:书写的形式类似于倒推的形式

Makefile的编写规则二:(不建议使用)

目标列表:关联性列表;命令列表
命令列表是一系列被分号隔开的命令,一个很长的命令行要续行的时候需要用一个反斜杠符号
如:all/mymath_test:src/mymath.c src/mymath_test.c; \
gcc -o all/mymath_test src/mymath.c  \
src/mymath_test.c

注意:makefile书写主要注意的是:

  • 1:编译规则
  • 2:依赖关系
  • 3:倒推原理
  • 4:使用make命令去执行
  • 5:如果已经是最新的文件的时候,就不会再去编译执行了
  • 6:make去读取makefile的时候,是按照依赖文件的顺序去查找并且执行命令的
  • 7:make在编译的时候,如果发现被编译的文件已经是最新的了,就不会再去编译(减少了编译次数)
  • 8:make文件是根据被编译文件的时间戳去判断文件是否是当前最新的文件,如果是最新的,那么就会去重新编译,如果不是最新的,就不会去进行编译;
  • 9:千万要注意makefile中编译命令前面的分隔符

Makefile变量的使用

简单变量:
    定义
        变量名字:=[文本]
        这类变量的实质就是一组字符串
    添加
        变量名字+=[文本]或者 变量名字:=[文本][文本]
    引用变量
        $(变量名)
        $单字符变量(指的是但字符的变量 a:=123  $a)

        如:G:=gcc  一般我们都是定义成大写的
            $G -o power power.c

内置变量:
    $@   当前目标的名词
    $?   比当前目标更新的已修改的依赖性列表
    $<   依赖性列表的第一个文件
    $^   用空格分开的所有依赖性列表

虚目标

虚目标是不存在的文件
虚目标允许你去强制执行某些事件,但这些事件在正常的规则中是不会发生的
虚目标不是真正的文件,make命令可以使用针对他们的任意规则
    虚目标总是使与之有关的命令被执行

all 生成工程中所有可以执行者,通常是makefile的第一个生成目标
test 运行程序的自动测试套件
clean 删除make all生成的所有文件
install 在系统目录中安装工程项目生成的可执行文件和文档
uninstall 删除make install安装的所有文件

特殊目标

make中有一些与定义的目标,这些预定义目标被make以一种特殊的方式进行处理,这些目标称为特殊目标;
.DEFAULTS  如果make找不到生成目标的任何makefile入口或后缀规则,就执行与目标相关的命令
.IGNORE  如果某一行makefile包含该目标,make忽略错误代码并继续建立,如果一个命令不正常存在,make自然会停止,带有-i选项的make命令可以执行相同的任务
.PHONY
    允许你指定一个不是文件的目标,所以您能只是make调用一系列makefile中的命令,即使在当前目录中有一个具有相同名字的文件
.SILENT
    make执行这些命令,但是不显示这些命令,带有-s的make可以执行相同的人物,
.SUFFIXES
    为目标指定的前提(后缀)可以与后缀规则相互关联,如果与目标没有相关性的前提,以存在的后缀列表就会被删除

默认模式规则

make中有许多预定义的规则成为后缀规则,它可以让make自动执行许多任务
为了建立一个目标,make会遍历一连串的依赖关系,这是为了决定从何处开始建立,如果没有找到目标文件,make就按有限顺序查找源文件       

默认模式规则:
    %o:%c
        $(CC) $(CFLAGS) -c $<
    $o:%s
        $(CC) $(AFLAGS) -o $@ $<

Makefile中的相关通配符:

#:注释
\:连接符号
关联列表和命令列表中可以使用shell通配符号? * %等

附上一个简单的makefile

#Sample
CC:=gcc
CFLAGS:=-Iinclude
CFLAGS+=-c
TARGET:=all/mytest_test3
DEPEND:=obj/mymath.o
DEPEND+=obj/mymath_test.o

$(TARGET):$(DEPEND)
    $(CC) -o $@ $^
#obj/mymath.o:src/mymath.c
#   $(CC) -o $@ $(CFLAGS) $^
#obj/mymath_test.o:src/mymath_test.c
#   $(CC) -o $@ $(CFLAGS) $^

#使用make中的默认的模式规则
obj/%.o:src/%.c
    $(CC) -o $@ $(CFLAGS) $^ 

#声明clean是一个虚目标
.PHONY:clean
clean:
    rm -rf obj/mymath.o obj/mymath_test.o

到此这篇关于C语言make和Makefile介绍及使用的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C语言Make命令用法讲解

    目录 格式 target 伪目标 prerequistites 多文件 commands 语法 注释 echoing 通配符 模式匹配 变量和赋值符 变量赋值 example 内置变量 自动变量 1. $@ 2. $< 3. $? 4. $^ 5. $* 6. (@D)和(@D)和(@F) 7. (<D)和(<D)和(<F) example 判断和循环 函数 1. shell 函数 2. wildcard 函数 3. subst 函数 4. patsubst函数 注意 实例 mak

  • 使用Make构建Node.js网站项目

    一.Make的优点 首先解释一下,为什么要用Make. 目前,网站项目(尤其是Node.js项目)有三种构建方案. 方案一:基于Node.js的专用构建工具(Grunt.Gulp.Brunch.Broccoli.Mimosa) 方案二:npm run命令(教程1.2.3) 方案三:make命令 我觉得,make是大型项目的首选方案.npm run可以认为是make的简化形式,只适用于简单项目,而Grunt.Gulp那样的工具,有很多问题. (1)插件问题 Grunt和Gulp的操作,都由插件完成

  • C语言 makefile学习及实现实例

    C语言 makefile学习及实现实例 俗话说,不会写makefile的程序员不是好的程序员. 看了很多人写的makefile教程,感觉太难懂,还不如韦东山老师视频里讲的好理解. 先记下这几个符号,以后看到就不会忘记这是什么东西了. 先来看一个例子: <span style="font-size:18px;">Person: main.o person.o g++ -o $@ $^ %.o : %.cpp g++ -c -o $@ $< clean: rm -rf *

  • Make命令基础用法教程

    目录 一.Make的概念 二.Makefile文件的格式 2.1 概述 2.2 目标(target) 2.3 前置条件(prerequisites) 2.4 命令(commands) 三.Makefile文件的语法 3.1 注释 3.2 回声(echoing) 3.3 通配符 3.4 模式匹配 3.5 变量和赋值符 3.6 内置变量(Implicit Variables) 3.7 自动变量(Automatic Variables) 3.8 判断和循环 3.9 函数 四.Makefile 的实例

  • C语言make和Makefile介绍及使用

    1:make和Makefile的介绍: 概念 在软件的工程中的源文件是不计其数的,其按照类型,功能,模块分别放在若干个目录中,哪些文件需要编译,那些文件需要后编译,那些文件需要重新编译,甚至进行 更复杂的功能操作,这就引入了我们的系统编译的工具: 在linux和unix中,有一个强大的使用程序,叫make,可以用它来管理多模块程序的编译和链接,直至生成可执行文件 make使用程序读取一个说明文件,称为Makefile,Makefile文件中描述了整个软件工程的 编译规则和各个文件之间的依赖关系:

  • C语言文件读写操作介绍与简单示例

    文件的打开函数fopen() 文件的打开操作表示将给用户指定的文件在内存分配一个FILE结构区,并将该结构的指针返回给用户程序,以后用户程序就可用此FILE指针来实现对指定文件的存取操作了.当使用打开函数时,必须给出文件名.文件操作方式(读.写或读写),如果该文件名不存在,就意味着建立(只对写文件而言,对读文件则出错),并将文件指针指向文件开头.若已有一个同名文件存在,则删除该文件,若无同名文件,则建立该文件,并将文件指针指向文件开头. fopen(char *filename,char *ty

  • 数据结构C语言链表的实现介绍

    目录 前言 函数 1. 链表初始化 2. 计算链表长度 3. 打印链表 4.计算链表长度 5. 删除链表中指定位置节点 6. 向链表中指定位置插入节点 7. 全代码+运行效果 前言 需要用到的函数库 #include<stdio.h> #include<malloc.h> malloc函数用来动态分配空间,相当于Java中new的作用 先是需要创建一个节点的结构体 typedef struct{ int data; struct linkNode* next; }linkNode;

  • C语言直接插入排序算法介绍

    目录 前言 一.什么是直接插入排序 二.代码讲解 总结 前言 直接 插入排序 (Straight Insertion Sort)是一种最简单的排序方法,其基本操作是将一条记录插入到已排好的有序表中,从而得到一个新的.记录数量增1的有序表.. 废话不多说先看看代码 #define _CRT_SECURE_NO_WARNINGS 1 //直接插入排序法 #include <stdio.h> void Compare(int arr[], int len) { int i = 0; for (i =

  • C语言动态内存管理介绍

    目录 前言: C 语言为内存的分配和管理提供了几个函数: 1.malloc() 用法 2.calloc() 用法 3.realloc() 与 free() 用法 前言: 简单记录一下,内存管理函数 为什么使用动态内存呢? 简单理解就是可以最大限度调用内存 用多少生成多少,不用时就释放而静止内存不能释放 动态可避免运行大程序导致内存溢出 C 语言为内存的分配和管理提供了几个函数: 头文件:<stdlib.h> 注意:void * 类型表示未确定类型的指针  1.malloc() 用法  分配一块

  • C语言全排列回溯算法介绍

    目录 前言 算法思想 完整代码 实验效果 总结 前言 本博文源于最近学习的递归算法,递归中遇到一个问题全排列的问题,我看见回溯特别神奇,特此记录一下.对比一下深度优先搜索与广度优先搜索,个人感觉这里的回溯像是一种递归树中的深度优先搜索的算法,他不断构造往下延伸的深度,使其达到完全编列 算法思想 比如3拿来举例,按照一般正常的话就是应该, 123 132 213 231 312 321 六种,先造出一个hashtable数组让其存储在各位是否使用,然后创建path的p数组将数字进行选填,递归树我花

  • 关于C语言动态内存管理介绍

    目录 1.为什么需要动态内存分配 2.有关动态内存函数介绍 2.1 malloc和free 2.2 calloc函数 2.3 realloc函数 3. 常见的动态内存错误 3.1 对NULL指针进行解引用操作 3.2 对动态开辟空间的越界访问 3.3 对非动态开辟内存使用free释放 3.4 使用free释放一块动态开辟内存的一部分 3.5 对同一块动态内存多次释放 3.6 动态开辟内存忘记释放(内存泄漏) 总结 1.为什么需要动态内存分配 关于这个问题,我们先看看我们之前是如何开辟内存的. i

  • C语言折半查找法介绍及使用示例

    目录 1. 折半查找介绍 1.1 定义 1.2 基本原理 1.3 时间复杂度与空间复杂度 1.4 优缺点 2. 代码实现 2.1 代码设计 2.2 代码实现 1. 折半查找介绍 1.1 定义 折半查找也称二分查找,是一种在有序数组中查找某一特定元素的搜索算法,每一次查找,搜索范围均缩小一半,效率较高.如果数组是乱序状态,则应排序,再进行查找. 1.2 基本原理 搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束:如果某一特定元素大于或者小于中间元素,则在数组大于或小于中

  • C语言直接插入排序算法介绍及示例

    目录 1. 直接插入排序介绍 1.1 定义 1.2 基本原理 1.3 时间复杂度 1.4 空间复杂度 1.5 优缺点 2. 代码实现 2.1 代码设计 2.2 代码实现 1. 直接插入排序介绍 1.1 定义 直接插入排序是一种最简单的排序方法,其基本操作是将一条记录插入到已排好的有序表中,从而得到一个新的.记录数量增1的有序表. 1.2 基本原理 每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序. 第一趟比较前两个数,然后把第二个数按大小插入到有序表中: 第二趟把第三个

  • C语言顺序查找算法介绍及示例

    目录 1. 顺序查找介绍 1.1 定义 1.2 基本原理 1.3 时间复杂度与空间复杂度 1.4 优缺点 2. 代码实现 2.1 代码设计 2.2 代码实现 1. 顺序查找介绍 1.1 定义 查找是指在指定数据组合中找出满足条件的元素个体.顺序查找是按照序列原有顺序对数组进行遍历比较查询的基本查找算法. 顺序查找是最基础也是最简单的查找算法,在需要进行查找时,这是我们的首选方法,只有数据较多,结构复杂,耗时较多需要优化时,我们才会考虑使用其他查找方法. 1.2 基本原理 对于任意一个序列以及一个

随机推荐