#include <stdarg.h>
#include <setjmp.h>
#include <stddef.h>
#include <cmocka.h>
#include "stdint.h"
typedef enum {
eSTATE_STARTUP,
eSTATE_ADDRESSING,
eSTATE_RANDOMISE,
eSTATE_SELECTED
}e_State_t;
void test_main()
{
static e_State_t e_state = eSTATE_STARTUP;
if(get_rx_dali_flag())
{
application_process(&e_state);
}
switch(e_state)
{
case eSTATE_STARTUP:
{
set_led_frequency(0);
break;
}
case eSTATE_ADDRESSING:
{
set_led_frequency(1);
break;
}
case eSTATE_RANDOMISE:
{
set_led_frequency(10);
break;
}
case eSTATE_SELECTED:
{
set_led_frequency(100);
break;
}
default:
break;
}
}
int __wrap_get_rx_dali_flag(void)
{
int data_available = mock_type(uint8_t);
return data_available;
}
void __wrap_application_process(e_State_t * ptr_state)
{
check_expected_ptr(ptr_state);
*ptr_state = mock_type(e_State_t);
}
void __wrap_set_led_frequency(uint16_t frequency)
{
assert_int_equal(frequency, 1);
}
void main_should_setLedFreq_1_when_stateADDRESSING()
{
will_return(__wrap_get_rx_dali_flag, 1);
will_return(__wrap_application_process, eSTATE_ADDRESSING);
test_main();
}
int main()
{
const struct CMUnitTest tests[] =
{
cmocka_unit_test(main_should_setLedFreq_1_when_stateADDRESSING),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
SET(CMAKE_C_COMPILER "C:/msys64/mingw64/bin/gcc.exe")
SET(GCC_COVERAGE_COMPILE_FLAGS "-g")
project(beTheLight-unit-tests VERSION 1.0 LANGUAGES C)
include(cmake/FetchCMocka.cmake)
add_executable(beTheLight-unit-tests main.c)
target_compile_features(beTheLight-unit-tests PRIVATE c_std_99)
target_link_libraries(beTheLight-unit-tests PRIVATE cmocka-static)
enable_testing()
add_test(NAME beTheLight-unit-tests COMMAND beTheLight-unit-tests)
set_target_properties(beTheLight-unit-tests PROPERTIES LINK_FLAGS "-Wl, --wrap=get_rx_dali_flag, --wrap=set_led_frequency, --wrap=application_process")
==============================================================
[ 50%] Linking C executable beTheLight-unit-tests.exe
gcc.exe: error: unrecognized command-line option '--wrap=get_rx_dali_flag,'
gcc.exe: error: unrecognized command-line option '--wrap=set_led_frequency,'
gcc.exe: error: unrecognized command-line option '--wrap=application_process'
make[2]: *** [beTheLight-unit-tests.exe] Error 1
make[1]: *** [CMakeFiles/beTheLight-unit-tests.dir/all] Error 2
make: *** [all] Error 2
I am trying to get cmocka unit testing to work but for some reason the linker does not accept multiple --wrap linker flags. I have seen people doing it this way at another post in stackoverflow. I am using gcc version 10.3.0 built by MSYS2 project on win10.
Just use:
add_executable(beTheLight-unit-tests main.c)
target_link_options(beTheLight-unit-tests PUBLIC
-Wl,--wrap=get_rx_dali_flag
-Wl,--wrap=set_led_frequency
-Wl,--wrap=application_process
)
on older cmake use target_link_libraries. No need for set_target_properties.
Related
I want to specify during run-time to ignore a function call for a function (which is of course defined) inside my executable. Please suggest some methodology for doing the same in C language on Linux.
Probably the best you can do is something like this:
// Filename mycode.c
int main()
{
// ...
#ifndef SOME_MACRO
someFUnction();
#endif
//...
}
int someFUnction()
{
// does something
}
To exclude the function call in main, you need to compile with
gcc -DSOME_MACRO mycode.c
If you will compile simply as
gcc mycode.c
then the function call will be enabled.
You cannot ignore function calls at runtime, you either call the function or you don't.
But let's assume for the sake of this answer that there exists a condition under which the function gets called and at least another condition under which the function is not called.
You can tell the program these conditions in several ways, for example per command-line, change of environment/file, and probably a long list more. For simplicity let's use the command-line and give the conditions in form of a argument to the executable. Additionally, because it is simple and short, use a signal.
File optional_functions.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
static void a(void)
{
puts("Function \"a\" called");
}
static void b(void)
{
puts("Function \"b\" called");
}
static void c(void)
{
puts("Function \"c\" called (by signal SIGINT)");
}
#include<signal.h>
#include<unistd.h>
static void signal_handler(int signal_number)
{
if (signal_number == SIGINT) {
c();
exit(EXIT_SUCCESS);
}
}
int main(int argc, char **argv)
{
void *dynlib;
void (*function_d) (void);
char *dynlib_error;
if (argc == 2) {
if (argv[1][0] == 'a') {
a();
} else if (argv[1][0] == 'b') {
b();
} else if (argv[1][0] == 'd') {
puts("External function \"d\" wanted, loading library");
dynlib = dlopen("libfunctiond.so", RTLD_LAZY);
if (dynlib == NULL) {
fprintf(stderr, "Failed loading lib: %s\n", dlerror());
exit(EXIT_FAILURE);
}
*(void **) (&function_d) = dlsym(dynlib, "d");
dynlib_error = dlerror();
if (dynlib_error != NULL) {
fprintf(stderr, "Failed calling function \"d\" fom lib: %s\n",
dynlib_error);
exit(EXIT_FAILURE);
}
(*function_d) ();
} else {
fprintf(stderr, "A function named \"%c\" does not exist, bailing out\n",
argv[1][0]);
exit(EXIT_FAILURE);
}
} else {
if (signal(SIGINT, signal_handler) == SIG_ERR) {
fprintf(stderr, "signal catching failed, bailing out\n");
exit(EXIT_FAILURE);
}
sleep(5);
puts("Signal catching timed out, assuming no function wanted in the first place.");
}
exit(EXIT_SUCCESS);
}
File functiond.h
#ifndef FUNCTIOND_H
#define FUNCTIOND_H
void d(void);
#endif
File functiond.c
#include <stdio.h>
#include "functiond.h"
void d(void)
{
puts("Function \"d\" called and says hello from the library");
}
Compile as
clang -Weverything -fPIC -c functiond.c
clang -shared -Wl,-soname,libfunctiond.so.1 -o libfunctiond.so.1.0 functiond.o
ln -sf libfunctiond.so.1.0 libfunctiond.so.1
ln -sf libfunctiond.so.1 libfunctiond.so
clang -Weverything -o optional_functions optional_functions.c example.c -ldl
Run it
$ ./optional_functions # waiting 5 seconds
Signal catching timed out, assuming no function wanted in the first place.
$ ./optional_functions # press CTRL+c in less than 5 seonds
^CFunction "c" called (by signal SIGINT)
$ ./optional_functions 1
A function named "1" does not exist, bailing out.
$ ./optional_functions a
Function "a" called
$ ./optional_functions b
Function "b" called
$ ./optional_functions d
External function "d" wanted, loading library
Failed loading lib: libfunctiond.so: cannot open shared object file: No such file or directory
That was expected. Either give dlopen() the complete path to the library or let the environment variable LD_LIBRARY_PATH do the job:
$ LD_LIBRARY_PATH=. ./optional_functions d
External function "d" wanted, loading library
Function "d" called and says hello from the library
It is not the proper way to make, install and and use dynamic libraries, of course, but again: for the sake of simplicity…
Edit #1: Please find the solution as an answer to this initial post as a code example is used. Please try also to find a possible solution in What is an undefined reference/unresolved external symbol error and how do I fix it? It didn't help me, but maybe it's suitable for you.
I try to build a project which consists of each two header and application files. If I compile each file, no errors occure. If I build the project, I run into the below error.
cd 'D:\Master\M_32561\9000_A\B13-03'
P:\PortableApps\MinGW\msys\1.0\bin\make.exe -f Makefile CONF=Debug
"/P/PortableApps/MinGW/msys/1.0/bin/make.exe" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
make.exe[1]: Entering directory `/d/Master/M_32561/9000_A/B13-03'
"/P/PortableApps/MinGW/msys/1.0/bin/make.exe" -f nbproject/Makefile-Debug.mk dist/Debug/MinGW-Windows/b13-03.exe
make.exe[2]: Entering directory `/d/Master/M_32561/9000_A/B13-03'
mkdir -p dist/Debug/MinGW-Windows
gcc -o dist/Debug/MinGW-Windows/b13-03 build/Debug/MinGW-Windows/B13-03_F1.o build/Debug/MinGW-Windows/B13-03_MAIN.o
build/Debug/MinGW-Windows/B13-03_F1.o: In function `anzeigen_artikelbestand':
D:\Master\M_32561\9000_A\B13-03/B13-03_F1.c:283: undefined reference to `ausgeben_artikelbestand_mit_listenkopf'
build/Debug/MinGW-Windows/B13-03_MAIN.o: In function `main':
D:\Master\M_32561\9000_A\B13-03/B13-03_MAIN.c:39: undefined reference to `erfassen_artikel'
D:\Master\M_32561\9000_A\B13-03/B13-03_MAIN.c:42: undefined reference to `anzeigen_artikel'
D:\Master\M_32561\9000_A\B13-03/B13-03_MAIN.c:45: undefined reference to `aendern_artikel'
D:\Master\M_32561\9000_A\B13-03/B13-03_MAIN.c:48: undefined reference to `loeschen_artikel'
collect2.exe: error: ld returned 1 exit status
make.exe[2]: *** [dist/Debug/MinGW-Windows/b13-03.exe] Error 1
make.exe[2]: Leaving directory `/d/Master/M_32561/9000_A/B13-03'
make.exe[1]: *** [.build-conf] Error 2
make.exe[1]: Leaving directory `/d/Master/M_32561/9000_A/B13-03'
make.exe": *** [.build-impl] Error 2
The project consists of the following files:
B13-03_MAIN.h
B13-03_MAIN.c
B13-03_H1.h
B13-03_F1.c
The undefined functions are declared in B13-03_MAIN.h and defined in B13-03_MAIN.c. Both application files are using B13-03_MAIN.h as a prototype.
Thanks for any help is much aprreciated.
The issue dealt with an incorrect nesting of the undefined functions. I focus on B13-03_MAIN.h and B13-03_MAIN.c.
/* B13-03_MAIN.h */
create_article();
show_article();
edit_article();
delete_article();
Implementation w/ issue:
/* B13-03_MAIN.c */
#include <stdio.h>
#include "B13-03_MAIN.h"
#include "B13-03_H1.h"
void main(void) {
switch(option) {
case abc_c: create_article(); break;
case abc_s: show_article(); break;
case abc_e: edit_article(); break;
case abc_d: delete_article(); break;
default: printf("Undefined option.");
}
void create_article(void) {
...
}
void show_article(void) {
...
}
void edit_article(void) {
...
}
void delete_article(void) {
...
}
} /* This curly braces is incorrectly nested */
Implementation w/o issues:
void main(void) {
switch(option) {
case abc_c: create_article(); break;
case abc_s: show_article(); break;
case abc_e: edit_article(); break;
case abc_d: delete_article(); break;
default: printf("Undefined option.");
}
} /*Incorrectly nested curly brace should be implemented here */
void create_article(void) {
...
}
void show_article(void) {
...
}
void edit_article(void) {
...
}
void delete_article(void) {
...
}
I have a three files, Oracle.h, Oracle.dll, Oracle.lib.
These files are in same directory of main.c file.
And I want to include Oracle.h file.
#include <stdio.h>
#include "Oracle.h"
#pragma comment(lib, "Oracle.lib")
int main(void)
{
int crit;
char P[36] = { 0, };
char C[36] = { 0, };
int Clen = 36;
crit = Oracle(C, Clen);
printf("%d", crit);
return 0;
}
I used this code for main.c file, and compile by make main command.
But compiling this file has error, and I don't know what should I do.
$ make problem4_oracle
cc problem4_oracle.c -o problem4_oracle
/var/tmp/cc9oUwU3.o: In function main':
problem4_oracle.c:(.text+0x79): undefined reference to Oracle'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'problem4_oracle' failed
make: *** [problem4_oracle] Error 1
Please help me.
I tried to write a simple D Program and use it to access a simple C library but there is unknown error.
My c Code, Box.c
#include "Box.h"
int SayHello( int _int)
{
_int ++;
return _int;
}
My c header file, Box.h
#ifndef BOX_H_INCLUDED
#define BOX_H_INCLUDED
/* export interfaces */
#ifdef __cplusplus
extern "C" {
#endif
int SayHello( int _int);
#ifdef __cplusplus
}
#endif
#endif // BOX_H_INCLUDED
I compile it
gcc -c Box.c Box.h
resulting files
Box.o
Box.h.gch
I place them to my D Program's project directory
My D Code
module main;
import std.stdio;
import std.conv;
import std.c.stdio;
import clib;
int main(string[] args)
{
// test external c library
auto s = to!string( SayHello(3) ) ;
writefln( "my int is "~ s );
readln();
return 0;
}
My D interface file ( clib ), trying to link to my C library
module clib;
import std.c.stdio;
extern (C) int SayHello( int _int);
The error I get when I compile it using codeblocks
Compiling: hello.d
Linking console executable: bin/Debug/tutorial03-access-c-library4
obj/Debug/hello.o: In function `_Dmain':
/home/hamilton/Tutorial/tutorial03-access-c-library4/hello.d:11: **undefined reference to `SayHello'**
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
0 errors, 0 warnings
Error is "undefined reference to `SayHello'"
There is no error I get when I compile it using command in console
$ dmd Box.o hello.d clib.di
it will be very painful if I cannot use codeblocks as I need the debugging functionality.
Thanks
Update:
Compiler setting in codeblocks as followed
Linker for dynamic libs: gcc -m32 -lrt
Linker for static libs: ar
Debugger: gdb
You can change the build options in CodeBlocks from Project -> Build Options, Compiler settings -> Other options. The simplest thing to do would be to just add Box.o to Other options.
I have a main function, but when tcc goes to link everything together, it says its undefined. Why is this?
I'm using a python build script, and arguments are passed as lists:
['v:/exe/tcc/tcc.exe', '-odist/***.exe', '-Llib/', '-llua5.1', '-lsoil', '-lSDL', '-lopengl32', 'build/luainterface\\msL.o', 'build/luainterface\\vector.o', 'build/rendering\\renderutil.o', 'build/structures\\crtree.o', 'build/structures\\uniqueid.o', 'build/structures\\vector.o', 'build/world\\blocklib.o', 'build/world\\chunk.o', 'build/world\\world.o', 'build/main.o']
The output is simply:
tcc: undefined symbol 'main'
My main function is defined in the file main.c (and doesn't have a header), with a couple of static functions.
Main function:
int main(int argc, char *argv[])
{
SDL_Surface* screen = render_initialize(1024,768);
lua_State* L = luaL_newstate();
//lua_atpanic(L,&Lpanic);
msL_registerState(L);
msL_openAllLibs(L);
int fail = luaL_dofile(L,"lua/main.luac");
if(fail)
{
fprintf(stderr, "Lua error: %s\n", lua_tostring(L,-1));
doexit(1);
}
lua_getfield(L,LUA_GLOBALSINDEX,"draw");
if(!lua_isfunction(L,-1))
{
lua_pop(L,1);
fprintf(stderr, "No draw function defined in global scope\n");
doexit(1);
}
lua_setfield(L,LUA_REGISTRYINDEX,"msL_drawfunction");
while(1)
{
lua_getfield(L,LUA_REGISTRYINDEX,"msL_drawfunction");
assert(lua_isfunction(L,-1));
int err = lua_pcall(L,0,0,0);
if(err)
{
fprintf(stderr,"Lua error: ");
switch(err)
{
case LUA_ERRRUN:
fprintf(stderr,"%s",lua_tostring(L,-1));
break;
case LUA_ERRMEM:
fprintf(stderr,"out of memory");
break;
default:
fprintf(stderr,"unknown error");
}
fprintf(stderr,"\n");
doexit(1);
}
render_flipbuffers(screen);
}
doexit(0);
}
EDIT: I ran the code through tcc with preprocessing only. Apparently the main function is being renamed to SDL_main, through some macro in SDL.
Add -lSDLmain to linker flags.
http://wiki.libsdl.org/moin.cgi/FAQWindows#I_get_.22Undefined_reference_to_.27WinMain.4016.27.22
Although things may be a little different in tcc.