使用Gambit-C编译Scheme

3
我正在运行Ubuntu 18.04,并安装了来执行Scheme脚本。 可以正常工作,可以解释我提供的任何文件,REPL也按预期工作。不幸的是,我无法弄清楚如何使用。http://gambitscheme.org/wiki/index.php/A_Tour_of_Scheme_in_Gambit提供了很少关于如何使用编译程序的信息,更多地涉及并未涵盖所有可用选项(例如,在man页面中未提及选项-o-c),而我能找到的所有其他来源都对我没有用。让我详细说明一下最后一部分:
$ cat hello.scm
;#!/usr/local/bin/gsi-script -:d0
;
(define hello-world
        (lambda ()
                (begin (write `Hello-World) (newline) (hello-world))))

(define (main)
        (hello-world))

那么

$ gsc hello.scm
$ ls
hello.o1  hello.scm
$ ./hello.o1
Segmentation fault (core dumped)

失败了,同样如此

$ gsc -c hello.scm
$ ls
hello.c hello.scm
$ gcc -o hello hello.c
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o : In function « _start » :
(.text+0x20) : Undefined reference to « main »
/tmp/ccnDUVi0.o : [30 more lines]
collect2: error: ld returned 1 exit status
  • 进行中
/* File: "m1.c" */
int power_of_2 (int x) { return 1<<x; }

; File: "m2.scm"
(c-declare "extern int power_of_2 ();")
(define pow2 (c-lambda (int) int "power_of_2"))
(define (twice x) (cons x x))

; File: "m3.scm"
(write (map twice (map pow2 '(1 2 3 4)))) (newline)

$ gsc -c m2.scm        # create m2.c (note: .scm is optional)
$ gsc -c m3.scm        # create m3.c (note: .scm is optional)
$ gsc -link m2.c m3.c  # create the incremental link file m3_.c

$ gsc -obj m1.c m2.c m3.c m3_.c
m1.c:
m2.c:
m3.c:
m3_.c:
$ gcc m1.o m2.o m3.o m3_.o -lgambit -lm -ldl -lutil
$ ./a.out
((2 . 2) (4 . 4) (8 . 8) (16 . 16))

根据http://www.iro.umontreal.ca/~gambit/doc/gambit.html的建议,使用$ gsc -obj m1.c m2.c m3.c m3_.c失败,提示m3_.c未定义。即使忽略这一点,再次使用$ gcc m1.o m2.o m3.o m3_.o -lgambit -lm -ldl -lutil时,它也抱怨-lgambit未定义。但该文档确实解释了-o-c选项的使用方法。
我到此为止,但我尝试过其他两个教程,都没有成功,而且我现在找不到它们了。
如果上述任何方法可以修改以适合我,或者如果有任何其他过程允许脚本编译成可执行文件(即使是简单的单文件程序),我将感激不尽。
2个回答

3
在你提到的 Gambit 手册的 第3部分,Gambit Scheme 编译器 中,有非常详细的编译器描述和所有选项。
如果你想将 Scheme 源文件 hello.scm 编译成可执行程序,请尝试:
gsc -exe hello

您不必提供文件扩展名。生成的可执行文件将与源文件同名,但没有扩展名(因此 hello.scm -> hello)。


我执行了 $ gsc -exe hello 命令,但终端返回了以下信息:hello_.o:(.data.rel+0x150) : référence indéfinie vers « ____20_hello » collect2: error: ld returned 1 exit status *** ERROR IN ##main -- C link failed while linking "/home/vanille/ALGO/Scheme/hello_.o" - Neven V.
哦,当hello已经被编译时,.scm是必需的。我得到了一个输出文件,现在需要找出为什么启动它没有任何反应。 - Neven V.
这应该适用于所有平台。你得到的错误来自链接器,与Gambit无关。也许Ubuntu版本(软件包)的Gambit有问题,但我只是猜测。重要的是 - 你不能通过一些gsc等开关来解决问题,你应该检查为什么你系统上的链接器不起作用。 - rsm
@NevenV。我建议联系Ubuntu Gambit软件包的维护者。信息(包括电子邮件)应该在软件包描述中。他可能还不知道这个问题(或已经知道如何解决它)。 - rsm
我会先休息一下,如果我无法解决问题,那么我会这样做。 - Neven V.

2

以下是我总结出来的,以防其他人遇到同样的问题。

  • 尽管在man页面中没有出现,但-exe选项确实可以启用可执行文件的创建。
$ gsc -exe hello.scm
$ ./hello
Hello, World!

它的使用在Scheme可移植实现Gambit中有解释,但不在“Gambit Scheme编译器”部分!相反,您需要向上滚动到前面的段落。

  • 正如@rsm所指出的那样,$ gsc -exe hello同样有效:即使已经编译了hello,也不需要.scm,但是有一系列特定的命令会导致此命令失败。

这个有效(h已正确编译):

$ ls
hello.scm
$ gsc -exe -o h hello
$ ls
h  hello.scm

下面的代码是正确的(h是从hello.scm编译而来,而不是hello):

$ ls
hello  hello.scm
$ gsc -exe -o h hello
$ ls
h  hello  hello.scm

但是这种方法失败了:
$ ls
hello.scm
$ gsc -c hello.scm
$ ls
hello.c  hello.scm
$ gsc -exe -o h hello
hello_.o:(.data.rel+0x110) : undefined reference to « ____20_hello »
collect2: error: ld returned 1 exit status
*** ERROR IN ##main -- C link failed while linking "/home/hello_.o"
$ ls
hello_.c  hello.c  hello_.o  hello.scm

在同名的.c文件已经存在的情况下,应该使用.scm扩展名。虽然提示出现了链接器错误,但据我所知,问题的根本是当扩展名未指定时,C文件优先于Scheme文件,这对于一个Scheme编译器来说是不符合预期的...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接