You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

用emcc编译JModelica导出的FMU C代码遇问题及RT/NRT咨询

解决Emscripten编译JModelica导出FMU代码的头文件问题,以及RT/NRT参数详解

我来梳理下你遇到的问题和对应的解决方案,顺便把RT、NRT的含义和注意事项讲清楚:

先回顾下你的环境和问题链

你的环境:

  • Ubuntu 18.10(64位)
  • JModelica r12614
  • Emscripten(emcc 1.3820 / clang 6.0.1)

你在编译JModelica导出的BouncingBall FMU代码时,先是碰到了gnu/stubs-32.h找不到的错误,后来去掉系统头文件又遇到linux/limits.h缺失,最终加了-DRT参数编译成功,但想知道这两个宏的意义和潜在问题。


第一个错误:gnu/stubs-32.h找不到的根源和规避

错误触发场景

你一开始的编译命令带了一堆系统头文件路径:

emcc -I /usr/include/ -I /usr/include/x86_64-linux-gnu/ -I /usr/include/x86_64-linux-gnu/bits/ -I /home/osboxes/Programme/JModelica/include/RuntimeLibrary/ -I /home/osboxes/Programme/JModelica/ThirdParty/FMI/2.0/ BouncingBall.c

结果报错:

/usr/include/x86_64-linux-gnu/gnu/stubs.h:7:11 fatal error: 'gnu/stubs-32.h' file not found

为什么会这样?

gnu/stubs.h里的分支逻辑:

#if !defined __x86_64__
# include <gnu/stubs-32.h>
#endif
#if defined __x86_64__ && defined __LP64__
# include <gnu/stubs-64.h>
#endif
#if defined __x86_64__ && defined __ILP32__
# include <gnu/stubs-x32.h>
#endif

Emscripten虽然是64位目标编译,但默认没定义__LP64__宏,导致编译器跳过了64位头文件的引入,反而去加载32位的stubs-32.h——但Emscripten根本不支持32位编译,装libc6-dev:i386也没用。

最直接的解决思路

别加系统头文件路径!因为你要编译的是WebAssembly目标,Emscripten有自己的标准库实现,原生Linux的系统头文件反而会搞出兼容性问题。JModelica导出的FMU代码依赖的RuntimeLibrary和FMI头文件已经足够,完全不需要系统头文件。


第二个错误:linux/limits.h找不到的解决

错误触发场景

去掉系统头文件后执行:

emcc -I /home/osboxes/Programme/JModelica/include/RuntimeLibrary/ -I /home/osboxes/Programme/JModelica/ThirdParty/FMI/2.0/ BouncingBall.c

又报错linux/limits.h找不到,这是因为JModelica的jmi_utils.h里的逻辑:

...
#if !defined(NO_FILE_SYSTEM) && (defined(RT) || defined(NRT))
#define NO_FILE_SYSTEM
#endif
#ifndef NO_FILE_SYSTEM
#ifdef _WIN32
#include <windows.h>
#define JMI_PATH_MAX MAX_PATH
#else
#define _GNU_SOURCE
#include <dlfcn.h>
#ifdef __APPLE__
#include <limits.h>
#define JMI_PATH_MAX PATH_MAX
#else
#include <linux/limits.h>
#define JMI_PATH_MAX PATH_MAX
#endif
#endif
#include <sys/types.h>
#include <sys/stat.h>
#endif
...

这段代码的意思是:如果没定义NO_FILE_SYSTEM,就会引入系统文件相关的头文件;但如果定义了RT或者NRT,就会自动定义NO_FILE_SYSTEM,跳过这些系统头文件的加载。

解决方法

-DRT参数编译就行,也就是你最后用的命令:

emcc -I /home/osboxes/Programme/JModelica/include/RuntimeLibrary/ -I /home/osboxes/Programme/JModelica/ThirdParty/FMI/2.0/ BouncingBall.c -DRT

这样就跳过了系统文件头文件的引入,编译自然成功。


重点:RT和NRT到底是什么?用的时候要注意什么?

含义解析

这两个是JModelica RuntimeLibrary的编译控制宏,用来切换功能模式:

  • RT:是Real-Time的缩写,对应实时仿真模式。实时场景下绝对不能有阻塞式的文件IO操作(会破坏实时性),所以定义RT后,RuntimeLibrary会自动禁用所有文件系统相关功能,只保留核心的仿真计算逻辑。
  • NRT:是轻量非实时模式——同样会禁用文件系统功能,但更侧重无依赖的轻量运行,适合像WebAssembly这种没有原生文件系统的环境,或者不需要实时性但要最小化体积的场景。

简单说,这两个宏的核心作用都是告诉RuntimeLibrary:别碰文件系统,我不需要这个功能

必须注意的问题

  1. 功能限制:一旦定义了RT/NRT,你的FMU模型就完全不能进行任何文件操作了——比如读取外部参数文件、输出结果到本地文件这些逻辑都会失效。如果你的模型原本有这类依赖,得先修改模型,改用内存中的数据传递(比如通过FMU的输入输出接口传递数据)。
  2. 环境适配:WebAssembly本身就没有原生文件系统(除非用Emscripten的虚拟文件系统模拟),所以你用-DRT完全适配这个场景,不会有额外问题。但如果之后要把这个代码编译回原生Linux程序,可能需要去掉这个参数,或者重新适配文件系统逻辑。
  3. 兼容性:这两个宏是JModelica专属的,其他工具(比如OpenModelica)导出的FMU代码可能不支持,别乱用。

内容的提问来源于stack exchange,提问作者19leunam93

火山引擎 最新活动