Skip to content

Commit

Permalink
qt: Add support for building for iOS. (#6594)
Browse files Browse the repository at this point in the history
  • Loading branch information
Steveice10 authored Jun 8, 2023
1 parent d9bf4fd commit 238a574
Show file tree
Hide file tree
Showing 17 changed files with 271 additions and 116 deletions.
28 changes: 21 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,35 @@ project(citra LANGUAGES C CXX ASM)

if (APPLE)
enable_language(OBJC)
if (IOS)
# Enable searching CMAKE_PREFIX_PATH for bundled dependencies.
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
endif()
endif()

option(ENABLE_LTO "Enable link time optimization" OFF)

option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
option(ENABLE_SDL2 "Enable using SDL2" ON)
CMAKE_DEPENDENT_OPTION(ENABLE_SDL2_FRONTEND "Enable the SDL2 frontend" ON "ENABLE_SDL2;NOT ANDROID AND NOT IOS" OFF)
option(USE_SYSTEM_SDL2 "Use the system SDL2 lib (instead of the bundled one)" OFF)

# Set bundled qt as dependent options.
option(ENABLE_QT "Enable the Qt frontend" ON)
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_QT_UPDATER "Enable built-in updater for the Qt frontend" ON "NOT IOS" OFF)
CMAKE_DEPENDENT_OPTION(CITRA_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC OR APPLE" OFF)

CMAKE_DEPENDENT_OPTION(ENABLE_TESTS "Enable generating tests executable" ON "NOT IOS" OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_DEDICATED_ROOM "Enable generating dedicated room executable" ON "NOT ANDROID AND NOT IOS" OFF)

option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
if (MSVC)
set(OPENSSL_DLL_DIR "" CACHE PATH "Location of the Openssl dlls")
endif()

option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
CMAKE_DEPENDENT_OPTION(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT IOS" OFF)
option(ENABLE_OPENAL "Enables the OpenAL audio backend" ON)

CMAKE_DEPENDENT_OPTION(ENABLE_LIBUSB "Enable libusb for GameCube Adapter support" ON "NOT IOS" OFF)
Expand Down Expand Up @@ -205,8 +216,7 @@ find_package(Threads REQUIRED)

if (ENABLE_QT)
if (CITRA_USE_BUNDLED_QT)
download_qt_external(6.5.0 QT_PREFIX)
list(APPEND CMAKE_PREFIX_PATH ${QT_PREFIX})
download_qt_external(6.5.0)
endif()

find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent)
Expand Down Expand Up @@ -290,10 +300,14 @@ if (APPLE)
find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED)
message(STATUS "Using MoltenVK at ${MOLTENVK_LIBRARY}.")

# Umbrella framework for everything GUI-related
find_library(COCOA_LIBRARY Cocoa REQUIRED)
if (NOT IOS)
# Umbrella framework for everything GUI-related
find_library(COCOA_LIBRARY Cocoa REQUIRED)
endif()

