C++编译之(2)-make及makefile编译过程

本文详细介绍了C++项目从使用g++手动编译到利用Makefile实现自动化构建的过程。通过实例展示了Makefile的编写,包括基本规则、变量、函数和嵌套执行Makefile,帮助读者理解Makefile的工作原理和编写技巧。通过学习,读者将能够为自己的C++项目编写有效的Makefile,提升开发效率。
摘要由CSDN通过智能技术生成

引言

前面我们介绍了c++的编译工具,使用g++实现对单个文件,多个文件,静态库动态库的编译;我们继续以该项目为例讲解;

g++ 的编译使用入门教程-点这里查看

我们继续以前面的目录解构为例,这里给出上一节的目录如下:

- mutilFilesDemo
  - include // 头文件目录
    - HelloTools.h
    - Prints.h
  - libs // 库子项目目录
    - ToolLibs.h
    - ToolLibs.cpp
    - libToolLibs.a // 静态库
  - src // 源码目录
    - module // 源码模块
      - Prints.cpp // Prints类
    - HelloTools.cpp // HelloTools类
  - main.cpp // main类

我们简单再回顾直接使用g++的编译上面项目的流程;该项目包含一个子项目静态库;所以我们需要首先编译子项目mutilFilesDemo/libs生成库文件libToolLibs.a,然后再进行编译主项目

step.1 编译子项目项目

# 进入子项目
cd mutilFilesDemo/libs
g++ -c ToolLibs.cpp
ar crv libToolLibs.a ToolLibs.o

step.编译主项目

# 回到主项目
cd mutilFilesDemo
# 编译并链接到静态库
g++ main.cpp ./src/HelloTools.cpp ./src/modules/Prints.cpp -L ./libs -l ToolLibs -o main

这样我们就完成整个编译了;

倘若,我们开发一个大工程,有很多的模块,很多子项目、代码文件,同时依赖很多静态库、动态库的话 ,显然采用这种方式工作量是非常大的。

于是我们创造出了一个make的工具及Makefile文件,Makefile文件记录编译相关的策略及配置项,我们只需要一个make命令即可完成编译,是不是很优雅?

Makefile如何编写?

首先,Makefile的本质其实可以理解为一个构建shell配置脚本;说白了,就是将我们前面写的g++ xxx.cpp -o xxx等一长串命令,预先写好,然后输入make命令,就自动执行了

理论上来说,你写shell脚本也可以实现c++的编译,再退一万步,只要你愿意,你可以一条条g++地输入

我们先看一个Makefile的最简单例子

Makefile文件

help :
	@echo "help info"

dist :
	@mkdir dist

clean :
	@rm -rf dist

我们执行一下make,输入help info字符串

$ make
help info

其实就是执行了@echo help info这条命令(前面加了@,表示不显示命令字符串自本身)

这个Makefile没啥用,然而,确实就是一个合法的Makefile文件,所以其实我们可以从侧面窥探出这个Makefile其实并没有什么高深的技术,它本质就是执行一系列的脚本,而不管你执行的是啥东西(当然,make工具添加许多非常方便的脚本函数,都是在g++手动编译过程中遇到的麻烦事转摸索过来的经验工具函数);Makefile更多的是一种自动化构建思想;

对于Makefile的规则,始终默认执行文件中的第一个标签的脚本,这里即是help;如果希望执行其他标签的脚本可在make命令的后面跟上相应的标签,如:make dist

实际上,Makefile官方介绍中,是这样介绍这个基本规则的,Makefile的编写基本规则如下

target: prerequisites
        recipe

target: 通常是程序生成(输出)的一个或多个文件名,例如:可执行文件或目标文件;它也可以是要执行任务的名称,例如用于清理生成文件的 clean 任务

prerequisites: 先决条件是用于生成 target 文件的输入文件或是完成 target 任务前需要先执行的任务 。一个 target 可以没有先决条件,也可以有一个或多个先决条件(比如,编译的依赖文件,这里还隐藏着的规则是,如果这些依赖发生了改变,则目标文件将会重新编译,着这个规则可以大大减少我们重新编译的效率)

