Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with NK_STATIC_ASSERT during compilation in MSYS2 #747

Open
rjopek opened this issue Nov 25, 2024 · 10 comments
Open

Issue with NK_STATIC_ASSERT during compilation in MSYS2 #747

rjopek opened this issue Nov 25, 2024 · 10 comments

Comments

@rjopek
Copy link

rjopek commented Nov 25, 2024

Hi,

I am working on creating Nuklear bindings for xBase family languages. During compilation in MSYS2, I encountered the following errors:

nuklear.h:301:61: error: size of array '_dummy_array443' is negative
  301 |   #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
nuklear.h:443:1: note: in expansion of macro 'NK_STATIC_ASSERT'
  443 | NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
nuklear.h:444:1: note: in expansion of macro 'NK_STATIC_ASSERT'
  444 | NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));  

The only way to bypass this issue and successfully compile the library and example was to comment out the following lines:

// NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
// NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));

This allowed me to proceed with testing, but I understand that this is not a proper solution.

The problem occurs only in the MSYS2 environment – everything works correctly under Linux.

What can be done to address this issue?

@rjopek
Copy link
Author

rjopek commented Nov 26, 2024

To address the issue with NK_STATIC_ASSERT in environments like MSYS2/MinGW, I would like to propose the following solution:

#ifdef NK_NO_STATIC_ASSERT
    #define NK_STATIC_ASSERT(exp)
#else
    #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
#endif

This change introduces the NK_NO_STATIC_ASSERT macro, which allows users to disable static assertions when needed by defining it during compilation (-DNK_NO_STATIC_ASSERT). By default, the static assertions remain active, ensuring backward compatibility.

@riri
Copy link
Contributor

riri commented Nov 26, 2024

The solution is not to disable static asserts, but to fix what's not working on this platform :)
I'll check those later as I have an MSYS2 env at work.
Is there a specific demo/example your are compiling so that I check from the same?

@rjopek
Copy link
Author

rjopek commented Nov 26, 2024

After further consideration, I would like to propose an alternative solution to address the issue with NK_STATIC_ASSERT in MSYS2/MinGW environments.

#if defined(__MINGW32__) || defined(__MINGW64__)
    // MSYS2/MinGW environment: skip static assertions
    #define NK_STATIC_ASSERT(exp)
#else
    // Default behavior
    #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
#endif

@riri
Copy link
Contributor

riri commented Nov 26, 2024

As there is no existing compilation example for MSYS2, could you show how you invoke the compiler?
aka gcc/clang? which flags?

I made a quick test on demo/gdi with gcc, and out of linking errors, I don't have any compilation one.

@rjopek
Copy link
Author

rjopek commented Nov 26, 2024

This is what my report looks like.

C:/hbnk/include/nuklear.h:301:61: error: size of array '_dummy_array443' is negative
  301 |   #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
      |                                                             ^~~~~~~~~~~~
C:/hbnk/include/nuklear.h:290:46: note: in definition of macro 'NK_STRING_JOIN_IMMEDIATE'
  290 | #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
      |                                              ^~~~
C:/hbnk/include/nuklear.h:292:36: note: in expansion of macro 'NK_STRING_JOIN_DELAY'
  292 | #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
      |                                    ^~~~~~~~~~~~~~~~~~~~
C:/hbnk/include/nuklear.h:297:32: note: in expansion of macro 'NK_STRING_JOIN'
  297 |   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
      |                                ^~~~~~~~~~~~~~
C:/hbnk/include/nuklear.h:301:46: note: in expansion of macro 'NK_UNIQUE_NAME'
  301 |   #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
      |                                              ^~~~~~~~~~~~~~
C:/hbnk/include/nuklear.h:443:1: note: in expansion of macro 'NK_STATIC_ASSERT'
  443 | NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
      | ^~~~~~~~~~~~~~~~
C:/hbnk/include/nuklear.h:301:61: error: size of array '_dummy_array444' is negative
  301 |   #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
      |                                                             ^~~~~~~~~~~~
