gcc常用编译选项简介

时间:2022-03-01 09:13:27
  • 注:关于gcc的详细使用说明,请man gcc查阅

gcc是什么

gcc是GNU Compiler Collection的缩写,它包括C、C++、Objective-C、Fortran、Java、Ada和Go语言的库和前端。

gcc最初是给GNU操作系统编写的编译器,GUN系统是完全*开放的软件。GCC支持几乎所有的操作系统平台和硬件。

本文侧重点在于使用gcc编译linux下的c程序,其他平台/语言大同小异,举一反三。

使用gcc编译一个应用程序

如下一个简单的程序:

/* test.c */
#include <stdio.h>

int main(void)
{
    printf("hello world!\n");

    return 0;
}

使用gcc test.c 即可完成编译,生成的应用程序名字为a.out。也可以指定应用程序名:gcc -o test test.c

gcc的编译过程分为预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)四个阶段,可以分别使用gcc编译,此处略。

当需要编译多个源文件时,只需要在命令行的后面添加便可,gcc能够很好地管理这些源文件。

使用gcc参数发现程序中的错误

编译是生成应用程序的过程,同时也是对程序检验的过程。虽然警告不影响程序的编译,也可以生成应用程序,但很多项目都要求程序0警告,这样能够避免很多错误的发生。

-Wall

根据字面意思理解,打开“所有”的编译警告。确实,它是编译程序时的必选项,修正编译时产生的警告,是增强程序健壮性的重要一步。

This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros.

-Wextra

打开-Wall未打开的更多编译警告。

包括但不限于以下警告:

  • A pointer is compared against integer zero with <, <=, >, or >=.
  • (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
  • (C++ only) Ambiguous virtual bases.
  • (C++ only) Subscripting an array that has been declared register.
  • (C++ only) Taking the address of a variable that has been declared register.
  • (C++ only) A base class is not initialized in a derived class’s copy constructor.

-Werror

把警告当作错误来处理。此时,编译器遇到第一个警告时就会停下来,逐个修正警告后编译都会继续进行。

-g

打开gdb调试时使用的符号表。使用此编译选项后,可以使用gdb调试程序,非常方便好用。但是遇到比较复杂的错误,如栈信息被破坏的情况时,gdb也无能为力。

一般开发程序使用此编译选项,出厂程序不使用。

为程序指定头文件/库文件的索引位置

gcc的-I选项可以指定头文件的位置,在比较大的项目中经常使用。

gcc -o test test.c -I. 指定当前目录为头文件的索引目录。

在编译需要使用外部提供的库文件时,使用语法如下:
gcc -o test test.c -L. -ltest
即在当前目录下寻找名为libtest.so/libtest.a的库文件进行编译。

使用gcc编译库文件

使用gcc -shared -fPIC -o test test.c编译动态库文件。注意,此处的test.c不是开头给出的程序。

如果使用带有main函数的程序编译为动态库文件,执行该动态库文件时就会出现莫名其妙的错误,程序一执行即退出,让人摸不着头脑。
(有次在编译应用程序时不小心加了-shared选项,执行程序时立即莫名退出,使用各种调试手段都不生效,最后还是通过代码走查发现的问题)

使用ar -r libtest.a test.o 即可生成静态库文件,静态库文件在动态库文件在编译时使用方式类似。

总结

使用gcc编译程序时是非常灵活的,在项目中要多使用编译选项来编译调试程序,增加程序健壮性。