recipe: 中文翻译为菜谱,它是 make 用于生成 target 文件或完成 target 任务而执行一系列 shell 命令。这些命令可以放在同一行里,也可以每个命令占一行。值得注意的是,recipe 默认以制表符开头,而不是空格

其实写到这里,你已经有办法可以写一个简单的符合Makefile的c++构建脚本了;
我们把Makefile再改造成如下内容:

build :
	@echo "开始编译c++"
	g++ main.cpp ./src/HelloTools.cpp ./src/modules/Prints.cpp -L ./libs -l ToolLibs -o main
	@echo "end"

执行一下make命令

$ make
开始编译c++
g++ main.cpp ./src/HelloTools.cpp ./src/modules/Prints.cpp -L ./libs -l ToolLibs -o main
end

编译成功!

当然Makefile的功能远不止这些,我们继续学习一下Makefile的基本语法规则

基本语法规则
1、变量
  • 变量的定义
    make的变量与shell的变量很像,但是make的变量可以出现许多特殊字符,包括空格(=除外),如下所示
objs = main.o model.o view.o controller.o

注意变量的赋值有两种,一种是取直接赋值(:=),领外一种是最后计算赋值(=);遗憾的我们熟悉的编程赋值语法是这一种最后计算赋值=;这意味着如果赋值内容存在变量,而该变量在后面的脚本中,被改变了,那边这个赋值是采用最终值来计算赋值的;所以搞不清楚用法的话,最好变量赋值最好只做一次赋值,避免踩坑

  • 变量的使用
    make中的变量采用$()的方式使用,如下所示
build: $(objs)
    g++ $(objs) -o app

变量的其他用法

$^ 表示所有的依赖文件

$@ 表示生成的目标文件

$< 代表第一个依赖文件

  • 一些常用的全局变量

这些变量与前面自定义的变量本质一样,都是可定义修改的,只不过这些变量全局的环境变量,可全局使用;

CFLAGSCXXFLAGSCPPFLAGS

选项 说明
-c 用于把源码文件编译成 .o 对象文件,不进行链接过程
-o 用于连接生成可执行文件,在其后可以指定输出文件的名称
-g 用于在生成的目标可执行文件中,添加调试信息,可以使用GDB进行调试
-Idir 用于把新目录添加到include路径上,可以使用相对和绝对路径,“-I.”、“-I./include”、“-I/opt/include”
-Wall 生成常见的所有告警信息,且停止编译,具体是哪些告警信息,请参见GCC手册,一般用这个足矣!
-w 关闭所有告警信息
-O 表示编译优化选项,其后可跟优化等级0\1\2\3,默认是0,不优化
-fPIC 用于生成位置无关的代码
-v (在标准错误)显示执行编译阶段的命令,同时显示编译器驱动程序,预处理器,编译器的版本号

LDFLAGS

选项 说明
-llibrary 链接时在标准搜索目录中寻找库文件,搜索名为liblibrary.a 或 liblibrary.so
-Ldir 用于把新目录添加到库搜索路径上,可以使用相对和绝对路径,“-L.”、“-L./include”、“-L/opt/include”
-Wl,option 把选项 option 传递给连接器,如果 option 中含有逗号,就在逗号处分割成多个选项
-static 使用静态库链接生成目标文件,避免使用共享库,生成目标文件会比使用动态链接库大

LIBS
如: LIBS = -lpthread -lm -lpthread -liconv

2、函数

make 中的函数用于处理 Makefile 文件中的文本,例如:计算操作的文件列表,“菜谱”中使用的命令等。

  • 函数的调用
    函数的调用与变量的使用有点像,格式如下所示:
$(function arguments)

例如常用的函数实例

SRC = $(wildcard *.cpp)
OBJ = $(patsubst %.cpp, %.o, $(SRC))
build:
	@echo 
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值