0

I'm trying to learn how to use the SDL2 KISS project/toolkit/library-thing, via the example provided in the manual (found on page 4). Whenever I link it, however, it fails, citing duplicate symbol errors. The two example files provided in the repo build, compile, and work fine.

My hypothesis is that because I'm trying to write the example code from the manual into a C++ file, and the library is pure C89, there is some angry internal compiler explosion going on. If I forward declare a C function with the same code, everything seems to be okay, but I'd really like to not have a bunch of C++ files that exist purely as delegates to call C functions.

It does say in the project readme (at the end of the first paragraph) that everything is C++ compatible, and is actually written in the same way that the SDL2 library is written- which I can use without issue. The SDL2 KISS header seems to be correctly setup for use with C++, using:

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
};
#endif

As far as possible causes for the Undefined symbols for architecture x86_64 linker errors go, I have three suspects: my ignorance about mixing pure C with C++, the CMakeLists I wrote for the project, or an issue in the library itself (which I think is incredibly unlikely). I've been messing with different potential solutions for a few days, but haven't come across anything better than forward declaring (which, again, I don't want to do). Bellow you'll find the exact errors, my main.cpp file, which contains exclusively the code from the manual, and the CMakeLists file I wrote. The code posted does not build for me, but I can post the working C++ file which forward declares a C function, if that would be helpful.

Make error from terminal

Scanning dependencies of target Test_KISS
[ 16%] Linking CXX executable bin/Test_KISS
duplicate symbol _kiss_border in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_green in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_progress_interval in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_click_interval in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_black in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_slider_padding in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_spacing in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_textfont_size in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_buttonfont_size in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_lightblue in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_blue in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_white in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
duplicate symbol _kiss_edge in:
    CMakeFiles/Test_KISS.dir/src/main.cpp.o
    CMakeFiles/Test_KISS.dir/include/kiss_draw.c.o
ld: 13 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [bin/Test_KISS] Error 1
make[1]: *** [CMakeFiles/Test_KISS.dir/all] Error 2
make: *** [all] Error 2

main.cpp

#include "kiss_sdl.h"


void button_event(kiss_button *button, SDL_Event *e, int *draw, int *quit)
{
    if (kiss_button_event (button, e, draw))
        *quit = 1;
}

int main (int argc, char *argv[])
{

    SDL_Renderer *renderer;
    SDL_Event e;

    kiss_array objects;
    kiss_window window;
    kiss_label label;
    kiss_button button;

    char message[KISS_MAX_LENGTH];
    int draw = 1;
    int quit = 0;

    kiss_array_new (&objects);
    renderer = kiss_init ("Test KISS SDL", &objects, 320, 120);
    kiss_window_new (&window, NULL, 0, 0, 0, kiss_screen_width, kiss_screen_height);
    strcpy (message, "Hello, world!");

    kiss_label_new (&label, &window, message, window.rect.w / 2 - strlen (message) * kiss_textfont.advance / 2, window.rect.h / 2 - (kiss_textfont.fontheight + 2 * kiss_normal.h) / 2);
    label.textcolor.r = 255;

    kiss_button_new (&button, &window, "Okay", window.rect.w / 2 - kiss_normal.w / 2, label.rect.y + kiss_textfont.fontheight + kiss_normal.h);
    window.visible = 1;

    while (!quit)
    {

        SDL_Delay (10);
        while (SDL_PollEvent (&e))
        {

             if (e.type == SDL_QUIT)
                 quit = 1;

             kiss_window_event (&window, &e, &draw);
             button_event (&button, &e, &draw, &quit);
        }

        if (!draw)
            continue;

        SDL_RenderClear (renderer);
        kiss_window_draw (&window, renderer);
        kiss_label_draw (&label, renderer);
        kiss_button_draw (&button, renderer);
        SDL_RenderPresent (renderer);
        draw = 0;
    }

    kiss_clean (&objects);
    return 0;
}

CMakeLists

cmake_minimum_required(VERSION 3.3)
project(Test_KISS)


set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${Test_KISS_SOURCE_DIR}/cmake")
set(BIN_DIR ${Test_KISS_SOURCE_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)


#Define Preprocessor Macros (RESDIR found in include/kiss_sdl.h)
add_definitions(-DRESDIR=\"../../resources/\")


find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIR})

find_package(SDL2_ttf REQUIRED)
include_directories(${SDL2_TTF_INCLUDE_DIR})

find_package(SDL2_image REQUIRED)
include_directories(${SDL2_IMAGE_INCLUDE_DIR})

include_directories(include)


add_executable(Test_KISS src/main.cpp include/kiss_draw.c include/kiss_general.c include/kiss_posix.c include/kiss_widgets.c)


target_link_libraries(Test_KISS ${SDL2_LIBRARY} ${SDL2_TTF_LIBRARY} ${SDL2_IMAGE_LIBRARY})
install(TARGETS Test_KISS RUNTIME DESTINATION ${BIN_DIR})

If I can provide any more information to help, please let me know!

Thanks!

Michael Bethke
  • 170
  • 4
  • 17

2 Answers2

2

kiss_sdl.h actually defines numerous variables:

double kiss_spacing;
int kiss_textfont_size, kiss_buttonfont_size;
int kiss_click_interval, kiss_progress_interval;
int kiss_slider_padding;
int kiss_border, kiss_edge;
int kiss_screen_width, kiss_screen_height;

Those variables get defined in every C/C++ file that #include's the file. Thus you get duplicate symbols - because there are duplicate symbols.

The fix? Fix the code so that it properly declares the variables instead of defining them.

In other words, the code is broken.

Community
  • 1
  • 1
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • Thank you for the answer! I'll look into this more, but should I report back to the library's creator, or is this something I've done wrong? Also, what code should be fixed, the header, or a different file? – Michael Bethke May 20 '16 at 16:16
  • @MichaelBethke - A header file meant for inclusion into multiple files that use a library should not *define* variables like that. Without digging into the library code and its documentation, I can't really say *how* best to fix it - and that would only be my opinion anyway. If you're using it as the documentation says to, the only way you'll get it to work is to either use a link-time option to accept duplicate symbols, or change your code in such a way that you include that header file in just one of your source files. – Andrew Henle May 20 '16 at 16:21
  • Alright, thanks for the input! I'll contact the library creator to see what they say about reviewing the header's definitions. Thank you! – Michael Bethke May 20 '16 at 16:30
0

It is fixed now. extern "C" though means that the declarations under it are like C++, and the rest of the code is compiled like C, like mine is C89. If compiled with a C compiler, and files with c extension. Rightly understanding this is what fixed the problem.

Simple universal GUI widget toolkit for SDL2 https://github.com/actsl/kiss_sdl , written by me.