在嵌入式linux开发板上跑QT应用,不同于PC上的开发过程。最大的区别就是需要交叉编译,才能在板子上运行。 这里总结下嵌入式linux环境下使用CMake,嵌入式QT的CMake工程模板配置及如何使用,分享给有需要的小伙伴,有用到的可以点击收藏。
CMake简介
CMake 是一个项目构建工具,并且是跨平台的。关于项目构建我们所熟知的还有Makefile(通过 make 命令进行项目的构建),大多的IDE软件都集成了make,比如:VS 的 nmake、linux 下的 GNU make、Qt 的 qmake等,如果自己动手写 makefile,会发现makefile 通常依赖于当前的编译平台,而且编写 makefile 的工作量比较大,解决依赖关系时也容易出错。
而 CMake 恰好能解决上述问题, 其允许开发者指定整个工程的编译流程,在根据编译平台,自动生成本地化的Makefile和工程文件,最后用户只需make编译即可,所以可以把CMake看成一款自动生成 Makefile工具。而且一旦习惯了CMake,再也不想回到手写makefile的时代了。
cmake的编译流程,执行原理如下图所示:
环境准备
CMake安装
Download | CMake
linux下的cmake安装很简单。以ubuntu为例,可以直接sudo apt-get install cmake。当然也可以手工下载最新源码包来安装。这里选择了一种最简单的方式。
sudo apt-get install cmake
交叉编译工具链gcc
这个一般的开发板都会提供,这里不在详细介绍。
下面介绍下工具链的配置:
(目的是指定cmake使用的交叉编译工具链)(选项:DCMAKE_TOOLCHAIN_FILE)。
在项目根目录下新建个toolchains目录,在此目录下,参照其它开发板的配置文件,添加一个该开发板的工具链的配置文件 arm-poky-linux-gnueabi.cmake。
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER "arm-poky-linux-gnueabi-gcc")
set(CMAKE_CXX_COMPILER "arm-poky-linux-gnueabi-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_C_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon --sysroot=/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi")
set(CMAKE_CXX_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon --sysroot=/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi")# cache flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")
工程模板
新建个test项目文件夹,内部新建hello.cpp文件源码。
#include <QCoreApplication>
#include<QDebug>
#include <QDir>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "hello QT test";return a.exec();
}
首先我们要创建一个CMakeLists.txt文件,名称大小写一定不能错。
需要注意的是,在CMakeLists.txt文件中还需要添加以下行来设置OE_QMAKE_PATH_EXTERNAL_HOST_BINS变量。它的目的是为了找到qmake的位置。
因此可以设置如下:
set(QT_VERSION 5)
set(CMAKE_CROSSCOMPILING TRUE)
set(OE_QMAKE_PATH_EXTERNAL_HOST_BINS /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/x86_64-pokysdk-linux/usr/bin)
另外需要注意的是,需要配置CMAKE_PREFIX_PATH,它
是一个分号分隔的路径列表,用来指明软件/库安装路径前缀,以供find_package()
,find_program()
,find_library()
,find_file()
和find_path()
命令搜索使用,这样就方便搜索可执行文件、头文件、库文件及相关配置文件等。
可以在编译时,在命令行指定它,如:
#在项目根目录,cd build,先进入build目录
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-poky-linux-gnueabi.cmake -DCMAKE_PREFIX_PATH=/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/usr/lib/cmake ../
或者嫌它太长,可以写到CMakeLists.txt文件里写固定。
set(CMAKE_PREFIX_PATH "/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/usr/lib/cmake")
完整的CMakeLists.txt文件工程模板:
cmake_minimum_required(VERSION 3.12)project(helloqt)add_definitions(-D_ENABLE_LOGGING
)set(CMAKE_PREFIX_PATH "/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/usr/lib/cmake")set(BUILD_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../build_out)
get_filename_component(ABSOLUTE_PATH ${BUILD_DIRECTORY} ABSOLUTE)
set(BUILD_DIRECTORY ${ABSOLUTE_PATH})#################### QT dependencies ####################
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)set(QT_VERSION 5)
set(CMAKE_CROSSCOMPILING TRUE)
set(OE_QMAKE_PATH_EXTERNAL_HOST_BINS /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/x86_64-pokysdk-linux/usr/bin)set(REQUIRED_LIBS Core Quick Widgets)
set(REQUIRED_LIBS_QUALIFIED Qt5::Core Qt5::Quick Qt5::Widgets)#################### set output directory ####################
set(BUILD_DIR ${BUILD_DIRECTORY})
set(LIB_DIR ${BUILD_DIR}/lib/Release)
#set(LIB_FIX)
#if (CMAKE_BUILD_TYPE MATCHES "Debug")
# set(LIB_DIR ${BUILD_DIR}/lib/Debug)
# set(LIB_FIX _d)
#endif ()#get_filename_component(ABSOLUTE_PATH ${LIB_DIR} ABSOLUTE)
#set(LIB_DIR ${ABSOLUTE_PATH})set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIB_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIB_DIR})
set(CMAKE_PDB_OUTPUT_DIRECTORY ${LIB_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIB_DIR})#set(LIB_DIR_FIX ${LIB_DIR})
#option(USE_VS_BUILD "use visual studio build." OFF)
#if (USE_VS_BUILD)
# set(LIB_DIR_FIX ${LIB_DIR}/bin/Debug)
#endif ()
###########set include path ####################
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/${BUILD_DIR}/include
)#################### scan source files ####################
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/ SRC_FILES)
#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/source/cpp/test2 SRC_FILES)#set(SRC_LIST hello.c)#add library(libhello SHARED hello.c)
#set_target_properties(libhello PROPERTIES OUTPUT NAME "hello")
find_package(Qt${QT_VERSION} COMPONENTS ${REQUIRED_LIBS} REQUIRED)
#find_package(Qt5 COMPONENTS Widgets)add_executable(${PROJECT_NAME} ${SRC_FILES})
#target_link_libraries(hello libhello)#################### set target dependencies ####################set(THIRD_LIBS "")target_link_libraries(${PROJECT_NAME} PRIVATE ${REQUIRED_LIBS_QUALIFIED} ${THIRD_LIBS})
如何使用
执行以下命令即可。
#先加载环境变量
source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi #在项目根目录,cd build,先进入build目录
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-poky-linux-gnueabi.cmake ../
#执行make,开始编译
make
最后,编译成功!可以在嵌入式环境下愉快的使用cmake来编译qt的工程。
总结一下CMake的优点:
1.跨平台;
2.能够管理大型项目;
3.简化编译构建过程和编译过程;
4.可扩展:可以为 cmake 编写特定功能的模块,扩充 cmake 功能。
5.可以集成CI/CD,自动化构建与部属。
其他资源
cmake的使用_cmake使用-CSDN博客
cmake使用详细教程(日常使用这一篇就足够了)-CSDN博客
iMX6ULL QT环境配置 | CMake在Linux下的交叉编译环境搭建及使用-CSDN博客
https://www.cnblogs.com/Fitanium/p/16181605.html
什么是 CI/CD ?5分钟让你明白 - 知乎