【问题标题】:How to compile multiple Chicken Scheme files?如何编译多个鸡计划文件?
【发布时间】:2016-12-22 06:06:05
【问题描述】:

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

根据the manualthis 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. 在没有importuse 子句的情况下,生成的.o 文件是否真的有效?还是会在运行时抱怨缺少代码?
  2. csi 要求我的代码包含 (import)(use) 声明,而 csc 要求它不包含。 但是,我要求我的代码在 csicsc 中都有效!

请问我该如何解决?

【问题讨论】:

    标签: compilation compiler-errors scheme chicken-scheme


    【解决方案1】:

    为什么编译器不能只看到我正在导入其他源,这超出了我的理解范围,但是嗯。

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

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

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

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

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

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

    您收到有关 unbound variable: use 的错误是因为您在 begin-for-syntax 块中使用了 use。根据your other SO question,您可能只需要(import-for-syntax chicken)

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

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

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

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

    【讨论】:

    • 但是如果我省略了load,解释器怎么知道在哪里可以找到我的包含?
    • 仅供参考,使用文件名作为单位名称是我的错字。我的意思是只使用“infinity.general”之类的。
    • 您可以使用include 代替load,后者在文本中包含另一个文件所在的源文件。它适用于解释器编译器。但我不确定您是否愿意这样做,因为它与在 C 文件中使用 #include "other-file.c" 基本相同。另一种选择是仅在解释器中运行时使用cond-expandload,否则将编译的对象链接在一起。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多