gcc和makefile用法总结(建议收藏)_gcc makefile(2),2024年最新10年阿里开发架构师经验分享

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Golang全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注go)
img

正文

本篇博文不是详细的gcc和makefile用法详解,而是基于实际使用过程中需要掌握的gcc和makefile的用法。其实是在makefile中需要用到的gcc.


1. 用GCC制作静态链接库

本节先给大家讲解静态链接库的创建和使用,至于如何创建动态链接库,会在下一节做详细介绍。

假设当前有一个 C 语言项目,其目录结构如下所示:

demo项目
├─ headers
│ └─ test.h
└─ sources
├─ add.c
├─ sub.c
├─ div.c
└─ main.c

其中,headers 用于表示该项目拥有的所有头文件;sources 表示该项目拥有的所用源文件,读者可按照此目录结构构建 demo 项目,也可以将所有文件统一放置在 demo 项目下,本节选择的是后者,即将所有文件统一放置在 demo 目录下。

可以看到,该项目中包含 1 个头文件( .h ),4 个源文件( .c ),它们各自包含的代码如下所示:

[root@bogon demo]# ls <- demo 目录结构
add.c div.c main.c sub.c test.h
[root@bogon demo]# cat test.h <- test.h 文件内容
#ifndef _TEST_H
#define _TEST_H

int add(int a,int b);
int sub(int a,int b);
int div(int a,int b);

#endif

[root@bogon demo]# cat add.c <- add.c 文件内容
#include “test.h”
int add(int a,int b)
{
return a + b;
}
[root@bogon demo]# cat sub.c <- sub.c 文件内容
#include “test.h”
int sub(int a,int b)
{
return a - b;
}
[root@bogon demo]# cat div.c <- div.c 文件内容
#include “test.h”
int div(int a,int b)
{
return a / b;
}
[root@bogon demo]# cat main.c <- main.c 文件内容
#include <stdio.h>
#include “test.h” //必须引入头文件
int main(void)
{
int m, n;
printf(“Input two numbers: “);
scanf(”%d %d”, &m, &n);
printf(“%d+%d=%d\n”, m, n, add(m, n));
printf(“%d-%d=%d\n”, m, n, sub(m, n));
printf(“%d÷%d=%d\n”, m, n, div(m, n));
return 0;
}

整个项目的逻辑很简单,其中 add.c、sub.c 和 div.c 这 3 个文件中各包含一个函数,分别实现将两个整数做相加、相减和除法操作,而 test.h 仅包含这 3 个函数的声明部分,main.c 是主程序文件,其通过引入 test.h 头文件调用了 3 个函数,从而分别完成了对用户输入的 2 个整数做相加、相减以及除法操作。

对于编译、运行 demo 项目,我们可以直接使用 gcc 命令完成:

[root@bogon demo]# gcc main.c add.c sub.c div.c -o main.exe
[root@bogon demo]# ls
add.c div.c main.c main.exe sub.c test.h
[root@bogon demo]# ./main.exe
Input two numbers: 10 2
10+2=12
10-2=8
10÷2=5

注意,由于在程序预处理阶段,GCC 编译器会自行处理各个 .c 文件内部引入的 .h 头文件(将 .h 文件中的代码直接拷贝到当前 .c 源文件中),因此编译运行 demo 项目时,我们只需要提供所有的源文件即可,不需要处理头文件。

注意,add.c、sub.c 和 div.c 这 3 个文件,其包含的都是一些功能模块(实现具体功能的函数),对于这样的源文件,只要我们愿意共享,每个人都可以直接用到自己的项目中。这就产生一个问题,如果仅希望别人使用我们实现的功能,但又不想它看到具体实现的源码,该怎么办呢?很简单,就是将它们加工成一个静态链接库。

静态链接库的创建

