跳到主要内容

CMake构建第三方开源库

C/C++用户库可以通过 CMake 构建第三方开源库,并将开源库提供的源码、头文件或预编译库集成到 PLC 工程中。本文以 FFTW 这类第三方源码库为例,说明如何把第三方源码加入用户库构建,并通过 IDE 菜单完成 CMake 构建和编译。

提示

本文重点说明第三方开源库的构建集成。用户库函数、功能块的接口创建和代码实现,请参考 C/C++ 用户库的其他说明文档。

操作流程

整体流程如下:

  1. 创建 C/C++ 用户库,并创建需要导出的函数或功能块接口。
  2. 将第三方开源库源码复制到用户库目录下。
  3. 配置第三方源码、头文件和编译选项。
  4. 执行 CMake构建,检查 CMake 配置是否正确。
  5. 执行 编译,生成用户库构建产物。
  6. 在 ST 程序中调用用户库导出的函数或功能块。

创建C/C++用户库

在工程中创建一个 C/C++ 用户库。例如创建名为 fftw 的用户库,并创建一个函数 FFT_TEST 作为 ST 侧调用入口。

创建C/C++用户库

创建完成后,工程树中会出现用户库节点。WasomeCodeX_AI 会为该用户库自动生成 CMakeLists.txt.MODULE 目录和接口框架代码。

C/C++用户库工程结构

典型目录结构如下:

MODULES/
└── fftw/
├── .MODULE/
│ └── cpp/
├── implements/
│ └── cpp/
├── CMakeLists.txt
└── wa_module.h

放置第三方源码

将第三方开源库源码复制到当前 C/C++ 用户库目录下。以 FFTW 为例,可将解压后的 fftw-3.3.10 放到 MODULES/fftw 目录中。

MODULES/
└── fftw/
├── .MODULE/
├── implements/
├── fftw-3.3.10/
│ ├── api/
│ ├── dft/
│ ├── kernel/
│ ├── rdft/
│ ├── reodft/
│ ├── simd-support/
│ └── config.h
├── CMakeLists.txt
└── module.cmake
注意

建议把第三方源码放在用户库目录内部,不建议引用工程外部的绝对路径。这样工程迁移、打包和多人协作时不容易出现路径失效问题。

第三方库内容通常按以下方式接入:

类型示例处理方式
源码库.c.cpp加入 MOD_EXTRA_SRCMOD_FULL_SRC
头文件.h.hpp加入包含路径
静态库.a加入链接库
目标文件.o.obj作为额外源文件或链接输入加入

配置第三方源码参与编译

用户库的 CMake 配置有两种方式:

方案做法适用场景
方案一直接修改 CMakeLists.txt临时验证、快速试验
方案二创建 module.cmake推荐用于正式工程和长期维护

方案一:直接修改CMakeLists.txt

用户可以打开用户库根目录下的 CMakeLists.txt,直接设置 MOD_EXTRA_SRCMOD_FULL_SRCMOD_EXTRA_INCLUDE_DIRS 等变量。

CMakeLists.txt 中通常会包含类似说明:

## --- 源文件 ---
## 自动生成的 wasome.cmake 会将自动扫描到的当前目录及子目录下的源文件填入私有列表,
## 可通过以下变量覆盖或补充。
#set(MOD_FULL_SRC src/a.c src/b.cpp) # 完全替换自动发现的源文件列表
#set(MOD_EXTRA_SRC vendor/x.c vendor/y.c) # 在自动列表之后追加源文件

## --- 包含路径与预处理 ---
#set(MOD_EXTRA_INCLUDE_DIRS third_party/include inc)
#set(MOD_COMPILE_DEFINITIONS DEBUG=1 USE_FOO) # 不带 -D 前缀

这种方式简单直接,适合快速确认第三方库是否能参与编译。但如果后续执行 重新生成CMakeLists文件,手动写入的内容可能被覆盖或需要重新整理。

方案二:创建module.cmake

推荐在用户库根目录创建 module.cmake,将第三方源码、头文件路径、编译选项和链接配置写在该文件中。用户库构建时会自动包含 module.cmake

推荐原因:

原因说明
避免生成文件被覆盖CMakeLists.txt 可能随接口或工程操作重新生成
配置更集中第三方库相关 CMake 内容都放在一个文件中
便于迁移维护拷贝用户库目录时,第三方源码和配置可以一起迁移
便于排查问题构建失败时可以优先检查 module.cmake 中的路径、源码和选项

module.cmake 示例:

set(FFTW3_DIR ${CMAKE_CURRENT_LIST_DIR}/fftw-3.3.10)

enable_language(C)

file(GLOB fftw_api_SOURCE ${FFTW3_DIR}/api/*.c)
file(GLOB fftw_dft_SOURCE ${FFTW3_DIR}/dft/*.c)
file(GLOB fftw_kernel_SOURCE ${FFTW3_DIR}/kernel/*.c)
file(GLOB fftw_rdft_SOURCE ${FFTW3_DIR}/rdft/*.c)
file(GLOB fftw_reodft_SOURCE ${FFTW3_DIR}/reodft/*.c)
file(GLOB fftw_simd_SOURCE ${FFTW3_DIR}/simd-support/*.c)

set(SOURCEFILES
${fftw_api_SOURCE}
${fftw_dft_SOURCE}
${fftw_kernel_SOURCE}
${fftw_rdft_SOURCE}
${fftw_reodft_SOURCE}
${fftw_simd_SOURCE}
)

include_directories(
${FFTW3_DIR}
${FFTW3_DIR}/api
)

set(MOD_EXTRA_SRC
${SOURCEFILES}
${CMAKE_CURRENT_LIST_DIR}/implements/cpp/wa_func.cpp
)

MOD_EXTRA_SRC与MOD_FULL_SRC

配置第三方源码时,常用变量如下:

变量说明建议
MOD_EXTRA_SRC在 IDE 自动扫描到的源文件之后追加源码推荐优先使用
MOD_FULL_SRC完全替换自动扫描结果,只使用指定源码需要完全控制编译输入时使用
MOD_EXTRA_INCLUDE_DIRS追加头文件搜索路径适合简单头文件目录
MOD_COMPILE_DEFINITIONS追加预处理宏定义不需要写 -D 前缀
MOD_LINK_LIBRARIES追加链接库引入 .a 或系统库时使用

MOD_FULL_SRC 示例:

set(MOD_FULL_SRC
${SOURCEFILES}
${CMAKE_CURRENT_LIST_DIR}/implements/cpp/wa_func.cpp
${CMAKE_CURRENT_LIST_DIR}/.MODULE/cpp/wa_interface.cpp
)
注意

使用 MOD_FULL_SRC 时,需要把用户库接口桥接文件一并加入,例如 .MODULE/cpp/wa_interface.cpp。否则 PLC 侧可能无法调用用户库导出的函数或功能块。

排除不需要的第三方源码

第三方开源库经常包含测试程序、命令行工具、平台相关代码或可选特性。这些文件不一定适合 PLC 目标环境,需要从编译列表中排除。

list(REMOVE_ITEM SOURCEFILES
${FFTW3_DIR}/libbench2/useropt.c
${FFTW3_DIR}/tools/some_command_line_tool.c
)

常见需要关注的源码类型:

类型处理建议
测试程序通常不加入用户库编译
命令行工具通常依赖 main、文件系统或终端输入,不加入编译
平台汇编/SIMD目标工具链不支持时关闭或排除
线程/OpenMP目标环境不支持时关闭相关选项
文件系统访问PLC 运行环境不支持时需要适配或禁用

执行CMake构建和编译

在工程树中右键点击 C/C++ 用户库,可以看到构建相关操作。

C/C++用户库右键菜单

右键菜单中与第三方库构建相关的操作如下:

菜单项作用使用时机
编译执行 CMake 配置、编译、链接和安装,生成用户库构建产物CMake 配置已经准备好,需要生成可被 PLC 工程使用的用户库时
清除编译清理当前用户库的构建产物和中间文件修改源码列表、编译选项或第三方库目录后,需要重新完整构建时
CMake构建只执行 CMake 配置,不执行实际编译修改 CMakeLists.txtmodule.cmake 后,先检查路径、源文件和选项是否正确
打开CMakeLists文件打开用户库根目录下的 CMakeLists.txt查看 IDE 生成的 CMake 入口文件,或临时修改 MOD_* 配置
生成接口代码根据用户库函数、功能块接口重新生成 C/C++ 框架代码修改用户库 POU 接口后,需要同步生成 C/C++ 调用框架时
重新生成CMakeLists文件重新生成用户库标准 CMakeLists.txtCMakeLists.txt 被误改或需要恢复 IDE 默认结构时
日志打开 CMake 构建日志和编译日志CMake 构建或编译失败,需要查看详细错误原因时
在文件浏览器中显示打开用户库所在的磁盘目录检查第三方源码、module.cmake 和用户实现文件是否放置正确
提示

集成第三方开源库时,建议先执行 CMake构建。确认 CMake 配置通过后,再执行 编译。这样可以先排查路径、源码列表和头文件配置问题,避免直接进入大量源码编译后才发现配置错误。

建议按以下顺序执行:

  1. 执行 CMake构建,检查路径、源文件列表、头文件目录和编译选项是否正确。
  2. CMake 构建成功后,执行 编译,生成用户库构建产物。

构建成功时,终端会显示类似信息:

正在运行 CMake 构建配置 — fftw
cmake 配置 ... (日志: .generate/cpp_building/fftw/release/logs/cmake-configure.log)
-> cmake 配置 OK
用户库 'fftw' 已完成 CMake 构建配置

编译成功时,终端会显示类似信息:

正在编译用户库 — fftw
cmake 配置 ...
-> cmake 配置 OK
[编译与安装] ...
Linking CXX static library libfftw.a
用户库 'fftw' 编译成功

查看文件和日志

在右键菜单中选择 在文件浏览器中显示,可以确认第三方源码、module.cmake、用户实现文件是否都在用户库目录内。

用户库文件浏览器视图

在文件浏览器视图中,点击工具栏的项目视图按钮可以返回工程项目树。

返回工程项目视图

构建失败时,可通过右键菜单中的 日志 查看 CMake 构建日志和编译日志。常见问题如下:

问题常见原因处理建议
找不到源码目录第三方库目录名称或路径不一致检查 ${CMAKE_CURRENT_LIST_DIR} 拼接路径
找不到头文件未配置 include 路径补充 include_directoriesMOD_EXTRA_INCLUDE_DIRS
源文件未参与编译file(GLOB ...) 路径不匹配检查源码实际目录和变量内容
undefined reference源文件缺失或库未链接补充源码,或加入 MOD_LINK_LIBRARIES
multiple definition同一源文件被重复加入检查自动扫描和 MOD_EXTRA_SRC 是否重复
出现 main 冲突加入了测试程序或工具程序排除测试目录、示例目录或命令行工具

在ST程序中调用验证

编译成功后,即可在 ST 程序中调用 C/C++ 用户库导出的函数或功能块。

PROGRAM DEMO_PLC_PRG1
VAR
END_VAR

FFT_TEST();
END_PROGRAM

验证建议:

验证点说明
ST 编译是否通过确认用户库接口已正确生成
C/C++ 编译是否通过确认第三方源码和用户实现均可构建
在线运行是否正常确认第三方库运行时没有访问不支持的系统能力
断点调试是否进入用户函数确认 ST 调用链已经进入 C/C++ 用户库
提示

构建大型开源库时,不建议一次性加入全部源码目录。更稳妥的方式是先加入核心源码和头文件,让一个最小调用编译通过,再逐步打开可选功能。