floooh / sokol

minimal cross-platform standalone C headers
https://floooh.github.io/sokol-html5
zlib License
7.08k stars 498 forks source link

_SAPP_CLEAR_ARC_STRUCT errors in MacOS (C++ version issue <C++17) #685

Closed eduardodoria closed 2 years ago

eduardodoria commented 2 years ago

I'm getting some errors when building in OSX (MacOS) using Cmake:

[build] sokol_app.h:2770:5: error: expected expression [build] _SAPP_CLEAR_ARC_STRUCT(_sapp_t, _sapp); [build] ^ [build] sokol_app.h:2514:61: note: expanded from macro '_SAPP_CLEAR_ARC_STRUCT' [build] #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = { }; } [build] ^

[build] sokol_gfx.h:15206:5: error: expected expression [build] _SG_CLEAR_ARC_STRUCT(_sg_state_t, _sg); [build] ^ [build] sokol_gfx.h:4275:59: note: expanded from macro '_SG_CLEAR_ARC_STRUCT' [build] #define _SG_CLEAR_ARC_STRUCT(type, item) { item = { }; } [build] ^

I solved replacing theses MACROS with the values that were in old commits:

sokol_gfx.h Where was:

#if defined(__cplusplus)
    #define _SG_CLEAR_ARC_STRUCT(type, item) { item = { }; }
#else
    #define _SG_CLEAR_ARC_STRUCT(type, item) { item = (type) { 0 }; }
#endif

It became:

#if defined(__cplusplus)
    #define _SG_CLEAR_ARC_STRUCT(type, item) { item = (type) { }; }
#else
    #define _SG_CLEAR_ARC_STRUCT(type, item) { item = (type) { 0 }; }
#endif

sokol_app.h Where was:

#if defined(__cplusplus)
    #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = { }; }
#else
    #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = (type) { 0 }; }
#endif

It became:

#if defined(__cplusplus)
    #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = (type) { }; }
#else
    #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = (type) { 0 }; }
#endif

I really don't know if this is the correct thing to fix this error. That's why I not asked to merge request.

floooh commented 2 years ago

Hmm weird, this was changed in this commit:

https://github.com/floooh/sokol/commit/f306862f2137f43c1145902adf086c8cf3cb81de

