mercury - 使用本地模块时出现 Mercury“未定义引用”编译错误
问题描述
我有一个模块导出nat/1
以测试/生成自然数:
:- module nat.
:- interface.
:- import_module int.
:- pred nat(int).
:- mode nat(in) is det.
:- mode nat(out) is multi.
:- implementation.
:- pragma promise_pure(nat/1).
nat(_::in).
nat(0::out).
nat(X::out) :- nat(Y), X = Y + 1.
和同一目录中的主模块进行尝试:
:- module main.
:- interface.
:- import_module io.
:- pred main(io__state::di, io__state::uo) is cc_multi.
:- implementation.
:- import_module nat.
main(!IO) :- nat(X), print(X, !IO).
我运行mmc --make-int nat.m
它成功生成了接口文件,但是当我运行时mmc main.m
出现以下错误:
/usr/bin/ld: main.o: in function `<predicate 'main'/2 mode 0>':
main.c:(.text+0x45): undefined reference to `<predicate 'nat.nat'/1 mode 1>'
collect2: error: ld returned 1 exit status
我正在使用 MMC version 20.06.1, on x86_64-pc-linux-gnu
。
我错过了一些明显的东西吗?代码改进也非常受欢迎。
解决方案
在“mmc --make-int nat.m”之后,需要运行的命令不是“mmc main.m”,而是“mmc main.m nat.m”。前者只编译main.m,而后者也编译 nat.m。两者都尝试从生成的目标文件构建可执行文件,但前者会失败,因为“nat”谓词的定义将在它不生成的目标文件中。
通常,与其尝试手动管理接口文件、目标文件和可执行文件的创建,不如使用自动构建系统更容易:mmake 脚本或 mmc --make。
至于代码改进,我建议用简单的 io 替换 io__state,这要短得多。我们在 io.m 中添加了“io”作为“状态”类型的同义词,专门使这成为可能。
推荐阅读
- dynamics-crm - Microsoft Dynamics 365 CRM 中的“对象引用未设置为对象的实例”,同时添加新的订单产品记录
- powerbi - 删除公式中的周末
- javascript - 在数组内的对象内填充数组
- php - 带有前缀和年/月数据的自动增量字段
- mongodb - 没有访问控制无法启动mongodb
- android - 我们可以在styles.xml 中有两个不同的textStyle 吗?
- python - 在 Python 中使用 Pool 类进行多处理会产生 Pickling 错误
- java - 自定义类加载器以限制对类的访问
- android - 如何创建多个指纹扫描并在数据库中注册?
- ios - 使用 Swift 5 - PDFKit 在 iOS 中编辑和保存现有的 pdf 文档