diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 7d0697e..27f7103 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -16,8 +16,13 @@ on: jobs: linux: - name: Linux (ubuntu-latest) - runs-on: ubuntu-latest + name: Linux (ubuntu-24.04) + # Pinned to 24.04 rather than ubuntu-latest, which this instance's two + # Linux runners answer with different releases. 24.04's libobs-dev is + # 30.0.2, exactly the OBS version buildspec.json pins for macOS/Windows, + # so all three platforms build against the same libobs. On a 22.04 runner + # libobs-dev is OBS 27, which is a different API surface entirely. + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/cmake/LiveKitSDK.cmake b/cmake/LiveKitSDK.cmake index 895fb6e..304eb1c 100644 --- a/cmake/LiveKitSDK.cmake +++ b/cmake/LiveKitSDK.cmake @@ -70,7 +70,19 @@ endfunction() function(_lk_default_triple out_triple) _lk_detect_host(_os _arch) - set(${out_triple} "${_os}-${_arch}" PARENT_SCOPE) + if(_os STREQUAL "linux") + # NOT the generic "linux-" asset, despite the name. That one is + # built on Ubuntu 24.04 and needs GLIBC_2.38 and GLIBCXX_3.4.32: linking + # it on Ubuntu 22.04 fails outright ("undefined reference to + # std::ios_base_library_init()@GLIBCXX_3.4.32", "__isoc23_strtol@GLIBC_2.38"), + # which is exactly what happened when CI landed on a 22.04 runner. + # The ubuntu-22.04 asset needs at most GLIBC_2.35 / GLIBCXX_3.4.30, so it + # links and runs on 22.04 AND on everything newer -- the right floor for a + # plugin that gets handed to directors as a binary. + set(${out_triple} "ubuntu-22.04-${_arch}" PARENT_SCOPE) + else() + set(${out_triple} "${_os}-${_arch}" PARENT_SCOPE) + endif() endfunction() function(_lk_archive_ext out_ext) diff --git a/cmake/common/buildspec_common.cmake b/cmake/common/buildspec_common.cmake index 72f9cab..cea80de 100644 --- a/cmake/common/buildspec_common.cmake +++ b/cmake/common/buildspec_common.cmake @@ -15,6 +15,11 @@ # 3. Only the Release configuration is built and installed. Upstream builds # Debug as well; nothing here consumes a debug libobs, and it doubles the # slowest step in CI. +# 4. macOS uses the Ninja generator and a single architecture, not upstream's +# Xcode generator and forced universal build. See the comment at that +# branch: a runner with only the Command Line Tools has no xcodebuild. +# 5. Generator flags are built as CMake lists so each becomes its own argv +# entry, rather than upstream's space-separated strings passed unquoted. # include_guard(GLOBAL) @@ -69,24 +74,50 @@ function(_setup_obs_studio) set(_is_fresh --fresh) endif() + # Every generator-specific flag is built as a proper CMake list, so each + # element becomes its own argv entry. Upstream packs several flags into one + # space-separated string and passes it unquoted, which execute_process hands + # to cmake as a single argument -- it happens not to matter there because + # those flags are optional, but -DCMAKE_BUILD_TYPE is not. + set(_cmake_arch "") + set(_cmake_extra "") + if(OS_WINDOWS) set(_cmake_generator "${CMAKE_GENERATOR}") - set(_cmake_arch "-A ${arch},version=${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") - set(_cmake_extra "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}") + if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) + list(APPEND _cmake_arch -A "${arch},version=${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") + else() + list(APPEND _cmake_arch -A "${arch}") + endif() + list(APPEND _cmake_extra "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}") 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}") + # Ninja, not upstream's Xcode generator. A runner with only the Command + # Line Tools installed has no xcodebuild, and the Xcode generator then + # fails the OBS sub-configure outright with "No CMAKE_C_COMPILER could be + # found" -- observed on the `home-mac` CI runner. Ninja is single-config, + # hence the explicit CMAKE_BUILD_TYPE below. + set(_cmake_generator "Ninja") + # Single-architecture, not upstream's forced universal build: this plugin + # is built for one architecture anyway (client-sdk-cpp ships single-arch + # dylibs), so building libobs universal would double the slowest step in + # CI for a slice nothing links against. + if(CMAKE_OSX_ARCHITECTURES) + list(APPEND _cmake_arch "-DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}") + endif() + list(APPEND _cmake_extra "-DCMAKE_BUILD_TYPE=Release") + if(CMAKE_OSX_DEPLOYMENT_TARGET) + list(APPEND _cmake_extra "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}") + endif() 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}" + "${dependencies_dir}/${_obs_destination}/build_${arch}" -G ${_cmake_generator} ${_cmake_arch} -DOBS_CMAKE_VERSION:STRING=3.0.0 -DENABLE_PLUGINS:BOOL=OFF -DENABLE_FRONTEND:BOOL=OFF -DENABLE_UI:BOOL=OFF -DENABLE_SCRIPTING:BOOL=OFF -DENABLE_BROWSER:BOOL=OFF - -DOBS_VERSION_OVERRIDE:STRING=${_obs_version} "-DCMAKE_PREFIX_PATH='${CMAKE_PREFIX_PATH}'" ${_is_fresh} + -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 diff --git a/obs-adapter/src/plugin-main.cpp b/obs-adapter/src/plugin-main.cpp index c55b6be..3bdc14d 100644 --- a/obs-adapter/src/plugin-main.cpp +++ b/obs-adapter/src/plugin-main.cpp @@ -165,8 +165,15 @@ void outputVideoFrame(CameraSource *self, const VideoFrameData &frame) } // WebRTC delivers limited-range BT.709 for anything at or above SD. - video_format_get_parameters_for_format(VIDEO_CS_709, VIDEO_RANGE_PARTIAL, out.format, out.color_matrix, - out.color_range_min, out.color_range_max); + // + // The plain video_format_get_parameters, not the _for_format variant: + // the latter only exists from libobs 30 onwards, and it only differs for + // the 10-bit formats (I010/P010) this source never receives. Using the + // older entry point keeps the module loadable on an older OBS, which is + // the direction that matters -- OBS refuses modules built against a + // NEWER libobs than the one running. + video_format_get_parameters(VIDEO_CS_709, VIDEO_RANGE_PARTIAL, out.color_matrix, out.color_range_min, + out.color_range_max); out.full_range = false; obs_source_output_video(self->source, &out);