find_library(AVFOUNDATION_LIBRARY AVFoundation REQUIRED)
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${AVFOUNDATION_LIBRARY} ${MOLTENVK_LIBRARY})
find_library(IOSURFACE_LIBRARY IOSurface REQUIRED)
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${AVFOUNDATION_LIBRARY} ${IOSURFACE_LIBRARY} ${MOLTENVK_LIBRARY})
elseif (WIN32)
set(PLATFORM_LIBRARIES winmm ws2_32)
if (MINGW)
Expand Down
32 changes: 27 additions & 5 deletions CMakeModules/DownloadExternals.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ endfunction()
# Params:
# target: Qt dependency to install. Specify a version number to download Qt, or "tools_(name)" for a specific build tool.
# prefix_var: Name of a variable which will be set with the path to the extracted contents.
function(download_qt_external target prefix_var)
function(download_qt_external target)
# Determine installation parameters for OS, architecture, and compiler
if (WIN32)
set(host "windows")
set(type "desktop")
if (MINGW)
set(arch_path "mingw81")
elseif ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND "x86_64" IN_LIST ARCHITECTURE)
Expand All @@ -56,10 +57,19 @@ function(download_qt_external target prefix_var)
set(arch "win64_${arch_path}")
elseif (APPLE)
set(host "mac")
set(arch "clang_64")
set(arch_path "macos")
if (IOS)
set(type "ios")
set(arch "ios")
set(arch_path "ios")
set(host_arch_path "macos")
else()
set(type "desktop")
set(arch "clang_64")
set(arch_path "macos")
endif()
else()
set(host "linux")
set(type "desktop")
set(arch "gcc_64")
set(arch_path "linux")
endif()
Expand All @@ -72,7 +82,11 @@ function(download_qt_external target prefix_var)
set(install_args install-tool --outputdir ${base_path} ${host} desktop ${target})
else()
set(prefix "${base_path}/${target}/${arch_path}")
set(install_args install-qt --outputdir ${base_path} ${host} desktop ${target} ${arch} -m qtmultimedia)
if (host_arch_path)
set(host_flag "--autodesktop")
set(host_prefix "${base_path}/${target}/${host_arch_path}")
endif()
set(install_args install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} ${host_flag} -m qtmultimedia)
endif()

if (NOT EXISTS "${prefix}")
Expand All @@ -97,7 +111,15 @@ function(download_qt_external target prefix_var)
endif()

message(STATUS "Using downloaded Qt binaries at ${prefix}")
set(${prefix_var} "${prefix}" PARENT_SCOPE)

# Add the Qt prefix path so CMake can locate it.
list(APPEND CMAKE_PREFIX_PATH "${prefix}")
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)

if (DEFINED host_prefix)
message(STATUS "Using downloaded host Qt binaries at ${host_prefix}")
set(QT_HOST_PATH "${host_prefix}" CACHE STRING "")
endif()
endfunction()

function(download_moltenvk)
Expand Down
54 changes: 54 additions & 0 deletions CMakeModules/GenerateBuildInfo.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Gets a UTC timstamp and sets the provided variable to it
function(get_timestamp _var)
string(TIMESTAMP timestamp UTC)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()

list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/externals/cmake-modules")

# Find the package here with the known path so that the GetGit commands can find it as well
find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")

# generate git/build information
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
string(SUBSTRING "${GIT_REV}" 0 7 GIT_SHORT_REV)
git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
get_timestamp(BUILD_DATE)

# Generate cpp with Git revision from template
# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well
set(REPO_NAME "")
set(BUILD_VERSION "0")
set(BUILD_FULLNAME "${GIT_SHORT_REV}")
if (DEFINED ENV{CI})
if (DEFINED ENV{GITHUB_ACTIONS})
set(BUILD_REPOSITORY $ENV{GITHUB_REPOSITORY})
set(BUILD_TAG $ENV{GITHUB_REF_NAME})
endif()

# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "citra-emu/citra-?(.*)" OUTVAR ${BUILD_REPOSITORY})
if ("${CMAKE_MATCH_COUNT}" GREATER 0)
# capitalize the first letter of each word in the repo name.
string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1})
foreach(WORD ${REPO_NAME_LIST})
string(SUBSTRING ${WORD} 0 1 FIRST_LETTER)
string(SUBSTRING ${WORD} 1 -1 REMAINDER)
string(TOUPPER ${FIRST_LETTER} FIRST_LETTER)
set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}")
endforeach()
string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG})
if (${CMAKE_MATCH_COUNT} GREATER 0)
set(BUILD_VERSION ${CMAKE_MATCH_1})
endif()
if (BUILD_VERSION)
# This leaves a trailing space on the last word, but we actually want that
# because of how it's styled in the title bar.
set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ")
else()
set(BUILD_FULLNAME "")
endif()
endif()
endif()
54 changes: 2 additions & 52 deletions CMakeModules/GenerateSCMRev.cmake
Original file line number Diff line number Diff line change
@@ -1,55 +1,5 @@
# Gets a UTC timstamp and sets the provided variable to it
function(get_timestamp _var)
string(TIMESTAMP timestamp UTC)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()