通过前面的学习我们知道,静态链接库其实就相当于压缩包,其内部可以包含多个源文件。但需要注意的是,并非任何一个源文件都可以被加工成静态链接库,其至少需要满足以下 2 个条件:

  • 源文件中只提供可以重复使用的代码,例如函数、设计好的类等,不能包含 main 主函数;
  • 源文件在实现具备模块功能的同时,还要提供访问它的接口,也就是包含各个功能模块声明部分的头文件。

显然对于 demo 项目中的 add.c、sub.c 以及 div.c 这 3 个源文件来说,以上 2 个条件都符合,因此都可以被加工成静态链接库。并且根据实际需要,我们可以将它们集体压缩到一个静态链接库中,也可以各自压缩成一个静态链接库。

将源文件打包为静态链接库的过程很简单,只需经历以下 2 个步骤:

  1. 将所有指定的源文件,都编译成相应的目标文件:

[root@bogon demo]# gcc -c sub.c add.c div.c
[root@bogon demo]# ls
add.c add.o div.c div.o main.c sub.c sub.o test.h

  1. 然后使用 ar 压缩指令,将生成的目标文件打包成静态链接库,其基本格式如下:

ar rcs 静态链接库名称 目标文件1 目标文件2 …

有关 ar 打包压缩指令,以及 rcs 各选项的含义和功能,感兴趣的读者可自行查找相关资料了解。这里需要重点说明的是,静态链接库的不能随意起名,需遵循如下的命名规则:

libxxx.a

Linux 系统下,静态链接库的后缀名为 .a;Windows 系统下,静态链接库的后缀名为 .lib。

其中,xxx 代指我们为该库起的名字,比如 Linux 系统自带的一些静态链接库名称为 libc.a、libgcc.a、libm.a,它们的名称分别为 c、gcc 和 m。

下面,我们尝试将 add.o、sub.o 和 div.o 打包到一个静态链接库中:

[root@bogon demo]# ar rcs libmymath.a add.o sub.o div.o
[root@bogon demo]# ls
add.c add.o div.c div.o libmymath.a main.c sub.c sub.o test.h

其中,libmymath.a 就是 add.o、sub.o 和 div.o 一起打包生成的静态链接库,mymath 是我们自定义的库名。

通过以上 2 步操作,我们就成功创建出了 libmymath.a 静态链接库。那么,该如何使用它呢?

静态链接库的使用

静态链接库的使用很简单,就是在程序的链接阶段,将静态链接库和其他目标文件一起执行链接操作,从而生成可执行文件。

以 demo 项目为例,首先我们将 main.c 文件编译为目标文件:

[root@bogon demo]# gcc -c main.c
[root@bogon demo]# ls
add.c div.c libmymath.a main.o sub.c
test.h add.o div.o main.c sub.o

在此基础上,我们可以直接执行如下命令,即可完成链接操作:

[root@bogon demo]# gcc -static main.o libmymath.a
[root@bogon demo]# ls
add.c a.out div.o main.c sub.c test.h
add.o div.c libmymath.a main.o sub.o

其中,-static 选项强制 GCC 编译器使用静态链接库。

注意,如果 GCC 编译器提示无法找到 libmymath.a,还可以使用如下方式完成链接操作:

[root@bogon demo]# gcc main.o -static -L /root/demo/ -lmymath
[root@bogon demo]# ls
add.c a.out div.o main.c sub.c test.h
add.o div.c libmymath.a main.o sub.o

其中,-L(大写的 L)选项用于向 GCC 编译器指明静态链接库的存储位置(可以借助 pwd 指令查看具体的存储位置); -l(小写的 L)选项用于指明所需静态链接库的名称,注意这里的名称指的是 xxx 部分,且建议将 -l 和 xxx 直接连用(即 -lxxx),中间不需有空格。

由此,就生成了 a.out 可执行文件:

[root@bogon demo]# ./a.out
Input two numbers: 10 2
10+2=12
10-2=8
10÷2=5


2. 用GCC制作动态链接库

前面章节中,给读者详细阐述了什么是库文件、什么是静态链接库和动态链接库,同时还介绍了手动创建静态链接库的过程。在此基础上,本节继续讲解动态链接库的创建和使用。

