我需要编译包含多个源文件的Chicken Scheme项目,但我得到错误。
根据手册和这个SO答案,我需要把(declare)
s放在我的源代码中。为什么编译器不能仅仅看到我正在导入另一个源代码,这让我很费解,但是,meh。
问题是,即使我放入(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
编译器说:
语法错误(import): cannot import from undefined module
和
未绑定变量:use
如果我只是删除import
和use
声明为"无限。,文件编译。但是,我有两个问题:
- 在没有
import
和use
子句的情况下,产生的.o
文件实际工作吗?或者它会在运行时抱怨缺少代码吗? -
csi
要求我的代码包含(import)
和(use)
声明,而csc
要求它不包含。然而,我要求我的代码在csi
和csc
中都能工作!
为什么编译器不能看到我正在导入另一个源代码,这让我很费解,但是meh。
声明用于确定依赖关系:编译器需要知道以什么顺序(如果有的话)调用特定的顶层,以确保在使用该单元的任何全局变量之前初始化正确的代码。当所有内容都单独编译时,编译器将不知道何时插入对顶层的调用。传递给csc
的-uses
开关是多余的:csc -uses foo
相当于将(declare (uses foo))
放在源代码中。据我所知,传递-uses foo.o
对文件 foo.o
没有任何作用。
在您的代码片段中,您使用的是load
,这不是在编译时包含代码的正确方式:load
将在运行时读取和计算目标文件。相反,你应该完全省略load
: declare
已经处理了依赖关系;你只需要把它们连在一起。
同样,使用文件名作为模块/单元名也不是很常见,尽管它应该可以工作。
如果我只是删除了import并使用了"infinity "声明。,文件编译。但是,我有两个问题:
1)在没有import和use子句的情况下,生成的。o文件是否实际工作?或者它会在运行时抱怨缺少代码吗?
您需要保留import
表达式,否则程序将无法编译。如果它确实可以编译,那就说明发生了一些奇怪的事情。当您静态地将所有内容链接在一起时,您不需要use
。如果你使用动态链接,你会得到一个运行时错误。
你得到关于unbound variable: use
的错误是因为你在begin-for-syntax
块中使用use
。你可能只需要(import-for-syntax chicken)
,就像你的另一个SO问题一样。
2) csi要求我的代码包含(import)和(use)声明,而CSC则不要求。但是,我要求我的代码在csi和csc中都能工作!
看起来你做得太快了:你正在编写一个完整的程序,同时试图让它运行编译和解释,而没有首先建立对系统如何工作的理解。
在这一点上,首先用一个由两个文件组成的小项目进行试验可能是一个好主意。然后,您可以弄清楚如何编译一个可执行文件,该文件可以从在解释器中也可以工作的代码中运行。然后,使用这些知识来构建实际的程序。如果在任何时候有什么东西坏了,你总是可以回到最小情况,找出你做得不同的地方。这也将有助于获得支持,因为您将能够提供一个完整的,但最少的文件集,人们将能够更快地告诉您哪里出错了,或者您是否发现了一个错误。