首页 > 解决方案 > 在 C/C++ 中将测试符号静态收集到一个数组中

问题描述

问题的简短版本

是否可以在编译时将 C 中的特定符号静态地收集到单个列表/数组中到可执行文件中,而不依赖于 crt 初始化(我经常支持嵌入式目标,并且对动态内存的支持有限)。

编辑:我 100% 可以在链接时发生这种情况,也可以不让符号跨越库边界。

编辑 2:如果它是 gcc 或 clang,我也可以接受编译器特定的答案,但如果可能的话,我更喜欢跨平台。

更长的版本,更多的背景

一段时间以来,这一直是我的痛苦。

现在我有一些我喜欢按顺序运行的内置自测。

我对所有函数强制执行相同的调用约定,并手动将所有测试静态收集到一个数组中。

// ThisLibrary_testlist.h
#define DECLARE_TEST(TESTNAME) void TESTNAME##_test(void * test_args)
DECLARE_TEST(test1);
DECLARE_TEST(test2);
DECLARE_TEST(test3);
// ThisLibrary_some_module.c
#include "ThisLibrary_testlist.h"
DECLARE_TEST(test1)
{
   // ... do hood stuff here
}
// ThisLibrary_testarray.c


#include "ThisLibrary_testlist.h"
typedef void (*testfunc_t) (void*);
#define LIST_TEST(TESTNAME)

testfunc_t tests[] =
{
    &LIST_TEST(test1),
    &LIST_TEST(test2)
}; 
// now it's an array... you know what to do.

到目前为止,这让我保持活力,但如果我想更新测试,我必须基本上修改 3 个不同位置的代码,这有点荒谬。

更不用说条件编译测试带来的绝对 #ifdef 噩梦了。

有没有更好的办法?

标签: cunit-testingembeddedcompiler-optimization

解决方案


使用一点脚本魔法,您可以执行以下操作:在编译源文件之后(但在链接之前),您在目标文件中搜索与您的测试名称模式匹配的符号。了解man nm如何从目标文件中获取符号名称(好吧,在 Unix 上,就是 - 不知道 windows,抱歉)。根据找到的对象名称列表,您自动创建文件ThisLibrary_testarray.c,放入所有extern声明,然后放入函数指针表。生成此文件后,您对其进行编译并最终链接所有内容。

这样,您只需将新的测试函数添加到源文件中。无需维护头文件ThisLibrary_testlist.h,但您必须确保测试函数具有外部链接,遵循命名模式 - 并确保没有其他符号使用命名模式:-)


推荐阅读