用maven将clojure和java源代码打包成jar文件

cngwdvgl  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(445)

我想在java应用程序中使用clojure代码:

; clj.clj
(ns utils
  (:gen-class
    :name clj.Clj
    :methods [#^{:static true} [clj [] String]])

(defn -clj []
  "Hello from Clojure!")
// Java.java
package main;

import clj.Clj;

public class Java {
    public static void main(String[] args) {
        System.out.println("Java main");
        System.out.println(Clj.clj());
    }
}

当我运行jar文件时,我想要输出:

Java main
Hello from Clojure!

如何使用maven编译clojure和java文件并将它们打包成可运行的jar文件?
更新:
以下是我目前的代码:

<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.github.loadingbg</groupId>
  <artifactId>proj</artifactId>
  <version>1.0.0</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <build>
    <plugins>
      <!-- Clojure Compiler -->
      <plugin>
        <groupId>com.theoryinpractise</groupId>
        <artifactId>clojure-maven-plugin</artifactId>
        <version>1.8.4</version>
        <executions>
          <execution>
            <phase>compile</phase>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <namespaces>
            <namespace>utils</namespace>
          </namespaces>
          <compileDeclaredNamespaceOnly>true</compileDeclaredNamespaceOnly>
          <sourceDirectories>
            <sourceDirectory>src/main/clojure</sourceDirectory>
          </sourceDirectories>
        </configuration>
      </plugin>

      <!-- Maven Compiler -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>11</source>
          <target>11</target>
        </configuration>
      </plugin>

      <!-- Maven Assembly Plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.3.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <mainClass>proj.Main</mainClass>
            </manifest>
          </archive>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>

      <!-- Maven Shade Plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <minimizeJar>true</minimizeJar>
          <transformers>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
              <mainClass>proj.Main</mainClass>
            </transformer>
          </transformers>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>org.clojure</groupId>
      <artifactId>clojure</artifactId>
      <version>1.10.0</version>
    </dependency>
  </dependencies>
</project>
; /src/main/clojure/utils.clj
(ns utils
  (:gen-class
    :name utils.Utils
    :methods [#^{:static true} [clj [] String]]))

(defn -clj []
  "Hello from clojure")
// /src/main/java/pack/Main.java
package proj;

import utils.Utils;

public class Main {
    public static void main(String[] args) {
        System.out.println("Starting");
        System.out.println(Utils.clj());
    }
}

当我跑的时候,我得到了以下信息 mvn clean install :

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$1 (file:/usr/share/maven/lib/guice.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.github.loadingbg:bot >----------------------
[INFO] Building bot 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ bot ---
[INFO] Deleting /home/loadingbg/proj/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ bot ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/loadingbg/proj/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ bot ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /home/loadingbg/proj/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /home/loadingbg/proj/src/main/java/proj/Main.java:[3,13] package utils does not exist
[ERROR] /home/loadingbg/proj/src/main/java/proj/Main.java:[8,28] cannot find symbol
  symbol:   variable Utils
  location: class proj.Main
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.136 s
[INFO] Finished at: 2020-12-22T22:36:42+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project
 bot: Compilation failure: Compilation failure:
[ERROR] /home/loadingbg/proj/src/main/java/proj/Main.java:[3,13] package utils does not exist
[ERROR] /home/loadingbg/proj/src/main/java/proj/Main.java:[8,28] cannot find symbol
[ERROR]   symbol:   variable Utils
[ERROR]   location: class proj.Main
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

它只是拒绝确认clojure文件生成的类。 utils.clj 应生成 utils.Utils 具有静态方法的类 Utils#clj() 返回一个字符串。
我看到它在动 clojure-maven-plugin 以上 maven-compiler-plugin 会有帮助,但没有。关键是要有 clojure-maven-plugin 在之前执行 maven-compiler-plugin 但事实并非如此。我如何重新排序插件的执行顺序,这会有帮助吗?
更新2(针对alan thompson):
我在新的leiningen项目中复制了以前的代码,但出现以下错误:

Compiling 1 source files to /home/loadingbg/proj/target/default/class-files
/home/loadingbg/proj/src/java/proj/Main.java:3: error: package utils does not exist
import utils.Utils;
            ^
/home/loadingbg/proj/src/java/proj/Main.java:8: error: cannot find symbol
        System.out.println(Utils.clj());
                           ^
  symbol:   variable Utils
  location: class Main
2 errors
Compilation of Java sources(lein javac) failed.

我错过什么了吗?我复制了 project.clj .

gmxoilav

gmxoilav1#

这个项目展示了如何用leiningen轻松地做到这一点。只是打字 lein clean; lein jar 并选择要部署的uberjar。
这个 project.clj 包括详细信息:

(defproject demo "0.1.0-SNAPSHOT"
  :license {:name "Eclipse Public License"
            :url  "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [
                 [org.clojure/clojure "1.10.2-alpha1"]
                 [org.clojure/spec.alpha "0.2.187"]
                 [prismatic/schema "1.1.12"]
                 [tupelo "20.08.27"]
                 ]
  :plugins [
            [com.jakemccrary/lein-test-refresh "0.24.1"]
            [lein-ancient "0.6.15"]
            [lein-codox "0.10.7"]
            ]

  :db "jdbc:postgresql://localhost/default"
  :settings "settings-default.edn"

  :profiles {:dev     {:dependencies []}
             :uberjar {:aot :all}}

  :global-vars {*warn-on-reflection* false}
  :main ^:skip-aot demo.core

  :source-paths ["src/clj"]
  :java-source-paths ["src/java"]
  :test-paths ["test/clj"]
  :target-path "target/%s"
  :compile-path "%s/class-files"
  :clean-targets [:target-path]

  :jvm-opts ["-Xms500m" "-Xmx4g"]
  )

确保代码与预期布局匹配:

~/expr/demo > tree src
src
├── clj
│   └── demo
│       └── core.clj
└── java
    └── demo
        └── Calc.java

运行测试:

> lein clean ; lein test
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Compiling 1 source files to /home/alan/expr/demo/target/default+test+test/class-files

lein test _bootstrap

-------------------------------
   Clojure 1.10.1    Java 15
-------------------------------

lein test tst.demo.core
(demo.Calc/theAnswer) => 42

制作uberjar:

> lein uberjar
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Compiling 1 source files to /home/alan/expr/demo/target/uberjar/class-files
Compiling demo.core
Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method, or the namespace has not been AOT-compiled.
Created /home/alan/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT.jar
Created /home/alan/expr/demo/target/uberjar/demo-0.1.0-SNAPSHOT-standalone.jar

单元测试甚至使用java互操作:

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test))

(dotest
  (is= 42 (spyx (demo.Calc/theAnswer))))

相关问题