-
Notifications
You must be signed in to change notification settings - Fork 0
Description
本期带来mac下C语言的编译方法,C语言本不属于前端范畴,但是作为一个有追求的软件工程师,多掌握一些,更有助于我们很容易地阅读各种类库、框架的源码。
mac下编译C语言
编译过程如下:
1、预处理
使用 -E 生成 .i 文件。
如gcc -E a.c -o a.i
2、汇编
使用 -S 生成 .s 文件。
如gcc -S a.i -o a.s
3、编译
使用 -c 生成 .o 文件。
如 gcc -c a.s -o a.o
4、链接
首先明白一个概念,什么是链接?
源文件编译成功后,会生成一个对应的 .o 目标文件,这就是一个二进制文件,但是,还是不能运行。目标文件不能运行的主要原因有2个:
1、 在开发过程中,不可能将所有的代码都写在一个.c文件中,为了模块化开发,一般会将不同的功能写到不同的源文件中。源文件编译之后,每个源文件都有对应的 .o 文件,比如 a.c 生成了 a.o、b.c 生成了 b.o,这些 .o 文件都不能单独运行,它们之间都有密不可分的关系,需要将所有相关联的 .o 目标文件组合在一起。
2> 除开组合所有的目标文件之后,还需要将C语言的函数库包含进来,才能生成可执行文件。
将所有相关联的 .o 目标文件、以及C语言函数库组合在一起生成可执行文件的过程,我们称为【链接】。
#####链接命令:
使用 -o 生成可执行文件,默认为a.out 。
//默认生成 a.out
gcc test.o
指定名字:
//生成test可执行文件,可以有后缀,也可无后缀。
gcc test.o -o test
mac下编译多个文件
在开发过程中,不可能将所有的代码都写在一个.c文件中,为了模块化开发,一般会将不同的功能写到不同的源文件中。如果要同时编译多个源文件,这样写:gcc -c a.c b.c c.c,源文件编译之后,每个源文件都会生成对应的 .o 文件,比如 a.c 生成了 a.o、b.c 生成了 b.o。
mac下编译多个文件有三种方式。
- 直接编译
- 动态链接库
- 静态库
直接编译方法
1、首先入口文件要先 include 其他依赖文件的头文件,如果没有声明头文件也可以,但是要在入口文件中声明依赖文件的函数或者变量。
避免入口文件中
没有声明就使用未定义的函数导致的报错 。
//main.c文件
//声明依赖的函数。
int add(int x,int y);
或者
#include "add.h"
int main() {
int p = add(30,50);
printf('%d',p);
}
// add.h 头文件
//add.c文件
int add (x,y){
return x+y;
}注意 #include "add.h" 和 #include <add.h> 两种引用方式的区别:
"add.h" 是先搜索本地目录,如果没有,才会搜索系统目录。
<add.h>则不搜索本地目录,而是搜索系统目录。
2、执行 gcc a.c b.c c.c main.c -o test
即可生成可执行文件test。
动态共享库
假设有三个库文件a.c,b.c,c.c 和一个入口文件 main.c。
动态共享库的方式:
1、先把三个文件a.c,b.c,c.c编译成动态共享库
gcc -shared -fPIC a.c -o a.so
gcc -shared -fPIC b.c -o b.so
gcc -shared -fPIC c.c -o c.so
2、main.c中要引入头文件或者声明外部函数
3、链接入口文件main.c和动态库。
gcc main.c -L. -la -lb -lc -o test好处是如果b.c有更新,则不用链接入口文件和动态库,只需要重新生成b.so即可。
静态库
假设有三个库文件a.c,b.c,c.c和一个入口文件 main.c
静态库的链接方法为:
1、先把三个库文件编译成a.o,b.o,c.o。
2、打包目标文件
ar -r liball.a a.o b.o c.o #这里的ar相当于tar的作用,将多个目标.o文件打包。程序 ar 配合参数 -r 创建一个新库 liball.o 文件,并将命令行中列出的文件打包入其中。这种方法,如果 liball.o 已经存在,将会覆盖现在文件,否则将新创建。
3、链接静态库
gcc main.c liball.o -L. -o main
以上就是 mac 下编译 C 文件的三种方式。我们可以先从这三种简单方式入手,为以后边写 nodejs 原生扩展打点基础。