zoukankan      html  css  js  c++  java
  • gcc编译 参数(转)

     生成一个可执行的文件通常需要经过以下几个步骤:

       1.

          预处理你的源代码,去掉注释,以及其他技巧性的工作就像在 C 中展开宏。
       2.

          检查代码的语法看你是否遵守了这个语言的规则。如果没有,编译器会给出 警告。
       3.

          把源代码转换为汇编语言 ── 和机器代码很相似, 但是在一定情况下我们仍然可以理解。 [1]
       4.

          把汇编语言转换为机器语言──是的,我们在说位元和字节,就是1和0。
       5.

          检查你是否准确地使用了函数和全局变量类似的东西。例如,如果你调用了一个不存在的函数,编译器就会给出警告。
       6.

          如果你是从多个源代码文件编译,就要学会如何把这些文件组合到一起。
       7.

          把产生出来的东西用系统的运行装载器装入内存并运行。
       8.

          最后,把可执行文件写入文件系统。

      编译 这个词的意思通常指 1 到 4 步──其他的 步骤叫做 连接。有时侯第一步叫做 预处理 。第三和第四步叫做 汇编 。

      幸运的是,几乎所有这些细节都是隐藏的,因为 cc 只是一个前端。它根据正确的参数调用程序来处理代码。只要输入
    % cc foobar.c

      就会把 foobar.c 通过以上的步骤编译出来。如果你有多个文件要编译,只要输入
    % cc foo.c bar.c

      注意,语法检查就是──纯粹的检查语法。而不会检测你可能犯的任何逻辑错误。比如无限循环,或者是你想用一元排序却使用了冒泡排序。 [2]

      cc 有很多选项,在帮助手册中都可以找到。这里列出了一些最重要的选项,并且有例子。

    -o filename

        输出的文件名。如果你不使用这个选项,cc为产生 出一个叫 a.out 的执行文件。 [3]

        % cc foobar.c
        可执行文件是 a.out
        % cc -o foobar foobar.c 可执行文件是 foobar

    -c

        仅仅编译文件,不会连接。如果你只想检查你写的测试程序的语法的话,这个选项非常有用。或者你会使用 Makefile。

        % cc -c foobar.c

        这会产生一个 目标文件 (不可执行) 叫做 foobar.o。这个文件可以和其他的目标文件连接在一起构成一个可执行文件。
    -g

        产生一个可调试的可执行文件。编译器会在可执行文件中植入一些信息,这些信息能够把源文件中的行数和被调用的函数联系起来。在你一步一步调试程序的时候,调试器能够使用这些信息来显示源代码。这是 非常 有用的;缺点就是被植入的信息让程序变得更大。通常情况下,开 发一个程序的时候我们经常使用 -g,但是我们在编译一个 “release 版本” 的程序的时候,如果程序工作得让人满意了,我 们就不使用 -g 编译。

        % cc -g foobar.c

        这会产生一个可调试版本的程序。 [4]
    -O

        产生一个优化版本的可执行文件。编译器会使用一些聪明的技巧产生出比普通编译产生的文件执行更快的可执行文件。可以在 -O 加上数字来使用更高级的优化。但是这样做经常会暴露出编译器的优化器中的一些 错误。例如,2.1.0 版本的 FreeBSD 中的 cc 在某些情况 下使用了 -O2 的话,会产生出错误的代码。

        优化通常只在编译一个 release 版本的时候才被打开。

        % cc -O -o foobar foobar.c

        这会产生一个优化版本的 foobar。

        -O和 -O1指定1级优化

        -O2 指定2级优化

        -O3 指定3级优化

        -O0指定不优化

        $cc -c O3 -O0 hello.c

        当出现多个优化时,以最后一个为准!!
    -I

        可指定查找include文件的其他位置.例如,如果有些include文件位于比较特殊的地方,比如/usr/local/include,就可以增加此选项如下:

        $cc -c -I/usr/local/include -I/opt/include hello.c

        此时目录搜索会按给出的次序进行.


    -E

        这个选项是相对标准的,它允许修改命令行以使编译程序把预先处理的C文件发到标准输出,而不实际编译代码.在查看C预处理伪指令和C宏时,这是很有用的.可能的编译输出可重新定向到一个文件,然后用编辑程序来分析:



        $cc -c -E hello.c >cpp.out

        此命令使include文件和程序被预先处理并重定向到文件cpp.out.以后可以用编辑程序或者分页命令分析这个文件,并确定最终的C语言代码看起来如何.

    -D

        允许从编译程序命令行定义宏符号


        一共有两种情况:一种是用-DMACRO,相当于在程序中使用#define MACRO,另一种是用-DMACRO=A,相当于

        程序中的#define MACRO A.如对下面这代码:

        #ifdefine DEBUG

        printf("debug message\n");

        #endif

        编译时可加上-DDEBUG参数,执行程序则打印出编译信息

      下面的三个参数会迫使 cc 检查你的代码是否符合一些国际标准,经常被我们叫做 ANSI 标准,虽然严格的来说它是一个 ISO 标准。

    -Wall

        打开所有 cc 的作者认为值得注意的警告。不要只看这个选项的名字,它并没有打开所有 cc 能够注意到的所有警告。
    -ansi

        关闭大多数,但并不是所有,cc 提供的非 ANSI C 特性。不要只看选项的名字,它并不严格保证你的代码会兼容标准。
    -pedantic

        关闭 所有 cc 的非 ANSI C 特性。

      没有这些选项,cc 能允许你按照标准使用一些非标准的扩展。有一些扩展非常有用,但不能与其他编译器兼容──实际上,这个标准的主要目的之一就是允许我们写出可以在任何系统上的由任何编译器编译的代码。这就叫做 可移植代码

      通常来说,你应该让你的代码尽可能的可以移植。否则你就不得不完全重写你的代码以便能够在其他地方运行之──而且谁知道几年后你是否还会用它?

    % cc -Wall -ansi -pedantic -o foobar foobar.c

      这会在检查 foobar.c对标准的兼容性以后产生一个 foobar 可执行文件。

    -Ldirname

        指定连接库的搜索目录,-l(小写L)指定连接库的名字

        $gcc main.o -L/usr/lib -lqt -o hello

        指定连接库的搜索目录,-l(小写L)指定连接库的名字

        上面的命令把目标文件main.o与库qt相连接,连接时会到/usr/lib查找这个库文件.也就是说-L与-l一般要成对出现.


    -llibrary

        在连接的时候指定一个函数库。

        最常见的情况就是当你编译一个使用了一些 C 中的数学函数的时候。不像大多数其他的平台,这些函数都不在 C 的标准库里面。你必须告诉编译器加 上这些库。

        这个规则就是,如果库的名字叫做 libsomething.a,你就必 须给 cc 这样的选项 -lsomething。例如,数学库 叫做 libm.a,因此你给 cc 的选 项就是 -lm。一般情况下,我们要把这个选项放到命令行的 最后。

        % cc -o foobar foobar.c -lm

        这个会把数学函数库连接到 foobar 里面。

        如果你要编译 C++ 代码,你需要 -lg++,或者 -lstdc++ 如果你使用的是 FreeBSD 2.2 或者更高版本,来 连接 C++ 库。或者,你可以运行 c++ 而不是 cc 来编译 C++ 代码。在 FreeBSD 上, c++ 也可以通过运行 g++ 来唤醒。

        % cc -o foobar foobar.cc
        -lg++ 对于 FreeBSD 2.1.6 或者更低的版本
        % cc -o foobar foobar.cc -lstdc++
        对 FreeBSD 2.2 或者更高的版本
        % c++ -o foobar foobar.cc

        两种情况都会从 C++ 源文件 foobar.cc产生一个 可执行文件 foobar。注意,在 UNIX? 系统中,C++ 源 文件的传统后缀是 .C,.cxx 或 者 .cc,而不是 MS-DOS? 类型的 .cpp (这个后缀已经被用到了其他的地方)。 gcc 根据这个约定来确定应该使用何种类型的编译器来编译源文件。但是,这个限制不再起作用了,因此现在你可以自由的使用 .cpp 这个后缀来命名你的 C++ 源文件!

    常见 cc 问题

    1. 我尝试写一个程序,其中使用了 sin() 这个函数。但是我却得到了如下的错误。这个错误是什么意思?
    2. 好的,我写了一个简单的程序,练习使用 -lm。也 就是计算 2.1 的 6 次方。
    3. 那么我怎么才能改正这个错误?
    4. 我编译了一个文件叫 foobar.c 但是我没有找 到叫 foobar 的执行文件。这个文件到哪里去了?
    5. 好的,我有一个执行文件 foobar,我用命令 ls 可以看见,但是在命令行我输入 foobar 却得到提示说没有这个文件。为什么找不到呢?
    6. 我的可执行文件叫做 test,但是我运行之后却 什么也没发生。到底怎么了?
    7. 我编译了一个程序,开始看起来运行得不错。但是后来调试了,说什么 “core dumped”。这个是什么意思?
    8. 挺不错,但现在我该怎么办呢?
    9. 我的程序把 core dump 以后,说有一个什么 “segmentation fault”。这是什么?
    10. 有时候当我得到一个 core dump,提示说 “bus error”。我的 UNIX 教材里面说这意味这硬件错误,但是计算机看起来运行很正常。这是真的吗?
    11. 如果我可以让 core dump 在需要的时候产生,那就真的很不错。我能 这样做吗,或者我得等直到发生一个错误?

    1. 我尝试写一个程序,其中使用了 sin() 这个函数。但是我却得到了如下的错误。这个错误是什么意思?


    /var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment


    当使用像 sin() 这样的数学函数的时候,你必 须告诉 cc 把数学函数库给连接进来,就像这样:

    % cc -o foobar foobar.c -lm



    2. 好的,我写了一个简单的程序,练习使用 -lm。也 就是计算 2.1 的 6 次方。

    #include <stdio.h>

    int main() {
    float f;

    f = pow(2.1, 6);
    printf("2.1 ^ 6 = %f\n", f);
    return 0;
    }

    然后我编译:

    % cc temp.c -lm

    可以给gcc加上-v选项看一下详细的编译过程。
  • 相关阅读:
    JavaScript中的ActiveXObject控制Excel的方法
    事务的作用
    SQL2005关于quotename的用法
    简易办公系统的设计与实现 文献收集
    《UML建模在办公自动化(OA)系统设计中的应用 》论文笔记(四)
    《基于 UML 与 J2EE 的高校 OA 系统的分析与设计》论文笔记(三)
    《浅谈企业办公管理OA系统的设计与实现 》论文笔记(二)
    《基于UML连锁超市OA系统公文流转的设计》论文笔记(五)
    《暗时间》读书笔记
    《无纸化办公管理系统的设计与实现》论文笔记(一)
  • 原文地址:https://www.cnblogs.com/zhihaowang/p/10128753.html
Copyright © 2011-2022 走看看