makefile简明教程

2023-05-16

makefile  主要是编译就是用来编译源文件的

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,也可以执行操作系统的命令。(百度百科)

makefile的文件命名:makefile 或 Makefile

makefile的规则或者说写法就三个部分:目标、依赖、命令

具体怎么写呢 

目标:依赖

 (tab缩进)命令

 看一个小例子

例一:

app:main.c add.c sub.c mul.c

      gcc main.c add.c sub.c mul.c -o app

app就是最终要生成的目标,所有需要的c文件就是依赖

执行gcc命令

这就是一个最简单的makefile,但是它最大问题是,如果你修改了中一个.c文件,在gcc编译的时候会把所有的c文件都编译一遍,这样效率就很低,所以可以把他们分开写,先编译成.o二进制文件。这样就是第二个例子

例二:

app:main.c add.c sub.c mul.c
      gcc main.o add.o sub.o mul.o  -o  app
main.o :main.c
       gcc main.c -c
add.o :add.c
      gcc add.c -c
sub.o :sub.c
      gcc sub.c -c
mul.o :mul.c
      gcc mul.c -c

只有app是要生成的终极目标,下面是为它服务的小目标

 这样当你更改某一个.c文件后,只会编译你修改的那个c文件,编译成.o二进制文件,而不用把所有的都编译一遍,节省很多时间。

那makefile是怎么知道要重新编译的是哪一个文件呢。

原理是

首先向下搜索下面的规则,检测下面的规则里是否有终极目标app需要的依赖,

如果依赖存在就判断是否需要更新也就是小目标是否要执行,

判断的依据是目标和依赖的时间,如果目标的时间大于依赖的时间,不更新,反之需要更新。说白了就是它会根据文件时间的变化检测你有没有更改源文件,更改了就要更新。因为一定是现有依赖才有的目标,目标.o文件时间要晚于依赖的时间也说成大于。也就是说一旦更改了依赖文件,这个文件最终时间就在目标之后了,依赖时间大于了目标时间,说明你修改了依赖文件,这时就需要更新。

但是上面这个makefile写的太冗余了。下面看下面一个例子改进一下:

例三:

前面说makefile就像一个脚本,那它就可以有变量和函数。所以先看一下变量,变量你可以自己定义,makefile本身也提供了几个固定的变量。

自定义变量:makefile里面自定义变量没有类型 直接赋值就行,例如:obj = a.o b.o c.o 或者 obj  = 10 ,不讲道理的使用,

但是变量不能直接使用要取出变量的值,用$符号,例如$(obj)

makfile提供的变量:CC 、CPPLAGS、LDFLAGS、LIBS等

这些参数都和gcc命令相关,例如让:

CC=”gcc -march=k8 -O2 -s”                           

LDFLAGS = -L/var/xxx/lib -L/opt/mysql/lib

LIBS = -lmysqlclient -liconv

CPPFLAGS='-I/usr/local/libjpeg/include -I/usr/local/libpng/include'

就是在gcc编译的时候需要指定一下头文件和库文件目录,写起来太长了,你就讲路径赋值给相应的变量,这是一种规范,你随便给别的变量也能用。甚至很多makefile文件中编译都没有gcc的字样就是把gcc赋值给了CC。当然也可以把这些值设置到环境变量中去export LDFLAGS="-L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib" ;

自动变量:$@、$<、$^,makefile提供了几个变量表示着固定的意思,不能对他们赋值且只能在规则命令中使用。

$@:规则中的目标

$<:规则中的第一个依赖

$^:规则中的所有的依赖

改写例二

obi = main.o add.o sub.o mul.o
target = app
$(target):$(obj)
     gcc $(obj)  -o  $(target)           这一行就可以替换成 gcc $^ -o $@
%.o:%.c                                 %模式匹配代表所有的.o文件和所有的.c文件
    gcc -c $< -o $@

 

 现在这个makefile的可移植性很差

例四:

这里看一下makefile的函数

makefile中所有的函数都有返回值,下面介绍两个makefile的函数

