Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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.1sl12cef3
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