diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d02bda..5b48fe3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ project(livekit VERSION ${LIVEKIT_VERSION} LANGUAGES C CXX) set(LIVEKIT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(LIVEKIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") option(LIVEKIT_BUILD_EXAMPLES "Build LiveKit examples" OFF) @@ -86,23 +87,39 @@ set(PROTO_BINARY_DIR ${LIVEKIT_BINARY_DIR}/generated) file(MAKE_DIRECTORY ${PROTO_BINARY_DIR}) # Try to find Protobuf via CONFIG mode first (vcpkg), then fall back to MODULE mode (apt/brew) -find_package(Protobuf CONFIG QUIET) -if(NOT Protobuf_FOUND) - find_package(Protobuf REQUIRED) +if(WIN32 AND LIVEKIT_USE_VCPKG) + # Keep existing find_package(Protobuf CONFIG) logic + find_package(Protobuf CONFIG REQUIRED) +else() + include(protobuf) # Livekit static protobuf-lite, for Linux and MacOS endif() -# Ensure protoc executable is found (some systems may not set Protobuf_PROTOC_EXECUTABLE) +# Ensure protoc executable is found (when using Livekit Protobuf, it should set Protobuf_PROTOC_EXECUTABLE already) if(NOT Protobuf_PROTOC_EXECUTABLE) find_program(Protobuf_PROTOC_EXECUTABLE NAMES protoc REQUIRED) endif() message(STATUS "Using protoc: ${Protobuf_PROTOC_EXECUTABLE}") add_library(livekit_proto OBJECT ${FFI_PROTO_FILES}) +if(TARGET protobuf::libprotobuf-lite) + set(LIVEKIT_PROTOBUF_TARGET protobuf::libprotobuf-lite) +elseif(TARGET protobuf::libprotobuf) + set(LIVEKIT_PROTOBUF_TARGET protobuf::libprotobuf) +else() + message(FATAL_ERROR "No protobuf library target found (expected protobuf::libprotobuf-lite or protobuf::libprotobuf)") +endif() target_include_directories(livekit_proto PRIVATE - "$" + "${PROTO_BINARY_DIR}" ${Protobuf_INCLUDE_DIRS} ) -target_link_libraries(livekit_proto PRIVATE protobuf::libprotobuf) +# Add Abseil headers to compile generated .pb.cc (protobuf includes absl headers) +if(TARGET absl::base) + get_target_property(_absl_inc absl::base INTERFACE_INCLUDE_DIRECTORIES) + if(_absl_inc) + target_include_directories(livekit_proto PRIVATE ${_absl_inc}) + endif() +endif() + # Manually generate protobuf files to avoid path prefix issues set(PROTO_SRCS) @@ -318,7 +335,7 @@ target_include_directories(livekit target_link_libraries(livekit PRIVATE livekit_ffi - protobuf::libprotobuf + ${LIVEKIT_PROTOBUF_TARGET} ) message(STATUS "Protobuf: version=${Protobuf_VERSION}; protoc=${Protobuf_PROTOC_EXECUTABLE}") @@ -487,35 +504,6 @@ if(APPLE) target_link_options(livekit INTERFACE "LINKER:-ObjC") endif() -if(Protobuf_VERSION VERSION_GREATER_EQUAL 6.0) - find_package(absl CONFIG QUIET) - if(NOT absl_FOUND) - find_package(Abseil QUIET) - endif() - - if(absl_FOUND) - target_link_libraries(livekit PRIVATE - absl::log - absl::check - absl::strings - absl::base - ) - elseif(Abseil_FOUND) - target_link_libraries(livekit PRIVATE - Abseil::log - Abseil::check - Abseil::strings - Abseil::base - ) - else() - message(FATAL_ERROR - "Protobuf ${Protobuf_VERSION} requires Abseil but no CMake package was found.\n" - "Install Abseil or use Protobuf < 6.") - endif() -else() - message(STATUS "Protobuf < 6 detected; skipping Abseil linking.") -endif() - if(WIN32) target_link_libraries(livekit PUBLIC ntdll @@ -587,11 +575,11 @@ write_basic_package_version_file( ) # Export targets -install(EXPORT LiveKitTargets - FILE LiveKitTargets.cmake - NAMESPACE ${LIVEKIT_EXPORT_NAMESPACE} - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${LIVEKIT_PACKAGE_NAME}" -) +#install(EXPORT LiveKitTargets +# FILE LiveKitTargets.cmake +# NAMESPACE ${LIVEKIT_EXPORT_NAMESPACE} +# DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${LIVEKIT_PACKAGE_NAME}" +#) # Install config files install(FILES diff --git a/cmake/protobuf.cmake b/cmake/protobuf.cmake new file mode 100644 index 0000000..4378cc4 --- /dev/null +++ b/cmake/protobuf.cmake @@ -0,0 +1,126 @@ +# cmake/protobuf.cmake +# +# Vendored Protobuf (static) + protobuf-lite + protoc for codegen. +# Also fetches Abseil because protobuf >= 22 commonly requires it. +# +# Exposes: +# - Protobuf_PROTOC_EXECUTABLE (generator expression: $) +# - Protobuf_INCLUDE_DIRS (best-effort; prefer target include dirs) +# - Target protobuf::libprotobuf-lite +# - Target protobuf::protoc + +include(FetchContent) + +option(LIVEKIT_USE_SYSTEM_PROTOBUF "Use system-installed Protobuf instead of vendoring" OFF) + +set(LIVEKIT_PROTOBUF_VERSION "25.3" CACHE STRING "Vendored Protobuf version") +set(LIVEKIT_ABSEIL_VERSION "20240116.2" CACHE STRING "Vendored Abseil version") + +if(LIVEKIT_USE_SYSTEM_PROTOBUF) + find_package(Protobuf CONFIG QUIET) + if(NOT Protobuf_FOUND) + find_package(Protobuf REQUIRED) + endif() + + if(NOT Protobuf_PROTOC_EXECUTABLE) + find_program(Protobuf_PROTOC_EXECUTABLE NAMES protoc REQUIRED) + endif() + message(STATUS "Using system protoc: ${Protobuf_PROTOC_EXECUTABLE}") + return() +endif() + +# ---- Abseil (needed by protobuf on many versions) ---- +# Fetch Abseil and make it available as CMake targets (absl::...) +FetchContent_Declare( + livekit_abseil + URL "https://github.com/abseil/abseil-cpp/archive/refs/tags/${LIVEKIT_ABSEIL_VERSION}.tar.gz" + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +# ---- Protobuf ---- +FetchContent_Declare( + livekit_protobuf + URL "https://github.com/protocolbuffers/protobuf/releases/download/v${LIVEKIT_PROTOBUF_VERSION}/protobuf-${LIVEKIT_PROTOBUF_VERSION}.tar.gz" + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +# Configure protobuf build: static libs, no tests/examples. +# Build static only +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + +# Disable installs/exports in subprojects (avoids export-set errors) +set(protobuf_INSTALL OFF CACHE BOOL "" FORCE) +set(ABSL_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) +set(utf8_range_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) + +set(protobuf_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(protobuf_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +set(protobuf_BUILD_CONFORMANCE OFF CACHE BOOL "" FORCE) +set(protobuf_BUILD_PROTOC_BINARIES ON CACHE BOOL "" FORCE) +set(protobuf_WITH_ZLIB OFF CACHE BOOL "" FORCE) + +set(protobuf_ABSL_PROVIDER "package" CACHE STRING "" FORCE) + +# Make abseil available first so protobuf can find absl:: targets. +FetchContent_MakeAvailable(livekit_abseil) + +# A workaround to remove the -Xarch_x86_64 / -msse4 flags that could fail the compilation. +if(APPLE AND (CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")) + foreach(t + absl_random_internal_randen_hwaes_impl + absl_random_internal_randen_hwaes + ) + if(TARGET ${t}) + foreach(prop COMPILE_OPTIONS INTERFACE_COMPILE_OPTIONS) + get_target_property(_opts ${t} ${prop}) + if(_opts) + list(FILTER _opts EXCLUDE REGEX "^-Xarch_x86_64$") + list(FILTER _opts EXCLUDE REGEX "^-msse4\\.1$") + list(FILTER _opts EXCLUDE REGEX "^-maes$") + set_target_properties(${t} PROPERTIES ${prop} "${_opts}") + endif() + endforeach() + endif() + endforeach() +endif() + + + +# Some protobuf versions look for absl via find_package(absl CONFIG). +# The abseil project usually provides targets directly, but not a config package. +# To help protobuf, ensure absl targets exist (they should after MakeAvailable). +if(NOT TARGET absl::base) + message(FATAL_ERROR "Abseil targets not found after FetchContent_MakeAvailable(livekit_abseil)") +endif() + +# Now make protobuf available. +FetchContent_MakeAvailable(livekit_protobuf) + +# Protobuf targets: modern protobuf exports protobuf::protoc etc. +if(TARGET protobuf::protoc) + set(Protobuf_PROTOC_EXECUTABLE "$" CACHE STRING "protoc (vendored)" FORCE) +elseif(TARGET protoc) + set(Protobuf_PROTOC_EXECUTABLE "$" CACHE STRING "protoc (vendored)" FORCE) +else() + message(FATAL_ERROR "Vendored protobuf did not create a protoc target") +endif() + +# Prefer protobuf-lite +if(TARGET protobuf::libprotobuf-lite) + # ok +elseif(TARGET libprotobuf-lite) + add_library(protobuf::libprotobuf-lite ALIAS libprotobuf-lite) +else() + message(FATAL_ERROR "Vendored protobuf did not create protobuf-lite target") +endif() + +# Include dirs: prefer target usage; keep this var for your existing CMakeLists. +get_target_property(_pb_includes protobuf::libprotobuf-lite INTERFACE_INCLUDE_DIRECTORIES) +if(NOT _pb_includes) + # common fallback + set(_pb_includes "${livekit_protobuf_SOURCE_DIR}/src") +endif() +set(Protobuf_INCLUDE_DIRS "${_pb_includes}" CACHE STRING "Protobuf include dirs" FORCE) + +message(STATUS "Using vendored Protobuf v${LIVEKIT_PROTOBUF_VERSION}") +message(STATUS "Using vendored protoc: ${Protobuf_PROTOC_EXECUTABLE}")