build: Add Ant build system.

* guix/build-system/ant.scm: New file.
* guix/build/ant-build-system: New file.
* Makefile.am (MODULES): Add new files.
* doc/guix.texi (Build Systems): Document ant-build-system.
This commit is contained in:
Ricardo Wurmus 2015-12-29 16:56:49 +01:00
parent 535e2a2fee
commit 5f7a1a4def
4 changed files with 332 additions and 0 deletions

View file

@ -56,6 +56,7 @@ MODULES = \
guix/graph.scm \ guix/graph.scm \
guix/cve.scm \ guix/cve.scm \
guix/build-system.scm \ guix/build-system.scm \
guix/build-system/ant.scm \
guix/build-system/cmake.scm \ guix/build-system/cmake.scm \
guix/build-system/emacs.scm \ guix/build-system/emacs.scm \
guix/build-system/glib-or-gtk.scm \ guix/build-system/glib-or-gtk.scm \
@ -75,6 +76,7 @@ MODULES = \
guix/cvs-download.scm \ guix/cvs-download.scm \
guix/svn-download.scm \ guix/svn-download.scm \
guix/ui.scm \ guix/ui.scm \
guix/build/ant-build-system.scm \
guix/build/download.scm \ guix/build/download.scm \
guix/build/cmake-build-system.scm \ guix/build/cmake-build-system.scm \
guix/build/emacs-build-system.scm \ guix/build/emacs-build-system.scm \

View file

