Makefile和CMake的简单入门

2023-05-16

Makefile和CMake的简单入门

  • 从源代码到可执行文件
  • Makefile的产生背景
  • 从make的调用到Makefile
  • Makefile的基本格式
  • Makefile的扩展用法
  • Makefile的生成和部署

一、从源代码到可执行文件

当编译文件依赖关系复杂的时候,make工具诞生了,而Makefile文件正是为make工具所使用的

1、可执行程序产生的过程

配置环境 -> 确定标准库和头文件的位置 -> 确定依赖关系 -> 头文件预编译 -> 预处理 -> 编译 -> 链接 -> 安装 -> 与操作系统减建立联系 -> 生成安装包

(1)预编译

预编译过程主要处理那些源代码文件中的以“#”开始的预编译指令,比如“#include”“#define”等,主要处理规则如下:

  • 将所有的“#define”删除,并且展开所有的宏定义
  • 处理所有条件预编译指令,比如“#if”“#ifdef”“#elif”“#else”“#endif”
  • 处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。删除所有的注释“//”“/**/”
  • 添加行号和文件名标识,比如#2“a.c”2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号
  • 保留所有的#pragma编译器指令,因为编译器需要使用它们
(2)编译

编译过程就是把预处理完的文件进行一系列词法分析,语法分析,语义分析,代码优化及优化后生成相应的汇编代码文件

代码优化的优缺点:

  • 优点:提高效率
  • 缺点:多线程下不可控
(3)汇编

汇编过程就是由汇编器将汇编代码转变成机器可以执行的二进制指令

(4)链接

链接的主要内存就是把各个模块之间相互引用长度部分都处理好,使得各个模块之间能够正确的衔接。简单的理解为将各个目标文件链接起来生成最终的可执行文件

链接过程可以具体的分为以下四步:

  • 合并段和符号表

    合并多个文件的符号表及各段内容,放入一个新的文件中

  • 符号解析

    在每个文件符号引用(引用外部符号)的地方找到符号的定义。这就是符号解析

  • 地址和空间分配

    符号解析成功后,为程序分配虚拟地址空间

  • 符号重定位 // 指令段

    符号重定向就是对.o文件中.text段指令中的无效地址给出具体的虚拟地址或者相对位移偏移量

链接又分为静态链接动态链接

2、Makefile做了什么

描述了整个工程所有文件的编译顺序、编译规则

二、Makefile产生背景

1、多个文件编译的简单示例

先创建三个文件:

  • reply.h

    #include<iostream>
    
    class Reply
    {
    public:
    	Reply();
    	~Reply();
    	void PrintHello();
    };
    
  • reply.cpp

    #include"reply.h"
    
    using namespace std;
    
    Reply::Reply()
    {}
    
    Reply::~Reply()
    {}
    
    void Reply::PrintHello()
    {
    	cout << "Hello World" << endl;
    }
    
  • main.cpp

    #include"reply.h"
    
    int main() 
    {
    	Reply reply;
    	reply.PrintHello();
    	return 0;
    }
    

我们使用c++编译命令:g++ main.cpp reply.h reply.cpp -o main即可完成编译

2、Makefile最简单的语法

创建Makefile文件

main: reply.o main.o
	g++ reply.o main.o -o main
reply.o: reply.cpp
	g++ -c reply.cpp -o reply.o
main.o: main.cpp
	g++ -c main.cpp -o main.o

3、make的初步使用

使用make命令回车,见到下面的输出完成

g++ -c reply.cpp -o reply.o
g++ -c main.cpp -o main.o
g++ reply.o main.o -o main

三、从make的调用到Makefile

1、make究竟是什么

make是一个批处理工具,能执行一系列linux命令

2、Makefile都有些什么

make工具就根据Makefile中的命令进行编译和链接的

3、其他的IDE工具:CMake

帮助开发者快速、简化部署工程编译链接

四、Makefile的格式

1、Makefile的基本规则

目标(target): 依赖(prerequisites)

​ 命令(command)

2、Makefile的简化规则

变量定义:变量=字符串

变量使用:$(变量名)

TARGET = main
OBJS = reply.o main.o

