news 2026/8/28 18:11:49

OpenPLC Runtime v4 编译流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenPLC Runtime v4 编译流程

编译流程

概述

OpenPLC Runtime v4 采用现代编译流程:用户上传由 OpenPLC Editor v4 生成的 ZIP 文件,运行时自动编译并加载 PLC 程序。

构建流水线

1. 在 OpenPLC Editor 中创建程序

用户在 OpenPLC Editor v4 中创建他们的 PLC 程序:

  1. 编写梯形图逻辑、结构化文本或其他 IEC 61131-3 语言
  2. 定义定位变量 (例如:%IX0.0, %QX0.0)
  3. 在编辑器中点击"编译"(本地编译:JSON → XML → ST → C)
  4. 点击"上传到运行时" - 编辑器将源文件打包成program.zip并上传

2. ZIP 文件上传

OpenPLC Editor 通过 REST API 上传 ZIP 文件:

端点:POST /api/upload-file
认证:JWT 令牌 (Bearer 头部)

文件内容:

  • LOCATED_VARIABLES.h- 变量定位定义
  • Config0.c- PLC 配置
  • Res0.c- 资源配置
  • debug.c- 调试支持代码
  • glueVars.c- 变量绑定代码
  • c_blocks_code.cpp- 自定义 C/C++ 功能块
  • lib/- IEC 61131-3 类型的头文件

3. 安全验证

在解压之前,ZIP 文件需经过安全检查:

执行的检查:

  • 有效的 ZIP 文件格式
  • 无路径遍历攻击尝试 (.., 绝对路径,:)
  • 文件大小限制 (单个文件 10 MB, 总计 50 MB)
  • 压缩率检查 (ZIP 炸弹检测, 最大比率 1000:1)
  • 扩展名白名单 (阻止 .exe, .dll, .sh, .bat, .js, .vbs, .scr)

实现:webserver/plcapp_management.py:analyze_zip()

4. 安全提取

如果验证通过,文件将被提取到core/generated/

提取功能:

  • 剥离 macOS 元数据 (__MACOSX/.DS_Store)
  • 如果存在单一根文件夹,则自动移除
  • 验证提取路径保持在目标目录内
  • 创建必要的子目录

实现:webserver/plcapp_management.py:safe_extract()

5. 编译

编译过程在后台线程中运行:

步骤 5a:编译脚本

脚本:scripts/compile.sh

过程:

  1. 验证所需文件是否存在:

    • Config0.c
    • Res0.c
    • debug.c
    • glueVars.c
    • lib/目录
  2. 将每个源文件编译为目标代码:

    gcc -w -O3 -fPIC -I core/generated/lib -c Config0.c -o build/Config0.o gcc -w -O3 -fPIC -I core/generated/lib -c Res0.c -o build/Res0.o gcc -w -O3 -fPIC -I core/generated/lib -c debug.c -o build/debug.o gcc -w -O3 -fPIC -I core/generated/lib -c glueVars.c -o build/glueVars.o g++ -w -O3 -fPIC -I core/generated/lib -c c_blocks_code.cpp -o build/c_blocks_code.o
  3. 将目标文件链接为共享库:

    g++ -w -O3 -fPIC -shared -o build/new_libplc.so\build/Config0.o build/Res0.o build/debug.o\build/glueVars.o build/c_blocks_code.o

编译器标志:

  • -w- 抑制警告
  • -O3- 最大程度优化
  • -fPIC- 位置无关代码 (共享库必需)
步骤 5b:清理脚本

脚本:scripts/compile-clean.sh

