Repository navigation
Expand file tree
/
Copy pathjavac.clj
More file actions
100 lines (91 loc) · 4.23 KB
/
Copy pathjavac.clj
File metadata and controls
100 lines (91 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
(ns leiningen.javac
"Compile Java source files."
(:require [leiningen.classpath :as classpath]
[leiningen.core.main :as main]
[clojure.java.io :as io])
(:import java.io.File
javax.tools.ToolProvider))
(defn- stale-java-sources
"Returns a lazy seq of file paths: every Java source file within
dirs modified since it was most recently compiled into
compile-path."
[dirs compile-path]
(for [dir dirs
^File source (filter #(-> ^File % (.getName) (.endsWith ".java"))
(file-seq (io/file dir)))
:let [rel-source (.substring (.getPath source) (inc (count dir)))
rel-compiled (.replaceFirst rel-source "\\.java$" ".class")
compiled (io/file compile-path rel-compiled)]
:when (>= (.lastModified source) (.lastModified compiled))]
(.getPath source)))
(def ^{:private true
:doc "Legacy (Lein1/Ant task) javac options that do not translate
to the new (JDK's javac) format as key-value pairs. For example, :debug \"off\"
needs to be translated to -g:none."}
special-ant-javac-keys [:destdir :debug :debugLevel])
(defn- normalize-specials
"Handles legacy (Lein1/Ant task) javac options that do not translate
to the new (JDK's javac) format as key-value pairs"
[{:keys [debug debugLevel]}]
;; debug "off" => -g:none
;; debugLevel "source,lines" => -g:source-lines
(if (or (= "off" debug) (false? debug))
["-g:none"]
(if debugLevel
[(str "-g:" debugLevel)]
[])))
(defn normalize-javac-options
"Converts :javac-opts in Leiningen 1 format (passed as a map) into
Leiningen 2 format (a vector).
Options in Leiningen 2 format are returned unmodified"
[opts]
(if (map? opts)
(let [special-opts (select-keys opts special-ant-javac-keys)
other-opts (apply dissoc (concat [opts] special-ant-javac-keys))
specials (normalize-specials special-opts)
others (flatten (vec (map (fn [[k v]]
[(str "-" (name k)) v]) other-opts)))]
(vec (map (comp name str) (flatten (concat specials others)))))
opts))
;; Tool's .run method expects the last argument to be an array of
;; strings, so that's what we'll return here.
(defn- javac-options
"Compile all sources of possible options and add important defaults.
Result is a String java array of options."
[project files args]
(into-array
String
(concat (normalize-javac-options (:javac-options project))
args
["-cp" (classpath/get-classpath-string project)
"-d" (:compile-path project)]
files)))
;; We can't really control what is printed here. We're just going to
;; allow `.run` to attach in, out, and err to the standard streams. This
;; should have the effect of compile errors being printed. javac doesn't
;; actually output any compilation info unless it has to (for an error)
;; or you make it do so with `-verbose`.
(defn- run-javac-task
"Run javac to compile all source files in the project."
[project args]
(let [compile-path (:compile-path project)
files (stale-java-sources (:java-source-paths project) compile-path)]
(when (seq files)
(if-let [compiler (ToolProvider/getSystemJavaCompiler)]
(do
(main/info "Compiling" (count files) "source files to" compile-path)
(.mkdirs (io/file compile-path))
(when-not (zero? (.run compiler nil nil nil (javac-options project files args)))
(main/abort "Compilation of Java sources (lein javac) failed, aborting.")))
(main/abort "lein-javac: system java compiler not found;"
"a JDK (vs. JRE) install is required.")))))
(defn javac
"Compile Java source files.
Add a :java-source-paths key to project.clj to specify where to find them.
Options passed in on the command line as well as options from the :javac-opts
vector in project.clj will be given to the compiler; e.g. `lein javac -verbose`.
Like the compile and deps tasks, this should be invoked automatically when
needed and shouldn't ever need to be run by hand. By default it is called before
compilation of Clojure source; change :prep-tasks to alter this."
[project & args]
(run-javac-task project args))