5

我需要编译一个包含多个源文件的 Chicken Scheme 项目,但我遇到了错误。

根据手册这个 SO answer,我需要将(declare)s 放入我的来源。为什么编译器不能只看到我正在导入另一个源代码超出了我的范围,但是嗯。

问题是,即使我把(declare)s 放进去,编译器也会抱怨(import)s 和(use)s。

infinity.filesystem.scm:

(use bindings filepath posix)
(declare (uses infinity.general.scm))
(load-relative "infinity.general.scm")

(module infinity.filesystem (with-open-file make-absolute-path with-temporary-directory with-chdir)
 (import scheme filepath posix infinity.general)
 (begin-for-syntax
  (use bindings chicken)
  (import infinity.general))

 ...etc...

infinity.general.scm:

(declare (unit infinity.general.scm))
(require-extension srfi-1 srfi-13 format data-structures ansi-escape-sequences basic-sequences)
(module infinity.general (bind+ format-ansi repeat-string join-strings pop-chars! inc! dec!
                          take* drop* take-right* drop-right* ends-with? take-where)
 (import scheme chicken srfi-1 srfi-13 data-structures ansi-escape-sequences basic-sequences bindings ports format)

 ...etc...

命令:

$ csc -uses bindings.o -uses infinity.general.o -c infinity.filesystem.scm -o infinity.filesystem.o

编译器说:

语法错误(导入):无法从未定义的模块导入

未绑定变量:使用

如果我只是删除“infinity.general”的importuse声明,文件就会编译。但是,我有两个问题:

  1. 在没有and子句的情况下,生成的.o文件会真正起作用吗?或者它会在运行时抱怨缺少代码?importuse
  2. csi要求我的代码包含(import)(use)声明,而csc要求它不包含。但是,我要求我的代码同时适用于csicsc

请问我该如何解决?

4

1 回答 1

3

为什么编译器不能只看到我正在导入另一个源代码超出了我的范围,但是嗯。

声明用于确定依赖关系:编译器需要知道调用特定顶层的顺序(如果有的话),以确保在可以使用来自该单元的任何全局变量之前初始化正确的代码。当所有内容都单独编译时,编译器不知道何时插入对顶层的调用。-uses您传递给的开关csc是多余的:csc -uses foo相当于放入(declare (uses foo))源代码。据我所知,传递对文件-uses foo.o没有任何作用。 foo.o

在您的代码片段中,您正在使用load,这不是在编译时包含代码的正确方法:load将在运行时读取和评估目标文件。相反,您应该完全省略loaddeclare已经处理了依赖项;您只需要将它们链接在一起。

此外,将文件名用作模块/单元名称并不常见,尽管它应该可以工作。

如果我只是删除“infinity.general”的导入和使用声明,文件就会编译。但是,我有两个问题:

1) 如果没有 import 和 use 子句,生成的 .o 文件是否真的可以工作?或者它会在运行时抱怨缺少代码?

您需要保留import表达式,否则程序不应该编译。如果它确实编译,就会发生一些奇怪的事情。use当您将所有内容静态链接在一起时,您不需要。如果您使用动态链接,您将收到运行时错误。

你得到的错误unbound variable: use是因为你use在一个begin-for-syntax块中使用。(import-for-syntax chicken)根据您的其他 SO 问题,您可能只需要这样做。

2) csi 要求我的代码包含 (import) 和 (use) 声明,而 csc 要求它不包含。但是,我要求我的代码在 csi 和 csc 中都有效!

看起来你处理这个问题的速度太快了:你正在编写一个完整的程序,同时试图让它运行编译和解释,而没有首先了解系统是如何工作的。

此时,首先尝试一个由两个文件组成的小项目可能是一个好主意。然后,您可以弄清楚如何编译一个可执行文件,该可执行文件的代码也适用于解释器。然后,使用这些知识来构建实际的程序。如果在任何时候出现问题,您总是可以回到最小的情况并找出您正在做的不同之处。

这也将有助于获得支持,因为您将能够提供完整但最少的文件集,并且人们将能够更快地告诉您哪里出错了,或者您是否发现了错误。

于 2016-08-16T06:51:14.747 回答