gcc安装与基本用法

admin
admin 2019年04月10日
  • 在其它设备中阅读本文章

安装

Linux 系统下可以直接使用包管理器(apt,yum,pacman 等) 搜索 gcc 并安装

$ sudo apt install gcc
$ sudo pacman -S gcc
$ sudo yum install gcc

查看帮助

使用 gcc --help 可以查看简单的帮助说明,部分 gcc 帮助:

$ gcc --help
用法:gcc [选项] 文件...
选项:
  -specs=<文件>            用 <文件> 的内容覆盖内建的 specs 文件。
  -std=<标准>              假定输入源文件遵循给定的标准。
  --sysroot=<目录>         将 <目录> 作为头文件和库文件的根目录。
  -B <目录>                将 <目录> 添加到编译器的搜索路径中。
  -v                      显示编译器调用的程序。
  -E                      仅作预处理,不进行编译、汇编或链接。
  -S                      编译到汇编语言,不进行汇编和链接,
  -c                      编译、汇编到目标代码,不进行链接。
  -o <文件>                输出到 <文件>。
  -shared                 生成一个共享库。
  -w                      禁止所有警告信息.
  -Wall                   开启所有警告信息

编译程序

gcc 是 c 语言编译器,编译出一个可执行程序需要四步:

  1. 预处理 (preprocessing),预处理后的代码送往标准输出,可以使用 - o 选项输出到指定文件
  2. 编译 (compilation),生成汇编语言文件,在当前目录下生成同名的.s 文件
  3. 汇编 (assembly),输出对应于源文件的目标文件,在当前目录下生成同名的.o 文件
  4. 连接 (linking). 把多个目标文件连接成一个可执行程序,在当前目录下生成 a.out 文件

注意:.c 文件到可执行程序 bin 的流程,.c -->.s -->.o -->bin,可以使用 - o 定义输出文件位置

分步编译程序
$ gcc -E hello.c -o hello.i
$ gcc -S hello.i -o hello.s
$ gcc -c hello.s -o hello.o
$ gcc hello.o -o hello

直接编译程序
$ gcc hello.c -o hello 

如果有很多文件,一般情况下是先编译为目标文件,再连接为可执行程序

$ gcc -c hello.c a.c b.c
$ gcc hello.o a.o b.o -o hello

生成静态库

实际上是一些.o 文件通过 ar 打包而成的

  • 生成 test.o 目标文件
  • 使用 ar 将 test.o 打包成 libtest.a 静态库
$ gcc -c test.c -o test.o
$ ar rcs -o libtest.a test.o
  • 创建动态库
  • 使用参数 -fPIC 参数生成 test.o 目标文件,该参数用于生成位置无关代码
  • 使用 -shared 参数生成动态库
//分步生成
$ gcc -c -fPIC -o test.o test.c
$ gcc -shared -o libmyshare.so test.o

//一步生成
$ gcc -shared -fPIC -o libmyshare.so test.c

连接静态库或者动态库

两种库连接方式一致,使用 -lLIBRARY 指定要连接的库,使用 -LDIRECTORY 指定库的路径, 另外可以把库文件视为目标文件一起编译程序

$ gcc hello.c -L. -ltest -o hello
$ gcc hello.c libtest.so -o hello

需要注意的问题

  1. 如果指定的库目录下存在同名的动态库与静态库,默认使用动态库,增加选项 -static 可以使用静态库。
  2. 静态库要放到源文件后面声明,不然连接会出错,提示找不到(undefined reference to "xxx")。
  3. 使用 ldd < 文件 > 可以查看程序运行依赖的动态库。
  4. 执行含有动态库编译而成的程序需要加载动态库,有三个办法:把动态库所在的路径加入到环境变量 LD_LIBRARY_PATH;拷贝或者创建软连接到系统的库目录 /usr/lib/(不推荐);在 /etc/ld.so.conf.d/ 下新建一个文件把动态库路径写进去。
//强制连接静态库
$ gcc -static hello.c -L. -ltest -o hello
//错误的静态库引用(放到源文件前面)
$ gcc -static -L. -ltest hello.c -o hello
//查看程序依赖的动态库
$ ldd hello
//修改LD_LIBRARY_PATH环境变量,绝对路径
$ export LD_LIBRARY_PATH="/home/yi/foobar"
//使/etc/ld.so.conf.d/配置的动态库路径生效
$ sudo ldconfig -v