Jelajahi Sumber

cmake: Add Xcode component to CMake build framework 3.0

Adds necessary macOS-specific implementation of the framework, focusing
on native Xcode builds.
PatTheMav 2 tahun lalu
induk
melakukan
bbeea0972a

+ 12 - 0
.swift-format

@@ -0,0 +1,12 @@
+{
+    "version": 1,
+    "lineLength": 120,
+    "indentation": {
+        "spaces": 4
+    },
+    "tabWidth": 4,
+    "maximumBlankLines": 1,
+    "respectsExistingLineBreaks": true,
+    "lineBreakBeforeControlFlowKeywords": false,
+    "lineBreakBeforeEachArgument": false
+}

+ 74 - 0
buildspec.json

@@ -0,0 +1,74 @@
+{
+    "dependencies": {
+        "prebuilt": {
+            "version": "2023-03-20",
+            "baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
+            "label": "Pre-Built obs-deps",
+            "hashes": {
+                "macos-x86_64": "bd4d3866c2e4b630410ff29b3f31a2553844af60b30fa0306d35d80a70f903ba",
+                "macos-arm64": "90078e2141818a37def7ebdceb3dcde71dc4adc1ce81d6e31ba21916f85c77bf",
+                "macos-universal": "a1c7f38701e0b6c0bd4224d3ab1a7b54d8eaf592dcee3223ce94404dc6787595",
+                "windows-x64": "79b259f65a0be9726b80b35ab86c07a1d5dc333bd3ef1391f6a0168ea6d28828",
+                "linux-x86_64": "36af10f49491193185dc1a115a29de31f9f2f4f7c01e4ebfe8a81b8094cd12f4"
+            }
+        },
+        "qt6": {
+            "version": "2023-03-20",
+            "baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
+            "label": "Pre-Built Qt6",
+            "hashes": {
+                "macos-x86_64": "8f5e1a865310898635d34b92e6d93c99c62f39289a17d6db140e776ba9b2e455",
+                "macos-arm64": "0011e2395afbb02aaa5e8641c4486680e30decc60e063ca5a73d6faf3649e723",
+                "macos-universal": "5bcbb8fee4b70a26912e04a62960c615153828eac66b9f0bcb0b30529193ca6e",
+                "windows-x64": "e52feb06203c043929e271acc3a8d1b2e959c26d8426c4a1fb6c7337fee4e5c8"
+            },
+            "debugSymbols": {
+                "windows-x64": "ae16477980e1bc602f244923f6e75c214311df286981211ee29a67ac060d4389"
+            }
+        },
+        "cef": {
+            "version": "5060",
+            "baseUrl": "https://cdn-fastly.obsproject.com/downloads",
+            "label": "Chromium Embedded Framework",
+            "hashes": {
+                "macos-x86_64": "7ef71717ff2e4ff4212274c33f0993729f47c109c464e499544fd3f63586a069",
+                "macos-arm64": "a9da8909202aefc8f35509d03eff9a7c837b5d3b2ed3afb39b67121cb16d457b",
+                "linux-x86_64": "bf4aa9388bab7e94fa945cc3bba16b6da63b6a30f9c0342d42235468b39d84bf",
+                "linux-aarch64": "68d915c9ba2639cba762a54cd3430fce2527aa6355d831d3cfcb6157664206b0",
+                "windows-x64": "c1b47beb7ee42e98f1a41b6d694c26842a4a3d452e44bdf6f758c9785696533d"
+            },
+            "revision": {
+                "macos-x86_64": 2,
+                "macos-arm64": 2
+            }
+        },
+        "vlc": {
+            "version": "3.0.8",
+            "baseUrl": "https://downloads.videolan.org/vlc",
+            "label": "VLC",
+            "hashes": {
+                "windows-x64": "91f589ef69fce51645a3ecbb215b405c98db7b891479474ec3b5ed3b63c25e4a"
+            }
+        }
+    },
+    "platformConfig": {
+        "macos-x86_64": {
+            "qtVersion": 6,
+            "deploymentTarget": "11.0",
+            "buildTarget": "11.0"
+        },
+        "macos-arm64": {
+            "qtVersion": 6,
+            "deploymentTarget": "11.0",
+            "buildTarget": "11.0"
+        },
+        "windows-x64": {
+            "qtVersion": 6
+        },
+        "linux-x86_64": {
+            "qtVersion": 6,
+            "generator": "Ninja"
+        }
+    },
+    "name": "obs-studio"
+}

+ 41 - 0
cmake/macos/.cmake-format.json

@@ -0,0 +1,41 @@
+{
+  "format": {
+    "line_width": 120,
+    "tab_size": 2,
+    "dangle_parens": false,
+    "enable_sort": true,
+    "autosort": true
+  },
+  "additional_commands": {
+    "find_qt": {
+      "flags": [],
+      "kwargs": {
+        "COMPONENTS": "+",
+        "COMPONENTS_WIN": "+",
+        "COMPONENTS_MACOS": "+",
+        "COMPONENTS_LINUX": "+"
+      }
+    },
+    "set_target_properties_obs": {
+      "pargs": 1,
+      "flags": [],
+      "kwargs": {
+        "PROPERTIES": {
+          "kwargs": {
+            "PREFIX": 1,
+            "OUTPUT_NAME": 1,
+            "FOLDER": 1,
+            "VERSION": 1,
+            "SOVERSION": 1,
+            "FRAMEWORK": 1,
+            "BUNDLE": 1,
+            "AUTOMOC": 1,
+            "AUTOUIC": 1,
+            "AUTORCC": 1,
+            "AUTOUIC_SEARCH_PATHS": 1
+          }
+        }
+      }
+    }
+  }
+}

+ 193 - 0
cmake/macos/buildspec.cmake

