即使源代码和编译器标志未修改,导致目标文件在编译之间变化的原因是什么?

时间:2016-09-23 18:58:11

标签: c gcc makefile pic sdcc

如果你点击这个因为你认为这是不可能的,那么在我遇到它之前我会想到同样的事情。

我正在开发一个用C语言编写的PIC项目,它是用Makefile构建的。 Makefile非常混乱,所以我想清理它。为了确保在我做的时候我没有破坏任何东西,我记录了所有文件的哈希值,以及新的make :(此项目中没有子目录。使用SDCC和GPUTILS构建。)

make clean
make
md5sum ./* > ../allsums.txt

然后我修改了Makefile并再次尝试,这次将生成的文件与 allsums.txt 进行比较。

make clean
vim Makefile
make
md5sum -c ../allsums.txt

有趣的是,.o文件的哈希值不匹配,但最终结果却是如此。假设问题是我以某种方式创建的,我花了很多时间试图追捕它。

然后,在预感中,我使用原始Makefile执行此操作:

make clean
make
md5sum ./* > ../allsums.txt
make clean
make
md5sum -c ../allsums.txt

我发现这里的对象文件也发生了变化!有些搜索引导我this question,它确认(至少对于gcc).o文件在每次编译之间都会发生变化。

是什么导致这种情况?

1 个答案:

答案 0 :(得分:3)

即使代码严格相同,对象中的调试信息(符号,日期)也可以使对象发生变化。

为确保您没有任何更改,只需剥离对象:

strip *.o

比较对象/对它们执行校验和的最佳方法是在剥离的对象上,否则你永远无法确定。

(相同的技术可以应用于可执行文件)

注意:剥离对象后,您可以链接它们,但是您将很难进行调试。您可以在副本上进行(theobject.o不变,然后):

strip theobject.o -o theobject_stripped.o

我们在交付前执行可执行文件的“正式生产”时使用该流程。

实际上我们反过来这样做:我们比较剥离的可执行文件,如果存在差异,我们比较剥离的对象以找到罪魁祸首并缩小范围。 然后我们在源上使用我们的版本控制系统来查找它发生变化的原因。

编辑:如果使用自定义的时间相关宏来定义目标文件中的日期(-DDATE=\"somedate\"),则校验和过程将需要多个条带操作。从目标文件(或文件)中反向操作(删除日期/版本/等)必须使用自定义工具完成。 您可以从此功能中受益,并且通过仅在包含导出符号上的版本(Version.o)的一个文件上应用宏来使大多数目标文件不受影响。

该文件的校验和将有所不同,但其他文件将是相同的(或者你的同事们对你毫无意义地使你很难)

编辑:对于SDCC,你有一个名为sdobjcopy的类似工具,其界面看起来非常像objcopy,并具有剥离对象的功能

sdobjcopy --strip-all theobject.o theobject_stripped.o

(如果--strip-debug选项太“暴力”,还有一个--strip-all选项。

检查sdobjcopy man page了解详情。

相关问题