meson-build-system: Return #t from all phases.
[jackhill/guix/guix.git] / guix / build / ant-build-system.scm
CommitLineData
5f7a1a4d 1;;; GNU Guix --- Functional package management for GNU
d7ee90fe 2;;; Copyright © 2016, 2018 Ricardo Wurmus <rekado@elephly.net>
5f7a1a4d
RW
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (guix build ant-build-system)
20 #:use-module ((guix build gnu-build-system) #:prefix gnu:)
21 #:use-module (guix build syscalls)
22 #:use-module (guix build utils)
23 #:use-module (sxml simple)
24 #:use-module (ice-9 match)
25 #:use-module (ice-9 ftw)
26 #:use-module (srfi srfi-1)
27 #:use-module (srfi srfi-26)
28 #:export (%standard-phases
29 ant-build))
30
31;; Commentary:
32;;
33;; Builder-side code of the standard build procedure for Java packages using
34;; Ant.
35;;
36;; Code:
37
8df64f73 38(define* (default-build.xml jar-name prefix #:optional
f403d7ab
JL
39 (source-dir ".") (test-dir "./test") (main-class #f)
40 (test-include '("**/*Test.java"))
41 (test-exclude '("**/Abstract*Test.java")))
5f7a1a4d
RW
42 "Create a simple build.xml with standard targets for Ant."
43 (call-with-output-file "build.xml"
44 (lambda (port)
45 (sxml->xml
46 `(project (@ (basedir "."))
47 (property (@ (name "classes.dir")
48 (value "${basedir}/build/classes")))
8df1faa0
JL
49 (property (@ (name "manifest.dir")
50 (value "${basedir}/build/manifest")))
51 (property (@ (name "manifest.file")
52 (value "${manifest.dir}/MANIFEST.MF")))
5f7a1a4d
RW
53 (property (@ (name "jar.dir")
54 (value "${basedir}/build/jar")))
55 (property (@ (name "dist.dir")
56 (value ,prefix)))
52a791f5
RW
57 (property (@ (name "test.home")
58 (value ,test-dir)))
59 (property (@ (name "test.classes.dir")
60 (value "${basedir}/build/test-classes")))
5f7a1a4d
RW
61
62 ;; respect the CLASSPATH environment variable
63 (property (@ (name "build.sysclasspath")
64 (value "first")))
65 (property (@ (environment "env")))
66 (path (@ (id "classpath"))
67 (pathelement (@ (location "${env.CLASSPATH}"))))
68
8df1faa0
JL
69 (target (@ (name "manifest"))
70 (mkdir (@ (dir "${manifest.dir}")))
90ea1006
GB
71 (manifest (@ (file "${manifest.file}"))
72 ,(if main-class
73 `(attribute (@ (name "Main-Class")
74 (value ,main-class)))
75 "")))
8df1faa0 76
5f7a1a4d
RW
77 (target (@ (name "compile"))
78 (mkdir (@ (dir "${classes.dir}")))
79 (javac (@ (includeantruntime "false")
8df64f73 80 (srcdir ,source-dir)
5f7a1a4d
RW
81 (destdir "${classes.dir}")
82 (classpath (@ (refid "classpath"))))))
83
52a791f5
RW
84 (target (@ (name "compile-tests"))
85 (mkdir (@ (dir "${test.classes.dir}")))
86 (javac (@ (includeantruntime "false")
87 (srcdir ,test-dir)
88 (destdir "${test.classes.dir}"))
89 (classpath
90 (pathelement (@ (path "${env.CLASSPATH}")))
91 (pathelement (@ (location "${classes.dir}")))
92 (pathelement (@ (location "${test.classes.dir}"))))))
93
94 (target (@ (name "check")
95 (depends "compile-tests"))
96 (mkdir (@ (dir "${test.home}/test-reports")))
97 (junit (@ (printsummary "true")
98 (showoutput "true")
99 (fork "yes")
100 (haltonfailure "yes"))
101 (classpath
102 (pathelement (@ (path "${env.CLASSPATH}")))
103 (pathelement (@ (location "${test.home}/resources")))
104 (pathelement (@ (location "${classes.dir}")))
105 (pathelement (@ (location "${test.classes.dir}"))))
106 (formatter (@ (type "plain")
107 (usefile "true")))
108 (batchtest (@ (fork "yes")
109 (todir "${test.home}/test-reports"))
110 (fileset (@ (dir "${test.home}/java"))
f403d7ab
JL
111 ,@(map (lambda (file)
112 `(include (@ (name ,file))))
113 test-include)
114 ,@(map (lambda (file)
115 `(exclude (@ (name ,file))))
116 test-exclude)))))
52a791f5 117
5f7a1a4d 118 (target (@ (name "jar")
8df1faa0 119 (depends "compile, manifest"))
5f7a1a4d 120 (mkdir (@ (dir "${jar.dir}")))
5f7a1a4d 121 (exec (@ (executable "jar"))
8df1faa0
JL
122 (arg (@ (line ,(string-append "-cmf ${manifest.file} "
123 "${jar.dir}/" jar-name
5f7a1a4d
RW
124 " -C ${classes.dir} ."))))))
125
126 (target (@ (name "install"))
127 (copy (@ (todir "${dist.dir}"))
128 (fileset (@ (dir "${jar.dir}"))
129 (include (@ (name "**/*.jar")))))))
130 port)))
131 (utime "build.xml" 0 0)
132 #t)
133
134(define (generate-classpath inputs)
135 "Return a colon-separated string of full paths to jar files found among the
136INPUTS."
137 (string-join
138 (apply append (map (match-lambda
139 ((_ . dir)
abc4cb57 140 (find-files dir "\\.jar$")))
5f7a1a4d
RW
141 inputs)) ":"))
142
932f2b70
RW
143(define* (unpack #:key source #:allow-other-keys)
144 "Unpack the jar archive SOURCE. When SOURCE is not a jar archive fall back
145to the default GNU unpack strategy."
146 (if (string-suffix? ".jar" source)
147 (begin
148 (mkdir "src")
149 (with-directory-excursion "src"
d7ee90fe
RW
150 (invoke "jar" "-xf" source))
151 #t)
932f2b70
RW
152 ;; Use GNU unpack strategy for things that aren't jar archives.
153 ((assq-ref gnu:%standard-phases 'unpack) #:source source)))
154
5f7a1a4d 155(define* (configure #:key inputs outputs (jar-name #f)
52a791f5 156 (source-dir "src")
8df1faa0 157 (test-dir "src/test")
f403d7ab
JL
158 (main-class #f)
159 (test-include '("**/*Test.java"))
160 (test-exclude '("**/Abstract*.java")) #:allow-other-keys)
5f7a1a4d
RW
161 (when jar-name
162 (default-build.xml jar-name
163 (string-append (assoc-ref outputs "out")
8df64f73 164 "/share/java")
f403d7ab 165 source-dir test-dir main-class test-include test-exclude))
5f7a1a4d 166 (setenv "JAVA_HOME" (assoc-ref inputs "jdk"))
d6ac4d42
DM
167 (setenv "CLASSPATH" (generate-classpath inputs))
168 #t)
5f7a1a4d
RW
169
170(define* (build #:key (make-flags '()) (build-target "jar")
171 #:allow-other-keys)
d7ee90fe 172 (apply invoke `("ant" ,build-target ,@make-flags)))
5f7a1a4d 173
bc65332a
DM
174(define* (generate-jar-indices #:key outputs #:allow-other-keys)
175 "Generate file \"META-INF/INDEX.LIST\". This file does not use word wraps
176and is preferred over \"META-INF/MAINFEST.MF\", which does use word wraps,
177by Java when resolving dependencies. So we make sure to create it so that
178grafting works - and so that the garbage collector doesn't collect
179dependencies of this jar file."
180 (define (generate-index jar)
181 (invoke "jar" "-i" jar))
182 (every (match-lambda
183 ((output . directory)
184 (every generate-index (find-files directory "\\.jar$"))))
185 outputs))
186
5f7a1a4d 187(define* (strip-jar-timestamps #:key outputs
9941e081 188 #:allow-other-keys)
5f7a1a4d
RW
189 "Unpack all jar archives, reset the timestamp of all contained files, and
190repack them. This is necessary to ensure that archives are reproducible."
191 (define (repack-archive jar)
192 (format #t "repacking ~a\n" jar)
9941e081
RW
193 (let* ((dir (mkdtemp! "jar-contents.XXXXXX"))
194 (manifest (string-append dir "/META-INF/MANIFEST.MF")))
d7ee90fe
RW
195 (with-directory-excursion dir
196 (invoke "jar" "xf" jar))
197 (delete-file jar)
198 ;; XXX: copied from (gnu build install)
199 (for-each (lambda (file)
200 (let ((s (lstat file)))
201 (unless (eq? (stat:type s) 'symlink)
202 (utime file 0 0 0 0))))
203 (find-files dir #:directories? #t))
9941e081 204
d7ee90fe
RW
205 ;; The jar tool will always set the timestamp on the manifest file
206 ;; and the containing directory to the current time, even when we
207 ;; reuse an existing manifest file. To avoid this we use "zip"
208 ;; instead of "jar". It is important that the manifest appears
209 ;; first.
210 (with-directory-excursion dir
211 (let* ((files (find-files "." ".*" #:directories? #t))
212 ;; To ensure that the reference scanner can detect all
213 ;; store references in the jars we disable compression
214 ;; with the "-0" option.
215 (command (if (file-exists? manifest)
216 `("zip" "-0" "-X" ,jar ,manifest ,@files)
217 `("zip" "-0" "-X" ,jar ,@files))))
218 (apply invoke command)))
219 (utime jar 0 0)
220 #t))
5f7a1a4d 221
d7ee90fe
RW
222 (for-each (match-lambda
223 ((output . directory)
224 (for-each repack-archive (find-files directory "\\.jar$"))))
225 outputs)
226 #t)
5f7a1a4d
RW
227
228(define* (check #:key target (make-flags '()) (tests? (not target))
229 (test-target "check")
230 #:allow-other-keys)
231 (if tests?
d7ee90fe
RW
232 (apply invoke `("ant" ,test-target ,@make-flags))
233 (format #t "test suite not run~%"))
234 #t)
5f7a1a4d
RW
235
236(define* (install #:key (make-flags '()) #:allow-other-keys)
d7ee90fe 237 (apply invoke `("ant" "install" ,@make-flags)))
5f7a1a4d
RW
238
239(define %standard-phases
240 (modify-phases gnu:%standard-phases
932f2b70 241 (replace 'unpack unpack)
189be331 242 (delete 'bootstrap)
5f7a1a4d
RW
243 (replace 'configure configure)
244 (replace 'build build)
245 (replace 'check check)
246 (replace 'install install)
bc65332a
DM
247 (add-after 'install 'generate-jar-indices generate-jar-indices)
248 (add-after 'generate-jar-indices 'strip-jar-timestamps
249 strip-jar-timestamps)))
5f7a1a4d
RW
250
251(define* (ant-build #:key inputs (phases %standard-phases)
252 #:allow-other-keys #:rest args)
253 "Build the given Java package, applying all of PHASES in order."
254 (apply gnu:gnu-build #:inputs inputs #:phases phases args))
255
256;;; ant-build-system.scm ends here