0


2023-11-17 VsCode使用makefile进行多文件编译


点击 <C 语言编程核心突破> 快速C语言入门


VsCode使用makefile进行多文件编译


前言

要解决问题: C或C++可以多文件编译, 意味着需要进行代码组织, 为了方便多文件编译, gnu开发了make工具, 但问题是这简直又是一种编程语言, 为了解决一个问题, 又产生另一个问题. 在一个问题回答中, 我了解了作为新手的我们, 对make是如此困惑.

想到的思路: 从一个最简单的多文件编译, 简述makefile的编写, 组织C文件.

其它的补充: 需要更系统的学习, 可以查看陈皓巨佬的相关文章<跟我一起写makefile>.


一、一个简单的多文件示例

一个问题, makefile文件中VPATH路径无法找到, 本来十分简单, 但回答搞得可说乱七八糟, 可以想见, 大家对

makefile

是如此的不熟悉,

一个有三个文件夹, 若干个

.c

文件的小项目, 要用

makefile

组织编译, 我根据这个题目, 模拟了一下:

项目文件

三个文件夹, 分别有一个

c

文件, 可能含有一个头文件, 文件的名称和文件夹的名称是一致的, 当然也可以不一致, 这没有关系.

现在编写makefile, 将上述文件夹中的所有文件组织为一个名为

main

的可执行程序.

二、makefile基本语法

既然是用于编译, makefile自然需要提供一些信息, 包括:

  1. 编译器, 一般是gcc, 或clang
  2. 目录信息, 让make自动寻找文件, 省的手动一个个设置
  3. 源文件名
  4. 最终编译出来的目标
  5. 编译依赖的文件
  6. 执行模板
  7. 如果头文件和源文件不在一起, 需指定头文件夹位置
  8. 如果需要引入库文件, 则需要指定库文件夹位置, 以及库文件

下面就是一个编写好的makefile, 用于处理我们上面提到的多文件编译, 大家先看一下.

CC := clang #编译器

VPATH := IO_tools menu shapes #自动寻找的目录

SRC := IO_tools.c menu.c shapes.c #源文件

OBJ :=$(SRC:.c=.o)#目标文件, 由.c更换为.o

EXEC := main #执行文件

all: $(EXEC)#目标all, 依赖main$(EXEC):$(OBJ)#main依赖.o文件, $^是所有依赖文件 $@是目标文件$(CC) $^ -o$@

%.o: %.c #将所有的.c文件编译为.o文件, $<是第一个依赖文件, -c是生成.o文件$(CC)-c $<-o$@

clean:
    rm-rf$(OBJ)$(EXEC)#E:\msys64\clang64\bin\mingw32-make.exe all -f E:\clangC++\answer\C\make\Makefile -C E:\clangC++\answer\C\make\

由于只是基础普及, 示例没有放函数等复杂应用, 对于小项目, 这个就基本够了.

我们一条一条说:

首先是变量赋值, 很遗憾, 你必须将

makefile

语法当成一门编程语言, 因为这样比较好理解.

CC

一般是编译器变量名,

:=

带冒号的赋值符号意味着非递归赋值, 也就是现在赋值是啥就是啥.

不带冒号的赋值, 则可能涉及递归, 这个不阐述, 暂时用不到.

我们给

CC

赋值为

clang

, 用clang进行编译.

VPATH

是一个特殊变量, 代表

make

要搜寻的文件夹, 我们将需要编译的文件所在文件夹

IO_tools menu shapes

赋值给它.

然后make会帮我们在这些文件夹中寻找我们要编译的源文件.

SCR

这个变量, 我们给它赋值为所有需要编译的源文件

IO_tools.c menu.c shapes.c
OBJ

这个变量, 我们给他赋值为源文件编译后的

.o

文件, 也就是还未链接的中间文件.

$(SRC:.c=.o)

大家看, 这是一个变量引用的语法, 它引用变量

SRC

, 需要用

$

()

括号将变量包裹,

.c=.o

这个操作, 是将

SRC

中的

.c

结尾变成

.o

结尾, 于是

OBJ

就应该是

IO_tools.o menu.o shapes.o
EXEC := main

