0%

C/C++项目构建教程

  • 构建工具有助于管理和简化构建过程,自动化的构建程序,多用于大型和复杂的项目中。
  • 本文介绍Makefile、CMake、XMake等构建工具。
  • 本文将以C/C++的源码作为基础,所以必然涉及一些关于C/C++的编译的知识,关于这方面的内容,还请各位自行学习。😘

概述

  • 运行大型项目需要确定不同代码模块或库文件如何编译链接在一起,这需要开发者用项目构建工具来实现。
  • 本文所述构建工具,如Makefile、CMake、XMake等,是为了简化编译和链接过程,以下是使用它们的一些主要原因:
    • 自动化:构建工具可以自动执行编译、链接和其他构建步骤,无需手动运行每个步骤。
    • 依赖管理:构建工具可以跟踪源文件之间的依赖关系,并确保在源文件更改时只重新编译必要的文件。
    • 跨平台:构建工具可以生成针对不同平台和编译器的构建文件,使得源代码可以在不同的环境中构建。
    • 可扩展:对于大型项目,构建工具可以帮助组织和管理多个源文件和库,使得构建过程更加可控。
    • 一致性:构建工具可以确保每次构建的过程都是一致的,无论是在哪个平台或环境中。
    • 集成其他工具:构建工具可以与其他工具集成,如测试框架、包管理器等,提供更完整的构建解决方案。

Make

Makefile是什么

  • Make: 是最早的构建工具之一,它使用Makefile来描述如何构建你的项目。
  • Makefile文件按照特定语法进行编写,用以说明如何编译各个源文件链接生成可执行文件,同时定义了源文件之间的依赖关系
  • 尽管Makefile的语法可能有些复杂,但它在C++社区中仍然广泛使用。

Makefile工作流程

1.查找当前目录下的Makefile文件  
2.初始化文件中的变量  
3.分析Makefile中的所有规则  
4.为所有的目标文件创建依赖关系  
5.根据依赖关系,决定哪些目标文件要重新生成  
6.执行生成命令

Makefile书写规范

1
2
目标文件:依赖文件列表
<Tab> 命令列表

目标文件(target)即为最终的可执行文件test(可自定义名称)
中间目标文件test1.o test2.o
每个目标文件和它的依赖文件用:隔开
每个.o文件都有一组依赖文件

调用make命令可输入:make target

如果省略target,make就将生成Makefile文件中定义的第一个目标

Makefile中的变量

Linux下的Makefile文件里面可能会使用非常多的变量,远不像前面示例Makefile文件那样简单。这些变量对大小写敏感,一般使用大写宇母

定义变量的语法:VARNAME=string

使用时,把变量用括号括起来,并在前面加上$符号,就可以引用变量的值:$(VARNAME)

Makefile中的变量分为

  • 用户自定义变量
  • 预定义变量
  • 自动变量
  • 环境变量

Makefile中的隐含规则

一些默认的动作,称作隐含规则的内置的规则,这些规则告诉make当用户没有完整地给出某些命令的时候,应该怎样执行。

在我们使用Makefile时,有一些我们会经常使用,而且使用频率非常高的东西,比如,我们编译C/C++的源程序为中间目标文件(Unix下是[.o]文件,Windows下是[.obj]文件)。这里讲述的就是一些在Makefile中的“隐含的”,早先约定了的,不需要我们再写出来的规则。

“隐含规则”也就是一种惯例,make会按照这种“惯例”心照不喧地来运行,那怕我们的Makefile中没有书写这样的规则。例如,把[.c]文件编译成[.o]文件这一规则,你根本就不用写出来,make会自动推导出这种规则,并生成我们需要的[.o]文件。

Makefile的编写实例

现在有一个c程序,实现输入姓名,输入hello+用户的输入

共有以下文件:input.h input.c output.h output.c main.c

Makefile的编写如下

1
2
3
4
5
6
7
8
9
10
main:input.o output.o main.o
gcc -Wall -O -g -o main main.o input.o output.o
input.o:input.c input.h
gcc -Wall -O -g -o input.o input.c
output.o:output.c output.h
gcc -Wall -O -g -o output.o output.c
main.o:main.c input.h output.h
gcc -Wall -O -g -o main.o main.c
clean:
rm -rf test *.o

Makefile的简化

通过上面的代码我们可以发现,我们在编写Makefile文件的时候有大量重复语句,可以通过自定义变量自动变量隐含规则等方式简化

第一次优化:自定义变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CC=gcc
CFLAGS=-Wall -O -g
OBJ=input.o output.o main.o

main:$(OBJ)
$(CC) $(CFLAGS) -o main main.o input.o output.o
input.o:input.c input.h
$(CC) $(CFLAGS) -o input.o input.c
output.o:output.c output.h
$(CC) $(CFLAGS) -o output.o output.c
main.o:main.c input.h output.h
$(CC) $(CFLAGS) -o main.o main.c
clean:
rm -rf test *.o

通过自定义变量,我们将原本冗长的语句进行缩短

第二次优化:自动变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CC=gcc
CFLAGS=-Wall -O -g
OBJ=input.o output.o main.o

main:$(OBJ)
$(CC) $(CFLAGS) -o $@ $^
input.o:input.c input.h
$(CC) $(CFLAGS) -o $@ $^
output.o:output.c output.h
$(CC) $(CFLAGS) -o $@ $^
main.o:main.c input.h output.h
$(CC) $(CFLAGS) -o $@ $^
clean:
rm -rf test *.o

第三次优化:隐含规则

1
2
3
4
5
6
7
8
CC=gcc
CFLAGS=-Wall -O -g
OBJ=input.o output.o m

main:$(OBJ)
$(CC) $(CFLAGS) -o $@ $^
clean:
rm -rf test *.o

CMake

TBD……

XMake

TBD……

参考资料