Skip to content

Commit fc75e09

Browse files
committed
GH-48555: [C++] Use FetchContent for bundled opentelemetry
1 parent 8fcab2f commit fc75e09

File tree

1 file changed

+73
-196
lines changed

1 file changed

+73
-196
lines changed

cpp/cmake_modules/ThirdpartyToolchain.cmake

Lines changed: 73 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,6 +1883,7 @@ function(build_protobuf)
18831883
PARENT_SCOPE)
18841884

18851885
fetchcontent_declare(protobuf
1886+
${FC_DECLARE_COMMON_OPTIONS} OVERRIDE_FIND_PACKAGE
18861887
URL ${PROTOBUF_SOURCE_URL}
18871888
URL_HASH "SHA256=${ARROW_PROTOBUF_BUILD_SHA256_CHECKSUM}"
18881889
SOURCE_SUBDIR cmake)
@@ -3726,220 +3727,96 @@ endif()
37263727
# ----------------------------------------------------------------------
37273728
# OpenTelemetry C++
37283729

3729-
macro(build_opentelemetry)
3730-
message(STATUS "Building OpenTelemetry from source")
3730+
function(build_opentelemetry)
3731+
list(APPEND CMAKE_MESSAGE_INDENT "OpenTelemetry: ")
3732+
message(STATUS "Building OpenTelemetry from source using FetchContent")
3733+
37313734
if(Protobuf_VERSION VERSION_GREATER_EQUAL 3.22)
37323735
message(FATAL_ERROR "GH-36013: Can't use bundled OpenTelemetry with Protobuf 3.22 or later. "
37333736
"Protobuf is version ${Protobuf_VERSION}")
37343737
endif()
37353738

3736-
set(OPENTELEMETRY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/opentelemetry_ep-install")
3737-
set(OPENTELEMETRY_INCLUDE_DIR "${OPENTELEMETRY_PREFIX}/include")
3738-
set(OPENTELEMETRY_STATIC_LIB
3739-
"${OPENTELEMETRY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry${CMAKE_STATIC_LIBRARY_SUFFIX}"
3739+
set(OPENTELEMETRY_VENDORED
3740+
TRUE
3741+
PARENT_SCOPE)
3742+
3743+
fetchcontent_declare(opentelemetry_proto
3744+
${FC_DECLARE_COMMON_OPTIONS}
3745+
URL ${OPENTELEMETRY_PROTO_SOURCE_URL}
3746+
URL_HASH "SHA256=${ARROW_OPENTELEMETRY_PROTO_BUILD_SHA256_CHECKSUM}"
37403747
)
3741-
set(_OPENTELEMETRY_APIS api ext sdk)
3742-
set(_OPENTELEMETRY_LIBS
3743-
common
3744-
http_client_curl
3745-
logs
3746-
ostream_log_record_exporter
3747-
ostream_span_exporter
3748-
otlp_http_client
3749-
otlp_http_log_record_exporter
3750-
otlp_http_exporter
3751-
otlp_recordable
3752-
proto
3753-
resources
3754-
trace
3755-
version)
3756-
set(OPENTELEMETRY_BUILD_BYPRODUCTS)
3757-
set(OPENTELEMETRY_LIBRARIES)
3758-
3759-
foreach(_OPENTELEMETRY_LIB ${_OPENTELEMETRY_APIS})
3760-
add_library(opentelemetry-cpp::${_OPENTELEMETRY_LIB} INTERFACE IMPORTED)
3761-
target_include_directories(opentelemetry-cpp::${_OPENTELEMETRY_LIB} BEFORE
3762-
INTERFACE "${OPENTELEMETRY_INCLUDE_DIR}")
3763-
endforeach()
3764-
foreach(_OPENTELEMETRY_LIB ${_OPENTELEMETRY_LIBS})
3765-
# N.B. OTel targets and libraries don't follow any consistent naming scheme
3766-
if(_OPENTELEMETRY_LIB STREQUAL "http_client_curl")
3767-
set(_OPENTELEMETRY_STATIC_LIBRARY
3768-
"${OPENTELEMETRY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_${_OPENTELEMETRY_LIB}${CMAKE_STATIC_LIBRARY_SUFFIX}"
3769-
)
3770-
elseif(_OPENTELEMETRY_LIB STREQUAL "ostream_span_exporter")
3771-
set(_OPENTELEMETRY_STATIC_LIBRARY
3772-
"${OPENTELEMETRY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_ostream_span${CMAKE_STATIC_LIBRARY_SUFFIX}"
3773-
)
3774-
elseif(_OPENTELEMETRY_LIB STREQUAL "otlp_http_client")
3775-
set(_OPENTELEMETRY_STATIC_LIBRARY
3776-
"${OPENTELEMETRY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_http_client${CMAKE_STATIC_LIBRARY_SUFFIX}"
3777-
)
3778-
elseif(_OPENTELEMETRY_LIB STREQUAL "otlp_http_exporter")
3779-
set(_OPENTELEMETRY_STATIC_LIBRARY
3780-
"${OPENTELEMETRY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_http${CMAKE_STATIC_LIBRARY_SUFFIX}"
3781-
)
3782-
elseif(_OPENTELEMETRY_LIB STREQUAL "otlp_http_log_record_exporter")
3783-
set(_OPENTELEMETRY_STATIC_LIBRARY
3784-
"${OPENTELEMETRY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_otlp_http_log${CMAKE_STATIC_LIBRARY_SUFFIX}"
3785-
)
3786-
elseif(_OPENTELEMETRY_LIB STREQUAL "ostream_log_record_exporter")
3787-
set(_OPENTELEMETRY_STATIC_LIBRARY
3788-
"${OPENTELEMETRY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_exporter_ostream_logs${CMAKE_STATIC_LIBRARY_SUFFIX}"
3789-
)
3790-
else()
3791-
set(_OPENTELEMETRY_STATIC_LIBRARY
3792-
"${OPENTELEMETRY_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}opentelemetry_${_OPENTELEMETRY_LIB}${CMAKE_STATIC_LIBRARY_SUFFIX}"
3793-
)
3794-
endif()
3795-
add_library(opentelemetry-cpp::${_OPENTELEMETRY_LIB} STATIC IMPORTED)
3796-
set_target_properties(opentelemetry-cpp::${_OPENTELEMETRY_LIB}
3797-
PROPERTIES IMPORTED_LOCATION ${_OPENTELEMETRY_STATIC_LIBRARY})
3798-
list(APPEND OPENTELEMETRY_BUILD_BYPRODUCTS ${_OPENTELEMETRY_STATIC_LIBRARY})
3799-
list(APPEND OPENTELEMETRY_LIBRARIES opentelemetry-cpp::${_OPENTELEMETRY_LIB})
3800-
endforeach()
38013748

3802-
set(OPENTELEMETRY_CMAKE_ARGS
3803-
${EP_COMMON_CMAKE_ARGS} "-DCMAKE_INSTALL_PREFIX=${OPENTELEMETRY_PREFIX}"
3804-
-DWITH_EXAMPLES=OFF)
3749+
# Use FetchContent_Populate instead of MakeAvailable because opentelemetry-proto
3750+
# has no CMakeLists.txt.
3751+
cmake_policy(PUSH)
3752+
if(POLICY CMP0169)
3753+
cmake_policy(SET CMP0169 OLD)
3754+
endif()
3755+
fetchcontent_populate(opentelemetry_proto)
3756+
cmake_policy(POP)
38053757

3806-
set(OPENTELEMETRY_PREFIX_PATH_LIST)
3807-
# Don't specify the DEPENDS unless we actually have dependencies, else
3808-
# Ninja/other build systems may consider this target to always be dirty
3809-
set(_OPENTELEMETRY_DEPENDENCIES)
3810-
add_custom_target(opentelemetry_dependencies)
3758+
fetchcontent_declare(opentelemetry_cpp
3759+
${FC_DECLARE_COMMON_OPTIONS}
3760+
URL ${OPENTELEMETRY_SOURCE_URL}
3761+
URL_HASH "SHA256=${ARROW_OPENTELEMETRY_BUILD_SHA256_CHECKSUM}")
38113762

3812-
set(_OPENTELEMETRY_DEPENDENCIES "opentelemetry_dependencies")
3813-
list(APPEND ARROW_BUNDLED_STATIC_LIBS ${OPENTELEMETRY_LIBRARIES})
3814-
list(APPEND OPENTELEMETRY_PREFIX_PATH_LIST ${NLOHMANN_JSON_PREFIX})
3763+
prepare_fetchcontent()
38153764

3816-
get_target_property(OPENTELEMETRY_PROTOBUF_INCLUDE_DIR ${ARROW_PROTOBUF_LIBPROTOBUF}
3817-
INTERFACE_INCLUDE_DIRECTORIES)
3818-
set(OPENTELEMETRY_PROTOBUF_LIBRARY "$<TARGET_FILE:${ARROW_PROTOBUF_LIBPROTOBUF}>")
3819-
set(OPENTELEMETRY_PROTOC_EXECUTABLE "$<TARGET_FILE:${ARROW_PROTOBUF_PROTOC}>")
3820-
list(APPEND
3821-
OPENTELEMETRY_CMAKE_ARGS
3822-
-DWITH_OTLP_HTTP=ON
3823-
-DWITH_OTLP_GRPC=OFF
3824-
# Disabled because it seemed to cause linking errors. May be worth a closer look.
3825-
-DWITH_FUNC_TESTS=OFF
3826-
# These options are slated for removal in v1.14 and their features are deemed stable
3827-
# as of v1.13. However, setting their corresponding ENABLE_* macros in headers seems
3828-
# finicky - resulting in build failures or ABI-related runtime errors during HTTP
3829-
# client initialization. There may still be a solution, but we disable them for now.
3830-
-DWITH_OTLP_HTTP_SSL_PREVIEW=OFF
3831-
-DWITH_OTLP_HTTP_SSL_TLS_PREVIEW=OFF
3832-
"-DProtobuf_INCLUDE_DIR=${OPENTELEMETRY_PROTOBUF_INCLUDE_DIR}"
3833-
"-DProtobuf_LIBRARY=${OPENTELEMETRY_PROTOBUF_LIBRARY}"
3834-
"-DProtobuf_PROTOC_EXECUTABLE=${OPENTELEMETRY_PROTOC_EXECUTABLE}")
3835-
3836-
# OpenTelemetry with OTLP enabled requires Protobuf definitions from a
3837-
# submodule. This submodule path is hardcoded into their CMake definitions,
3838-
# and submodules are not included in their releases. Add a custom build step
3839-
# to download and extract the Protobufs.
3840-
3841-
# Adding such a step is rather complicated, so instead: create a separate
3842-
# ExternalProject that just fetches the Protobufs, then add a custom step
3843-
# to the main build to copy the Protobufs.
3844-
externalproject_add(opentelemetry_proto_ep
3845-
${EP_COMMON_OPTIONS}
3846-
URL_HASH "SHA256=${ARROW_OPENTELEMETRY_PROTO_BUILD_SHA256_CHECKSUM}"
3847-
URL ${OPENTELEMETRY_PROTO_SOURCE_URL}
3848-
BUILD_COMMAND ""
3849-
CONFIGURE_COMMAND ""
3850-
INSTALL_COMMAND ""
3851-
EXCLUDE_FROM_ALL OFF)
3765+
set(OTELCPP_PROTO_PATH "${opentelemetry_proto_SOURCE_DIR}")
3766+
set(WITH_EXAMPLES OFF)
3767+
set(WITH_OTLP_HTTP ON)
3768+
set(WITH_OTLP_GRPC OFF)
3769+
set(WITH_FUNC_TESTS OFF)
3770+
# These options are slated for removal in v1.14 and their features are deemed stable
3771+
# as of v1.13. However, setting their corresponding ENABLE_* macros in headers seems
3772+
# finicky - resulting in build failures or ABI-related runtime errors during HTTP
3773+
# client initialization. There may still be a solution, but we disable them for now.
3774+
set(WITH_OTLP_HTTP_SSL_PREVIEW OFF)
3775+
set(WITH_OTLP_HTTP_SSL_TLS_PREVIEW OFF)
3776+
3777+
# Configure nlohmann_json prefix path for OpenTelemetry to find it
38523778
if(NLOHMANN_JSON_VENDORED)
3853-
add_dependencies(opentelemetry_dependencies nlohmann_json_fc)
3854-
else()
3855-
add_dependencies(opentelemetry_dependencies nlohmann_json::nlohmann_json)
3779+
list(APPEND CMAKE_PREFIX_PATH "${NLOHMANN_JSON_PREFIX}")
38563780
endif()
38573781

3858-
add_dependencies(opentelemetry_dependencies opentelemetry_proto_ep
3859-
${ARROW_PROTOBUF_LIBPROTOBUF})
3782+
# Unity build causes some build errors
3783+
# TODO: Validate on CI whether enabling unity build works fine
3784+
# set(CMAKE_UNITY_BUILD OFF)
38603785

3861-
# Ensure vendored protobuf is installed before OpenTelemetry builds
3862-
if(PROTOBUF_VENDORED)
3863-
add_dependencies(opentelemetry_dependencies protobuf_fc)
3786+
fetchcontent_makeavailable(opentelemetry_cpp)
3787+
3788+
if(CMAKE_VERSION VERSION_LESS 3.28)
3789+
set_property(DIRECTORY ${opentelemetry_cpp_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL TRUE)
38643790
endif()
38653791

3866-
string(JOIN "${EP_LIST_SEPARATOR}" OPENTELEMETRY_PREFIX_PATH
3867-
${OPENTELEMETRY_PREFIX_PATH_LIST})
3868-
list(APPEND OPENTELEMETRY_CMAKE_ARGS "-DCMAKE_PREFIX_PATH=${OPENTELEMETRY_PREFIX_PATH}")
3792+
# Remove unused directories to save build directory storage
3793+
file(REMOVE_RECURSE "${opentelemetry_cpp_SOURCE_DIR}/ci")
38693794

3870-
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "s390x")
3871-
# OpenTelemetry tries to determine the processor arch for vcpkg, which fails
3872-
# on s390x, even though it doesn't use vcpkg there. Tell it ARCH manually
3873-
externalproject_add(opentelemetry_ep
3874-
${EP_COMMON_OPTIONS}
3875-
URL_HASH "SHA256=${ARROW_OPENTELEMETRY_BUILD_SHA256_CHECKSUM}"
3876-
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env ARCH=s390x
3877-
${CMAKE_COMMAND} -G ${CMAKE_GENERATOR}
3878-
"<SOURCE_DIR><SOURCE_SUBDIR>"
3879-
${OPENTELEMETRY_CMAKE_ARGS}
3880-
BUILD_COMMAND ${CMAKE_COMMAND} --build "<BINARY_DIR>" --target all
3881-
INSTALL_COMMAND ${CMAKE_COMMAND} --build "<BINARY_DIR>" --target
3882-
install
3883-
URL ${OPENTELEMETRY_SOURCE_URL}
3884-
BUILD_BYPRODUCTS ${OPENTELEMETRY_BUILD_BYPRODUCTS}
3885-
EXCLUDE_FROM_ALL NOT
3886-
${ARROW_WITH_OPENTELEMETRY}
3887-
DEPENDS ${_OPENTELEMETRY_DEPENDENCIES})
3888-
else()
3889-
externalproject_add(opentelemetry_ep
3890-
${EP_COMMON_OPTIONS}
3891-
URL_HASH "SHA256=${ARROW_OPENTELEMETRY_BUILD_SHA256_CHECKSUM}"
3892-
CMAKE_ARGS ${OPENTELEMETRY_CMAKE_ARGS}
3893-
URL ${OPENTELEMETRY_SOURCE_URL}
3894-
BUILD_BYPRODUCTS ${OPENTELEMETRY_BUILD_BYPRODUCTS}
3895-
EXCLUDE_FROM_ALL NOT
3896-
${ARROW_WITH_OPENTELEMETRY}
3897-
DEPENDS ${_OPENTELEMETRY_DEPENDENCIES})
3898-
endif()
3899-
3900-
externalproject_add_step(opentelemetry_ep download_proto
3901-
COMMAND ${CMAKE_COMMAND} -E copy_directory
3902-
$<TARGET_PROPERTY:opentelemetry_proto_ep,_EP_SOURCE_DIR>/opentelemetry
3903-
$<TARGET_PROPERTY:opentelemetry_ep,_EP_SOURCE_DIR>/third_party/opentelemetry-proto/opentelemetry
3904-
DEPENDEES download
3905-
DEPENDERS configure)
3906-
3907-
set(OPENTELEMETRY_VENDORED 1)
3908-
3909-
target_link_libraries(opentelemetry-cpp::common
3910-
INTERFACE opentelemetry-cpp::api opentelemetry-cpp::sdk
3911-
Threads::Threads)
3912-
target_link_libraries(opentelemetry-cpp::resources INTERFACE opentelemetry-cpp::common)
3913-
target_link_libraries(opentelemetry-cpp::trace INTERFACE opentelemetry-cpp::common
3914-
opentelemetry-cpp::resources)
3915-
target_link_libraries(opentelemetry-cpp::logs INTERFACE opentelemetry-cpp::common
3916-
opentelemetry-cpp::resources)
3917-
target_link_libraries(opentelemetry-cpp::http_client_curl
3918-
INTERFACE opentelemetry-cpp::common opentelemetry-cpp::ext
3919-
CURL::libcurl)
3920-
target_link_libraries(opentelemetry-cpp::proto INTERFACE ${ARROW_PROTOBUF_LIBPROTOBUF})
3921-
target_link_libraries(opentelemetry-cpp::otlp_recordable
3922-
INTERFACE opentelemetry-cpp::logs opentelemetry-cpp::trace
3923-
opentelemetry-cpp::resources opentelemetry-cpp::proto)
3924-
target_link_libraries(opentelemetry-cpp::otlp_http_client
3925-
INTERFACE opentelemetry-cpp::common opentelemetry-cpp::proto
3926-
opentelemetry-cpp::http_client_curl
3927-
nlohmann_json::nlohmann_json)
3928-
target_link_libraries(opentelemetry-cpp::otlp_http_exporter
3929-
INTERFACE opentelemetry-cpp::otlp_recordable
3930-
opentelemetry-cpp::otlp_http_client)
3931-
target_link_libraries(opentelemetry-cpp::otlp_http_log_record_exporter
3932-
INTERFACE opentelemetry-cpp::otlp_recordable
3933-
opentelemetry-cpp::otlp_http_client)
3934-
3935-
foreach(_OPENTELEMETRY_LIB ${_OPENTELEMETRY_LIBS})
3936-
add_dependencies(opentelemetry-cpp::${_OPENTELEMETRY_LIB} opentelemetry_ep)
3937-
list(APPEND ARROW_BUNDLED_STATIC_LIBS opentelemetry-cpp::${_OPENTELEMETRY_LIB})
3938-
endforeach()
3795+
# OpenTelemetry creates its own targets. We need to add them to bundled static libs.
3796+
# The targets created by OpenTelemetry's CMakeLists.txt use the opentelemetry:: namespace.
3797+
# List of libraries that we actually need and want to bundle.
3798+
set(_OPENTELEMETRY_BUNDLED_LIBS
3799+
opentelemetry-cpp::common
3800+
opentelemetry-cpp::http_client_curl
3801+
opentelemetry-cpp::logs
3802+
opentelemetry-cpp::ostream_log_record_exporter
3803+
opentelemetry-cpp::ostream_span_exporter
3804+
opentelemetry-cpp::otlp_http_client
3805+
opentelemetry-cpp::otlp_http_log_record_exporter
3806+
opentelemetry-cpp::otlp_http_exporter
3807+
opentelemetry-cpp::otlp_recordable
3808+
opentelemetry-cpp::proto
3809+
opentelemetry-cpp::resources
3810+
opentelemetry-cpp::trace
3811+
opentelemetry-cpp::version)
39393812

3940-
# Work around https://gitlab.kitware.com/cmake/cmake/issues/15052
3941-
file(MAKE_DIRECTORY ${OPENTELEMETRY_INCLUDE_DIR})
3942-
endmacro()
3813+
list(APPEND ARROW_BUNDLED_STATIC_LIBS ${_OPENTELEMETRY_BUNDLED_LIBS})
3814+
set(ARROW_BUNDLED_STATIC_LIBS
3815+
"${ARROW_BUNDLED_STATIC_LIBS}"
3816+
PARENT_SCOPE)
3817+
3818+
list(POP_BACK CMAKE_MESSAGE_INDENT)
3819+
endfunction()
39433820

39443821
if(ARROW_WITH_OPENTELEMETRY)
39453822
if(NOT ARROW_ENABLE_THREADING)

0 commit comments

Comments
 (0)