GCC 编译和链接多个文件

GCC 编译和链接多个文件

编译多个源代码文件会生成多个目标文件,每个目标文件都包含一个源文件的机器码和相关数据的符号表。除非使用 -c 选项指示 GCC 只编译不链接,否则 GCC 会使用临时文件作为目标文件输出:

$ gcc -c function_printf.c
$ gcc -c hello_world.c
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 16
drwxrwxr-x 2 strong strong 4096 Sep  4 20:57 ./
drwxrwxr-x 6 strong strong 4096 Sep  4 20:16 ../
-rw-rw-r-- 1 strong strong  452 Sep  4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong  503 Sep  4 20:18 hello_world.c
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ gcc -c function_printf.c
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ gcc -c hello_world.c
hello_world.c: In function ‘main’:
hello_world.c:15:5: warning: implicit declaration of function ‘function_printf’ [-Wimplicit-function-declaration]
     function_printf();
     ^
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 24
drwxrwxr-x 2 strong strong 4096 Sep  4 20:57 ./
drwxrwxr-x 6 strong strong 4096 Sep  4 20:16 ../
-rw-rw-r-- 1 strong strong  452 Sep  4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 1528 Sep  4 20:57 function_printf.o
-rw-rw-r-- 1 strong strong  503 Sep  4 20:18 hello_world.c
-rw-rw-r-- 1 strong strong 1592 Sep  4 20:57 hello_world.o
strong@foreverstrong:~/ForeverStrong/hello_world$ 

这些命令会在当前目录中生成两个目标文件,分别是 function_printf.o 和 hello_world.o。把两个源文件名放在同一个 GCC 命令中,也可以获得同样的结果:

$ gcc -c function_printf.c hello_world.c
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 16
drwxrwxr-x 2 strong strong 4096 Sep  4 20:58 ./
drwxrwxr-x 6 strong strong 4096 Sep  4 20:16 ../
-rw-rw-r-- 1 strong strong  452 Sep  4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong  503 Sep  4 20:18 hello_world.c
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ gcc -c function_printf.c hello_world.c
hello_world.c: In function ‘main’:
hello_world.c:15:5: warning: implicit declaration of function ‘function_printf’ [-Wimplicit-function-declaration]
     function_printf();
     ^
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 24
drwxrwxr-x 2 strong strong 4096 Sep  4 20:58 ./
drwxrwxr-x 6 strong strong 4096 Sep  4 20:16 ../
-rw-rw-r-- 1 strong strong  452 Sep  4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 1528 Sep  4 20:58 function_printf.o
-rw-rw-r-- 1 strong strong  503 Sep  4 20:18 hello_world.c
-rw-rw-r-- 1 strong strong 1592 Sep  4 20:58 hello_world.o
strong@foreverstrong:~/ForeverStrong/hello_world$

实际上编译器通常每次只会被调用来完成一件小型任务。大的程序包含许多源文件,在开发期间必须被编译、测试、编辑,然后再编译,很少会有在创建中的修改行为 (会影响所有的源文件)。为了节省时间,可以使用 make 控制创建过程,由它调用编译器重新编译,而且只编译比对应的最新源文件旧的那些目标文件。

一旦所有当前源文件都被编译为目标文件,就可以使用 GCC 来链接它们:

$ gcc function_printf.o hello_world.o -o app.out -lm
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 24
drwxrwxr-x 2 strong strong 4096 Sep  4 20:58 ./
drwxrwxr-x 6 strong strong 4096 Sep  4 20:16 ../
-rw-rw-r-- 1 strong strong  452 Sep  4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 1528 Sep  4 20:58 function_printf.o
-rw-rw-r-- 1 strong strong  503 Sep  4 20:18 hello_world.c
-rw-rw-r-- 1 strong strong 1592 Sep  4 20:58 hello_world.o
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ gcc function_printf.o hello_world.o -o app.out -lm
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 36
drwxrwxr-x 2 strong strong 4096 Sep  4 20:59 ./
drwxrwxr-x 6 strong strong 4096 Sep  4 20:16 ../
-rwxrwxr-x 1 strong strong 8688 Sep  4 20:59 app.out*
-rw-rw-r-- 1 strong strong  452 Sep  4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 1528 Sep  4 20:58 function_printf.o
-rw-rw-r-- 1 strong strong  503 Sep  4 20:18 hello_world.c
-rw-rw-r-- 1 strong strong 1592 Sep  4 20:58 hello_world.o
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ ./app.out 
!!!Hello Printf!!!
!!!Hello World!!!
strong@foreverstrong:~/ForeverStrong/hello_world$

