【问题标题】:How to get project version at compile time如何在编译时获取项目版本
【发布时间】:2017-05-27 13:00:55
【问题描述】:

我在 cljc 文件中有以下代码:

(ns proj
  #?(:cljs
     (:require-macros
       [proj :refer [define-project-version]])))

(declare project-version)

#?(:clj
   (defmacro define-project-version []
 `(def ~'project-version ~(first (drop 2 (read-string (slurp "project.clj")))))))

(define-project-version)

当用于 clj 文件和启动 REPL 时,这确实有效。但是,一旦我制作了一个 uberjar 并尝试运行它,我就会收到关于 project.clj 的异常 - “没有这样的文件或目录”。错误来自 ClojureScript 部分。 uberjar 编译得很好。

为什么代码会尝试加载 project.clj?宏不应该在编译时运行吗?

【问题讨论】:

  • 正如我从您提供的代码中看到的那样,您仅为 Clojure 平台(不适用于 ClojureScript)定义了 define-project-version。应该是这样吗?
  • define-project-version 是一个宏 - 它不能直接在 ClojureScript 中声明,只能在 Clojure 中声明。因为我使用的是 cljc 文件,所以我只为 Clojure 声明它 - 然后为了在 ClojureScript 中实际使用它,我需要它与 require-macros 一起使用,这仅对 ClojureScript 有效。
  • 你不能直接在 uberjar 中 slurp 文件,你必须先将它作为资源加载。
  • 我会试试看,但不是在编译时运行宏的全部意义——这意味着当 uberjar 准备好时,这些宏应该已经在它们的位置生成了代码?跨度>

标签: clojure clojurescript leiningen


【解决方案1】:

要从 Uberjar 中的 Clojure 应用程序访问文件,这些文件应该放在类路径上的资源目录中。在典型的 Leiningen 项目中,这将是项目根目录中的 resources

可以通过将:resource-paths ["src/main/resource"] 添加到project.clj 项目配置文件来显式定义不同的路径。

然后可以使用 clojure.java.io/resource 函数访问文件,例如位于 resources/hello.txt 的文件

; Use clojure.java.io/resource to read resources from the classpath:

(ns rescue.core
  (:require [clojure.java.io :as io] ))


(def data-file (io/resource 
                   "hello.txt" ))
(defn -main []
  (println (slurp data-file)) )

这可以在项目根目录打开终端并运行命令java -jar uberjar-name.jar进行检查

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    • 2018-06-14
    • 2010-11-15
    • 2017-08-13
    相关资源
    最近更新 更多