SDL icon indicating copy to clipboard operation
SDL copied to clipboard

Support consuming SDL via C++20 modules.

Open Zopolis4 opened this issue 3 years ago • 4 comments

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.

Zopolis4 avatar Jul 25 '22 04:07 Zopolis4

This is a duplicate of #5499. Please re-open if you think it's not.

madebr avatar Jul 25 '22 11:07 madebr

#5499 is about clang's personal implementation of modules for C, whereas this is relating to the C++20 modules standard.

Zopolis4 avatar Jul 25 '22 11:07 Zopolis4

I don't have the permissions to reopen.

Zopolis4 avatar Jul 25 '22 11:07 Zopolis4

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

madebr avatar Jul 25 '22 16:07 madebr

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.

GhostCore07 avatar Oct 04 '22 18:10 GhostCore07

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. 

Zopolis4 avatar Oct 07 '22 03:10 Zopolis4

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.

GhostCore07 avatar Oct 07 '22 14:10 GhostCore07

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.

CyborgCabbage avatar Jan 25 '23 13:01 CyborgCabbage