Skip to content

Instantly share code, notes, and snippets.

@paulmasri
Last active June 26, 2025 18:45
Show Gist options
  • Save paulmasri/b5d80c743530093feebe051774b09ca6 to your computer and use it in GitHub Desktop.
Save paulmasri/b5d80c743530093feebe051774b09ca6 to your computer and use it in GitHub Desktop.
CMake for Qt 6 + Xcode (target iOS)
# This is an anonymised and annotated version of my CMake
# This enabled me to build / archive / validate / distribute my app in Xcode
# without having to manually edit any configuration in Xcode
cmake_minimum_required(VERSION 3.24)
# Some variables needed more than once below
set(MY_APP_PROJECT_NAME "My App")
set(PROJECT_VERSION 1.2.3)
set(MY_APP_REVERSE_DNS_IDENTIFIER "com.mycompany.myapp")
project(${MY_APP_PROJECT_NAME} VERSION ${PROJECT_VERSION} LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# C++ visibility needed to generate symbols for upload.
# Essential for being able to symbolicate crash reports.
# Note that Qt hide visibility of their own code by default and warn against
# making your own code visible. However I have not encountered any issues
# and I cannot get it to generate symbols without this.
# See also XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS below
set(CMAKE_CXX_VISIBILITY_PRESET default)
find_package(Qt6 6.4 REQUIRED COMPONENTS Core)
qt_standard_project_setup()
# Add the app target (along with your main.cpp)
qt_add_executable(MyAppTarget main.cpp)
# Other cross-platform target-specific code as needed
# qt_add_qml_module(MyAppTarget ...)
if (IOS)
# Provide the launch screen and app icon asset catalog to Xcode such that they get included in copied bundles
set(RESOURCE_ASSETS
"${CMAKE_CURRENT_SOURCE_DIR}/LaunchScreen.storyboard"
"${CMAKE_CURRENT_SOURCE_DIR}/AppIconSet.xcassets"
)
target_sources(MyAppTarget PRIVATE ${RESOURCE_ASSETS})
set_source_files_properties(${RESOURCE_ASSETS}
TARGET_DIRECTORY MyAppTarget
PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)
set_target_properties(MyAppTarget PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in"
# Suppress Qt's default launch screen
QT_IOS_LAUNCH_SCREEN "${CMAKE_CURRENT_SOURCE_DIR}/LaunchScreen.storyboard"
# New Xcode attributes for General tab
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER ${MY_APP_REVERSE_DNS_IDENTIFIER}
XCODE_ATTRIBUTE_PRODUCT_NAME ${MY_APP_PROJECT_NAME}
XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION ${PROJECT_VERSION}
XCODE_ATTRIBUTE_MARKETING_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon"
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY 2 # iPad only in my case
XCODE_ATTRIBUTE_INFOPLIST_KEY_CFBundleDisplayName ${MY_APP_PROJECT_NAME}
XCODE_ATTRIBUTE_INFOPLIST_KEY_LSApplicationCategoryType "public.app-category.mycategory" # Choose your own category
# Any other optional items – note how they appear in Info.plist
# These could have stayed in Info.plist but I prefer to edit everything in the CMake file.
XCODE_ATTRIBUTE_INFOPLIST_KEY_NSPhotoLibraryUsageDescription
"${MY_APP_PROJECT_NAME} accesses photos because..."
XCODE_ATTRIBUTE_INFOPLIST_KEY_NSCameraUsageDescription
"${MY_APP_PROJECT_NAME} accesses the camera because..."
XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS "YES"
)
endif()
# Other cross-platform target-specific code as needed
# target_link_libraries(MyAppTarget
# PRIVATE
# Qt6::Core
# ...
# )
install(TARGETS MyAppTarget
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleDisplayName</key>
<string>$(INFOPLIST_KEY_CFBundleDisplayName)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleDevelopmentRegion</key>
<string>en-GB</string>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>LSApplicationCategoryType</key>
<string>$(INFOPLIST_KEY_LSApplicationCategoryType)</string>
<key>UILaunchStoryboardName</key>
<string>@qt_ios_launch_screen_plist_entry@</string>
<key>UIRequiresFullScreen</key>
<true/>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSPhotoLibraryUsageDescription</key>
<string>$(INFOPLIST_KEY_NSPhotoLibraryUsageDescription)</string>
<key>NSCameraUsageDescription</key>
<string>$(INFOPLIST_KEY_NSCameraUsageDescription)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
</dict>
</plist>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment