最近在工作中需要编译一个库文件,使用gcc的交叉编译环境。遇到了一个令人迷惑的问题:同样的编译环境,同样的代码,只是因为在硬盘上存放的位置不同,编译出来的.o文件大小就会产生差异。此刻,终于搞明白了原因。记录一下。
背景知识:先了解下gcc编译选项:(以下内容均载自网络,有的翻译可能有点拗口,凑合看吧)
参考链接https://www.cnblogs.com/lsgxeva/p/7605141.html
GCC的-g选项用于配置GDB调试级别
如果不打开-g或者-ggdb(GDB专用)调试开关,GCC编译时不会加入调试信息,因为这会增大生成代码的体积。GCC采用了分级调试,通过在-g选项
后附加数字1、2或3来指定在代码中加入调试信息量。默认的级别是2(-g2),此时调试信息包括扩展的符号表、行号、局部或外部变量信息。
级别3(-g3)包含级别2中的调试信息和源代码中定义的宏。
级别1(-g1)不包含局部变量和与行号有关的调试信息,只能用于回溯跟踪和堆栈转储之用。
回溯跟踪指的是监视程序在运行过程中的函数调用历史,堆栈转储则是一种以原始的十六进制格式保存程序执行环境的方法,两者都是经常用到的调试手段。

顺别学习下GCC的-O选项,这是用来优化代码的(优化指的是速度和体积)
-O0:这个等级(字母“O”后面跟个零)关闭所有优化选项,也是CFLAGS或CXXFLAGS中没有设置-O等级时的默认等级。这样就不会优化代码,这通常不是我们想要的。
-O1:这是最基本的优化等级。编译器会在不花费太多编译时间的同时试图生成更快更小的代码。这些优化是非常基础的,但一般这些任务肯定能顺利完成。
-O2:-O1的进阶。这是推荐的优化等级,除非你有特殊的需求。-O2会比-O1启用多一些标记。设置了-O2后,编译器会试图提高代码性能而不会增大体积和大量占用的编译时间。
-O3:这是最高最危险的优化等级。用这个选项会延长编译代码的时间,并且在使用gcc4.x的系统里不应全局启用。自从3.x版本以来gcc的行为已经有了极大地改变。在3.x,-O3生成的代码也只是比-O2快一点点而已,而gcc4.x中还未必更快。用-O3来编译所有的软件包将产生更大体积更耗内存的二进制文件,大大增加编译失败的机会或不可预知的程序行为(包括错误)。这样做将得不偿失,记住过犹不及。在gcc 4.x.中使用-O3是不推荐的。
-Os:这个等级用来优化代码尺寸。其中启用了-O2中不会增加磁盘空间占用的代码生成选项。这对于磁盘空间极其紧张或者CPU缓存较小的机器非常有用。但也可能产生些许问题,因此软件树中的大部分ebuild都过滤掉这个等级的优化。使用-Os是不推荐的。

GCC提供选项控制代码的优化等级:
这些选项可以实现不同程度的优化。
没有任何优化选项的话,编译时的目标是降低编译成本,并使调试产生预期的结果。语句是独立的:如果你使程序停止在语句之间设置的断点处,你可以改变任何变量的值或者改变程序计数器的值使程序执行任意函数中的语句并得到源代码中期望的结果。
打开优化标志使编译器尝试以编译时间和可能的调试程序的能力为代价来改进性能和/或代码大小。
编译器根据程序的信息执行优化。 一次编译多个文件生成单个可执行文件的模式允许编译器在编译每个文件时使用从所有文件中获取的信息。
并非所有优化都由标志直接控制。以下仅列出具有标志的优化。
只有在命令行上设置-O或其他等级的优化选项时,才会启用大多数优化。 否则,即使指定了单独的优化标志,它们也会被禁用。
根据目标和GCC的配置方式,可以在每个-O级别启用略有不同的优化集。

-O0:减少编译时间并使调试可以产生预期的结果,这也是默认的优化等级。

-O、-O1:优化编译需要更多时间,并且大型函数需要更多内存。使用-O选项,编译器会尝试减小代码尺寸减少执行时间,不执行任何需要大量编译时间的优化。
-O选项打开了如下优化标志:
-fauto-inc-dec -fbranch-count-reg -fcombine-stack-adjustments -fcompare-elim -fcprop-registers -fdce -fdefer-pop
-fdelayed-branch -fdse -fforward-propagate -fguess-branch-probability -fif-conversion2 -fif-conversion
-finline-functions-called-once -fipa-pure-const -fipa-profile -fipa-reference -fmerge-constants -fmove-loop-invariants
-fshrink-wrap -fsplit-wide-types -ftree-bit-ccp -ftree-ccp -fssa-phiopt -ftree-ch -ftree-copy-prop -ftree-copyrename -ftree-dce
-ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre -ftree-phiprop -ftree-sink -ftree-slsr -ftree-sra -ftree-pta
-ftree-ter -funit-at-a-time

-O2:相对-O优化更多。 GCC几乎执行所有支持的优化,但不涉及空速权衡。 与-O相比,此选项增加了编译时间和生成代码的性能。
-O2除了打开所有-O指定的优化标志,还打开了如下优化标志:
-fthread-jumps
-falign-functions  -falign-jumps -falign-loops  -falign-labels -fcaller-saves -fcrossjumping -fcse-follow-jumps
-fcse-skip-blocks -fdelete-null-pointer-checks -fdevirtualize -fdevirtualize-speculatively -fexpensive-optimizations -fgcse
-fgcse-lm -fhoist-adjacent-loads -finline-small-functions -findirect-inlining -fipa-cp -fipa-cp-alignment -fipa-sra -fipa-icf
-fisolate-erroneous-paths-dereference -flra-remat -foptimize-sibling-calls -foptimize-strlen -fpartial-inlining -fpeephole2
-freorder-blocks -freorder-blocks-and-partition -freorder-functions -frerun-cse-after-loop -fsched-interblock  -fsched-spec
-fschedule-insns  -fschedule-insns2 -fstrict-aliasing -fstrict-overflow -ftree-builtin-call-dce -ftree-switch-conversion
-ftree-tail-merge -ftree-pre -ftree-vrp -fipa-ra

-O3:相对-O2优化更多。
-O3除了打开所有-O2指定的优化标志,还打开了如下优化标志:
-finline-functions, -funswitch-loops,
-fpredictive-commoning, -fgcse-after-reload, -ftree-loop-vectorize, -ftree-loop-distribute-patterns, -ftree-slp-vectorize,
-fvect-cost-model, -ftree-partial-pre and -fipa-cp-clone

-Os:优化尺寸。 -Os启用所有通常不会增加代码大小的-O2优化。 它还执行旨在减少代码大小的进一步优化。
-Os关闭如下优化标志:
-falign-functions  -falign-jumps  -falign-loops -falign-labels  -freorder-blocks
-freorder-blocks-and-partition -fprefetch-loop-arrays

-Ofast:无视严格的标准合规性。 -Ofast启用所有-O3优化。 它还打开并非对所有符合标准的程序有效的优化。 它打开
-ffast-math和Fortran特定的-fno-protect-parens和-fstack-arrays。

-Og:优化调试体验。 -Og启用不会干扰调试的优化。 它是标准编辑 - 编译 - 调试周期可以选择的优化级别,提供合理的优化级别,同时保持快速编译和良好的调试体验。
如果使用多个-O选项(包含或不包含级别编号),则最后一个选项是有效的选项。

背景知识了解后,问题显而易见

引起上述问题的原因就是GDB调试级别。因为编译脚本使用了-g选项,因此导致生成的二进制文件包含了适应本地环境的调试信息,诸如代码的完整路径。这会导致同样的编译脚本在不同的目录中进行编译时所生成的二进制文件的大小会有差异。要避免这个差异,只要将-g选项删掉即可。或者写成-g0也可以。
贴出我的Makefile脚本
=============================
TOOLCHAIN_PREFIX = arm-none-eabi-
TARGET = LIBRARY
CC = $(TOOLCHAIN_PREFIX)gcc
CXX = $(TOOLCHAIN_PREFIX)g++
AR = $(TOOLCHAIN_PREFIX)ar
OUT_FILE_NAME = lib$(TARGET).a
COMMON_FLAGS =  -mcpu=cortex-m33 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 -Og -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -Wall  -g0(原先这里是-g3) -T
CFLAGS = -std=c11
CXXFLASG = -std=c++14
INC = -Iinclude
OBJS = $(patsubst %.cpp,%.cpp.o,$(wildcard *.cpp)) $(patsubst %.c,%.c.o,$(wildcard *.c))
DEPS = $(patsubst %.o,%.d,$(OBJS))
# Enumerating of every *.cpp as *.o and using that as dependency
$(OUT_FILE_NAME): $(OBJS)
    $(AR) -r -o $@ $^
%.cpp.o: %.cpp
    $(CXX) -c $(INC) $(COMMON_FLAGS) $(CXXFLAGS) -o $@  $<
%.c.o: %.c
    $(CC) -c $(INC) $(COMMON_FLAGS) $(CFLAGS) -o $@  $<
clean:
    rm -f $(OBJS) $(DEPS) $(OUT_FILE_NAME)
check:
    @echo $(OBJS)
    @echo $(DEPS)
==================================

