Couche d'abstraction de portabilité (PAL)¶
Ce document décrit les composants de la couche de portabilité qui permettent au projet de fonctionner sur Linux, macOS et Windows.
Vue d'ensemble¶
La PAL (Portability Abstraction Layer) est organisée en trois modules dans src/platform/ :
| Module | Fichier | Responsabilité |
|---|---|---|
platform_utils |
platform_utils.c/.h |
Détection de plateforme, macros |
platform_time |
platform_time.c/.h |
Mesure du temps haute résolution |
platform_fs |
platform_fs.c/.h |
Opérations sur le système de fichiers |
Composant : platform_utils¶
Détection de plateforme¶
#if defined(_WIN32)
#define PLATFORM_WINDOWS 1
#elif defined(__APPLE__)
#define PLATFORM_MACOS 1
#elif defined(__linux__)
#define PLATFORM_LINUX 1
#endif
Macros utilitaires¶
// Attributs portables
#define MAYBE_UNUSED __attribute__((unused))
#define INLINE static inline __attribute__((always_inline))
// Séparateur de chemin
#ifdef PLATFORM_WINDOWS
#define PATH_SEP '\\'
#else
#define PATH_SEP '/'
#endif
Composant : platform_time¶
Fournit un chronomètre haute résolution indépendant de la plateforme :
typedef struct { uint64_t value; } PlatformTime;
PlatformTime platform_time_now(void);
double platform_time_elapsed_ms(PlatformTime start, PlatformTime end);
double platform_time_elapsed_s(PlatformTime start, PlatformTime end);
Implémentation :
- Linux : clock_gettime(CLOCK_MONOTONIC)
- macOS : mach_absolute_time()
- Windows : QueryPerformanceCounter()
Composant : platform_fs¶
Listage de répertoires basé sur le callback¶
L'API de listage de répertoires utilise une architecture callback pour éviter l'allocation dynamique et permettre un traitement streaming :
typedef void (*fs_dir_entry_callback)(const char* path, void* user_data);
int platform_fs_list_dir(const char* dir,
fs_dir_entry_callback callback,
void* user_data);
Usage :
// Lister tous les fichiers .hdr dans le dossier assets
void on_hdr_found(const char* path, void* ctx) {
if (str_ends_with(path, ".hdr")) {
add_environment(ctx, path);
}
}
platform_fs_list_dir("assets/environments", on_hdr_found, &env_list);
Opérations courantes¶
// Vérifier l'existence d'un fichier
bool platform_fs_exists(const char* path);
// Obtenir la taille d'un fichier
int64_t platform_fs_size(const char* path);
// Lire un fichier entier en mémoire
uint8_t* platform_fs_read_all(const char* path, size_t* out_size);
Support Windows (cross-compilation)¶
La compilation Windows s'effectue via la toolchain MinGW :
# Configurer pour Windows
just configure-win
# Compiler
just build-win
# Exécuter via Wine
just run-win
La toolchain est définie dans toolchain-mingw.cmake :
L'exécution des tests sous Wine est gérée par le script wrapper
run_test_with_xvfb.sh, qui détecte automatiquement les binaires
.exe et les préfixe avec wine64. Chaque test standalone dans
tests/CMakeLists.txt utilise ce wrapper en build WIN32 :
if(WIN32)
add_test(NAME test_foo
COMMAND ${CMAKE_SOURCE_DIR}/.github/workflows/scripts/run_test_with_xvfb.sh $<TARGET_FILE:test_foo>)
else()
add_test(NAME test_foo COMMAND test_foo)
endif()
Limitations connues¶
Manette/Joystick non détecté sous Wine¶
L'API gamepad de GLFW (glfwJoystickIsGamepad) repose sur la pile native de
la plateforme. Sous Wine, cela correspond aux API Windows WinMM/XInput, qui
nécessitent que Wine détecte le périphérique joystick Linux.
- Cause : Le passthrough joystick de Wine dépend de la présence de
libSDL2dans le préfixe Wine et des permissions udev correctes sur/dev/input/js*et/dev/input/event*. - Symptômes : La manette fonctionne parfaitement avec le build Linux
natif (
just run) mais n'est pas reconnue sous Wine (just run-win). L'overlay F2 masque correctement la page manette puisquegamepad.connected == 0. - Statut : C'est une limitation connue de Wine, pas un bug applicatif. Le support manette sous Wine est best-effort. Pour une fonctionnalité manette complète, utiliser le build Linux natif.
Voir aussi¶
- build.md — Guide de compilation
- project_structure.md — Structure du projet