Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ env:
SLGenerator: Visual Studio 17 2022
SLDistributeDirectory: distribute
SLFullDistributePath: "streamlabs-build.app/distribute" # The .app extension is required to run macOS tests correctly.
LibOBSVersion: 32.1.1sl12
LibOBSVersion: 32.1.1sl12cef1
PACKAGE_NAME: osn

jobs:
Expand Down
93 changes: 92 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,40 @@ if(MSVC)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/Zc:__cplusplus>)
endif()

# The supported Windows x64 CEF sandbox archive is Release-only and built with /MT.
# Apply its ABI requirements only to the obs64 link closure. In particular,
# never change the addon's runtime: it is loaded into Electron and must retain
# the dynamic CRT selected by its host.
function(osn_target_uses_static_msvc_runtime target)
if(MSVC)
set_property(TARGET ${target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
target_compile_definitions(
${target}
PRIVATE
$<$<CONFIG:Debug>:NDEBUG>
$<$<CONFIG:Debug>:_HAS_ITERATOR_DEBUGGING=0>
)
target_compile_options(${target} PRIVATE $<$<CONFIG:Debug>:/U_DEBUG>)
endif()
endfunction()

function(osn_target_uses_dynamic_msvc_runtime target)
if(MSVC)
set_property(TARGET ${target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
endif()
endfunction()

# A configure-time guard against accidentally widening the CEF CRT setting to
# Electron's native addon again.
function(osn_verify_msvc_runtime target expected_runtime)
if(MSVC)
get_property(actual_runtime TARGET ${target} PROPERTY MSVC_RUNTIME_LIBRARY)
if(NOT actual_runtime STREQUAL expected_runtime)
message(FATAL_ERROR "${target} must use ${expected_runtime}; found ${actual_runtime}")
endif()
endif()
endfunction()

# CppCheck
IF( NOT CLANG_ANALYZE_CONFIG)
include(cppcheck)
Expand Down Expand Up @@ -114,6 +148,10 @@ if (WIN32)
FetchContent_Populate(stackwalker)
add_subdirectory(${stackwalker_SOURCE_DIR} ${stackwalker_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
if(TARGET StackWalker)
osn_target_uses_static_msvc_runtime(StackWalker)
osn_verify_msvc_runtime(StackWalker "MultiThreaded")
endif()
endif()

# Nlohmann JSON (modern JSON for C++)
Expand All @@ -140,6 +178,14 @@ if(BUILD_TESTING)
set(CATCH_DEVELOPMENT_BUILD OFF CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(Catch2)
if(TARGET Catch2)
osn_target_uses_static_msvc_runtime(Catch2)
osn_verify_msvc_runtime(Catch2 "MultiThreaded")
endif()
if(TARGET Catch2WithMain)
osn_target_uses_static_msvc_runtime(Catch2WithMain)
osn_verify_msvc_runtime(Catch2WithMain "MultiThreaded")
endif()
list(APPEND CMAKE_MODULE_PATH "${catch2_SOURCE_DIR}/extras")
endif()

Expand Down Expand Up @@ -174,7 +220,52 @@ endif()
add_subdirectory(${libcurl_SOURCE_DIR} ${libcurl_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()

if(TARGET libcurl)
osn_target_uses_static_msvc_runtime(libcurl)
osn_verify_msvc_runtime(libcurl "MultiThreaded")
endif()

add_subdirectory(lib-streamlabs-ipc)

if(WIN32)
# lib-streamlabs-ipc is a shared static archive for both binaries. Clone its
# target-local build settings into a second archive so the Electron addon
# remains /MD while obs64 gets the /MT CEF-compatible objects.
get_target_property(OSN_IPC_SOURCES lib-streamlabs-ipc SOURCES)
get_target_property(OSN_IPC_INCLUDE_DIRECTORIES lib-streamlabs-ipc INCLUDE_DIRECTORIES)
get_target_property(OSN_IPC_COMPILE_DEFINITIONS lib-streamlabs-ipc COMPILE_DEFINITIONS)
get_target_property(OSN_IPC_COMPILE_OPTIONS lib-streamlabs-ipc COMPILE_OPTIONS)
get_target_property(OSN_IPC_LINK_LIBRARIES lib-streamlabs-ipc LINK_LIBRARIES)
get_target_property(OSN_IPC_SOURCE_DIRECTORY lib-streamlabs-ipc SOURCE_DIR)
get_property(
OSN_IPC_DIRECTORY_COMPILE_DEFINITIONS
DIRECTORY "${OSN_IPC_SOURCE_DIRECTORY}"
PROPERTY COMPILE_DEFINITIONS
)

add_library(lib-streamlabs-ipc-obs64 STATIC ${OSN_IPC_SOURCES})
if(OSN_IPC_INCLUDE_DIRECTORIES)
target_include_directories(lib-streamlabs-ipc-obs64 PRIVATE ${OSN_IPC_INCLUDE_DIRECTORIES})
endif()
if(OSN_IPC_COMPILE_DEFINITIONS)
target_compile_definitions(lib-streamlabs-ipc-obs64 PRIVATE ${OSN_IPC_COMPILE_DEFINITIONS})
endif()
if(OSN_IPC_DIRECTORY_COMPILE_DEFINITIONS)
target_compile_definitions(lib-streamlabs-ipc-obs64 PRIVATE ${OSN_IPC_DIRECTORY_COMPILE_DEFINITIONS})
endif()
if(OSN_IPC_COMPILE_OPTIONS)
target_compile_options(lib-streamlabs-ipc-obs64 PRIVATE ${OSN_IPC_COMPILE_OPTIONS})
endif()
if(OSN_IPC_LINK_LIBRARIES)
target_link_libraries(lib-streamlabs-ipc-obs64 PRIVATE ${OSN_IPC_LINK_LIBRARIES})
endif()

osn_target_uses_dynamic_msvc_runtime(lib-streamlabs-ipc)
osn_target_uses_static_msvc_runtime(lib-streamlabs-ipc-obs64)
osn_verify_msvc_runtime(lib-streamlabs-ipc "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
osn_verify_msvc_runtime(lib-streamlabs-ipc-obs64 "MultiThreaded")
endif()

add_subdirectory(obs-studio-client)
add_subdirectory(obs-studio-server)

Expand All @@ -188,4 +279,4 @@ install(CODE "
file(COPY \${file} DESTINATION \"${CMAKE_INSTALL_PREFIX}/bin\")
endforeach()
")
endif()
endif()
9 changes: 9 additions & 0 deletions obs-studio-client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ add_nodejs_module(
${osn-client_SOURCES}
)

# Node modules are loaded into Electron, whose dynamic CRT must remain shared
# with the addon and its normal IPC archive.
osn_target_uses_dynamic_msvc_runtime(obs_studio_client)
osn_verify_msvc_runtime(obs_studio_client "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")

if(BUILD_TESTING)
include(Catch)

Expand Down Expand Up @@ -203,6 +208,10 @@ if(BUILD_TESTING)
Catch2::Catch2WithMain
)

# Catch2 is a static test dependency of the obs64 tests, so it is /MT.
# Keep this standalone test executable compatible with that archive too.
osn_target_uses_static_msvc_runtime(obs_studio_client_unit_tests)

if(APPLE)
add_custom_command(
TARGET obs_studio_client_unit_tests
Expand Down
Binary file modified obs-studio-client/dependencies/obs_studio_client.node.txt
Binary file not shown.
70 changes: 63 additions & 7 deletions obs-studio-server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ endif()

if (WIN32)
set(PROJECT_LIBRARIES
lib-streamlabs-ipc
lib-streamlabs-ipc-obs64
OBS::libobs
dwmapi.lib
dxgi.lib
Expand All @@ -247,8 +247,6 @@ if (WIN32)
"${libobs_SOURCE_DIR}/include"
"${stackwalker_SOURCE_DIR}/Main/StackWalker"
"${nlohmannjson_SOURCE_DIR}/single_include"
"${source_dir}/include/third_party/mini_chromium/mini_chromium"
"${source_dir}/include"
)
else ()
set(PROJECT_LIBRARIES
Expand All @@ -266,6 +264,31 @@ else ()
)
endif ()

# Crashpad's prebuilt static libraries use /MD and contain Chromium base
# symbols that conflict with CEF's /MT sandbox. Keep them in a small /MD DLL
# rather than letting either the server library or obs64 link them directly.
if(WIN32)
add_library(
crashpad-bridge
SHARED
"${PROJECT_SOURCE_DIR}/source/crashpad-bridge.cpp"
"${PROJECT_SOURCE_DIR}/source/crashpad-bridge.h"
)
add_library(OSN::crashpad-bridge ALIAS crashpad-bridge)

target_link_libraries(crashpad-bridge PRIVATE crashpad shell32 ole32)
set_target_properties(
crashpad-bridge
PROPERTIES
OUTPUT_NAME "osn-crashpad-bridge"
MSVC_RUNTIME_LIBRARY "MultiThreadedDLL"
)
target_compile_definitions(crashpad-bridge PRIVATE NDEBUG _HAS_ITERATOR_DEBUGGING=0)
if(MSVC)
target_compile_options(crashpad-bridge PRIVATE /U_DEBUG)
endif()
endif()

set(PROJECT_DATA "${PROJECT_SOURCE_DIR}/resources")

SET(osn-server_SOURCES
Expand Down Expand Up @@ -438,6 +461,8 @@ elseif(WIN32)
LIST(
APPEND
osn-server_SOURCES
"${PROJECT_SOURCE_DIR}/source/cef-subprocess.cpp"
"${PROJECT_SOURCE_DIR}/source/cef-subprocess.hpp"
"${PROJECT_SOURCE_DIR}/source/osn-multitrack-video-system-info.cpp"
)
endif ()
Expand All @@ -449,6 +474,8 @@ add_library(
obs-studio-server-lib STATIC
${OSN_SERVER_CORE_SOURCES}
)
osn_target_uses_static_msvc_runtime(obs-studio-server-lib)
osn_verify_msvc_runtime(obs-studio-server-lib "MultiThreaded")

IF(WIN32)
target_compile_definitions(
Expand All @@ -464,7 +491,7 @@ ENDIF()
target_include_directories(obs-studio-server-lib PUBLIC ${PROJECT_INCLUDE_PATHS})

if(WIN32)
target_link_libraries(obs-studio-server-lib PUBLIC ${PROJECT_LIBRARIES} optimized crashpad strmiids StackWalker)
target_link_libraries(obs-studio-server-lib PUBLIC ${PROJECT_LIBRARIES} crashpad-bridge strmiids StackWalker)
else()
target_link_libraries(obs-studio-server-lib PUBLIC ${PROJECT_LIBRARIES} crashpad ${COREFOUNDATION} ${COCOA} ${IOSURF} ${GLKIT} ${AVFOUNDATION} ${IOKit} ${SECURITY_LIBRARY} ${BSM_LIBRARY})
endif()
Expand All @@ -475,12 +502,32 @@ add_executable(
${PROJECT_NAME}
"${PROJECT_SOURCE_DIR}/source/main.cpp"
)
osn_target_uses_static_msvc_runtime(${PROJECT_NAME})
osn_verify_msvc_runtime(${PROJECT_NAME} "MultiThreaded")

if(WIN32)
target_sources(${PROJECT_NAME} PUBLIC "${PROJECT_BINARY_DIR}/version.rc")
if(NOT TARGET OBS::cef-sandbox)
message(FATAL_ERROR "The libobs development package does not provide required target OBS::cef-sandbox")
endif()

target_sources(
${PROJECT_NAME}
PRIVATE
"${PROJECT_BINARY_DIR}/version.rc"
"${PROJECT_SOURCE_DIR}/source/cef-sandbox-host.cpp"
"${PROJECT_SOURCE_DIR}/source/cef-sandbox-host.hpp"
)

endif()

target_link_libraries(${PROJECT_NAME} obs-studio-server-lib)
target_link_libraries(${PROJECT_NAME} PRIVATE obs-studio-server-lib)

if(WIN32)
# The supported Windows x64 CEF sandbox archive is Release-only and built
# with /MT. Link it into obs64.exe itself, where the CEF sandbox contract
# requires cef_sandbox_info_create/destroy to reside.
target_link_libraries(${PROJECT_NAME} PRIVATE crashpad-bridge OBS::cef-sandbox)
endif()

if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS)
Expand Down Expand Up @@ -536,6 +583,7 @@ set(PROGRAM_PERMISSIONS_DEFAULT

if (WIN32)
install(TARGETS obs-studio-server RUNTIME DESTINATION "./" PERMISSIONS ${PROGRAM_PERMISSIONS_DEFAULT} COMPONENT Runtime)
install(TARGETS crashpad-bridge RUNTIME DESTINATION "./" PERMISSIONS ${PROGRAM_PERMISSIONS_DEFAULT} COMPONENT Runtime)
ELSE()
install(TARGETS obs-studio-server RUNTIME DESTINATION "./bin" PERMISSIONS ${PROGRAM_PERMISSIONS_DEFAULT} COMPONENT Runtime)
set(_COMMAND
Expand All @@ -548,6 +596,9 @@ ENDIF()

IF(WIN32 AND NOT CLANG_ANALYZE_CONFIG)
install(FILES $<TARGET_PDB_FILE:obs-studio-server> DESTINATION "./" OPTIONAL)
if(MSVC)
install(FILES $<TARGET_PDB_FILE:crashpad-bridge> DESTINATION "./" OPTIONAL)
endif()
ENDIF()
install(DIRECTORY ${PROJECT_DATA} DESTINATION "./" OPTIONAL USE_SOURCE_PERMISSIONS)
install(DIRECTORY ${crashpad_SOURCE_DIR}/bin/ DESTINATION "./" USE_SOURCE_PERMISSIONS)
Expand Down Expand Up @@ -657,6 +708,11 @@ if(BUILD_TESTING)
Catch2::Catch2WithMain
obs-studio-server-lib
)
osn_target_uses_static_msvc_runtime(obs_studio_server_unit_tests)

if(WIN32)
target_sources(obs_studio_server_unit_tests PRIVATE "tests/test-cef-subprocess.cpp")
endif()

if(APPLE)
add_custom_command(
Expand All @@ -677,7 +733,7 @@ if(BUILD_TESTING)
if(APPLE)
list(APPEND _osn_server_test_dl_paths "${libobs_SOURCE_DIR}/OBS.app/Contents/Frameworks")
elseif(WIN32)
list(APPEND _osn_server_test_dl_paths "${libobs_SOURCE_DIR}/bin/64bit")
list(APPEND _osn_server_test_dl_paths "${libobs_SOURCE_DIR}/bin/64bit" "$<TARGET_FILE_DIR:crashpad-bridge>")
endif()

catch_discover_tests(
Expand Down
Binary file modified obs-studio-server/dependencies/obs64.exe.txt
Binary file not shown.
Loading
Loading