C:/hbnk/include/nuklear.h:290:46: note: in definition of macro 'NK_STRING_JOIN_IMMEDIATE'
  290 | #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
      |                                              ^~~~
C:/hbnk/include/nuklear.h:292:36: note: in expansion of macro 'NK_STRING_JOIN_DELAY'
  292 | #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
      |                                    ^~~~~~~~~~~~~~~~~~~~
C:/hbnk/include/nuklear.h:297:32: note: in expansion of macro 'NK_STRING_JOIN'
  297 |   #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
      |                                ^~~~~~~~~~~~~~
C:/hbnk/include/nuklear.h:301:46: note: in expansion of macro 'NK_UNIQUE_NAME'
  301 |   #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
      |                                              ^~~~~~~~~~~~~~
C:/hbnk/include/nuklear.h:444:1: note: in expansion of macro 'NK_STATIC_ASSERT'
  444 | NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));

To calm down the errors, I used it as I wrote earlier and I leave it that way in my project.

#if defined(__MINGW32__) || defined(__MINGW64__)
    // MSYS2/MinGW environment: skip static assertions
    #define NK_STATIC_ASSERT(exp)
#else
    // Default behavior
    #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
#endif

In the second case, the macro forces a compile-time check of the condition. If the condition (exp) is false (equals 0), the compiler will generate an error, because we are trying to define an array with a negative size, which is illegal in C.

@rjopek
Copy link
Author

rjopek commented Nov 26, 2024

I recall that this topic was already discussed a few years ago.
510

@riri
Copy link
Contributor

riri commented Nov 26, 2024

Indeed a negative size array is illegal in C, and that's the purpose of static assertions.

That's why I ask you how you compile, which compiler is used and with which switches, to reproduce your error and find out why those sanity checks don't pass. I got the error, now I need the command line triggering this error.

@rjopek
Copy link
Author

rjopek commented Nov 26, 2024

The problem here lies in the assumption that sizeof(nk_size) >= sizeof(void*) is always true. In environments like MSYS2/MinGW, this assumption might not hold, leading to compilation errors.

To make the library more flexible for such cases, I propose adding a conditional check for MSYS2/MinGW environments to skip static assertions when necessary.

@rjopek
Copy link
Author

rjopek commented Nov 26, 2024

The issue is specifically related to the nuklear.h file, and the errors are not backend-dependent. While working on language bindings, I have carefully examined nuklear.h to ensure proper compilation of the sdl_renderer backend under both Linux and MSYS2. To achieve successful compilation, I had to make the following changes:

  1. Modify this line:
#define NK_SDL_RENDERER_SDL_H <SDL.h>

to:

#define NK_SDL_RENDERER_SDL_H <SDL2/SDL.h>
  1. Add the following declaration at the beginning of the nuklear_sdl_renderer.h file:
struct nk_font_atlas;

With these changes, the compilation under Linux works perfectly, and everything runs as expected.

Regarding MSYS2, I have described the issue above in detail. My suggestions and changes are provided for your consideration as an informational note.

@riri
Copy link
Contributor

riri commented Nov 26, 2024

The problem here lies in the assumption that sizeof(nk_size) >= sizeof(void*) is always true. In environments like MSYS2/MinGW, this assumption might not hold, leading to compilation errors.

Actually sizeof(nk_size)should be >= to sizeof(void *) whatever the platform/environment because addresses will be held in nk_size variables.

To make the library more flexible for such cases, I propose adding a conditional check for MSYS2/MinGW environments to skip static assertions when necessary.

It's not making itmore flexible, but less robust and candidate to segfaults.

The solution is more to understand why in your MSYS2 implementation, you fall on this case, because that should not occur. Once the origin of the problem is detected, we can add the various #ifdef needed to handle this.

I just need the compilation command line (and/or Makefile), as well as your environment like Windows version to see if there is some peculiar context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants