6

在我的 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"]
  )

我正在使用 gen-class 生成 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-class 生成类的部分(这里TestGenClass
  2. 运行lein compile(生成类文件)
  3. 然后再次输入注释掉的代码
  4. lein compile再次运行。

我肯定有更好的方法,可以让所有手动步骤变得多余。

4

3 回答 3

1

您想添加一个预编译步骤。运行预编译...然后你就可以开始了。

  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应该工作

于 2016-11-16T00:09:03.513 回答
0

让我再次向您推荐使用 Leiningen 的 Polyglot (Clojure, Java) 项目,尤其是这一部分:交错编译步骤

默认情况下,Leiningen 正在执行javac,然后compile. 您还可以实现compile-> javac-> compile

于 2014-10-17T08:21:25.603 回答
0

这是一个项目的示例 project.clj,其中 clojure 代码依赖于 Java 代码,并且 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层的问题。瞧。

PS也许我们甚至可以覆盖lein的编译任务而不是添加新任务,但这对我来说不值得玩......

于 2017-03-31T17:56:24.843 回答