4.Linux下Cmake交叉编译Qt项目到Jetson Orin Nano(arm)

这篇具有很好参考价值的文章主要介绍了4.Linux下Cmake交叉编译Qt项目到Jetson Orin Nano(arm)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

由于3:Ubuntu上配置QT交叉编译环境并编译QT程序到Jetson Orin Nano(ARM)_月上林梢的博客-CSDN博客

 这一篇文章只用手动配置,一直在点、点、点。比较 LOW,现在在Ubuntu上使用Cmake实现交叉编译QT程序到Jetson Orin Nano上。

提醒:

我的工作环境是Visual Studio+QT+arm由于Ubuntu下没有Visual studio 只能在Ubuntu上创建对应的文件,通过CMake的方式对VS+QT项目进行交叉编译,然后在ARM(Jetson Orin Nano)上进行程序,具体过程如下:

注:

在此文中 Ubuntu,Jetson Orin Nano 上的QT环境不再赘述,请看以往文章,进行配置相关的编译环境。

1.创建文件

4.Linux下Cmake交叉编译Qt项目到Jetson Orin Nano(arm),Jetson Orin Nano,linux,qt,arm开发,Jetson,Linux下Cmake交叉编译

 文章来源地址https://www.toymoban.com/news/detail-661010.html

需要创建的文件有

arm_linux_setup.cmake用于存放arm交叉编译工具位置,具体内容如下:

cmake_minimum_required(VERSION 3.15)#用于设定需要的最低版本的CMake
## include_guard([DIRECTORY|GLOBAL])
#为CMake当前正在处理的文件提供包含保护,可选参数指定保护的范围:
#DIRECTORY:include guard适用于当前目录及以下子目录。该文件只会在该目录范围内包含一次,但可能会被该目录以外的其他文件再次包含(即父目录或其他目录,而不是由当前文件或其子目录中的add_subdirectory()或include()拉入)。
#GLOBAL:include guard适用于整个构建。无论范围如何,当前文件只包含一次。
include_guard(GLOBAL)
## CMAKE_SYSTEM_NAME 交叉编译的必设参数,只有当CMAKE_SYSTEM_NAME这个变量被设置了,CMake才认为此时正在交叉编译,它会额外设置一个变量CMAKE_CROSSCOMPILING为true.
set(CMAKE_SYSTEM_NAME Linux)
#CMAKE_SYSTEM_PROCESSOR的可选值大多数情况下可以使用命令 uname -m 查看
set(CMAKE_SYSTEM_PROCESSOR arm)
#设置 变量TARGET_SYSROOT为/opt/Qt5JetsonOrinNano/sysroot   /opt/Qt5JetsonOrinNano/sysroot为 同步arm上的库文件
set(TARGET_SYSROOT /opt/Qt5JetsonOrinNano/sysroot)
# CROSS_COMPILER 交叉编译工具的目录
set(CROSS_COMPILER /usr/bin)
#CMAKE_SYSROOT 一般设置为工具链的sysroot目录,CMAKE_STAGING_PREFIX可以设置为我们自定义的根文件系统目录,里面已安装之前编译的一些库及头文件,这样cmake可以从这两个目录中找到相关依赖。
set(CMAKE_SYSROOT ${TARGET_SYSROOT})
# c和C++的交叉编译工具
set(CMAKE_C_COMPILER ${CROSS_COMPILER}/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILER}/aarch64-linux-gnu-g++)
# 下面用不到  
## CMake变量CMAKE_FIND_ROOT_PATH指定了一个或者多个优先于其他搜索路径的搜索路径。该变量能够有效地重新定位在给定位置下进行搜索的根路径。该变量默认为空。当使用交叉编译时,该变量十分有用:用该变量指向目标环境的根目录,然后CMake将会在那里查找。默认情况下,在CMAKE_FIND_ROOT_PATH中列出的路径会首先被搜索,然后是“非根”路径。该默认规则可以通过设置CMAKE_FIND_ROOT_PATH_MODE_LIBRARY做出调整。在每次调用该命令之前,都可以通过设置这个变量来手动覆盖默认行为。如果使用了NO_CMAKE_FIND_ROOT_PATH变量,那么只有重定位的路径会被搜索。
## 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 `文件内容