@@ -0,0 +1,193 @@
+# OBS CMake macOS build dependencies module
+
+# cmake-format: off
+# cmake-lint: disable=E1126
+# cmake-lint: disable=R0912
+# cmake-lint: disable=R0915
+# cmake-format: on
+
+# _check_deps_version: Checks for obs-deps VERSION file in prefix paths
+macro(_check_deps_version version)
+  set(found FALSE)
+
+  foreach(path IN LISTS CMAKE_PREFIX_PATH)
+    if(EXISTS "${path}/share/obs-deps/VERSION")
+      if(dependency STREQUAL qt6 AND NOT EXISTS "${path}/lib/cmake/Qt6/Qt6Config.cmake")
+        set(found FALSE)
+        break()
+      endif()
+
+      file(READ "${path}/share/obs-deps/VERSION" _check_version)
+      string(REPLACE "\n" "" _check_version "${_check_version}")
+
+      if(_check_version VERSION_EQUAL version)
+        set(found TRUE)
+        break()
+      elseif(_check_version VERSION_LESS version)
+        message(AUTHOR_WARNING "Outdated ${label} version detected in ${path}: \n"
+                               "Found ${_check_version}, require ${version}")
+        list(REMOVE_ITEM CMAKE_PREFIX_PATH "${path}")
+        list(APPEND CMAKE_PREFIX_PATH "${path}")
+        continue()
+      else()
+        message(AUTHOR_WARNING "Future ${label} version detected in ${path}: \n"
+                               "Found ${_check_version}, require ${version}")
+        set(found TRUE)
+        break()
+      endif()
+    endif()
+  endforeach()
+endmacro()
+
+# _check_dependencies: Fetch and extract pre-built OBS build dependencies
+function(_check_dependencies)
+  if(CMAKE_OSX_ARCHITECTURES MATCHES ".+;.+")
+    set(arch universal)
+  else()
+    set(arch ${CMAKE_OSX_ARCHITECTURES})
+  endif()
+
+  file(READ "${CMAKE_CURRENT_SOURCE_DIR}/buildspec.json" buildspec)
+
+  # cmake-format: off
+  string(JSON deployment_target GET ${buildspec} platformConfig macos-${arch} deploymentTarget)
+  string(JSON dependency_data GET ${buildspec} dependencies)
+  # cmake-format: on
+
+  if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
+    set(CMAKE_OSX_DEPLOYMENT_TARGET
+        ${_deployment_target}
+        CACHE STRING "Minimum macOS version to target for deployment (at runtime). Newer APIs will be weak-linked."
+              FORCE)
+  endif()
+
+  set(dependencies_dir "${CMAKE_CURRENT_SOURCE_DIR}/.deps")
+  set(prebuilt_filename "macos-deps-VERSION-ARCH-REVISION.tar.xz")
+  set(prebuilt_destination "obs-deps-VERSION-ARCH")
+  set(qt6_filename "macos-deps-qt6-VERSION-ARCH-REVISION.tar.xz")
+  set(qt6_destination "obs-deps-qt6-VERSION-ARCH")
+  set(cef_filename "cef_binary_VERSION_macos_ARCH_REVISION.tar.xz")
+  set(cef_destination "cef_binary_VERSION_macos_ARCH")
+
+  foreach(dependency IN ITEMS prebuilt qt6 cef)
+    # cmake-format: off
+    string(JSON data GET ${dependency_data} ${dependency})
+    string(JSON version GET ${data} version)
+    string(JSON hash GET ${data} hashes macos-${arch})
+    string(JSON url GET ${data} baseUrl)
+    string(JSON label GET ${data} label)
+    string(JSON revision ERROR_VARIABLE error GET ${data} revision macos-${arch})
+    # cmake-format: on
+
+    message(STATUS "Setting up ${label}")
+
+    set(file "${${dependency}_filename}")
+    set(destination "${${dependency}_destination}")
+    string(REPLACE "VERSION" "${version}" file "${file}")
+    string(REPLACE "VERSION" "${version}" destination "${destination}")
+    string(REPLACE "ARCH" "${arch}" file "${file}")
+    string(REPLACE "ARCH" "${arch}" destination "${destination}")
+    if(revision)
+      string(REPLACE "_REVISION" "_v${revision}" file "${file}")
+      string(REPLACE "-REVISION" "-v${revision}" file "${file}")
+    else()
+      string(REPLACE "_REVISION" "" file "${file}")
+      string(REPLACE "-REVISION" "" file "${file}")
+    endif()
+
+    set(skip FALSE)
+    if(dependency STREQUAL prebuilt OR dependency STREQUAL qt6)
+      _check_deps_version(${version})
+
+      if(found)
+        set(skip TRUE)
+      endif()
+    elseif(_dependency STREQUAL sparkle)
+      find_library(SPARKLE Sparkle)
+
+      if(NOT ENABLE_SPARKLE OR SPARKLE)
+        set(skip TRUE)
+      else()
+        unset(SPARKLE CACHE)
+      endif()
+    elseif(dependency STREQUAL vlc)
+      if(NOT ENABLE_VLC OR (VLC_PATH AND EXISTS "${VLC_PATH}"))
+        set(skip TRUE)
+      endif()
+    elseif(dependency STREQUAL cef)
+      if(NOT ENABLE_BROWSER OR (CEF_ROOT_DIR AND EXISTS "${CEF_ROOT_DIR}"))
+        set(skip TRUE)
+      endif()
+    endif()
+
+    if(skip)
+      message(STATUS "Setting up ${label} - skipped")
+      continue()
+    endif()
+
+    if(dependency STREQUAL qt6 AND "$ENV{CI}")
+      # cmake-format: off
+      string(JSON hash GET ${buildspec} dependencies qt6 hashes macos-universal)
+      # cmake-format: on
+      string(REPLACE "${arch}" "universal" file "${file}")
+    endif()
+
+    if(dependency STREQUAL cef)
+      set(url ${url}/${file})
+    else()
+      set(url ${url}/${version}/${file})
+    endif()
+
+    if(NOT EXISTS "${dependencies_dir}/${file}")
+      message(STATUS "Downloading ${url}")
+      file(
+        DOWNLOAD "${url}" "${dependencies_dir}/${file}"
+        STATUS download_status
+        EXPECTED_HASH SHA256=${hash})
+
+      list(GET download_status 0 error_code)
+      list(GET download_status 1 error_message)
+      if(error_code GREATER 0)
+        message(STATUS "Downloading ${url} - Failure")
+        message(FATAL_ERROR "Unable to download ${url}, failed with error: ${error_message}")
+        file(REMOVE "${dependencies_dir}/${file}")
+      else()
+        message(STATUS "Downloading ${url} - done")
+      endif()
+    endif()
+
+    if(NOT EXISTS "${dependencies_dir}/${destination}")
+      file(MAKE_DIRECTORY "${dependencies_dir}/${destination}")
+      if(dependency STREQUAL vlc)
+        file(ARCHIVE_EXTRACT INPUT "${dependencies_dir}/${file}" DESTINATION "${dependencies_dir}")
+      else()
+        file(ARCHIVE_EXTRACT INPUT "${dependencies_dir}/${file}" DESTINATION "${dependencies_dir}/${destination}")
+      endif()
+      execute_process(COMMAND "xattr" -r -d com.apple.quarantine "${dependencies_dir}/${destination}"
+                      RESULT_VARIABLE result COMMAND_ERROR_IS_FATAL ANY)
+    endif()
+
+    if(dependency STREQUAL cef)
+      set(CEF_ROOT_DIR
+          "${dependencies_dir}/${destination}"
+          CACHE PATH "CEF Root directory" FORCE)
+    elseif(dependency STREQUAL prebuilt)
+      set(VLC_PATH
+          "${dependencies_dir}/${destination}"
+          CACHE PATH "VLC source code directory" FORCE)
+      list(APPEND CMAKE_PREFIX_PATH "${dependencies_dir}/${destination}")
+    elseif(dependency STREQUAL qt6)
+      list(APPEND CMAKE_PREFIX_PATH "${dependencies_dir}/${destination}")
+    endif()
+
+    message(STATUS "Setting up ${label} - done")
+  endforeach()
+
+  list(REMOVE_DUPLICATES CMAKE_PREFIX_PATH)
+
+  set(CMAKE_PREFIX_PATH
+      ${CMAKE_PREFIX_PATH}
+      CACHE PATH "CMake prefix search path" FORCE)
+endfunction()
+
+_check_dependencies()

+ 66 - 0
cmake/macos/compilerconfig.cmake

@@ -0,0 +1,66 @@
+# OBS CMake macOS compiler configuration module
+
+# Enable distinction between Clang and AppleClang
+if(POLICY CMP0025)
+  cmake_policy(SET CMP0025 NEW)
+endif()
+
+# Honor visibility presets for all target types (executable, shared, module, static)
+if(POLICY CMP0063)
+  cmake_policy(SET CMP0063 NEW)
+endif()
+
+include(ccache)
+include(compiler_common)
+include(simd)
+
+# Add default C and C++ compiler options if Xcode generator is not used
+if(NOT XCODE)
+  list(
+    APPEND
+    _obs_c_options
+    -Werror
+    -Wextra
+    -Wvla
+    -Wswitch
+    -Wformat-security
+    -Wunused-parameter
+    -Wno-unused-function
+    -Wno-missing-field-initializers
+    -Wformat
+    -fno-strict-aliasing
+    -Wno-error=shorten-64-to-32)
+
+  # Set symbols to be hidden by default for C and C++
+  set(CMAKE_CXX_STANDARD 17)
+  set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+  set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+  set(CMAKE_C_VISIBILITY_PRESET hidden)
+  set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE)
+
+  # Enable stripping of dead symbols when not building for Debug configuration
+  set(_release_configs RelWithDebInfo Release MinSizeRel)
+  if(CMAKE_BUILD_TYPE IN_LIST _release_configs)
+    add_link_options(LINKER:-dead_strip)
+  endif()
+
+  add_compile_options("$<$<COMPILE_LANGUAGE:C>:${_obs_c_options}>" "$<$<COMPILE_LANGUAGE:CXX>:${_obs_c_options}>")
+
+  option(ENABLE_COMPILER_TRACE "Enable clang time-trace (requires Ninja)" OFF)
+  mark_as_advanced(ENABLE_COMPILER_TRACE)
+
+  # Add time trace option to compiler, if enabled.
+  if(ENABLE_COMPILER_TRACE AND CMAKE_GENERATOR STREQUAL "Ninja")
+    add_compile_options($<$<COMPILE_LANGUAGE:C>:-ftime-trace> $<$<COMPILE_LANGUAGE:CXX>:-ftime-trace>)
+  else()
+    set(ENABLE_COMPILER_TRACE
+        OFF
+        CACHE STRING "Enable clang time-trace (requires Ninja)" FORCE)
+  endif()
+
+  # Enable color diagnostics for AppleClang
+  set(CMAKE_COLOR_DIAGNOSTICS ON)
+endif()
+
+add_compile_definitions($<$<CONFIG:DEBUG>:DEBUG> $<$<CONFIG:DEBUG>:_DEBUG>)

+ 49 - 0
cmake/macos/cpackconfig.cmake

@@ -0,0 +1,49 @@
+# OBS CMake macOS CPack configuration module
+
+include(cpackconfig_common)
+
+# Set architecture suffix for package file name based on project target
+if(CMAKE_OSX_ARCHITECTURES STREQUAL arm64)
+  set(_cpack_arch_suffix Apple)
+elseif(CMAKE_OSX_ARCHITECTURES STREQUAL x86_64)
+  set(_cpack_arch_suffix Intel)
+else()
+  set(_cpack_arch_suffix Universal)
+endif()
+
+if(ENABLE_RELEASE_BUILD)
+  set(CPACK_PACKAGE_VERSION ${OBS_VERSION_CANONICAL})
+else()
+  set(CPACK_PACKAGE_VERSION ${OBS_VERSION})
+endif()
+
+set(CPACK_PACKAGE_NAME "OBS")
+set(CPACK_PACKAGE_FILE_NAME "obs-studio-${CPACK_PACKAGE_VERSION}-macOS-${_cpack_arch_suffix}")
+set(CPACK_COMPONENTS_ALL Application)
+set(CPACK_COMPONENT_Application_DISPLAY_NAME "OBS Studio")
+
+# Set background image and icon for generated Drag&Drop disk image
+set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/cmake/macos/resources/background.tiff")
+set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/cmake/macos/resources/AppIcon.icns")
+cmake_path(GET CPACK_DMG_BACKGROUND_IMAGE FILENAME _cpack_dmg_background_filename)
+
+set(CPACK_GENERATOR DragNDrop)
+set(CPACK_DMG_FORMAT UDZO)
+set(CPACK_DMG_FILESYSTEM APFS)
+set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_BINARY_DIR}/package.applescript")
+
+set(_dmg_window_x 100)
+set(_dmg_window_y 100)
+set(_dmg_window_width 540)
+set(_dmg_window_height 380)
+set(_dmg_icon_size 96)
+set(_dmg_text_size 16)
+set(_dmg_obs_x 124)
+set(_dmg_obs_y 180)
+set(_dmg_app_link_x 416)
+set(_dmg_app_link_y 180)
+
+configure_file("${CMAKE_SOURCE_DIR}/cmake/macos/resources/package.applescript.in"
+               "${CMAKE_BINARY_DIR}/package.applescript" @ONLY)
+
+include(CPack)

+ 96 - 0
cmake/macos/defaults.cmake

@@ -0,0 +1,96 @@
+# OBS CMake macOS defaults module
+
+# Enable selection between arm64 and x86_64 targets
+if(NOT CMAKE_OSX_ARCHITECTURES)
+  set(CMAKE_OSX_ARCHITECTURES
+      arm64
+      CACHE STRING "Build architectures for macOS" FORCE)
+endif()
+set_property(CACHE CMAKE_OSX_ARCHITECTURES PROPERTY STRINGS arm64 x86_64)
+
+# Set empty codesigning team if not specified as cache variable
+if(NOT OBS_CODESIGN_TEAM)
+  set(OBS_CODESIGN_TEAM
+      ""
+      CACHE STRING "OBS code signing team for macOS" FORCE)
+
+  # Set ad-hoc codesigning identity if not specified as cache variable
+  if(NOT OBS_CODESIGN_IDENTITY)
+    set(OBS_CODESIGN_IDENTITY
+        "-"
+        CACHE STRING "OBS code signing identity for macOS" FORCE)
+  endif()
+endif()
+
+if(XCODE)
+  include(xcode)
+endif()
+
+include(buildspec)
+
+# Set default deployment target to 11.0 if not set and enable selection in GUI up to 13.0
+if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
+  set(CMAKE_OSX_DEPLOYMENT_TARGET
+      11.0
+      CACHE STRING "Minimum macOS version to target for deployment (at runtime). Newer APIs will be weak-linked." FORCE)
+endif()
+set_property(CACHE CMAKE_OSX_DEPLOYMENT_TARGET PROPERTY STRINGS 13.0 12.0 11.0)
+
+# Use Applications directory as default install destination
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+  set(CMAKE_INSTALL_PREFIX
+      "/Applications"
+      CACHE STRING "Directory to install OBS after building" FORCE)
+endif()
+
+# Show warning about missing CMAKE_PREFIX_PATH, usually required for successful builds
+if(NOT DEFINED CMAKE_PREFIX_PATH)
+  message(
+    WARNING "No CMAKE_PREFIX_PATH set: OBS supplies pre-built dependencies for building on macOS.\n"
+            "While OBS can be built using packages installed via Homebrew, pre-built dependencies "
+            "contain beneficial patches and fixes for use within OBS and is the suggested source "
+            "of these dependencies.\n"
+            "You can download the appropriate obs-deps package for your "
+            "architecture and set CMAKE_PREFIX_PATH to this directory:\n"
+            "CMAKE_PREFIX_PATH=\"<PATH_TO_OBS_DEPS>\"\n"
+            "Download pre-built OBS dependencies at https://github.com/obsproject/obs-deps/releases\n")
+endif()
+
+# SWIG hard codes the directory to its library directory at compile time. As obs-deps need to be relocatable, we need to
+# force SWIG to look for its files in a directory relative to the PREFIX_PATH. The best way to ensure this is to set the
+# SWIG_LIB environment variable.
+
+foreach(path IN LISTS CMAKE_PREFIX_PATH)
+  if(NOT DEFINED ENV{SWIG_LIB} AND EXISTS "${path}/bin/swig")
+    set(ENV{SWIG_LIB} "${path}/share/swig/CURRENT")
+    break()
+  endif()
+endforeach()
+
+# Set default values for CMake's bundle generator and created Info.plist files
+set(MACOSX_BUNDLE_EXECUTABLE_NAME OBS)
+set(MACOSX_BUNDLE_BUNDLE_NAME "${OBS_PRODUCT_NAME}")
+set(MACOSX_BUNDLE_BUNDLE_VERSION ${OBS_BUILD_NUMBER})
+set(MACOSX_BUNDLE_COPYRIGHT "${OBS_LEGAL_COPYRIGHT}")
+set(MACOSX_BUNDLE_GUI_IDENTIFIER com.obsproject.obs-studio)
+set(MACOSX_BUNDLE_ICON_FILE AppIcon)
+set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${OBS_VERSION_CANONICAL})
+string(TIMESTAMP CURRENT_YEAR "%Y")
+
+# Enable find_package targets to become globally available targets
+set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL TRUE)
+# Enable RPATH support for generated binaries
+set(CMAKE_MACOSX_RPATH TRUE)
+# Use RPATHs from build tree _in_ the build tree
+set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
+# Do not add default linker search paths to RPATH
+set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
+# Use common bundle-relative RPATH for installed targets
+set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks")
+
+# Used for library exports only (obs-frontend-api)
+set(OBS_LIBRARY_DESTINATION "lib")
+set(OBS_INCLUDE_DESTINATION "include/obs")
+set(OBS_CMAKE_DESTINATION "lib/cmake")
+
+include(cpackconfig)

+ 371 - 0
cmake/macos/helpers.cmake

@@ -0,0 +1,371 @@
+# OBS CMake macOS helper functions module
+
+# cmake-format: off
+# cmake-lint: disable=C0307
+# cmake-lint: disable=R0912
+# cmake-lint: disable=R0915
+# cmake-lint: disable=E1126
+# cmake-format: on
+
+include(helpers_common)
+
+# set_target_properties_obs: Set target properties for use in obs-studio
+function(set_target_properties_obs target)
+  set(options "")
+  set(oneValueArgs "")
+  set(multiValueArgs PROPERTIES)
+  cmake_parse_arguments(PARSE_ARGV 0 _STPO "${options}" "${oneValueArgs}" "${multiValueArgs}")
+
+  message(DEBUG "Setting additional properties for target ${target}...")
+
+  while(_STPO_PROPERTIES)
+    list(POP_FRONT _STPO_PROPERTIES key value)
+    set_property(TARGET ${target} PROPERTY ${key} "${value}")
+  endwhile()
+  get_target_property(target_type ${target} TYPE)
+
+  # Target is a GUI or CLI application
+  if(target_type STREQUAL EXECUTABLE)
+    if(target STREQUAL obs-studio)
+      _check_info_plist()
+      set_target_properties(
+        ${target}
+        PROPERTIES OUTPUT_NAME OBS
+                   MACOSX_BUNDLE TRUE
+                   MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/Info.plist.in"
+                   XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.obsproject.obs-studio
+                   XCODE_ATTRIBUTE_PRODUCT_NAME OBS
+                   XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME AppIcon
+                   XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY YES
+                   XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY YES
+                   XCODE_EMBED_PLUGINS_REMOVE_HEADERS_ON_COPY YES
+                   XCODE_EMBED_PLUGINS_CODE_SIGN_ON_COPY YES
+                   XCODE_ATTRIBUTE_COPY_PHASE_STRIP NO
+                   XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES)
+
+      get_property(obs_dependencies GLOBAL PROPERTY _OBS_DEPENDENCIES)
+      add_dependencies(${target} ${obs_dependencies})
+
+      if(NOT XCODE)
+        return()
+      endif()
+
+      get_property(obs_frameworks GLOBAL PROPERTY _OBS_FRAMEWORKS)
+      set_property(
+        TARGET ${target}
+        APPEND
+        PROPERTY XCODE_EMBED_FRAMEWORKS ${obs_frameworks})
+
+      if(SPARKLE_APPCAST_URL AND SPARKLE_PUBLIC_KEY)
+        set_property(
+          TARGET ${target}
+          APPEND
+          PROPERTY XCODE_EMBED_FRAMEWORKS ${SPARKLE})
+      endif()
+
+      get_property(obs_executables GLOBAL PROPERTY _OBS_EXECUTABLES)
+      foreach(executable IN LISTS obs_executables)
+        add_custom_command(
+          TARGET ${target}
+          POST_BUILD
+          COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE:${executable}>"
+                  "$<TARGET_BUNDLE_CONTENT_DIR:${target}>/MacOS/"
+          COMMENT "Copy ${executable} to application bundle")
+      endforeach()
+
+      _check_entitlements()
+
+      add_custom_command(
+        TARGET ${target}
+        POST_BUILD
+        COMMAND
+          /usr/bin/sed -i '' 's/font-size: 10pt\;/font-size: 12pt\;/'
+          "$<TARGET_BUNDLE_CONTENT_DIR:${target}>/Resources/themes/Acri.qss"
+          "$<TARGET_BUNDLE_CONTENT_DIR:${target}>/Resources/themes/Grey.qss"
+          "$<TARGET_BUNDLE_CONTENT_DIR:${target}>/Resources/themes/Light.qss"
+          "$<TARGET_BUNDLE_CONTENT_DIR:${target}>/Resources/themes/Rachni.qss"
+          "$<TARGET_BUNDLE_CONTENT_DIR:${target}>/Resources/themes/Yami.qss"
+        COMMENT "Patch Qt stylesheets to use larger default font size on macOS")
+
+      add_custom_command(
+        TARGET ${target}
+        POST_BUILD
+        COMMAND /bin/ln -fs obs-frontend-api.dylib libobs-frontend-api.1.dylib
+        WORKING_DIRECTORY "$<TARGET_BUNDLE_CONTENT_DIR:${target}>/Frameworks"
+        COMMENT "Create symlink for legacy obs-frontend-api")
+
+      if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/qt.conf")
+        target_add_resource(${target} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/qt.conf")
+      endif()
+
+      target_add_resource(${target} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/Assets.xcassets")
+      target_add_resource(${target} "${CMAKE_CURRENT_SOURCE_DIR}/../AUTHORS")
+
+      if(TARGET obs-dal-plugin)
+        add_custom_command(
+          TARGET ${target}
+          POST_BUILD
+          COMMAND "${CMAKE_COMMAND}" -E copy_directory "$<TARGET_BUNDLE_DIR:obs-dal-plugin>"
+                  "$<TARGET_BUNDLE_CONTENT_DIR:${target}>/Resources/$<TARGET_BUNDLE_DIR_NAME:obs-dal-plugin>"
+          COMMENT "Add OBS DAL plugin to application bundle")
+      endif()
+
+      if(TARGET obspython)
+        add_custom_command(
+          TARGET ${target}
+          POST_BUILD
+          COMMAND "${CMAKE_COMMAND}" -E copy_if_different "$<TARGET_FILE_DIR:obspython>/obspython.py"
+                  "$<TARGET_BUNDLE_CONTENT_DIR:${target}>/Resources"
+          COMMENT "Add OBS::python import module")
+      endif()
+
+      _bundle_dependencies(${target})
+
+      install(TARGETS ${target} BUNDLE DESTINATION "." COMPONENT Application)
+    else()
+      set_property(GLOBAL APPEND PROPERTY _OBS_EXECUTABLES ${target})
+      set_property(GLOBAL APPEND PROPERTY _OBS_DEPENDENCIES ${target})
+    endif()
+
+    _add_entitlements()
+  elseif(target_type STREQUAL SHARED_LIBRARY)
+    set_target_properties(
+      ${target}
+      PROPERTIES NO_SONAME TRUE
+                 MACHO_COMPATIBILITY_VERSION 1.0
+                 MACHO_CURRENT_VERSION ${OBS_VERSION_MAJOR}
+                 SOVERSION 0
+                 VERSION 0
+                 XCODE_ATTRIBUTE_DYLIB_COMPATIBILITY_VERSION 1.0
+                 XCODE_ATTRIBUTE_DYLIB_CURRENT_VERSION ${OBS_VERSION_MAJOR}
+                 XCODE_ATTRIBUTE_PRODUCT_NAME ${target}
+                 XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.obsproject.${target})
+
+    get_target_property(is_framework ${target} FRAMEWORK)
+    if(is_framework)
+      _check_info_plist()
+      set_target_properties(
+        ${target}
+        PROPERTIES FRAMEWORK_VERSION A
+                   MACOSX_FRAMEWORK_IDENTIFIER com.obsproject.${target}
+                   MACOSX_FRAMEWORK_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/Info.plist.in")
+    endif()
+
+    _add_entitlements()
+
+    set_property(GLOBAL APPEND PROPERTY _OBS_FRAMEWORKS ${target})
+    set_property(GLOBAL APPEND PROPERTY _OBS_DEPENDENCIES ${target})
+  elseif(target_type STREQUAL MODULE_LIBRARY)
+    if(target STREQUAL obspython)
+      set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_PRODUCT_NAME ${target}
+                                                 XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.obsproject.${target})
+    elseif(target STREQUAL obslua)
+      set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_PRODUCT_NAME ${target}
+                                                 XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.obsproject.${target})
+    elseif(target STREQUAL obs-dal-plugin)
+      set_target_properties(${target} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
+      set_property(GLOBAL APPEND PROPERTY _OBS_DEPENDENCIES ${target})
+      return()
+    else()
+      _check_info_plist()
+      set_target_properties(
+        ${target}
+        PROPERTIES BUNDLE TRUE
+                   BUNDLE_EXTENSION plugin
+                   MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/Info.plist.in"
+                   XCODE_ATTRIBUTE_PRODUCT_NAME ${target}
+                   XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER com.obsproject.${target})
+
+      if(target STREQUAL obs-browser)
+        # Good-enough for now as there are no other variants - in _theory_ we should only add the appropriate variant,
+        # but that is only known at project generation and not build system configuration.
+        get_target_property(imported_location CEF::Library IMPORTED_LOCATION_RELEASE)
+        if(imported_location)
+          list(APPEND cef_items "${imported_location}")
+        endif()
+
+        foreach(helper IN ITEMS _gpu _plugin _renderer "")
+          if(TARGET OBS::browser-helper${helper})
+            set_property(GLOBAL APPEND PROPERTY _OBS_DEPENDENCIES OBS::browser-helper${helper})
+            list(APPEND cef_items OBS::browser-helper${helper})
+          endif()
+        endforeach()
+
+        set_property(GLOBAL APPEND PROPERTY _OBS_FRAMEWORKS ${cef_items})
+      endif()
+    endif()
+
+    set_property(GLOBAL APPEND PROPERTY OBS_MODULES_ENABLED ${target})
+    set_property(GLOBAL APPEND PROPERTY _OBS_DEPENDENCIES ${target})
+  endif()
+
+  target_install_resources(${target})
+
+  get_target_property(target_sources ${target} SOURCES)
+  set(target_ui_files ${target_sources})
+  list(FILTER target_ui_files INCLUDE REGEX ".+\\.(ui|qrc)")
+  source_group(
+    TREE "${CMAKE_CURRENT_SOURCE_DIR}"
+    PREFIX "UI Files"
+    FILES ${target_ui_files})
+
+  if(${target} STREQUAL libobs)
+    set(target_source_files ${target_sources})
+    set(target_header_files ${target_sources})
+    list(FILTER target_source_files INCLUDE REGEX ".+\\.(m|c[cp]?p?|swift)")
+    list(FILTER target_header_files INCLUDE REGEX ".+\\.h(pp)?")
+
+    source_group(
+      TREE "${CMAKE_CURRENT_SOURCE_DIR}"
+      PREFIX "Source Files"
+      FILES ${target_source_files})
+    source_group(
+      TREE "${CMAKE_CURRENT_SOURCE_DIR}"
+      PREFIX "Header Files"
+      FILES ${target_header_files})
+  endif()
+endfunction()
+
+# _check_info_plist: Macro to check if project ships with Info.plist template
+macro(_check_info_plist)
+  if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/Info.plist.in")
+    message(FATAL_ERROR "Target ${target} is missing an Info.plist template in its cmake directory.")
+  endif()
+endmacro()
+
+# _check_entitlements: Macro to check if project ships with entitlements plist
+macro(_check_entitlements)
+  if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/entitlements.plist")
+    message(FATAL_ERROR "Target ${target} is missing an entitlements.plist in its cmake directory.")
+  endif()
+endmacro()
+
+# _add_entitlements: Macro to add entitlements shipped with project
+macro(_add_entitlements)
+  if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/entitlements.plist")
+    set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS
+                                               "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos/entitlements.plist")
+  endif()
+endmacro()
+
+# target_export: Helper function to export target as CMake package
+function(target_export target)
+  # Exclude CMake package from 'ALL' target
+  set(exclude_variant EXCLUDE_FROM_ALL)
+  _target_export(${target})
+endfunction()
+
+# target_install_resources: Helper function to add resources into bundle
+function(target_install_resources target)
+  message(DEBUG "Installing resources for target ${target}...")
+  if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/data")
+    file(GLOB_RECURSE data_files "${CMAKE_CURRENT_SOURCE_DIR}/data/*")
+    foreach(data_file IN LISTS data_files)
+      cmake_path(RELATIVE_PATH data_file BASE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/data/" OUTPUT_VARIABLE
+                 relative_path)
+      cmake_path(GET relative_path PARENT_PATH relative_path)
+      target_sources(${target} PRIVATE "${data_file}")
+      set_property(SOURCE "${data_file}" PROPERTY MACOSX_PACKAGE_LOCATION "Resources/${relative_path}")
+      source_group("Resources/${relative_path}" FILES "${data_file}")
+    endforeach()
+  endif()
+endfunction()
+
+# target_add_resource: Helper function to add a specific resource to a bundle
+function(target_add_resource target resource)
+  message(DEBUG "Add resource ${resource} to target ${target} at destination ${destination}...")
+  target_sources(${target} PRIVATE "${resource}")
+  set_property(SOURCE "${resource}" PROPERTY MACOSX_PACKAGE_LOCATION Resources)
+  source_group("Resources" FILES "${resource}")
+endfunction()
+
+# _bundle_dependencies: Resolve 3rd party dependencies and add them to macOS app bundle
+function(_bundle_dependencies target)
+  message(DEBUG "Discover dependencies of target ${target}...")
+  set(found_dependencies)
+  find_dependencies(TARGET ${target} FOUND_VAR found_dependencies)
+
+  get_property(obs_module_list GLOBAL PROPERTY OBS_MODULES_ENABLED)
+  list(LENGTH obs_module_list num_modules)
+  if(num_modules GREATER 0)
+    add_dependencies(${target} ${obs_module_list})
+    set_property(
+      TARGET ${target}
+      APPEND
+      PROPERTY XCODE_EMBED_PLUGINS ${obs_module_list})
+    foreach(module IN LISTS obs_module_list)
+      find_dependencies(TARGET ${module} FOUND_VAR found_dependencies)
+    endforeach()
+  endif()
+
+  list(REMOVE_DUPLICATES found_dependencies)
+
+  set(library_paths)
+  set(plugins_list)
+  file(GLOB sdk_library_paths /Applications/Xcode*.app)
+  set(system_library_path "/usr/lib/")
+
+  foreach(library IN LISTS found_dependencies)
+    get_target_property(library_type ${library} TYPE)
+    get_target_property(is_framework ${library} FRAMEWORK)
+    get_target_property(is_imported ${library} IMPORTED)
+
+    if(is_imported)
+      get_target_property(imported_location ${library} LOCATION)
+      if(NOT imported_location)
+        continue()
+      endif()
+
+      set(is_xcode_framework FALSE)
+      set(is_system_framework FALSE)
+
+      foreach(sdk_library_path IN LISTS sdk_library_paths)
+        if(is_xcode_framework)
+          break()
+        endif()
+        cmake_path(IS_PREFIX sdk_library_path "${imported_location}" is_xcode_framework)
+      endforeach()
+      cmake_path(IS_PREFIX system_library_path "${imported_location}" is_system_framework)
+
+      if(is_system_framework OR is_xcode_framework)
+        continue()
+      elseif(is_framework)
+        file(REAL_PATH "../../.." library_location BASE_DIRECTORY "${imported_location}")
+      elseif(NOT library_type STREQUAL "STATIC_LIBRARY")
+        if(NOT imported_location MATCHES ".+\\.a")
+          set(library_location "${imported_location}")
+        else()
+          continue()
+        endif()
+      else()
+        continue()
+      endif()
+
+      if(library MATCHES "Qt[56]?::.+")
+        find_qt_plugins(COMPONENT ${library} TARGET ${target} FOUND_VAR plugins_list)
+      endif()
+      list(APPEND library_paths ${library_location})
+    elseif(NOT imported AND library_type STREQUAL "SHARED_LIBRARY")
+      message(TRACE "${library} is a project target")
+      list(APPEND library_paths ${library})
+    endif()
+  endforeach()
+
+  list(REMOVE_DUPLICATES plugins_list)
+  foreach(plugin IN LISTS plugins_list)
+    cmake_path(GET plugin PARENT_PATH plugin_path)
+    set(plugin_base_dir "${plugin_path}/../")
+    cmake_path(SET plugin_stem_dir NORMALIZE "${plugin_base_dir}")
+    cmake_path(RELATIVE_PATH plugin_path BASE_DIRECTORY "${plugin_stem_dir}" OUTPUT_VARIABLE plugin_file_name)
+    target_sources(${target} PRIVATE "${plugin}")
+    set_source_files_properties("${plugin}" PROPERTIES MACOSX_PACKAGE_LOCATION "plugins/${plugin_file_name}"
+                                                       XCODE_FILE_ATTRIBUTES "CodeSignOnCopy")
+    source_group("Qt plugins" FILES "${plugin}")
+  endforeach()
+
+  list(REMOVE_DUPLICATES library_paths)
+  set_property(
+    TARGET ${target}
+    APPEND
+    PROPERTY XCODE_EMBED_FRAMEWORKS ${library_paths})
+endfunction()

TEMPAT SAMPAH
cmake/macos/resources/AppIcon.icns


TEMPAT SAMPAH
cmake/macos/resources/background.tiff


+ 13 - 0
cmake/macos/resources/ccache-launcher-c.in

@@ -0,0 +1,13 @@
+#!/bin/sh
+
+if [[ "$1" == "${CMAKE_C_COMPILER}" ]] ; then
+    shift
+fi
+
+export CCACHE_CPP2=true
+export CCACHE_DEPEND=true
+export CCACHE_DIRECT=true
+export CCACHE_FILECLONE=true
+export CCACHE_INODECACHE=true
+export CCACHE_SLOPPINESS="modules,include_file_mtime,include_file_ctime,pch_defines,clang_index_store,system_headers"
+exec "${CMAKE_C_COMPILER_LAUNCHER}" "${CMAKE_C_COMPILER}" "$@"

+ 13 - 0
cmake/macos/resources/ccache-launcher-cxx.in

@@ -0,0 +1,13 @@
+#!/bin/sh
+
+if [[ "$1" == "${CMAKE_CXX_COMPILER}" ]] ; then
+    shift
+fi
+
+export CCACHE_CPP2=true
+export CCACHE_DEPEND=true
+export CCACHE_DIRECT=true
+export CCACHE_FILECLONE=true
+export CCACHE_INODECACHE=true
+export CCACHE_SLOPPINESS="modules,include_file_mtime,include_file_ctime,pch_defines,clang_index_store,system_headers"
+exec "${CMAKE_CXX_COMPILER_LAUNCHER}" "${CMAKE_CXX_COMPILER}" "$@"

+ 66 - 0
cmake/macos/resources/package.applescript.in

@@ -0,0 +1,66 @@
+on run (volumeName)
+    tell application "Finder"
+        tell disk (volumeName as string)
+            open
+
+            set theXOrigin to @_dmg_window_x@
+            set theYOrigin to @_dmg_window_y@
+            set theWidth to @_dmg_window_width@
+            set theHeight to @_dmg_window_height@
+
+            set theBottomRightX to (theXOrigin + theWidth)
+            set theBottomRightY to (theYOrigin + theHeight)
+            set dsStore to "\"" & "/Volumes/" & volumeName & "/" & ".DS_STORE\""
+
+            tell container window
+                set current view to icon view
+                set toolbar visible to false
+                set statusbar visible to false
+                set the bounds to {theXOrigin, theYOrigin, theBottomRightX, theBottomRightY}
+                set statusbar visible to false
+                set position of every item to {theBottomRightX + 100, 100}
+            end tell
+
+            set opts to the icon view options of container window
+            tell opts
+                set icon size to @_dmg_icon_size@
+                set text size to @_dmg_text_size@
+                set arrangement to not arranged
+            end tell
+            set background picture of opts to file ".background:@_cpack_dmg_background_filename@"
+            set position of item "@[email protected]" to {@_dmg_obs_x@, @_dmg_obs_y@}
+            set position of item "Applications" to {@_dmg_app_link_x@, @_dmg_app_link_y@}
+            close
+            open
+            -- Force saving of the size
+            delay 1
+
+            tell container window
+                set statusbar visible to false
+                set the bounds to {theXOrigin, theYOrigin, theBottomRightX - 10, theBottomRightY - 10}
+            end tell
+        end tell
+
+        delay 1
+
+        tell disk (volumeName as string)
+            tell container window
+                set statusbar visible to false
+                set the bounds to {theXOrigin, theYOrigin, theBottomRightX, theBottomRightY}
+            end tell
+        end tell
+
+        --give the finder some time to write the .DS_Store file
+        delay 3
+
+        set waitTime to 0
+        set ejectMe to false
+        repeat while ejectMe is false
+            delay 1
+            set waitTime to waitTime + 1
+
+            if (do shell script "[ -f " & dsStore & " ]; echo $?") = "0" then set ejectMe to true
+        end repeat
+        log "waited " & waitTime & " seconds for .DS_STORE to be created."
+    end tell
+end run

+ 7 - 0
cmake/macos/simd.cmake

@@ -0,0 +1,7 @@
+# OBS CMake macOS SIMD module
+
+# Enable openmp-simd when compiling for arm64
+if(CMAKE_OSX_ARCHITECTURES MATCHES ".*[aA][rR][mM]64e?.*" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
+  set(ARCH_SIMD_FLAGS -fopenmp-simd)
+  set(ARCH_SIMD_DEFINES SIMDE_ENABLE_OPENMP)
+endif()

+ 134 - 0
cmake/macos/xcode.cmake

@@ -0,0 +1,134 @@
+# OBS CMake macOS Xcode module
+
+# Use a compiler wrapper to enable ccache in Xcode projects
+if(ENABLE_CCACHE AND CCACHE_PROGRAM)
+  configure_file("${CMAKE_SOURCE_DIR}/cmake/macos/resources/ccache-launcher-c.in" ccache-launcher-c)
+  configure_file("${CMAKE_SOURCE_DIR}/cmake/macos/resources/ccache-launcher-cxx.in" ccache-launcher-cxx)
+
+  execute_process(COMMAND chmod a+rx "${CMAKE_BINARY_DIR}/ccache-launcher-c" "${CMAKE_BINARY_DIR}/ccache-launcher-cxx")
+  set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/ccache-launcher-c")
+  set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/ccache-launcher-cxx")
+  set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_C_COMPILER}")
+  set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CXX_COMPILER}")
+endif()
+
+# Set project variables
+set(CMAKE_XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION ${OBS_BUILD_NUMBER})
+set(CMAKE_XCODE_ATTRIBUTE_DYLIB_COMPATIBILITY_VERSION 1.0.0)
+set(CMAKE_XCODE_ATTRIBUTE_MARKETING_VERSION ${OBS_VERSION_CANONICAL})
+
+# Set deployment target
+set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET ${CMAKE_OSX_DEPLOYMENT_TARGET})
+
+if(NOT OBS_CODESIGN_TEAM)
+  # Switch to manual codesigning if no codesigning team is provided
+  set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual)
+  set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${OBS_CODESIGN_IDENTITY}")
+else()
+  if(DEFINED OBS_CODESIGN_IDENTITY AND NOT OBS_CODESIGN_IDENTITY STREQUAL "-")
+    # Switch to manual codesigning if a non-adhoc codesigning identity is provided
+    set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual)
+    set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${OBS_CODESIGN_IDENTITY}")
+  else()
+    # Switch to automatic codesigning via valid team ID
+    set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic)
+  endif()
+  set(CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${OBS_CODESIGN_TEAM}")
+endif()
+
+# Only create a single Xcode project file
+set(CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY TRUE)
+# Add all libraries to project link phase (lets Xcode handle linking)
+set(CMAKE_XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION)
+
+# Enable codesigning with secure timestamp when not in Debug configuration (required for Notarization)
+set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS[variant=Release] "--timestamp")
+set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS[variant=RelWithDebInfo] "--timestamp")
+set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS[variant=MinSizeRel] "--timestamp")
+
+# Enable codesigning with hardened runtime option when not in Debug configuration (required for Notarization)
+set(CMAKE_XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME[variant=Release] YES)
+set(CMAKE_XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME[variant=RelWithDebInfo] YES)
+set(CMAKE_XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME[variant=MinSizeRel] YES)
+
+# Disable injection of Xcode's base entitlements used for debugging when not in Debug configuration (required for
+# Notarization)
+set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_INJECT_BASE_ENTITLEMENTS[variant=Release] NO)
+set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_INJECT_BASE_ENTITLEMENTS[variant=RelWithDebInfo] NO)
+set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_INJECT_BASE_ENTITLEMENTS[variant=MinSizeRel] NO)
+
+# Use Swift version 5.0 by default
+set(CMAKE_XCODE_ATTRIBUTE_SWIFT_VERSION 5.0)
+
+# Use DWARF with separate dSYM files when in Release or MinSizeRel configuration
+set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Debug] dwarf)
+set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=RelWithDebInfo] dwarf)
+set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Release] dwarf-with-dsym)
+set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=MinSizeRel] dwarf-with-dsym)
+
+# Strip generated and installed products only in Release or MinSizeRel configuration
+set(CMAKE_XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT[variant=Release] YES)
+set(CMAKE_XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT[variant=MinSizeRel] YES)
+
+# Make all symbols hidden by default
+set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN YES)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_INLINES_ARE_PRIVATE_EXTERN YES)
+
+# Strip unused code in Release or MinSizeRel configuration only
+set(CMAKE_XCODE_ATTRIBUTE_DEAD_CODE_STRIPPING[variant=Release] YES)
+set(CMAKE_XCODE_ATTRIBUTE_DEAD_CODE_STRIPPING[variant=MinSizeRel] YES)
+
+# Display mangled names in Debug configuration
+set(CMAKE_XCODE_ATTRIBUTE_LINKER_DISPLAYS_MANGLED_NAMES[variant=Debug] YES)
+
+# Disable using ARC in ObjC by default (OBS does not support this - yet)
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC NO)
+# Disable strict aliasing
+set(CMAKE_XCODE_ATTRIBUTE_GCC_STRICT_ALIASING NO)
+# cmake-format: off
+# Re-enable once the bad goto statements are fixed
+# set(CMAKE_XCODE_ATTRIBUTE_GCC_C_LANGUAGE_STANDARD c99)
+# cmake-format: on
+# Set C++ language default to c++17
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD c++17)
+# Enable support for module imports in ObjC
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES NO)
+# Enable automatic linking of imported modules in ObjC
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_MODULES_AUTOLINK NO)
+# Enable strict msg_send rules for ObjC
+set(CMAKE_XCODE_ATTRIBUTE_ENABLE_STRICT_OBJC_MSGSEND YES)
+
+# Set default warnings for ObjC and C++
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING YES_ERROR)
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION NO)
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS YES)
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK YES)
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_RANGE_LOOP_ANALYSIS YES)
+set(CMAKE_XCODE_ATTRIBUTE_CLANG_WARN_EMPTY_BODY YES)
+
+# Set default warnings for C and C++
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS NO)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_MISSING_NEWLINE YES)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_ABOUT_RETURN_TYPE YES_ERROR)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_CHECK_SWITCH_STATEMENTS YES)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_FOUR_CHARACTER_CONSTANTS YES)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_SIGN_COMPARE YES)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_SHADOW NO)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_FUNCTION NO)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_PARAMETER YES)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VALUE YES)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_VARIABLE YES)
+set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_TYPECHECK_CALLS_TO_PRINTF YES)
+
+# Add additional warning compiler flags
+set(CMAKE_XCODE_ATTRIBUTE_WARNING_CFLAGS "-Wvla -Wformat-security -Wno-error=shorten-64-to-32")
+
+set(CMAKE_XCODE_ATTRIBUTE_GCC_TREAT_WARNINGS_AS_ERRORS YES)
+
+# Disable color diagnostics
+set(CMAKE_COLOR_DIAGNOSTICS FALSE)
+
+# Disable usage of RPATH in build or install configurations
+set(CMAKE_SKIP_RPATH TRUE)
+# Have Xcode set default RPATH entries
+set(CMAKE_XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks")