You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

build.clj 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. (require '[cljs.build.api :as api]
  2. '[clojure.string :as str])
  3. ;; clj build.clj help # Prints details about tasks
  4. ;;; Configuration.
  5. (def cljsbuild-config
  6. {:dev
  7. {:ios
  8. {:source-paths ["components/src" "react-native/src/cljsjs" "react-native/src/mobile" "src"]
  9. :compiler {:output-to "target/ios/app.js"
  10. :main "env.ios.main"
  11. :output-dir "target/ios"
  12. :npm-deps false
  13. :optimizations :none}
  14. :warning-handlers '[status-im.utils.build/warning-handler]}
  15. :android
  16. {:source-paths ["components/src" "react-native/src/cljsjs" "react-native/src/mobile" "src"]
  17. :compiler {:output-to "target/android/app.js"
  18. :main "env.android.main"
  19. :output-dir "target/android"
  20. :npm-deps false
  21. :optimizations :none}
  22. :warning-handlers '[status-im.utils.build/warning-handler]}
  23. :desktop
  24. {:source-paths ["components/src" "react-native/src/cljsjs" "react-native/src/desktop" "src"]
  25. :compiler {:output-to "target/desktop/app.js"
  26. :main "env.desktop.main"
  27. :output-dir "target/desktop"
  28. :npm-deps false
  29. :optimizations :none}
  30. :warning-handlers '[status-im.utils.build/warning-handler]}}
  31. :prod
  32. {:ios
  33. {:source-paths ["components/src" "react-native/src/cljsjs" "react-native/src/mobile" "src" "env/prod"]
  34. :compiler {:output-to "index.ios.js"
  35. :output-dir "target/ios-prod"
  36. :static-fns true
  37. :optimize-constants true
  38. :optimizations :simple
  39. :closure-defines {"goog.DEBUG" false}
  40. :parallel-build false
  41. :elide-asserts true
  42. :language-in :ecmascript5}
  43. :warning-handlers '[status-im.utils.build/warning-handler]}
  44. :android
  45. {:source-paths ["components/src" "react-native/src/cljsjs" "react-native/src/mobile" "src" "env/prod"]
  46. :compiler {:output-to "index.android.js"
  47. :output-dir "target/android-prod"
  48. :static-fns true
  49. :optimize-constants true
  50. :optimizations :simple
  51. :closure-defines {"goog.DEBUG" false}
  52. :parallel-build false
  53. :elide-asserts true
  54. :language-in :ecmascript5}
  55. :warning-handlers '[status-im.utils.build/warning-handler]}
  56. :desktop
  57. {:source-paths ["components/src" "react-native/src/cljsjs" "react-native/src/desktop" "src" "env/prod"]
  58. :compiler {:output-to "index.desktop.js"
  59. :output-dir "target/desktop-prod"
  60. :static-fns true
  61. :optimize-constants true
  62. :optimizations :simple
  63. :closure-defines {"goog.DEBUG" false}
  64. :parallel-build false
  65. :elide-asserts true
  66. :language-in :ecmascript5}
  67. :warning-handlers '[status-im.utils.build/warning-handler]}}
  68. :test
  69. {:test
  70. {:source-paths ["src" "test/cljs"]
  71. :compiler {:main "status-im.test.runner"
  72. :output-to "target/test/test.js"
  73. :output-dir "target/test"
  74. :optimizations :none
  75. :preamble ["js/hook-require.js"]
  76. :target :nodejs}}
  77. :protocol
  78. {:source-paths ["src" "test/cljs"]
  79. :compiler {:main "status-im.test.protocol.runner"
  80. :output-to "target/test/test.js"
  81. :output-dir "target/test"
  82. :optimizations :none
  83. :target :nodejs}}
  84. :env-dev-utils
  85. {:source-paths ["env/dev/env/utils.cljs" "test/env/dev"]
  86. :compiler {:main "env.test.runner"
  87. :output-to "target/test/test.js"
  88. :output-dir "target/test"
  89. :optimizations :none
  90. :target :nodejs}}}})
  91. (def cli-tasks-info
  92. {:compile {:desc "Compile ClojureScript"
  93. :usage ["Usage: clj build.clj compile [env] [build-id] [type]"
  94. ""
  95. "[env] (required): Pre-defined build environment. Allowed values: \"dev\", \"prod\", \"test\""
  96. "[build-id] (optional): Build ID. When omitted, this task will compile all builds from the specified [env]."
  97. "[type] (optional): Build type - value could be \"once\" or \"watch\". Default: \"once\"."]}
  98. :watch {:desc "Start development"
  99. :usage ["Usage: clj -R:dev build.clj watch [options]"
  100. ""
  101. "[-h|--help] to see all available options"]}
  102. :test {:desc "Run tests"
  103. :usage ["Usage: clj -R:test build.clj test [build-id]"
  104. ""
  105. "[build-id] (required): Value could be \"test\", \"protocol\" or \"env-dev-utils\". It will compile then run the tests once."]}
  106. :help {:desc "Show this help"}})
  107. ;;; Helper functions.
  108. (def reset-color "\u001b[0m")
  109. (def red-color "\u001b[31m")
  110. (def green-color "\u001b[32m")
  111. (def yellow-color "\u001b[33m")
  112. (defn- colorizer [c]
  113. (fn [& args]
  114. (str c (apply str args) reset-color)))
  115. (defn- println-colorized [message color]
  116. (println ((colorizer color) message)))
  117. (defn- elapsed [started-at]
  118. (let [elapsed-us (- (System/currentTimeMillis) started-at)]
  119. (with-precision 2
  120. (str (/ (double elapsed-us) 1000) " seconds"))))
  121. (defn- try-require [ns-sym]
  122. (try
  123. (require ns-sym)
  124. true
  125. (catch Exception e
  126. false)))
  127. (defmacro with-namespaces [namespaces & body]
  128. (if (every? try-require namespaces)
  129. `(do ~@body)
  130. `(do (println-colorized "task not available - required dependencies not found" red-color)
  131. (System/exit 1))))
  132. (defn- get-cljsbuild-config [name-env & [name-build-id]]
  133. (try
  134. (let [env (keyword name-env)]
  135. (when-not (contains? cljsbuild-config env)
  136. (throw (Exception. (str "ENV " (pr-str name-env) " does not exist"))))
  137. (let [env-config (get cljsbuild-config env)]
  138. (if name-build-id
  139. (let [build-id (keyword name-build-id)]
  140. (when-not (contains? env-config build-id)
  141. (throw (Exception. (str "Build ID " (pr-str name-build-id) " does not exist"))))
  142. (get env-config build-id))
  143. env-config)))
  144. (catch Exception e
  145. (println-colorized (.getMessage e) red-color)
  146. (System/exit 1))))
  147. (defn- get-output-files [compiler-options]
  148. (if-let [output-file (:output-to compiler-options)]
  149. [output-file]
  150. (into [] (map :output-to (->> compiler-options :modules vals)))))
  151. (defn- compile-cljs-with-build-config [build-config build-fn env build-id]
  152. (let [{:keys [source-paths compiler]} build-config
  153. output-files (get-output-files compiler)
  154. started-at (System/currentTimeMillis)]
  155. (println (str "Compiling " (pr-str build-id) " for " (pr-str env) "..."))
  156. (flush)
  157. (build-fn (apply api/inputs source-paths) compiler)
  158. (println-colorized (str "Successfully compiled " (pr-str output-files) " in " (elapsed started-at) ".") green-color)))
  159. (defn- compile-cljs [env & [build-id watch?]]
  160. (let [build-fn (if watch? api/watch api/build)]
  161. (if build-id
  162. (compile-cljs-with-build-config (get-cljsbuild-config env build-id) build-fn env build-id)
  163. (doseq [[build-id build-config] (get-cljsbuild-config env)]
  164. (compile-cljs-with-build-config (get-cljsbuild-config env build-id) build-fn env build-id)))))
  165. (defn- show-help []
  166. (doseq [[task {:keys [desc usage]}] cli-tasks-info]
  167. (println (format (str yellow-color "%-12s" reset-color green-color "%s" reset-color)
  168. (name task) desc))
  169. (when usage
  170. (println)
  171. (->> usage
  172. (map #(str " " %))
  173. (str/join "\n")
  174. println)
  175. (println))))
  176. ;;; Task dispatching
  177. (defmulti task first)
  178. (defmethod task :default [args]
  179. (println (format "Unknown or missing task. Choose one of: %s\n"
  180. (->> cli-tasks-info
  181. keys
  182. (map name)
  183. (interpose ", ")
  184. (apply str))))
  185. (show-help)
  186. (System/exit 1))
  187. ;;; Compiling task
  188. (defmethod task "compile" [[_ env build-id type]]
  189. (case type
  190. (nil "once") (compile-cljs env build-id)
  191. "watch" (compile-cljs env build-id true)
  192. (do (println "Unknown argument to compile task:" type)
  193. (System/exit 1))))
  194. ;;; Testing task
  195. (defmethod task "test" [[_ build-id]]
  196. (with-namespaces [[doo.core :as doo]]
  197. (compile-cljs :test build-id)
  198. (doo/run-script :node (->> build-id (get-cljsbuild-config :test) :compiler))))
  199. ;;; :watch task
  200. (defn hawk-handler-resources
  201. [ctx e]
  202. (let [path "src/status_im/utils/js_resources.cljs"
  203. js-resourced (slurp path)]
  204. (spit path (str js-resourced " ;;"))
  205. (spit path js-resourced))
  206. ctx)
  207. (defn hawk-handler-translations
  208. [ctx e]
  209. (let [path "dev/status_im/i18n_resources.cljs"
  210. i18n (slurp path)]
  211. (spit path (str i18n " ;;"))
  212. (spit path i18n))
  213. ctx)
  214. (defmethod task "watch" [[_ & args]]
  215. (with-namespaces [[hawk.core :as hawk]
  216. [re-frisk-sidecar.core :as rfs]
  217. [figwheel-sidecar.repl-api :as ra]
  218. [clj-rn.core :as clj-rn]
  219. [clj-rn.main :as main]]
  220. (let [options (main/parse-cli-options args main/watch-task-options)]
  221. (clj-rn/watch (assoc options :start-cljs-repl false))
  222. (rfs/-main)
  223. (hawk/watch! [{:paths ["resources"] :handler hawk-handler-resources}
  224. {:paths ["translations"] :handler hawk-handler-translations}])
  225. (when (:start-cljs-repl options) (ra/cljs-repl)))))
  226. ;;; Help
  227. (defmethod task "help" [_]
  228. (show-help)
  229. (System/exit 1))
  230. ;;; Build script entrypoint.
  231. (task *command-line-args*)