# 标注最低版本
cmake_minimum_required(VERSION 3.15)

# 设置项目名称
project(demo)

# 设置C++标准 C++11
set(CMAKE_CXX_STANDARD 11)

# 自动把ui转化为C++代码
# uic qtcmake.ui > ui_qtcmake.h
set(CMAKE_AUTOUIC ON)

# 自动生成元对象的C++代码
set(CMAKE_AUTOMOC ON)

# 自动生成资源文件
set(CMAKE_AUTORCC ON)

# 在项目中加入需要编译的文件
add_executable(${PROJECT_NAME}
    main.cpp
    #res.qrc 资源文件 有的话加上,没有则不用加
    mywidget.cpp 
    mywidget.h
    mywidget.ui
)

# 根据自己电脑的环境,写死的指定Qt5_DIR这个变量
# 目的是寻找 Qt5Config.cmake 这个文件
set(Qt5_DIR /opt/Qt5JetsonOrinNano/sysroot/usr/local/Qt5JetsonOrinNano/lib/cmake/Qt5/)

# find_package 查找内部库
# 导入qt的库
# cmake通过qt5提供的查找方案,去查找对应的库
# 这里以查找 Widgets库 为例
find_package(Qt5 COMPONENTS Widgets REQUIRED PATHS /opt/ NO_DEFAULT_PATH)


# 指定qt依赖的动态库
# Qt5 自带连接头文件
target_link_libraries(${PROJECT_NAME}
    Qt5::Widgets
)

main.cpp文件

#include "mywidget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    mywidget w;
    w.show();
    return a.exec();
}

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"

mywidget::mywidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::mywidget)
{
    ui->setupUi(this);
}

mywidget::~mywidget()
{
    delete ui;
}

`mywidget.h`

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class mywidget; }
QT_END_NAMESPACE

class mywidget : public QWidget
{
    Q_OBJECT

public:
    mywidget(QWidget *parent = nullptr);
    ~mywidget();

private:
    Ui::mywidget *ui;
};
#endif // MYWIDGET_H+

mywidget.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>mywidget</class>
 <widget class="QWidget" name="mywidget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>mywidget</string>
  </property>
  <widget class="QPushButton" name="pushButton">
   <property name="geometry">
    <rect>
     <x>230</x>
     <y>130</y>
     <width>80</width>
     <height>23</height>
    </rect>
   </property>
   <property name="text">
    <string>demo</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

2. 编译

进入到build目录下进行编译

cd build 
# -DCMAKE_TOOLCHAIN_FILE指定工具链文件
sudo cmake -DCMAKE_TOOLCHAIN_FILE=../arm_linux_setup.cmake ..
# 输出的log如下
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/aarch64-linux-gnu-gcc
-- Check for working C compiler: /usr/bin/aarch64-linux-gnu-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/aarch64-linux-gnu-g++
-- Check for working CXX compiler: /usr/bin/aarch64-linux-gnu-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/tanglin/cmake/build
ls
#执行上面命令之后会产生下面4个文件
CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile
#执行sudo make 命令
sudo make 
## 输出的log 如下
Scanning dependencies of target demo_autogen
[ 20%] Automatic MOC and UIC for target demo
[ 20%] Built target demo_autogen
Scanning dependencies of target demo
[ 40%] Building CXX object CMakeFiles/demo.dir/demo_autogen/mocs_compilation.cpp.o
[ 60%] Building CXX object CMakeFiles/demo.dir/main.cpp.o
[ 80%] Building CXX object CMakeFiles/demo.dir/mywidget.cpp.o
[100%] Linking CXX executable demo
[100%] Built target demo
#查看输出
ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  demo  demo_autogen  Makefile
#demo 就是上面CMakeLists.txt中设置的项目名称,查看demo的文件类型
file demo
##输出内容如下,ARM aarch64 就是我们需要的文件
demo: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=a5d0d1dd4e080e68a28392423e1ce419cee55042, for GNU/Linux 3.7.0, not stripped
#把内容拷贝到arm机器上并运行
scp ./demo  nvidia@armIP:/tmp

3. 效果

在arm机器上打开刚才生成的文件

./demo

4.Linux下Cmake交叉编译Qt项目到Jetson Orin Nano(arm),Jetson Orin Nano,linux,qt,arm开发,Jetson,Linux下Cmake交叉编译

 

4.时钟例子

按照上面方法完成一个时钟demo,具体代码如下(这个demo没有UI文件):

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

`widget.cpp`

#include "widget.h"
#include<QPainter>
#include<QTimer>
#include<QTime>
#include<QString>
#include<QVector>
#include<QMap>

#define CLOCK_RADIUS (80) //时钟的半径
#define PANEL_RADIUS_NUM (3) //表盘的3个圆
#define PANEL_RADIUS1 CLOCK_RADIUS //圆1的半径
#define PANEL_RADIUS2 (CLOCK_RADIUS - 6) //圆2的半径
#define PANEL_RADIUS3 (CLOCK_RADIUS - 8) //圆3的半径
#define HOUR_NUM_SIZE (10) //小时数字的字体大小

//3个表针的形状(三角形)
static QPoint hourHand[3] = {
    QPoint(5, 3),
    QPoint(-5, 3),
    QPoint(0, -30)
};
static QPoint minuteHand[3] = {
    QPoint(4, 6),
    QPoint(-4, 6),
    QPoint(0, -45)
};
static QPoint secondHand[3] = {
    QPoint(2, 10),
    QPoint(-2, 10),
    QPoint(0, -60)
};

//表针与刻度颜色
static QColor hourColor(255, 0, 0);
static QColor minuteColor(0, 0, 255);
static QColor secondColor(0, 255, 0);

//表盘参数
struct panelPara{
    int radius;
    QColor color;
};
//圆的半径与对于的颜色
static panelPara stPanelParaArr[] = {
    {PANEL_RADIUS1, QColor(255, 200, 100)},
    {PANEL_RADIUS2, QColor(164, 211, 238)},
    {PANEL_RADIUS3, QColor(255, 255, 255)},
};

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(1000);

    setWindowTitle(tr("Clock"));
    setMinimumSize(200, 200); //设置最小尺寸
}

Widget::~Widget()
{

}


void Widget::paintEvent(QPaintEvent *event)
{
    int side = qMin(width(), height());
    QTime time = QTime::currentTime();

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.translate(width()/2, height()/2); //画图的基准位置
    painter.scale(side/200.0, side/200.0); //随窗口尺寸自动缩放

    //表盘
    for (int i=0; i<PANEL_RADIUS_NUM; i++)
    {
        QBrush brush(stPanelParaArr[i].color);
        QPen pen(stPanelParaArr[i].color);
        painter.setBrush(brush);
        painter.setPen(pen);
        painter.drawEllipse(-stPanelParaArr[i].radius, -stPanelParaArr[i].radius, 2*stPanelParaArr[i].radius, 2*stPanelParaArr[i].radius);
    }

    //小时的表针
    painter.setPen(Qt::NoPen);
    painter.setBrush(hourColor);

    painter.save();
    painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
    painter.drawConvexPolygon(hourHand, 3);
    painter.restore();

    //小时的刻度
    painter.setPen(hourColor);
    for (int i = 0; i < 12; ++i)
    {
        painter.rotate(30.0);
        painter.drawLine(PANEL_RADIUS3-6, 0, PANEL_RADIUS3, 0);
        QFont font("TimesNewRoman", HOUR_NUM_SIZE);
        painter.setFont(font);
        painter.drawText(-HOUR_NUM_SIZE, -(CLOCK_RADIUS-15), 2*HOUR_NUM_SIZE, 2*HOUR_NUM_SIZE, Qt::AlignHCenter, QString::number(i+1));
    }

    //分钟的表针
    painter.setPen(Qt::NoPen);
    painter.setBrush(minuteColor);

    painter.save();
    painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
    painter.drawConvexPolygon(minuteHand, 3);
    painter.restore();

    painter.setPen(minuteColor);
    for (int j = 0; j < 60; ++j)
    {
        if ((j % 5) != 0)
        {
            painter.drawLine(PANEL_RADIUS3-4, 0, PANEL_RADIUS3, 0);
        }
        painter.rotate(6.0);
    }

    //秒钟的表针
    painter.setPen(Qt::NoPen);
    painter.setBrush(secondColor);

    painter.save();
    painter.rotate(6.0 * time.second());
    painter.drawConvexPolygon(secondHand, 3);
    painter.restore();

    painter.end();
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void paintEvent(QPaintEvent *event);
};

