Andrew Peter Marlow created AVRO-4353:
-----------------------------------------

             Summary: [C++] Installed avro-cpp CMake package does not pass fmt 
on to consumers, although its public headers include fmt
                 Key: AVRO-4353
                 URL: https://issues.apache.org/jira/browse/AVRO-4353
             Project: Apache Avro
          Issue Type: Bug
          Components: c++
    Affects Versions: 1.12.2
         Environment: Linux. Rocky Linux 8 with gcc 8.5 and CMake 3.26; Linux 
Mint 22 with gcc 13.3 and CMake 3.28. fmt 11.0.2 and 12.1.0 installed under 
their own prefixes.
            Reporter: Andrew Peter Marlow


The installed avro-cpp package cannot be used by a CMake project unless that 
project separately
adds fmt itself, because the fmt dependency of Avro's public headers is not 
passed on.

Three installed headers use fmt: avro/Exception.hh includes <fmt/core.h>, 
avro/Types.hh includes
<fmt/format.h>, and avro/Node.hh uses fmt::. But in lang/c++/CMakeLists.txt, 
setup_avro_lib links
fmt only for the build of Avro itself:

{code}
target_link_libraries (${target} PUBLIC
  $<BUILD_INTERFACE:fmt::fmt-header-only>
  ...
{code}

There is no matching INSTALL_INTERFACE entry, so the exported targets 
avro-cpp::avrocpp and
avro-cpp::avrocpp_s carry no fmt include directory or link. The installed 
avro-cpp-config.cmake
does call find_dependency(fmt REQUIRED), so fmt is found for the consumer, but 
nothing links it.

*To reproduce*, with Avro 1.12.2 and fmt installed under separate prefixes:

{code}
cmake_minimum_required(VERSION 3.16)
project(consumer CXX)
set(CMAKE_CXX_STANDARD 17)
find_package(avro-cpp CONFIG REQUIRED)
add_executable(consumer main.cpp)   # main.cpp includes <avro/Encoder.hh>
target_link_libraries(consumer PRIVATE avro-cpp::avrocpp_shared)
{code}

configured with -DCMAKE_PREFIX_PATH="<avro prefix>;<fmt prefix>". Configuring 
succeeds, and
compiling fails:

{code}
<avro prefix>/include/avro/Exception.hh:23:10: fatal error: fmt/core.h: No such 
file or directory
{code}

It works only when the consumer adds find_package(fmt) and links fmt::fmt 
itself.

*Suggested fix.* Drop the BUILD_INTERFACE wrapper, so fmt is part of the 
installed interface too:

{code}
target_link_libraries (${target} PUBLIC
  fmt::fmt-header-only
  ...
{code}

find_dependency(fmt) in avro-cpp-config.cmake then provides the target. A 
project that already
uses the compiled fmt library may prefer Avro to link fmt::fmt instead of 
fmt::fmt-header-only,
so that the program has one copy of fmt; linking fmt::fmt in both interfaces 
also resolves this
report, and builds and works with fmt 11.0.2 and 12.1.0 (checked with gcc 8.5 
and gcc 13).

The main branch no longer uses fmt (AVRO-4260 moves to std::format and C++20), 
so this affects
the 1.12 line only.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to