| 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2016, 2017 Ricardo Wurmus <rekado@elephly.net> |
| 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 (gnu packages axoloti) |
| 20 | #:use-module (guix utils) |
| 21 | #:use-module (guix packages) |
| 22 | #:use-module (guix download) |
| 23 | #:use-module ((guix licenses) #:prefix license:) |
| 24 | #:use-module (guix build-system gnu) |
| 25 | #:use-module (guix build-system ant) |
| 26 | #:use-module (gnu packages) |
| 27 | #:use-module (gnu packages base) |
| 28 | #:use-module (gnu packages compression) |
| 29 | #:use-module (gnu packages cross-base) |
| 30 | #:use-module (gnu packages embedded) |
| 31 | #:use-module (gnu packages flashing-tools) |
| 32 | #:use-module (gnu packages java) |
| 33 | #:use-module (gnu packages libusb) |
| 34 | #:use-module (gnu packages pkg-config) |
| 35 | #:use-module (gnu packages textutils) |
| 36 | #:use-module (gnu packages version-control) |
| 37 | #:use-module (gnu packages xml)) |
| 38 | |
| 39 | (define libusb-for-axoloti |
| 40 | (package (inherit libusb) |
| 41 | (name "axoloti-libusb") |
| 42 | (version (package-version libusb)) |
| 43 | (source |
| 44 | (origin |
| 45 | (inherit (package-source libusb)) |
| 46 | (patches (list (search-patch "libusb-for-axoloti.patch"))))))) |
| 47 | |
| 48 | (define dfu-util-for-axoloti |
| 49 | (package (inherit dfu-util) |
| 50 | (name "axoloti-dfu-util") |
| 51 | (version "0.8") |
| 52 | (source |
| 53 | (origin |
| 54 | (method url-fetch) |
| 55 | (uri (string-append "http://dfu-util.sourceforge.net/releases/" |
| 56 | "dfu-util-" version ".tar.gz")) |
| 57 | (sha256 |
| 58 | (base32 |
| 59 | "0n7h08avlzin04j93m6hkq9id6hxjiiix7ff9gc2n89aw6dxxjsm")))) |
| 60 | (inputs |
| 61 | `(("libusb" ,libusb-for-axoloti))))) |
| 62 | |
| 63 | (define-public axoloti-runtime |
| 64 | (package |
| 65 | (name "axoloti-runtime") |
| 66 | (version "1.0.12") |
| 67 | (source (origin |
| 68 | (method url-fetch) |
| 69 | (uri (string-append "https://github.com/axoloti/axoloti/" |
| 70 | "archive/" version ".tar.gz")) |
| 71 | (file-name (string-append name "-" version ".tar.gz")) |
| 72 | (sha256 |
| 73 | (base32 |
| 74 | "1dynk6h0nixp4zihpirpqa4vi8fq1lhm443jsmvhk135ykhf364p")) |
| 75 | (modules '((guix build utils))) |
| 76 | (snippet |
| 77 | '(begin |
| 78 | ;; Remove pre-built Java binaries. |
| 79 | (delete-file-recursively "lib/") |
| 80 | #t)))) |
| 81 | (build-system gnu-build-system) |
| 82 | (arguments |
| 83 | `(#:tests? #f ; no check target |
| 84 | #:modules ((guix build gnu-build-system) |
| 85 | (guix build utils) |
| 86 | (srfi srfi-1) |
| 87 | (srfi srfi-26) |
| 88 | (ice-9 match) |
| 89 | (ice-9 regex)) |
| 90 | #:imported-modules ((guix build syscalls) |
| 91 | ,@%gnu-build-system-modules) |
| 92 | #:phases |
| 93 | (modify-phases %standard-phases |
| 94 | (add-after 'unpack 'patch-paths |
| 95 | (lambda* (#:key inputs #:allow-other-keys) |
| 96 | ;; prepare ChibiOS |
| 97 | (and (zero? (system* "unzip" "-o" (assoc-ref inputs "chibios"))) |
| 98 | (zero? (system* "mv" "ChibiOS_2.6.9" "chibios")) |
| 99 | (with-directory-excursion "chibios/ext" |
| 100 | (zero? (system* "unzip" "-o" "fatfs-0.9-patched.zip")))) |
| 101 | |
| 102 | ;; Remove source of non-determinism in ChibiOS |
| 103 | (substitute* "chibios/os/various/shell.c" |
| 104 | (("#ifdef __DATE__") "#if 0")) |
| 105 | |
| 106 | ;; Patch shell paths |
| 107 | (substitute* '("src/main/java/qcmds/QCmdCompileFirmware.java" |
| 108 | "src/main/java/qcmds/QCmdCompilePatch.java" |
| 109 | "src/main/java/qcmds/QCmdFlashDFU.java") |
| 110 | (("/bin/sh") (which "sh"))) |
| 111 | |
| 112 | ;; Override cross compiler base name |
| 113 | (substitute* "firmware/Makefile.patch" |
| 114 | (("arm-none-eabi-(gcc|g\\+\\+|objcopy|objdump)" tool) |
| 115 | (which tool))) |
| 116 | |
| 117 | ;; Hardcode full path to compiler tools |
| 118 | (substitute* '("firmware/Makefile" |
| 119 | "firmware/flasher/Makefile" |
| 120 | "firmware/mounter/Makefile") |
| 121 | (("TRGT =.*") |
| 122 | (string-append "TRGT = " |
| 123 | (assoc-ref inputs "cross-toolchain") |
| 124 | "/bin/arm-none-eabi-\n"))) |
| 125 | |
| 126 | ;; Hardcode path to "make" |
| 127 | (substitute* '("firmware/compile_firmware_linux.sh" |
| 128 | "firmware/compile_patch_linux.sh") |
| 129 | (("make") (which "make"))) |
| 130 | |
| 131 | ;; Hardcode path to "dfu-util" |
| 132 | (substitute* "platform_linux/upload_fw_dfu.sh" |
| 133 | (("-f \"\\$\\{platformdir\\}/bin/dfu-util\"") "-z \"\"") |
| 134 | (("\\./dfu-util") (which "dfu-util"))) |
| 135 | #t)) |
| 136 | (delete 'configure) |
| 137 | (replace 'build |
| 138 | ;; Build Axoloti firmware with cross-compiler |
| 139 | (lambda* (#:key inputs #:allow-other-keys) |
| 140 | (let* ((toolchain (assoc-ref inputs "cross-toolchain")) |
| 141 | (headers (string-append |
| 142 | toolchain |
| 143 | "/arm-none-eabi/include:" |
| 144 | toolchain |
| 145 | "/arm-none-eabi/include/arm-none-eabi/armv7e-m"))) |
| 146 | (setenv "CROSS_CPATH" headers) |
| 147 | (setenv "CROSS_CPLUS_INCLUDE_PATH" headers) |
| 148 | (setenv "CROSS_LIBRARY_PATH" |
| 149 | (string-append toolchain |
| 150 | "/arm-none-eabi/lib"))) |
| 151 | (with-directory-excursion "platform_linux" |
| 152 | (zero? (system* "sh" "compile_firmware.sh"))))) |
| 153 | (replace 'install |
| 154 | (lambda* (#:key inputs outputs #:allow-other-keys) |
| 155 | (let* ((out (assoc-ref outputs "out")) |
| 156 | (share (string-append out "/share/axoloti/")) |
| 157 | (doc (string-append share "doc")) |
| 158 | (dir (getcwd)) |
| 159 | (pats '("/doc/[^/]+$" |
| 160 | "/patches/[^/]+/[^/]+$" |
| 161 | "/objects/[^/]+/[^/]+$" |
| 162 | "/firmware/.+" |
| 163 | "/chibios/[^/]+$" |
| 164 | "/chibios/boards/ST_STM32F4_DISCOVERY/[^/]+$" |
| 165 | "/chibios/(ext|os|docs)/.+" |
| 166 | "/CMSIS/[^/]+/[^/]+$" |
| 167 | "/patch/[^/]+/[^/]+$" |
| 168 | "/[^/]+\\.txt$")) |
| 169 | (pattern (string-append |
| 170 | "(" (string-join |
| 171 | (map (cut string-append dir <>) |
| 172 | pats) |
| 173 | "|") ")")) |
| 174 | (files (find-files dir |
| 175 | (lambda (file stat) |
| 176 | (and (eq? 'regular (stat:type stat)) |
| 177 | (string-match pattern file)))))) |
| 178 | (for-each (lambda (file) |
| 179 | (install-file file |
| 180 | (string-append |
| 181 | share |
| 182 | (regexp-substitute |
| 183 | #f |
| 184 | (string-match dir (dirname file)) |
| 185 | 'pre 'post)))) |
| 186 | files) |
| 187 | #t)))))) |
| 188 | (inputs |
| 189 | `(("chibios" |
| 190 | ,(origin |
| 191 | (method url-fetch) |
| 192 | (uri "mirror://sourceforge/chibios/ChibiOS%20GPL3/Version%202.6.9/ChibiOS_2.6.9.zip") |
| 193 | (sha256 |
| 194 | (base32 |
| 195 | "0lb5s8pkj80mqhsy47mmq0lqk34s2a2m3xagzihalvabwd0frhlj")))) |
| 196 | ;; for compiling patches |
| 197 | ("make" ,gnu-make) |
| 198 | ;; for compiling firmware |
| 199 | ("cross-toolchain" ,arm-none-eabi-nano-toolchain-4.9) |
| 200 | ;; for uploading compiled patches and firmware |
| 201 | ("dfu-util" ,dfu-util-for-axoloti))) |
| 202 | (native-inputs |
| 203 | `(("unzip" ,unzip))) |
| 204 | (home-page "http://www.axoloti.com/") |
| 205 | (synopsis "Audio development environment for the Axoloti core board") |
| 206 | (description |
| 207 | "The Axoloti patcher offers a “patcher” environment similar to Pure Data |
| 208 | for sketching digital audio algorithms. The patches run on a standalone |
| 209 | powerful microcontroller board: Axoloti Core. This package provides the |
| 210 | runtime.") |
| 211 | (license license:gpl3+))) |
| 212 | |
| 213 | (define-public axoloti-patcher |
| 214 | (package (inherit axoloti-runtime) |
| 215 | (name "axoloti-patcher") |
| 216 | (version (package-version axoloti-runtime)) |
| 217 | (arguments |
| 218 | `(#:tests? #f ; no check target |
| 219 | #:modules ((guix build gnu-build-system) |
| 220 | ((guix build ant-build-system) #:prefix ant:) |
| 221 | (guix build utils) |
| 222 | (srfi srfi-1) |
| 223 | (srfi srfi-26) |
| 224 | (ice-9 match) |
| 225 | (ice-9 regex) |
| 226 | (sxml simple) |
| 227 | (sxml xpath) |
| 228 | (sxml transform)) |
| 229 | #:imported-modules ((guix build ant-build-system) |
| 230 | (guix build syscalls) |
| 231 | ,@%gnu-build-system-modules) |
| 232 | #:phases |
| 233 | (modify-phases %standard-phases |
| 234 | (delete 'configure) |
| 235 | (replace 'build |
| 236 | (lambda* (#:key inputs #:allow-other-keys) |
| 237 | (setenv "JAVA_HOME" (assoc-ref inputs "icedtea")) |
| 238 | ;; We want to use our own jar files instead of the pre-built |
| 239 | ;; stuff in lib. So we replace the zipfileset tags in the |
| 240 | ;; build.xml with new ones that reference our jars. |
| 241 | (let* ((build.xml (with-input-from-file "build.xml" |
| 242 | (lambda _ |
| 243 | (xml->sxml #:trim-whitespace? #t)))) |
| 244 | (jars (append-map (match-lambda |
| 245 | (((? (cut string-prefix? "java-" <>) |
| 246 | label) . directory) |
| 247 | (find-files directory "\\.jar$")) |
| 248 | (_ '())) |
| 249 | inputs)) |
| 250 | (classpath (string-join jars ":")) |
| 251 | (fileset (map (lambda (jar) |
| 252 | `(zipfileset (@ (excludes "META-INF/*.SF") |
| 253 | (src ,jar)))) |
| 254 | jars))) |
| 255 | (call-with-output-file "build.xml" |
| 256 | (lambda (port) |
| 257 | (sxml->xml |
| 258 | (pre-post-order |
| 259 | build.xml |
| 260 | `(;; Remove all zipfileset tags from the "jar" tree and |
| 261 | ;; inject our own tags. |
| 262 | (jar . ,(lambda (tag . kids) |
| 263 | `(jar ,@(append-map |
| 264 | (filter (lambda (e) |
| 265 | (not (eq? 'zipfileset (car e))))) |
| 266 | kids) |
| 267 | ,@fileset))) |
| 268 | ;; Skip the "bundle" target (and the "-post-jar" target |
| 269 | ;; that depends on it), because we don't need it and it |
| 270 | ;; confuses sxml->xml. |
| 271 | (target . ,(lambda (tag . kids) |
| 272 | (let ((name ((sxpath '(name *text*)) |
| 273 | (car kids)))) |
| 274 | (if (or (member "bundle" name) |
| 275 | (member "-post-jar" name)) |
| 276 | '() ; skip |
| 277 | `(,tag ,@kids))))) |
| 278 | (*default* . ,(lambda (tag . kids) `(,tag ,@kids))) |
| 279 | (*text* . ,(lambda (_ txt) |
| 280 | (match txt |
| 281 | ;; Remove timestamp. |
| 282 | ("${TODAY}" "(unknown)") |
| 283 | (_ txt)))))) |
| 284 | port))) |
| 285 | |
| 286 | ;; Build it! |
| 287 | (zero? (system* "ant" |
| 288 | (string-append "-Djavac.classpath=" classpath) |
| 289 | "-Dbuild.runtime=true" |
| 290 | "-Dbuild.time=01/01/1970 00:00:00" |
| 291 | "-Djavac.source=1.7" |
| 292 | "-Djavac.target=1.7" |
| 293 | (string-append "-Dtag.short.version=" |
| 294 | ,version)))))) |
| 295 | (replace 'install |
| 296 | (lambda* (#:key inputs outputs #:allow-other-keys) |
| 297 | (let* ((out (assoc-ref outputs "out")) |
| 298 | (share (string-append out "/share/axoloti/"))) |
| 299 | (install-file "dist/Axoloti.jar" share) |
| 300 | |
| 301 | ;; We do this to ensure that this package retains references to |
| 302 | ;; other Java packages' jar files. |
| 303 | (install-file "build.xml" share) |
| 304 | |
| 305 | ;; Create a launcher script |
| 306 | (mkdir (string-append out "/bin")) |
| 307 | (let ((target (string-append out "/bin/Axoloti"))) |
| 308 | (with-output-to-file target |
| 309 | (lambda () |
| 310 | (let* ((dir (string-append (assoc-ref outputs "out") |
| 311 | "/share/axoloti")) |
| 312 | (runtime (string-append (assoc-ref inputs "axoloti-runtime") |
| 313 | "/share/axoloti")) |
| 314 | (toolchain (assoc-ref inputs "cross-toolchain")) |
| 315 | (includes (string-append |
| 316 | toolchain |
| 317 | "/arm-none-eabi/include:" |
| 318 | toolchain |
| 319 | "/arm-none-eabi/include/arm-none-eabi/armv7e-m"))) |
| 320 | (display |
| 321 | (string-append "#!" (which "sh") "\n" |
| 322 | "export CROSS_CPATH=" includes "\n" |
| 323 | "export CROSS_CPLUS_INCLUDE_PATH=" includes "\n" |
| 324 | "export CROSS_LIBRARY_PATH=" |
| 325 | toolchain "/arm-none-eabi/lib" "\n" |
| 326 | (which "java") |
| 327 | " -Daxoloti_release=" runtime |
| 328 | " -Daxoloti_runtime=" runtime |
| 329 | " -jar " dir "/Axoloti.jar"))))) |
| 330 | (chmod target #o555)) |
| 331 | #t))) |
| 332 | (add-after 'install 'strip-jar-timestamps |
| 333 | (assoc-ref ant:%standard-phases 'strip-jar-timestamps))))) |
| 334 | (inputs |
| 335 | `(("icedtea" ,icedtea "jdk") |
| 336 | ("cross-toolchain" ,arm-none-eabi-nano-toolchain-4.9) |
| 337 | ("java-simple-xml" ,java-simple-xml) |
| 338 | ("java-rsyntaxtextarea" ,java-rsyntaxtextarea) |
| 339 | ("java-usb4java" ,java-usb4java) |
| 340 | ("java-jsch" ,java-jsch) |
| 341 | ("java-slf4j-api" ,java-slf4j-api) |
| 342 | ("java-jgit" ,java-jgit-4.2) |
| 343 | ("axoloti-runtime" ,axoloti-runtime))) |
| 344 | (native-inputs |
| 345 | `(("ant" ,ant) |
| 346 | ("zip" ,zip) ; for repacking the jar |
| 347 | ("unzip" ,unzip))) |
| 348 | (description |
| 349 | "The Axoloti patcher offers a “patcher” environment similar to Pure Data |
| 350 | for sketching digital audio algorithms. The patches run on a standalone |
| 351 | powerful microcontroller board: Axoloti Core. This package provides the |
| 352 | patcher application."))) |