`
raojl
  • 浏览: 206956 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

GCC注意笔记

阅读更多

大多数程序和库在编译时默认的优化级别是"2"(使用gcc选项:"-O2")并且在Intel/AMD平台上默认按照i386处理器来编译。
如果你只想让编译出来的程序运行在特定的平台上,就需要执行更高级的编译器优化选项,以产生只能运行于特定平台的代码。

一种方法是修改每个源码包中的Makefile文件,在其中寻找CFLAGS和CXXFLAGS变量(C和C++编译器的编译选项)并修改它的值。
一些源码包比如binutils, gcc, glibc等等,在每个子文件夹中都有Makefile文件,这样修改起来就太累了!

另一种简易做法是设置CFLAGS和CXXFLAGS环境变量。大多数configure脚本会使用这两个环境变量代替Makefile文件中的值。
但是少数configure脚本并不这样做,他们必须需要手动编辑才行。

为了设置CFLAGS和CXXFLAGS环境变量,你可以在bash中执行如下命令(也可以写进.bashrc以成为默认值):
export CFLAGS="-O3 -march=" && CXXFLAGS=$CFLAGS
这是一个确保能够在几乎所有平台上都能正常工作的最小设置。

"-march"选项表示为特定的cpu类型编译二进制代码(不能在更低级别的cpu上运行),
Intel通常是:pentium2, pentium3, pentium3m, pentium4, pentium4m, pentium-m, prescott, nocona
说明:pentium3m/pentium4m是笔记本用的移动P3/P4;pentium-m是迅驰I/II代笔记本的cpu;
prescott是带SSE3的P4(以滚烫到可以煎鸡蛋而闻名);nocona则是最新的带有EMT64(64位)的P4(同样可以煎鸡蛋)
AMD通常是:k6, k6-2, k6-3, athlon, athlon-tbird, athlon-xp, athlon-mp, opteron, athlon64, athlon-fx
用AMD的一般都是DIYer,就不必解释了吧。

如果编译时没有抱怨"segmentation fault, core dumped",那么你设定的"-O"优化参数一般就没什么问题。
否则请降低优化级别("-O3" -> "-O2" -> "-O1" -> 取消)。
个人意见:服务器使用"-O2"就可以了,它是最安全的优化参数(集合);桌面可以使用"-O3" ;
不鼓励使用过多的自定义优化选项,其实他们之间没什么明显的速度差异(有时"-O3"反而更慢)。

编译器对硬件非常敏感,特别是在使用较高的优化级别的时候,一丁点的内存错误都可能导致致命的失败。
所以在编译时请千万不要超频你的电脑(我编译关键程序时总是先降频然的)。

注意:选项的顺序很重要,如果有两个选项互相冲突,则以后一个为准。
比如"-O3"将打开-finline-functions选项,但是可以用"-O3 -fno-inline-functions"既使用-O3的功能又关闭函数内嵌功能。

更多的优化选项请参见:
http://gcc.gnu.org/onlinedocs/gcc-3....e-Options.html
http://gcc.gnu.org/onlinedocs/gcc-3....4-Options.html
http://gcc.gnu.org/onlinedocs/gcc-4....e-Options.html
http://gcc.gnu.org/onlinedocs/gcc-4....4-Options.html
所有GCC选项完整列表参见:
http://gcc.gnu.org/onlinedocs/gcc-3....n-Summary.html
http://gcc.gnu.org/onlinedocs/gcc-4....n-Summary.html

有两个页面值的参考:
(对于gentoo-1.4)比较安全的优化选项
http://www.freehackers.org/gentoo/gc...flag_gcc3.html
(对于gentoo-1.4)进阶优化选项
http://www.freehackers.org/gentoo/gc...g_gcc3opt.html

*******************************************************************

哦,忘了说一声,"-O2"已经启用绝大多数安全的优化选项了,所以其实你不必对那一堆选项发愁。
先说说"-O3"在"-O2"基础上增加的几项,你可以按需添加(还算比较安全):
[gcc-3.4.4]
-finline-functions 允许编译器选择某些简单的函数在其被调用处展开
-fweb 为每个web结构体分配一个伪寄存器
-frename-registers 试图驱除代码中的假依赖关系,这个选项对具有大量寄存器的机器很有效。
[gcc-4.0.2]
-finline-functions 说明如上
-funswitch-loops 将循环体中不改变值的变量移动到循环体之外
-fgcse-after-reload **不太明白它的含义**[哪位大峡知道给小弟讲解一下,先行谢过 ]

说完"-O3"再说说在嵌入式系统上常用的"-Os"选项,这个选项其实也很重要,它的含义是对生成的二进制代码进行尺寸上的优化,它打开了所有"- O2"打开的选项,因此通常认为的"-Os"生成的二进制代码执行效率低的潜在意识是错误的!当然该选项与"-O2"的不同之处在于它在"-O2"的基础上禁止了所有为了对齐而插入的空间,也就是将所有"-falign-*"系列的选项禁用了。这种禁用究竟是否一定降低了代码的执行效率,依据程序的不同而不同,据说某些情况下"-Os"的效率比"-O3"还要高14%!请兄弟们在实践中自己摸索吧...

---------------------------------------------

下面选择我认为比较重要的几项简单介绍一下[gcc-3.4.4],GCC选项完整列表太长了!精力有限。
[注意]这里列出的都是非默认的选项,你只需要添加你所需要的选项即可

-w 禁止输出警告消息

-Werror 将所有警告转换为错误

-Wall 显示所有的警告消息

-v 显示编译程序的当前版本号

-V 指定gcc将要运行的版本。只有在安装了多个版本gcc的机器上才有效。

-ansi 按照ANSI标准编译程序,但并不限制与标准并不冲突的GNU扩展(一般不用该选项)

-pedantic 如果要限制代码必须严格符合ISO标准,就在"-ansi"的基础上同时启用这个选项(很少使用)

-std= 指定C语言的标准(c89,c99,gnu89),该选项禁止了GNU C的扩展关键字asm,typeof,inline (一般不用该选项)

-static 连接器将忽略动态连接库,同时通过将静态目标文件直接包含到结果目标文件完成对所有引用的解析。

-shared 连接器将生成共享目标代码,该共享库可在运行时动态连接到程序形成完整的可执行体。
如果使用gcc命令创建共享库作为其输出,该选项可以防止连接器将缺失main()方法视为错误。
为了可以正确的工作,应该一致的使用选项"-fpic"以及目标平台选项编译构成同一个库的所有共享目标模块。

-shared-libgcc 该选项指定使用共享版本的libgcc,在没有共享版本的libgcc的机器上该选项无效。

-specs= gcc驱动程序读取该文件以确定哪些选项应该传递给那些子进程。
该选项可以通过指定配置文件来覆盖默认配置,指定的文件将在默认配置文件读取后进行处理以修改默认配置。

-pipe 使用管道而不是临时文件一个阶段到另一个阶段交换输出的方式,可以加快编译速度。建议使用。

-o 指定输出文件,对各种输出皆有效。由于只能指定一个文件,所以在产生多个输出文件的情况下不要使用该选项。

--help 显示gcc的命令行选项列表;与"-v"一起使用时还将显示gcc调用的各个进程所接受的选项。

--target-help 显示目标机器相关的命令行选项列表

-b 指示需要编译程序的目标机器;默认为编译程序所运行的目标机编译代码。
目标机通过指定包含编译程序的目录来确定,通常为/usr/local/lib/gcc-lib//

-B 指定库文件的位置,包括编译程序的文件、执行程序和数据文件,如果需要运行子程序(如cpp,as,ld)就会用该前缀来定位。
这个前缀可以是用冒号分割的多个路径,环境变量GCC_EXEC_PREFIX和这个选项有相同的效果。

-I
指定搜索系统头文件的目录,可以重复使用多个该选项指定多个目录。

-dumpmachine 显示该程序的目标机名字,不做其他任何动作

-dumpspecs 显示构件编译程序的规范信息,包括用来编译、汇编和连接gcc编译程序自身用到的所有选项,不做其他任何动作。

-dumpversion 显示编译程序自身的版本号,不做其他任何动作

-falign-functions=N 将所有函数的起始地址在N(N=1,2,4,8,16...)的边界上对齐,默认为机器自身的默认值,指定为1表示禁止对齐。

-falign-jumps=N 将分支目标在N(N=1,2,4,8,16...)的边界上对齐,默认为机器自身的默认值,指定为1表示禁止对齐。
-fno-align-labels 建议使用它,以保证不和-falign-jumps("-O2"默认启用的选项)冲突

-fno-align-loops 建议使用它,以确保不会在分支目标前插入多余的空指令。

-fbranch-probabilities 在使用"-fprofile-arcs"选项编译程序并执行它来创建包含每个代码块执行次数的文件之后,程序可以利用这一选项再次编译,
文件中所产生的信息将被用来优化那些经常发生的分支代码。如果没有这些信息,gcc将猜测那一分支可能经常发生并进行优化。
这类优化信息将会存放在一个以源文件为名字的并以".da"为后缀的文件中。

-fno-guess-branch-probability 默认情况下gcc将使用随机模型进行猜测哪个分支更可能被经常执行,并以此来优化代码,该选项关闭它。

-fprofile-arcs 在使用这一选项编译程序并运行它以创建包含每个代码块的执行次数的文件后,程序可以再次使用"-fbranch-probabilities"编译,
文件中的信息可以用来优化那些经常选取的分支。如果没有这些信息,gcc将猜测哪个分支将被经常运行以进行优化。
这类优化信息将会存放在一个以源文件为名字的并以".da"为后缀的文件中。

-fforce-addr 必须将地址复制到寄存器中才能对他们进行运算。由于所需地址通常在前面已经加载到寄存器中了,所以这个选项可以改进代码。
-fforce-mem 必须将数值复制到寄存器中才能对他们进行运算。由于所需数值通常在前面已经加载到寄存器中了,所以这个选项可以改进代码。

-ffreestanding 所编译的程序能够在独立的环境中运行,该环境可以没有标准库,而且可以不从main()函数开始运行。
该选项将设置"-fno-builtin",且等同于"-fno-hosted"。
-fhosted 所编译的程序需要运行在宿主环境中,其中需要有完整的标准库,而且main()函数具有int型的返回值。
-fno-builtin 除非利用"__builtin_"进行引用,否则不识别所有内建函数。

-fmerge-all-constants 试图将跨编译单元的所有常量值和数组合并在一个副本中。但是标准C/C++要求每个变量都必须有不同的存储位置。

-fmove-all-movables 将所有不变的表达式移动到循环体之外,这种做法的好坏取决于源代码中的循环结构。

-fnon-call-exceptions 产生的代码可供陷阱指令(如非法浮点运算和非法内存寻址)抛出异常,需要相关平台的运行时支持,并不普遍有效。

-fomit-frame-pointer 对于不需要栈指针的函数就不在寄存器中保存指针,因此可以忽略存储和检索地址的代码,并将寄存器用于普通用途。
所有"-O"级别都打开着一选项,但仅在调试器可以不依靠栈指针运行时才有效。建议不需要调试的情况下显式的设置它。

-fno-optional-diags 禁止输出诊断消息,C++标准并不需要这些消息。
-fpermissive 将代码中与标准不符合的诊断消息作为警告而不是错误输出。

-fpic 生成可用于共享库的位置独立代码(PIC),所有的内存寻址均通过全局偏移表(GOT)完成。该选项并非在所有的机器上都有效。
要确定一个地址,需要将代码自身的内存位置作为表中的一项插入。该选项可以产生在共享库中存放并从中加载的目标模块。

-fprefetch-loop-arrays 生成数组预读取指令,对于使用巨大数组的程序可以加快代码执行速度,适合数据库相关的大型软件等。

-freg-struct-return 生成用寄存器返回短结构的代码,如果寄存器无法荣纳将使用内存。

-fstack-check 为防止程序栈溢出而进行必要的检测,在多线程环境中运行时才可能需要它。

-ftime-report 编译完成后显示编译耗时的统计信息

-funroll-loops 如果在编译时可以确定迭代的次数非常少而且循环中的指令也非常少,可以使用该选项进行循环展开,以驱除循环和复制指令。

-finline-limit= 对伪指令数超过的函数,编译程序将不进行展开,默认为600

--param = gcc内部存在一些优化代码程度的限制,调整这些限制就是调整整个优化全局。下面列出了参数的名字和对应的解释:
名字 解释
max-delay-slot-insn-search 较大的数目可以生成更优化的代码,但是会降低编译速度,默认为100
max-delay

 

++++++++++++++++++++++++++++++++++++++++++++++++++

编译64位——————m64 ,链接库指向64位。

 

分享到:
评论

相关推荐

    GCC 学习 笔记GCC学习笔记

    ### GCC 学习笔记知识点详解 #### 一、GCC简介与版本检查 - **GCC**(GNU Compiler Collection)是一款开源的编译器集合,广泛应用于Linux等类Unix系统上,支持多种编程语言如C、C++等。 - **版本检查**: - 要...

    GCC的连接脚本学习笔记

    ### GCC的连接脚本学习笔记知识点详解 #### 1. 输入段与输出段的概念解析 在探讨GCC连接脚本之前,首先要明确输入段(input section)和输出段(output section)的概念。 - **输入段**:指的是链接过程中提供的所有...

    JNI笔记(GCC4.4.0编译器)

    本笔记主要围绕使用GCC 4.4.0编译器来实现JNI开发进行详细阐述。 首先,我们需要理解JNI的基本结构。JNI接口定义了一套函数,这些函数由Java虚拟机(JVM)提供,使得本地代码(如C/C++)能够与Java代码进行通信。当...

    编译安装bzip2的笔记。

    编译安装bzip2的笔记 编译安装bzip2是 Linux 操作系统中的一种常见操作。bzip2 是一种流行的压缩工具,广泛应用于 Linux 和 Unix 系统中。下面是编译安装 bzip2 的详细笔记: 首先,需要下载 bzip2 的源代码包。...

    达内嵌入式 Linux开发 笔记

    笔记中提到的 gcc 命令选项包括: - -E 选项用于预处理阶段; - -S 选项用于生成汇编代码; - -c 选项用于编译成目标文件,但不进行连接; - -o 选项用于指定输出文件的名称; - -std 用于指定C语言标准; - -Wall ...

    黑马程序员 linux从入门到精通配套笔记.docx

    黑马程序员 Linux 从入门到精通配套笔记 本资源汇总了 Linux 操作系统的发展史、安装方法、特点和分支等内容。下面是从文件中提取的知识点: 一、Linux 发展史 1. Linux 的前身是 Unix,于 1968 年由 Multics ...

    linux 下学生信息管理系统 GCC编译

    - `项目文档_吴军华.doc`:这是项目的文档文件,可能是开发者的笔记、设计文档或者用户手册,包含了关于系统设计、功能和使用方法的详细信息。 - `itemlast`:这个文件没有明确的扩展名,可能是已经编译的二进制...

    mingw32_gcc441 编译ffmpeg

    MingW32与GCC4.4.1:构建FFmpeg的Windows编译环境 MingW32(Minimalist GNU for Windows...不过,需要注意的是,保持编译环境的更新和与源代码版本的兼容性是至关重要的,这样才能充分利用FFmpeg的功能并确保其性能。

    STM32CubeMX学习笔记大全

    7. **代码生成与工程导入**:讲解STM32CubeMX生成的代码结构,如何将生成的代码导入到IDE(如Keil、STM32CubeIDE、GCC等)中,以及代码的初始化流程。 8. **HAL库与LL库的使用**:对比分析HAL库的易用性和LL库的...

    应用笔记LAT1254+巧用STM32CubeIDE之编译警告

    ### 应用笔记LAT1254+巧用STM32CubeIDE之编译警告 #### 1. 前言 在软件开发过程中,编译警告常常被视为一种辅助工具,帮助开发者识别潜在的问题和非最佳实践。尤其对于像STM32CubeIDE这样的集成开发环境(IDE),...

    嵌入式系统学习笔记(非常有帮助)

    ### 嵌入式系统学习笔记关键知识点解析 #### 一、嵌入式系统的软件环境:uClinux与GNU/Linux **知识点概述**: - **uClinux**:是一种为无MMU(Memory Management Unit,内存管理单元)的处理器设计的嵌入式Linux...

    caffe配置笔记

    本笔记将详述在Ubuntu 14.04系统下配置Caffe的步骤和注意事项,包括环境搭建、CUDA的安装以及相关依赖的解决。 首先,确保你的操作系统是Ubuntu 14.04,并且已经安装了GCC/G++ 4.7.x版本。这是因为不同的Matlab版本...

    Redis 笔记.pdf

    直接编译安装需要准备好gcc环境,并通过源码安装;使用Docker安装则需要先安装Docker环境,通过docker run命令快速部署;直接安装则在不同操作系统中有不同的包管理器安装命令,例如在CentOS中使用yum install命令,...

    AVR学习笔记(网上特别火的avr学习资料,用过真的很好)

    10. **问题与注意事项**:笔记中作者分享了在学习过程中遇到的问题及其解决办法,对于初学者来说,这些经验教训可以帮助避免常见的陷阱。 通过这份学习笔记,读者不仅能系统地学习到AVR单片机的基本知识,还能了解...

    (单片机Protues入门笔记)单片机Proteus仿真软件入门笔记约80多页,内容图像并茂

    安装过程中需要注意兼容性问题,确保软件版本与你的操作系统相匹配。安装完成后,启动软件,你会看到一个简洁的工作界面,包括原理图编辑区、元器件库、仿真控制面板等。 3. 原理图绘制: 在Proteus中,你可以从...

    文章笔记1

    在C和C++混合编程时,GCC可以处理这两种语言的集成,但需要注意不同语言间的命名约定、参数传递、数据类型转换和错误处理等问题。 此外,GCC在单片机开发中也有应用,尤其是在内存管理方面。在51单片机中,时钟周期...

    linux C 动态库和静态库生成及使用笔记

    "linux C 动态库和静态库生成及使用笔记" Linux C 动态库和静态库是两种不同的库类型,它们在生成、使用和链接时有着不同的机制和要求。下面我们将详细介绍 Linux C 动态库和静态库的生成、使用和链接机制。 一、...

    笔记本 ubuntu22.04 安装RTX3080TI nvidia显卡驱动

    sudo apt-get install gcc sudo apt-get install make ``` 接下来,从NVIDIA官方网站下载与你的显卡兼容的驱动程序。例如,你可以选择版本为470.129.06的驱动。下载完成后,确保驱动文件夹的名称是英文的,以便后续...

    live555学习笔记

    而使用VC环境编译时,由于Live555代码原生不支持gcc,所以需要手动为每个库生成一个lib项目,并为媒体服务器生成一个exe项目。完成这些设置后,就可以使用VC进行编译了。值得注意的是,对于较新的VC版本,可能需要...

Global site tag (gtag.js) - Google Analytics