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.
I've not used cmocka so I'm unsure if there is a method for managing this already within the framework.
However, cmock uses a method whereby the header is copied to a location somewhere higher in the include hierarchy of the test build (and only the test build, the location is not included even implicitly by the release build).
The copy of this header then can be edited such that the function declaration simply becomes port void vPortRaiseBASEPRI( void );. Then when the mocks are generated a mock is generated for this (and the other function declarations within the same header) just like in any other case. Because hte mocks are being generated it does not matter that there is no matching source code definition (i.e. .c file) for the function(s).
See the "Dealing with compiler-specific stuff" section at https://dmitryfrank.com/articles/unit_testing_embedded_c_applications
And my similar question and how I solved it here: Unit test C with compiler specific keywords
Related
I'm working on a project which requires to develop the firmware for several esp32. All the microcontrollers share a common code that takes care of wifi and mqtt, however they all have a different behavior, which is defined in a specific component. The structure of my project is something like this:
- CMakeLists.txt
- Makefile
- sdkconfig
- main
- CMakeLists.txt
- main.c
- components
- wifi_fsm
- wifi_fsm.h
- wifi_fsm.c
- CMakeLists.txt
- mqtt_fsm
- mqtt_fsm.h
- mqtt_fsm.c
- CMakeLists.txt
- entity_1
- entity_1.h
- entity_1.c
- CMakeLists.txt
- entity2
- entity2.h
- entity2.c
- CMakeLists.txt
...
Each entity defines some functions with standard names, which implement specific logic for the entity itself and which are called within the shared code (main, wifi_fsm, mqtt_fsm).
void init_entity(); // called in main.c
void http_get(char *buf); // called in wifi_fsm
void http_put(char *buf);
void mqtt_msg_read(char *buf); // called in mqtt_fsm
void mqtt_msg_write(char *buf);
My idea was to have a conditional statement to include at will a specific behavior, so that depending on the entity included, the compiler would link the calls to the functions above to those found in the specific included library. Therefore, at the beginning of main.c I just added the following lines with the goal of having to change the only defined pre-processor symbol to compile for different enity behaviors.
#define ENTITY_1
#ifdef ENTITY_1
#include "entity_1.h"
#elif defined ENTITY_2
#include "entity_2.h"
#elif ...
#endif
#include "wifi_fsm.h"
#include "mqtt_fsm.h"
void app_main(void)
{
while(1){
...
}
}
On the one hand the compiler apparently works fine, giving successful compilation without errors or warnings, meaning that the include chain works correctlty otherwise a duplicate name error for the standard functions would be thrown. On the other hand, it always links against the first entity in alphabetical order, executing for instance the code included in the init_entity() of the component entity_1. If I rename the standard functions in entity_1, then it links against entity_2.
I can potentially use pointers to standard calls to be linked to specific functions in each entity if the approach above is wrong, but I would like to understand first what is wrong in my approach.
EDIT in response to Bodo's request (content of the CMakeFile.txt)
Project:
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(proj)
Main:
set(COMPONENT_REQUIRES )
set(COMPONENT_PRIV_REQUIRES )
set(COMPONENT_SRCS "main.c")
set(COMPONENT_ADD_INCLUDEDIRS "")
register_component()
Component:
set(COMPONENT_SRCDIRS "src")
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_REQUIRES log freertos driver nvs_flash esp_http_server mqtt)
register_component()
This answer is based on guessing because I don't have enough information. For the same reason it is incomplete in some parts or may not fully match the use case of the question.
The details about how the project will be built seems to be hidden in a cmake include file like project.cmake or nested include files.
My guess is that the build system creates libraries from the source code of every individual component and then links the main object file with the libraries. In this case, the linker will find a symbol like init_entity in the first library that fulfills the dependency. This means the library (=component) listed first in the linker command line will be used.
If the linker command line would explicitly list the object files entity_1.o and entity_2.o, I would expect an error message about a duplicate symbol init_entity.
I can propose two ways to solve the problem:
Make sure only the selected entity is used to build the program.
Make the identifier names unique in all entities and use preprocessor macros to choose the right one depending on the selected entity.
For the first approach you can use conditionals in CMakeLists.txt. See https://stackoverflow.com/a/15212881/10622916 for an example. Maybe the register_component() is responsible for adding the component to the build. In this case you could wrap this in a condition.
BUT modifying the CMakeLists.txt might be wrong if the files are generated automatically.
For the second approach you should rename the identifiers in the entities to make them unique. The corresponding header files can define a macro to replace the common name intended for the identifier with the specific identifier of the selected entity.
In the code that uses the selected entity you will always use the common name, not the individual names.
Example:
entity_1.c:
#include "entity_1.h"
void init_entity_1(void)
{
}
entity_2.c:
#include "entity_2.h"
void init_entity_2(void)
{
}
entity_1.h:
void init_entity_1(void);
// This replaces the token/identifier "init_entity" with "init_entity_1" in subsequent source lines
#define init_entity init_entity_1
// or depending on the parameter list something like
// #define init_entity() init_entity_1()
// #define init_entity(x,y,z) init_entity_1(y,x,z)
entity_2.h:
void init_entity_2(void);
#define init_entity init_entity_2
main.c
#define ENTITY_1
#ifdef ENTITY_1
#include "entity_1.h"
#elif defined ENTITY_2
#include "entity_2.h"
#elif ...
#endif
void some_function(void)
{
init_entity();
}
In this example case with #define ENTITY_1, the preprocessor will change some_function to
void some_function(void)
{
init_entity_1();
}
before the compilation step and the linker will use init_entity_1 from entity_1.c. An optimizing linker may then omit the object file entity_2.o or the corresponding library because it is unused.
I have a small static library project that I'm rewriting from building with Makefiles to modern CMake, which I am trying to learn.
My project uses assertions quite heavily for checking preconditions, so I have written a very simple custom assertion macro that conditionally expands into a function that prints formatted diagnostics and then aborts if the library was compiled in debug mode, or expands to nothing if the library was compiled in release mode.
However, I want to be able to test whether these assertions fire correctly. Cmocka allows you to test this by calling mock_assert in library code, which cmocka will intercept as part of testing. To this end, I want to have another macro, say LIBRARY_TESTING, that will redefine my custom assertion macro to invoke mock_assert instead of my own assertion function, so assertions can be tested. The final assertion macro can be considered morally equivalent to the following:
// In file include/assertion.h
#ifdef LIBRARY_DEBUG
#ifdef LIBRARY_TESTING
// mock_assert is provided by cmocka
void mock_assert(
int const result,
char const *const expression,
char const *const file,
int const line);
#define ASSERT(cond) \
mock_assert((cond), #cond, __FILE__, __LINE__)
#else
// emit_assertion is defined in src/assertion.c
void emit_assertion(int cond, char const *const msg);
#define ASSERT(cond) emit_assertion((cond), #cond)
#endif
#else
#define ASSERT(cond) // Nothing
#endif
I have been able to get the desired behaviour for building in debug mode (where ASSERT expands to a call to emit_assertion) and release mode (where ASSERT expands into nothing, as desired) through the following Cmake snippet in src/CMakeLists.txt):
target_compile_options(library PRIVATE
$<$<CONFIG:Debug>:-Og -ggdb3 -DLIBRARY_DEBUG >>
$<$<CONFIG:Testing>:-Og -ggdb3 -DLIBRAY_DEBUG -DLIBRARY_TESTING >>
)
From which building with either -DCMAKE_BUILD_TYPE=Debug or -DCMAKE_BUILD_TYPE=Release produces the intended behaviour. Extrapolating how CONFIG works here, I also added a generator expression that checks Testing, which defines BASIC_TESTING when compiling. All is well so far.
I start to run into problems when executing unit tests. For the purposes of exposition, the function that I want to test is equivalent to this, defined in include/example.h:
static inline bool example(int *arg)
{
ASSERT(arg != NULL);
return *arg == 0;
}
With a corresponding unit test in tests/example.c:
#include "example.h"
#include <cmocka.h>
// Other cmocka required #includes
static void test_example(void **state)
{
(void) state;
expect_assert_failure(example(NULL));
}
And the contents of test/CMakeLists.txt:
add_executable(example
${CMAKE_CURRENT_SOURCE_DIR}/example.c
)
add_test(example example)
target_include_directories(example PRIVATE
"${PROJECT_SOURCE_DIR}/include"
)
# 'library' is the static library target defined in the top-level
# CMakeLists.txt
target_link_libraries(example library cmocka)
Now, in order to unit test my library, I want my custom assertions to expand to mock_assert, so I compile my library for testing (as I understand it):
# In ./build
$ cmake -DCMAKE_BUILD_TYPE=Testing .. && make
Everything builds correctly and I have my static library liblibrary.a where I expect it to be. Additionally, my test executable example also compiles and links successfully, but when I run it, the test fails with a segmentation fault as if my custom assertion was never called (and the function attempts to dereference the NULL pointer I intentionally gave it to trigger the assertion). I am reasonably confident that there were no issues linking with cmocka itself, because running the test results in cmocka's fancy command-line output formatting.
In my original makefile-oriented build, all test executable targets would compile a special "testing" library target, and the test executables link to this library target and all assertions are correctly intercepted by cmocka as I would expect. However, in this case, it appears as if the static library I compiled is behaving as if neither LIBRARY_DEBUG or LIBRARY_TESTING were defined -- as evidenced by the segmentation fault.
I'm very new to modern cmake, so I feel like I am misunderstanding something conceptual. My question is:
How can I ensure that my static library is compiled with a particular (set of) compilation option(s) (here it is -DBASIC_TESTING) to ensure that the custom assertions that it fires can be tested with cmocka?
I solved this problem by defining a new library target specifically for building the testing library, and linked all test executables to the testing library.
I had to set the compile options on the testing library target to PUBLIC for these options to apply to building the testing targets. I then no longer had any use for the generator expression in the compile options for library-testing as it was implied that this target will only ever be built for linking with testing executables.
In src/CMakeLists.txt
add_library(
library,
src/example.c)
+add_library(
+ library-testing,
+ src/example.c)
target_compile_options(library PRIVATE
$<$<CONFIG:Debug>:-Og -ggdb3 -DLIBRARY_DEBUG >>
)
+target_compile_options(library-testing PUBLIC
+ -Og -ggdb3 -DLIBRARY_DEBUG -DLIBRARY_TESTING
+)
And then in test/CMakeLists.txt:
add_executable(example
${CMAKE_CURRENT_SOURCE_DIR}/example.c
)
add_test(example example)
target_include_directories(example PRIVATE
"${PROJECT_SOURCE_DIR}/include"
)
# Link with library-testing target instead of library target
-target_link_libraries(example library cmocka)
+target_link_libraries(example library-testing cmocka)
After making these changes my test executables all behaved as expected.
Let's say I have two files named "AA.c", "BB.c"
/* in AA.c */
inline void AA(void) __attribute__((always_inline));
void AA()
{
/* do something */
}
and then
/* in BB.c */
#include "AA.c"
extern void funcAA(void);
int main(void)
{
funcAA();
return 0;
}
does funcAA( ) also become inline???
no matter the answer is yes or no, could you explain some more about the under the hood??
including a .c file is equivalent of copying and pasting the file contents directly in the file which includes that, exactly like if the function was directly defined in the including file.
You can see what the compiler is going to compile by trying to compile your file with -E flag (preprocessor output). You'll see your function pasted-in.
So it will be inline just because of the inline keyword, and forced with the always_inline attribute even if the compiler would have refused to inline it because of function size for instance.
Word of advice: know what you're doing when including a .c file from another one. Some build systems/makefiles just scan the directories looking for files called *.c so they can compile them separately. Putting a possibly non-compiling C file there can make the build fail, and if it builds, you could have duplicate symbols when linking. Just don't do this.
If you want to do this, put your function in a .h file and declare it static so it won't fail the link if included in many .c files (each function will be seen as different)
I'm having an issue with compiling code for Arduino if the code is in multiple files. What I have been doing in the past is have a script concatenate the files in another directory and make the project there. I would like to be able to compile directly from my build folder without having to jump through hoops of making sure everything is defined in the right order, etc.
I'm using avrdude to compile from Linux command line, because the Arduino IDE doesn't work very well with my window manager. When I make with multiple files (with appropriate #include statements, I get errors of the following nature, but for all of my methods and variables.
./../lib/motor.ino:3:21: error: redefinition of ‘const long unsigned int MOVE_DELAY’
./../lib/motor.ino:3:21: error: ‘const long unsigned int MOVE_DELAY’ previously defined here
The only other place that MOVE_DELAY is used is inside the void loop() function, and it doesn't redefine it there. The code also compiles fine if concatenate it into one file and run make in that directory, but not if they are in separate files with includes.
I believe your problem is solvable by declaring the objects with the "extern" prefix or external. For example. I often use the SdFat library, in which it is included in both my main sketch and instanced in other libraries.
/**
* \file test.ino
*/
#include <SdFat.h>
#include <foo.h>
SdFat sd;
...
Where I also use the same object in other libraries, such as foo.h.
/**
* \file foo.h
*/
#include <SdFat.h>
extern SdFat sd;
...
If it was not for the prefix of "extern" it would error like yours, as "sd" can not exist twice. Where the extern prefix tells the linker don't make a new instantiation, rather link to the externally instance elsewhere.
How can I go about reusing the same kernel without getting fatal linker errors due to defining the symbol multiple times?
In Visual Studio I get:
"fatal error LNK1169: one or more multiply defined symbols found"
I have three files: Interface.h, Kernel.cu, and Wrapper.cu. My current structure is as follows (ala the "C++ integration" SDK example):
//Interface.h
extern "C" void myCfunction( ... );
//Kernel.cu
__global__ void my_kernel( ... );
//Wrapper.cu
#include "Interface.h"
#include "Kernel.cu"
extern "C" void myCfunction( ... );
void myCfunction( ... ) {
// Call CUDA kernel in Kernel.cu
my_kernel<<< ... >>>( ... );
}
This all works fine.
But if I add another C function in another file which also includes Kernel.cu and uses those kernels, I get the above error. e.g.
//NewWrapper.cu
#include "Kernel.cu"
extern "C" void myNewCfunction( ... );
void myNewCfunction( ... ) {
// Call CUDA kernel in Kernel.cu
my_kernel<<< ... >>>( ... );
// Now I get linker errors...
}
So how can I reuse the kernels in Kernel.cu among many C functions in different files.
The purpose of this by the way is unit testing, and integrating my kernels with CPP unit, if there is no way to reuse kernels (there must be!) then other suggestions for unit testing kernels within my existing CPP unit framework would be appreciate.
Create launcher functions and reference them from a header which will be included from multiple locations.
In .cu file:
__global__ myKernel(){...}
void myKernelLauncher(){ myKernel<<<...>>>()...}
In .h file
void myKernelLauncher();
The solution that usually works for me is to compile a library out of all the cu files and
create entry points to initialize the kernel.
Otherwise put all the common functions inside a .cuh and wrap it if #IFDEF _MYHEADER_H