我想在我的 C++ 项目中使用 Boost Multi precision,但我无法做到。我怀疑我没有在我的根
CMakeLists.txt
配置中添加正确的依赖项,其相关部分如下所示:
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)
我确保在
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})
以及我的图书馆
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})
我已经通过包管理器验证了
Boost
和 MPFR
都安装在我的系统上。
当我包含必要的标头并使用多精度类型时,我的 linter (Clangd
) 不会产生错误:
#include <boost/multiprecision/mpfr.hpp>
// ...
int main() {
IOParser<boost::multiprecision::mpfr_float_100> parser;
// ...
}
但是当我编译程序时,我得到了一些对各种 MPFR 函数的未定义引用,例如:
[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'
我做错了什么?
MPFR (https://www.mpfr.org/) 不提供 CMake 支持。
所以你需要从其他地方获取FindMPFR。如果您的发行版打包程序没有添加它,您必须将其发送到您自己的存储库中:
(mkdir -pv cmake && cd cmake && wget -c https://raw.githubusercontent.com/quarkslab/NFLlib/refs/heads/master/cmake/FindMPFR.cmake)
下载以下示例
cmake/FindMPFR.cmake
:
# Copyright (c) 2008-2010 Kent State University
# Copyright (c) 2011-2012 Texas A&M University
#
# This file is distributed under the MIT License. See the accompanying file
# LICENSE.txt or http://www.opensource.org/licenses/mit-license.php for terms
# and conditions.
# FIXME: How do I find the version of MPFR that I want to use?
# What versions are available?
# NOTE: MPFR prefix is understood to be the path to the root of the MPFR
# installation library.
set(MPFR_PREFIX "" CACHE PATH "The path to the previx of an MPFR installation")
find_path(MPFR_INCLUDE_DIR mpfr.h
PATHS ${MPFR_PREFIX}/include /usr/include /usr/local/include)
find_library(MPFR_LIBRARY NAMES mpfr
PATHS ${MPFR_PREFIX}/lib /usr/lib /usr/local/lib)
if(MPFR_INCLUDE_DIR AND MPFR_LIBRARY)
get_filename_component(MPFR_LIBRARY_DIR ${MPFR_LIBRARY} PATH)
set(MPFR_FOUND TRUE)
endif()
if(MPFR_FOUND)
if(NOT MPFR_FIND_QUIETLY)
MESSAGE(STATUS "Found MPFR: ${MPFR_LIBRARY}")
endif()
elseif(MPFR_FOUND)
if(MPFR_FIND_REQUIRED)
message(FATAL_ERROR "Could not find MPFR")
endif()
endif()
现在,您可以将 cmake 目录添加到前缀路径:
set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/cmake:${CMAKE_PREFIX_PATH}")
或者,显然您已经使用的模块路径行:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
现在我这样做是为了 MPFR 和 GMP 更加完整:
文件
./main.cpp
#include <boost/multiprecision/mpfr.hpp>
#include <boost/multiprecision/gmp.hpp>
#include <iostream>
int main()
{
using namespace boost::multiprecision;
mpfr_float_100 a = 1.0;
mpfr_float_100 b = 2.0;
mpfr_float_100 c = a + b;
std::cout << c << std::endl;
mpz_int d = 1;
mpz_int e = 1;
mpz_int f = d + e;
std::cout << f << std::endl;
return 0;
}
空文件
./app/CMakeLists.txt
空文件
./test/CMakeLists.txt
空文件
./SomeFile.cpp
空文件
./src/CMakeLists.txt
文件
./CMakeLists.txt
cmake_minimum_required(VERSION 3.29.0)
project(MyProject VERSION 1.0.0 LANGUAGES C CXX)
#set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/cmake:${CMAKE_PREFIX_PATH}")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
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})
find_package(GMP REQUIRED)
include_directories(${GMP_INCLUDE_DIRS})
add_subdirectory(app)
add_subdirectory(test)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE myLib)
target_link_libraries(main PUBLIC ${Boost_LIBRARIES})
target_link_libraries(main PUBLIC ${MPFR_LIBRARY})
target_link_libraries(main PUBLIC ${GMP_LIBRARY})
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})
文件
./cmake/FindMPFR.cmake
# Copyright (c) 2008-2010 Kent State University
# Copyright (c) 2011-2012 Texas A&M University
#
# This file is distributed under the MIT License. See the accompanying file
# LICENSE.txt or http://www.opensource.org/licenses/mit-license.php for terms
# and conditions.
# FIXME: How do I find the version of MPFR that I want to use?
# What versions are available?
# NOTE: MPFR prefix is understood to be the path to the root of the MPFR
# installation library.
set(MPFR_PREFIX "" CACHE PATH "The path to the previx of an MPFR installation")
find_path(MPFR_INCLUDE_DIR mpfr.h
PATHS ${MPFR_PREFIX}/include /usr/include /usr/local/include)
find_library(MPFR_LIBRARY NAMES mpfr
PATHS ${MPFR_PREFIX}/lib /usr/lib /usr/local/lib)
if(MPFR_INCLUDE_DIR AND MPFR_LIBRARY)
get_filename_component(MPFR_LIBRARY_DIR ${MPFR_LIBRARY} PATH)
set(MPFR_FOUND TRUE)
endif()
if(MPFR_FOUND)
if(NOT MPFR_FIND_QUIETLY)
MESSAGE(STATUS "Found MPFR: ${MPFR_LIBRARY}")
endif()
elseif(MPFR_FOUND)
if(MPFR_FIND_REQUIRED)
message(FATAL_ERROR "Could not find MPFR")
endif()
endif()
文件
./cmake/FindGMP.cmake
# Copyright (c) 2008-2010 Kent State University
# Copyright (c) 2011-2012 Texas A&M University
#
# This file is distributed under the MIT License. See the accompanying file
# LICENSE.txt or http://www.opensource.org/licenses/mit-license.php for terms
# and conditions.
# FIXME: How do I find the version of GMP that I want to use?
# What versions are available?
# NOTE: GMP prefix is understood to be the path to the root of the GMP
# installation library.
set(GMP_PREFIX "" CACHE PATH "The path to the prefix of a GMP installation")
find_path(GMP_INCLUDE_DIR gmp.h
PATHS ${GMP_PREFIX}/include /usr/include /usr/local/include)
find_library(GMP_LIBRARY NAMES gmp
PATHS ${GMP_PREFIX}/lib /usr/lib /usr/local/lib)
if(GMP_INCLUDE_DIR AND GMP_LIBRARY)
get_filename_component(GMP_LIBRARY_DIR ${GMP_LIBRARY} PATH)
set(GMP_FOUND TRUE)
endif()
if(GMP_FOUND)
if(NOT GMP_FIND_QUIETLY)
MESSAGE(STATUS "Found GMP: ${GMP_LIBRARY}")
endif()
elseif(GMP_FOUND)
if(GMP_FIND_REQUIRED)
message(FATAL_ERROR "Could not find GMP")
endif()
endif()
它可以在我的机器(TM)上使用 Nix 软件包用于
mpfr
和 gmp
: