SDL
SDL copied to clipboard
Support consuming SDL via C++20 modules.
I'm working on a project written using C++20 modules, but I have to use global module fragments in order to #include "SDL.h". Being able to simply use import SDL; would be more convenient and would allow me to benefit from the increased compilation speed and smaller file size from using modules.
This is a duplicate of #5499. Please re-open if you think it's not.
#5499 is about clang's personal implementation of modules for C, whereas this is relating to the C++20 modules standard.
I don't have the permissions to reopen.
Using c++ modules is implementation dependent: clang, gcc and MSVC have a different implementation. This requires support by the build tools, which CMake does not have yet. Also, there is currently no standard way to distribute c++ modules.
Nonetheless, this should not stop anyone from consuming SDL as a c++20 module today already. You just need to create the interface yourself. e.g. the following works with gcc 12.1 on Linux
#/bin/sh
set -e
cat >mygame.cpp <<EOF
import "SDL.h";
int main(int argc, char* args[]) {
SDL_version compiled;
SDL_version linked;
SDL_VERSION(&compiled);
SDL_GetVersion(&linked);
SDL_Log("Compiled against SDL %u.%u.%u.\n",
compiled.major, compiled.minor, compiled.patch);
SDL_Log(" Linked against SDL %u.%u.%u.\n",
linked.major, linked.minor, linked.patch);
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
SDL_Log("could not initialize sdl2: %s\n", SDL_GetError());
return 1;
}
SDL_Quit();
return 0;
}
EOF
# Exclude SDL_cpuinfo.h from the CMI because gcc has issues with mmintrin.h, xmmintrin.h, emmintrin.h and pmmintrin.h
g++ -std=c++20 -fmodules-ts -x c++-header -fdirectives-only /usr/include/SDL2/SDL.h -DSDL_cpuinfo_h_
g++ -std=c++20 -fmodules-ts mygame.cpp -I/usr/include/SDL2 -lSDL2 -o mygame
Attempting to import SDL.h is probably not the best idea in a lot of cases. Clearly it can be done in a roundabout way with GCC but I could not find a similar compiler flag for MSVC. The added complexity of "importing" macros (the whole thing modules are designed to prevent you from doing) when you need them does not make import/modules look good here.
Precompiled header units aren't really the focus of modules. Here's how you do them with MSVC, anyways.
Also--
An important difference between a header unit and a header file is that a header unit isn't affected by macro definitions outside of the header unit.
Precompiled header units aren't really the focus of modules. Here's how you do them with MSVC, anyways.
Also--
An important difference between a header unit and a header file is that a header unit isn't affected by macro definitions outside of the header unit.
Agreed it goes both ways though, only declarations and definitions can be imported/exported, for example SDL_INIT_VIDEO is a macro that cannot be imported/exported:
#define SDL_INIT_VIDEO 0x00000020u
If, instead, it was enum then the enum could be exported, as an example:
typedef enum { SDL_FALSE = 0, SDL_TRUE = 1 } SDL_bool;
certianly the reliance of macros within SDL is much deeper than that, only the devs would know how hard it would be to switch macros to enums, if it's possible or even worth it to do so.
Thus in my humble opinion SDL.h is not fully compatible with modules. If you need SDL_INIT_VIDEO, you have to take "extra steps" after import SDL.h and even then it's platform dependent. In my case that means #include is the obvious choice and not some workaround that lets me use import. This is just my situation though, others might have different needs.
From https://en.cppreference.com/w/cpp/language/modules
Importing a header will make accessible all its definitions and declarations. Preprocessor macros are also accessible (because import declarations are recognized by the preprocessor). However, contrary to #include, preprocessing macros defined in the translation unit will not affect the processing of the header. This may be inconvenient in some cases (some headers use preprocessing macros as a form of configuration), in which case the usage of global module fragment is needed.
In my experience with MSVC import <SDL.h> works just fine (intellisense dies, but it does that for all modules). The only issue is that #define SDL_HANDLED_MAIN and such like do not work because you cannot pass macros into header imports even though you can get them out. Then again, you can just make a header file which has the macro and #include <SDL.h> in it, and then import that.
As far as I can tell, there isn't anything SDL can do to support modules better.