gcc

编译的过程

写个 hello.c 代码。

  1. #include <stdio.h>
  2. #define STR "hello world\n"
  3. void main() {
  4. printf(STR);
  5. }

第一步:预处理(preprocess)

其实就是以下三个动作:

  1. 头文件展开;
  2. 宏定义直接替换;
  3. 条件编译不成立就去掉。
    1. gcc -E hello.c -o hello.i

    第二步:编译(compile)

    转换成汇编语言。
    1. gcc -S hello.i -o hello.s

    第三步:汇编(assemble)

    转换成二进制(ELF relocatable)。
    1. gcc -c hello.s -o hello.o

    第四步:链接(link)

    具体分为动态链接和静态链接。
    1. # 动态链接
    2. gcc hello.o -o hello
    3. # 静态链接
    4. gcc hello.o -o hello -static

    静态库制作

    写一个加法函数。
    1. int add(int a, int b) {
    2. return a+b;
    3. }
    编译成 .o。
    1. gcc -c add.c -o add.o
    制作成静态库。
    1. ar rcs libadd.a add.o
    编写测试代码。
    1. #include <stdio.h>
    2. void main(){
    3. printf("%d", add(1,2));
    4. }
    编译成可执行文件。
    1. #写法一
    2. gcc test.c -o test libadd.a
    3. #写法二
    4. gcc test.c -o test -static -ladd -L ./
    执行。
    1. ./test
    2. 3

    动态库制作

    写一个加法函数。
    1. int add(int a, int b) {
    2. return a+b;
    3. }
    编译成 .o。
    1. gcc -c add.c -o add.o -fPIC
    制作成动态库。
    1. gcc -shared -o libadd.so add.o
    上面两步也可以直接从源文件一步到位。
    1. gcc -fPIC -shared -o libadd.so add.c
    编写测试代码。
    1. #include <stdio.h>
    2. void main(){
    3. printf("%d", add(1,2));
    4. }
    编译成可执行文件。
    1. gcc test.c -o test -ladd -L ./
    执行发现报错。
    1. ./test
    2. error while loading shared libraries: libadd.so:
    3. cannot open shared object file: No such file or directory
    因为执行的时候找不到指定的动态库。
    那把 libadd.so 放在执行时的动态库默认搜索路径下,比如 /lib64
    1. cp libadd.so /lib64
    再次执行就成功了。
    1. ./test
    2. 3
    查看二进制文件的链接信息,也可以发现 libadd.so 生效了。
    1. ldd test
    2. linux-vdso.so.1 => (0x00007ffe0f597000)
    3. libadd.so => /lib64/libadd.so (0x00007fa5ab29f000)
    4. libc.so.6 => /lib64/libc.so.6 (0x00007fa5aaed1000)
    5. /lib64/ld-linux-x86-64.so.2 (0x00007fa5ab4a1000)