Skip to content
Open
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
70 changes: 29 additions & 41 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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
"$<BUILD_INTERFACE:${PROTO_BINARY_DIR}>"
"${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)
Expand Down Expand Up @@ -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}")
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
126 changes: 126 additions & 0 deletions cmake/protobuf.cmake
Original file line number Diff line number Diff line change
@@ -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: $<TARGET_FILE:protobuf::protoc>)
# - 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 "$<TARGET_FILE:protobuf::protoc>" CACHE STRING "protoc (vendored)" FORCE)
elseif(TARGET protoc)
set(Protobuf_PROTOC_EXECUTABLE "$<TARGET_FILE:protoc>" 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}")
Loading