Multiple includes of header only library causing redefinition errors

898 views Asked by At

I'm using a header only library called Nuklear. It's a header only library. I'm having trouble when using multiple includes from different files. It returns a multiple definition example:

...
obj/main.o:main.c:(.text+0x4a52b): multiple definition of `nk_sdl_font_stash_begin'
obj/components.o:components.c:(.text+0x4a56f): first defined here
obj/main.o:main.c:(.text+0x4a563): multiple definition of `nk_sdl_font_stash_end'
obj/components.o:components.c:(.text+0x4a5a7): first defined here
obj/main.o:main.c:(.text+0x4a5f4): multiple definition of `nk_sdl_handle_event'
obj/components.o:components.c:(.text+0x4a638): first defined here
obj/main.o:main.c:(.text+0x4ac9f): multiple definition of `nk_sdl_shutdown'
obj/components.o:components.c:(.text+0x4ace3): first defined here

I'm attempting to include the library into 2 files.

main.c

#define SDL_MAIN_HANDLED
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>

#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_IMPLEMENTATION
#define NK_SDL_GL3_IMPLEMENTATION
#include "nuklear.h"
#include "nuklear_sdl_gl3.h"
#include "components.h"
...

components.c

#define SDL_MAIN_HANDLED
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>

#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_IMPLEMENTATION
#define NK_SDL_GL3_IMPLEMENTATION
#include "nuklear.h"
#include "nuklear_sdl_gl3.h"

The Nuklear library already includes header guards so I'm not sure why this error is happening. Any advice?

3

There are 3 answers

0
Jonathan Leffler On BEST ANSWER

From the README at GitHub:

This library is self contained in one single header file and can be used either in header only mode or in implementation mode. The header only mode is used by default when included and allows including this header in other headers and does not contain the actual implementation.

The implementation mode requires to define the preprocessor macro NK_IMPLEMENTATION in one .c/.cpp file before #includeing this file, e.g.:

#define NK_IMPLEMENTATION
#include "nuklear.h"

So, only one of main.c and components.c should include the #define NK_IMPLEMENTATION — yet you define it in both.

Fix

  • Remove #define NK_IMPLEMENTATION from components.c.
  • Do not include any other Nuklear header than nuklear.h — the instructions don't tell you to do that (at least, not on the surface; maybe there's something elsewhere that says so, but …).

The documentation also notes:

IMPORTANT: Every time you include "nuklear.h" you have to define the same optional flags. This is very important not doing it either leads to compiler errors or even worse stack corruptions.

It would probably be worth having your own header — use_nuklear.h for example, though I'm sure you'll think of a better name — that contains the correct set of NK_* options (all except NK_IMPLEMENTATION). Then #include "use_nuklear.h" in your source files. That way, if (when) you change options, you have only one place to change — and the rebuilds will be consistent.

0
0___________ On

nuklear_sdl_gl3.h contains data and functions. It is just very badly written. All definitions should be in the .c files and only declaration, type definitions, extern variables declarations and static inline functions should be in the header file.

You cant include this file more than once in the whole project. The guards do not work here as it is included in different compilations units.

1
brhans On

You should only #define NK_SDL_GL3_IMPLEMENTATION in one of your .c source files before you #include "nuklear_sdl_gl3.h".

The nuklear_sdl_gl3.h file contains all the function definitions, as well as function declarations, and you only want the definitions in one place or, as you've found, your linker will complain.