open-telemetry / opentelemetry-cpp

The OpenTelemetry C++ Client
https://opentelemetry.io/
Apache License 2.0
879 stars 419 forks source link

Build with external abseil not working, ambiguous references #3063

Open maxlein opened 1 month ago

maxlein commented 1 month ago

Describe your environment Ubuntu 22.04 CMake build

I want to add tracing to my already existing app where we also use and link against grpc/abseil.

Steps to reproduce

I made a little install script for otel:

#!/bin/bash

mkdir -p build 
cd build

cmake -DBUILD_TESTING:BOOL=OFF \
    -DBUILD_SHARED_LIBS:BOOL=ON \
    -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON \
    -DWITH_JAEGER:BOOL=OFF \
    -DWITH_OTLP_HTTP:BOOL=OFF \
    -DWITH_OTLP_GRPC:BOOL=OFF \
    -DWITH_PROMETHEUS:BOOL=OFF \
    -DWITH_ZIPKIN:BOOL=OFF \
    -DWITH_EXAMPLES:BOOL=OFF \
    -DOTELCPP_VERSIONED_LIBS:BOOL=ON \
    -DBUILD_PACKAGE=ON \
    -DWITH_ABSEIL=ON \
    -DWITH_STL=ON \
    -DCMAKE_PREFIX_PATH=/usr/alpen \
    ..

cmake --build .

cpack

and I added some output to see if otel finds my installed version of abseil:

if(WITH_ABSEIL)
  if(NOT TARGET absl::strings)
    find_package(absl CONFIG REQUIRED)
    message(STATUS "Found Abseil: ${absl_DIR}")
  else ()
    message(STATUS "Using external Abseil")
  endif()
endif()

Output: Found Abseil: /usr/alpen/lib/cmake/absl

Then in my app I created a little testing lib to see if it will build:

find_package(opentelemetry-cpp CONFIG REQUIRED)

add_library(tracer_lib SHARED src/tracer_common.cpp)
target_include_directories(tracer_lib PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>)
target_link_libraries(tracer_lib PUBLIC
        ${COMMON_LIBS}
        ${OPENTELEMETRY_CPP_LIBRARIES}
)
set_property(TARGET tracer_lib PROPERTY POSITION_INDEPENDENT_CODE 1)
#include <grpcpp/grpcpp.h>
#include "msg/task_service.grpc.pb.h"

namespace grpc::tracing
{
class TaskServer : public grpc::task::TaskService::Service

...

But when compile I always get this error: _reference to ‘baseinternal’ is ambiguous

What is the expected behavior? I can build without interfering header files from different abseil libs.

What is the actual behavior?

I see this error:

from /home/XXX/alpen/service_lib/tests/tracing/server.cpp:5:
/usr/alpen/include/absl/synchronization/internal/per_thread_sem.h:80:47: error: reference to ‘base_internal’ is ambiguous

/usr/include/opentelemetry/nostd/internal/absl/base/internal/invoke.h:49:11: note: candidates are: ‘namespace absl::otel_v1::base_internal { }’

/usr/alpen/include/absl/base/internal/low_level_alloc.h:59:11: note:                 ‘namespace absl::lts_20220623::base_internal { }’

Additional context

I looked at the hints here, but they had no effect.

owent commented 1 month ago

Could you please check whether HAVE_ABSEIL is in INTERFACE_COMPILE_DEFINITIONS of opentelemetry-cpp::api?(located in ${opentelemetry-cpp_DIR}/opentelemetry-cpp-target.cmake)

It seems otel-cpp's headers are included without HAVE_ABSEIL, this macro should be defined automaticly by cmake when linking otel-cpp's CONFIG package.

maxlein commented 1 month ago

For me it looks like this in this file /usr/lib/cmake/opentelemetry-cpp/opentelemetry-cpp-target.cmake:

set_target_properties(opentelemetry-cpp::api PROPERTIES
  INTERFACE_COMPILE_DEFINITIONS "OPENTELEMETRY_DEPRECATED_SDK_FACTORY;HAVE_ABSEIL;OPENTELEMETRY_STL_VERSION=2023;OPENTELEMETRY_ABI_VERSION_NO=1"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "absl::bad_variant_access;absl::any;absl::base;absl::bits;absl::city"
)

And in my app it looks like this now:

#### Tracing Library ####
find_package(opentelemetry-cpp CONFIG REQUIRED)
message(STATUS "Found otel: ${opentelemetry-cpp_DIR}")

#print INTERFACE_COMPILE_DEFINITIONS
message("INTERFACE_COMPILE_DEFINITIONS: ${opentelemetry-cpp_INTERFACE_COMPILE_DEFINITIONS}")

if(NOT DEFINED HAVE_ABSEIL)
    message(FATAL_ERROR "HAVE_ABSEIL not defined")
endif(NOT DEFINED HAVE_ABSEIL)

if(NOT DEFINED ${HAVE_ABSEIL})
    message(FATAL_ERROR "HAVE_ABSEIL empty")
else ()
    message("HAVE_ABSEIL defined as ${HAVE_ABSEIL}")
endif(NOT DEFINED ${HAVE_ABSEIL})
-- Found otel: /usr/lib/cmake/opentelemetry-cpp
INTERFACE_COMPILE_DEFINITIONS: 
CMake Error at CMakeLists.txt:35 (message):
  HAVE_ABSEIL not defined

Adding add_compile_definitions(HAVE_ABSEIL) manually to my project cmake file fixes the issue and I can compile

owent commented 1 month ago

HAVE_ABSEIL is a C++ macro, not a CMake variable. It should be included using target_link_libraries(tracer_lib PUBLIC ${COMMON_LIBS} ${OPENTELEMETRY_CPP_LIBRARIES}) in your project. Please check whether OPENTELEMETRY_CPP_LIBRARIES includes opentelemetry-cpp::api by using message("OPENTELEMETRY_CPP_LIBRARIES=${OPENTELEMETRY_CPP_LIBRARIES}"). The CMake config file /usr/lib/cmake/opentelemetry-cpp/opentelemetry-cpp-target.cmake appears to be fine.