Ver Fonte

cmake: Add updated common CMake scripts

PatTheMav há 2 anos atrás
pai
commit
094c88115e

+ 77 - 0
cmake/common/bootstrap.cmake

@@ -0,0 +1,77 @@
+cmake_minimum_required(VERSION 3.16...3.26)
+
+include_guard(GLOBAL)
+
+# Enable automatic PUSH and POP of policies to parent scope
+if(POLICY CMP0011)
+  cmake_policy(SET CMP0011 NEW)
+endif()
+
+# Enable distinction between Clang and AppleClang
+if(POLICY CMP0025)
+  cmake_policy(SET CMP0025 NEW)
+endif()
+
+# Enable strict checking of "break()" usage
+if(POLICY CMP0055)
+  cmake_policy(SET CMP0055 NEW)
+endif()
+
+# Honor visibility presets for all target types (executable, shared, module, static)
+if(POLICY CMP0063)
+  cmake_policy(SET CMP0063 NEW)
+endif()
+
+# Disable export function calls to populate package registry by default
+if(POLICY CMP0090)
+  cmake_policy(SET CMP0090 NEW)
+endif()
+
+# Prohibit in-source builds
+if("${CMAKE_CURRENT_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
+  message(FATAL_ERROR "In-source builds are not supported. "
+                      "Specify a build directory via 'cmake -S <SOURCE DIRECTORY> -B <BUILD_DIRECTORY>' instead.")
+  file(REMOVE_RECURSE "${CMAKE_CURRENT_SOURCE_DIR}/CMakeCache.txt" "${CMAKE_CURRENT_SOURCE_DIR}/CMakeFiles")
+endif()
+
+# Use folders for source file organization with IDE generators (Visual Studio/Xcode)
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+# Add common module directories to default search path
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/common")
+
+file(READ "${CMAKE_CURRENT_SOURCE_DIR}/buildspec.json" buildspec)
+
+# cmake-format: off
+string(JSON _name GET ${buildspec} name)
+string(JSON _website GET ${buildspec} website)
+string(JSON _author GET ${buildspec} author)
+string(JSON _email GET ${buildspec} email)
+string(JSON _version GET ${buildspec} version)
+string(JSON _bundleId GET ${buildspec} platformConfig macos bundleId)
+string(JSON _macosPackageUUID GET ${buildspec} uuids macosPackage)
+string(JSON _macosInstallerUUID GET ${buildspec} uuids macosInstaller)
+string(JSON _windowsAppUUID GET ${buildspec} uuids windowsApp)
+# cmake-format: on
+
+set(PLUGIN_AUTHOR ${_author})
+set(PLUGIN_WEBSITE ${_website})
+set(PLUGIN_EMAIL ${_email})
+set(PLUGIN_VERSION ${_version})
+set(MACOS_BUNDLEID ${_bundleId})
+
+include(buildnumber)
+include(osconfig)
+
+# Allow selection of common build types via UI
+if(NOT CMAKE_BUILD_TYPE)
+  set(CMAKE_BUILD_TYPE
+      "RelWithDebInfo"
+      CACHE STRING "OBS build type [Release, RelWithDebInfo, Debug, MinSizeRel]" FORCE)
+  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Release RelWithDebInfo Debug MinSizeRel)
+endif()
+
+# Disable exports automatically going into the CMake package registry
+set(CMAKE_EXPORT_PACKAGE_REGISTRY FALSE)
+# Enable default inclusion of targets' source and binary directory
+set(CMAKE_INCLUDE_CURRENT_DIR TRUE)

+ 21 - 0
cmake/common/buildnumber.cmake

@@ -0,0 +1,21 @@
+# CMake build number module
+
+include_guard(GLOBAL)
+
+# Define build number cache file
+set(_BUILD_NUMBER_CACHE
+    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/.CMakeBuildNumber"
+    CACHE INTERNAL "OBS build number cache file")
+
+# Read build number from cache file or manual override
+if(NOT DEFINED PLUGIN_BUILD_NUMBER AND EXISTS "${_BUILD_NUMBER_CACHE}")
+  file(READ "${_BUILD_NUMBER_CACHE}" PLUGIN_BUILD_NUMBER)
+  math(EXPR PLUGIN_BUILD_NUMBER "${PLUGIN_BUILD_NUMBER}+1")
+elseif(NOT DEFINED PLUGIN_BUILD_NUMBER)
+  if($ENV{CI} AND $ENV{GITHUB_RUN_ID})
+    set(PLUGIN_BUILD_NUMBER "$ENV{GITHUB_RUN_ID}")
+  else()
+    set(PLUGIN_BUILD_NUMBER "1")
+  endif()
+endif()
+file(WRITE "${_BUILD_NUMBER_CACHE}" "${PLUGIN_BUILD_NUMBER}")

