What I am doing:
I am using cmocka to run unit tests for large embedded project.
The embedded project is compiled with a arm-gcc-compiler
.
The unit tests are compiled with the normal gcc
using fragments of the embedded code and the cmocka library.
Normally cmocka recommends to use the -Wl,--wrap=functionName
flag to mock (replace) some unneeded sub-functions. This works pretty good.
The Problem:
Well, within my embedded code there is one header file (foo.h
), which contains some functions (declared as inline). One of these functions contains some assembler code for the arm-gcc-compiler
, which, of course, cannot be compiled by the gcc
.
Stupidly the wrap
-flag seems not to work on functions which are placed in header files.
Question:
How to mock this function in the headerfile away?
How I tried to solve the Problem:
I thought about inserting some #idef
macros to exclude the mentioned assembler section. But this cannot be done because this file belongs to a licensed library and I am not allowed to change its content.
I could extract my function-under-test into an additional files so that foo.h
doesn't need to be included anymore. But this would confuse the embedded source codes structure.
Exact lines of problem
The exact code is placed in portmacro.h of freeRtos at line 233:
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 )
);
}
where as portFORCE_INLINE
is defined as:
#define portFORCE_INLINE inline __attribute__(( always_inline))
Stupidly the wrap-flag seems not to work on functions which are placed in header files.
It's not the fault of wrap
, the function has been inlined by compiler so there's nothing linker can do.
How to mock this function in the headerfile away?
One option is to use sed
to automatically patch the offending code before passing it to gcc. E.g. to change
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI;
...
}
portFORCE_INLINE static void vPortRaiseBASEPRI_2( void )
{
uint32_t ulNewBASEPRI;
...
}
from your example to
portFORCE_INLINE static void vPortRaiseBASEPRI( void );
portFORCE_INLINE static void vPortRaiseBASEPRI_2( void );
do
cat tmp.c | sed '/inline\|INLINE/,/^}$/{ s/^\(.*\(inline\|INLINE\).*\)/\1;/; /inline\|INLINE/!d }'
The regex is quite sloppy, it relies on the fact that all definitions in header will have the INLINE
marker but should probably be enough in your case.
You can embed above command into your Makefile to generate custom header in a temp folder and then override default header with -Ipath/to/temp/folder
flag.