2014-10-17 45 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的编译任务,而不是添加一个新的任务,但是这对我来说并不值得...