How to get project version at compile time
Asked Answered
T

1

6

I have the following code in a cljc file:

(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)

This does work when used in clj files and when starting the REPL. However as soon as I make an uberjar and try to run it I get an exception regarding project.clj - "No such file or directory." The error comes from the ClojureScript part. The uberjar is compiled just fine.

Why is it that the code tries to load project.clj? Aren't macros supposed to be run at compile time?

Tilley answered 12/1, 2017 at 12:8 Comment(4)
As I see from code you provided you define define-project-version only for Clojure platform (not for ClojureScript). Is this supposed to be so?Lea
define-project-version is a macro - it cannot be declared directly in ClojureScript, only in Clojure. Since I am using cljc file I am declaring it only for Clojure - then for actually having it in ClojureScript I am requiring it with require-macros, which is valid only for ClojureScript.Tilley
You can not directly slurp the file in an uberjar, you have to load it as a resource first.Insolent
I'll try that, but isn't the whole point of macros to be ran at compile time - meaning that when the uberjar is ready those macros should have already produced code on their place?Tilley
E
1

To access files from a Clojure application in an Uberjar, the files should be places in a resources directory that is on the classpath. In a typical Leiningen project, this would be resources in the root of the project.

A different path can be explicitly defined by adding :resource-paths ["src/main/resource"] to the project.clj project configuration file.

Files can then be accessed using the clojure.java.io/resource function, for example a file located at 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)) )

This can be checked opening a terminal in the root of the project and running the command java -jar uberjar-name.jar

Extort answered 3/1, 2022 at 13:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.