(1)wildcard 查找指定文件夹下指定类型的文件

     src = $(wildcard ./*.c)  当前目录下所有的.c文件并赋值给src

(2)patsubst匹配替换

    obj = $(patsubst %.c, %.o,$(src))  把src变量中所有.c文件替换为.o文件

src = $(wildcard ./*.c)
obj = $(patsubst %.c,%.c,$(src))
trarget = app
$(target):$(obj)
    gcc $^ -o $@
%.o:%.c
    gcc -c $< -o $@

 

例五:

前面说的makefile最后生成的是只有第一目标,也就终极目标。其实makefile也可以生成不是终极目标的目标,

调用使用 :make 目标名   ,例如一个makefile最后会执行make clean清理项目

src = $(wildcard ./*.c)
obj = $(patsubst %.c,%.c,$(src))
trarget = app
$(target):$(obj)
    gcc $^ -o $@
%.o:%.c
    gcc -c $< -o $@
hello:
   echo "hello,makefile"

 

执行make hello 会打印hello,makefile

 如果我们加一个,清理项目的操作,表示如果执行失败删除前面生成的文件。

clean:

    -mkdir  /abc

    -rm $(obj)&(target) -f       #-f表示强制执行 ,命令前的'-'号表示当前命令失败向下执行

这里有会有个问题就是,如果当前目录下有同名的clean文件,make clean就不会执行。前面例二就说了,makefile根据依赖的时间来判断会不会更新,但是这里clean没有依赖。

解决这个问题的方法是写一个伪目标  .PHONY:clean ,注意PHONY前面有个'.'符号。

完整的就是

src = $(wildcard ./*.c)
obj = $(patsubst %.c,%.c,$(src))
trarget = app
$(target):$(obj)
    gcc $^ -o $@
%.o:%.c
    gcc -c $< -o $@
.PHONY:clean
clean:
    -mkdir /abc
    -rm $(obj)&(target) -f 

 

 好了makefile就是这么简单。

最后写一个小例子

在plus目录下有两个目录include和src,现在在plus目录下编写makefile,编译src下的源文件,需要include中的头文件。

trarget = app
CPPFLAS = ./include
src = $(wildcard ./src/*.c)
obj = $(patsubst %.c,%.c,$(src))
$(target):$(obj)
   gcc $^ -o $@
%.o:%.c
   echo $<
   gcc -c $< -I $(CPPFLAGS) -o $@

 

上面可以甚至让 CPPFLAS = '-I./include',这样gcc中就不用再加参数 -I了

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

makefile简明教程 的相关文章

随机推荐

  • 兵棋推演系统软件开发方法有哪些呢

    兵棋推演系统软件开发方法有哪些呢 兵棋推演系统北京软件开发公司针对 B S 架构及先进的多想定 多进程以及多方推演技术进行研究 xff0c 实现了基于 B S 架构的兵棋推演系统 该系统使用便捷 xff0c 只需通过浏览器访问系统即可 兵棋
  • 工厂生产设备全生命周期管理系统软件

    工厂生产设备全生命周期管理系统软件 设备全生命周期管理系统是解决当下设备管理问题 xff0c 实现设备效能利用最优化的重要举措 设备全生命周期管理系统传统意义上的设备管理系统或软件 xff0c 往往局限在业务层面和主数据层面 然而 xff0
  • 2万字系统总结,带你实现 Linux 命令自由?还不赶紧进来学习

    2万字系统总结 xff0c 带你实现 Linux 命令自由 还不赶紧进来学习 前言 Linux 的学习对于一个程序员的重要性是不言而喻的 前端开发相比后端开发 xff0c 接触 Linux 机会相对较少 xff0c 因此往往容易忽视它 但是
  • ENVI 5.3遥感(无人机)影像的镶嵌(拼接)

    图像镶嵌 xff0c 对一幅或若干幅图像通过预处理 几何镶嵌 色调调整 去重叠等处理 xff0c 镶嵌到一起生成一幅大的图像的影像处理方法 要求是尽量是镶嵌后的影像没有镶嵌缝 图像质量不下降 色彩均衡等 ENVI5 3的图像镶嵌功能可提供交
  • NotePad++ XMLTools 插件离线安装

    在使用NotePad 43 43 时 xff0c 在某些情形下 xff0c 需要格式化Xml格式内容 xff0c 可以使用Xml Tools插件 xff0c 注意下载安装包时 xff0c 需下载与NotePad 43 43 像匹配版本的插件
  • errors_impl.AlreadyExistsError: Another metric with the same name already exists.

    errors impl AlreadyExistsError Another metric with the same name already exists 今天在导包keras包时 xff0c 总是报上面这个错误 xff0c 说已经ke
  • docker-compose 中 volumes、environment、privileged、network_mode的使用

    privileged xff1a 用来给容器root权限 xff0c 不安全的environment xff1a 设置容器中的环境变量volumes xff1a 用来存储docker持久化的数据 xff0c 启动tomcat容器后 xff0
  • 普通程序员如何逆袭,达到财富自由?

    这两天闲逛知乎 xff0c 发现了一个有趣的问题 xff1a 大部分人的回答大概率无非这两种模式 xff1a 1 去大厂 混到管理层或者高P xff0c 拿大量股权 xff0c 财务自由 这个模式还挺常见的 xff0c 基本上阿里P8能到年
  • intel realsense SR300 深度图像和彩色图像对齐

    深度图像和彩色图像对齐 原因 xff1a 由于RGB图像数据与深度图像数据的空间坐标系是不同的 xff0c 前者的原点是RGB摄像头 xff0c 后者的原点是红外摄像头 xff0c 因此两者会有相应的误差 没对齐之前的结果如下图所示 xff
  • CMakeLIsts.txt与Makefile的区别

    CMake是一个跨平台的安装 编译 工具 可以用简单的语句来描述所有平台的安装 编译过程 他能够输出各种各样的makefile或者project文件 能测试编译器所支持的C 43 43 特性 类似UNIX下的automake CMake 使
  • linux socket编程

    1 网络中进程之间如何通信 进程通信的概念最初来源于单机系统 由于每个进程都在自己的地址范围内运行 xff0c 为保证两个相互通信的进程之间既互不干扰又协调一致工作 xff0c 操作系统为进程通信提供了相应设施 xff0c 如 UNIX B
  • linux环境下如何卸载一路赚钱(yilu/mservice)

    一 删除定时任务 xff1a sudo crontab l u root 2 gt dev null grep v mservice sudo crontab u root 二 停止服务 对于ubuntu以及centos 7的用户 serv
  • 【图像处理】多帧降噪算法

    本文参考论文 xff1a Denoising image sequences does not require motion estimation http citeseerx ist psu edu viewdoc download do
  • VINS-Fusion初始化------IMU与Camera外参旋转标定,IMU角速度偏置标定,重力向量、单目尺度标定

    本文基于VINS Fusion解释VIO系统的初始化 xff0c 包括在线标定IMU Camera的外参旋转 xff0c IMU角速度偏置 xff0c 重力方向 xff0c 单目尺度 单目初始化相比于双目 xff0c 多一个构建SFM问题优
  • 视觉惯性里程计Visual–Inertial Odometry(VIO)概述

    本文主要来自于博客园关于知乎的讨论 链接如下 xff1a Visual Inertial Odometry VIO
  • IBM Was 打补丁记录

    0 拷贝解压ifph52925升级包 通过FTP工具 xff0c 把压缩包传到服务器 xff0c unzip d test01 9 0 0 0 ws was ifph52925 zip 1 停掉was 服务 ps ef grep was k
  • 阿里云服务器远程桌面安装

    阿里云服务器远程桌面安装 环境说明 xff1a CentOS 8 3 一 安装桌面环境 root用户下执行命令 yum grouplist yum groupinstall y span class token string 34 Serv
  • STM32与Futaba遥控器进行S.Bus的通讯程序

    Futaba xff08 日本双叶电子工业 xff0c 戏称 扶他爸 xff09 的遥控器用航模中使用较为广泛的遥控器 S Bus则是Futaba公司提出的舵机控制总线 本篇博文主要以T6K为对象 xff0c 介绍STM32与S Bus协议
  • c++ 小知识点记录

    数据类型 数据类型类型说明符位数取值范围整型int32 2147483648 43 2147483647短整型short int16 32767 43 32768长整型long int32 2147483648 43 2147483647单
  • makefile简明教程

    makefile 主要是编译就是用来编译源文件的 一个工程中的源文件不计其数 xff0c 其按类型 功能 模块分别放在若干个目录中 xff0c makefile定义了一系列的规则来指定哪些文件需要先编译 xff0c 哪些文件需要后编译 xf