Files
parallel-gx2/CMakeLists.txt
T
WizzardSK 271fc32c1c Build the core for webOS
aarch64 only. The other half of the platform is armv7a, and the recompiler
backends here are x86-64 and arm64 - there is nothing for a 32-bit ARM device
to run Espresso code on, so that half is not offered rather than offered and
broken.

webOS is a Linux by CMAKE_SYSTEM_NAME whose buildroot is as bare as Android's:
EGL and GLES, no X11, no Wayland, no session bus, no desktop GL. Everything
here follows from that. The X11 headers in platform.h, the Xlib and xcb
surfaces in the Vulkan backend and the VK_USE_PLATFORM_*_KHR defines that make
the Vulkan headers reach for xcb/xcb.h are all skipped the way they already are
on Android, and the desktop session options - Wayland, GameMode, BlueZ - default
off. OpenGL goes with them: the backend here is desktop GL 4.5 with direct
state access, so Vulkan is the one that fits, and it needs nothing from the SDK
because the loader is dlopen()ed and the headers are vendored.

The dependency set is the part with no precedent. vcpkg builds its ports with
the toolchain named by their triplet - the one CMakeLists chainloads reaches
try_compile and nothing else - so arm64-linux would have built all thirty of
them for the host. Hence dependencies/vcpkg_triplets/arm64-webos.cmake, which
points at the SDK's toolchain file, and a webOS overlay carrying only the empty
dbus port: the Linux overlays take libpng, cairo and gtk3 from the system,
which in a cross build means the host's x86_64 copies. libusb is left out for a
reason of its own - its Linux backend wants libudev, which the buildroot does
not carry, and a webOS app has no raw USB access to use it with.

Not built anywhere yet: the SDK exists only on the buildbot, so the job is
allow_failure and keeps a probe log as an artifact - the image has never run
vcpkg, and a trace needs an account to read while an artifact does not. What
the job cannot answer either way is whether a given TV has a libvulkan for the
core to dlopen; where there is none, the core loads and fails at renderer
creation.
2026-09-20 20:43:27 +02:00

415 lines
16 KiB
CMake

cmake_minimum_required(VERSION 3.21.1)
option(ENABLE_VCPKG "Enable the vcpkg package manager" ON)
# Declared here as well as below because the vcpkg manifest features have to be
# selected before project() is called.
option(ENABLE_LIBRETRO "Build as libretro core" OFF)
option(MACOS_BUNDLE "The executable when built on macOS will be created as an application bundle" OFF)
option(ALLOW_PORTABLE "Allow Cemu to be run in portable mode" ON)
# used by CI script to set version:
set(EMULATOR_VERSION_MAJOR "0" CACHE STRING "")
set(EMULATOR_VERSION_MINOR "0" CACHE STRING "")
set(EMULATOR_VERSION_PATCH "0" CACHE STRING "")
set(THREADS_PREFER_PTHREAD_FLAG true) # needs to be set before vcpkg
execute_process(
COMMAND git log --format=%h -1
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DEMULATOR_HASH=${GIT_HASH})
# webOS is a Linux by CMAKE_SYSTEM_NAME with a buildroot as bare as Android's:
# EGL and GLES and nothing else - no X11, no Wayland, no desktop GL, no session
# bus. It has to be settled here, before the vcpkg block below picks the overlay
# ports and before the option defaults further down are chosen - which is ahead
# of project(), so the compiler is not known yet and the SDK's toolchain file is
# what gives it away (/developer/aarch64-webos-linux-gnu_sdk-buildroot/...), the
# same tell CEMU_TARGET_ANDROID uses below. -DWEBOS=ON says it outright.
if(NOT WEBOS AND CMAKE_TOOLCHAIN_FILE MATCHES "webos")
set(WEBOS TRUE)
endif()
if (ENABLE_VCPKG)
# check if vcpkg is shallow and unshallow it if necessary
execute_process(
COMMAND git rev-parse --is-shallow-repository
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/vcpkg
OUTPUT_VARIABLE is_vcpkg_shallow
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(is_vcpkg_shallow STREQUAL "true")
message(STATUS "vcpkg is shallow. Unshallowing it now...")
execute_process(
COMMAND git fetch --unshallow
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/dependencies/vcpkg"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
)
endif()
# Cross builds hand cmake a toolchain file of their own - the NDK's on
# Android, MXE's for the MinGW Windows build - which would bypass vcpkg
# entirely and leave every find_package() below unsatisfied. Hand it to
# vcpkg as a chainload toolchain instead and let vcpkg's own toolchain take
# the primary slot. (A cache entry set from the command line wins over the
# plain set() below, so this has to be done here rather than there.)
if(CMAKE_TOOLCHAIN_FILE AND NOT VCPKG_CHAINLOAD_TOOLCHAIN_FILE
AND NOT CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg.cmake$")
if(CMAKE_TOOLCHAIN_FILE MATCHES "android.toolchain.cmake$")
set(CEMU_TARGET_ANDROID ON)
endif()
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" CACHE STRING "" FORCE)
unset(CMAKE_TOOLCHAIN_FILE CACHE)
endif()
if(WEBOS)
# The Linux overlays take libpng, cairo and gtk3 from the system, which
# for a cross build would mean the host's x86_64 copies. Only the dbus
# one is worth carrying over - nothing links D-Bus, SDL dlopen()s it -
# and its port exists because upstream's tarball host answers 504 often
# enough to fail whole pipelines.
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_webos;${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports")
# vcpkg builds its ports with the triplet's own toolchain, not with the
# one this file chainloads for the core (that reaches try_compile and
# nothing else), so the cross compiler has to be named in a triplet of
# its own. arm64-linux would build them for the host.
set(VCPKG_OVERLAY_TRIPLETS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_triplets")
elseif(CEMU_TARGET_ANDROID)
# no android-specific overlay ports at the moment - vcpkg refuses to start
# if an overlay path does not exist, so do not name one that is not there
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports")
elseif(VCPKG_TARGET_TRIPLET MATCHES "mingw")
# Cross-compiling to Windows from a Unix host: WIN32 is not set yet (no
# project() call so far, and the host is what counts before it), so the
# triplet is what tells the Windows overlay apart from the Linux one.
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_win;${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports")
elseif(UNIX AND NOT APPLE)
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_linux;${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports")
elseif(APPLE)
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_mac;${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports")
else()
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_win;${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports")
endif()
# The libretro core forces ENABLE_WXWIDGETS OFF, so keep wxWidgets and its
# gtk3/cairo/... dependency tree out of the install plan for that build.
if (NOT ENABLE_LIBRETRO)
list(APPEND VCPKG_MANIFEST_FEATURES "gui")
endif()
# libusb is a feature rather than a plain dependency because iOS and tvOS
# have no USB API to build it against: its Darwin backend is IOKit's USB
# family, and the SDK there does not even carry IOKit/IOCFBundle.h, so the
# port stops on a missing header before anything of ours is compiled.
# Nothing is lost - a phone or a TV box has no Wii U GamePad adapter to
# plug in - and ENABLE_LIBUSB below follows the same condition.
#
# This runs before project(), so APPLE is not set yet and the system name
# is what tells the platforms apart.
# webOS is left out for a different reason than the Apple ones: the port
# builds there, but its Linux backend wants libudev, which the buildroot
# does not carry - and a webOS app has no raw USB access to use it with.
if (NOT CMAKE_SYSTEM_NAME STREQUAL "iOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS" AND NOT WEBOS)
list(APPEND VCPKG_MANIFEST_FEATURES "usb")
endif()
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/vcpkg/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "Vcpkg toolchain file")
# Set this so that all the various find_package() calls don't need an explicit
# CONFIG option
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
if (WIN32)
set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "")
endif()
endif()
project(Cemu VERSION 2.0.0)
# vcpkg hangs an applocal.ps1 post-build step on every Windows target, to copy
# the DLLs it built next to the binary. That is a PowerShell script, and the
# MinGW job cross-compiles on Linux, where linking cemu_libretro.dll then ends
# in "/bin/sh: 1: powershell.exe: not found" with everything else already done.
# A static triplet has no DLLs to copy anyway.
if(WIN32 AND NOT MSVC)
set(VCPKG_APPLOCAL_DEPS OFF)
endif()
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_definitions($<$<CONFIG:Debug>:CEMU_DEBUG_ASSERT>) # if build type is debug, set CEMU_DEBUG_ASSERT
add_definitions(-DEMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR})
add_definitions(-DEMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR})
add_definitions(-DEMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH})
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# enable link time optimization for release builds
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON)
if (MSVC)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT CemuBin)
# floating point model: precise, fiber safe optimizations
add_compile_options(/EHsc /fp:precise)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Speeds up static linking (especially helpful in incremental compilation)
if((CMAKE_LINKER MATCHES ".*lld-link.*") AND (CMAKE_AR MATCHES ".*llvm-lib.*"))
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY STATIC_LIBRARY_OPTIONS /llvmlibthin)
endif()
else()
add_compile_options(/GT)
endif()
# enable additional optimization flags for release builds
add_compile_options($<$<CONFIG:Release,RelWithDebInfo>:/Oi>) # enable intrinsic functions
add_compile_options($<$<CONFIG:Release,RelWithDebInfo>:/Ot>) # favor speed
endif()
if(CMAKE_GENERATOR STREQUAL "Xcode")
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY XCODE_STARTUP_PROJECT CemuBin)
endif()
if (APPLE)
enable_language(OBJC OBJCXX)
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.4")
endif()
if (UNIX AND NOT APPLE)
# None of the three exist on webOS: the buildroot carries no Wayland, no
# GameMode daemon and no BlueZ, and a TV has no Wiimote to pair over it.
if (WEBOS)
set(CEMU_DESKTOP_SESSION_DEFAULT OFF)
else()
set(CEMU_DESKTOP_SESSION_DEFAULT ON)
endif()
option(ENABLE_WAYLAND "Build with Wayland support" ${CEMU_DESKTOP_SESSION_DEFAULT})
option(ENABLE_FERAL_GAMEMODE "Enables Feral Interactive GameMode Support" ${CEMU_DESKTOP_SESSION_DEFAULT})
option(ENABLE_BLUEZ "Build with Bluez support" ${CEMU_DESKTOP_SESSION_DEFAULT})
endif()
if (APPLE)
set(ENABLE_METAL_DEFAULT ON)
set(ENABLE_OPENGL_DEFAULT OFF)
else()
set(ENABLE_METAL_DEFAULT OFF)
# The GL backend here is desktop GL 4.5 with direct state access; webOS
# offers GLES through EGL and nothing more, so Vulkan is the backend that
# fits there - the same split as Android.
if (WEBOS)
set(ENABLE_OPENGL_DEFAULT OFF)
else()
set(ENABLE_OPENGL_DEFAULT ON)
endif()
endif()
option(ENABLE_OPENGL "Enables the OpenGL backend" ${ENABLE_OPENGL_DEFAULT})
option(ENABLE_VULKAN "Enables the Vulkan backend" ON)
option(ENABLE_METAL "Enables the Metal backend" ${ENABLE_METAL_DEFAULT})
option(ENABLE_DISCORD_RPC "Enables the Discord Rich Presence feature" ON)
if (ENABLE_METAL AND NOT APPLE)
message(FATAL_ERROR "Metal backend is only supported on Apple platforms")
endif()
# input backends
if (WIN32)
option(ENABLE_XINPUT "Enables the usage of XInput" ON)
# DirectInput reaches for GetdfDIJoystick(), which comes with the MSVC DirectX SDK;
# MinGW's dinput.h only has the c_dfDIJoystick data it wraps. Same story for the
# DirectSound/XAudio2 audio backends below, so all of them are MSVC-only. Nothing is
# lost in the libretro build, where input and audio belong to the frontend anyway.
if (MSVC)
option(ENABLE_DIRECTINPUT "Enables the usage of DirectInput" ON)
else()
set(ENABLE_DIRECTINPUT OFF)
endif()
if (ENABLE_DIRECTINPUT)
add_compile_definitions(HAS_DIRECTINPUT)
endif()
endif()
option(ENABLE_HIDAPI "Build with HIDAPI" ON)
option(ENABLE_SDL "Enables the SDLController backend" ON)
# Off on the Apple embedded platforms, where there is no USB API to talk to and
# the dependency is not built either (see the manifest features above).
if (CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "tvOS" OR WEBOS)
set(ENABLE_LIBUSB_DEFAULT OFF)
else()
set(ENABLE_LIBUSB_DEFAULT ON)
endif()
option(ENABLE_LIBUSB "Build with libusb support" ${ENABLE_LIBUSB_DEFAULT})
if (ENABLE_LIBUSB)
add_compile_definitions(HAS_LIBUSB)
endif()
# audio backends
if (WIN32)
option(ENABLE_DIRECTAUDIO "Enables the directaudio backend" ON)
option(ENABLE_XAUDIO "Enables the xaudio backend" ON)
endif()
option(ENABLE_CUBEB "Enabled cubeb backend" ON)
option(ENABLE_WXWIDGETS "Build with wxWidgets UI (Currently required)" ON)
option(ENABLE_LIBRETRO "Build as libretro core" OFF)
if (ENABLE_LIBRETRO)
set(ENABLE_WXWIDGETS OFF)
set(ENABLE_DISCORD_RPC OFF)
add_compile_definitions(ENABLE_LIBRETRO)
# All static libs must be compiled with -fPIC for shared library linking
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
option(ENABLE_LIBRETRO "Build Libretro core" OFF)
# Disable cubeb for libretro builds (COM threading issues with WASAPI)
if(ENABLE_LIBRETRO)
add_compile_definitions(RETRO_CORE)
set(ENABLE_CUBEB OFF CACHE BOOL "" FORCE)
endif()
find_package(Threads REQUIRED)
find_package(CURL REQUIRED)
find_package(pugixml REQUIRED)
find_package(RapidJSON REQUIRED)
set(CEMU_BOOST_COMPONENTS program_options filesystem nowide)
if (ANDROID)
# Fiber/FiberAndroid.cpp needs fcontext
list(APPEND CEMU_BOOST_COMPONENTS context)
endif()
find_package(Boost COMPONENTS ${CEMU_BOOST_COMPONENTS} REQUIRED)
find_package(libzip REQUIRED)
find_package(glslang REQUIRED)
find_package(ZLIB REQUIRED)
find_package(zstd MODULE REQUIRED) # MODULE so that zstd::zstd is available
find_package(OpenSSL COMPONENTS Crypto SSL REQUIRED)
find_package(glm REQUIRED)
find_package(fmt 12.1 REQUIRED)
find_package(PNG REQUIRED)
if(ENABLE_SDL)
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
add_compile_definitions(HAS_SDL)
endif()
# glslang versions older than 11.11.0 define targets without a namespace
if (NOT TARGET glslang::SPIRV AND TARGET SPIRV)
add_library(glslang::SPIRV ALIAS SPIRV)
endif()
# Android and webOS are UNIX as far as CMake is concerned, but have none of
# this: no X11, no Wayland, no GTK, no BlueZ.
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT WEBOS)
find_package(X11 REQUIRED)
if (ENABLE_WAYLAND)
find_package(Wayland REQUIRED Client)
find_package(WaylandScanner REQUIRED)
find_package(WaylandProtocols 1.15 REQUIRED)
ecm_add_wayland_client_protocol(WAYLAND_PROTOCOL_SRCS
PROTOCOL "${WaylandProtocols_DATADIR}/stable/viewporter/viewporter.xml"
BASENAME viewporter)
add_library(CemuWaylandProtocols STATIC ${WAYLAND_PROTOCOL_SRCS})
target_include_directories(CemuWaylandProtocols PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")
target_include_directories(CemuWaylandProtocols PRIVATE ${Wayland_INCLUDE_DIRS})
add_compile_definitions(HAS_WAYLAND)
endif()
# Only CemuWxGui links GTK3::gtk, so a core build does not need it at all.
if (ENABLE_WXWIDGETS)
find_package(GTK3 REQUIRED)
endif()
if(ENABLE_BLUEZ)
find_package(bluez REQUIRED)
set(SUPPORTS_WIIMOTE ON)
add_compile_definitions(HAS_BLUEZ)
endif()
endif()
if (WEBOS)
add_compile_definitions(WEBOS)
endif()
if (ENABLE_VULKAN)
include_directories("dependencies/Vulkan-Headers/include")
add_compile_definitions(ENABLE_VULKAN)
add_compile_definitions(VK_NO_PROTOTYPES)
endif()
if (ENABLE_OPENGL AND NOT ANDROID AND NOT WEBOS)
# Android and webOS have no desktop OpenGL, only GLES/EGL - the core uses
# Vulkan on both.
find_package(OpenGL REQUIRED)
add_compile_definitions(ENABLE_OPENGL)
endif()
if (ENABLE_METAL)
include_directories(${CMAKE_SOURCE_DIR}/dependencies/metal-cpp)
add_compile_definitions(ENABLE_METAL)
endif()
if (ENABLE_DISCORD_RPC)
add_compile_definitions(ENABLE_DISCORD_RPC)
endif()
if (ENABLE_HIDAPI)
set(SUPPORTS_WIIMOTE ON)
add_compile_definitions(HAS_HIDAPI)
endif ()
if(UNIX AND NOT APPLE)
if(ENABLE_FERAL_GAMEMODE)
add_compile_definitions(ENABLE_FERAL_GAMEMODE)
add_subdirectory(dependencies/gamemode EXCLUDE_FROM_ALL)
target_include_directories(gamemode INTERFACE ./dependencies/gamemode/lib)
endif()
endif()
if (ENABLE_WXWIDGETS)
find_package(wxWidgets 3.3 REQUIRED COMPONENTS base core gl propgrid xrc)
endif()
if (ENABLE_CUBEB)
if (NOT ENABLE_VCPKG)
find_package(cubeb)
endif()
if (NOT cubeb_FOUND)
option(BUILD_TESTS "" OFF)
option(BUILD_TOOLS "" OFF)
option(BUNDLE_SPEEX "" OFF)
set(USE_WINMM OFF CACHE BOOL "")
add_subdirectory("dependencies/cubeb" EXCLUDE_FROM_ALL SYSTEM)
set_property(TARGET cubeb PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
add_library(cubeb::cubeb ALIAS cubeb)
endif()
add_compile_definitions("HAS_CUBEB=1")
endif()
add_subdirectory("dependencies/ih264d" EXCLUDE_FROM_ALL)
if (CMAKE_OSX_ARCHITECTURES)
set(CEMU_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES})
else()
set(CEMU_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
endif()
if(CEMU_ARCHITECTURE MATCHES "(aarch64)|(AARCH64)|(arm64)|(ARM64)")
add_subdirectory("dependencies/xbyak_aarch64" EXCLUDE_FROM_ALL)
endif()
find_package(ZArchive QUIET)
if (NOT ZArchive_FOUND)
add_subdirectory("dependencies/ZArchive" EXCLUDE_FROM_ALL)
endif()
add_subdirectory(src)