+ 215 - 0
cmake/common/buildspec_common.cmake

@@ -0,0 +1,215 @@
+# Common build dependencies module
+
+# cmake-format: off
+# cmake-lint: disable=C0103
+# cmake-lint: disable=E1126
+# cmake-lint: disable=R0912
+# cmake-lint: disable=R0915
+# cmake-format: on
+
+include_guard(GLOBAL)
+
+# _check_deps_version: Checks for obs-deps VERSION file in prefix paths
+function(_check_deps_version version)
+  # cmake-format: off
+  set(found FALSE PARENT_SCOPE)
+  # cmake-format: on
+
+  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")
+        # cmake-format: off
+        set(found FALSE PARENT_SCOPE)
+        # cmake-format: on
+        continue()
+      endif()
+
+      file(READ "${path}/share/obs-deps/VERSION" _check_version)
+      string(REPLACE "\n" "" _check_version "${_check_version}")
+      string(REPLACE "-" "." _check_version "${_check_version}")
+      string(REPLACE "-" "." version "${version}")
+
+      if(_check_version VERSION_EQUAL version)
+        # cmake-format: off
+        set(found TRUE PARENT_SCOPE)
+        # cmake-format: on
+        break()
+      elseif(_check_version VERSION_LESS version)
+        message(AUTHOR_WARNING "Older ${label} version detected in ${path}: \n"
+                               "Found ${_check_version}, require ${version}")
+        list(REMOVE_ITEM CMAKE_PREFIX_PATH "${path}")
+        list(APPEND CMAKE_PREFIX_PATH "${path}")
+        # cmake-format: off
+        set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
+        # cmake-format: on
+        continue()
+      else()
+        message(AUTHOR_WARNING "Newer ${label} version detected in ${path}: \n"
+                               "Found ${_check_version}, require ${version}")
+        # cmake-format: off
+        set(found TRUE PARENT_SCOPE)
+        # cmake-format: on
+        break()
+      endif()
+    endif()
+  endforeach()
+endfunction()
+
+# _setup_obs_studio: Create obs-studio build project, then build libobs and obs-frontend-api
+function(_setup_obs_studio)
+  if(NOT libobs_DIR)
+    set(_is_fresh --fresh)
+  endif()
+
+  if(OS_WINDOWS)
+    set(_cmake_generator "${CMAKE_GENERATOR}")
+    set(_cmake_arch "-A ${arch}")
+    set(_cmake_extra "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION} -DCMAKE_ENABLE_SCRIPTING=OFF")
+    set(_cmake_version "2.0.0")
+  elseif(OS_MACOS)
+    set(_cmake_generator "Xcode")
+    set(_cmake_arch "-DCMAKE_OSX_ARCHITECTURES:STRING='arm64;x86_64'")
+    set(_cmake_extra "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
+    set(_cmake_version "3.0.0")
+  endif()
+
+  message(STATUS "Configure ${label} (${arch})")
+  execute_process(
+    COMMAND
+      "${CMAKE_COMMAND}" -S "${dependencies_dir}/${_obs_destination}" -B
+      "${dependencies_dir}/${_obs_destination}/build_${arch}" -G ${_cmake_generator} "${_cmake_arch}"
+      -DOBS_CMAKE_VERSION:STRING=${_cmake_version} -DENABLE_PLUGINS:BOOL=OFF -DENABLE_UI:BOOL=OFF
+      -DOBS_VERSION_OVERRIDE:STRING=${_obs_version} "-DCMAKE_PREFIX_PATH='${CMAKE_PREFIX_PATH}'" ${_is_fresh}
+      ${_cmake_extra}
+    RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
+    OUTPUT_QUIET)
+  message(STATUS "Configure ${label} (${arch}) - done")
+
+  message(STATUS "Build ${label} (${arch})")
+  execute_process(
+    COMMAND "${CMAKE_COMMAND}" --build build_${arch} --target obs-frontend-api --config Debug --parallel
+    WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
+    RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
+    OUTPUT_QUIET)
+  message(STATUS "Build ${label} (${arch}) - done")
+
+  message(STATUS "Install ${label} (${arch})")
+  if(OS_WINDOWS)
+    set(_cmake_extra "--component obs_libraries")
+  else()
+    set(_cmake_extra "")
+  endif()
+  execute_process(
+    COMMAND "${CMAKE_COMMAND}" --install build_${arch} --component Development --config Debug --prefix
+            "${dependencies_dir}" ${_cmake_extra}
+    WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
+    RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
+    OUTPUT_QUIET)
+  message(STATUS "Install ${label} (${arch}) - done")
+endfunction()
+
+# _check_dependencies: Fetch and extract pre-built OBS build dependencies
+function(_check_dependencies)
+  if(NOT buildspec)
+    file(READ "${CMAKE_CURRENT_SOURCE_DIR}/buildspec.json" buildspec)
+  endif()
+
+  # cmake-format: off
+  string(JSON dependency_data GET ${buildspec} dependencies)
+  # cmake-format: on
+
+  foreach(dependency IN LISTS dependencies_list)
+    # cmake-format: off
+    string(JSON data GET ${dependency_data} ${dependency})
+    string(JSON version GET ${data} version)
+    string(JSON hash GET ${data} hashes ${platform})
+    string(JSON url GET ${data} baseUrl)
+    string(JSON label GET ${data} label)
+    string(JSON revision ERROR_VARIABLE error GET ${data} revision ${platform})
+    # cmake-format: on
+
+    message(STATUS "Setting up ${label} (${arch})")
+
+    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()
+    endif()
+
+    if(skip)
+      message(STATUS "Setting up ${label} (${arch}) - skipped")
+      continue()
+    endif()
+
+    if(dependency STREQUAL obs-studio)
+      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 obs-studio)
+        file(ARCHIVE_EXTRACT INPUT "${dependencies_dir}/${file}" DESTINATION "${dependencies_dir}")
+      else()
+        file(ARCHIVE_EXTRACT INPUT "${dependencies_dir}/${file}" DESTINATION "${dependencies_dir}/${destination}")
+      endif()
+    endif()
+
+    if(dependency STREQUAL prebuilt)
+      list(APPEND CMAKE_PREFIX_PATH "${dependencies_dir}/${destination}")
+    elseif(dependency STREQUAL qt6)
+      list(APPEND CMAKE_PREFIX_PATH "${dependencies_dir}/${destination}")
+    elseif(dependency STREQUAL obs-studio)
+      set(_obs_version ${version})
+      set(_obs_destination "${destination}")
+      list(APPEND CMAKE_PREFIX_PATH "${dependencies_dir}")
+
+    endif()
+
+    message(STATUS "Setting up ${label} (${arch}) - done")
+  endforeach()
+
+  list(REMOVE_DUPLICATES CMAKE_PREFIX_PATH)
+
+  # cmake-format: off
+  set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} CACHE PATH "CMake prefix search path" FORCE)
+  # cmake-format: on
+
+  _setup_obs_studio()
+endfunction()