.PHONY: clean

$(TARGET):$(OBJS)
	g++ $(OBJS) -o $(TARGET)
reply.o: reply.cpp
main.o: main.cpp

clean:
	rm $(TARGET) $(OBJS)
  • TARGET = main:定义变量
  • .PHONY: clean:当目录下存在clean文件时,执行make clean会失效,声明clean为非实体文件
  • clean::定义make clean命令

3、改写Makefile的基本实例

注意:不生成目标文件的命令最好都设成假想目标

五、Makefile的扩展用法

1、make工程的安装和卸载

Makefile文件与上面类似

TARGET = main
OBJS = reply.o main.o

.PHONY: clean

$(TARGET):$(OBJS)
	g++ $(OBJS) -o $(TARGET)
reply.o: reply.cpp
main.o: main.cpp

clean:
	rm $(TARGET) $(OBJS)

install:
	cp ./main /usr/local/bin/mainTest

uninstall:
	rm /usr/local/bin/mainTest

之后在当前项目路径下执行:make installmake uninstall即可进行安装与卸载,记得使用root权限!

2、Makefile中的变量

  • 用户自定义变量

  • 变量中的变量

    让一个变量依赖一个还没有定义的变量,有一种延迟的效果,将变量的真实值放到之后来定义

    foo = $(bar)
    bar = $(ugh)
    ugh = Huh
    
    test1:
    	echo $(foo), foo
    test2:
    	echo $(bar), bar
    

    避免向后依赖使用:=,如下:

    y := $(x)bar
    z = $(x)bar
    x := foo
    
  • 追加变量

    接上面,如果我们追加一行:x += foo1

  • 多行变量

    define two-lines
    foo
    echo $(bar)
    endef
    test4:
    	echo $(two-lines)
    
  • 环境变量

    echo $(HOME), $(SHELL), $(LD_LIBRARY_PATH)
    

    以下使用动态链接库来生成可执行文件

    TARGET = main
    OBJS = reply.o
    LIB = libreply.so
    CXXFLAGS = -c -fPIC
    
    .PHONY: clean
    
    $(TARGET):$(LIB) main.o
            $(CXX) main.o -o $(TARGET) -L. -lreply -Wl,-rpath ./
    $(LIB):$(OBJS)
            $(CXX) -shared $(OBJS) -o $(LIB)
    reply.o:reply.cpp
            $(CXX) $(CXXFLAGS) reply.cpp -o $(OBJS)
    main.o: main.cpp
            $(CXX) $(CXXFLAGS) main.cpp -o main.o
    
  • 自动变量 & 模式变量

  • 自动匹配

六、Makefile的自动生成和部署

1、项目的生成和部署

一般来说,至少有下面的目录:

  • src

    头文件的实现文件

  • include

    用到的头文件

  • bin

    可运行文件

  • build

    临时构建的文件

2、关于automake/autoconfig、CMake的使用

依赖关系比较复杂的项目可以使用上面的两个工具来实现

3、CMake的使用

  • 我们先需要安装CMake工具,具体安装过程Google

  • 安装好以后,我们依然使用上面的reply.cppreply.hmain.cpp简单demo来使用我们的CMake

  • 先创建俩文件夹:src(放cpp文件)include(放h文件)

  • 然后编写CMakeList.txt

    # CMakeList.txt
    # 设置cmake最低版本
    cmake_minimum_required(VERSION 2.8.0)
    # 设置c++标准
    set(CMAKE_CXX_STANDARD 11)
    # 项目名称
    project(xxx)
    # 包含的头文件目录
    include_directories(./include)
    set(SRC_DIR ./src)
    # 指定生成链接库
    add_library(XXX ${SRC_DIR}/XXX.cpp)
    add_library(YYY ${SRC_DIR}/YYY.cpp)
    # 设置变量
    set(LIBRARIES XXX YYY)
    set(OBJECT XXX_test)
    # 生成可执行文件
    add_executable(${OBJECT} ${SRC_DIR}/main.cpp)
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Makefile和CMake的简单入门 的相关文章

  • 误差与精度

    整理自 误差理论与数据处理 合肥工业大学 机械专业用于教授学生误差与精度概念的课程叫做 公差与测量 或者叫做 机械精度设计 xff0c 而公差或者精度的本质含义就是误差的大小 xff0c 公差越小 xff0c 误差越小 xff0c 精度越高
  • 两个类的头文件互相包含

    两个类的头文件互相包含 我做任务的时候遇到了两个类都互相包含对方的对象的问题 xff0c 本来是有错误的 xff0c 但经过我一番改动 xff0c 两个头文件互相包含同时 xff0c 每个头文件都含有令一个类的前置声明 虽然最后运行正确 x
  • 【C++ STL 容器】——vector

    概述 vector容器也被称作向量 xff0c 实现了动态的数组 xff0c 用于元素数量变化的对象数组 xff0c 算是比较常用的容器 常用函数 构造函数 vector 创建一个空vectorvector int size 创建一个vec
  • 2021-07-22

    MSP432在keil中通过CMSIS DAP下载程序出现cannot enter debug mode的解决办法 xff1a MSP432下载程序出现cannot enter debug mode 可以通过修改如下设置 Debug里面的两
  • 通信协议基础以及常用的串口通信协议

    通信协议 xff1a 串行通信和并行通信 在数据的通信方式中根据数据传输方式的不同可以分为 xff1a 串行通信和并行通信 串行通信 xff1a 串行通信是指使用一条数据线 xff0c 将数据一位一位地依次传输 xff0c 每一位数据占据一
  • Ubuntu安装ROS melodic,管理环境,创建工作空间

    一 安装ROS 1 设置源 xff1a sudo sh c 39 etc lsb release amp amp echo 34 deb http mirrors tuna tsinghua edu cn ros ubuntu 96 lsb
  • HTTP请求报文的结构组成及URL的结构组成

    HTTP请求报文 HTTP 超文本传输协议 Hypertext Transfer Protocol xff0c 简称HTTP 是应用层协议 HTTP 是一种请求 响应式的协议 xff0c 即一个客户端与服务器建立连接后 xff0c 向服务器
  • Qt之旅_001>>Qt常用窗口类之间的关系

    QApplication xff0c QGuiApplication QCoreApplication三者之间的关系 QCoreApplication处于core模块中 xff0c 为应用程序提供了一个非gui的时间循环 xff1b QGu
  • GPIO相关介绍

    文章目录 GPIO概念TXD与RXD GPIO的使用注意STM32IO口哪些兼容5V一定不要接超过5V的电压默认不能做输出的GPIO GPIO硬件原理图GPIO地址 GPIO的八种工作模式浮空输入带上拉输入带下拉输入模拟输入开漏输出推挽输出
  • STM32的常用C语言

    文章目录 一些被坑了的注意点 int16 define结构体与共用体指针 C语言发展史C语言概述C90 标准C99标准C11标准 C编译o代替c 条件语句else ifdo while 变量定义一个字符串字符串结尾 定义一个字符串数组sta
  • STM32应用霍尔转速传感器基于输入捕获

    这里我用通用定时器3的通道1来测量转速 霍尔转速传感器基本介绍霍尔传感器分类和原理关于为什么选用开关型常开PNP型霍尔传感器 STM32程序实现程序介绍程序源码TIM3 CAP HTIM3 CAP H解读TIM3 CAP CTIM3 CAP
  • Android so库开发——使用Studio生成自己的so库(一)

    一 创建Native项目 1 新建 Native 项目 1 xff09 新建项目 选择最下面的 Native C 43 43 下一步即可 2 xff09 填写项目信息 3 xff09 选择C 43 43 版本可以直接选择默认 2 下载并配置
  • C语言实现线性回归求斜率

    2020 11 22 修改 span class token comment 线性回归求斜率 注意数据类型 参数 count 数据个数 数组行 列 的个数 数组的行列数目相等 参数 dataCol X 数据的列数据 参数 dataRow Y
  • 【C语言】详解位域定义与使用

    位域的定义 span class token keyword struct span span class token class name bit span span class token punctuation span span c
  • C语言实现MQTT协议(一)协议讲解

    MQTT介绍 MQTT是一个客户端服务端架构的发布 订阅模式的消息传输协议 它的设计思想是轻巧 开放 简单 规范 xff0c 易于实现 这些特点使得它对很多场景来说都是很好的选择 xff0c 特别是对于受限的环境如机器与机器的通信 xff0
  • 【STM32】HAL库-外部中断

    外部中断框图 产生中断 硬件触发外部中断 配置中断屏蔽寄存器中的屏蔽位 xff0c 允许该外部中断请求 通过AFIO EXTICRx配置GPIO线上的外部中断 事件 xff0c 必须先使能AFIO时钟 选择外部中断的触发边沿 xff0c 上
  • 【STM32】HAL库-系统滴答定时器SysTick

    SysTick定时器被捆绑在NVIC中 xff0c 是一个简单的定时器 xff0c 对于CM3 CM4内核芯片 xff0c 都有Systick定时器 Systick定时器常用来做延时 xff0c 或者实时系统的心跳时钟 这样可以节省MCU资
  • 【STM32】HAL库-串口USART

    USART简介 通用同步异步收发器 USART 提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换 USART利用分数波特率发生器提供宽范围的波特率选择 一个波特率寄存器 USART BRR xff0c
  • 【STM32】HAL库-通用定时器

    简介 通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成 它适用于多种场合 xff0c 包括测量输入信号的脉冲长度 输入捕获 或者产生输出波形 输出比较和PWM 使用定时器预分频器和RCC时钟控制器预分频器 xff0c 脉冲长
  • 【STM32】HAL库-SPI

    3线全双工同步传输 带或不带第三根双向数据线的双线单工同步传输 8或16位传输帧格式选择 主或从操作 支持多主模式 8个主模式波特率预分频系数 最大为fPCLK 2 从模式频率 最大为fPCLK 2 主模式和从模式的快速通信 主模式和从模式

随机推荐

  • 【STM32】标准库-以太网外设-LAN8720A-LWIP-无操作系统

    TCP IP模型 TCP IP 只有四个分层 xff0c 分别为应用层 传输层 网络层以及网络访问层 xff08 物理层 xff09 实际上 xff0c 还有一个 TCP IP 混合模型 xff0c 分为五个层 它实际与 TCP IP四层模
  • 【STM32】标准库-LTDC-DMA2D

    LTDC STM32F429 系列芯片内部自带一个 LTDC 液晶控制器 xff0c 使用 SDRAM 的部分空间作为显存 xff0c 可直 接控制液晶面板 xff0c 无需额外增加液晶控制器芯片 STM32 的 LTDC 液晶控制器最高支
  • 【STM32】HAL库-以太网外设-LAN8720A-LWIP-无操作系统

    开发环境 KEIL MDK ARM 5 27MCU STM32F429IGT6PHY IC LAN8720ALWIP LWIP2 1 2STM32CUBEMX 6 6 1HAL V1 27 1 LAN8720A使用RMII接口与STM32的
  • git学习

    常用命令 查看当前文件夹下的文件与文件夹 xff1a ls ll 进入当前文件夹下的user文件夹 xff1a cd user 查看当前文件夹下的test txt文件 xff1a cat test txt 返回上一级目录 xff1a cd
  • 电赛专题---一.概述【电赛简介 /信号类需要准备什么?/怎么才能打好电赛?】

    1 电赛简介 全国大学生电子设计竞赛 xff08 National Undergraduate Electronics Design Contest xff09 是教育部和工业和信息化部共同发起的大学生学科竞赛之一 xff0c 是面向大学生
  • Postman安装

    1 官网下载 下载链接地址 xff1a https www postman com downloads 点击Download the App 根据自己的电脑以及需求选择对应的32位或者64位的版本 2 双击安装包 xff0c 不用任何操作
  • UART串口通信

    串口是 串行接口 的简称 xff0c 即采用串行通信方式的接口 串行通信将数据字节分成一位一位的形式在一条数据线上逐个传送 xff0c 其特点是通信线路简单 xff0c 但传输速度较慢 因此串口广泛应用于嵌入式 工业控制等领域中对数据传输速
  • Java第四课数据类型(二)

    一 变量类型 1 字节型 byte 2 整型 xff08 1 xff09 int 整型 4字节 xff08 2 xff09 show 短型 2字节 xff08 3 xff09 long 长型 8字节 3 浮点型 xff08 1 xff09
  • ESP32蓝牙配网

    注意 menuconfig 配置 xff08 必须打开蓝牙我这是C2所以使用NimBLE xff09 可以直接从demo的配置文件拷贝 Component config gt Bluetooth gt NimBLE BLE only Com
  • [C#] UDP协议 常用简单的代码(基于UdpClient类)(Thread实现)

    目录 说明1 消息发送端2 消息接收端 说明 在使用 C 开发Winform WPF等富客户端应用程序时 xff0c 有时会有 进程 之间 相互通信 的需求 下面是一种能够实现Udp 消息收发 常用且较为简单的 C 代码 使用注意 xff1
  • 掌控板OLED显示

    掌控板OLED显示 OLED显示文本内容 需要先将显示清空 xff0c 然后将想要显示的内容放在里面 xff0c 最后放入oled显示生效 源代码如下 xff1a span class token keyword from span mpy
  • 激光slam学习笔记1--RTK组合惯导、激光雷达传感器一些经验知识分享

    前言 xff1a 跟组合惯导和激光雷达打交道半年了 xff0c 过程中查找学习了这两方面的资料 xff0c 这里来个小结 如果有理解错误的 xff0c 望大佬们不吝赐教 一 RTK组合惯导 个人理解有两部分组成 xff0c 一个提供gps信
  • 计算机组成原理第五章:输入输出系统

    本章知识架构 接口 接口分类 xff1a 并行接口 xff1a 接口与系统总线 xff0c 接口与外设均按并行方式传送数据 串行接口 xff1a 接口与系统总线并行 xff0c 与外部设备串行 按I O传送控制方式划分 xff1a 直接程序
  • STM32串口通信 (缓冲区 发送不出数据&接收不到数据)

    STM32串口通信 流程附上代码注意事项一点心得 xff1a 流程 xff08 简单的发送数据 xff09 GPIO时钟使能串口时钟使能串口的GPIO配置写初始化串口函数 xff0c 配置串口USART Init USART1 amp US
  • 设计一个脉冲发生器,已知系统时钟为50MHz,生成脉冲宽度为1ms,脉冲间隔可调,最大间隔为1s

    设计一个脉冲发生器 xff0c 已知系统时钟为50MHz xff0c 生成脉冲宽度为1ms xff0c 脉冲间隔可调 xff0c 最大间隔为1s Design a pulse generator The system clock is kn
  • 详解结构体与链表

    目录 1 定义使用结构体变量 2 使用结构体数组 3 结构体指针 4 结构体内存对齐 重点 5 typedef的使用 6 动态内存的分配与释放 7 链表的创立 增删查改插 什么是链表 xff1f 静态链表和动态链表 链表的创立 链表的插入元
  • c++头文件及函数

    目前小编只了解到这些 xff0c 如果还有其他的一些头文件或函数 xff0c 欢迎评论区留言或者私信小编 xff0c 谢谢大家的观看 1 include lt iostream gt system pause 系统暂停 system mod
  • 将Ubuntu虚拟机架设到GNS3拓扑网络上并进行TCP协议仿真分析

    目录 前言环境配置 xff08 将Ubuntu虚拟机挂载到GNS3拓扑网络上 xff09 配置Ubuntu虚拟机GNS3拓扑网络配置先进行一下数据传输检验通路是否正常 开始实验task1 TCP传输过程中的IP分片task2 TCP请求与一
  • HTTP协议---工作原理&报文详情&完整请求过程

    1 工作原理 1 1 OSI 七层模型 OSI xff08 Open System Interconnection xff0c 开放系统互连 xff09 七层网络模型称为开放式系统互联参考模型 xff0c 是一个逻辑上的定义 xff0c 一
  • Makefile和CMake的简单入门

    Makefile和CMake的简单入门 从源代码到可执行文件Makefile的产生背景从make的调用到MakefileMakefile的基本格式Makefile的扩展用法Makefile的生成和部署 一 从源代码到可执行文件 当编译文件依