iT邦幫忙

2026 iThome 鐵人賽

0
Software Development

玩轉ABCL Lisp!用奇怪偏門的方式學習JavaFX系列 第 33 篇

lesson 24(S4): 怎麼把ABCL System打包成JAR檔案?

  • 分享至 

  • xImage
  •  

TL;DR

在CalcFX with SceneBuilder Event中,已完成可執行的abcl-javafx ASDF系統。本文示範如何使用ABCL contrib提供的asdf-jar將系統打包成JAR,再從JAR載入系統並確認資源可正常讀取。

確認ASDF系統與資源

專案結構如下:

abcl-javafx/
├── abcl-javafx.asd
├── package.lisp
├── constants.lisp
├── utils.lisp
├── main.lisp
├── pack-asdf.lisp
├── run-jar.lisp
├── run-system.lisp
├── scenes/
│   └── calcFX.lisp
└── res/
    ├── CalcFX.fxml
    ├── calcfx.css
    ├── style.css
    └── icon32x32.png

系統定義檔abcl-javafx.asd如下:

(defsystem "abcl-javafx"
  :description "Create GUI Application with ABCL and JavaFX"
  :version "0.0.1"
  :author "lagagain <lagagain@email.com>"
  :licence "MIT"
  :depends-on (#:jss)
  :serial t
  :components ((:file "package")
               (:file "constants")
               (:file "utils")
               (:module "scenes"
                :components
                ((:file "calcFX")))
               (:file "main")
               (:module "res"
                :components
                ((:static-file "style.css")
                 (:static-file "CalcFX.fxml")
                 (:static-file "calcfx.css")
                 (:static-file "icon32x32.png")))))

調整載入的資源路徑

在utils.lisp中,get-system-resource使用asdf/system:system-relative-pathname取得系統資源路徑。系統從JAR載入時,路徑已經是jar:file: URI,可以直接使用;從一般檔案系統載入時,則透過java.io.File.toURI()轉成JavaFX可用的URI:

(defun get-system-resource (resource-path)
  (let ((p (namestring (asdf/system:system-relative-pathname
                        :abcl-javafx
                        resource-path))))
    (if (uiop:string-prefix-p "jar:file:" p)
        p
        (chain (new "java.io.File" p)
               "toURI"
               "toString"))))

先確認系統可以載入

打包前先使用提供的run-system.lisp測試ASDF系統:

(require "asdf")
(require :abcl-contrib)
(push #P"./" asdf:*central-registry*)
(asdf:load-system "abcl-javafx")

在專案根目錄執行:

abcl --noinform --load run-system.lisp

先確認視窗能正常顯示,再關閉程式。

打包ASDF系統

asdf-jar不是CLHS的標準功能,而是ABCL contrib提供的ASDF擴充:

(require :abcl-contrib)
(require :abcl-asdf)
(asdf:make :asdf-jar)   ;; 載入 asdf-jar 功能

專案將打包流程放在pack-asdf.lisp,內容如下:

(require :abcl-contrib)
(require :asdf)
(require :abcl-asdf)
(asdf:make :asdf-jar)

(push #P"./" asdf:*central-registry*)

(asdf-jar:package :abcl-javafx
                 :verbose t
                 :out "."
                 :fasls t
                 :recursive nil)

在專案根目錄執行:

abcl --noinform --load pack-asdf.lisp --eval '(quit)'

:out設定輸出位置,設定成"."表示把輸出JAR放在目前目錄;也可以指定輸出資料夾,例如:

(asdf-jar:package :abcl-javafx
                 :verbose t
                 :out "dist"
                 :fasls t
                 :recursive nil)

完成後應該會得到類似abcl-javafx-0.0.1.jar的檔案。實際檔名可能依系統名稱和版本號略有不同,以命令列輸出的檔名為準。

檢查JAR內容

打包後可以用jar -tf查看JAR內的檔案:

jar -tf abcl-javafx-0.0.1.jar

我得到的結果如下:

abcl-javafx/
abcl-javafx/scenes/
abcl-javafx/scenes/calcFX.abcl
abcl-javafx/abcl-javafx.asd
abcl-javafx/main.lisp
abcl-javafx/constants.lisp
abcl-javafx/utils.abcl
abcl-javafx/package.abcl
abcl-javafx/package.lisp
abcl-javafx/res/
abcl-javafx/res/calcfx.css
abcl-javafx/utils.lisp
abcl-javafx/constants.abcl
abcl-javafx/res/style.css
abcl-javafx/res/CalcFX.fxml
abcl-javafx/res/icon32x32.png
abcl-javafx/scenes/calcFX.lisp
abcl-javafx/main.abcl

通常可以看到ASDF系統描述、Lisp原始檔、編譯後的.abcl檔案,以及被宣告為:static-file的資源。

從JAR載入ASDF系統

打包完成後,可以讓ABCL載入JAR中的ASDF系統。專案的run-jar.lisp將JAR內的系統路徑加入asdf:*central-registry*,再呼叫asdf:load-system:

(require :asdf)
(require :abcl-contrib)

(push "jar:file:./abcl-javafx-0.0.1.jar!/abcl-javafx/" asdf:*central-registry*)
(asdf:load-system :abcl-javafx)

執行載入腳本:

abcl --noinform --load run-jar.lisp

載入後應能啟動CalcFX,並從JAR讀取FXML、CSS和圖示。至此已完成ASDF系統的JAR打包與載入驗證;不過要直接提供給一般使用者,使用jlink或jpackage,建立包含執行環境的應用程式,再進行分發可能更好。


上一篇
lesson 23(S4): 單一檔案編譯成JAVA字節碼,保存成ABCL檔案
系列文
玩轉ABCL Lisp!用奇怪偏門的方式學習JavaFX 共 33 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言