有关动态链接库,以及它的特性、和静态链接库的区别,读者可阅读《GCC使用静态链接库和动态链接库》一节做详细了解,这里不再做赘述。

为了方便读者更好地理解创建和使用动态链接库的过程,本节仍以在《静态链接库的创建和使用》一节中创建好的 demo 项目(一个 C 语言多文件项目)为例,如下是该目录的具体构成和相关源码:

[root@bogon demo]# ls <- demo 目录结构
add.c div.c main.c sub.c test.h
[root@bogon demo]# cat test.h <- test.h 文件内容
#ifndef _TEST_H
#define _TEST_H

int add(int a,int b);
int sub(int a,int b);
int div(int a,int b);

#endif

[root@bogon demo]# cat add.c <- add.c 文件内容
#include “test.h”
int add(int a,int b)
{
return a + b;
}
[root@bogon demo]# cat sub.c <- sub.c 文件内容
#include “test.h”
int sub(int a,int b)
{
return a - b;
}
[root@bogon demo]# cat div.c <- div.c 文件内容
#include “test.h”
int div(int a,int b)
{
return a / b;
}
[root@bogon demo]# cat main.c <- main.c 文件内容
#include <stdio.h>
#include “test.h” //必须引入头文件
int main(void)
{
int m, n;
printf(“Input two numbers: “);
scanf(”%d %d”, &m, &n);
printf(“%d+%d=%d\n”, m, n, add(m, n));
printf(“%d-%d=%d\n”, m, n, sub(m, n));
printf(“%d÷%d=%d\n”, m, n, div(m, n));
return 0;
}

动态链接库的创建

总的来说,动态链接库的创建方式有 2 种。

  1. 直接使用源文件创建动态链接库,采用 gcc 命令实现的基本格式如下:

gcc -fpic -shared 源文件名… -o 动态链接库名

其中,-shared 选项用于生成动态链接库;-fpic(还可写成 -fPIC)选项的功能是,令 GCC 编译器生成动态链接库(多个目标文件的压缩包)时,表示各目标文件中函数、类等功能模块的地址使用相对地址,而非绝对地址。这样,无论将来链接库被加载到内存的什么位置,都可以正常使用。

例如,由 demo 项目中的 add.c、sub.c 和 div.c 这 3 个源文件生成一个动态链接库,执行命令为:

[root@bogon demo]# ls
add.c div.c main.c sub.c test.h
[root@bogon demo]# gcc -fpic -shared add.c sub.c div.c -o libmymath.so
[root@bogon demo]# ls
add.c div.c libmymath.so main.c sub.c test.h

注意,动态链接库的命令规则和静态链接库完全相同,只不过在 Linux 发行版系统中,其后缀名用 .so 表示;Windows 系统中,后缀名为 .dll。

  1. 先使用 gcc -c 指令将指定源文件编译为目标文件。仍以 demo 项目中的 add.c、sub.c 和 div.c 为例,先执行如下命令:

[root@bogon demo]# ls
add.c div.c main.c sub.c test.h
[root@bogon demo]# gcc -c -fpic add.c sub.c div.c
[root@bogon demo]# ls
add.c add.o div.c div.o main.c sub.c sub.o test.h

注意,为了后续生成动态链接库并能正常使用,将源文件编译为目标文件时,也需要使用 -fpic 选项。

在此基础上,接下来利用上一步生成的目标文件,生成动态链接库:

[root@bogon demo]# gcc -shared add.o sub.o div.o -o libmymath.so
[root@bogon demo]# ls
add.c add.o div.c div.o libmymath.so main.c sub.c sub.o test.h

以上 2 种操作,生成的动态链接库是完全一样的,读者任选一种即可。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
.o sub.o div.o -o libmymath.so
[root@bogon demo]# ls
add.c add.o div.c div.o libmymath.so main.c sub.c sub.o test.h

以上 2 种操作,生成的动态链接库是完全一样的,读者任选一种即可。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-KEX0YXJM-1713302895721)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值