这句很好懂, 就是最终的可执行文件

EXEC

的名字叫

main
all: $(EXEC)

这一句是

makefile

的精髓, 意思很简单, 生成的目标叫all, 这也是默认最终目标, 它依赖变量

EXEC

也就是

main

然后递归,

main

现在作为目标, 又需要

OBJ

这些文件来链接, 于是就有

$(EXEC): $(OBJ)

这个语句.

注意, 下面是执行编译命令模板,

 $(CC) $^ -o $@

这个前面空白必须是一个

tab

符号, 否则无法编译, 这句命令的意思是

clang IO_tools.o menu.o shapes.o -o main

这就是模板完成的语句, 我们说明一下

$(CC)

是编译器, 我们这里就是

clang

, 这个符号

$^

代表所有依赖项, 也就是所有的

.o

文件, 这个

-o

是编译选项, 输出编译结果名 , 这个符号

$@

是目标项, 也就是

main

将所有模板扩充之后就是我们的编译命令行.

之后继续递归,

%.o: %.c

, 所有

.o

文件依赖对应的

.c

文件, 这里的百分号

%

是一个识别模式,

代表在

makefile

文件中查找所有前面可以是任意字符组成, 最后必须是

.o

的文件名, 除了后缀不同, 目标和依赖这两个文件的名字是一致的.

将所有的

.c

文件编译为

.o

文件,

$<

是第一个依赖文件,

-c

是生成

.o

文件

 $(CC) -c $< -o $@

是编译命令模板,

-c

是编译但不链接, 这个符号

$<

是依赖的第一项, 也就是

.c

文件,

因为一对一对应, 所以没必要用全部依赖. 这个模板扩展之后, 是三个编译命令行, 如

clang -c menu/menu.c -o menu.o

,

注意, 因为我们使用了

VPATH

这个变量, make自动帮我们查找

.c

文件的路径, 并补全,

但开头提到的makefile文件中VPATH路径无法找到, 问题就在于不是使用模板编译命令, 而是直接写死了命令行, 导致

VPATH

这个设置无法使用.

最后是

clean:

, 这是删除所有生成的文件, 包括中间文件以及最终的可执行文件.

 rm -rf $(OBJ) $(EXEC)

这是执行语句, 记住前面必须是

tab

,

rm -rf

这个是大家熟悉的

Linux

命令, 强制删除文件夹及文件.

三、VsCode使用makefile

为了在

vscode

中方便使用

makefile

组织项目, 可以下载插件, 微软官方的

VS Code Makefile Tools

, 编写

makefile

后可以一件运行, 以及生成各种子目标.

make tools

以及

Makefile-Creator

作者是

Antoine aka. Zenor

, 可以通过右键文件夹, 自动生成

makefile

模板.
在这里插入图片描述

CXX = g++
CXXFLAGS =-Wall-Werror-Wextra-pedantic-std=c++17 -g-fsanitize=address
LDFLAGS =-fsanitize=address

SRC = 
OBJ =$(SRC:.cc=.o)
EXEC = main

all: $(EXEC)$(EXEC):$(OBJ)$(CXX)$(LDFLAGS)-o$@$(OBJ)$(LBLIBS)

clean:
    rm-rf$(OBJ)$(EXEC)

之后根据需要进行调整.


总结

到这里, 基础普及知识就完成了, 对于小项目, 可以说基本能覆盖百分之八十了, 大项目, 还是自己去学吧, 网上的内容很多, 推荐开头说的陈皓巨佬的文章, 我们十分怀念这位前辈, 他所留下的文字, 始终指引着一批批程序员.

最后, 如果你觉得

makefile

很麻烦, 可以看看

xmake

, 这个国产的项目工具, 一定能找到惊喜.


点击 <C 语言编程核心突破> 快速C语言入门


标签: vscode makefile

本文转载自: https://blog.csdn.net/m0_54206076/article/details/134458165
版权归原作者 不停感叹的老林_<C 语言编程核心突破> 所有, 如有侵权,请联系我们删除。

“2023-11-17 VsCode使用makefile进行多文件编译”的评论:

还没有评论