如何通过deps.edn别名跨平台编译带分类器的JavaFX uberjar
配置失效核心原因
- JavaFX平台依赖写法错误:Clojure CLI的Maven分类器依赖不能用
$拼接在artifact ID后,必须通过依赖配置项的:classifier字段指定 - 平台依赖不全:所有JavaFX组件(base、controls、fxml、graphics等)都需要对应平台的分类器版本,现有配置漏配大量组件,且macOS需要区分Intel(分类器
mac)和苹果硅(分类器mac-aarch64)两个版本 - 缺失构建流程配置:仅添加平台依赖不会自动生成带分类器的uberjar,需要搭配官方构建工具指定构建逻辑和输出命名规则
- 全局依赖冲突:在公共
:deps节点配置了无分类器的JavaFX依赖,会覆盖平台别名下的带分类器版本,导致原生依赖缺失
修正后的deps.edn配置
{:paths ["./src" "out/ui" "out/identicon"] :mvn/repos {"jitpack.io" {:url "https://jitpack.io"}} :deps {org.clojure/clojure {:mvn/version "1.10.3"} org.clojure/clojurescript {:mvn/version "1.11.4"} org.clojure/core.async {:mvn/version "1.3.618"} org.clojure/test.check {:git/url "https://github.com/clojure/test.check" :sha "b6a318af92e836f1f20960f38a5944168b88d60d"} cheshire/cheshire {:mvn/version "5.10.2"} cljfx/cljfx {:git/url "https://github.com/cljfx/cljfx" :sha "29aaef956b22cee774524912a3083ed651033f1b" :exclusions [org.openjfx/javafx-controls org.openjfx/javafx-base org.openjfx/javafx-fxml org.openjfx/javafx-graphics org.openjfx/javafx-media org.openjfx/javafx-web]} ;; 其余非JavaFX的公共依赖(Ripley、Genie、Zazu、shadow-cljs、ui相关依赖)可直接放在此处 } :aliases ;; 各平台专属JavaFX依赖 :linux {:extra-deps {org.openjfx/javafx-base {:mvn/version "17.0.2" :classifier "linux"} org.openjfx/javafx-controls {:mvn/version "17.0.2" :classifier "linux"} org.openjfx/javafx-fxml {:mvn/version "17.0.2" :classifier "linux"} org.openjfx/javafx-graphics {:mvn/version "17.0.2" :classifier "linux"} org.openjfx/javafx-media {:mvn/version "17.0.2" :classifier "linux"} org.openjfx/javafx-web {:mvn/version "17.0.2" :classifier "linux"}}} :windows {:extra-deps {org.openjfx/javafx-base {:mvn/version "17.0.2" :classifier "win"} org.openjfx/javafx-controls {:mvn/version "17.0.2" :classifier "win"} org.openjfx/javafx-fxml {:mvn/version "17.0.2" :classifier "win"} org.openjfx/javafx-graphics {:mvn/version "17.0.2" :classifier "win"} org.openjfx/javafx-media {:mvn/version "17.0.2" :classifier "win"} org.openjfx/javafx-web {:mvn/version "17.0.2" :classifier "win"}}} :mac-intel {:extra-deps {org.openjfx/javafx-base {:mvn/version "17.0.2" :classifier "mac"} org.openjfx/javafx-controls {:mvn/version "17.0.2" :classifier "mac"} org.openjfx/javafx-fxml {:mvn/version "17.0.2" :classifier "mac"} org.openjfx/javafx-graphics {:mvn/version "17.0.2" :classifier "mac"} org.openjfx/javafx-media {:mvn/version "17.0.2" :classifier "mac"} org.openjfx/javafx-web {:mvn/version "17.0.2" :classifier "mac"}}} :mac-arm {:extra-deps {org.openjfx/javafx-base {:mvn/version "17.0.2" :classifier "mac-aarch64"} org.openjfx/javafx-controls {:mvn/version "17.0.2" :classifier "mac-aarch64"} org.openjfx/javafx-fxml {:mvn/version "17.0.2" :classifier "mac-aarch64"} org.openjfx/javafx-graphics {:mvn/version "17.0.2" :classifier "mac-aarch64"} org.openjfx/javafx-media {:mvn/version "17.0.2" :classifier "mac-aarch64"} org.openjfx/javafx-web {:mvn/version "17.0.2" :classifier "mac-aarch64"}}} ;; 构建工具别名 :build {:deps {io.github.clojure/tools.build {:git/tag "v0.9.4" :git/sha "76b78fe656279e89a4a0c6a73b7d8960f47b2036"}} :ns-default build}}}
交叉编译操作步骤
- 在项目根目录创建
build.clj构建脚本,内容如下:
(ns build (:require [clojure.tools.build.api :as b])) (defn uber [opts] (let [platform (or (:platform opts) "local") class-dir "target/classes" ;; 将your-app替换为实际的项目名 uber-file (format "target/your-app-%s.jar" platform) ;; 将your.main.ns替换为项目的入口主命名空间 main-ns 'your.main.ns] (b/delete {:path "target"}) (b/copy-dir {:src-dirs ["src" "out/ui" "out/identicon"] :target-dir class-dir}) (b/compile-clj {:basis (b/create-basis {}) :src-dirs ["src"] :class-dir class-dir}) (b/uber {:class-dir class-dir :uber-file uber-file :basis (b/create-basis {}) :main main-ns})))
- 直接在当前开发系统执行对应命令,即可交叉编译出目标平台的带原生依赖uberjar,无需切换操作系统:
- 编译Linux版本:
clj -X:linux:build uber :platform linux - 编译Windows版本:
clj -X:windows:build uber :platform windows - 编译Intel芯片Mac版本:
clj -X:mac-intel:build uber :platform mac-intel - 编译苹果硅Mac版本:
clj -X:mac-arm:build uber :platform mac-arm
- 编译Linux版本:
注意事项
- 禁止在公共
:deps节点下放置任何无分类器的org.openjfx开头的依赖,否则会覆盖平台别名下的带分类器版本,导致原生库加载失败 - 如果项目不需要JavaFX的media、web组件,可以直接在对应平台别名中删除这两项依赖,缩小最终jar包体积
- 生成的jar包已内置对应平台的所有JavaFX原生依赖,目标机器无需单独安装JavaFX,仅需安装对应大版本的JDK即可通过
java -jar 包名.jar直接运行
内容的提问来源于stack exchange,提问作者Sergei-Udris
相关产品推荐
相关产品推荐