...because of this issue (basically the old style generated a warning in 'pedantic' mode:

https://github.com/floooh/sokol/issues/644

What compiler and compiler version are you using? (e.g. clang --version)

eduardodoria commented 2 years ago

This error is only with Cmake. With Xcode it works.

clang --version

Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: x86_64-apple-darwin21.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

Also can see the error in this Github workflow: https://github.com/supernovaengine/supernova/runs/7162913905?check_suite_focus=true

floooh commented 2 years ago

Super weird... ok... the Github Actions version is a bit older (13.0.0) but that shouldn't matter.

In the sokol-samples project I'm compiling Objective-C++ files with the .mm extension (sokol.mm, here: https://github.com/floooh/sokol-samples/runs/7183101219?check_suite_focus=true#step:7:87).

However in the tests that are embedded in sokol I also just use a .cc extension for the C++ compilation test and use the -x objective-c++ flag (https://github.com/floooh/sokol/blob/7f2b86f5bb7145b1d6b2b8d81c81b8356475c1e7/tests/CMakeLists.txt#L123)...

So TBH I currently have no idea what the reason could be, but both the samples and the tests compile all headers also as C++.

Only thing I can recommend currently is that you go through the tests cmake files (that's the one that uses -x objective-c++ and see if you can find any differences to your cmake file:

https://github.com/floooh/sokol/blob/master/tests/CMakeLists.txt

floooh commented 2 years ago

Btw, is there a specific reason why you are compiling the sokol implementations as C++ and not C? C++ is only needed for the sokol_app.h UWP backend (which isn't really properly supported anymore).

eduardodoria commented 2 years ago

I found! It was CXX version. I only added to my CMakeLists.txt and worked:

set(CMAKE_CXX_STANDARD 17)

I really need C++ because I integrate with my code using:

#define SOKOL_LOG(s) { SOKOL_ASSERT(s); Supernova::Log::Error(s); }

Thanks for your help!

floooh commented 2 years ago

Oh ok, thanks for finding the culprit! This is definitely unexpected. I'll need to dig into this a bit more to figure out why the change isn't valid in C++ versions before 17, ideally compiling the sokol headers as C++ shouldn't require any specific C++ version (except if it's a requirement from underlying APIs, like in the sokol_app.h UWP backend).

I'll keep the ticket open as a reminer.

PS: also good point about the logging requirement, I should probably add a proper logging callback instead of a macro override (same thing I did with allocators recently).

floooh commented 2 years ago

Aha! I can reproduce the problem!

When I set the C++ standard to '98' here:

https://github.com/floooh/sokol-samples/blob/e3bdfaa43f197dd9d14a088f5de8cfbd534236f2/CMakeLists.txt#L10

...I get the following error when compiling the sokol-cpp target:

In file included from /Users/floh/projects/sokol-samples/libs/sokol/sokol.mm:6:
/Users/floh/projects/sokol/sokol_app.h:2770:5: error: expected expression
    _SAPP_CLEAR_ARC_STRUCT(_sapp_t, _sapp);
    ^
/Users/floh/projects/sokol/sokol_app.h:2514:61: note: expanded from macro '_SAPP_CLEAR_ARC_STRUCT'
        #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = { }; }
                                                            ^
/Users/floh/projects/sokol/sokol_app.h:2816:5: error: expected expression
    _SAPP_CLEAR_ARC_STRUCT(_sapp_t, _sapp);
    ^
/Users/floh/projects/sokol/sokol_app.h:2514:61: note: expanded from macro '_SAPP_CLEAR_ARC_STRUCT'
        #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = { }; }
                                                            ^
In file included from /Users/floh/projects/sokol-samples/libs/sokol/sokol.mm:7:
/Users/floh/projects/sokol/sokol_gfx.h:15212:5: error: expected expression
    _SG_CLEAR_ARC_STRUCT(_sg_state_t, _sg);
    ^
/Users/floh/projects/sokol/sokol_gfx.h:4281:59: note: expanded from macro '_SG_CLEAR_ARC_STRUCT'
        #define _SG_CLEAR_ARC_STRUCT(type, item) { item = { }; }
                                                          ^
/Users/floh/projects/sokol/sokol_gfx.h:15235:5: error: expected expression
    _SG_CLEAR_ARC_STRUCT(_sg_state_t, _sg);
    ^
/Users/floh/projects/sokol/sokol_gfx.h:4281:59: note: expanded from macro '_SG_CLEAR_ARC_STRUCT'
        #define _SG_CLEAR_ARC_STRUCT(type, item) { item = { }; }
                                                          ^
4 errors generated.

...so the problem isn't C++ versions before 17, but before C++11 (C++11 also works fine).

It looks like clang is still using C++98 as default. When I compile this test program with clang bla.cc -o bla:

int main() {
    __builtin_printf("%ld\n", __cplusplus);
    return 0;
}

...it prints 199711, which is the value for C++98:

https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/preprocessor/macros/predefined/__cplusplus

...so at least the mystery is solved. I'm still surprised a bit that this syntax isn't accepted by C++98.

But this means you can safely go from C++17 to C++11, only C++98 has this problem.

Regular Clang uses C++14 by default: https://www.godbolt.org/z/bs7ahc6ef, it's just Apple's Clang which lives in the past ;)

eduardodoria commented 2 years ago

For me it's ok with C++17. But it is good to know that C++11 also works. A lot of projects uses C++11 as minimum requirement.

floooh commented 2 years ago

I'm currently working on a fix, this should work all the way back to C++98: { item = type(); }