如何在头文件中模拟函数?

eDe*_*ser 5 c gcc unit-testing cmocka

我在做什么:

我正在使用cmocka对大型嵌入式项目运行单元测试。嵌入式项目使用编译arm-gcc-compiler。单元测试是gcc使用嵌入代码和cmocka库的片段与普通代码一起编译的。

通常,cmocka建议使用该-Wl,--wrap=functionName标志来模拟(替换)一些不需要的子功能。这个效果很好。

问题:

好吧,在我的嵌入式代码中,有一个头文件(foo.h),其中包含一些函数(声明为内联)。这些函数之一包含的一些汇编代码arm-gcc-compiler,当然,这些不能被编译gcc

愣神的wrap-flag似乎并没有被放置在头文件中的函数工作。

题:

如何在头文件中模拟该功能呢?

我如何解决问题:

我考虑过要插入一些#idef宏以排除提到的汇编器部分。但这无法完成,因为此文件属于许可库,并且不允许更改其内容。

我可以将待测函数提取到其他文件中,这样foo.h就不再需要包含它了。但这会混淆嵌入式源代码的结构。

确切的问题

确切的代码位于233行的freeRtos的portmacro.h中:

portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI;

    __asm volatile
    (
        "   mov %0, %1                                              \n" \
        "   msr basepri, %0                                         \n" \
        "   isb                                                     \n" \
        "   dsb                                                     \n" \
        :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
    );
}
Run Code Online (Sandbox Code Playgroud)

其中portFORCE_INLINE定义为:

#define portFORCE_INLINE inline __attribute__(( always_inline))
Run Code Online (Sandbox Code Playgroud)

yug*_*ugr 2

愚蠢的是,包装标志似乎不适用于放置在头文件中的函数。

这不是 的错wrap,该函数已被编译器内联,因此链接器无能为力。

如何在头文件中模拟这个函数?

一种选择是在将sed有问题的代码传递给 gcc 之前自动对其进行修补。例如改变

portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
  uint32_t ulNewBASEPRI;
  ...
}

portFORCE_INLINE static void vPortRaiseBASEPRI_2( void )
{
  uint32_t ulNewBASEPRI;
  ...
}
Run Code Online (Sandbox Code Playgroud)

从你的例子到

portFORCE_INLINE static void vPortRaiseBASEPRI( void );

portFORCE_INLINE static void vPortRaiseBASEPRI_2( void );
Run Code Online (Sandbox Code Playgroud)

cat tmp.c | sed '/inline\|INLINE/,/^}$/{ s/^\(.*\(inline\|INLINE\).*\)/\1;/; /inline\|INLINE/!d }'
Run Code Online (Sandbox Code Playgroud)

正则表达式非常草率,它依赖于标头中的所有定义都具有INLINE标记的事实,但在您的情况下可能应该足够了。

您可以将上述命令嵌入到 Makefile 中,以在临时文件夹中生成自定义标头,然后使用-Ipath/to/temp/folder标志覆盖默认标头。