我有以下文件。
#include <cstdlib>
set(CMAKE_MINIMUM_VERSION 3.8)
cmake_minimum_required(VERSION ${CMAKE_MINIMUM_VERSION})
find_package(GTest REQUIRED)
set(gtest_test gtest-test)
add_executable(${gtest_test} empty.cc)
#target_link_libraries(${gtest_test} ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) # Line A
target_link_libraries(${gtest_test} GTest::GTest GTest::Main) # Line B
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 4.14.0)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER /opt/zynq/xtl/bin/arm-linux-musleabihf-gcc)
set(CMAKE_CXX_COMPILER /opt/zynq/xtl/bin/arm-linux-musleabihf-g++)
set(CMAKE_SYSROOT /opt/zynq/xtl/arm-linux-musleabihf)
set(CMAKE_FIND_ROOT_PATH /opt/zynq/xtl/arm-linux-musleabihf)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER)
set(CMAKE_INSTALL_PREFIX /opt/zynq/xtl/arm-linux-musleabihf)
我使用以下方法构建它:
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake .. && make VERBOSE=1 -j
当我使用GTest
(即Line A
链接到target_link_libraries(${gtest_test} ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
时,一切正常。但是,当我使用Line B
即target_link_libraries(${gtest_test} GTest::GTest GTest::Main)
时,出现以下错误:
/opt/zynq/xtl/bin/arm-linux-musleabihf-g++ --sysroot=/opt/zynq/xtl/arm-linux-musleabihf -isystem /opt/zynq/xtl/arm-linux-musleabihf/include -o CMakeFiles/gtest-test.dir/empty.cc.o -c /home/xxx/git/cmake/cmake-with-gtest/empty.cc
In file included from /home/xxx/git/cmake/cmake-with-gtest/empty.cc:1:
/opt/zynq/xtl/arm-linux-musleabihf/include/c++/8.3.0/cstdlib:75:15: fatal error: stdlib.h: No such file or directory
#include_next <stdlib.h>
^~~~~~~~~~
compilation terminated.
CMakeFiles/gtest-test.dir/build.make:62: recipe for target
'CMakeFiles/gtest-test.dir/empty.cc.o' failed
make[2]: *** [CMakeFiles/gtest-test.dir/empty.cc.o] Error 1
g++
版本
...$ /opt/zynq/xtl/bin/arm-linux-musleabihf-g++ --version
arm-linux-musleabihf-g++ (GCC) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
正常构建(即不交叉编译)可以很好地使用其中一种
target_link_libraries(${gtest_test} ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) # Line A
或
target_link_libraries(${gtest_test} GTest::GTest GTest::Main) # Line B
为什么使用一种链接方式会导致缺少标题,而另一种却能正常工作?
答案 0 :(得分:0)
众所周知,对于标准编译器使用-isystem
包含目录中断#include_next
伪指令,该伪指令广泛用于标准C ++头文件。参见例如这个问题:-isystem on a system include directory causes errors。
CMake具有一种过滤标准编译器包含目录的机制,该机制使用变量CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES作为需要过滤的包含目录的列表。不幸的是,编译器无法自动检测到此列表(请参见已关闭的错误报告:https://gitlab.kitware.com/cmake/cmake/issues/16291)。而是将目录/usr/include
(相对于sysroot)添加到该列表中。
由于在您的工具链编译器中,include目录不是/usr/include
而是/include
,因此您需要将该目录明确地添加到例外列表中:
# in toolchain.cmake
list(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_SYSROOT}/include)
# Setting the exclude directory for C compiler is optional:
# C standard headers rarely use `#include_next` directive
list(APPEND CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_SYSROOT}/include)
之间的差异
target_link_libraries(${gtest_test} ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) # Line A
和
target_link_libraries(${gtest_test} GTest::GTest GTest::Main) # Line B
是Line B
使用目标名称进行链接,并且与该目标关联的include目录会自动添加到可执行文件中。这就是为什么您获得-isystem
。
第二种方式(Line B
)被视为“现代”方式,建议在新编写的代码中使用。但是两种方法都可以。