同一个编译脚本下 arm 交叉编译 生成文件大小不一致的问题分析相关推荐

  1. Ubuntu12.04下arm交叉编译环境的建立

    http://blog.csdn.net/heyangya2009/article/details/5424376 备注:ubuntu12.04+Android+Real6410 在主机上用来编译其他 ...

  2. linux文件尺寸的大小不一样,linux下文件大小不一致的情况分析,文件空洞

    df 显示的已使用磁盘占用率比du 统计出来的结果要大很多.原因,主要是由于两者计算结果的方式不同. 一.实验情况 1.创建并删除文件 创建文件前的磁盘容量情况: # df -h 文件系统 容量 已用 ...

  3. linux top交叉编译_Linux 系统下ARM Linux交叉编译环境crosstool工具

    Linux系统下ARM Linux交叉编译环境的建立目前流行的有三种途径. 一.使用别人编译好的开发工具链本文引用地址:http://www.eepw.com.cn/article/201611/31 ...

  4. apache arm 交叉编译_MacOS 下交叉编译的折腾笔记

    这是这个系列 "折腾笔记" 的第一篇,希望能用更直白的方式去展现交叉编译的时候做了些什么.因此,这个教程并不是最佳实践,但是可以让小伙伴们有一个更直白的理解.之后,我会把笔记的重点 ...

  5. arm-linux 交叉编译后程序,ARM交叉编译下,应用程序实践

    ARM交叉编译下,应用程序实践 一.首先准备一个小程序 hello.c 代码如下: #include int main(void) { printf("hello,world\n" ...

  6. linux curl编译 arm交叉编译

    虚拟机环境 ubuntu12.04 开发板 EasyARM-i.MX280A:   64m  sdram  128M  nandflash   运行官方提供的Linux-2.6.35.3内核linux ...

  7. CGO arm 树莓pi下的交叉编译

    转载 CGO arm 树莓pi下的交叉编译 https://medium.com/@chrischdi/cross-compiling-go-for-raspberry-pi-dc09892dc745 ...

  8. 建立ARM交叉编译环境 (arm-none-linux-gnueabi-gcc with EABI)

    昨天终于把交叉编译环境.移植内核和制作root文件系统在arm开发板上顺利跑通了.期间有的步骤很顺利,但更多的是被诸多问题困扰,比如最后一个不起眼的小问题导致文件系统无法加载,郁闷了我一个星期,最终通 ...

  9. Linux ARM交叉编译工具链制作过程

    一.下载源文件 源代码文件及其版本与下载地址: Binutils-2.19.tar.bz2 http://ftp.gnu.org/gnu/binutils/ gcc-4.4.4.tar.bz2 htt ...

最新文章

  1. Java写手机专题分析接口_jeesite学习文档API-内容管理模块
  2. 0418 jQuery笔记(添加事件、each、prop、$(this))
  3. 消息称字节跳动正在开发一款类Clubhouse应用
  4. Maven学习总结(46)——Maven跳过单元测试的两种方法及其区别(-Dmaven.test.skip=true与-DskipTests)
  5. linux限制堆栈大小,进程超过RedHat Enterprise Linux 6的线程堆栈大小限制?
  6. bzoj2705: [SDOI2012]Longge的问题
  7. Java构建指定大小文件
  8. Kafka 分布式消息系统详解
  9. 【SICP练习】31 练习1.37
  10. py-R-FCN安装记录
  11. 设计模式:(工厂模式)
  12. 20190321——Python模块
  13. 4G模组EC20在使用电信物联网专用卡时无信号问题
  14. 【Java 线程池 概念+深析】简单理解
  15. 求X的N次方,介绍三种方法
  16. 宇宙代码与磁子计算机,新认识!宇宙产生什么最强磁铁?比人类产生的最强磁场强一亿倍...
  17. 热爱工作,拥抱明天——读《干法》有感2800字
  18. KanKan甄选,BaseAdapter我要对你说,ViewHolder你懂得,性能优化必读
  19. YARN源码分析(一)-----ApplicationMaster
  20. 测试篇(二): 如何合理的创建bug、bug的级别、bug的生命周期、跟开发产生争执怎么办

热门文章

  1. Python调接口实现图像风格转化、黑白图像上色、人像动漫化
  2. 金万维快解析远程服务,助力企业客户维护
  3. linux出现没有文件或目录,Linux解决bash ./没有那个文件或目录的方法
  4. Timeout expired
  5. 第二十二课:PR简介
  6. 中亿丰数字前后端接口请求说明书
  7. android 统计应用流量 NetworkStatsManager
  8. 大气磅礴的网站效果 scroll+easing+animation+水平、竖直滚动
  9. Instrumentation 实践详解
  10. Correct Bracket Sequence Editor