Skip to content

feat(build): Add native Linux build support #2088

@sebyx07

Description

@sebyx07

Summary

Add native Linux compilation support alongside existing Windows builds. Currently, the Docker-based build produces Windows executables (.exe) that run via Wine — this proposal adds true native Linux binaries.

Problem

Current State

  • Docker build (scripts/docker-build.sh) exists but produces Windows .exe files
  • Linux users must run the game through Wine/Proton
  • No way to compile native Linux binaries directly
  • Scripts don't clearly indicate they produce Windows executables, not native Linux

Why Native Linux?

  • Better performance (no Wine overhead)
  • Easier debugging with native tools (gdb, valgrind)
  • Simpler CI/CD without Docker containers
  • First-class Linux support for the community

Solution

Core Approach: DXVK

Use DXVK to translate DirectX 8 calls to Vulkan at runtime. This allows the existing DirectX rendering code to work on Linux with minimal source code changes.

DirectX 8 Code (unchanged) → DXVK Library → Vulkan → GPU

Key Changes

  1. CMake Feature Toggles

    option(RTS_USE_DXVK "Use DXVK (DirectX->Vulkan)" OFF)
    option(RTS_USE_FFMPEG "Use FFmpeg for video" ON)
    option(RTS_USE_OPENAL "Use OpenAL for audio" OFF)
    
    cmake_dependent_option(RTS_USE_DX8 "Use DirectX 8" ON "WIN32" OFF)
    cmake_dependent_option(RTS_USE_DXVK "Use DXVK" ON "NOT WIN32" OFF)
  2. Linux CMake Presets

    {
      "name": "linux",
      "displayName": "Linux x64 Release",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/linux",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "RTS_USE_DXVK": "ON",
        "RTS_USE_FFMPEG": "ON"
      }
    }
  3. Platform Detection

    if(WIN32)
      target_compile_definitions(core_config INTERFACE _WINDOWS)
    elseif(UNIX AND NOT APPLE)
      target_compile_definitions(core_config INTERFACE _LINUX _UNIX)
    endif()

Dependency Matrix

Component Windows Linux (Native)
Graphics DirectX 8 DXVK (DX8→Vulkan)
Video Bink FFmpeg
Audio Miles Miles*/OpenAL
Fonts GDI FreeType + FontConfig
File I/O Win32 API std::filesystem (StdDevice)
Windowing Win32 SDL3 or X11
Input DirectInput SDL3 or libevdev

*Miles may work via compatibility layer

Existing Infrastructure

The codebase already has cross-platform foundations:

  • StdLocalFileSystem - Uses std::filesystem, handles path separators and case-insensitivity
  • Compatibility headers in Dependencies/Utility/Utility/:
    • compat.h, thread_compat.h, endian_compat.h, intrin_compat.h
  • FFmpeg video backend - Already exists in Core/GameEngineDevice/Source/VideoDevice/FFmpeg/

Reference Implementation

Fighter19's fork (develop branch) demonstrates a working approach with:

  • DXVK integration
  • SDL3 support
  • CMake feature toggles
  • Linux CI builds

Tasks

Phase 1: CMake Restructuring

  • Add feature toggle options (RTS_USE_DXVK, RTS_USE_FFMPEG, RTS_USE_OPENAL, etc.)
  • Add platform detection defines (_LINUX, _UNIX)
  • Add linux and linux-debug presets to CMakePresets.json
  • Create cmake/platform-deps.cmake for centralized dependency handling
  • Create cmake/game-install.cmake helper to reduce CMake duplication

Phase 2: DXVK Integration

  • Create cmake/dxvk.cmake to fetch DXVK native libraries
  • Configure imported target for d3d8 library
  • Test DXVK linking and runtime loading

Phase 3: Dependency Management

  • Create cmake/ffmpeg.cmake for Linux video playback
  • Create cmake/freetype.cmake for font rendering
  • Create cmake/openal.cmake for audio (if needed)
  • Update vcpkg.json with Linux dependencies

Phase 4: Compiler Compatibility

  • Add GCC/Clang compiler settings to cmake/compilers.cmake
  • Add floating-point determinism flags for replay compatibility
  • Add sanitizer options (ASan, UBSan) for development
  • Fix hash_mapunordered_map (MSVC extension)
  • Fix enum forward declaration compliance issues
  • Fix vexing parse issues

Phase 5: Build Scripts

  • Create scripts/linux-native-build.sh
  • Create scripts/install-linux-deps.sh (distro detection)
  • Create scripts/run-generals-linux.sh (game launcher)
  • Update scripts/docker-build.sh header to clarify it produces Windows .exe

Phase 6: CI/CD

  • Create .github/workflows/linux-native.yml
  • Add GCC and Clang build matrix
  • Add artifact upload for built binaries

Phase 7: Documentation

  • Update README.md with Linux build instructions
  • Document difference between Docker and native builds
  • Document runtime requirements (Vulkan drivers, etc.)

Open Questions

  1. SDL3 - Required or optional for windowing/input?
  2. Audio - Miles via compatibility layer vs native OpenAL?
  3. Priority - Zero Hour first, then Generals?
  4. Minimum requirements - Vulkan 1.1+, glibc version?
  5. Tools - Include WorldBuilder, W3DView in Linux build?

Files to Create

cmake/dxvk.cmake
cmake/ffmpeg.cmake
cmake/openal.cmake
cmake/freetype.cmake
cmake/platform-deps.cmake
cmake/game-install.cmake
scripts/linux-native-build.sh
scripts/install-linux-deps.sh
scripts/run-generals-linux.sh
.github/workflows/linux-native.yml

Files to Modify

CMakeLists.txt
CMakePresets.json
cmake/config.cmake
cmake/compilers.cmake
vcpkg.json
README.md
scripts/docker-build.sh

Related


/cc @xezon @feliwir

Metadata

Metadata

Assignees

No one assigned

    Labels

    PlatformWork towards platform support, such as Linux, MacOS

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions