<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Home on hbb&#39;s blog</title>
    <link>/</link>
    <description>Recent content in Home on hbb&#39;s blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sun, 15 Feb 2026 12:00:00 +0800</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>claude_code笔记</title>
      <link>/post/claude_code%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Sun, 15 Feb 2026 12:00:00 +0800</pubDate>
      
      <guid>/post/claude_code%E7%AC%94%E8%AE%B0/</guid>
      <description>claude code 笔记 2016/2/19 更新本地在claude code中使用自己部署的 code tool llm 以下记录一些本人使用技巧,不定时更新
入门 /terminal-setup 方便shift + 加回在终端中换行
/init 初始化claude.md ,初步分析项目结构
#空格xxx 回车, xxx将被记录到claude.md ,
./claude.local.md 优先级最高, 慢慢会被弃用
./claude.md
~/.claude.md 优先级最低
/memory 可以直接编辑claude.md添加条目
/model选择模型 , opus 很消耗token, 普通任务不用作用opus
@文件名选择, 方向键选择,按下shift确定候选条目, 让claude知道上下文位置
如果在vscode中用claude扩展, 可以打开文件选中, 会自动添加上下文件
上下文件可以通过@xx:行号-等号 或在vs code中选中多行来指定更具体的位置
@符号也在claude.md中,让memory 知道上下文
做ui时,可以拖拽一个效果图片到终端, 然后@出某个代码中已存在的按钮,让修改
一次对话中上下文太多可能在无意中引用他们,导致输出效果不好
/exit 退出对话,再用claude命令重新打开命令 如果不退出对话 /clear 清除对话历史,和上下文,基本上和 /exit 重开对话效果一样 /compact 压缩对话历史和上下文, 对话很长时仍然有风险 按两次esc ,回溯到某个对话历史,删除后面的对话和上下文 /resume 如果在新会话中想恢复之前关闭的对话的上下文, /permissions 权限相关:如果在交互中选择了,是的并不再提问, 会保存配置到./.claude/setting.local.json
计划模式, /plan 或 ctrl+ tab 切换模式</description>
    </item>
    
    <item>
      <title>play-bittle-with-ros2-isaaclab-isaacsim</title>
      <link>/post/play-bittle-with-ros2-isaaclab-isaacsim/</link>
      <pubDate>Sat, 24 Jan 2026 12:51:56 +0800</pubDate>
      
      <guid>/post/play-bittle-with-ros2-isaaclab-isaacsim/</guid>
      <description>_ 2025.11 - 2025结束这段时间,跳槽到具身智能行业, 在同事的引导下摸索着自定义usd schema, 并使用非侵入的方式修改isaac sim的physX插件, 支持从UI上对USD scene中的prim增删自定义的schema api, 修改schema属性.
下一阶段的目标是在isaac lab上尝试替换物理引擎进行rl 训练
为了更快的适应工作要求,我给自己设定了一个快速入门的计划, 通过训练一个自己的机器人模型,来学习工作所需要的技能
本博客将围绕bittle 4足机器狗 记录
isaaclab 中训练 (平坦地面,4096个仿真环境 2000个迭代训练量, 4090 D大概10分钟左右即可) isaacsim 中推理 (在Ros2使用ps5手柄控制,发消息到仿真环境的Ros2节点,控制仿真世界的bittle) sim2sim (从physX 物理引擎转换到 其他物理引擎验证模型泛化能力) sim2real (通过模型蒸馏, 去除现实世界中不方便采样的数据,以及添加真实世界的6轴陀螺仪传感器) 本文不会介绍rl 和 infer的具体细节,但会提供代码,操作步骤,
尝试探索代码,优化代码,这样才会有所收获
计划常常在随着工作,目标,兴趣 调整, 不保证能做完, 但是有完成,我都会更新博客(否则岂不是做了个寂寞)
0. Bittle bittle是一款比较成熟的学习用的机器狗, 4条腿每条腿有两个自由度,还有脖子一个,共有9个自由度,不过训练行走的话,脖子可以简略,视作8个dof.
他有一个第三方的逆向建模, 但有一些小问题, 右边肢体的关节方向与左边不一样
我做了一些调整,统一所有肢体的行为, 使其关节角度为负时,向前抬起肢体,
除此之外,还修改了关节的名称, 把关节名称按 左右(L/R),关节位置(Front / Hind), 关节名称(Hip/Knee),关节行为(Flexion-Extention/Abduction- Adduction) 重命名
由于Bittle没有向外侧扩张/合拢的关节(HAA),所以没有办法走螃蟹步,修改后的8个关节名称为
LF_HFE (左前,髋关节,伸屈) LH_HFE &amp;hellip; RF_HFE &amp;hellip; RH_HFE &amp;hellip; LF_KFE &amp;hellip; LF_KFE &amp;hellip; RF_KFE &amp;hellip; RH_KFE (右后,膝关节,伸屈) 如果想购买Bittle, 需要注意他有ardiuno版本和esp32版本, 其中ardiuno版本不支持读取关节角度</description>
    </item>
    
    <item>
      <title>在nvidia_omniverse_app中加载c&#43;&#43;_qt_qml插件</title>
      <link>/post/%E5%9C%A8nvidia_omniverse_app%E4%B8%AD%E5%8A%A0%E8%BD%BDc-_qt_qml%E6%8F%92%E4%BB%B6/</link>
      <pubDate>Sat, 20 Dec 2025 12:51:56 +0800</pubDate>
      
      <guid>/post/%E5%9C%A8nvidia_omniverse_app%E4%B8%AD%E5%8A%A0%E8%BD%BDc-_qt_qml%E6%8F%92%E4%BB%B6/</guid>
      <description>接上文 好久没写博客了, 5月份-11月份一直在研究react native , ts和cpp hybrid的mvvm
从一开始的app单个工程,到后面的npm模块化, 在11月份勉强画上句号
国庆前经恒星和银狼介绍,投了他们仿真团伙UI岗位,原计划qt6 + vulkan写一个仿真软件.
(感谢他们,新的工作环境比以前好得多, 新的工作也是每天在探索无人区,充满新鲜感
​ 希望新的公司可以干趴其他竞争对手,也希望自己可以在新的行业有所成长
入职前狠狠的研究了一把qt6 + vulkan
封装了vulkan 的qml控件;把我的prism for qt mvvm框架从qt5切到qt6 修复了热重载 / native无边框窗口
不过计划总是赶不上变化,入职后变成基于nvidia omniverse的二开了
就像在岸上走的人突然掉入水中, 第一件事就是努力爬到岸上去
所以我当时也试图把qt搬到omniverse app 的python世界里, 随着目标越来越清晰, qt方案已经放弃了
但是那段时间积累了一些经验, 还是觉得需要记录一下 ,防止未来还会遇到在python中调用qt c++ plugin 的场景
创建qt qml c++ plugin 本文不介绍如何封装自定义接口的qt 插件,
简而言之就是定义一个接口, 然后在动态库中定义,实现继承接口的类 , 在app中实例化类以调用
安装qt和pyside版本 从license 方面来看 pyqt的开源协议为具有左传染的GPL, pyside 是LGPL, pyside胜
从兼容方面来看, pyqt的qobject 和c++ qt 的qobject不兼容, pyside 则是兼容的, 还是pyside胜
所以选择pyside
我安装的qt 6是 6.</description>
    </item>
    
    <item>
      <title>react_native笔记</title>
      <link>/post/react_native%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Sun, 18 May 2025 12:48:29 +0800</pubDate>
      
      <guid>/post/react_native%E7%AC%94%E8%AE%B0/</guid>
      <description>qt qml 中 可以把 c++对象注入 qml engine
reac native 自从收编 nitro 之后,也获得了这种能力
我已经用qt qml 在windows/linux/mac / embed linux中写gui, 但对于android和ios 一直没有实践
1是确实没有什么项目, 2是lgpl 和商城规则或多或少存在争议
所以在知道react native也可以这么说后,我打算开始玩一玩, 尝试把我自己写的c++ 静态反射库应用于其中
于是有此笔记,将和往常一样不定时整理更新
1 配置sdk版本,及兼容的最低版本 1.1 IOS 1.1.1 SDK版本选择 sdk向下兼容是有限制的,所以想开发兼容很旧的ios系统的程序,只能下载旧的xcode版本开发,且开发后上不了架,并且ios系统不一定能运行旧版本的xcode, 想开发不上架的ios app,有可能需要装虚拟机,安装旧的系统,再安装旧的xcode,再开发
xcode 版本支持的sdk版本支持参考这里
因为apple store要求sdk需要使用较新版本,所以想上架的话, 最好在apple store安装最新的xcode,更新最新的sdk
apple store 安装完的xcode 第一次打开时可能有弹出一个选择安装sdk的版本,如果有的话把ios sdk 打钩安装
下载的xcode.xip解压的好像没有这个弹窗 ,有的话也是把ios sdk打钩安装(这试了几次都没有)
选择了xcode就等于选择了sdk 版本了,想改只能切换xcode版本
附上一些在命令行中切换 xcode和sdk版本的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #选择xcode xcode-select -p sudo xcode-select --switch /Applications/Xcode.</description>
    </item>
    
    <item>
      <title>wsl同时使用udp广播和usb</title>
      <link>/post/wsl%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8udp%E5%B9%BF%E6%92%AD%E5%92%8Cusb/</link>
      <pubDate>Fri, 02 May 2025 12:48:29 +0800</pubDate>
      
      <guid>/post/wsl%E5%90%8C%E6%97%B6%E4%BD%BF%E7%94%A8udp%E5%B9%BF%E6%92%AD%E5%92%8Cusb/</guid>
      <description>0.背景 ​ 遇到一个问题, 之前写了一个cv ai 模型辅助训练的工具给客户使用,用于采集我司AI相机的图片,训练模型后再上传回AI相机
这个工具中使用了很多bash环境下的工具, 比如async scp,节约了很多重复造轮子的时间,但也注定了几乎离不开bash环境了
在要windows上运行这个工具,面临这几种方案的选择
使用wsl,docker之类的,运行于其中 (快乐的摸鱼时光) 在windows上安装bash环境 (小量修改) 抽象bash工具调用的方法适配 (工作量巨大) 毫无疑问,出于对公司的负责,我选择了成本最低的方案1
工业软件经常在在配置设备的Ip之前用udp广播来发现网络设备, 因为udp broadcast运行在 第二层数据链路层, ip在第三层
我写的这个工具也使用了udp广播来发现设备, 同时后期还加入了硬件加密 usb子锁,
所以它需要运行在wsl中,同时使用udp广播和usb接口
1. 同时使用udp广播和usb接口的问题 1.1 wsl usb挂载模式 wsl中已经有成熟的usb方案,即 usbipd.
可以在windows host上把某一个usb设置共享,在wsl中设置挂载
如它的名字, usb ip d, 基于usb/ip协议的daemon程序,它的运行的基础是:
需要windows 和 wsl 可以通过ip 通讯
1.2 wsl的三种网络模式 经常使用wsl的朋友都知道wsl有三种网络工作模式
NAT (默认) Mirrored Bridged nat 模式时, wsl运行在一个hyper v 的nat子网络中, 这个网络适配器在ncpa.cpl工具中看不到,但使用ipconfig可以看到,用hyper v网络管理工具也可以看到,应该是防老6误操作,偷感十足. nat天然的不能广播udp, 就像在家里的局域网不能无限制的向上层网络广播一样
mirrored械时, wsl里可以看到所有windows的网络适配器, 这个模式是微软推荐的方式,但这个模式,可能是为了防止udp风暴,这个模式下udp广播是有限制的,随便一搜就能看到很多人在github上讨论谁家的udp包又丢了
最后birgded,这个模式是微软想要铲掉的功能,因为bridge模式下, wsl 的网络像一座孤岛, 完全和windows host隔离了, 它独自占用了一个wsl 外部网络(对应一个物理网卡),所以它也可以对外广播</description>
    </item>
    
    <item>
      <title>编译精简的chromium记录</title>
      <link>/post/%E7%BC%96%E8%AF%91%E7%B2%BE%E7%AE%80%E7%9A%84chromium%E8%AE%B0%E5%BD%95/</link>
      <pubDate>Sun, 30 Mar 2025 12:48:29 +0800</pubDate>
      
      <guid>/post/%E7%BC%96%E8%AF%91%E7%B2%BE%E7%AE%80%E7%9A%84chromium%E8%AE%B0%E5%BD%95/</guid>
      <description>0 前言 春节尝试了自己写pytorch模型, 通过我封装的vnc控件,远程docker中的Ubuntu, 采集扫雷游戏的截图, 训练两个模型
自定义卷积对游戏截图状态识别 ddqn 强化学习,仅通过奖励在不教规则的情况下让模型自己学会玩扫雷 前面的识别模型一个星期就成功了,但是强化学习的效果除了花了春节一周时间,还追加了三个星期的周末,都没能成功
不知道是不是强化学习需要的数据量太大导致的,因此只能暂时搁置此学习任务,否则道心不稳,天空好像始终覆盖一层厚重的阴霾
为了走出ddqn的滑铁卢,我把目光转向chromium , 我想编译各平台的精简版本的chromium内核,像electorn一样使用它进行一些web集成到客户端(qt qml 的opengl frame buffer object)中的开发,这样既能享受web前端便利的生态,又能使用qt qml全平台的c++能力,对web在音视频等领域的乏力进行补充.
1 mac os 官方文档
https://github.com/chromium/chromium/blob/main/docs/mac_build_instructions.md
https://bitbucket.org/chromiumembedded/cef/wiki/AutomatedBuildSetup.md#markdown-header-windows-configuration
我们主要完成以下三个步骤
arm64构建 x64构建 合并为通用的flat版本(x64和arm64都可用) 1.0 源码拉取 1.1 切换sdk 在src/build/config/mac/mac_sdk.gni里可以确认需要官方编译时的sdk版本
这个版本不一定是要低要救,如果没有这个版本的sdk可以调为你有的版本实验编译,如果编译不过,再安装和他们一样的sdk版本
如果需要安装新的sdk, 可能需要安装对应的xcode版本,在这里下载
什么版本的xcode有什么版本的sdk 看这个说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #选择xcode xcode-select -p sudo xcode-select --switch /Applications/Xcode.</description>
    </item>
    
    <item>
      <title>modbus_rtu从站仿真</title>
      <link>/post/modbus_rtu%E4%BB%8E%E7%AB%99%E4%BB%BF%E7%9C%9F/</link>
      <pubDate>Sun, 29 Dec 2024 12:48:29 +0800</pubDate>
      
      <guid>/post/modbus_rtu%E4%BB%8E%E7%AB%99%E4%BB%BF%E7%9C%9F/</guid>
      <description>前言 上周,开发了一个可视化配置的modbus模块,用于和电气部门的西门子plc的modbus RTU slave通讯.
实现主要使用qt的qmodbusslave相关的类, 细节不再展开
由于电气工程师们也是第一次使用modbus RTU模块, 对配置不熟悉,所以我需要自己仿真通讯,验证程序逻辑
主要遇到的问题是, modbus RTU是基于串口的, 如果是modbus tcp直接通过已有的网络仿真 modbus slave就可以,但电脑本身没有串口,要怎么仿真 modbus slave运行,以验证自己实现的modbus master逻辑呢.
通过一周下来的摸索,我找到3种方法
方法1 qt5中,modbus RTU的从站对应的c++类是 QModbusRtuSerialMaster , modbus Tcp从站应对的c++类则是QModbusTcpClient. 它们都继承自QModbusClient.
这两个除了连接的接口不同,上层封装的接口没有任何区别,包括读写,状态,错误接口
所以可以先用QModbusTcpClient类 + 一个仿真的modbus tcp master, 就可以验证了
可以直接从qt 5安装的exmaple中找到 modbus slave代码,编译了它你就拥有一个仿真用的modbus 从站
配置好环境编译后直接运行以验证
这个方法的缺点是串口连接的逻辑没有办法验证
有一个坑是 QModbusRtuSerialMaster连接的方法connectDevice成功是同步返回的,不像 QModbusTcpClient连接后立即返回,
如果用事件循环进一步封装需要注意,否则会导致事件循环永退出在开始之前,调用modbus 连接的线程一直挂起
我就在这个问题浪费一下午,痛定思痛才摸索出第2种和第3种方式,完全的仿真 modbus RTU的通讯
方法2 在windows上使用虚拟串口(这个可以自选上网搜索,大多数是破解收费的),创建一对Tx Rx交叉的串口对, 例如 COM1和 COM2
然后使用qt example的modbus slave 运行在COM1
你的modbus master程序使用com2 ,连接上之后就可以完整的验证modbus RTU的整个通讯过程
方式3 此方式与 方法2雷同
区别是直接使用两个物理串口 交叉连接 TX RX</description>
    </item>
    
    <item>
      <title>wsl2设置网络桥接到物理网卡</title>
      <link>/post/wsl2%E8%AE%BE%E7%BD%AE%E7%BD%91%E7%BB%9C%E6%A1%A5%E6%8E%A5%E5%88%B0%E7%89%A9%E7%90%86%E7%BD%91%E5%8D%A1/</link>
      <pubDate>Sat, 28 Dec 2024 12:48:29 +0800</pubDate>
      
      <guid>/post/wsl2%E8%AE%BE%E7%BD%AE%E7%BD%91%E7%BB%9C%E6%A1%A5%E6%8E%A5%E5%88%B0%E7%89%A9%E7%90%86%E7%BD%91%E5%8D%A1/</guid>
      <description>0. 前言 前几个月已经探索了通过x11 转发, 在windows与mac os上通过ubuntu docker 镜像,运行具有gpu加速的ubuntu gui程序
但是在windows上有更直接的选择, 那就是通过wsl2 运行ubutnu的linux 子系统, 这种方式,可以通过在docker desktop中设置与具体的wsl2 发行版集成, 让windows和wsl2 发行版使用同一个docker socket,共享一个docker engine
docker 也更建议把docker与wsl2一起使用, 此方案应有更多的性能红利和社区支持红利
由于我将在windows上通过wsl2 ubuntu运行的程序会使用udp广播来发现局域网中的设备,所以不能使用wsl默认的nat网络,否则udp广播刚不能传达到局域网的设备端. 所以我探索了设置wsl 网络桥接物理网卡的方式,并记录在此,留痕
此方法需要
使用hyper-v 创建虚拟网络 配置wsl 使用 虚拟网络 限制
终于目前只在win11上使用 win10上还没测试,所以不保证在windows上可以成功 如果将来在windows 10测试验证, 将会更新些文档
1.windows家族版安装hyper-v 通常安装hyper-v的方式是在程序中打开windows功能,选中hyper-v,确定安装,不过如果你是windows 家庭版,那么在打开windows功能的界面中不会有hyper-v的选项,需要用以下方式安装
创建 hyper-v.bat
1 2 3 4 5 6 pushd &amp;#34;%~dp0&amp;#34; dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum &amp;gt;hyper-v.txt for /f %%i in (&amp;#39;findstr /i . hyper-v.txt 2^&amp;gt;nul&amp;#39;) do dism /online /norestart /add-package:&amp;#34;%SystemRoot%\servicing\Packages\%%i&amp;#34; del hyper-v.</description>
    </item>
    
    <item>
      <title>raspberry-pi5-开发笔记</title>
      <link>/post/raspberry-pi5-%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Sat, 26 Oct 2024 12:48:29 +0800</pubDate>
      
      <guid>/post/raspberry-pi5-%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/</guid>
      <description>2024/07/27 添加nvme,bluetoothcli 相关内容 2024/10/26 添加使用非pd电源遇到的Usb电流问题 2024/12/14更新i2c 写入eeprom , 定制启动动画和开始菜单图标 0. 前车之鉴 0.1 glibc 兼容性问题 刚开始的时候，pi5的板子用了官方的镜像，即 Debian 12 bookworm. 但是交叉编译的镜像使用了Ubuntu 23.10 mantic, 交叉编译了Qt5 和程序后，放到板子上运行时，提示glibc版本不兼容， 是因为 bookworm和ubuntu 23.10的 libc 和libcxx版本不同导致，ubuntu23.10 2.38， bookworm 2.36，后面板子和交叉编译的docker镜像统一之后就ok了
0.2 Qt程序显示不正常，半透明的图形不显示，窗口有黑边 虽然Qt正常编译过了，但是部署到板子上后，程序显示不正常，后经排查，是由于 Qt配置 EGL on X11失败，需要在编译配置/src/qt5/qtbase/mkspecs/devices/linux-rasp-pi4-v3d-g++/qmake.confr中添加编译选项 -fpermissive
1 QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -fpermissive 否则qt 源码中的configure工具 生成的EGL on X11 的单元测试会执行失败，导致配置失败
0.3 检测不到I2C 初遇0.1中所述问题时，我把板子和docker环境的系统都 刷成ubuntu 23.10，之后板子一直检测不到i2c，叫大师帮忙检测硬件接线问题，无果，用示波器测量波形，正常。其他硬件没有测试，但应该也是有问题的，是因为官方虽然给了ubuntu23.10的镜像，但却没有预装硬件相关的工具，例如i2cdetect， 于是我用apt安装了一个，于是不能正常工作 ，如果克隆内核源码，单独编译工具应该也可以行得通，但我解决的方法简单粗暴，把板子和docker的系统都换为bookworm了，bookworm的工具是齐全的。
0.4 GPIO C++编码后，不能正常初始化，提示系统不是树莓派 由于 PI5 做了很大的变更，所以GPIO相关的系统工具虽然内置了，但并不能适用 于pi5，pigpio在 /usr/include和/usr/lib中头文件库可以正常编译，链接，但编好的程序会提示初始化失败，解决的方法是使用开始的源 libgpiod，不要使用pigpio
https://github.com/joan2937/pigpio/issues/589
1. I2C 树莓波5支持3路i2c通讯，默认只打开 一组，即pin3,pin5，通过修改/boot/fireware/config.</description>
    </item>
    
    <item>
      <title>windows_wsl2_nvidia-docker2镜像记录</title>
      <link>/post/windows_wsl2_nvidia-docker2%E9%95%9C%E5%83%8F%E8%AE%B0%E5%BD%95/</link>
      <pubDate>Sun, 20 Oct 2024 12:48:29 +0800</pubDate>
      
      <guid>/post/windows_wsl2_nvidia-docker2%E9%95%9C%E5%83%8F%E8%AE%B0%E5%BD%95/</guid>
      <description>0. 写在前面 上上周我尝试了使用mac os 通过x11转发,显示从ubuntu docker中启动的gui程序,并使用ubuntu docker中的输入法的实践
上周我尝试了在windows上在其基础上加入了nvidia-docker2的步骤,也成功了,不过没时间记录,于是今日写此文档记录
不管是mac os还是windows上所做的这些实验,都是为了在docker中运行我的开源的yolo8辅助训练软件label-image
1. 前置条件 1.1 wsl 2 由于windows上的ubuntu docker container运行在wsl2可以支持得更好,也是nvidia-docker2的充分必要条件,所以如果你安装的wsl发行版本不是wsl版本的话,需要先安装一个wsl2的docker-desktop
安装成功后可以命令行查看
1 2 3 PS C:\WINDOWS\system32&amp;gt; wsl --list -v NAME STATE VERSION * docker-desktop Running 2 wsl2的安装方法,随便搜索一下就有很多,略
需要在docker-desktop中启用wsl2, 如果设置成功的放在, setting-&amp;gt;resouces中显示如下图
1.2 nvidia-docker2安装 https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
参照些文,如此如此,这般这般,就好了,这里不再展开,没安装成功的再努力百度一下
相比linux下的步骤简单, 安装完后在docker-desktop中重启一下docker就可以生效
如果是在linux下, 需要
sudo systemctl reload-daemon &amp;amp;&amp;amp; sudo systemctl restart docker by the way ,
linux的docker的daemon.json在/etc/docker/daemon.json
widnows的docker的daemon.json在~/.config/docker/daemon.json
设置代理会解决很多镜像拉不下来的问题
1 2 3 4 5 6 7 8 9 10 11 12 { &amp;#34;registry-mirrors&amp;#34;: [ &amp;#34;https://dockerhub.</description>
    </item>
    
    <item>
      <title>使用x11转发在macos上从docker容器中启动gui程序</title>
      <link>/post/%E4%BD%BF%E7%94%A8x11%E8%BD%AC%E5%8F%91%E5%9C%A8macos%E4%B8%8A%E4%BB%8Edocker%E5%AE%B9%E5%99%A8%E4%B8%AD%E5%90%AF%E5%8A%A8gui%E7%A8%8B%E5%BA%8F/</link>
      <pubDate>Sun, 06 Oct 2024 12:48:29 +0800</pubDate>
      
      <guid>/post/%E4%BD%BF%E7%94%A8x11%E8%BD%AC%E5%8F%91%E5%9C%A8macos%E4%B8%8A%E4%BB%8Edocker%E5%AE%B9%E5%99%A8%E4%B8%AD%E5%90%AF%E5%8A%A8gui%E7%A8%8B%E5%BA%8F/</guid>
      <description>0.写在前面 之所以要研究这个,主要是我写的一个Yolo目标检测AI 模型的辅助训练软件label-image不支持Windows平台, 如果需要在Windows上使用, 需要在Windows上启动ubuntu的docker ,再从中启动 ubuntu版本的label-image 通过转发x11消息的方式显示,在Nvidia-docker2的加持下, 直接从docker中访问windows上的显卡,使用cuda加速模型训练
虽然目前MacOS的MPS不管是性能还是配套,都没有Nvidia CUDA做得好,不支持从docker中硬件加速,但我还是觉得有必要研究一下,毕竟将来也许也就支持了.
1.安装 XQuartz XQuartz
为了让mac os可以作为X11服务器,接收来自linux的x11消息
安装XQuartz ,安装完后,配置为允许从网络客户端接收消息
设置允许的x11客户端
1 xhost + #表示不过滤任务客户端ip 2. 创建一个ubuntu docker镜像,安装中文输入法 dockfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 FROM --platform=linux/amd64 ubuntu:20.</description>
    </item>
    
    <item>
      <title>radxa-rock5c-开发笔记</title>
      <link>/post/radxa-rock5c-%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Sat, 27 Jul 2024 12:48:29 +0800</pubDate>
      
      <guid>/post/radxa-rock5c-%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/</guid>
      <description>1. 从NVME 启动系统 从官方的文档上看rock5c, 你会有一种看山跑死马的感觉, 因为它在一本正经的胡说八道
怀疑它只是把rock 5b或5a的文档复制过来改一一改
按他们文档上刷nvme的文档,你将永远不可能成功, 因为rock 5c 从emmc或nvme启动,只能二选一
因为pin脚不够用.但是他们文档上没有指出这点, 截止2024-07-27
如果不想买额外的模块,又想从nvme启动系统,唯的一选项是 把系统刷到 sd中,
这里sd卡中有三个分区
bootloader 硬件配置分区 操作系统分区 然后把sd卡的 第二个分区和第三个分区格式化后,这样当sd卡中的bootloader找不到系统,会尝试从pcie启动
前提是系统已经识别到nvme设备
1 $lsblk #查看是否有nvme设备 格式化可以把sd加载到linux,使用fdisk
1 2 3 4 5 6 $lsblk #查看是否正常识别sd卡设备 $fdisk /dev/sdc #进入交互式cli d 2 #删除第二分区 d 3 #删除第三分区 w #保存 q #退出 然后把官网下载的镜像烧录到m2, 接入rock5c
启动后应该可以看到系统挂载在nvme
1 df -h 可以买容量比较小的sd卡, 10元以内的, 烧录系统失败也没关系,因第一个分区应该还是成功的,失败了应该不影响使用sd卡作为bootload
这样比较经济实惠
2. 开机不自动WIFI 关闭 钱包服务
kwalletmanager中禁用掉
把wireless网络删除，重新创建 无线连接
设置固定ip地址 为wifi生成一个随机的mac (radxa估计没有买mac地址,所以没有mac地址导致dhcp服务器不会缓存,每次重新开机都是新的ip,真是满满的惊喜)
需要在/config/config.txt中设置</description>
    </item>
    
    <item>
      <title>amd-zynq-freeRTOS-开发笔记</title>
      <link>/post/amd-zynq-freertos-%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Sun, 07 Jul 2024 12:48:29 +0800</pubDate>
      
      <guid>/post/amd-zynq-freertos-%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/</guid>
      <description>0.序 Zynq®-7000 系列基于 Xilinx SoC 架构。这些产品在单个器件中集成了功能丰富的基于 ARM® Cortex™-A9 的双核或单核处理系统 (PS) 和 28 nm Xilinx 可编程逻辑 (PL)。 ARM Cortex-A9 CPU 是 PS 的核心，还包括片上存储器、外部存储器接口和丰富的外设连接接口。
本文档记录的是 zynq 7020开发过程中的一些经验
7020上PS端有两个ARM 核 ，还有一个FPGA用的PL
我们的FPGA工程师使用Vivado完成PL端的工程配置，编码后，导出.xsa 文件，
我和我组内的小伙伴使用Vitis ，将.xsa生成为 PS端的工程
使用xilinx BSP中集成的SDK和FreeRTOS,进行裸机开发
由我同事完成网络相机核心代码
我作为摸鱼罪犯，被发配到这个项目做一些比较有手就行的任务
裸机意味着很多工具都不能用了，比如ssh, shell，文件系统， 还有c++的libc
所以我在这个项目中主要用c进行下面这几项开发
文件系统移植，验证 (bsp中有现成的) FreeRTOS串口命令行CLI工具移植 （用来平替Linux的ssh + shell 格式化文件系统 上传文件 打印文件内容 打包程序，制作引导，烧录固化 1.FreeRTOS串口CLI 移植 zynq 7020有两个串口，默认会把启动信息写到第0个， 第1个串口则预留着，
我们的硬件工程师只把串口0 暴露到设备外壳上，所以我们要做的是 zynq 默认串口通道上 加上CLI命令行交互功能以及传输文件功能，
1.1 zynq相关源码获取 签出FreeRTOS源码，切换到vitis 内置的FreeRTOS对应的版本，对于我来说是10.4.x ，我们需要下列这些
CLI插件整个目录
串口CLI实现
几个示例命令实现
Zynq串口头文件 和 Zynq的串口实现 （官方提供了一个基于队列的串口，性能比较差，但够用，如果想更快，需要自己用DMA实现</description>
    </item>
    
    <item>
      <title>vim-ctag-符号查找</title>
      <link>/post/vim-ctag-%E7%AC%A6%E5%8F%B7%E6%9F%A5%E6%89%BE/</link>
      <pubDate>Sun, 16 Jun 2024 12:00:00 +0800</pubDate>
      
      <guid>/post/vim-ctag-%E7%AC%A6%E5%8F%B7%E6%9F%A5%E6%89%BE/</guid>
      <description>0x00 为什么使用CTag 长久以来， 我一直在ide中使用VIM插件，除此之外在Bash,Zsh也使用vim作为基本的文本编辑器， 所有的Git操作也都都交给了VIM+ Shell，在文本编辑方面，我使用统一的一套快捷键方案
我使用过的IDE：visual studio , visual studio code , qt creator
他们都有很好的VIM插件，并且集成了很好的符号查找，所以作为实用主义者，我一直觉得没有使用CTag+VIM的必要
直到上周疯狂摸鱼后，被抓去写 C &amp;amp; Embedded， 我接触到了 Xilinx Vitis这款AMD旗下的IDE,这货竟然没有VIM键盘方案
整一周在这条路上我走得像一个瘸子，痛定思痛，我认为是时候端出CTag这根阵年火腿了
0x01 CTag安装+生成索引 0x0101 安装 由于编译服务器是Ubuntu，所以先只记录Ubuntu， 其他平台大差不差
1 $ sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install -y exuberant-ctags 0x0110 生成索引 写一个用于生成c/c++ tag的脚本 ctag.sh
1 2 3 4 5 6 7 8 9 #!/bin/bash regex=&amp;#34;^.+.+$&amp;#34; if [[ ! $1 =~ $regex ]]; then echo &amp;#34;需要输入生成tag的目录的绝对路径，不能是‘.’&amp;#34; exit 1 fi cd $1 ctags -R --languages=c,c++ --exclude=node_modules --c++-kinds=+p --fields=+iaS --extra=+q .</description>
    </item>
    
    <item>
      <title>nvidia-jetson开发笔记</title>
      <link>/post/nvidia-jetson%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Wed, 01 May 2024 12:00:00 +0800</pubDate>
      
      <guid>/post/nvidia-jetson%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/</guid>
      <description>2024.05.01 更新 jetson orin nx 刷nvme
一开始只针对jetson xavier写文档,后来公司又用了jetson orin, 所以就一起写一个文档里了, jetson orin可以刷最新的 jetson linux 和 jetpack, 不过为了只维护一个版本, 我决定不管是xavier还是orin 都使用 xavier能用的最新版本, 即 jetpack 5.1.3+ jeson linux 35.5.0
1. 刷机 jetson xavier NX开发板官方推荐的方式是使用刷sd卡的方式， 也可以使用flash.sh脚本或l4t_initrd_flash.sh直接刷，这样可以省略制作镜像的步骤
截止2024.3.26， jetson xavier NX已然停产，不过仍然可以使用 JetPack 5.1.3 开发包进行开发
我使用我的ubuntu16.04 开发环境的虚拟机制作镜像及烧录脚本烧录，
也可以使用官方的gui刷机工具sdk-manager（ps 名称有点忘记了，好像是这个），不过那需要ubuntu18或ubuntu20
1.1 准备工作 在Jetson Linux | NVIDIA Developer下载这两个
Title Driver Package (BSP) Sample Root Filesystem 最好在linux中下载，因为windows文件系统不支持符号链接文件，我担心解压后会影响文件完整性
下载后得到
1 2 3 4 5 6 ~/Downloads/nvidia/Linux_for_Tegra$ ll total 2229716 drwxrwxr-x 3 deepvision deepvision 4096 3月 26 13:10 .</description>
    </item>
    
    <item>
      <title>cpp跨平台共享内存进程通讯</title>
      <link>/post/cpp%E8%B7%A8%E5%B9%B3%E5%8F%B0%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98%E8%BF%9B%E7%A8%8B%E9%80%9A%E8%AE%AF/</link>
      <pubDate>Thu, 04 Apr 2024 12:00:00 +0800</pubDate>
      
      <guid>/post/cpp%E8%B7%A8%E5%B9%B3%E5%8F%B0%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98%E8%BF%9B%E7%A8%8B%E9%80%9A%E8%AE%AF/</guid>
      <description>1. Linux的两种共享内存机制，及选用 shmget 和 shm_open 是两种不同的共享内存机制，它们在使用方式和本质上有所不同。
1.1 System V 共享内存 shmget 是 POSIX 标准中定义的 System V 共享内存的接口函数。 System V 共享内存是一种传统的 UNIX 共享内存机制，使用 shmget 函数创建的共享内存对象被映射到进程的地址空间中，进程可以直接访问共享内存区域，而无需通过文件系统。 System V 共享内存需要使用键值来唯一标识共享内存对象，进程可以使用该键值来获取或创建共享内存对象。 System V 共享内存需要使用额外的信号量进行同步和互斥操作，以避免竞争条件和数据损坏。 1.2 映射文件共享内存 shm_open 是 POSIX 标准中定义的另一种共享内存机制，属于 POSIX 共享内存对象。 POSIX 共享内存是一种基于文件的共享内存机制，使用 shm_open 函数创建的共享内存对象实际上对应着文件系统中的一个特殊文件。 与 System V 共享内存不同，POSIX 共享内存可以直接通过文件系统访问和管理，进程可以像操作普通文件一样来操作共享内存对象。 POSIX 共享内存不需要使用键值来标识共享内存对象，而是使用文件路径来唯一标识共享内存对象，这样更加简洁和直观。 POSIX 共享内存不需要使用额外的信号量进行同步和互斥操作，而是通过操作系统提供的文件锁机制来实现并发访问的同步。 由于要考虑跨平台封装，windows上共享内存映射也是文件系统相关，所以选择映射文件的这个套机制
2. 查看共享内存分配情况 2.1 POSIX - System V 虽然我们选用了映射文件共享内存的方式，但是还是简单提一下system v共享内存机制查看已分配内存的方式
1 2 3 4 5 6 7 8 9 huangbinbin@cs-bj:~$ ipcs -m ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 557056 chenyan 600 524288 2 dest 0x00000000 557057 chenyan 600 2097152 2 dest 0x00000000 491523 hanhaopeng 600 8388608 2 dest 0x00000000 1146884 huangbinbi 600 67108864 2 dest .</description>
    </item>
    
    <item>
      <title>boost-asio-udp-同步超时陷阱</title>
      <link>/post/boost-asio-udp-%E5%90%8C%E6%AD%A5%E8%B6%85%E6%97%B6%E9%99%B7%E9%98%B1/</link>
      <pubDate>Sun, 24 Mar 2024 12:48:29 +0800</pubDate>
      
      <guid>/post/boost-asio-udp-%E5%90%8C%E6%AD%A5%E8%B6%85%E6%97%B6%E9%99%B7%E9%98%B1/</guid>
      <description>2024/03/24 阴， 约了许久没见面的妹妹吃了一个饭，她去找他同学玩了，我到咖啡店找点下周要开发的nvidia jetson xavier的资料， 由于板子没在身边，具体型号也不记得，所以有时间记录一下去年遇到的一个boost asio 同步通讯中，客户端设置超时的坑， 顺便记录一下boost udp 客户端 通讯的example， 同步，异步应该是大同小异， 我使用的boost 版本是1.83
0. boost udp 同步超时陷阱 遇到这个问题时，我在开发一个gige 协议的客户端，用于windows和linux环境，使用gige相机。gige中通过gvcp和gvsp来对相机进行交互和取流，gvcp是udp协议，所以我用的是udp socket。开始时，我在windows上开发， 使用下面这段代码设置超时时间 ，它可以正常的工作 ，当超时发生时，返回超时的结果。
代码中先创建了endpoint和udp socket，然后把它们绑定在一起，然后设置socket的超时时间 为5000毫秒
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 void foo() { try { boost::asio::io_service io_service; boost::asio::ip::udp::socket socket(io_service); socket.</description>
    </item>
    
    <item>
      <title>forgejo-drone-ci-cd</title>
      <link>/post/forgejo-drone-ci-cd/</link>
      <pubDate>Sat, 23 Mar 2024 12:48:29 +0800</pubDate>
      
      <guid>/post/forgejo-drone-ci-cd/</guid>
      <description>相关服务 forgejo : 源码版本控制， 前身是gitea， 由于 gitea有闭源风险， 社区不再信任，fork出forgejo继续开发开源版本， ps gitea也是从其他项目继续过来开发的
drone : ci/cd
drone服务 通过 weebhook 监听git 仓库事件，分发任务给runner执行CI/CD
CI/CD 需要执行什么， 取决于添加到drone配置文件，通常名为 .drone.yml
服务相关的docker compose放在附录之中了
上传已有git仓库到forgejo 先在forgejo上创建仓库
创建时，需要关注几个仓库的属性
拥有者， 设置组织，如SW组织， 可见性， 一般都设置私有仓库， 再添加协作者 默认分支，一般设置为master ,和gitlab保持一致 创建完后把drone 用户添加到git仓库协作者， ci的docker环境会设置drone的ssh代理，让drone有权限访问代码
再本地的代码库中设置远程库直接推送
1 2 git remote add forgejo ssh://git@git3.deepvision-tech.net:222/SW/ci_demo_0.git git push 激活git仓库的drone 激活之前，git项目不会创建webhook,
需要登录drone 激活 drone : http://10.1.8.129
不需要填写用户名密码，点登录后自动以forgejo登录信息登录drone
点击右上角同步项目信息,同步完会看到刚才新建的项目
点击项目进制配置界面，点击
默认设置点击保存
保存后forgejo上的项目会生成一个webhook
可以这weebhook中设置需要关注的git事件类型和git 分支
通常是只有关键分支才需要ci/cd， 开发分支不需要，
开发分支 合到关键分支，需要提交合并请求或拉取申请，待审核后合并后自动触发 持续集成
weebook还可以试触发， 在调试ci/cd时很方便
.drone.yml example</description>
    </item>
    
    <item>
      <title>ubuntu安装nvidia显卡驱动</title>
      <link>/post/ubuntu%E5%AE%89%E8%A3%85nvidia%E6%98%BE%E5%8D%A1%E9%A9%B1%E5%8A%A8/</link>
      <pubDate>Wed, 07 Feb 2024 00:00:00 +0800</pubDate>
      
      <guid>/post/ubuntu%E5%AE%89%E8%A3%85nvidia%E6%98%BE%E5%8D%A1%E9%A9%B1%E5%8A%A8/</guid>
      <description>0. 大纲 查看显卡驱动 添加apt 仓库 自动检测安装(对于较新型号无效) 手动安装 0.查看显卡驱动 1 lscpi |grep -i vga 输出
确认是NVIDIA 显卡后， 继续后面的步骤，如果不是，可以试试 3，不一定有效， 2和4就不需要执行了
1.禁用nouveau 显卡驱动 nouveau是预置的通用显卡,如果要安装nvidia的显卡驱动,需要先禁用它
1 2 3 4 5 6 7 8 9 10 11 sudo cat &amp;lt;&amp;lt; EOF &amp;gt; /etc/modprobe.d/blacklist-nouveau.conf blacklist nouveau options nouveau modeset=0 EOF #建议在执行这行之前,再次检查一下是不是已经把文件正确写入了,否则重启后没正常成功还要检查一次 sudo update-initramfs -u #重启生效 reboot 2. 添加apt 源 添加Ubuntu图形驱动仓库PPA。在终端输入以下命令：
1 2 sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update 3. 自动检测安装（对较新型号无效） 1 sudo ubuntu-drivers autoinstall 如果没有自动安装，需要手动安装，执行第4步</description>
    </item>
    
    <item>
      <title>ubuntu安装多个gcc版本</title>
      <link>/post/ubuntu%E5%AE%89%E8%A3%85%E5%A4%9A%E4%B8%AAgcc%E7%89%88%E6%9C%AC/</link>
      <pubDate>Wed, 07 Feb 2024 00:00:00 +0800</pubDate>
      
      <guid>/post/ubuntu%E5%AE%89%E8%A3%85%E5%A4%9A%E4%B8%AAgcc%E7%89%88%E6%9C%AC/</guid>
      <description>ubuntu 16.04 安装多个gcc版本 1.背景 由于我们软件开发时，通常在ubuntu16.04系统中运行，而ubuntu16.04 中系统自带的gcc版本为5.4.
ubuntu16.04 从2016年发布以来，就实验性的支持了c++17的部分功能，所以我们的工程中也部分的使用了c++17的功能。
最近，在windows上使用msvc写了一部分代码，在与linux版本合并的时候，出现很多编译错误，才来了解gcc对c++17的支持情况
gcc 5，部分的，实验性的支持了c++17的语法
gcc 7, 在语法层面，完整的兼容了c++17标准
gcc 9, c++17 ABI层面完整的兼容(意味着可以安全的交叉编译)
信息来源
考虑到ubuntu16已经于2021年结束标准支持，2026年将结束生命周期，以及使用更多的c++17的特性
我决定在我的开发环境安装多个gcc版本，踩一下升级gcc坑，
先设定一个小目标：安装可以在gcc 5 和gcc7之间来回切换的开发环境
2.升级之前 备份虚拟机环境 ，基操
3. 升级 我们主要通过build-essential 这个基础设施来 安装，管理 gcc ， 所以首先安装它
1 sudo apt install build-essential 下面三个镜像任选一个
1 2 3 4 5 6 #清华 sudo sed -i &amp;#39;s/http:\/\/archive.ubuntu.com\/ubuntu\//http:\/\/mirrors.tuna.tsinghua.edu.cn\/ubuntu\//g&amp;#39; /etc/apt/sources.list #阿里云 sudo sed -i &amp;#39;s/http:\/\/archive.ubuntu.com\/ubuntu\//http:\/\/mirrors.aliyun.com\/ubuntu\//g&amp;#39; /etc/apt/sources.list #华为云 sudo sed -i &amp;#39;s/http:\/\/archive.ubuntu.com\/ubuntu\//https:\/\/mirrors.huaweicloud.com\/ubuntu\//g&amp;#39; /etc/apt/sources.list 安装gcc版本
1 sudo apt -y install gcc-5 g++-5 gcc-7 g++-7 1 2 3 4 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 5 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 5 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 7 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 7 配置gcc版本</description>
    </item>
    
    <item>
      <title>cmake_vcpkg_meson交叉编译arm64_raspberry_pi程序</title>
      <link>/post/cmake_vcpkg_meson%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91arm64_raspberry_pi%E7%A8%8B%E5%BA%8F/</link>
      <pubDate>Wed, 31 Jan 2024 18:48:29 +0800</pubDate>
      
      <guid>/post/cmake_vcpkg_meson%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91arm64_raspberry_pi%E7%A8%8B%E5%BA%8F/</guid>
      <description>0. 背景 大概是上个月左右，协助韩博把我写的这套网口相机框架运行到树莓派上，一直想找时间 记录一下，终于有时间 了。
除了交叉编译我们自己的代码之外，还有一些依赖的3方的框架也需要编译为arm64的库，大概会按我下面列的这几点为大纲进行记录
vcpkg用于安装大部分版本稳定的三方框架，少部分三方框架用vcpkg安装也不一定编译得了，因为官方只维护几种常用的triplets，如果是自定义太高的编译工作，将不得不使用社区版本的triplets，将使vcpkg遇到比平时更多的编译问题，当然如果有时间 +有能力的话，可以fix这些bug为vcpkg提交pr ，这部分工作通常由微软的vcpkg小组和社区开发者一同维护
接下来我不会很详细的介绍某个具体的库是怎么编译的，甚至会跳过，主要介绍交叉编译的大致过程
目录
准备工作
arm64 gcc工具链下载
复制树莓派 systemroot库目录，用于交叉编译时程序链接
编译环境docker制作
编译arm64 Qt5.15
cmake交叉编译树莓派的工具链配置
meson交叉编译配置
vcpkg配置
绕过qt下载编译，使用本地已有的Qt cmake交叉编译配置 meson交叉编译配置 1. 准备工作 1.1 arm64 gcc 下载 略
1.2 复制树莓派 systemroot库目录，用于交叉编译时程序链接 略 ,韩博做的镜像 host:rpi4-1中已经有做这个操作了，/sysroot 这个目录
1.3 编译环境docker制作 SW/dv-qt-dev: Dockerfiles and scripts for QT development with containers. - dv-qt-dev (deepvision-tech.net)
之前韩博写的这个dockerfile里，是从qt 安装包安装qt 的.run安装包+提取安装包脚本 安装qt 5.12.6，
但qt 5.15没有.run安装包，所以需要自己编译
所以如果你想编译的是5.12.6，可以直接使用这个docker file
如果想用5.15，可以参考我在韩博的帮助下，创建的这个dockerfile，它没有包含qt的编译，我们以它做成的容器为环境，在容器中编译qt到我们挂载的卷上
build_dev_env.docker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 FROM --platform=linux/amd64 ubuntu:16.</description>
    </item>
    
    <item>
      <title>ubuntu16.04设置core dump</title>
      <link>/post/ubuntu16.04%E8%AE%BE%E7%BD%AEcore-dump/</link>
      <pubDate>Sat, 13 Jan 2024 17:51:56 +0800</pubDate>
      
      <guid>/post/ubuntu16.04%E8%AE%BE%E7%BD%AEcore-dump/</guid>
      <description>0. 之前同事写过这个主题，包括我们软件给技术支持的pdf里也有这个说明，但都请得比较抽象，所以重新写一个详细版本
1. 设置core dump资源限制 通过ulimit -a可以查看各类资源限制，其中-c类表示core
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 deepvision@ubuntu:~/source/repos/dv_app_solution/bin/x86_64(master)$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 31574 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 31574 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 默认情况下，应该看到core file size 限制为0，ubuntu 16.</description>
    </item>
    
    <item>
      <title>动态加载动态库，及库内c风格方法</title>
      <link>/post/%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD%E5%8A%A8%E6%80%81%E5%BA%93%E5%8F%8A%E5%BA%93%E5%86%85c%E9%A3%8E%E6%A0%BC%E6%96%B9%E6%B3%95/</link>
      <pubDate>Thu, 21 Dec 2023 17:51:56 +0800</pubDate>
      
      <guid>/post/%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD%E5%8A%A8%E6%80%81%E5%BA%93%E5%8F%8A%E5%BA%93%E5%86%85c%E9%A3%8E%E6%A0%BC%E6%96%B9%E6%B3%95/</guid>
      <description>1 背景 《新的网口相机软件工程》，设计之初就考虑到扩展性，对于不同产品，不同的项目来说，
代码全都收敛到同一个代码库，同一个分支。不同的产品也只不过是不同的插件而已，
可以通过配置文件中的项目类型，过滤不需要加载的插件
这样做的优点是，
可以像搭积木一样，从各个动态库中取出UI和逻辑， 拼凑成一个app 减少重复的代码，提高代码重用率 减少维护成本，bug的修复，只需要一次，不需要跨分支，跨产品的到处合fix分支和补丁 减少代码分支数量，所有使用框架的人围绕着master分支展开工作 方便进行重构，好的代码都是重构出来的，当所有代码都在事一个分支上时，重构时只要把旧的接口保留，并标记为过时，增加新的重构方法，慢慢迭代掉过时方法就行了，如果分支很多的话，重构往往阻力重重 2 遇到什么问题 算法库，按产品划分分支， 不同的产品，有不同的头文件
这导致一个问题
当软件与不同的算法产品搭配使用时，按以往的方式，添加头文件，链接算法库， 由于算法头文件不同，将导致软件也需要开和算法一样多的分支才能保证链接算法库不会因为找不到符号导致编译失败
这样一来，软件也不得不每一个定制项目开一个分支去和算法适配了。
3 解决方法 我曾向算法部沟通建议过，让他们给出一个合并版本的头文件， 不同的产品，按名称空间划分好，例如二维码算法项目有自己的接口，也有3d激光线扫的接口，但3d激光线扫的接口只放空实现， 这个建议完驳回了，因为算法认为这样会污染头文件
所以我尝试了另一种动态库调用的方式， 通过系统api 动态加载动态库，并查找已知的符号，转换为函数指针， 调用函数指针。
经测试， windows上和linux上都可以正常的调用，不过需要算法提供C风格的函数导出。
4 示例代码 4.1 纯c风格导出 头文件 purecpplib.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #ifndef PURECPPLIB_H #define PURECPPLIB_H #ifdef _WIN32 #define HBBEXPORT __declspec(dllexport) #else #define HBBEXPORT #endif #ifdef __cplusplus extern &amp;#34;C&amp;#34; { #endif HBBEXPORT int avg(int a, int b); #ifdef __cplusplus } #endif #endif // PURECPPLIB_H 使用__cplusplus这个宏加了一对</description>
    </item>
    
    <item>
      <title>qt5-cmake-qml多语言实践</title>
      <link>/post/qt5-cmake-qml%E5%A4%9A%E8%AF%AD%E8%A8%80%E5%AE%9E%E8%B7%B5/</link>
      <pubDate>Sat, 09 Dec 2023 17:51:56 +0800</pubDate>
      
      <guid>/post/qt5-cmake-qml%E5%A4%9A%E8%AF%AD%E8%A8%80%E5%AE%9E%E8%B7%B5/</guid>
      <description>1. 编码 1.1 CMake 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # 添加引用Qt的名为LinguistTools的component find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core LinguistTools) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Gui Widgets Quick Qml QuickControls2 LinguistTools) #定义需要生成的.ts ,放到TS_FILES这个cmake变量中 set(TS_FILES src/translations/zh_CN.ts src/translations/en_US.ts src/translations/ja_JP.ts ) #扫描这dv_app,dv_camera, dv_common这三个目录，把需要翻译的字符串扫描进.ts文件中 qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR}/dv_app ${CMAKE_SOURCE_DIR}/dv_camera ${CMAKE_SOURCE_DIR}/dv_common ${TS_FILES} ) #在生成 xxx可执行文件时，把执行扫描生成.ts ，再把.ts生成.qm翻译二进制文件 add_library(xxx SHARED ${TS_FILES} #这一行只是为了在qt creator中看到.</description>
    </item>
    
    <item>
      <title>ubuntu16.04编译qt5.15的qt creator</title>
      <link>/post/ubuntu16.04%E7%BC%96%E8%AF%91qt5.15%E7%9A%84qt-creator/</link>
      <pubDate>Thu, 30 Nov 2023 17:51:56 +0800</pubDate>
      
      <guid>/post/ubuntu16.04%E7%BC%96%E8%AF%91qt5.15%E7%9A%84qt-creator/</guid>
      <description>1 为什么需要自己编译 相机软件 使用最新版本的qt 开源版本 5.15.2，以及cmake，qml来组织工程，
遇到几个问题
1.1 Qt5.15.2预装的Qt Creator不支持在Ubuntu16.04环境运行 qt 5.15.2预装版本的qt creator是在ubuntu20下使用qt 6和gcc9编译的，ubuntu16.04 下不能使用，我曾尝试升级ubuntu16的libc，最终把ubuntu16 环境搞崩溃，重启之后很多系统软件都不能运行了，apt升级也升级不了，依赖树产生问题。除非你添加18或20的源才能正确的升级，所以不得不重做开发环境， 先用qt 5.12.6预装的qt creator 4.10.2进行开发
1.2 Qt Creator 4.10.2的问题 加载Qt 5.15.2的qml 控制库，很多误报，不管是在cmake运行，还是IDE里的代码提示，都很多噪音
cmake 子模块代码变更后， 检测不到变更，只能整个工程rebuild才能正常
cmake功能支持比较粗糙， 设置cmake比较不方便
cmake循环依赖问题(在新的版本上不是问题)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 CMake Warning at CMakeLists.txt:176 (add_executable): Cannot generate a safe runtime search path for target tst_dv_camera because there is a cycle in the constraint graph: dir 0 is [/home/deepvision/source/repos/dv_app_solution/build-dv_camera-Desktop_Qt_5_15_2_GCC_64bit-Debug] dir 4 must precede it due to runtime library [libdv_zlog.</description>
    </item>
    
    <item>
      <title>vcpkg资产缓存与二进制缓存</title>
      <link>/post/vcpkg%E8%B5%84%E4%BA%A7%E7%BC%93%E5%AD%98%E4%B8%8E%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%BC%93%E5%AD%98/</link>
      <pubDate>Mon, 13 Nov 2023 17:51:56 +0800</pubDate>
      
      <guid>/post/vcpkg%E8%B5%84%E4%BA%A7%E7%BC%93%E5%AD%98%E4%B8%8E%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%BC%93%E5%AD%98/</guid>
      <description>0x01 背景 翻墙用了一段时间的vcpkg了，在项目中使用vcpkg安装管理了一众开源框架
range-v3 catch2 boost fmt opencv4 体验感很好，除了两个问题点
需要翻墙才能安装依赖 就算其他同事也翻墙使用vcpkg，那上面的库他需要从克隆代码，下载二进制，编译，重新来一次，很耗时 于是围绕这两个问题挖掘msdn文档，用这个markdown记录探索过程
0x02 坑 为了解决第1个问题，我把这几个库，以及vcpkg本身，从github上迁移到公司内网的forgejo服务器上，然后尝试修改vcpkg中，包的配置，试图让vcpkg改为从公司内网下载代码。像catch2, fmt, range-v3这几个库，结构比较简单，用这种方式确实成功了，工作量也不大，维护也简单，只需要修改vcpkg源码中这几个库的url，从github改为公司的forgejo路径就行了。但是当我在处理opencv4和boost的时候，我发现光是boost就有一百八十几个git submodule ， 不过这还不足以让我推翻这个方法， 因为我觉得可以通过脚本+ forgejo 的api服务+ access token就能用脚本批量的创建库存，上传代码。 直到我尝试修改opencv的vcpkg中的配置，我发现这些超大规模的大型开源库，并不只是用git clone拉取编译所需要的依赖，有的是通过http下载tar包，zip包。并且有时候并不是opencv4这种顶层项目下载的，而是它的子模块，或子模块的模块下载的。 这样一来，即使把源码都迁移到内网的forgejo上了，仍然会有一些二进制的包，没有在内网之中。 所以这个方案行不通
0x03 最终解 在msdn上把vcpkg相关的文档精读了一下，我发现vcpkg不管是下载的文件，还是编译的文件，都可以缓存 ，而且可以在网络位置上共享。我测试了一下，把两台电脑设置了同样的网络位置的缓存目录，在一台电脑上翻墙，编译boost1.83.0和opencv4.5.5，在另一台电脑上，确实不翻墙的情况下也可以用vcpkg安装boost 1.83.0以及opencv 4.5.5，不需要重新从github下载，。当然还是需要从网络位置下载的，缓存几百兆的二进制文件如果不是在杭州，下载也是需要时间的，但相对来说快了不少。
下面说说怎么配置
1.研发的nas目录 dv-rd中创建缓存目录 vcpkg_asset_cache用于缓存安装过程中下载二进制
vcpkg_binary_cache 用于缓存编译时生成的二进制包
2.配置环境变量，告诉vcpkg从这两目录读写缓存 windows:
VCPKG_BINARY_SOURCES clear;files,Z:/sw/vcpkg_binary_cache/,readwrite
X_VCPKG_ASSET_SOURCES clear;x-azurl,file://Z:/sw/vcpkg_asset_cache/,,readwrite
linux:由于同办法想windows一样把网络位置映射成为磁盘，所以用nfs挂载的方式
1 mount -t nfs 10.2.1.11:/data/syncthing_data /xxxx/xxx 1 2 export X_VCPKG_ASSET_SOURCES=&amp;#34;clear;x-azurl,file:/nfs/vcpkg_cache/vcpkg_cache_linux/asset/,,readwrite&amp;#34; export VCPKG_BINARY_SOURCES=&amp;#34;clear;files,/nfs/vcpkg_cache/vcpkg_cache_linux/binary/,readwrite&amp;#34; 这里也可以配置网络位置只读，加一个本地路径读写，我电脑空间比较紧张，就只配置了远程的了。
然后使用vcpkg安装的时候，就会自动从这里面找缓存了。如果没有的缓存，只需要在翻墙的电脑上用vcpkg安装一下，就会自动上传了。</description>
    </item>
    
    <item>
      <title>创建vcpkg私有仓库</title>
      <link>/post/%E5%88%9B%E5%BB%BAvcpkg%E7%A7%81%E6%9C%89%E4%BB%93%E5%BA%93/</link>
      <pubDate>Fri, 06 Oct 2023 18:48:29 +0800</pubDate>
      
      <guid>/post/%E5%88%9B%E5%BB%BAvcpkg%E7%A7%81%E6%9C%89%E4%BB%93%E5%BA%93/</guid>
      <description>0.前言 ​ 最近在做公司一个新的工程，对标海康的MVS, 基于GENICAM通用协议，目标是适配市场上众多的厂牌的基于GENICAM协议的相机。 由于预计到会引用很多开源项目，且会围绕相机扩展很多公司的业务功能。所以我重新设计了新软件总体的架构，由原来的qmake改为cmake，并使用插件式开发。这即方便于引用其他开源框架，也可以使公司的代码模块化，更容易维护以及复用。但在众多开源模块与公司的模块，以及公司的不同的项目之间要如何处理依赖关系？如何科学的减少重复的工作？满地都是cmake + git submodule，我抬头却看到了vcpkg私有仓库。
1.随便聊聊 1.1 包管理器 ​ python有pip， c#有nuget ， java有maven， 基本上每一个语言都有一个亲妈背书的包管理器，可以递归解决项目依赖，但是c++没有。
语言特性太复杂， 编译选项不一样，同样的代码生成的程序就可能不能一起工作 模块元编程只能以源码方式发布，而不是二进制 ABI兼容性问题导致需要根据cpu架构发布不同的二进制文件版本 ​ 基于上面的问题以及等等，导致c++的包管理不好实现，长久以来，c++开发者如果需要采用其他开源项目，通常需要手动把 其他c++项目的源码，静态链接库，动态链接库集成到自己的项目里，在集成的过程中，往往不是顺利的，可能需要处理依赖关系，环境问题，编译选项问题。
1.2 Cmake cmake的出现简化了这个过程， 它是一款跨平台c++项目的管工具， 可以很方便的把cmake工程集成到另一个cmake工程中，然后指定生成器，生成各种类型的构建工具的项目，如ninja,visual studio 等，，并且它可以枚举项目的依赖项目，但是它没有版本控制的能力，所以通常与git联合使用 。 目前基本主流的IDE都集成了cmake和git，并且c++开源项目大多数也是以cmake的方式组织工程，因此使用cmake+git可以方便的集成开源项目。这也是我想用cmake的原因之一，除此之外，只要项目没有相互依赖，不管所处何目录结点，cmake都支持并行构建（qmkae子目录构建完才会构建父目录），可以更好的利用多核计算机的性能。所以cmake已经足够好了，为什么还需要vcpkg?
​ 想像一下，你有一个巨大的项目，依赖关系比较复杂，如果说顶层项目是第0层，某个第1层的项目A依赖了开源库D，另一个第1层的项目B的第2层项目BA也依赖了项目D， 你如果不修改优化工程结构，你的项目目录里将存在两份D的源码，并且如果修改了其中一份D的代码，需要把它提交给他的父项目们，直到第0层，然后再到另一份D代码处，拉代码后，再一层一层的提交到第0层。这样别人拉取你的第0层代码时，才能简单的git submodule update --init --recursive，克隆下来。而项目中可能会出现多个D项目这样的存在，这意味着即使使用git submodule，也需要做很多重复工作 。 而vcpkg可以解决这种问题,甚至允许控制每份D的代码版本不一样。
1.3 vcpkg ​ vcpkg是微软推出的c++ 源码级别的跨平台包管理器。虽然vc开头，但不仅限于visual c++， 它基本上=git + cmake,但扩展了包管理器应该有的功能，可以方便的解决项目依赖问题，也可以方便切换依赖项目的ABI，Cpu架构，目标平台。 vcpkg有经典模式和清单模式两种模式。
经典模式
允许安装D到系的某个目录，然后所有层级的项目都引用这个 D目录里的cmake module.
清单模式
允许在每个层级cmakelist.txt旁边创建一个vcpkg.json配置文件，把需要的包配置在里面，然后执行 vcpkg install --recursive 递归安装依赖包。
可以看出 清单模式可以解决我在1.2第二段落中描述的问题。但拿来就用还是有一些局限性。以下两种情况
需要针对性修改某个项目中某个vcpkg安装的开源库依赖，编译选项或bugfix，但其不希望他项目被影响 希望把公司的项目需要集成到vcpkg，享受包管理器带来的便利，又不想开源 何以解忧，唯有搭建自己的vcpkg 仓库，这也是本文档想讲的内容(终于酝酿好氛围)
​ 除此这外，vcpkg相对于公司现在的项目管理，还有一个优点，就是减少二进制文件的提交，理论上只提交源码就行，install的时候，vcpkg会根据配置 使用git签出正确分支的源码，构建为本地的二进制文件</description>
    </item>
    
    <item>
      <title>为drone制作qt编译打包的ubuntu环境的docker镜像</title>
      <link>/post/%E4%B8%BAdrone%E5%88%B6%E4%BD%9Cqt%E7%BC%96%E8%AF%91%E6%89%93%E5%8C%85%E7%9A%84ubuntu%E7%8E%AF%E5%A2%83%E7%9A%84docker%E9%95%9C%E5%83%8F/</link>
      <pubDate>Wed, 27 Sep 2023 18:48:29 +0800</pubDate>
      
      <guid>/post/%E4%B8%BAdrone%E5%88%B6%E4%BD%9Cqt%E7%BC%96%E8%AF%91%E6%89%93%E5%8C%85%E7%9A%84ubuntu%E7%8E%AF%E5%A2%83%E7%9A%84docker%E9%95%9C%E5%83%8F/</guid>
      <description>0.前言 之前我已经写了 Drone+Forgejo+SonarQube 持续集成code review的文档，
但在之前的文档中，我们并没有自己动手创建docker，都是用别人做好的镜像。
现在我们需要把开发环境打到docker镜像中，并且把我们的代码库拉到镜像中，做一个基线 ，
每次Forgejo上触发一个webhook时，我们上Drone基于这个基线，执行指令递归拉取所有git submodule，执行打包脚本。
1 三种思路 摆在我们面前有三种选择
编写dockerfile ，从dockerfile生成镜像
直接运行容器，在容器中安装好所有依赖后，把容器实例转换为镜像
用现有的系统直接打成docker镜像
前者的好处是，文件系统分层情况良好，当你有很多镜像时，他们可能可以复用某一些文件层，节约空间和网络流量
不好的地方就是步骤比较繁琐。后者的好处就是操作简单，但基础镜像的分层信息会丢失。
因为我们除了Drone构建打包用docker，基本上没其他事了，ubuntu16裸机的这个分层，复用率不高，另外我们只在ci cd的这台电脑上加载这个镜像，没有什么docker集群，所以也不用担心网络流量的问题。所以综合考虑，我们可以考虑使用第二种方式或第三种方式， 由于我硬盘剩余空间比较小，故采用第二种方式
1 安装docker 由于闫工给我的机器是ubuntu，所以我用apt安装 docker，略
2.制作开发环境docker 2.1 docker镜像 拉取，启动 拉一个下载量最多的
1 root@drone-ci-8-20:~# docker pull homebrew/ubuntu16.04 这时查看电脑上的镜像可以看到已经拉取的
1 2 3 root@drone-ci-8-20:~# docker images REPOSITORY TAG IMAGE ID CREATED SIZE homebrew/ubuntu16.04 latest 6347afdf9148 6 months ago 1.27GB 实例化容器
1 2 root@drone-ci-8-20:~# docker run -d homebrew/ubuntu16.04 tail -f /dev/null ed1c0b7568119b788b940e21fb1b2d50d63c3e9fe74a48a1dabd0d02987b3a5c tail -f /dev/null 会使这个容器一启动就 一直保持运行，这样我们才有机会进去安装环境</description>
    </item>
    
    <item>
      <title>cpp跨平台项目在windows上的文本编码问题</title>
      <link>/post/cpp%E8%B7%A8%E5%B9%B3%E5%8F%B0%E9%A1%B9%E7%9B%AE%E5%9C%A8windows%E4%B8%8A%E7%9A%84%E6%96%87%E6%9C%AC%E7%BC%96%E7%A0%81%E9%97%AE%E9%A2%98/</link>
      <pubDate>Sun, 17 Sep 2023 18:48:29 +0800</pubDate>
      
      <guid>/post/cpp%E8%B7%A8%E5%B9%B3%E5%8F%B0%E9%A1%B9%E7%9B%AE%E5%9C%A8windows%E4%B8%8A%E7%9A%84%E6%96%87%E6%9C%AC%E7%BC%96%E7%A0%81%E9%97%AE%E9%A2%98/</guid>
      <description>1.背景 linux系统和mac os默认使用utf8编码，windows系统上通常是跟随系统设置，如果系统选择为中文地区的话，默认为GBK编码。
windows 10 1703开始，支持把windows编码设置为utf8 。
IDE上一般也是默认是这个配置，但是IDE可以选择编码源码保存为什么格式。
2.跨平台项目遇到的问题 由于linux和windows共用一个代码库，所以源码都使用同一编码格式，在我的情况，我把源码保存为utf8，并在windows上把ide配置为 utf8 不带BOM， FL 格式
BOM，windows字符前加上额外字节的信息，用来让windows认识字符串属于哪种编码
FL , 换行符windows上是CRFL, Mac os是CR ，Linux是FL
同时windows上把编译器设置为输出utf8 格式，
qmake使用 CONFIG += utf8_source 配置，它会根据编码器自动加上utf8的编码选项
至此为止，世界如此美好， 一切显示正常，甚至还能用emoji 表情字符
直到打开文件发现打不开， 调用系统命令行无故执行错误 ,控制台显示乱码
3.解决方法 3.1 使用windows api转换utf8为gbk 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include &amp;lt;sstream&amp;gt; #include &amp;lt;locale&amp;gt; #include &amp;lt;codecvt&amp;gt; inline std::string utf8_to_gbk(const std::string&amp;amp; str) { std::wstring_convert&amp;lt;std::codecvt_utf8&amp;lt;wchar_t&amp;gt;&amp;gt; conv; std::wstring tmp_wstr = conv.</description>
    </item>
    
  </channel>
</rss>