GCC 假设扩展名为 .o 的文件是要被链接的目标文件。

1. 混合输入类型

可以在 GCC 命令行中混合使用其他输入文件类型。如果编译器不能按照请求处理指定的文件,那么它会忽略它们。

$ gcc hello_world.c function_printf.o -o app.out -lm
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 20
drwxrwxr-x 2 strong strong 4096 Sep  4 21:04 ./
drwxrwxr-x 6 strong strong 4096 Sep  4 20:16 ../
-rw-rw-r-- 1 strong strong  452 Sep  4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 1528 Sep  4 20:58 function_printf.o
-rw-rw-r-- 1 strong strong  503 Sep  4 20:18 hello_world.c
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ gcc hello_world.c function_printf.o -o app.out -lm
hello_world.c: In function ‘main’:
hello_world.c:15:5: warning: implicit declaration of function ‘function_printf’ [-Wimplicit-function-declaration]
     function_printf();
     ^
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ ll
total 32
drwxrwxr-x 2 strong strong 4096 Sep  4 21:05 ./
drwxrwxr-x 6 strong strong 4096 Sep  4 20:16 ../
-rwxrwxr-x 1 strong strong 8688 Sep  4 21:05 app.out*
-rw-rw-r-- 1 strong strong  452 Sep  4 20:18 function_printf.c
-rw-rw-r-- 1 strong strong 1528 Sep  4 20:58 function_printf.o
-rw-rw-r-- 1 strong strong  503 Sep  4 20:18 hello_world.c
strong@foreverstrong:~/ForeverStrong/hello_world$ 
strong@foreverstrong:~/ForeverStrong/hello_world$ ./app.out 
!!!Hello Printf!!!
!!!Hello World!!!
strong@foreverstrong:~/ForeverStrong/hello_world$

借助于这个命令,假设指定的文件都存在,GCC 会编译和汇编 hello_world.c,汇编 function_printf.o,并且链接库文件 libm.a。

2. 文件类型

编译器支持许多和 C 语言程序相关的扩展名。

扩展名 (后缀) 说明:
.c - C 程序源代码,在编译之前要先进行预处理。
.i - C 程序预处理输出,可以被编译。
.h - C 程序头文件。(为了节省时间,许多源文件会包含相同的头文件,GCC 允许事先编译好头文件,称为预编译头文件,它合适情况下自动被用于编译。)
.s - 汇编语言。
.S - 有 C 命令的汇编语言,在汇编之前必须先进行预处理。

GCC 也支持以下扩展名:.ii、.cc、.cp、.cxx、.cpp、.CPP、.c++、.C、.hh、.H、.m、.mi、.f、.for、.FOR、.F、.fpp、.FPP、.r、.ads 和 .adb。这些文件类型涉及 C++、Objective-C、Fortran 或 Ada 等程序的编译。使用其他扩展名的文件会被视为对象文件,以作为链接之用。

如果使用其他命名惯例为输入文件命名,可以使用 -x file_type 选项来指示 GCC 应该如何对待这些文件。file_type 必须是下面其中之一:c、c-header、cpp-output、assembler (表示该文件包含汇编语言)、assembler-with-cpp 或 none。

在命令行中,-x 后面所列的所有文件都会被视为所指定的类型。如果想改变类型,可以再次使用 -x。如下例所示:

$ gcc -o bigprg mainpart.c -x assembler trickypart.asm -x c otherpart.c

可以在同一个命令行中多次使用 -x 选项,以指示不同类型的文件。-x none 选项会全部取消这些指示,后续文件会按照 GCC 默认规则解释它们的扩展名。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yongqiang Cheng

梦想不是浮躁,而是沉淀和积累。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值