学习一下Mac系统下C多文件链接

背景

起因

在学习《深入理解计算机系统》一书中讲解链接一章中,突然想试一下多文件进行链接,结果阻力不断,遇到了各种怪问题。

环境

mac版本:MacOs Big Sur 11.3
gcc版本:Apple clang version 12.0.5 (clang-1205.0.22.11)

过程

理想过程

#include <stdio.h>
#include "swap.c"

// main.c
void swaap();

int buf[2] = {1, 2};

int main() {
  printf("%d %d\n", buf[0], buf[1]);
  swap();
  printf("%d %d\n", buf[0], buf[1]);
}
// swap.c
extern int buf[];

int *bufp0 = &buf[0];
int *bufp1;

void swap()
{
  int temp;

  bufp1 = &buf[1];
  temp = *bufpp0;
  *bufp0 = *bufp1;
  *bufp1 = temp;
}
# shell中执行
gcc -o2 -g -o p main.c swap.c
# 等价于
cpp main.c main.i
cc1 main.i main.c -o2 -o main.s
as -o main.o main.s
cpp swap.c swap.i
cc1 swap.i swap.c -o2 -o swap.s
as -o swap.o swap.s
ld -o p main.o swap.o
./p

如果顺利的话应该一路直行下来没有什么问题,然而问题就是并不顺利。

真实过程

重复引用问题

当执行第一条gcc语句时,提醒我swap中的变量被重复引用两次。
错误展示
费了很多力气也没查到问题,最后我才意识到是因为我在main中include了swap,这个时候不需要进行多文件编译,将该语句注释掉后可顺利进行后续步骤。(或者直接改成单文件编译直接完成,从链接变成了包含)

.i生成问题

由于include了stdio.h导致无法正常生产.i文件,原因未知,取消掉之后能顺利生产.i文件

cc1无法使用问题

在mac中是没有cc1这个命令的,至于具体原因我也不太清楚,但是当前采取的方法是

# 将这部分代码
cpp main.c main.i
cc1 main.i main.c -o2 -o main.s
as -o main.o main.s
cpp swap.c swap.i
cc1 swap.i swap.c -o2 -o swap.s
as -o swap.o swap.s
# 化简为
gcc -c main.c
gcc -c swap.c

且此时可正常include stdio.h。
参考文章:
C语言(GCC)如何编译多个文件?
gcc参数中的-I, -L和-l
(其实最开始走了个弯路尝试把swap做成库,后来发现其实生产.o就可以进行链接了)

链接问题

执行最后的ld命令又出现了新的问题
问题
一开始认为和之前一样,是因为include了stdio的问题,尝试注释掉
又出现了新的问题又出现了新的问题。
经过查找是因为mac系统必须链接动态库,

#将连接命令改成
ld -macosx_version_min 11.0.1 -o b.out main.o swap.o -lSystem
# 但Big Sur系统有一个坑,必须进行修改成如下
ld -o b.out main.o swap.o -macosx_version_min 11.0.1 -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem

链接完成,且此时可以正常对stdio.h进行include。
参考文献:
MacOS Big Sur下使用nasm编写汇编程序

总结

对我当前的环境,最适合的命令方式为:

gcc -c main.c
gcc -c swap.c
ld -o b.out main.o swap.o -macosx_version_min 11.0.1 -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem

完成。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值