c++cmakeboostundefined-referenceboost-multiprecision

Undefined references to mpfr_*() functions when trying to use Boost Multiprecision in a CMake Project?


I want to use Boost Multiprecision in my C++ project, but I am unable to. I suspect I haven't added the correct dependencies in my root CMakeLists.txt configuration, the relevant part of which look like this:

cmake_minimum_required(VERSION 3.30.0)
project(MyProject VERSION 1.0.0 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_subdirectory(src)
add_subdirectory(app)
add_subdirectory(test)

find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(MPFR REQUIRED)
include_directories(${MPFR_INCLUDE_DIRS})

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

I made sure to link the libraries for my executable in app/CMakeLists.txt:

add_executable(main main.cpp)
target_link_libraries(main PRIVATE myLib)
target_link_libraries(main ${Boost_LIBRARIES})
target_link_libraries(main ${MPFR_LIBRARIES})

and for my library at src/CMakeLists.txt:

file(GLOB HEADER_LIST CONFIGURE_DEPENDS "${MyProject_SOURCE_DIR}/include/*.h")
add_library(myLib SomeFile.cpp ${HEADER_LIST})
target_include_directories(myLib PUBLIC ../include)
target_link_libraries(myLib ${Boost_LIBRARIES})
target_link_libraries(myLib ${MPFR_LIBRARIES})

I have verified that both Boost and MPFR are installed on my system through the package manager. My linter (Clangd) produces no errors when I include the necessary headers and use a multiprecision type:

#include <boost/multiprecision/mpfr.hpp>
// ...

int main() {
    IOParser<boost::multiprecision::mpfr_float_100> parser;
    // ...
}

But when I compile my program, I get several undefined references to various MPFR functions such as:

[build] /usr/bin/ld: CMakeFiles/main.dir/main.cpp.o: in function `boost::multiprecision::backends::detail::mpfr_float_imp<100u, (boost::multiprecision::mpfr_allocation_type)1>::operator=(boost::multiprecision::backends::detail::mpfr_float_imp<100u, (boost::multiprecision::mpfr_allocation_type)1>&&) [clone .isra.0]':
[build] main.cpp:(.text+0x2dc): undefined reference to `mpfr_swap'
[build] /usr/bin/ld: main.cpp:(.text+0x30c): undefined reference to `mpfr_set4'
[build] /usr/bin/ld: main.cpp:(.text+0x386): undefined reference to `mpfr_init2'

What am I doing wrong?


Solution

  • Since both GMP and MPFR offer pkg-config files, you can use the built-in PkgConfig module to generate a nice modern target that will resolve both include and linker dependencies for you:

    find_package(PkgConfig REQUIRED)
    pkg_check_modules(deps REQUIRED IMPORTED_TARGET gmp mpfr)
    

    Now, in app/CMakeLists.txt you can just do:

    target_link_libraries(main PkgConfig::deps)
    

    As a bonus, the PkgConfig approach allows you to specify version bounds.