[英]Linking Boost when using cmake-conan
I am trying to have the following CMake project working: the idea is to use cmake-conan to have cmake handle the conan install step (sparing the user the need to set up the profile etc).我正在尝试使以下 CMake 项目正常工作:想法是使用cmake-conan让 cmake 处理柯南安装步骤(使用户无需设置配置文件等)。
However it fails to link to Boost.但是它无法链接到 Boost。
# CMakelist.txt
cmake_minimum_required(VERSION 3.23.2)
# project name and language
project(MYAPP LANGUAGES CXX)
# we default to Release build type if DCMAKE_BUILD_TYPE not provided
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "C++ flags, Debug configuration: ${CMAKE_CXX_FLAGS_DEBUG}")
message(STATUS "C++ flags, Release configuration: ${CMAKE_CXX_FLAGS_RELEASE}")
message(STATUS "C++ flags, Release configuration with Debug info: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
message(STATUS "C++ flags, minimal Release configuration: ${CMAKE_CXX_FLAGS_MINSIZEREL}")
# Use modern C++ with support for concepts and mp-units
set(CMAKE_CXX_STANDARD 20)
# Prevent use of non-portable compiler extensions
set(CMAKE_CXX_EXTENSIONS OFF)
# This makes C++20 a requirement and prevents a "decay" to C++98 when the compiler does not support C++20.
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Tell find_package() to first search using Config mode before falling back to Module mode (for conan)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
set(Boost_DEBUG ON)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/0.18.1/conan.cmake"
"${CMAKE_BINARY_DIR}/conan.cmake"
TLS_VERIFY ON)
endif()
include(${CMAKE_BINARY_DIR}/conan.cmake)
conan_cmake_configure(
REQUIRES
boost/1.79.0
GENERATORS
cmake_find_package
)
# By default, Conan only searches for packages from the two central repositories
# hosted and moderated by **Conan.io** staff: `conan-center` and `conan-transit`.
# We will need packages that are not hosted by these official repositories.
# The [Bincrafters](https://bincrafters.github.io/2017/06/06/using-bincrafters-conan-repository/)
# community posts new packages/versions every week in a separate Conan repository.
conan_add_remote(NAME bincrafters
URL https://bincrafters.jfrog.io/artifactory/api/conan/public-conan)
# Detect settings like OS and architecture
# I think it also detects CMake settings like gcc, gcc-version; cppstd, build_type etc
conan_cmake_autodetect(settings)
# Since GCC >= 5, the compiler is likely to be using the new CXX11 ABI by default (libstdc++11)
# See https://docs.conan.io/en/latest/howtos/manage_gcc_abi.html
conan_cmake_install(PATH_OR_REFERENCE .
BUILD missing
REMOTE conancenter bincrafters
SETTINGS
${settings}
compiler.libcxx=libstdc++11
)
find_package(Boost 1.79 REQUIRED COMPONENTS program_options REQUIRED)
add_executable(my_app main.cpp)
target_link_libraries(my_app Boost::boost)
# We need C++ 20 activated with the concepts library
target_compile_features(my_app PUBLIC cxx_std_20)
// main.cpp
#include <boost/program_options.hpp>
namespace bpo = boost::program_options;
int main(int argc, char* argv[])
{
bpo::variables_map vm;
bool verbose = false;
return 0;
}
$ mkdir build && cd build
$ cmake -D CMAKE_BUILD_TYPE=Release \
-D CMAKE_C_COMPILER=/usr/bin/gcc-10 \
-D CMAKE_CXX_COMPILER=/usr/bin/g++-10 \
..
$ cmake --build .
The Conan profile defined on the fly during the configuration step ( cmake ..
) is the following:在配置步骤 (
cmake ..
) 中动态定义的柯南配置文件如下:
Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=20
compiler.libcxx=libstdc++11
compiler.version=10
os=Linux
os_build=Linux
[options]
[build_requires]
[env]
CC=[/usr/bin/gcc-10]
CXX=[/usr/bin/g++-10]
[conf]
[ 50%] Building CXX object CMakeFiles/my_app.dir/main.cpp.o
[100%] Linking CXX executable my_app
/usr/bin/ld: CMakeFiles/my_app.dir/main.cpp.o: in function `main':
main.cpp:(.text.startup+0x24): undefined reference to `boost::program_options::variables_map::variables_map()'
/usr/bin/ld: main.cpp:(.text.startup+0x33): undefined reference to `vtable for boost::program_options::variables_map'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/my_app.dir/build.make:97: my_app] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/my_app.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
I have looked around for now two days and I could not find any lead (although I learned a lot).我已经环顾了两天,但找不到任何线索(尽管我学到了很多东西)。
Accordind the discussion in the comments, I updated the CMake file to ask for dependencies to be built from source.根据评论中的讨论,我更新了 CMake 文件以要求从源代码构建依赖项。 The conan.io/cmake-conan README documentation states that replacing the
BUILD missing
by BUILD all
should work: conan.io/cmake-conan README 文档指出,将
BUILD missing
替换为BUILD all
应该可以工作:
BUILD
(if this parameter takes theall
value, Conan will build everything from source)BUILD
(如果此参数采用all
值,柯南将从源代码构建所有内容)
So I tried it, removing the bincrafters reference and even trying to downgrade the Boost version to 1.77, or cleaning the conan cache with conan remove "*" -s -b -f
.所以我尝试了一下,删除了 bincrafters 引用,甚至尝试将 Boost 版本降级到 1.77,或者使用
conan remove "*" -s -b -f
清理柯南缓存。 But I still end with the exact same linking error.但我仍然以完全相同的链接错误结束。
cmake_minimum_required(VERSION 3.23.2)
# project name and language
project(MYAPP LANGUAGES CXX)
# we default to Release build type if DCMAKE_BUILD_TYPE not provided
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
# Use modern C++ with support for concepts and mp-units
set(CMAKE_CXX_STANDARD 20)
# Prevent use of non-portable compiler extensions
set(CMAKE_CXX_EXTENSIONS OFF)
# This makes C++20 a requirement and prevents a "decay" to C++98 when the compiler does not support C++20.
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Tell find_package() to first search using Config mode before falling back to Module mode (for conan)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
set(Boost_DEBUG ON)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/0.18.1/conan.cmake"
"${CMAKE_BINARY_DIR}/conan.cmake"
TLS_VERIFY ON)
endif()
include(${CMAKE_BINARY_DIR}/conan.cmake)
conan_cmake_configure(
REQUIRES
boost/1.77.0
GENERATORS
cmake_find_package
)
# Detect settings like OS and architecture
# I think it also detects CMake settings like gcc, gcc-version; cppstd, build_type etc
conan_cmake_autodetect(settings)
# Since GCC >= 5, the compiler is likely to be using the new CXX11 ABI by default (libstdc++11)
# See https://docs.conan.io/en/latest/howtos/manage_gcc_abi.html
# The BUILD all option builds all dependencies from source every time
conan_cmake_install(PATH_OR_REFERENCE .
BUILD all
REMOTE conancenter
SETTINGS
${settings}
compiler.libcxx=libstdc++11
)
find_package(Boost 1.77 REQUIRED COMPONENTS program_options REQUIRED)
add_executable(my_app main.cpp)
target_link_libraries(my_app Boost::boost)
During the configuration, I receive suspicious/intriguing outputs.在配置过程中,我收到了可疑/有趣的输出。 I am not knowledgeable enough to know if they could be part of the solution, so here they are:
我没有足够的知识知道他们是否可以成为解决方案的一部分,所以他们在这里:
/home/becheler/.conan/data/libbacktrace/cci.20210118/_/_/build/19729b9559f3ae196cad45cb2b97468ccb75dcd1/source_subfolder/missing: Unknown `--is-lightweight' option
Try `/home/becheler/.conan/data/libbacktrace/cci.20210118/_/_/build/19729b9559f3ae196cad45cb2b97468ccb75dcd1/source_subfolder/missing --help' for more information
configure: WARNING: 'missing' script is too old or missing
Libraries have been installed in:
/home/becheler/.conan/data/libbacktrace/cci.20210118/_/_/package/19729b9559f3ae196cad45cb2b97468ccb75dcd1/lib
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'
notice: [python-cfg] Details of this Python configuration:
notice: [python-cfg] interpreter command: "python"
notice: [python-cfg] include path: "/home/becheler/dev/virtual_environments/conan-env/include/python3.8"
notice: [python-cfg] library path: "/home/becheler/dev/virtual_environments/conan-env/lib/python3.8/config" "/home/becheler/dev/virtual_environments/conan-env/lib"
notice: [python-cfg] Checking for NumPy...
notice: [python-cfg] running command 'python -c "import sys; sys.stderr = sys.stdout; import numpy; print(numpy.get_include())"'
notice: [python-cfg] NumPy disabled. Reason:
notice: [python-cfg] python -c "import sys; sys.stderr = sys.stdout; import numpy; print(numpy.get_include())" aborted with
notice: [python-cfg] Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'numpy'
And maybe the most relevant concerns the components spelling:也许最相关的是组件拼写:
- Conan: Using autogenerated FindBoost.cmake
-- Conan: Component 'program_options' found in package 'Boost'
... // ~~~~~~~~ A BIT LATER ~~~~~~~~~~~~~~~~~
-- Library boost_program_options found /home/becheler/.conan/data/boost/1.77.0/_/_/package/f54880bb9f17d8cef9b4d28f5cf70e057f105ac1/lib/libboost_program_options.a
-- Found: /home/becheler/.conan/data/boost/1.77.0/_/_/package/f54880bb9f17d8cef9b4d28f5cf70e057f105ac1/lib/libboost_program_options.a
... // ~~~~~~~~ A BIT LATER AGAIN ~~~~~~~~~~~~~~~~~
-- Library boost_program_options found /home/becheler/.conan/data/boost/1.77.0/_/_/package/f54880bb9f17d8cef9b4d28f5cf70e057f105ac1/lib/libboost_program_options.a
-- Found: /home/becheler/.conan/data/boost/1.77.0/_/_/package/f54880bb9f17d8cef9b4d28f5cf70e057f105ac1/lib/libboost_program_options.a
The solution to have a successful build was to change the default generator from Ninja to CMake, that is replacing GENERATORS cmake_find_package
by GENERATORS cmake
in the call the conan_cmake_configure
.成功构建的解决方案是将默认生成器从 Ninja 更改为 CMake,即在调用
conan_cmake_configure
时将GENERATORS cmake_find_package
替换为GENERATORS cmake
。 I have no idea why!我不知道为什么!
Here is the successful CMake file:这是成功的 CMake 文件:
cmake_minimum_required(VERSION 3.23.2)
# project name and language
project(MYAPP LANGUAGES CXX)
# we default to Release build type if DCMAKE_BUILD_TYPE not provided
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "C++ flags, Debug configuration: ${CMAKE_CXX_FLAGS_DEBUG}")
message(STATUS "C++ flags, Release configuration: ${CMAKE_CXX_FLAGS_RELEASE}")
message(STATUS "C++ flags, Release configuration with Debug info: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
message(STATUS "C++ flags, minimal Release configuration: ${CMAKE_CXX_FLAGS_MINSIZEREL}")
# Use modern C++ with support for concepts and mp-units
set(CMAKE_CXX_STANDARD 20)
# Prevent use of non-portable compiler extensions
set(CMAKE_CXX_EXTENSIONS OFF)
# This makes C++20 a requirement and prevents a "decay" to C++98 when the compiler does not support C++20.
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Tell find_package() to first search using Config mode before falling back to Module mode (for conan)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
set(Boost_DEBUG ON)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/0.18.1/conan.cmake"
"${CMAKE_BINARY_DIR}/conan.cmake"
TLS_VERIFY ON)
endif()
include(${CMAKE_BINARY_DIR}/conan.cmake)
conan_cmake_configure(
REQUIRES
boost/1.77.0
GENERATORS
cmake
)
# Detect settings like OS and architecture
# I think it also detects CMake settings like gcc, gcc-version; cppstd, build_type etc
conan_cmake_autodetect(settings)
# Since GCC >= 5, the compiler is likely to be using the new CXX11 ABI by default (libstdc++11)
# See https://docs.conan.io/en/latest/howtos/manage_gcc_abi.html
# The BUILD all option builds all dependencies from source every time
conan_cmake_install(PATH_OR_REFERENCE .
BUILD all
REMOTE conancenter
SETTINGS
${settings}
compiler.libcxx=libstdc++11
compiler.cppstd=20
)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
# find_package(Boost 1.77 REQUIRED COMPONENTS program_options REQUIRED)
add_executable(my_app main.cpp)
target_link_libraries(my_app CONAN_PKG::boost)
# We need C++ 20 activated with the concepts library
# target_compile_features(my_app PUBLIC cxx_std_20)
And then:接着:
$ mkdir build && cd build
$ cmake -D CMAKE_BUILD_TYPE=Release \
-D CMAKE_C_COMPILER=/usr/bin/gcc-10 \
-D CMAKE_CXX_COMPILER=/usr/bin/g++-10 \
..
$ cmake --build .
The price to pay is that we get a bit far from the Conan 2.0 way of doing things, that is calling:付出的代价是我们离柯南 2.0 的做事方式有点远,那就是调用:
conan_cmake_configure()
conan_cmake_autodetect()
conan_cmake_install()
find_package()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.