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
    No fields configured for Feature.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions