2014-10-17 68 views
4

在我Leiningen項目:如何編譯Java代碼的Clojure代碼後leiningen

(defproject com.stackoverflow.clojure/tests "0.1.0-SNAPSHOT" 
    :description "Tests of Clojure test-framework." 
    :url "http://example.com/FIXME" 
    :license {:name "Eclipse Public License" 
      :url "http://www.eclipse.org/legal/epl-v10.html"} 
    :dependencies [[org.clojure/clojure "1.6.0"] 
       [instaparse "1.3.4"]] 
    :aot [com.stackoverflow.clojure.testGenClass] 
    :source-paths  ["src/main/clojure"] 
    :java-source-paths ["src/main/java"] 
    :test-paths  ["src/test/clojure"] 
    :java-test-paths ["src/test/java"] 
) 

我生成與根級的Java類:

(ns com.stackoverflow.clojure.testGenClass 
    (:gen-class 
    :name com.stackoverflow.clojure.TestGenClass 
    :implements [com.stackoverflow.clojure.TestGenClassInterface] 
    :prefix "java-")) 

(def ^:private pre "START: ") 

(defn java-addToString [this text post] 
    (str pre text post)) 

,我想在使用Java的:

package com.stackoverflow.clojure; 

public class TestGenClassTest { 

    private TestGenClassTest() { 
    } 

    public static void main(String[] args) { 
     TestGenClassInterface gc = new TestGenClass(); 
     System.out.println(gc.addToString("Called from Java!", " :END")); 
    } 
} 

開始lein compile引發以下錯誤:

Compiling 4 source files to /home/eddy/workspace/TestSkripts/target/classes 
/home/eddy/workspace/TestSkripts/src/main/java/com/stackoverflow/clojure/TestGenClassTest.java:9: error: cannot find symbol 
     TestGenClassInterface gc = new TestGenClass(); 
            ^
    symbol: class TestGenClass 
    location: class TestGenClassTest 
1 error 

在我看來,在編譯Java代碼(此處爲:TestGenClassTest)時,該類不可用。我通常所做的是

  1. 註釋掉那些使用GEN-類生成的類(這裏TestGenClass
  2. 運行lein compile部分(生成類文件)
  3. 然後再採取outcommented代碼
  4. 並再次運行lein compile

我確定有一個更好的方法,這使得所有的手動步驟被刪除。

回答

-1

讓我再次轉介到Polyglot (Clojure, Java) Projects With Leiningen,特別是這部分:Interleaving Compilation Steps

默認情況下,Leiningen正在執行javac,然後是compile。你也可以實現的compile - >javac - >compile

+0

那麼配置文件看起來像怎麼樣,先編譯接口'com.stackoverflow.clojure .TestGenClassInterface'使用javac(必要時)然後編譯實現接口的Clojure部分('com.stackoverflow.clojure.TestGenClass'),然後編譯Java主程序?它是兩個額外的配置文件,還是一個?使用path-statements調用正確的編譯器嗎? – Edward 2014-10-17 11:56:38

+0

哎呀,我不小心低估了這一點。 – matanster 2017-03-31 17:50:58

+0

不,正如我所見,正確的編譯器不會從路徑語句中自動傳入。 – matanster 2017-03-31 18:16:45

0

您想要添加預編譯步驟。運行預編譯...然後你就可以走了。

  1. 把你的接口轉換成一個單獨的文件路徑src/main/pre/interface/clojure

  2. 添加下面:profiles

    (defproject com.stackoverflow.clojure/tests "0.1.0-SNAPSHOT" 
    :description "Tests of Clojure test-framework." 
    :url "http://example.com/FIXME" 
    :dependencies [[org.clojure/clojure "1.6.0"] 
          [instaparse "1.3.4"]] 
    :source-paths  ["src/main/clojure"] 
    :java-source-paths ["src/main/java"] 
    :test-paths  ["src/test/clojure"] 
    :java-test-paths ["src/test/java"] 
    :profiles { :precomp { :source-paths ["src/main/pre/interface/clojure"] 
            :aot [parser.ast] } }) 
    

然後你可以運行lein with-profile precomp compile之後lein test應該工作

0

這是來自clojure代碼依賴於Java代碼的項目的示例project.clj,並且AOT編譯爲可用於上游測試Java代碼。所以在這裏,我們有編譯依賴三層:Java的→Clojure的→Java和所有的工作:

(defproject myproject "0.1.0-SNAPSHOT" 
    :min-lein-version "2.0.0" 
    :source-paths  ["src/clojure"]/ 
    :java-source-paths ["src/java"] 
    :javac-options  ["-target" "1.8" "-source" "1.8"] 
    :dependencies [[org.clojure/clojure "1.8.0"]] 
    :aot [the class that java-test needs] 
    :profiles {:java-tests-compile 
    {:java-source-paths ["src/java-test"]}} 
    :aliases { 
    "java-tests" ["do" "compile," "with-profile" "java-tests-compile" "javac," "run" "-m" "myorg.myProject.java-test-code"] 
    "all-tests" ["do" "test," "java-tests"] 
    }) 

; https://github.com/technomancy/leiningen/issues/847#issuecomment-289943710 

上游的Java測試的代碼查找所有當它編譯和運行需要。 (這個示例來自的項目中的上游java層恰好是java測試代碼,但這裏沒有任何特定於測試代碼的內容,當您希望Java代碼使用您生成的gen-class時,該技術應該一般地工作clojure代碼)。

原始問題的代碼只是缺少這裏顯示的配置文件和別名部分,告訴leiningen如何在clojure編譯後編譯Java。這是必要的,因爲默認情況下,在leiningen的當前版本中,leiningen在編譯clojure之前編譯Java;它不會嘗試命令跨語言編譯源文件。

因此,在此解決方案中,我們通過使用別名將另一個編譯步驟作爲單獨的leiningen任務添加。有了這個配置,我們只需要發佈lein java-tests,它首先編譯clojure,然後發佈上游Java層。瞧。

P.S.也許我們甚至可以重寫lein的編譯任務,而不是添加一個新的任務,但是這對我來說並不值得...