Skip to content

mac下编译C语言的几种方式 #4

@lucefer

Description

@lucefer

本期带来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 原生扩展打点基础。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions