2

どうやら私の前の質問は広すぎました。ここでもう一度質問を簡略化し、ソース コードの例を示します。

複数のファイルを含む Chicken Scheme プロジェクトをコンパイルしようとしています。

テスト a.scm:

#!/usr/bin/csi -script

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

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

(test-syntax)

テスト b.scm:

(declare (unit test-b))

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

公式マニュアルによると、次のようにする必要があります。

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 で動作するプログラムが必要です。

csiとの互換性を損なうことなく、これをコンパイルするにはどうすればよいですか?

4

1 に答える 1

2

ここには 4 つの (!) 問題があります。

  • test-a.scmユニット宣言が含まれています。これは正しくありません。main()C関数を持つためにコンパイルする必要があるファイルは常に1つです。それがユニット宣言のないファイルです。リンクしたマニュアルページをより詳しく調べると、「この場合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 でこれを簡単にしようと試みています。また、よくある質問を wiki に追加する予定です。

リンクしたマニュアル ページは長い間変更されていません。たとえば、モジュールの存在を完全に無視しています。そのため、コンパイルできませんでした-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)
于 2016-08-17T07:13:58.530 に答える