过程:

  1. 停止 PLC 运行时 (如果正在运行)
  2. 删除旧库文件:build/libplc_*.so
  3. build/new_libplc.so重命名为build/libplc_<时间戳>.so
  4. 删除目标文件:build/*.o

时间戳格式:Unix 纪元秒数 (例如,libplc_1700000000.so)

目的:唯一的库名可防止缓存问题并允许回滚

6. 构建状态跟踪

构建过程在整个编译期间维护状态:

状态:

  • IDLE- 无构建进行中
  • UNZIPPING- 正在解压 ZIP 文件
  • COMPILING- 正在运行编译脚本
  • SUCCESS- 构建成功完成
  • FAILED- 构建失败 (查看日志)

状态端点:GET /api/compilation-status

响应:

{"status":"SUCCESS","logs":["[INFO] 开始编译","..."],"exit_code":0}

7. 程序加载

如果编译成功,运行时自动加载新程序:

  1. 停止 PLC:运行时转换到 STOPPED 状态
  2. 卸载旧程序:通过dlclose()卸载先前的库
  3. 加载新库dlopen()加载libplc_<时间戳>.so
  4. 解析符号dlsym()解析函数指针:
    • ext_config_init__()- 初始化
    • ext_config_run__()- 扫描周期执行
    • ext_get_var_*()- 变量元数据函数
  5. 初始化:调用ext_config_init__()
  6. 启动 PLC:运行时转换到 RUNNING 状态

实现:core/src/plc_app/plc_state_manager.c

编译日志

构建输出会实时流式传输到客户端:

  • stdout- 普通编译消息
  • stderr- 错误消息 (以[ERROR]为前缀)

日志被缓存在build_state.logs中,可通过compilation-status端点访问。

错误处理

验证失败

如果 ZIP 验证失败:

  • 构建状态设置为FAILED
  • 返回描述性错误消息
  • 不提取任何文件

编译失败

如果编译失败:

  • 构建状态设置为FAILED
  • 编译器错误消息被捕获到日志中
  • 退出代码被保留用于调试
  • 旧的 PLC 程序保持加载状态 (如果有)

恢复

构建失败后:

  1. 在 OpenPLC Editor 中修复问题
  2. 生成新的 ZIP 文件
  3. 再次上传 (先前的构建状态会自动清除)

文件位置

源文件

  • 上传目标目录:core/generated/
  • 临时文件:编译后清理

构建产物

  • 目标文件:build/*.o(链接后删除)
  • 共享库:build/libplc_<时间戳>.so
  • 可执行文件:build/plc_main(运行时核心)

日志

  • 构建日志:内存中的缓冲区,可通过 API 访问
  • 运行时日志:Unix 套接字到 Web 服务器

手动编译 (开发)

为了开发和测试,您可以手动编译:

先决条件

sudoapt-getinstallbuild-essential cmake python3

步骤

  1. 准备源文件core/generated/目录中:

    • 从 OpenPLC Editor 生成或从 ZIP 文件中提取
  2. 运行编译:

    bashscripts/compile.sh
  3. 运行清理:

    bashscripts/compile-clean.sh
  4. 重启运行时:

    sudobashstart_openplc.sh

高级主题

自定义编译器标志

要修改编译器标志,请编辑scripts/compile.sh

FLAGS="-w -O3 -fPIC"# 当前标志

常见的修改:

  • -g- 添加调试符号
  • -O0- 为调试禁用优化
  • -Wall- 启用所有警告

交叉编译

为了交叉编译到不同的架构:

  1. 安装交叉编译器工具链
  2. 修改scripts/compile.sh以使用交叉编译器
  3. 设置适当的架构标志

ARM 示例:

CC=arm-linux-gnueabihf-gccCXX=arm-linux-gnueabihf-g++

库依赖

编译后的 PLC 程序可能依赖于:

  • IEC 61131-3 运行时- 由lib/中的头文件提供
  • 数学库- 如果使用数学函数,链接-lm
  • 线程库- 如果使用线程,链接-lpthread

scripts/compile.sh的链接步骤中添加依赖项。

故障排除

缺少源文件

错误:[ERROR] 缺少必需的源文件

解决方案:确保 ZIP 文件包含来自 OpenPLC Editor 的所有必需文件

编译错误

错误:日志中的编译器错误

解决方案:

  1. 在 OpenPLC Editor 中检查 PLC 程序语法
  2. 验证功能块中的自定义 C/C++ 代码
  3. 查看编译日志以获取具体错误

库加载失败

错误:Failed to load PLC program

解决方案:

  1. 检查库文件是否存在:ls -la build/libplc_*.so
  2. 验证库是否有效:file build/libplc_*.so
  3. 在运行时日志中检查 dlopen 错误

权限错误

错误:编译期间出现Permission denied

解决方案:

  1. 确保对build/目录有写权限
  2. 以适当的权限运行
  3. 检查 SELinux/AppArmor 策略

相关文档

  • 编辑器集成 - OpenPLC Editor 如何上传程序
  • 架构 - 系统概述
  • API 参考 - 上传端点详情
  • 安全 - 文件验证详情
  • 故障排除 - 常见问题
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/21 13:42:05

燕尾潮汐表查询2026-02-03

位置&#xff1a;燕尾&#xff0c;日期&#xff1a;2026-02-03&#xff0c;农历&#xff1a;乙巳[蛇]年十二(腊)月十六&#xff0c;星期&#xff1a;星期二&#xff0c;潮汐类型&#xff1a;大潮活汛 最高水位&#xff1a;469.00cm&#xff0c;最低水位&#xff1a;59.00cm&a…

作者头像 李华
网站建设 2026/8/21 13:42:34

人工智能应用-机器听觉:3.早期的语音合成器

1769 年&#xff0c;匈牙利发明家沃尔夫冈冯肯佩伦&#xff08;Wolfgang von Kempelen&#xff09;依据人类发声原理制作了一台机械发声器&#xff0c;这是让机器“开口说话”的早期尝试之一。如图所示&#xff0c;这台机械装置的皮质风箱相当于人类的肺&#xff0c;木质空箱内…

作者头像 李华
网站建设 2026/8/21 13:43:06

26.11 风险管理

一、风险管理各过程常见问题&#xff08;1&#xff09;规划风险管理问题类型具体表现计划缺失或不规范• 未开展风险管理规划• 由项目经理一人编制计划&#xff0c;未团队参与• 仅照搬历史模板&#xff0c;未结合当前项目特点流程缺陷• 计划未经讨论直接签发实施• 缺乏沟通…

作者头像 李华
网站建设 2026/8/25 14:09:31

计算机网络经典问题透视:简述一下无线局域网中的NAV

引言&#xff1a;无线信道中的“交通规则”制定者 在当今高度互联的世界&#xff0c;无线局域网&#xff08;WLAN&#xff09;已成为我们数字生活的基石。然而&#xff0c;无线信道&#xff0c;这个看不见的“以太”&#xff0c;本质上是一个开放、共享且混乱的广播媒介。想象…

作者头像 李华
网站建设 2026/8/21 13:42:14

微信支付商家转账,支持多微信商户号

大家好&#xff0c;我是小悟。 商家转账支持微信商户向用户微信零钱转账&#xff0c;为商户提供免费、安全的转账服务&#xff0c;资金实时到账。可用于现金营销、企业赔付、佣金报酬、采购货款、二手回收、公益补助、行政补贴、保险理赔等场景。 安全增强&#xff1a;微信提…

作者头像 李华
网站建设 2026/8/22 5:23:26

2010-2025年地级市长期护理保险制度试点DID

数据简介 长期护理保险制度试点政策是我国为应对老龄化、解决失能人员护理难题而建的独立社保制度。它以社会互助筹集资金&#xff0c;初期覆盖职工医保人群&#xff0c;为重度失能且持续6个月以上的老残人员提供费用补偿或服务保障&#xff0c;基金支付约70%&#xff0c;旨在…

作者头像 李华