Build with external abseil not working, ambiguous references
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 ‘base_internal’ 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.
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.
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
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.
This issue was marked as stale due to lack of activity.
Starting with opentelemetry-cpp 1.18.0, this part:
Overall, the build failures looks like the compiler finds multiple abseil implementations, one found externally, and one found in opentelemetry-cpp/api/include/opentelemetry/nostd/internal/absl, which is meant to be used only when there is no external abseil.
is now resolved, with the refactoring work related to abseil implemented in #3041.
It is now possible to have both:
- the internal abseil implementation
- an external abseil implementation
present in the same build.
Errors such as reference to abseil::xyz is ambiguous are fixed, because the internal implementation no longer refers to abseil::xyz with an inline namespace. Instead, the internal implementation uses abseil::otel_v1::xyz.