@ -2720,6 +2720,27 @@ of @var{gnu-build-system}, and differ mainly in the set of inputs
implicitly added to the build process, and in the list of phases implicitly added to the build process, and in the list of phases
executed. Some of these build systems are listed below. executed. Some of these build systems are listed below.
@defvr {Scheme Variable} ant-build-system
This variable is exported by @code{(guix build-system ant)}. It
implements the build procedure for Java packages that can be built with
@url{http://ant.apache.org/, Ant build tool}.
It adds both @code{ant} and the @dfn{Java Development Kit} (JDK) as
provided by the @code{icedtea} package to the set of inputs. Different
packages can be specified with the @code{#:ant} and @code{#:jdk}
parameters, respectively.
When the original package does not provide a suitable Ant build file,
the parameter @code{#:jar-name} can be used to generate a minimal Ant
build file @file{build.xml} with tasks to build the specified jar
archive.
The parameter @code{#:build-target} can be used to specify the Ant task
that should be run during the @code{build} phase. By default the
``jar'' task will be run.
@end defvr
@defvr {Scheme Variable} cmake-build-system @defvr {Scheme Variable} cmake-build-system
This variable is exported by @code{(guix build-system cmake)}. It This variable is exported by @code{(guix build-system cmake)}. It
implements the build procedure for packages using the implements the build procedure for packages using the

149
guix/build-system/ant.scm Normal file
View file

@ -0,0 +1,149 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix build-system ant)
#:use-module (guix store)
#:use-module (guix utils)
#:use-module (guix packages)
#:use-module (guix derivations)
#:use-module (guix search-paths)
#:use-module (guix build-system)
#:use-module (guix build-system gnu)
#:use-module (ice-9 match)
#:use-module (srfi srfi-26)
#:export (%ant-build-system-modules
ant-build
ant-build-system))
;; Commentary:
;;
;; Standard build procedure for Java packages using Ant.
;;
;; Code:
(define %ant-build-system-modules
;; Build-side modules imported by default.
`((guix build ant-build-system)
(guix build syscalls)
,@%gnu-build-system-modules))
(define (default-jdk)
"Return the default JDK package."
;; Lazily resolve the binding to avoid a circular dependency.
(let ((jdk-mod (resolve-interface '(gnu packages java))))
(module-ref jdk-mod 'icedtea)))
(define (default-ant)
"Return the default Ant package."
;; Lazily resolve the binding to avoid a circular dependency.
(let ((jdk-mod (resolve-interface '(gnu packages java))))
(module-ref jdk-mod 'ant)))
(define* (lower name
#:key source inputs native-inputs outputs system target
(jdk (default-jdk))
(ant (default-ant))
#:allow-other-keys
#:rest arguments)
"Return a bag for NAME."
(define private-keywords
'(#:source #:target #:jdk #:ant #:inputs #:native-inputs))
(and (not target) ;XXX: no cross-compilation
(bag
(name name)
(system system)
(host-inputs `(,@(if source
`(("source" ,source))
'())
,@inputs
;; Keep the standard inputs of 'gnu-build-system'.
,@(standard-packages)))
(build-inputs `(("jdk" ,jdk "jdk")
("ant" ,ant)
,@native-inputs))
(outputs outputs)
(build ant-build)
(arguments (strip-keyword-arguments private-keywords arguments)))))
(define* (ant-build store name inputs
#:key
(tests? #t)
(test-target "tests")
(configure-flags ''())
(make-flags ''())
(build-target "jar")
(jar-name #f)
(phases '(@ (guix build ant-build-system)
%standard-phases))
(outputs '("out"))
(search-paths '())
(system (%current-system))
(guile #f)p
(imported-modules %ant-build-system-modules)
(modules '((guix build ant-build-system)
(guix build utils))))
"Build SOURCE with INPUTS."
(define builder
`(begin
(use-modules ,@modules)
(ant-build #:name ,name
#:source ,(match (assoc-ref inputs "source")
(((? derivation? source))
(derivation->output-path source))
((source)
source)
(source
source))
#:make-flags ,make-flags
#:configure-flags ,configure-flags
#:system ,system
#:tests? ,tests?
#:test-target ,test-target
#:build-target ,build-target
#:jar-name ,jar-name
#:phases ,phases
#:outputs %outputs
#:search-paths ',(map search-path-specification->sexp
search-paths)
#:inputs %build-inputs)))
(define guile-for-build
(match guile
((? package?)
(package-derivation store guile system #:graft? #f))
(#f ; the default
(let* ((distro (resolve-interface '(gnu packages commencement)))
(guile (module-ref distro 'guile-final)))
(package-derivation store guile system #:graft? #f)))))
(build-expression->derivation store name builder
#:inputs inputs
#:system system
#:modules imported-modules
#:outputs outputs
#:guile-for-build guile-for-build))
(define ant-build-system
(build-system
(name 'ant)
(description "The standard Ant build system")
(lower lower)))
;;; ant.scm ends here

View file

@ -0,0 +1,160 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix build ant-build-system)
#:use-module ((guix build gnu-build-system) #:prefix gnu:)
#:use-module (guix build syscalls)
#:use-module (guix build utils)
#:use-module (sxml simple)
#:use-module (ice-9 match)
#:use-module (ice-9 ftw)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:export (%standard-phases
ant-build))
;; Commentary:
;;
;; Builder-side code of the standard build procedure for Java packages using
;; Ant.
;;
;; Code:
(define (default-build.xml jar-name prefix)
"Create a simple build.xml with standard targets for Ant."
(call-with-output-file "build.xml"
(lambda (port)
(sxml->xml
`(project (@ (basedir "."))
(property (@ (name "classes.dir")
(value "${basedir}/build/classes")))
(property (@ (name "jar.dir")
(value "${basedir}/build/jar")))
(property (@ (name "dist.dir")
(value ,prefix)))
;; respect the CLASSPATH environment variable
(property (@ (name "build.sysclasspath")
(value "first")))
(property (@ (environment "env")))
(path (@ (id "classpath"))
(pathelement (@ (location "${env.CLASSPATH}"))))
(target (@ (name "compile"))
(mkdir (@ (dir "${classes.dir}")))
(javac (@ (includeantruntime "false")
(srcdir "src")
(destdir "${classes.dir}")
(classpath (@ (refid "classpath"))))))
(target (@ (name "jar")
(depends "compile"))
(mkdir (@ (dir "${jar.dir}")))
;; We cannot use the simpler "jar" task here, because
;; there is no way to disable generation of a
;; manifest. We do not include a generated manifest
;; to ensure determinism, because we cannot easily
;; reset the ctime/mtime before creating the archive.
(exec (@ (executable "jar"))
(arg (@ (line ,(string-append "-Mcf ${jar.dir}/" jar-name
" -C ${classes.dir} ."))))))
(target (@ (name "install"))
(copy (@ (todir "${dist.dir}"))
(fileset (@ (dir "${jar.dir}"))
(include (@ (name "**/*.jar")))))))
port)))
(utime "build.xml" 0 0)
#t)
(define (generate-classpath inputs)
"Return a colon-separated string of full paths to jar files found among the
INPUTS."
(string-join
(apply append (map (match-lambda
((_ . dir)
(find-files dir "\\.*jar$")))
inputs)) ":"))
(define* (configure #:key inputs outputs (jar-name #f)
#:allow-other-keys)
(when jar-name
(default-build.xml jar-name
(string-append (assoc-ref outputs "out")
"/share/java")))
(setenv "JAVA_HOME" (assoc-ref inputs "jdk"))
(setenv "CLASSPATH" (generate-classpath inputs)))
(define* (build #:key (make-flags '()) (build-target "jar")
#:allow-other-keys)
(zero? (apply system* `("ant" ,build-target ,@make-flags))))
(define* (strip-jar-timestamps #:key outputs
#:allow-other-keys)
"Unpack all jar archives, reset the timestamp of all contained files, and
repack them. This is necessary to ensure that archives are reproducible."
(define (repack-archive jar)
(format #t "repacking ~a\n" jar)
(let ((dir (mkdtemp! "jar-contents.XXXXXX")))
(and (with-directory-excursion dir
(zero? (system* "jar" "xf" jar)))
;; The manifest file contains timestamps
(for-each delete-file (find-files dir "MANIFEST.MF"))
(delete-file jar)
;; XXX: copied from (gnu build install)
(for-each (lambda (file)
(let ((s (lstat file)))
(unless (eq? (stat:type s) 'symlink)
(utime file 0 0 0 0))))
(find-files dir #:directories? #t))
(unless (zero? (system* "jar" "-Mcf" jar "-C" dir "."))
(error "'jar' failed"))
(utime jar 0 0)
#t)))
(every (match-lambda
((output . directory)
(every repack-archive (find-files directory "\\.jar$"))))
outputs))
(define* (check #:key target (make-flags '()) (tests? (not target))
(test-target "check")
#:allow-other-keys)
(if tests?
(zero? (apply system* `("ant" ,test-target ,@make-flags)))
(begin
(format #t "test suite not run~%")
#t)))
(define* (install #:key (make-flags '()) #:allow-other-keys)
(zero? (apply system* `("ant" "install" ,@make-flags))))
(define %standard-phases
(modify-phases gnu:%standard-phases
(replace 'configure configure)
(replace 'build build)
(replace 'check check)
(replace 'install install)
(add-after 'install 'strip-jar-timestamps strip-jar-timestamps)))
(define* (ant-build #:key inputs (phases %standard-phases)
#:allow-other-keys #:rest args)
"Build the given Java package, applying all of PHASES in order."
(apply gnu:gnu-build #:inputs inputs #:phases phases args))
;;; ant-build-system.scm ends here