0

I'm having a heck of a time understanding the CMake documentation. Most of my programming life has been in C#. So, this is new.

What I have is a directory structure like so:

- bin/  
  -- <empty>  
- include/  
  -- cmocka.h  
  -- cmocka_pbc.h  
  -- cmocka_private.h  
- lib/  
  -- libcmocka.dll.a  
- src/  
  -- jargon/  
  |  -- <*.c *.h>  
- testing/  
  -- jargon_test/  
  |  -- main.c (executable console)  
  |  -- <*.c *.h>  

I've been working on CMakeLists.txt as follows:

cmake_minimum_required(VERSION 3.20)
project(jargon_test C)

set(CMAKE_C_STANDARD 11)

add_executable(jargon_test main.c token_tests.h token_tests.c)

include_directories(
        "../../src/jargon/"
        "../../include"
)

add_library(cmocka SHARED IMPORTED)
set_target_properties(cmocka
        PROPERTIES
        IMPORTED_LOCATION "../../lib/libcmocka.dll.a"
        INTERFACE_INCLUDE_DIRECTORIES "../../include/cmocka"
)

I'm using CLion 2021.2.3.

Trying to build, I get the following errors:

CMakeFiles\jargon_test.dir/objects.a(token_tests.c.obj): In function test_hello': *directory*:29: undefined reference to _assert_true`

CMakeFiles\jargon_test.dir/objects.a(token_tests.c.obj): In function run_token_tests': *directory*:47: undefined reference to _cmocka_run_group_tests`

The source itself has no issues. But, for completeness, here are the source files:

// token_tests.h
#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdint.h>
#include <cmocka.h>

#include "jargon.h"


#ifndef JARGON_TOKEN_TESTS_H
#define JARGON_TOKEN_TESTS_H

void test_hello(void ** state);

int setup(void ** state);
int teardown(void ** state);

int run_token_tests(void);
#endif //JARGON_TOKEN_TESTS_H


// token_tests.c
#include "token_tests.h"


void test_hello(void ** state) {
    int ret = 0;
    assert_true(ret == 0);
}

int setup (void ** state) {
    printf("executing test\n");

    return 0;
}

int teardown (void ** state) {
    return 0;
}

int run_token_tests(void) {
    const struct CMUnitTest tests [] = {
            cmocka_unit_test(test_hello)
    };

    int count_fail_tests = cmocka_run_group_tests(tests, setup, teardown);

    return count_fail_tests;
}
IAbstract
  • 19,551
  • 15
  • 98
  • 146
  • 1
    At first glance you should not add token_tests.h to the executable, and you should link cmocka to the executable via target_link_libraries(). Also it's better to use target_include_directories(). – Nickolay Olshevsky Nov 17 '21 at 17:52
  • @NickolayOlshevsky: can you put that into an answer with examples? I've been trying to follow the CMake documentation and it misses out on some information that is assumed I know. FYI: CLion added the .h file to the executable. – IAbstract Nov 17 '21 at 17:57
  • @fabian: thanks for formatting the directory structure. I couldn't figure out how to make that work. – IAbstract Nov 17 '21 at 17:58
  • The `.a` extension usually indicates a static library. You seem to be using mingw. Not sure if this requires you to specify the `.a` part as `IMPORTED_IMPLIB` or even as static library in this case. (I don't have experience with mingw) – fabian Nov 17 '21 at 18:02
  • @fabian: correct. I am using MinGW. I loaded up the directory as supplied by CMocka into CLion. – IAbstract Nov 17 '21 at 18:10
  • It should be `target_link_libraries` call which links your executable `jargon_test` with the library `cmocka`. – Tsyvarev Nov 17 '21 at 18:10
  • @Tsyvarev: supply an answer with your example fix, please. – IAbstract Nov 17 '21 at 18:11
  • It's hard to type in example without ability to reproduce it, but this link should be helpful: https://discourse.cmake.org/t/how-to-statically-link-external-library-by-target-link-libraries/1718 – Nickolay Olshevsky Nov 17 '21 at 18:28
  • @IAbstract: So the problem is that you forgot to call `target_link_libraries`, am I correctly understand your last comment? In that case the question seems to be of "typo" type. Because this call is noted in every answer to the question about linking external libraries: https://stackoverflow.com/questions/8774593/cmake-link-to-external-library. – Tsyvarev Nov 17 '21 at 18:31
  • @NickolayOlshevsky: just an example of what the CMakeList should look like since this is where the problem is. I understand that you cannot give a definitive answer, "This works." I'm having difficulty with examples because explanations are minimal. – IAbstract Nov 17 '21 at 18:45

1 Answers1

0

It seems the cmocka library is not linked to your executable, add target_link_libraries(jargon_test cmocka)

Also, maybe some of your function definitions (implementation in c files) are not given to the cmake script.

Try to update your cmake script like this:

e been working on CMakeLists.txt as follows:

cmake_minimum_required(VERSION 3.20)
project(jargon_test C)

set(CMAKE_C_STANDARD 11)

add_executable(jargon_test main.c token_tests.h token_tests.c ../../src/jargon/xxxx.c)

include_directories(
        "../../src/jargon/"
        "../../include"
)

add_library(cmocka SHARED IMPORTED)
set_target_properties(cmocka
        PROPERTIES
        IMPORTED_LOCATION "../../lib/libcmocka.dll.a"
        INTERFACE_INCLUDE_DIRECTORIES "../../include/cmocka"
} 

target_link_libraries(jargon_test cmocka) 

To have more clean cmake scripts, try to adopt a top to down approach (with a top level CMakeLists.txt including other ones located in subdirectories) and to declare a "jargon" library in your src/jargon folder. Thus, in your test folder you will only have to add c test files and to link your "jargon" library and your test harness.

quent
  • 1,936
  • 1
  • 23
  • 28
  • Added the `target_link_libraries` and I get `Imported target "cmocka" includes non-existent path "../../include/cmocka"` ... so trying to figure this thing out. :/ – IAbstract Nov 17 '21 at 21:43
  • Try to set `INTERFACE_INCLUDE_DIRECTORIES "../../include"` instead of `INTERFACE_INCLUDE_DIRECTORIES "../../include/cmocka"` – quent Nov 17 '21 at 22:38