【问题标题】:Cmake build with extern libraires使用外部库构建 Cmake
【发布时间】:2022-01-07 03:53:08
【问题描述】:

我是手臂构造的初学者。 我想为 armel 平台构建此代码。 我有一个代码:

#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <nlohmann/json.hpp>
int main() 
{
    return 0;
}

我还有 Cmake 文件:

cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
project(test CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++-10)

set(SRC_FILES test.cpp)

add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY)
add_definitions(-DBOOST_SYSTEM_NO_DEPRECATED)
add_definitions(-DBOOST_ALL_NO_LIB)
add_definitions(-DBOOST_NO_RTTI)
add_definitions(-DBOOST_NO_TYPEID)
add_definitions(-DBOOST_ASIO_DISABLE_THREADS)

add_executable(${PROJECT_NAME} ${SRC_FILES})

我将 nlohmann 库安装到:

/usr/local/include/nlohmann/json.hpp

在我生成make和make之后:

/home/test-machine/project-dir/test/test.cpp:3:10: fatal error: nlohmann/json.hpp: No such file or directory
    3 | #include <nlohmann/json.hpp>
      |          ^~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/test.dir/build.make:82: CMakeFiles/test.dir/test.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/test.dir/all] Error 2
make: *** [Makefile:103: all] Error 2

为什么我有这个错误。请帮帮我!!!

【问题讨论】:

  • 非原生编译器一般默认不使用系统包含路径,可能需要指定/usr/local/include作为包含目录
  • 您可以通过使用命令“include_directories(/usr/local/include)”来做到这一点:cmake.org/cmake/help/latest/command/include_directories.html
  • 谢谢!我在真实代码上对其进行了测试,但我对 ld 有很多注意事项。我有这样的通知/usr/lib/gcc-cross/arm-linux-gnueabi/10/../../../../arm-linux-gnueabi/bin/ld: CMakeFiles/power-control.dir/src/power-control.cpp.o: in function `sdbusplus::bus::bus::process_discard()': power-control.cpp:(.text._ZN9sdbusplus3bus3bus15process_discardEv[_ZN9sdbusplus3bus3bus15process_discardEv]+0x98): undefined reference to `sdbusplus::exception::SdBusError::SdBusError(int, char const*, sdbusplus::SdBusInterface*) make 后没有 exec 文件。

标签: c++ linux cmake arm cross-compiling


【解决方案1】:

您的代码存在一些问题。如果你不介意我会使用更新的 CMake。

# CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(test LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(foobar)

target_sources(foobar PRIVATE
    test.cpp
)

target_compile_definitions(foobar PRIVATE
    BOOST_ERROR_CODE_HEADER_ONLY
    BOOST_SYSTEM_NO_DEPRECATED
    BOOST_ALL_NO_LIB
    BOOST_NO_RTTI
    BOOST_NO_TYPEID
    BOOST_ASIO_DISABLE_THREADS
)

要指定您的 ARM 编译器,请使用 CMAKE_TOOLCHAIN_FILE。如果您在 CMake 代码中指定编译器,一开始可能会很好,但以后会导致问题。

# arm.cmake

set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++-10)

set(CMAKE_C_COMPILER arm-linux-gnueabi-g-10)

现在,当您制作项目时,请执行以下操作:

cd <your-project>
cmake -S . -B build/ -D CMAKE_TOOLCHAIN_FILE=arm.cmake

现在您的代码存在的问题是您无法找到第三方依赖项。

您需要添加代码来查找/链接boost。并找到/链接nlohmann/json

提升

How do you add Boost libraries in CMakeLists.txt?

nlohmann/json

这个 repo 实际上有关于如何将库添加到 CMake 项目的非常好的文档。

https://github.com/nlohmann/json#cmake

TLDR:

要在 CMake 项目中使用此库,您可以直接使用 find_package() 找到它,并使用生成的包配置中的命名空间导入目标:

# CMakeLists.txt
find_package(nlohmann_json 3.2.0 REQUIRED)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)

【讨论】:

    【解决方案2】:

    使用非本机编译器,您必须配置整个环境。

    事实上,这样做时,我强烈建议使用toolchain file

    使用它你可以设置你的工具链,甚至是多个工具链。

    然后,对于环境,我建议使用它们的安装程序安装库并让 CMake 找到它。以 nlohmann json 为例:

    nlohmann_json$ mkdir build
    nlohmann_json$ cd build
    nlohmann_json/build$ cmake .. -DCMAKE_INSTALL_PREFIX=/home/youruser/arm-prefix -DCMAKE_TOOLCHAIN_FILE=yourtoolchain.cmake
    nlohmann_json/build$ cmake --build . --target install
    

    这些命令将使用您的工具链设置 nlohmann json,并将其安装在新前缀中。

    然后,在你的项目中,你可以有这样的工具链和这样的 CMakeLists.txt 文件:

    工具链.cmake:

    set(CMAKE_SYSTEM_NAME Linux)
    set(CMAKE_SYSTEM_PROCESSOR arm)
    set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++-10)
    set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc-10)
    set(CMAKE_STAGING_PREFIX /home/youruser/arm-prefix)
    set(CMAKE_SYSTEM_PREFIX_PATH /home/youruser/arm-prefix)
    
    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
    set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
    

    CMakeLists.txt:

    project(test CXX)
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    add_executable(test)
    
    find_package(nlohmann_json REQUIRED)
    
    target_sources(test PRIVATE test.cpp)
    target_link_libraries(test PUBLIC nlohmann_json::nlohmann_json)
    

    神奇之处在于前缀路径。当您设置安装前缀以安装库并在构建项目时设置相同的前缀路径时,find_package 突然起作用。如果您在这两个项目之间使用相同的工具链,则 CMake 将检测这两个包是否兼容。

    请注意,我也明确没有在 CMakeLists 文件中使用变量。这是因为变量是 CMake 的痛点,会导致意外行为。在普通的 CMake 文件中定义一个项目,它们的使用应该很少。

    另外,请远离add_definitionslink_directoriesinclude_directories 以及所有这些。 总是更喜欢target_compile_definitionstarget_link_librariestarget_include_directories 和其他基于目标的命令。


    至于 boost 我不太了解他们的构建系统。可能有交叉编译库并安装它的方法,但我的知识到此为止。

    【讨论】:

      【解决方案3】:

      在我看来,更正确的方法是正确安装库,然后使用find_package 指令。

      # CMakeLists.txt
      find_package(nlohmann_json 3.2.0 REQUIRED)
      ...
      add_library(foo ...)
      ...
      target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
      

      上面的例子是nlohmann Cmake documentation的一部分。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-09
        • 2016-11-02
        • 2021-12-25
        • 2021-09-30
        • 1970-01-01
        • 2023-04-07
        • 1970-01-01
        相关资源
        最近更新 更多