2016-08-17 50 views
2

顯然我的previous question太寬泛了。所以這裏再次提出這個問題,簡化了一下,並附帶了示例源代碼。我如何獲得這個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"))))) 

根據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中工作。

如何,沒有破壞兼容csi,我可以做這個編譯?

回答

1

有四個方面的問題在這裏(!):

  • 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) 

測試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 

我意識到這是相當多的東西知道了,太刁鑽而像useregister-feature!有些東西根本就沒有太大的意義。我們正試圖在CHICKEN 5中減少這個問題,並且我們還會爲wiki添加一個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) 
+0

謝謝,這是非常有用的。但我可以問一個後續問題嗎?爲什麼我會收到像'未定義的引用blah_toplevel'的錯誤?我生成了導入文件,並且鏈接了.o文件。無可否認,我正在編譯的文件比示例稍微複雜一些。 –

+0

'blah_toplevel'是一個單元的「主要」入口點。它不是實際的C main(),但是它被所有使用'blah'的單元調用來初始化該單元。如果它丟失了,也許你在一些源文件中有'(聲明(使用blah))',但是你忘了實際上將它鏈接到'blah'?另一種可能的解釋是,你在源文件中有'(declare(unit blah2))'blah,所以它不會聲明與其他人期望的相同的單元名稱。如果沒有真正看到源代碼,確切原因很難說清楚。 – sjamaan

+0

我試圖邀請你去聊天,但我不認爲它有效。如果我給你我的項目文件,你能告訴我爲什麼我會得到一個奇怪的錯誤嗎? –