# SPDX-License-Identifier: GPL-3.0-or-later
# nxrt: game-independent runtime skeleton (OS/HLE layer) for the Metroid Prime Remastered static recompilation.
# Build: scripts\build.ps1   (clang-cl + Ninja, Release)
cmake_minimum_required(VERSION 3.25)
# Static MSVC runtime (/MT): players need no Visual C++ Redistributable. Set before project() so every target below, third-party code
# included, uses it; the libraries this one links must agree (a mismatch is a link error).
if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
project(nxrt C CXX)
if(APPLE)
    enable_language(OBJCXX)
endif()

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)

if(NOT WIN32 AND NOT APPLE)
    message(FATAL_ERROR "nxrt targets native Windows x64 and macOS (Apple silicon) only")
endif()

# The generated-code ABI header (Ctx, call_indirect, ...) lives in the recompiler (recomp/include/nxrecomp/).
# Found next to the checkout (../recomp) or, for a git worktree under runtime-wt/<name>, two levels up (../../recomp).
set(NXRT_RECOMP_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/../recomp/include" CACHE PATH "Directory that holds nxrecomp/")
if(NOT EXISTS "${NXRT_RECOMP_INCLUDE}/nxrecomp/ctx.h" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../recomp/include/nxrecomp/ctx.h")
    get_filename_component(_nxrt_ri "${CMAKE_CURRENT_SOURCE_DIR}/../../recomp/include" ABSOLUTE)
    set(NXRT_RECOMP_INCLUDE "${_nxrt_ri}" CACHE PATH "Directory that holds nxrecomp/" FORCE)
endif()

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND MSVC)
    add_compile_options(/W3 -Wno-unused-parameter -Wno-missing-field-initializers -Wno-cast-function-type-mismatch
                        -Wno-cast-function-type-strict -Wno-language-extension-token)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    add_compile_options(-Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-function
                        -Wno-unused-private-field -Wno-unused-but-set-variable -Wno-deprecated-declarations -Wno-nullability-completeness
                        -Wno-c99-designator -Wno-vla-cxx-extension -Wno-c++11-narrowing -fno-strict-aliasing)
endif()
add_compile_definitions(NOMINMAX WIN32_LEAN_AND_MEAN _CRT_SECURE_NO_WARNINGS _WIN32_WINNT=0x0A00)

option(NXRT_BUILD_GFX "Build the graphics shell (SDL3 + Vulkan + NVN front end, src/gfx, cmake/gfx.cmake)" ON)
# Game modules (games/<id>/, docs/GAME_BOUNDARY.md): the title-specific code a game exe links.
option(NXRT_BUILD_GAMES "Build the game modules in games/" ON)
set(NXRT_GAMES "pkp" CACHE STRING "ids of the game modules to build (games/<id>/), a list")

file(GLOB_RECURSE NXRT_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
list(FILTER NXRT_SOURCES EXCLUDE REGEX "/src/gfx/")   # the graphics shell is its own library (cmake/gfx.cmake)
if(APPLE)
    # macOS: the Win32 subset the runtime uses comes from nxwin (platform/posix: <windows.h> and friends over POSIX and Mach), and the
    # parts that are Windows components (XAudio2, Media Foundation, the audio endpoint list, dbghelp) are replaced by platform/mac.
    set(NXRT_WINDOWS_ONLY "/src/services/audio_xaudio2\\.cpp$|/src/services/audio_devices\\.cpp$|/src/media/movie_mf\\.cpp$|/src/diag/symbols\\.cpp$")
    list(FILTER NXRT_SOURCES EXCLUDE REGEX "${NXRT_WINDOWS_ONLY}")
    file(GLOB NXWIN_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/platform/posix/src/*.cpp")
    add_library(nxwin STATIC ${NXWIN_SOURCES})
    target_include_directories(nxwin SYSTEM BEFORE PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/platform/posix/include")
    target_link_libraries(nxwin PUBLIC "-framework CoreFoundation")
    target_compile_options(nxwin PUBLIC "$<$<COMPILE_LANGUAGE:CXX>:SHELL:-include nxwin/msvcrt.h>")
    file(GLOB NXRT_MAC_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/platform/mac/core/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/platform/mac/core/*.mm")
    list(APPEND NXRT_SOURCES ${NXRT_MAC_SOURCES})
    set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/platform/mac/core/movie_avf.mm" PROPERTIES COMPILE_OPTIONS "-fobjc-arc")   # movie:: on AVFoundation is ARC code
endif()
add_library(nxrt STATIC ${NXRT_SOURCES})
target_include_directories(nxrt PUBLIC include)
if(EXISTS "${NXRT_RECOMP_INCLUDE}")
    target_include_directories(nxrt PUBLIC "${NXRT_RECOMP_INCLUDE}")
endif()
if(WIN32)
    target_link_libraries(nxrt PUBLIC psapi)
else()
    target_link_libraries(nxrt PUBLIC nxwin "-framework CoreFoundation" "-framework CoreAudio" "-framework AudioToolbox" "-framework AVFoundation"
                          "-framework VideoToolbox" "-framework CoreMedia" "-framework CoreVideo" "-framework ImageIO"
                          "-framework CoreGraphics" "-framework UniformTypeIdentifiers" "-framework Foundation")
endif()
add_subdirectory(third_party/pokopia-coop)   # [net] protocol = native: pokopia-native's Link Play (MIT, C11)
target_link_libraries(nxrt PRIVATE pokopia_coop)
add_subdirectory(third_party/miniz)   # zlib streams (MIT): the Pokopia save repair, games/pkp/pkp_save_uuid.cpp
include(cmake/media_deps.cmake)   # libvpx for the Switch 2 video decoders (optional)

if(NXRT_BUILD_GFX)
    include(cmake/gfx.cmake)
endif()

if(NXRT_BUILD_GAMES)
    foreach(_game ${NXRT_GAMES})
        add_subdirectory(games/${_game})
    endforeach()
endif()
# The launcher's branding and factory settings: the data part of one game module and its launcher.rc (version info, manifest). Without that
# module the launcher builds unbranded, with no resources.
if(WIN32 AND TARGET mpr_launcher AND TARGET nxrt_game_${NXRT_LAUNCHER_GAME}_data)
    target_sources(mpr_launcher PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/games/${NXRT_LAUNCHER_GAME}/launcher.rc")
    target_link_libraries(mpr_launcher PRIVATE nxrt_game_${NXRT_LAUNCHER_GAME}_data)
    target_compile_definitions(mpr_launcher PRIVATE NXRT_LAUNCHER_GAME_REGISTER=nxrt_register_game_${NXRT_LAUNCHER_GAME}_data)
    target_link_options(mpr_launcher PRIVATE /MANIFEST:NO)   # launcher.rc carries the manifest
endif()
