Здесь есть четыре(!) проблемы:
test-a.scm
содержит объявление модуля. Это неправильно; всегда есть один файл, который нужно скомпилировать, чтобы иметь функцию main()
C. Это файл без объявления модуля. Если вы внимательно изучите страницу руководства, на которую вы ссылаетесь, вы увидите: «В данном случае foo.scm
является основным модулем, потому что в нем нет объявления модуля».
- Поскольку вы решили использовать модули, вам нужно будет скомпилировать
test-b.scm
следующим образом: csc -c -j test-b test-b.scm
. Переключатель -j
заставит компилятор выдать библиотеку модулей test-b.import.scm
, которую компилятор ищет при компиляции test-a.scm
. Когда библиотека импорта отсутствует, она будет жаловаться, что модуль не определен. В интерпретаторе это не проблема, потому что вы load
файл перед импортом модуля, который он определяет.
- Вы используете
load
даже в скомпилированной версии программы. Это означает, что он будет читать и оценивать файл test-b.scm
(и жаловаться, если он отсутствует) в любой ситуации.
- Вы используете
use
, для которого потребуется библиотека во время выполнения. Это предназначено для загрузки и импорта модулей, определенных динамически подключаемыми библиотеками.
Итак, чтобы решить эту проблему, вы можете сделать это следующим образом:
тест-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!
, просто не имеют особого смысла. Мы пытаемся сделать это менее запутанным в CHICKEN 5, и мы также собираемся добавить FAQ на вики, потому что это действительно не очевидно и немного похоже на FAQ.
Страница руководства, на которую вы ссылаетесь, не менялась в течение длительного времени: например, она полностью игнорирует существование модулей. Вот почему вы не смогли его скомпилировать, ключ -j
отсутствовал, потому что файлы примеров на странице руководства не определяют модули.
Редактировать:
Это можно немного исправить, потому что declare
в любом случае учитывается только компилятором. Так что мы можем переместить это и в cond-expand
:
тест-a.scm
#!/usr/bin/csi -script
(cond-expand
(compiling (declare (uses test-b)))
(else (load "test-b.scm")))
(import test-b)
(test-syntax)
person
sjamaan
schedule
17.08.2016