diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 3f2b50e..d07c346 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -100,10 +100,25 @@ jobs: run: ctest --test-dir build --output-on-failure - name: Show what was built + # This used to be informational only (every command "|| true"'d), so + # a bootstrap failure that silently fell back to a core-library-only + # build still reported a green job -- exactly the false-positive + # class of bug this step exists to catch, caught instead by a human + # reading the raw log by hand. The macOS bootstrap has been reliably + # building the real module in CI (6/6 tests, artifact uploaded -- + # see README), so a missing module here is a regression to fail + # loudly on, not the old silent fallback. (This is separate from the + # macOS packaging gap in README -- that the module doesn't yet load + # as an OBS.app bundle -- which this check does not and cannot test.) run: | ls -la .deps/Frameworks/libobs.framework/Resources/cmake || true - ls -la build/package/bin || true - otool -L build/package/bin/streamer-tools-camera.so || true + if [ ! -f build/package/bin/streamer-tools-camera.so ]; then + echo "::error::no plugin module was built -- build/package/bin/streamer-tools-camera.so is missing. The macOS from-source libobs bootstrap is expected to succeed; treat this as a build failure, not a core-library-only fallback." + exit 1 + fi + ls -la build/package/bin + otool -L build/package/bin/streamer-tools-camera.so + otool -L build/package/bin/streamer-tools-camera.so | grep -E 'obs|livekit' - name: Upload plugin continue-on-error: true @@ -150,11 +165,25 @@ jobs: run: ctest --test-dir build -C Release --output-on-failure - name: Show what was built + # This used to be informational only: the else branch printed a + # message and exited 0, so a bootstrap failure that silently fell + # back to a core-library-only build (or a find_package(libobs) + # failure after a libobs that genuinely built, per the + # find_package(libobs) CMakeLists.txt fix above) still reported a + # green job -- exactly the false-positive class of bug this step + # exists to catch, caught instead by a human reading the raw log by + # hand across several "green" runs. The from-source libobs bootstrap + # is now expected to work reliably on this runner (that is the whole + # point of the buildspec bootstrap + find_package fix), so a missing + # module here is a regression to fail loudly on, not the old silent + # fallback. run: | - if (Test-Path build\package\bin\64bit) { + $module = "build\package\bin\64bit\streamer-tools-camera.dll" + if (Test-Path $module) { Get-ChildItem build\package\bin\64bit } else { - Write-Host "no plugin module was built (core library only)" + Write-Host "::error::no plugin module was built -- $module is missing. The Windows from-source libobs bootstrap is expected to succeed; treat this as a build failure, not a core-library-only fallback." + exit 1 } - name: Upload plugin diff --git a/CMakeLists.txt b/CMakeLists.txt index c125aa6..8754bd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,54 @@ find_package(LiveKit CONFIG REQUIRED) add_subdirectory(core) +# On Windows, OBS's own modern-CMake install layout +# (obs-studio/cmake/windows/defaults.cmake: OBS_CMAKE_DESTINATION=cmake) +# installs libobs's CMake package config to /cmake// -- +# a shape find_package( CONFIG) never searches under CMAKE_PREFIX_PATH. +# CMake's documented Config-mode search suffixes include +# "/(cmake|CMake)/" (the file directly inside that dir, no +# subdirectory) and "/*/(cmake|CMake)/[...]" (a -prefixed +# directory first) -- neither matches "/cmake/*/". Verified +# empirically: a find_package(libobs CONFIG) run with CMAKE_PREFIX_PATH +# pointed at a directory laid out exactly like this (cmake/libobs/ +# libobsConfig.cmake underneath it) never even tries that path, confirmed +# with --debug-find-pkg=libobs. +# +# macOS does not have this problem -- its OBS_CMAKE_DESTINATION is +# "lib/cmake", so the package lands at /lib/cmake/libobs/, which +# matches the standard "/lib*/cmake/*/" suffix -- and neither +# does Linux's libobs-dev, which installs to +# /usr/lib//cmake/libobs/, the same standard suffix. Windows is +# the one platform whose own upstream install destination CMake's +# find_package was never going to locate on its own; this is not caused by, +# and is not fixed by, the earlier "file INSTALL cannot find +# obs-frontend-api.dll" error tolerated in +# cmake/common/buildspec_common.cmake's _setup_obs_studio -- libobs is the +# FIRST subdirectory obs-studio's modern top-level CMakeLists.txt adds +# (before libobs-d3d11/-winrt/-opengl, plugins, test/test-input and finally +# UI), so libobs's own install(EXPORT ...) rules, including this Config file, +# already ran to completion by the time cmake --install later aborts inside +# UI/obs-frontend-api's install script. +# +# So: point find_package(libobs) directly at the from-source Windows install +# rather than relying on path-search heuristics that were never going to find +# it. Guarded by "NOT libobs_DIR" so an explicit -Dlibobs_DIR=... from a +# developer with their own OBS SDK is never overridden, and by EXISTS so this +# is a no-op whenever STPLUGIN_BOOTSTRAP_OBS=OFF or the bootstrap didn't +# reach this point. +if(OS_WINDOWS AND NOT libobs_DIR) + set(_stplugin_win_libobs_dir "${CMAKE_CURRENT_SOURCE_DIR}/.deps/cmake/libobs") + if(EXISTS "${_stplugin_win_libobs_dir}/libobsConfig.cmake") + set(libobs_DIR "${_stplugin_win_libobs_dir}" CACHE PATH + "Directory containing libobsConfig.cmake" FORCE) + message(STATUS + "libobs_DIR not set; OBS's Windows OBS_CMAKE_DESTINATION=cmake " + "does not match any of CMake's standard find_package Config-mode " + "search suffixes, so pointing it directly at the from-source " + "install: ${_stplugin_win_libobs_dir}") + endif() +endif() + find_package(libobs QUIET) # The imported OBS::libobs target can come back without a location. OBS 30.0.2 @@ -176,8 +224,15 @@ if(libobs_FOUND AND TARGET OBS::libobs) message(STATUS "OBS::libobs had no imported location; pointed it at ${_stplugin_obs_binary}") endif() elseif(WIN32) + # obs-studio/cmake/windows/defaults.cmake sets + # OBS_EXECUTABLE_DESTINATION=bin/64bit (the RUNTIME destination + # obs.dll installs to as a SHARED_LIBRARY target) and + # OBS_LIBRARY_DESTINATION=lib (the ARCHIVE destination for + # obs.lib) -- not a flat "bin", which is what upstream + # obs-plugintemplate's own equivalent macOS-only repair never had + # to get right. find_file(_stplugin_obs_implib_found obs.lib PATHS "${_stplugin_deps}/lib" NO_DEFAULT_PATH) - find_file(_stplugin_obs_dll_found obs.dll PATHS "${_stplugin_deps}/bin" NO_DEFAULT_PATH) + find_file(_stplugin_obs_dll_found obs.dll PATHS "${_stplugin_deps}/bin/64bit" NO_DEFAULT_PATH) if(_stplugin_obs_implib_found) set_target_properties(OBS::libobs PROPERTIES IMPORTED_IMPLIB "${_stplugin_obs_implib_found}") if(_stplugin_obs_dll_found)