簡體   English   中英

使用 cmake-conan 時鏈接 Boost

[英]Linking Boost when using cmake-conan

1 - 初始情況

問題描述

我正在嘗試使以下 CMake 項目正常工作:想法是使用cmake-conan讓 cmake 處理柯南安裝步驟(使用戶無需設置配置文件等)。

但是它無法鏈接到 Boost。

系統配置

  • Ubuntu 20.04.4 LTS
  • cmake 版本 3.23.2(通過 snap)
  • 柯南 1.49.0 版(通過虛擬環境)
  • gcc (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0
  • Python 3.8.10

最小的例子

# 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 .

在配置步驟 ( 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

我已經環顧了兩天,但找不到任何線索(盡管我學到了很多東西)。

2 - 進展

始終從源頭構建 Boost

根據評論中的討論,我更新了 CMake 文件以要求從源代碼構建依賴項。 conan.io/cmake-conan README 文檔指出,將BUILD missing替換為BUILD all應該可以工作:

BUILD (如果此參數采用all值,柯南將從源代碼構建所有內容)

所以我嘗試了一下,刪除了 bincrafters 引用,甚至嘗試將 Boost 版本降級到 1.77,或者使用conan remove "*" -s -b -f清理柯南緩存。 但我仍然以完全相同的鏈接錯誤結束。

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)

配置片段

在配置過程中,我收到了可疑/有趣的輸出。 我沒有足夠的知識知道他們是否可以成為解決方案的一部分,所以他們在這里:

/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'

也許最相關的是組件拼寫:

- 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

成功構建的解決方案是將默認生成器從 Ninja 更改為 CMake,即在調用conan_cmake_configure時將GENERATORS cmake_find_package替換為GENERATORS cmake 我不知道為什么!

這是成功的 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)

接着:

$ 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 .

付出的代價是我們離柯南 2.0 的做事方式有點遠,那就是調用:

  1. conan_cmake_configure()
  2. conan_cmake_autodetect()
  3. conan_cmake_install()
  4. find_package()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM