我有以下问题。我尝试使用 CMake 中构建的本机机制进行交叉编译。我准备了以下 toolchain.cmake 文件:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSROOT /tmp/filesystem)
set(tools /opt/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux/bin/arm-linux-gnueabihf)
set(CMAKE_C_COMPILER ${tools}-gcc)
set(CMAKE_CXX_COMPILER ${tools}-g++)
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)
并且在目标
CMakeList.txt
中使用:
set(CMAKE_AUTOMOC ON)
我希望当我使用
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
设置为 NEVER
时,根据文档,CMake 将使用 HOST
中的 moc:
如果设置为 NEVER,则 CMAKE_FIND_ROOT_PATH 中的根将是 忽略,仅使用主机系统根目录。
但是它仍然尝试使用来自
TARGET
手臂图像 rootfs 的 moc。
我尝试重新找到 moc 可执行文件,就像这篇文章的第一个答案中一样:如何使用 CMake 包含某个 Qt 安装?但没有运气。
我还尝试将
QT_MOC_EXECUTABLE
变量设置为来自 HOST
rootfs 的正确路径,而不是 TARGET
变量,但也没有运气。我认为当 CMAKE_AUTOMOC
设置为 ON
时,CMake 不会使用此变量,因为在强制更改此缓存变量后,cmake 仍然使用来自 TARGET
rootfs 的 moc。
有什么想法可以解决这个问题吗?
#编辑1
我发现automoc在build文件夹中生成了这样的文件:
CMakeFiles/*target_name*_automoc.dir/AutogenInfo.cmake
在我的例子中,此类变量设置为错误的路径:
set(AM_QT_MOC_EXECUTABLE "/tmp/filesystem/usr/lib/arm-linux-gnueabihf/qt5/bin/moc")
应该是:
set(AM_QT_MOC_EXECUTABLE "/usr/bin/moc")
我将
AM_QT_MOC_EXECUTABLE
设置为 main CMakeList.txt
中的正确值,但仍然在使用来自 TARGET
rootfs 的错误路径生成了上述文件之后。
由于这篇文章,我终于找到了解决方案:How can I use CMake's AUTOMOC feature with a custom Qt package?。正如我假设
QT_MOC_EXECUTABLE
不直接由 AUTOMOC
使用。
在第一个 qt 之前
find_package
必须添加以下行:
set(QT_MOC_EXECUTABLE /usr/bin/moc)
add_executable(Qt5::moc IMPORTED)
set_property(TARGET Qt5::moc PROPERTY IMPORTED_LOCATION ${QT_MOC_EXECUTABLE})
这里的问题是,不仅变量
QT_MOC_EXECUTABLE
必须设置为正确的值,而且最终 automoc 仅使用 Qt5:moc
目标,必须在任何 qt 包包含在 CMakeList.txt
文件中之前声明该目标。
其他 qt 工具也存在同样的问题,因此更通用的选项是:
file(GLOB Qt_bin /usr/bin)
find_program(QT_MOC_EXECUTABLE qt_moc moc PATHS ${Qt_bin})
add_executable(Qt5::moc IMPORTED)
set_property(TARGET Qt5::moc PROPERTY IMPORTED_LOCATION ${QT_MOC_EXECUTABLE})
我在 Qt6 交叉编译中遇到了同样的问题,并将尝试提供一些关于新的 https://doc.qt.io/qt-6/cmake-variable-qt-host-path.html 的见解和QT_HOST_PATH_CMAKE_DIR 在定位主机工具(如 moc/rcc)的上下文中需要交叉编译。
简短的回答,确保QT_HOST_PATH指向native_sysroot,另外QT_HOST_PATH_CMAKE_DIR指向native_sysroot的cmake目录,其中安装了qt_host_tools(如Qt6CoreTools)。
如果您有兴趣了解更多见解。
正如所描述的,toolchain.cmake 指示 cmake 仅在目标 sysroot 中搜索 XXXConfig.cmake 文件。
set(CMAKE_SYSROOT /tmp/filesystem)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
对于 qt_host_tools(包括 Qt6CoreTools),配置将位于您的 native_sysroot 上的某个位置。 因此,Qt6 让 CMake 寻找主机工具而不弄乱整个其他包的魔力位于 QtPublicDependencyHelpers.cmake
set(BACKUP_${target}_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH})
set(BACKUP_${target}_CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH})
list(PREPEND CMAKE_PREFIX_PATH "${QT_HOST_PATH_CMAKE_DIR}"
"${_qt_additional_host_packages_prefix_paths}")
list(PREPEND CMAKE_FIND_ROOT_PATH "${QT_HOST_PATH}"
"${_qt_additional_host_packages_root_paths}")
临时切换 CMAKE_FIND_ROOT_PATH 以在主机上查找包。