+ 22 - 0
cmake/common/ccache.cmake

@@ -0,0 +1,22 @@
+# CMake ccache module
+
+include_guard(GLOBAL)
+
+if(NOT DEFINED CCACHE_PROGRAM)
+  message(DEBUG "Trying to find ccache on build host...")
+  find_program(CCACHE_PROGRAM "ccache")
+  mark_as_advanced(CCACHE_PROGRAM)
+endif()
+
+if(CCACHE_PROGRAM)
+  message(DEBUG "Ccache found as ${CCACHE_PROGRAM}...")
+  option(ENABLE_CCACHE "Enable compiler acceleration with ccache" ON)
+
+  if(ENABLE_CCACHE)
+    set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
+    set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
+    set(CMAKE_OBJC_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
+    set(CMAKE_OBJCXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
+    set(CMAKE_CUDA_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
+  endif()
+endif()

+ 87 - 0
cmake/common/compiler_common.cmake

@@ -0,0 +1,87 @@
+# CMake common compiler options module
+
+include_guard(GLOBAL)
+
+# Set C and C++ language standards to C17 and C++17
+if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17)
+  set(CMAKE_C_STANDARD 17)
+else()
+  set(CMAKE_C_STANDARD 11)
+endif()
+set(CMAKE_C_STANDARD_REQUIRED TRUE)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
+
+# Set symbols to be hidden by default for C and C++
+set(CMAKE_C_VISIBILITY_PRESET hidden)
+set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE)
+
+# clang options for C
+set(_obs_clang_c_options
+    # cmake-format: sortable
+    -fno-strict-aliasing
+    -Wbool-conversion
+    -Wcomma
+    -Wconstant-conversion
+    -Wdeprecated-declarations
+    -Wempty-body
+    -Wenum-conversion
+    -Werror=return-type
+    -Wextra
+    -Wformat
+    -Wformat-security
+    -Wfour-char-constants
+    -Winfinite-recursion
+    -Wint-conversion
+    -Wnewline-eof
+    -Wno-conversion
+    -Wno-float-conversion
+    -Wno-implicit-fallthrough
+    -Wno-missing-braces
+    -Wno-missing-field-initializers
+    -Wno-missing-prototypes
+    -Wno-semicolon-before-method-body
+    -Wno-shadow
+    -Wno-sign-conversion
+    -Wno-strict-prototypes
+    -Wno-trigraphs
+    -Wno-unknown-pragmas
+    -Wno-unused-function
+    -Wno-unused-label
+    -Wnon-literal-null-conversion
+    -Wobjc-literal-conversion
+    -Wparentheses
+    -Wpointer-sign
+    -Wquoted-include-in-framework-header
+    -Wshadow
+    -Wshorten-64-to-32
+    -Wuninitialized
+    -Wunreachable-code
+    -Wunused-parameter
+    -Wunused-value
+    -Wunused-variable
+    -Wvla)
+
+# clang options for C++
+set(_obs_clang_cxx_options
+    # cmake-format: sortable
+    ${_obs_clang_c_options}
+    -Wconversion
+    -Wdeprecated-implementations
+    -Wduplicate-method-match
+    -Wfloat-conversion
+    -Wfour-char-constants
+    -Wimplicit-retain-self
+    -Winvalid-offsetof
+    -Wmove
+    -Wno-c++11-extensions
+    -Wno-exit-time-destructors
+    -Wno-implicit-atomic-properties
+    -Wno-objc-interface-ivars
+    -Wno-overloaded-virtual
+    -Wrange-loop-analysis)
+
+if(NOT DEFINED CMAKE_COMPILE_WARNING_AS_ERROR)
+  set(CMAKE_COMPILE_WARNING_AS_ERROR ON)
+endif()

+ 137 - 0
cmake/common/helpers_common.cmake

@@ -0,0 +1,137 @@
+# CMake common helper functions module
+
+# cmake-format: off
+# cmake-lint: disable=C0103
+# cmake-format: on
+
+include_guard(GLOBAL)
+
+# * Use QT_VERSION value as a hint for desired Qt version
+# * If "AUTO" was specified, prefer Qt6 over Qt5
+# * Creates versionless targets of desired component if none had been created by Qt itself (Qt versions < 5.15)
+if(NOT QT_VERSION)
+  set(QT_VERSION
+      AUTO
+      CACHE STRING "OBS Qt version [AUTO, 5, 6]" FORCE)
+  set_property(CACHE QT_VERSION PROPERTY STRINGS AUTO 5 6)
+endif()
+
+# find_qt: Macro to find best possible Qt version for use with the project:
+macro(find_qt)
+  set(multiValueArgs COMPONENTS COMPONENTS_WIN COMPONENTS_MAC COMPONENTS_LINUX)
+  cmake_parse_arguments(find_qt "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  # Do not use versionless targets in the first step to avoid Qt::Core being clobbered by later opportunistic
+  # find_package runs
+  set(QT_NO_CREATE_VERSIONLESS_TARGETS TRUE)
+
+  message(DEBUG "Start Qt version discovery...")
+  # Loop until _QT_VERSION is set or FATAL_ERROR aborts script execution early
+  while(NOT _QT_VERSION)
+    message(DEBUG "QT_VERSION set to ${QT_VERSION}")
+    if(QT_VERSION STREQUAL AUTO AND NOT qt_test_version)
+      set(qt_test_version 6)
+    elseif(NOT QT_VERSION STREQUAL AUTO)
+      set(qt_test_version ${QT_VERSION})
+    endif()
+    message(DEBUG "Attempting to find Qt${qt_test_version}")
+
+    find_package(
+      Qt${qt_test_version}
+      COMPONENTS Core
+      QUIET)
+
+    if(TARGET Qt${qt_test_version}::Core)
+      set(_QT_VERSION
+          ${qt_test_version}
+          CACHE INTERNAL "")
+      message(STATUS "Qt version found: ${_QT_VERSION}")
+      unset(qt_test_version)
+      break()
+    elseif(QT_VERSION STREQUAL AUTO)
+      if(qt_test_version EQUAL 6)
+        message(WARNING "Qt6 was not found, falling back to Qt5")
+        set(qt_test_version 5)
+        continue()
+      endif()
+    endif()
+    message(FATAL_ERROR "Neither Qt6 nor Qt5 found.")
+  endwhile()
+
+  # Enable versionless targets for the remaining Qt components
+  set(QT_NO_CREATE_VERSIONLESS_TARGETS FALSE)
+
+  set(qt_components ${find_qt_COMPONENTS})
+  if(OS_WINDOWS)
+    list(APPEND qt_components ${find_qt_COMPONENTS_WIN})
+  elseif(OS_MACOS)
+    list(APPEND qt_components ${find_qt_COMPONENTS_MAC})
+  else()
+    list(APPEND qt_components ${find_qt_COMPONENTS_LINUX})
+  endif()
+  message(DEBUG "Trying to find Qt components ${qt_components}...")
+
+  find_package(Qt${_QT_VERSION} REQUIRED ${qt_components})
+
+  list(APPEND qt_components Core)
+
+  if("Gui" IN_LIST find_qt_COMPONENTS_LINUX)
+    list(APPEND qt_components "GuiPrivate")
+  endif()
+
+  # Check for versionless targets of each requested component and create if necessary
+  foreach(component IN LISTS qt_components)
+    message(DEBUG "Checking for target Qt::${component}")
+    if(NOT TARGET Qt::${component} AND TARGET Qt${_QT_VERSION}::${component})
+      add_library(Qt::${component} INTERFACE IMPORTED)
+      set_target_properties(Qt::${component} PROPERTIES INTERFACE_LINK_LIBRARIES Qt${_QT_VERSION}::${component})
+    endif()
+    set_property(TARGET Qt::${component} PROPERTY INTERFACE_COMPILE_FEATURES "")
+  endforeach()
+
+endmacro()
+
+# check_uuid: Helper function to check for valid UUID
+function(check_uuid uuid_string return_value)
+  set(valid_uuid TRUE)
+  set(uuid_token_lengths 8 4 4 4 12)
+  set(token_num 0)
+
+  string(REPLACE "-" ";" uuid_tokens ${uuid_string})
+  list(LENGTH uuid_tokens uuid_num_tokens)
+
+  if(uuid_num_tokens EQUAL 5)
+    message(DEBUG "UUID ${uuid_string} is valid with 5 tokens.")
+    foreach(uuid_token IN LISTS uuid_tokens)
+      list(GET uuid_token_lengths ${token_num} uuid_target_length)
+      string(LENGTH "${uuid_token}" uuid_actual_length)
+      if(uuid_actual_length EQUAL uuid_target_length)
+        string(REGEX MATCH "[0-9a-fA-F]+" uuid_hex_match ${uuid_token})
+        if(NOT uuid_hex_match STREQUAL uuid_token)
+          set(valid_uuid FALSE)
+          break()
+        endif()
+      else()
+        set(valid_uuid FALSE)
+        break()
+      endif()
+      math(EXPR token_num "${token_num}+1")
+    endforeach()
+  else()
+    set(valid_uuid FALSE)
+  endif()
+  message(DEBUG "UUID ${uuid_string} valid: ${valid_uuid}")
+  set(${return_value}
+      ${valid_uuid}
+      PARENT_SCOPE)
+endfunction()
+
+if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/plugin-support.c.in")
+  configure_file(src/plugin-support.c.in plugin-support.c @ONLY)
+  add_library(plugin-support STATIC)
+  target_sources(
+    plugin-support
+    PRIVATE plugin-support.c
+    PUBLIC src/plugin-support.h)
+  target_include_directories(plugin-support PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
+endif()

+ 22 - 0
cmake/common/osconfig.cmake

@@ -0,0 +1,22 @@
+# CMake operating system bootstrap module
+
+include_guard(GLOBAL)
+
+# Set minimum CMake version specific to host operating system, add OS-specific module directory to default search paths,
+# and set helper variables for OS detection in other CMake list files.
+if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+  set(CMAKE_C_EXTENSIONS FALSE)
+  set(CMAKE_CXX_EXTENSIONS FALSE)
+  list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows")
+  set(OS_WINDOWS TRUE)
+elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
+  set(CMAKE_C_EXTENSIONS FALSE)
+  set(CMAKE_CXX_EXTENSIONS FALSE)
+  list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos")
+  set(OS_MACOS TRUE)
+elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|FreeBSD|OpenBSD")
+  set(CMAKE_CXX_EXTENSIONS FALSE)
+  list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux")
+  string(TOUPPER "${CMAKE_HOST_SYSTEM_NAME}" _SYSTEM_NAME_U)
+  set(OS_${_SYSTEM_NAME_U} TRUE)
+endif()