list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/externals/cmake-modules")

# Find the package here with the known path so that the GetGit commands can find it as well
find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")

# generate git/build information
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
get_timestamp(BUILD_DATE)

# Generate cpp with Git revision from template
# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well
set(REPO_NAME "")
set(BUILD_VERSION "0")
if (DEFINED ENV{CI})
if (DEFINED ENV{GITHUB_ACTIONS})
set(BUILD_REPOSITORY $ENV{GITHUB_REPOSITORY})
set(BUILD_TAG $ENV{GITHUB_REF_NAME})
endif()

# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "citra-emu/citra-?(.*)" OUTVAR ${BUILD_REPOSITORY})
if ("${CMAKE_MATCH_COUNT}" GREATER 0)
# capitalize the first letter of each word in the repo name.
string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1})
foreach(WORD ${REPO_NAME_LIST})
string(SUBSTRING ${WORD} 0 1 FIRST_LETTER)
string(SUBSTRING ${WORD} 1 -1 REMAINDER)
string(TOUPPER ${FIRST_LETTER} FIRST_LETTER)
set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}")
endforeach()
string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG})
if (${CMAKE_MATCH_COUNT} GREATER 0)
set(BUILD_VERSION ${CMAKE_MATCH_1})
endif()
if (BUILD_VERSION)
# This leaves a trailing space on the last word, but we actually want that
# because of how it's styled in the title bar.
set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ")
else()
set(BUILD_FULLNAME "")
endif()
endif()
endif()
list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/CMakeModules")
include(GenerateBuildInfo)

# The variable SRC_DIR must be passed into the script (since it uses the current build directory for all values of CMAKE_*_DIR)
set(VIDEO_CORE "${SRC_DIR}/src/video_core")
Expand Down
58 changes: 31 additions & 27 deletions src/citra_qt/Info.plist → dist/apple/Info.plist.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,49 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<!-- Templated data -->
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string></string>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>citra.icns</string>
<key>CFBundleIdentifier</key>
<string>com.citra-emu.citra</string>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<!-- Fixed -->
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>NSCameraUsageDescription</key>
<string>This app requires camera access to emulate the 3DS&apos;s cameras.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to emulate the 3DS&apos;s microphone.</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string></string>
<key>CFBundleName</key>
<string>Citra</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string></string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string></string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSRequiresCarbon</key>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string></string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
<string>True</string>
<key>NSCameraUsageDescription</key>
<string>This app requires camera access to emulate the 3DS&apos;s cameras.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to emulate the 3DS&apos;s microphone.</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
</dict>
</plist>
42 changes: 42 additions & 0 deletions dist/apple/LaunchScreen.storyboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="Y6W-OH-hqX">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_logo.png" translatesAutoresizingMaskIntoConstraints="NO" id="yrZ-hu-Uge">
<rect key="frame" x="-59.666666666666657" y="306" width="512.33333333333337" height="240"/>
<constraints>
<constraint firstAttribute="height" constant="240" id="VhL-hA-Bwr"/>
</constraints>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="yrZ-hu-Uge" firstAttribute="centerX" secondItem="5EZ-qb-Rvc" secondAttribute="centerX" id="1y3-Mx-a65"/>
<constraint firstItem="yrZ-hu-Uge" firstAttribute="centerY" secondItem="5EZ-qb-Rvc" secondAttribute="centerY" id="vNO-xV-EPD"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="219" y="18"/>
</scene>
</scenes>
<resources>
<image name="launch_logo.png" width="512" height="512"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
File renamed without changes.
Binary file added dist/apple/launch_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions externals/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ target_include_directories(enet INTERFACE ./enet/include)
# Cubeb
if (ENABLE_CUBEB)
set(BUILD_TESTS OFF CACHE BOOL "")
set(BUILD_TOOLS OFF CACHE BOOL "")
add_subdirectory(cubeb EXCLUDE_FROM_ALL)
endif()

Expand Down
2 changes: 1 addition & 1 deletion externals/libressl
Loading

0 comments on commit 238a574

Please sign in to comment.