首页 文章

如何编译这个Chicken Scheme代码?

提问于
浏览
2

显然我的previous question太广了 . 所以这里的问题是再次,简化,以及示例源代码 .

我正在尝试编译包含多个文件的Chicken Scheme项目:

test-a.scm:

#!/usr/bin/csi -script

(declare (unit test-a))
(declare (uses test-b))

(load "test-b.scm")
(use test-b)

(test-syntax)

test-b.scm:

(declare (unit test-b))

(module test-b *
 (import scheme chicken)
 (define-syntax test-syntax
  (syntax-rules ()
   ((_)
    (print "In test-syntax")))))

根据official manual,我应该这样做:

csc -c test-b.scm
csc -c test-a.scm
csc test-a.o test-b.o -o test

我真正得到的是:

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

注意事项:

  • 我正在调用一个宏 .

  • 我有 (declare (uses 条款,但csc找不到我的来源 .

  • csc test-a.scm test-b.o -o test 也不起作用 .

  • 如果删除 load ,程序将无法在csi中运行 .

  • 如果我删除 use ,程序将无法在csi中运行 .

  • 我需要程序在csi中工作 .

如何, without breaking compatibility with csi ,我能编译吗?

1 回答

  • 1

    这里有四个(!)问题:

    • test-a.scm 包含单位声明 . 这是不正确的;总有一个文件需要编译才能具有 main() C函数 . 那是没有单位声明的文件 . 如果您研究更紧密地链接的手册页,它会说“在这种情况下 foo.scm 是主要模块,因为它没有单位声明” .

    • 由于您决定使用模块,因此需要按如下方式编译 test-b.scmcsc -c -j test-b test-b.scm . -j 开关将使编译器发出模块库 test-b.import.scm ,这是编译器在编译 test-a.scm 时要查找的内容 . 当缺少导入库时,它会抱怨模块未定义 . 在解释器中它没有问题,因为在导入它定义的模块之前你是 load 文件 .

    • 您正在使用 load ,即使在程序的编译版本中也是如此 . 这意味着它将在每种情况下读取和评估 test-b.scm 文件(并在其丢失时进行投诉) .

    • 您正在使用 use ,这将在运行时需要库 . 这用于加载和导入由动态链接库定义的模块 .

    所以,要解决这个问题,你可以这样做:

    test-a.scm

    #!/usr/bin/csi -script
    
    ;; Declare that this uses test-b, so that its toplevel is initialised
    (declare (uses test-b))
    ;; No (declare (unit test-a)) because this file should generate main().
    
    ;; Because we tell the compiler what to link together and we want to
    ;; avoid passing all the .scm files on the csi command line, we can load
    ;; the test-b.scm file here, but only when interpreting:
    (cond-expand
      ((not compiling) (load "test-b.scm"))
      (else))
    
    ;; Only import the module; we take care of loading the code above,
    ;; or in the linking step when compiling.  If we had (use test-b),
    ;; the library would be searched for at runtime.
    ;; Alternatively, (use test-b) here, but add (register-feature! 'test-b)
    ;; to test-b.scm, which prevents the runtime from attempting to load test-b.
    (import test-b)
    
    (test-syntax)
    

    test-b.scm (不变)

    (declare (unit test-b))
    
    (module test-b *
     (import scheme chicken)
     (define-syntax test-syntax
      (syntax-rules ()
       ((_)
        (print "In test-syntax")))))
    

    并且,编译它:

    csc -c -j test-b test-b.scm
    csc -c test-a.scm
    csc test-a.o test-b.o -o test
    

    我知道这有很多东西要知道,也很棘手,有些像 use 加上 register-feature! 只是试图在鸡5中不那么繁琐,而且我们显而易见并且有点像常见问题解答 .

    您链接的手册页没有't been changed in a long time: it completely ignores the existence of modules, for example. That'为什么你无法编译它, -j 开关丢失了,因为手册页中的示例文件没有定义模块 .

    编辑:

    这可以稍微清理一下,因为 declare 无论如何都只能被编译器尊重 . 所以我们也可以将它移到 cond-expand 中:

    test-a.scm

    #!/usr/bin/csi -script
    (cond-expand
      (compiling (declare (uses test-b)))
      (else (load "test-b.scm")))
    
    (import test-b)
    
    (test-syntax)
    

相关问题