opentelemetry-cpp/CMakeLists.txt

467 lines
15 KiB
CMake
Executable File

cmake_minimum_required(VERSION 3.1)
# See https://cmake.org/cmake/help/v3.3/policy/CMP0057.html required by certain
# versions of gtest
cmake_policy(SET CMP0057 NEW)
# See https://cmake.org/cmake/help/v3.12/policy/CMP0074.html required by certain
# version of zlib which is dependeded by cURL.
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12")
cmake_policy(SET CMP0074 NEW)
endif()
project(opentelemetry-cpp)
# Mark variables as used so cmake doesn't complain about them
mark_as_advanced(CMAKE_TOOLCHAIN_FILE)
# Don't use customized cmake modules if vcpkg is used to resolve dependence.
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/")
endif()
if(EXISTS "${CMAKE_SOURCE_DIR}/third_party_release")
file(STRINGS "${CMAKE_SOURCE_DIR}/third_party_release" third_party_tags)
foreach(third_party ${third_party_tags})
string(REGEX REPLACE "^[ ]+" "" third_party ${third_party})
string(REGEX MATCH "^[^=]+" third_party_name ${third_party})
string(REPLACE "${third_party_name}=" "" third_party_tag ${third_party})
set(${third_party_name} "${third_party_tag}")
endforeach()
endif()
if(DEFINED ENV{ARCH})
# Architecture may be specified via ARCH environment variable
set(ARCH $ENV{ARCH})
else()
# Autodetection logic that populates ARCH variable
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
# Windows may report AMD64 even if target is 32-bit
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ARCH x64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ARCH x86)
endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*")
# Windows may report x86 even if target is 64-bit
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ARCH x64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ARCH x86)
endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES
"^(aarch64.*|AARCH64.*|arm64.*|ARM64.*)")
set(ARCH arm64)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)")
set(ARCH arm)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
set(ARCH ppc64le)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64")
set(ARCH ppc64)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(mips.*|MIPS.*)")
set(ARCH mips)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv.*|RISCV.*)")
set(ARCH riscv)
else()
message(
FATAL_ERROR
"opentelemetry-cpp: unrecognized target processor configuration!")
endif()
endif()
message(STATUS "Building for architecture ARCH=${ARCH}")
# Autodetect vcpkg toolchain
if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE
"$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "")
endif()
if(VCPKG_CHAINLOAD_TOOLCHAIN_FILE)
include("${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}")
endif()
file(READ "${CMAKE_CURRENT_LIST_DIR}/api/include/opentelemetry/version.h"
OPENTELEMETRY_CPP_HEADER_VERSION_H)
if(OPENTELEMETRY_CPP_HEADER_VERSION_H MATCHES
"OPENTELEMETRY_ABI_VERSION_NO[ \t\r\n]+\"?([0-9]+)\"?")
math(EXPR OPENTELEMETRY_ABI_VERSION_NO ${CMAKE_MATCH_1})
else()
message(
FATAL_ERROR
"OPENTELEMETRY_ABI_VERSION_NO not found on ${CMAKE_CURRENT_LIST_DIR}/api/include/opentelemetry/version.h"
)
endif()
if(OPENTELEMETRY_CPP_HEADER_VERSION_H MATCHES
"OPENTELEMETRY_VERSION[ \t\r\n]+\"?([^\"]+)\"?")
set(OPENTELEMETRY_VERSION ${CMAKE_MATCH_1})
else()
message(
FATAL_ERROR
"OPENTELEMETRY_VERSION not found on ${CMAKE_CURRENT_LIST_DIR}/api/include/opentelemetry/version.h"
)
endif()
option(WITH_STL "Whether to use Standard Library for C++latest features" OFF)
option(WITH_ABSEIL "Whether to use Abseil for C++latest features" OFF)
if(NOT DEFINED CMAKE_CXX_STANDARD)
if(WITH_STL)
# Require at least C++17. C++20 is needed to avoid gsl::span
if(CMAKE_VERSION VERSION_GREATER 3.11.999)
# Ask for 20, may get anything below
set(CMAKE_CXX_STANDARD 20)
else()
# Ask for 17, may get anything below
set(CMAKE_CXX_STANDARD 17)
endif()
else()
set(CMAKE_CXX_STANDARD 11)
endif()
endif()
if(WITH_ABSEIL)
find_package(absl CONFIG REQUIRED)
set(CORE_RUNTIME_LIBS absl::bad_variant_access absl::any absl::base
absl::bits absl::city)
# target_link_libraries(main PRIVATE absl::any absl::base absl::bits
# absl::city)
endif()
if(WITH_STL)
# These definitions are needed for test projects that do not link against
# opentelemetry-api library directly. We ensure that variant implementation
# (absl::variant or std::variant) in variant unit test code is consistent with
# the global project build definitions.
add_definitions(-DHAVE_CPP_STDLIB)
add_definitions(-DHAVE_GSL)
# Guidelines Support Library path. Used if we are not on not get C++20.
#
# TODO: respect WITH_ABSEIL as alternate implementation of std::span
find_package(Microsoft.GSL QUIET)
if(TARGET Microsoft.GSL::GSL)
list(APPEND CORE_RUNTIME_LIBS Microsoft.GSL::GSL)
else()
set(GSL_DIR third_party/ms-gsl)
include_directories(${GSL_DIR}/include)
endif()
# Optimize for speed to reduce the hops
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
if(CMAKE_BUILD_TYPE MATCHES Debug)
# Turn off optimizations for DEBUG
set(MSVC_CXX_OPT_FLAG "/Od")
else()
string(REGEX MATCH "\/O" result ${CMAKE_CXX_FLAGS})
if(NOT ${result} MATCHES "\/O")
set(MSVC_CXX_OPT_FLAG "/O2")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MSVC_CXX_OPT_FLAG}")
endif()
endif()
option(WITH_OTLP "Whether to include the OpenTelemetry Protocol in the SDK" OFF)
option(WITH_ZIPKIN "Whether to include the Zipkin exporter in the SDK" OFF)
option(WITH_PROMETHEUS "Whether to include the Prometheus Client in the SDK"
OFF)
option(WITH_ELASTICSEARCH
"Whether to include the Elasticsearch Client in the SDK" OFF)
option(WITH_ZPAGES "Whether to include the Zpages Server in the SDK" OFF)
option(WITH_JAEGER "Whether to include the Jaeger exporter" OFF)
option(WITH_NO_GETENV "Whether the platform supports environment variables" OFF)
option(BUILD_TESTING "Whether to enable tests" ON)
option(BUILD_W3CTRACECONTEXT_TEST "Whether to build w3c trace context" OFF)
if(WITH_NO_GENENV)
add_definitions(-DNO_GETENV)
endif()
if(WIN32)
add_definitions(-DNOMINMAX)
if(BUILD_TESTING)
if(MSVC)
# GTest bug: https://github.com/google/googletest/issues/860
add_compile_options(/wd4275)
endif()
endif()
option(WITH_ETW "Whether to include the ETW Exporter in the SDK" ON)
if(WITH_ETW)
add_definitions(-DHAVE_MSGPACK)
endif(WITH_ETW)
endif(WIN32)
option(
WITH_API_ONLY
"Only build the API (use as a header-only library). Overrides WITH_EXAMPLES and all options to enable exporters"
OFF)
option(WITH_EXAMPLES "Whether to build examples" ON)
option(WITH_METRICS_PREVIEW "Whether to build metrics preview" OFF)
if(WITH_METRICS_PREVIEW)
add_definitions(-DENABLE_METRICS_PREVIEW)
endif()
option(WITH_LOGS_PREVIEW "Whether to build logs preview" OFF)
if(WITH_LOGS_PREVIEW)
add_definitions(-DENABLE_LOGS_PREVIEW)
endif()
find_package(Threads)
function(install_windows_deps)
# Bootstrap vcpkg from CMake and auto-install deps in case if we are missing
# deps on Windows. Respect the target architecture variable.
set(VCPKG_TARGET_ARCHITECTURE
${ARCH}
PARENT_SCOPE)
message("Installing build tools and dependencies...")
set(ENV{ARCH} ${ARCH})
execute_process(
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/setup-buildtools.cmd)
set(CMAKE_TOOLCHAIN_FILE
${CMAKE_CURRENT_SOURCE_DIR}/tools/vcpkg/scripts/buildsystems/vcpkg.cmake
PARENT_SCOPE)
endfunction()
if(WITH_JAEGER)
find_package(Thrift QUIET)
if(NOT Thrift_FOUND)
# Install Thrift and propagate via vcpkg toolchain file
if(WIN32 AND (NOT DEFINED CMAKE_TOOLCHAIN_FILE))
install_windows_deps()
endif()
endif()
endif()
if(MSVC)
# Options for Visual C++ compiler: /Zc:__cplusplus - report an updated value
# for recent C++ language standards. Without this option MSVC returns the
# value of __cplusplus="199711L"
if(MSVC_VERSION GREATER 1900)
# __cplusplus flag is not supported by Visual Studio 2015
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:__cplusplus")
endif()
# When using vcpkg, all targets build with the same runtime
if(VCPKG_TOOLCHAIN)
set(CMAKE_MSVC_RUNTIME_LIBRARY
"MultiThreaded$<$<CONFIG:Debug>:Debug>$<$<STREQUAL:${VCPKG_CRT_LINKAGE},dynamic>:DLL>"
CACHE STRING "")
endif()
endif()
# include GNUInstallDirs before include cmake/opentelemetry-proto.cmake because
# opentelemetry-proto installs targets to the location variables defined in
# GNUInstallDirs.
include(GNUInstallDirs)
if((NOT WITH_API_ONLY)
AND (WITH_ELASTICSEARCH
OR WITH_ZIPKIN
OR WITH_OTLP
OR WITH_OTLP_HTTP
OR WITH_ZPAGES
OR BUILD_W3CTRACECONTEXT_TEST
OR WITH_ETW
))
# nlohmann_json package is required for most SDK build configurations
find_package(nlohmann_json QUIET)
set(nlohmann_json_clone FALSE)
if(nlohmann_json_FOUND)
message("Using external nlohmann::json")
elseif(EXISTS ${PROJECT_SOURCE_DIR}/.git
AND EXISTS
${PROJECT_SOURCE_DIR}/third_party/nlohmann-json/CMakeLists.txt)
message("Trying to use local nlohmann::json from submodule")
set(JSON_BuildTests
OFF
CACHE INTERNAL "")
set(JSON_Install
ON
CACHE INTERNAL "")
# This option allows to link nlohmann_json::nlohmann_json target
add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/nlohmann-json)
# This option allows to add header to include directories
include_directories(
${PROJECT_SOURCE_DIR}/third_party/nlohmann-json/single_include)
else()
set(nlohmann_json_clone TRUE)
include(cmake/nlohmann-json.cmake)
message("\nnlohmann_json package was not found. Cloning from github")
endif()
endif()
if(WITH_PROMETHEUS)
find_package(prometheus-cpp CONFIG QUIET)
if(NOT prometheus-cpp_FOUND)
message("Trying to use local prometheus-cpp from submodule")
if(EXISTS ${PROJECT_SOURCE_DIR}/third_party/prometheus-cpp/.git)
add_subdirectory(third_party/prometheus-cpp)
else()
message(
FATAL_ERROR
"\nprometheus-cpp package was not found. Please either provide it manually or clone with submodules. "
"To initialize, fetch and checkout any nested submodules, you can use the following command:\n"
"git submodule update --init --recursive")
endif()
else()
message("Using external prometheus-cpp")
endif()
endif()
if(WITH_OTLP)
set(protobuf_MODULE_COMPATIBLE ON)
find_package(Protobuf)
if(WITH_OTLP_GRPC OR (NOT DEFINED WITH_OTLP_GRPC AND NOT DEFINED
CACHE{WITH_OTLP_GRPC}))
find_package(gRPC)
endif()
if((NOT Protobuf_FOUND AND NOT PROTOBUF_FOUND) OR (NOT gRPC_FOUND))
if(WIN32 AND (NOT DEFINED CMAKE_TOOLCHAIN_FILE))
install_windows_deps()
endif()
if(WIN32 AND (NOT DEFINED CMAKE_TOOLCHAIN_FILE))
message(STATUS_FATAL "Windows dependency installation failed!")
endif()
if(WIN32)
include(${CMAKE_TOOLCHAIN_FILE})
endif()
if(NOT Protobuf_FOUND AND NOT PROTOBUF_FOUND)
find_package(Protobuf REQUIRED)
endif()
if(NOT gRPC_FOUND
AND (WITH_OTLP_GRPC OR (NOT DEFINED WITH_OTLP_GRPC
AND NOT DEFINED CACHE{WITH_OTLP_GRPC})))
find_package(gRPC)
endif()
if(WIN32)
# Always use x64 protoc.exe
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
set(Protobuf_PROTOC_EXECUTABLE
${CMAKE_CURRENT_SOURCE_DIR}/tools/vcpkg/packages/protobuf_x64-windows/tools/protobuf/protoc.exe
)
endif()
endif()
# Latest Protobuf uses mixed case instead of uppercase
if(Protobuf_PROTOC_EXECUTABLE)
set(PROTOBUF_PROTOC_EXECUTABLE ${Protobuf_PROTOC_EXECUTABLE})
endif()
endif()
include(CMakeDependentOption)
if(WITH_OTLP_HTTP OR (NOT DEFINED WITH_OTLP_HTTP AND NOT DEFINED
CACHE{WITH_OTLP_HTTP}))
find_package(CURL)
endif()
cmake_dependent_option(
WITH_OTLP_GRPC "Whether to include the OTLP gRPC exporter in the SDK" ON
"gRPC_FOUND" OFF)
cmake_dependent_option(
WITH_OTLP_HTTP "Whether to include the OTLP http exporter in the SDK" ON
"CURL_FOUND" OFF)
message(STATUS "PROTOBUF_PROTOC_EXECUTABLE=${PROTOBUF_PROTOC_EXECUTABLE}")
include(cmake/opentelemetry-proto.cmake)
endif()
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")
include(CTest)
if(BUILD_TESTING)
if(EXISTS ${CMAKE_BINARY_DIR}/lib/libgtest.a)
# Prefer GTest from build tree. GTest is not always working with
# CMAKE_PREFIX_PATH
set(GTEST_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googletest/include
${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googlemock/include)
set(GTEST_BOTH_LIBRARIES
${CMAKE_BINARY_DIR}/lib/libgtest.a
${CMAKE_BINARY_DIR}/lib/libgtest_main.a
${CMAKE_BINARY_DIR}/lib/libgmock.a)
elseif(WIN32)
# Make sure we are always bootsrapped with vcpkg on Windows
find_package(GTest)
if(NOT (GTEST_FOUND OR GTest_FOUND))
install_windows_deps()
find_package(GTest REQUIRED)
endif()
else()
# Prefer GTest installed by OS distro, brew or vcpkg package manager
find_package(GTest REQUIRED)
endif()
include_directories(SYSTEM ${GTEST_INCLUDE_DIRS})
message("GTEST_INCLUDE_DIRS = ${GTEST_INCLUDE_DIRS}")
message("GTEST_BOTH_LIBRARIES = ${GTEST_BOTH_LIBRARIES}")
enable_testing()
# Benchmark respects the CMAKE_PREFIX_PATH
find_package(benchmark CONFIG REQUIRED)
endif()
include(CMakePackageConfigHelpers)
include_directories(api/include)
add_subdirectory(api)
if(NOT WITH_API_ONLY)
include_directories(sdk/include)
include_directories(sdk)
include_directories(ext/include)
add_subdirectory(sdk)
add_subdirectory(ext)
add_subdirectory(exporters)
if(WITH_EXAMPLES)
add_subdirectory(examples)
endif()
endif()
# Export cmake config and support find_packages(opentelemetry-cpp CONFIG) Write
# config file for find_packages(opentelemetry-cpp CONFIG)
set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}")
configure_package_config_file(
"${CMAKE_CURRENT_LIST_DIR}/cmake/opentelemetry-cpp-config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
PATH_VARS OPENTELEMETRY_ABI_VERSION_NO OPENTELEMETRY_VERSION PROJECT_NAME
INCLUDE_INSTALL_DIR CMAKE_INSTALL_LIBDIR
NO_CHECK_REQUIRED_COMPONENTS_MACRO)
# Write version file for find_packages(opentelemetry-cpp CONFIG)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake"
VERSION ${OPENTELEMETRY_VERSION}
COMPATIBILITY ExactVersion)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
# Export all components
export(
EXPORT "${PROJECT_NAME}-target"
NAMESPACE "${PROJECT_NAME}::"
FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-target.cmake"
)
install(
EXPORT "${PROJECT_NAME}-target"
NAMESPACE "${PROJECT_NAME}::"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")