由于某些数学计算会返回意外结果,我有一些单元测试失败。
我们使用cmake生成makefile,这让我对makefile的正确性有了很高的信心。
构建已经工作了好几个月了,这就是这个特殊的,不寻常的,虚假的失败,因此这个问题。
我查看了失败测试的目标文件,并且正如预期的那样,它比源文件更新,因此make认为不需要重建它。
-rw------- 1 steve steve 64578 Feb 7 11:13 foo_tests.cc
-rw------- 1 steve steve 12930760 Feb 14 13:18 foo_tests.cc.o
如果删除目标文件并重建,现在测试通过了。
-rw------- 1 steve steve 12931080 Feb 16 13:57 foo_tests.cc.o
我注意到新的目标文件略大。这有点令人费解。
什么会导致这样的错误构建?
在运行错误构建并发现虚假错误之前,我能做些什么来检测错误的构建?
构建详细信息:
这是一个发布模式二进制文件,其中makefile使用cmake生成,并使用Centos 7.2上的gcc 5.2.1构建
我们使用的编译器标志是:
CXX_FLAGS
-Werror
-Wall
-Wextra
-m64
-msse2
-msse4.2
-mfpmath=sse
-ftemplate-depth-128
-Wno-unused-parameter
-Wno-maybe-uninitialized
-Wno-strict-aliasing
-pthread
-DBOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
-ggdb2
-DNDEBUG
-O3
-funroll-loops
-fdevirtualize
-finline-functions
-fno-builtin-malloc
-fno-builtin-calloc
-fno-builtin-realloc
-fno-builtin-free
LINKER_FLAGS:
-m64
-rdynamic
答案 0 :(得分:1)
- 什么会造成这样糟糕的构建?
最可能的原因是糟糕的源代码,其中“坏”只是意味着过时。如果你的makefile没有表达所有每个目标的依赖关系,那么make
可能无法在需要重建时重建某些组件。结果可能是一组没有正确协同工作的目标文件。
另一种可能性是编译器选项不良或不一致。如果程序的行为取决于编译器选项(符号定义在这里是一个特别可能的罪魁祸首),并且您使用错误的选项构建组件,那么更改选项通常不足以说服make
重建任何内容。在这种情况下,干净的构建是最好的策略。
鉴于您的“错误”构建仍然会生成可以链接到工作(虽然不正确)程序的对象,并且删除目标文件并使用相同的工具链重建它会导致具有不同行为的不同目标文件,我没有看到任何其他可能的选择。
- 在运行错误的构建并发现虚假错误之前,我能做些什么来检测错误的构建?
假设构建实际上首先成功,没有。这是 for 的测试之一。但请注意,执行失败的构建是由于我描述的任何一种问题而产生成功但不良构建的切入点。