#endif // WIDGET_H

CMakeLists.txt

# 标注最低版本
cmake_minimum_required(VERSION 3.15)

# 设置项目名称
project(clock)

# 设置C++标准 C++11
set(CMAKE_CXX_STANDARD 11)

# 自动把ui转化为C++代码
# uic qtcmake.ui > ui_qtcmake.h
set(CMAKE_AUTOUIC ON)

# 自动生成元对象的C++代码
set(CMAKE_AUTOMOC ON)

# 自动生成资源文件
set(CMAKE_AUTORCC ON)

# 在项目中加入需要编译的文件
add_executable(${PROJECT_NAME}
    main.cpp
    widget.cpp 
    widget.h
)

# 根据自己电脑的环境,写死的指定Qt5_DIR这个变量
# 目的是寻找 Qt5Config.cmake 这个文件
set(Qt5_DIR /opt/Qt5JetsonOrinNano/sysroot/usr/local/Qt5JetsonOrinNano/lib/cmake/Qt5/)

# find_package 查找内部库
# 导入qt的库
# cmake通过qt5提供的查找方案,去查找对应的库
# 这里以查找 Widgets库 为例
find_package(Qt5 COMPONENTS Widgets REQUIRED PATHS /opt/ NO_DEFAULT_PATH)


# 指定qt依赖的动态库
# Qt5 自带连接头文件
target_link_libraries(${PROJECT_NAME}
    Qt5::Widgets
)

arm_linux_setup.cmake

cmake_minimum_required(VERSION 3.15)#用于设定需要的最低版本的CMake
## include_guard([DIRECTORY|GLOBAL])
#为CMake当前正在处理的文件提供包含保护,可选参数指定保护的范围:
#DIRECTORY:include guard适用于当前目录及以下子目录。该文件只会在该目录范围内包含一次,但可能会被该目录以外的其他文件再次包含(即父目录或其他目录,而不是由当前文件或其子目录中的add_subdirectory()或include()拉入)。
#GLOBAL:include guard适用于整个构建。无论范围如何,当前文件只包含一次。
include_guard(GLOBAL)
## CMAKE_SYSTEM_NAME 交叉编译的必设参数,只有当CMAKE_SYSTEM_NAME这个变量被设置了,CMake才认为此时正在交叉编译,它会额外设置一个变量CMAKE_CROSSCOMPILING为true.
set(CMAKE_SYSTEM_NAME Linux)
#CMAKE_SYSTEM_PROCESSOR的可选值大多数情况下可以使用命令 uname -m 查看
set(CMAKE_SYSTEM_PROCESSOR arm)
#设置 变量TARGET_SYSROOT为/opt/Qt5JetsonOrinNano/sysroot   /opt/Qt5JetsonOrinNano/sysroot为 同步arm上的库文件
set(TARGET_SYSROOT /opt/Qt5JetsonOrinNano/sysroot)
# CROSS_COMPILER 交叉编译工具的目录
set(CROSS_COMPILER /usr/bin)
#CMAKE_SYSROOT 一般设置为工具链的sysroot目录,CMAKE_STAGING_PREFIX可以设置为我们自定义的根文件系统目录,里面已安装之前编译的一些库及头文件,这样cmake可以从这两个目录中找到相关依赖。
set(CMAKE_SYSROOT ${TARGET_SYSROOT})
# c和C++的交叉编译工具
set(CMAKE_C_COMPILER ${CROSS_COMPILER}/aarch64-linux-gn

效果

4.Linux下Cmake交叉编译Qt项目到Jetson Orin Nano(arm),Jetson Orin Nano,linux,qt,arm开发,Jetson,Linux下Cmake交叉编译

 

到了这里,关于4.Linux下Cmake交叉编译Qt项目到Jetson Orin Nano(arm)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【NVIDIA】Jetson Orin Nano系列:安装 Qt6、firefox、jtop、flameshot

    qtcreator 直接使用 sudo apt install firefox 安装时,会使用snap来安装,经常因为网络不好而卡死,下面使用官方的源来安装deb版本的firefox 注意:不要使用 sudo apt install 安装 jtop,要使用pip3来安装

    2024年01月23日
    浏览(36)
  • 使用CMake交叉编译Arm Linux程序

    注意,工具链文件的指定一定要紧跟cmake命令之后,不能放到 … 后面构建arm架构cmake 工程里新建一个文件叫arm_linux_setup.cmake arm_linux_setup.cmake内容如下

    2024年02月03日
    浏览(39)
  • QT配置arm-linux-g++交叉编译器

    ubuntu16.4版本虚拟机 qt5.12.9版本 ,qt-everywhere-src-5.12.9(版本要一致,没试过版本不同是否可行) (qt5.15.2 qt5.14.2都装了下,按照以下流程都是完全没错误) arm-linux-g++4.8.3版本 由于最近接手公司离职员工的代码,通常我个人都是直接写Makefile来完成,对方用的Qt配合交叉编译器

    2024年01月19日
    浏览(38)
  • 【适用于Jetson Orin Nano的录屏软件】

    适用于Jetson Orin Nano的录屏软件kazam,亲测好用!

    2024年02月02日
    浏览(39)
  • Linux-Arm环境下配置编译qt-everywhere及交叉编译环境

    最近在搞交叉编译的事,手上拿了个同事的香橙派玩交叉编译,现在来到了第一步,就是先在arm上配置qt的开发环境。当然了Qt没有直接提供qt on arm,而是需要自行在arm环境下编译一个qt环境出来,所以这里需要使用到qt提供的qt everywhere套件在板载系统上编译 移植Qt到ARM平台及

    2024年04月11日
    浏览(38)
  • jetson-nano编译qt5.15.2带opengl,xcb

    项目需求原因,需要编译高版本qt到jetson-nano板子,历经10天来回折腾,终于是成功了。期间历经交叉编译失败,然后转直接编译,然后尝试各种版本的坑,最后整理的方法异常简单,只需6小时左右即可流畅在板子上编译成功。文章最后有我编译好的qt-5.15.2版本链接。 友情提

    2023年04月09日
    浏览(38)
  • Jetson Orin arm64架构搭建手写AI tensorRT_Pro项目环境

      tensorRT是nvidia发布的dnn推理引擎,是针对nvidia系列硬件进行优化加速,实现最大程度的利用GPU资源,提升推理性能。   手写AI:tensorRT_Pro项目是在tensorRT的基础上,提出的一套从onnx( pytorch etc.)到TRT Engine模型推理的解决方案。   但是该方案目前主要支持的是linux x86_6

    2024年02月15日
    浏览(350)
  • ubuntu22.04@Jetson Orin Nano之OpenCV安装

    昨天用Jetson跑demo程序发现帧率很慢(只有10FPS左右),按照视频文件怎么说应该有30FPS。但是为什么jetson orin nano跑不起来呢??? dnn_object_detection_embedded_device 想着,估计是GPU没有跑起来,正好凑着调试了下板子,记录、整理下资料。 从现象上看,OpenCV运行的时候没有跑GPU,从

    2024年02月21日
    浏览(35)
  • Jetson Orin Nano 使用OpenCV调用USB摄像头

    Jetson Orin Nano 8G ubuntu 20.04 检查usb摄像头是否被识别到 或者 Jetson Orin Nano 使用OpenCV调用USB摄像头

    2024年01月21日
    浏览(53)
  • Jetson Orin Nano使用OpenCV获取视频帧率和帧数的方法

    首先确认下视频的播放时间 使用cv库来获取帧率和帧数,测试代码如下 python3运行结果,30fps,总帧数807 计算验证,fps含义,多少帧frame每秒,视频的时间就等于总帧数/fps,807/30=26.9s,符合我们最开始看到的视频时间 Jetson Orin Nano使用OpenCV获取视频帧率和帧数的方法

    2024年01月21日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包