From 4528aee1d700ba0ac611fb07faf4c5a8c7e0b9ad Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Thu, 1 Dec 2016 15:25:07 -0400 Subject: - Slightly changed the lux-lein commands. --- lux-lein/src/leiningen/lux.clj | 27 ++++ lux-lein/src/leiningen/lux/builder.clj | 18 +++ lux-lein/src/leiningen/lux/packager.clj | 212 +++++++++++++++++++++++++++++++ lux-lein/src/leiningen/lux/repl.clj | 35 +++++ lux-lein/src/leiningen/lux/test.clj | 27 ++++ lux-lein/src/leiningen/lux/utils.clj | 96 ++++++++++++++ lux-lein/src/leiningen/luxc.clj | 27 ---- lux-lein/src/leiningen/luxc/compiler.clj | 19 --- lux-lein/src/leiningen/luxc/packager.clj | 212 ------------------------------- lux-lein/src/leiningen/luxc/repl.clj | 35 ----- lux-lein/src/leiningen/luxc/test.clj | 27 ---- lux-lein/src/leiningen/luxc/utils.clj | 97 -------------- 12 files changed, 415 insertions(+), 417 deletions(-) create mode 100644 lux-lein/src/leiningen/lux.clj create mode 100644 lux-lein/src/leiningen/lux/builder.clj create mode 100644 lux-lein/src/leiningen/lux/packager.clj create mode 100644 lux-lein/src/leiningen/lux/repl.clj create mode 100644 lux-lein/src/leiningen/lux/test.clj create mode 100644 lux-lein/src/leiningen/lux/utils.clj delete mode 100644 lux-lein/src/leiningen/luxc.clj delete mode 100644 lux-lein/src/leiningen/luxc/compiler.clj delete mode 100644 lux-lein/src/leiningen/luxc/packager.clj delete mode 100644 lux-lein/src/leiningen/luxc/repl.clj delete mode 100644 lux-lein/src/leiningen/luxc/test.clj delete mode 100644 lux-lein/src/leiningen/luxc/utils.clj (limited to 'lux-lein') diff --git a/lux-lein/src/leiningen/lux.clj b/lux-lein/src/leiningen/lux.clj new file mode 100644 index 000000000..6b2268d70 --- /dev/null +++ b/lux-lein/src/leiningen/lux.clj @@ -0,0 +1,27 @@ +;; Copyright (c) Eduardo Julian. All rights reserved. +;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +;; If a copy of the MPL was not distributed with this file, +;; You can obtain one at http://mozilla.org/MPL/2.0/. + +(ns leiningen.lux + (:require [leiningen.pom :as pom] + [leiningen.core.classpath :as classpath] + (leiningen.lux [builder :as &builder] + [test :as &test] + [repl :as &repl]))) + +;; [Exports] +(defn lux [project & args] + (case (first args) + "build" + (&builder/build project) + + "test" + (&test/test project) + + "repl" + (&repl/repl project) + + ;; default... + (println "Commands available: build, test, repl")) + ) diff --git a/lux-lein/src/leiningen/lux/builder.clj b/lux-lein/src/leiningen/lux/builder.clj new file mode 100644 index 000000000..530b61bfe --- /dev/null +++ b/lux-lein/src/leiningen/lux/builder.clj @@ -0,0 +1,18 @@ +;; Copyright (c) Eduardo Julian. All rights reserved. +;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +;; If a copy of the MPL was not distributed with this file, +;; You can obtain one at http://mozilla.org/MPL/2.0/. + +(ns leiningen.lux.builder + (:require [leiningen.core.classpath :as classpath] + (leiningen.lux [utils :as &utils] + [packager :as &packager]))) + +(defn build [project] + (if-let [program-module (get-in project [:lux :program])] + (do (&utils/run-process (&utils/compile-path project program-module (get project :source-paths (list))) + nil + "[BUILD BEGIN]" + "[BUILD END]") + (&packager/package project program-module (get project :resource-paths (list)))) + (println "Please provide a program main module in [:lux :program]"))) diff --git a/lux-lein/src/leiningen/lux/packager.clj b/lux-lein/src/leiningen/lux/packager.clj new file mode 100644 index 000000000..dd037fe51 --- /dev/null +++ b/lux-lein/src/leiningen/lux/packager.clj @@ -0,0 +1,212 @@ +;; Copyright (c) Eduardo Julian. All rights reserved. +;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +;; If a copy of the MPL was not distributed with this file, +;; You can obtain one at http://mozilla.org/MPL/2.0/. + +(ns leiningen.lux.packager + (:require [clojure.string :as string] + [leiningen.core.classpath :as classpath] + [leiningen.uberjar] + [leiningen.lux.utils :as &utils]) + (:import (java.io InputStream + File + FileInputStream + FileOutputStream + BufferedInputStream + ByteArrayInputStream + ByteArrayOutputStream) + (java.util.jar Manifest + Attributes$Name + JarEntry + JarInputStream + JarOutputStream + ))) + +;; [Utils] +(def ^:private kilobyte 1024) +(def ^:private buffer-size (* 10 kilobyte)) + +(defn ^:private manifest + "(-> Project Text Bool Manifest)" + [project module includes-android?] + (doto (new Manifest) + (-> .getMainAttributes + (doto (-> (.put Attributes$Name/MAIN_CLASS (str module "._")) + (->> (when (not includes-android?)))) + (.put Attributes$Name/MANIFEST_VERSION "1.0") + (.put (new Attributes$Name "LUX_JAR") "true") + (-> (.put (new Attributes$Name name) real-v) + (->> (doseq [[name v] (get project :manifest) + :let [real-v (if (string? v) v (v project))]]))))))) + +(defn ^:private write-class! + "(-> Text File JarOutputStream Null)" + [^String path ^File file ^JarOutputStream out] + (with-open [in (new BufferedInputStream (new FileInputStream file))] + (let [buffer (byte-array buffer-size)] + (doto out + (.putNextEntry (new JarEntry (str path "/" (.getName file)))) + (-> (.write buffer 0 bytes-read) + (->> (when (not= -1 bytes-read)) + (loop [bytes-read (.read in buffer)]))) + (.flush) + (.closeEntry) + )) + )) + +(defn ^:private write-module! + "(-> File JarOutputStream Null)" + [^File file ^JarOutputStream out output-dir] + (let [output-dir-size (inc (.length output-dir)) + module-name (.substring (.getPath file) output-dir-size) + inner-files (.listFiles file) + inner-modules (filter #(.isDirectory ^File %) inner-files) + inner-classes (filter #(not (.isDirectory ^File %)) inner-files)] + (doseq [$class inner-classes] + (write-class! module-name $class out)) + (doseq [$module inner-modules] + (write-module! $module out output-dir)))) + +(defn ^:private write-resources! + "(-> JarOutputStream (List Text) Null)" + [^JarOutputStream out resources-dirs] + (doseq [resources-dir resources-dirs + :let [resources-dir (new File resources-dir)] + :when (.exists resources-dir) + ^File res (.listFiles resources-dir) + :let [buffer (byte-array buffer-size)]] + (with-open [in (->> res (new FileInputStream) (new BufferedInputStream))] + (doto out + (.putNextEntry (new JarEntry (.getName res))) + (-> (.write buffer 0 bytes-read) + (->> (when (not= -1 bytes-read)) + (loop [bytes-read (.read in buffer)]))) + (.flush) + (.closeEntry)) + ))) + +(let [init-capacity (* 100 1024) + buffer-size 1024] + (defn ^:private ^"[B" read-stream [^InputStream is] + (let [buffer (byte-array buffer-size)] + (with-open [os (new ByteArrayOutputStream init-capacity)] + (loop [bytes-read (.read is buffer 0 buffer-size)] + (when (not= -1 bytes-read) + (do (.write os buffer 0 bytes-read) + (recur (.read is buffer 0 buffer-size))))) + (.toByteArray os))))) + +(defn ^:private add-jar! [^File jar-file project !all-jar-files] + (with-open [is (->> jar-file (new FileInputStream) (new JarInputStream))] + (loop [^JarEntry entry (.getNextJarEntry is)] + (when entry + (let [entry-name (.getName entry)] + (if (and (not (.isDirectory entry)) + (not (.startsWith entry-name "META-INF/maven/")) + (not (some (fn [exclusion] + (re-find exclusion entry-name)) + (get project :uberjar-exclusions)))) + (let [entry-data (read-stream is) + entry-data (or (some (fn [[pattern [read fuse write]]] + (let [matches? (if (string? pattern) + (= pattern entry-name) + (re-find pattern entry-name))] + (when matches? + (let [os (new ByteArrayOutputStream 1024) + [_data _entry] (get @!all-jar-files entry-name [(byte-array 0) nil]) + _ (write os (fuse (read (new ByteArrayInputStream _data)) + (read (new ByteArrayInputStream entry-data))))] + (.toByteArray os))))) + (eval (get project :uberjar-merge-with))) + entry-data)] + (swap! !all-jar-files assoc entry-name [entry-data entry]) + (recur (.getNextJarEntry is))) + (recur (.getNextJarEntry is)))) + )))) + +(def default-manifest-file "./AndroidManifest.xml") + +;; [Resources] +(defn package + "(-> Text (List Text) Null)" + [project module resources-dirs] + (let [output-dir (get-in project [:lux :target] &utils/output-dir) + output-package (str (get-in project [:lux :target] &utils/output-dir) "/" + (get project :jar-name &utils/output-package)) + !all-jar-files (atom {}) + includes-android? (boolean (some #(-> % first (= 'com.google.android/android)) + (get project :dependencies))) + project* (-> project + (update-in [:dependencies] (fn [_deps] + ;; Skip the last two, + ;; because they are: + ;; tools.nrepl-0.2.12.jar and + ;; clojure-complete-0.2.4.jar + ;; and they belong to Leiningen. + (take (- (count _deps) 2) _deps)))) + deps (->> project* + (classpath/resolve-managed-dependencies :dependencies :managed-dependencies) + (map #(.getAbsolutePath ^File %)))] + (do (.delete (new File output-package)) + (with-open [out (new JarOutputStream + (->> output-package (new File) (new FileOutputStream)) + (manifest project module includes-android?))] + (do (doseq [$group (.listFiles (new File output-dir))] + (write-module! $group out output-dir)) + (when (not (get-in project [:lux :android])) + (write-resources! out resources-dirs)) + (doseq [^String file-path deps] + (add-jar! (new File file-path) project !all-jar-files)) + (doseq [[_ [entry-data entry]] @!all-jar-files] + (doto out + (.putNextEntry (doto entry (.setCompressedSize -1))) + (.write entry-data 0 (alength entry-data)) + (.flush) + (.closeEntry))) + nil)) + (when (get-in project [:lux :android]) + (let [output-dex "classes.dex" + _ (do (.delete (new File output-dex)) + (&utils/run-process (str "dx --dex --output=" output-dex " " output-package) + (new File (get-in project [:lux :target] &utils/output-dir)) + "[DX BEGIN]" + "[DX END]")) + manifest-path (get-in project [:lux :android :manifest] default-manifest-file) + sdk-path (get-in project [:lux :android :sdk]) + android-path (str sdk-path "/platforms/android-" (get-in project [:lux :android :version]) "/android.jar") + _ (assert (.exists (new File android-path)) + (str "Can't find Android JAR: " android-path)) + output-apk-unaligned (string/replace output-package #"\.jar$" ".apk.unaligned") + output-apk (string/replace output-package #"\.jar$" ".apk") + current-working-dir (.getCanonicalPath (new File ".")) + _ (do (&utils/run-process (str "aapt package -f -M " manifest-path " -I " android-path " -F " output-apk-unaligned + (apply str " " (interleave (repeat (count resources-dirs) + "-A ") + (filter #(.exists (new File %)) + resources-dirs))) + (apply str " " (interleave (repeat (count resources-dirs) + "-S ") + (->> (get-in project [:lux :android :resources] ["android-resources"]) + (map (partial str current-working-dir "/")) + (filter #(.exists (new File %))))))) + nil + "[AAPT PACKAGE BEGIN]" + "[AAPT PACKAGE END]") + (&utils/run-process (str "aapt add -f " output-apk-unaligned " " output-dex) + (new File (get-in project [:lux :target] &utils/output-dir)) + "[AAPT ADD BEGIN]" + "[AAPT ADD END]") + (when-let [path (get-in project [:lux :android :keystore :path])] + (when-let [alias (get-in project [:lux :android :keystore :alias])] + (when-let [password (get-in project [:lux :android :keystore :password])] + (&utils/run-process (str "jarsigner -storepass " password " -keystore " path " " output-apk-unaligned " " alias) + nil + "[JARSIGNER BEGIN]" + "[JARSIGNER END]")))) + (&utils/run-process (str "zipalign 4 " output-apk-unaligned " " output-apk) + nil + "[ZIPALIGN BEGIN]" + "[ZIPALIGN END]") + ) + ] + nil))))) diff --git a/lux-lein/src/leiningen/lux/repl.clj b/lux-lein/src/leiningen/lux/repl.clj new file mode 100644 index 000000000..271e79db9 --- /dev/null +++ b/lux-lein/src/leiningen/lux/repl.clj @@ -0,0 +1,35 @@ +;; Copyright (c) Eduardo Julian. All rights reserved. +;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +;; If a copy of the MPL was not distributed with this file, +;; You can obtain one at http://mozilla.org/MPL/2.0/. + +(ns leiningen.lux.repl + (:require [leiningen.core.classpath :as classpath] + [leiningen.lux.utils :as &utils]) + (:import (java.io InputStreamReader + BufferedReader + PrintStream))) + +(defn repl [project] + (println (&utils/repl-path project (:source-paths project))) + ;; (let [process (.exec (Runtime/getRuntime) (&utils/repl-path project (:source-paths project)))] + ;; (with-open [std-in (->> System/in (new InputStreamReader) (new BufferedReader)) + ;; process-in (->> process .getOutputStream (new PrintStream)) + ;; process-out (->> process .getInputStream (new InputStreamReader) (new BufferedReader)) + ;; process-err (->> process .getErrorStream (new InputStreamReader) (new BufferedReader))] + ;; (loop [] + ;; (do (loop [] + ;; (when (.ready process-out) + ;; (println (.readLine process-out)) + ;; (recur))) + ;; (loop [had-error? false] + ;; (if (.ready process-out) + ;; (do (println (.readLine process-err)) + ;; (recur true)) + ;; (when had-error? + ;; (System/exit 1)))) + ;; (when-let [input (.readLine std-in)] + ;; (do (.println process-in input) + ;; (recur))))) + ;; )) + ) diff --git a/lux-lein/src/leiningen/lux/test.clj b/lux-lein/src/leiningen/lux/test.clj new file mode 100644 index 000000000..2a7038904 --- /dev/null +++ b/lux-lein/src/leiningen/lux/test.clj @@ -0,0 +1,27 @@ +;; Copyright (c) Eduardo Julian. All rights reserved. +;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +;; If a copy of the MPL was not distributed with this file, +;; You can obtain one at http://mozilla.org/MPL/2.0/. + +(ns leiningen.lux.test + (:refer-clojure :exclude [test]) + (:require [leiningen.core.classpath :as classpath] + (leiningen.lux [utils :as &utils] + [packager :as &packager]))) + +(defn test [project] + (if-let [tests-module (get-in project [:lux :tests])] + (do (&utils/run-process (&utils/compile-path project tests-module (concat (:test-paths project) (:source-paths project))) + nil + "[BUILD BEGIN]" + "[BUILD END]") + (let [java-cmd (get project :java-cmd "java") + jvm-opts (->> (get project :jvm-opts) (interpose " ") (reduce str "")) + output-package (str (get-in project [:lux :target] &utils/output-dir) "/" + (get project :jar-name &utils/output-package))] + (do (&packager/package project tests-module (get project :resource-paths (list))) + (&utils/run-process (str java-cmd " " jvm-opts " -jar " output-package) + nil + "[TEST BEGIN]" + "[TEST END]")))) + (println "Please provide a test module in [:lux :tests]"))) diff --git a/lux-lein/src/leiningen/lux/utils.clj b/lux-lein/src/leiningen/lux/utils.clj new file mode 100644 index 000000000..70d203865 --- /dev/null +++ b/lux-lein/src/leiningen/lux/utils.clj @@ -0,0 +1,96 @@ +;; Copyright (c) Eduardo Julian. All rights reserved. +;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +;; If a copy of the MPL was not distributed with this file, +;; You can obtain one at http://mozilla.org/MPL/2.0/. + +(ns leiningen.lux.utils + (:require [leiningen.core.classpath :as classpath]) + (:import (java.io File + InputStreamReader + BufferedReader))) + +(def ^:const ^String output-dir "target/jvm") +(def ^:const ^String output-package "program.jar") + +(def ^:private unit-separator (str (char 31))) + +(def ^:private vm-options "-server -Xms2048m -Xmx2048m -XX:+OptimizeStringConcat") + +(defn compile-path [project module source-paths] + (let [output-dir (get-in project [:lux :target] output-dir) + jar-paths (->> ^java.net.URLClassLoader (ClassLoader/getSystemClassLoader) + (.getURLs) + (map #(.getFile ^java.net.URL %)) + (filter #(.endsWith ^String % ".jar"))) + compiler-path (some (fn [^:private path] + (if (.contains path "com/github/luxlang/luxc-jvm") + path + nil)) + jar-paths) + stdlib-path (some (fn [^:private path] + (if (.contains path "com/github/luxlang/lux-stdlib") + path + nil)) + jar-paths) + deps-paths (filter (fn [^:private path] + (or (.contains path "org/ow2/asm/asm-all") + (.contains path "org/clojure/core.match") + (.contains path "org/clojure/clojure"))) + jar-paths) + sdk-path (get-in project [:lux :android :sdk]) + android-path (str sdk-path "/platforms/android-" (get-in project [:lux :android :version]) "/android.jar") + deps-paths (if (.exists (new File android-path)) + (cons android-path deps-paths) + deps-paths)] + (let [class-path (->> (classpath/get-classpath project) + (filter #(.endsWith % ".jar")) + (concat deps-paths) + (list* stdlib-path) + (interpose java.io.File/pathSeparator) + (reduce str "")) + java-cmd (get project :java-cmd "java") + jvm-opts (->> (get project :jvm-opts) (interpose " ") (reduce str ""))] + (str java-cmd " " jvm-opts " " vm-options " -cp " (str compiler-path ":" class-path) + " lux release " module + " " (->> (get project :resource-paths (list)) (interpose unit-separator) (apply str)) + " " (->> source-paths (interpose unit-separator) (apply str)) + " " output-dir)))) + +(defn repl-path [project source-paths] + (let [jar-paths (->> ^java.net.URLClassLoader (ClassLoader/getSystemClassLoader) + (.getURLs) + (map #(.getFile ^java.net.URL %)) + (filter #(.endsWith ^String % ".jar"))) + compiler-path (some (fn [^:private path] + (if (.contains path "com/github/luxlang/luxc-jvm") + path + nil)) + jar-paths) + deps-paths (filter (fn [^:private path] + (or (.contains path "org/ow2/asm/asm-all") + (.contains path "org/clojure/core.match") + (.contains path "org/clojure/clojure"))) + jar-paths)] + (let [class-path (->> (classpath/get-classpath project) (filter #(.endsWith % ".jar")) (concat deps-paths) (interpose ":") (reduce str "")) + java-cmd (get project :java-cmd "java") + jvm-opts (->> (get project :jvm-opts) (interpose " ") (reduce str ""))] + (str java-cmd " " jvm-opts " " vm-options " -cp " (str compiler-path ":" class-path) + " lux repl " (->> source-paths (interpose unit-separator) (apply str)))))) + +(defn run-process [command working-directory pre post] + (let [process (.exec (Runtime/getRuntime) command nil working-directory)] + (with-open [std-out (->> process .getInputStream (new InputStreamReader) (new BufferedReader)) + std-err (->> process .getErrorStream (new InputStreamReader) (new BufferedReader))] + (println pre) + (loop [line (.readLine std-out)] + (when line + (println line) + (recur (.readLine std-out)))) + (loop [had-error? false + line (.readLine std-err)] + (if line + (do (println line) + (recur true (.readLine std-err))) + (when had-error? + (System/exit 1)))) + (println post)))) diff --git a/lux-lein/src/leiningen/luxc.clj b/lux-lein/src/leiningen/luxc.clj deleted file mode 100644 index b04e4997a..000000000 --- a/lux-lein/src/leiningen/luxc.clj +++ /dev/null @@ -1,27 +0,0 @@ -;; Copyright (c) Eduardo Julian. All rights reserved. -;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -;; If a copy of the MPL was not distributed with this file, -;; You can obtain one at http://mozilla.org/MPL/2.0/. - -(ns leiningen.luxc - (:require [leiningen.pom :as pom] - [leiningen.core.classpath :as classpath] - (leiningen.luxc [compiler :as &compiler] - [test :as &test] - [repl :as &repl]))) - -;; [Exports] -(defn luxc [project & args] - (case (first args) - "compile" - (&compiler/compile project) - - "test" - (&test/test project) - - "repl" - (&repl/repl project) - - ;; default... - (println "Commands available: compile, test, repl")) - ) diff --git a/lux-lein/src/leiningen/luxc/compiler.clj b/lux-lein/src/leiningen/luxc/compiler.clj deleted file mode 100644 index 18eef63a0..000000000 --- a/lux-lein/src/leiningen/luxc/compiler.clj +++ /dev/null @@ -1,19 +0,0 @@ -;; Copyright (c) Eduardo Julian. All rights reserved. -;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -;; If a copy of the MPL was not distributed with this file, -;; You can obtain one at http://mozilla.org/MPL/2.0/. - -(ns leiningen.luxc.compiler - (:refer-clojure :exclude [compile]) - (:require [leiningen.core.classpath :as classpath] - (leiningen.luxc [utils :as &utils] - [packager :as &packager]))) - -(defn compile [project] - (if-let [program-module (get-in project [:lux :program])] - (do (&utils/run-process (&utils/compile-path project program-module (get project :source-paths (list))) - nil - "[COMPILATION BEGIN]" - "[COMPILATION END]") - (&packager/package project program-module (get project :resource-paths (list)))) - (println "Please provide a program main module in [:lux :program]"))) diff --git a/lux-lein/src/leiningen/luxc/packager.clj b/lux-lein/src/leiningen/luxc/packager.clj deleted file mode 100644 index e7b1d71d8..000000000 --- a/lux-lein/src/leiningen/luxc/packager.clj +++ /dev/null @@ -1,212 +0,0 @@ -;; Copyright (c) Eduardo Julian. All rights reserved. -;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -;; If a copy of the MPL was not distributed with this file, -;; You can obtain one at http://mozilla.org/MPL/2.0/. - -(ns leiningen.luxc.packager - (:require [clojure.string :as string] - [leiningen.core.classpath :as classpath] - [leiningen.uberjar] - [leiningen.luxc.utils :as &utils]) - (:import (java.io InputStream - File - FileInputStream - FileOutputStream - BufferedInputStream - ByteArrayInputStream - ByteArrayOutputStream) - (java.util.jar Manifest - Attributes$Name - JarEntry - JarInputStream - JarOutputStream - ))) - -;; [Utils] -(def ^:private kilobyte 1024) -(def ^:private buffer-size (* 10 kilobyte)) - -(defn ^:private manifest - "(-> Project Text Bool Manifest)" - [project module includes-android?] - (doto (new Manifest) - (-> .getMainAttributes - (doto (-> (.put Attributes$Name/MAIN_CLASS (str module "._")) - (->> (when (not includes-android?)))) - (.put Attributes$Name/MANIFEST_VERSION "1.0") - (.put (new Attributes$Name "LUX_JAR") "true") - (-> (.put (new Attributes$Name name) real-v) - (->> (doseq [[name v] (get project :manifest) - :let [real-v (if (string? v) v (v project))]]))))))) - -(defn ^:private write-class! - "(-> Text File JarOutputStream Null)" - [^String path ^File file ^JarOutputStream out] - (with-open [in (new BufferedInputStream (new FileInputStream file))] - (let [buffer (byte-array buffer-size)] - (doto out - (.putNextEntry (new JarEntry (str path "/" (.getName file)))) - (-> (.write buffer 0 bytes-read) - (->> (when (not= -1 bytes-read)) - (loop [bytes-read (.read in buffer)]))) - (.flush) - (.closeEntry) - )) - )) - -(defn ^:private write-module! - "(-> File JarOutputStream Null)" - [^File file ^JarOutputStream out output-dir] - (let [output-dir-size (inc (.length output-dir)) - module-name (.substring (.getPath file) output-dir-size) - inner-files (.listFiles file) - inner-modules (filter #(.isDirectory ^File %) inner-files) - inner-classes (filter #(not (.isDirectory ^File %)) inner-files)] - (doseq [$class inner-classes] - (write-class! module-name $class out)) - (doseq [$module inner-modules] - (write-module! $module out output-dir)))) - -(defn ^:private write-resources! - "(-> JarOutputStream (List Text) Null)" - [^JarOutputStream out resources-dirs] - (doseq [resources-dir resources-dirs - :let [resources-dir (new File resources-dir)] - :when (.exists resources-dir) - ^File res (.listFiles resources-dir) - :let [buffer (byte-array buffer-size)]] - (with-open [in (->> res (new FileInputStream) (new BufferedInputStream))] - (doto out - (.putNextEntry (new JarEntry (.getName res))) - (-> (.write buffer 0 bytes-read) - (->> (when (not= -1 bytes-read)) - (loop [bytes-read (.read in buffer)]))) - (.flush) - (.closeEntry)) - ))) - -(let [init-capacity (* 100 1024) - buffer-size 1024] - (defn ^:private ^"[B" read-stream [^InputStream is] - (let [buffer (byte-array buffer-size)] - (with-open [os (new ByteArrayOutputStream init-capacity)] - (loop [bytes-read (.read is buffer 0 buffer-size)] - (when (not= -1 bytes-read) - (do (.write os buffer 0 bytes-read) - (recur (.read is buffer 0 buffer-size))))) - (.toByteArray os))))) - -(defn ^:private add-jar! [^File jar-file project !all-jar-files] - (with-open [is (->> jar-file (new FileInputStream) (new JarInputStream))] - (loop [^JarEntry entry (.getNextJarEntry is)] - (when entry - (let [entry-name (.getName entry)] - (if (and (not (.isDirectory entry)) - (not (.startsWith entry-name "META-INF/maven/")) - (not (some (fn [exclusion] - (re-find exclusion entry-name)) - (get project :uberjar-exclusions)))) - (let [entry-data (read-stream is) - entry-data (or (some (fn [[pattern [read fuse write]]] - (let [matches? (if (string? pattern) - (= pattern entry-name) - (re-find pattern entry-name))] - (when matches? - (let [os (new ByteArrayOutputStream 1024) - [_data _entry] (get @!all-jar-files entry-name [(byte-array 0) nil]) - _ (write os (fuse (read (new ByteArrayInputStream _data)) - (read (new ByteArrayInputStream entry-data))))] - (.toByteArray os))))) - (eval (get project :uberjar-merge-with))) - entry-data)] - (swap! !all-jar-files assoc entry-name [entry-data entry]) - (recur (.getNextJarEntry is))) - (recur (.getNextJarEntry is)))) - )))) - -(def default-manifest-file "./AndroidManifest.xml") - -;; [Resources] -(defn package - "(-> Text (List Text) Null)" - [project module resources-dirs] - (let [output-dir (get-in project [:lux :target] &utils/output-dir) - output-package (str (get-in project [:lux :target] &utils/output-dir) "/" - (get project :jar-name &utils/output-package)) - !all-jar-files (atom {}) - includes-android? (boolean (some #(-> % first (= 'com.google.android/android)) - (get project :dependencies))) - project* (-> project - (update-in [:dependencies] (fn [_deps] - ;; Skip the last two, - ;; because they are: - ;; tools.nrepl-0.2.12.jar and - ;; clojure-complete-0.2.4.jar - ;; and they belong to Leiningen. - (take (- (count _deps) 2) _deps)))) - deps (->> project* - (classpath/resolve-managed-dependencies :dependencies :managed-dependencies) - (map #(.getAbsolutePath ^File %)))] - (do (.delete (new File output-package)) - (with-open [out (new JarOutputStream - (->> output-package (new File) (new FileOutputStream)) - (manifest project module includes-android?))] - (do (doseq [$group (.listFiles (new File output-dir))] - (write-module! $group out output-dir)) - (when (not (get-in project [:lux :android])) - (write-resources! out resources-dirs)) - (doseq [^String file-path deps] - (add-jar! (new File file-path) project !all-jar-files)) - (doseq [[_ [entry-data entry]] @!all-jar-files] - (doto out - (.putNextEntry (doto entry (.setCompressedSize -1))) - (.write entry-data 0 (alength entry-data)) - (.flush) - (.closeEntry))) - nil)) - (when (get-in project [:lux :android]) - (let [output-dex "classes.dex" - _ (do (.delete (new File output-dex)) - (&utils/run-process (str "dx --dex --output=" output-dex " " output-package) - (new File (get-in project [:lux :target] &utils/output-dir)) - "[DX BEGIN]" - "[DX END]")) - manifest-path (get-in project [:lux :android :manifest] default-manifest-file) - sdk-path (get-in project [:lux :android :sdk]) - android-path (str sdk-path "/platforms/android-" (get-in project [:lux :android :version]) "/android.jar") - _ (assert (.exists (new File android-path)) - (str "Can't find Android JAR: " android-path)) - output-apk-unaligned (string/replace output-package #"\.jar$" ".apk.unaligned") - output-apk (string/replace output-package #"\.jar$" ".apk") - current-working-dir (.getCanonicalPath (new File ".")) - _ (do (&utils/run-process (str "aapt package -f -M " manifest-path " -I " android-path " -F " output-apk-unaligned - (apply str " " (interleave (repeat (count resources-dirs) - "-A ") - (filter #(.exists (new File %)) - resources-dirs))) - (apply str " " (interleave (repeat (count resources-dirs) - "-S ") - (->> (get-in project [:lux :android :resources] ["android-resources"]) - (map (partial str current-working-dir "/")) - (filter #(.exists (new File %))))))) - nil - "[AAPT PACKAGE BEGIN]" - "[AAPT PACKAGE END]") - (&utils/run-process (str "aapt add -f " output-apk-unaligned " " output-dex) - (new File (get-in project [:lux :target] &utils/output-dir)) - "[AAPT ADD BEGIN]" - "[AAPT ADD END]") - (when-let [path (get-in project [:lux :android :keystore :path])] - (when-let [alias (get-in project [:lux :android :keystore :alias])] - (when-let [password (get-in project [:lux :android :keystore :password])] - (&utils/run-process (str "jarsigner -storepass " password " -keystore " path " " output-apk-unaligned " " alias) - nil - "[JARSIGNER BEGIN]" - "[JARSIGNER END]")))) - (&utils/run-process (str "zipalign 4 " output-apk-unaligned " " output-apk) - nil - "[ZIPALIGN BEGIN]" - "[ZIPALIGN END]") - ) - ] - nil))))) diff --git a/lux-lein/src/leiningen/luxc/repl.clj b/lux-lein/src/leiningen/luxc/repl.clj deleted file mode 100644 index 2bfb281e6..000000000 --- a/lux-lein/src/leiningen/luxc/repl.clj +++ /dev/null @@ -1,35 +0,0 @@ -;; Copyright (c) Eduardo Julian. All rights reserved. -;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -;; If a copy of the MPL was not distributed with this file, -;; You can obtain one at http://mozilla.org/MPL/2.0/. - -(ns leiningen.luxc.repl - (:require [leiningen.core.classpath :as classpath] - [leiningen.luxc.utils :as &utils]) - (:import (java.io InputStreamReader - BufferedReader - PrintStream))) - -(defn repl [project] - (println (&utils/repl-path project (:source-paths project))) - ;; (let [process (.exec (Runtime/getRuntime) (&utils/repl-path project (:source-paths project)))] - ;; (with-open [std-in (->> System/in (new InputStreamReader) (new BufferedReader)) - ;; process-in (->> process .getOutputStream (new PrintStream)) - ;; process-out (->> process .getInputStream (new InputStreamReader) (new BufferedReader)) - ;; process-err (->> process .getErrorStream (new InputStreamReader) (new BufferedReader))] - ;; (loop [] - ;; (do (loop [] - ;; (when (.ready process-out) - ;; (println (.readLine process-out)) - ;; (recur))) - ;; (loop [had-error? false] - ;; (if (.ready process-out) - ;; (do (println (.readLine process-err)) - ;; (recur true)) - ;; (when had-error? - ;; (System/exit 1)))) - ;; (when-let [input (.readLine std-in)] - ;; (do (.println process-in input) - ;; (recur))))) - ;; )) - ) diff --git a/lux-lein/src/leiningen/luxc/test.clj b/lux-lein/src/leiningen/luxc/test.clj deleted file mode 100644 index a1b5a830c..000000000 --- a/lux-lein/src/leiningen/luxc/test.clj +++ /dev/null @@ -1,27 +0,0 @@ -;; Copyright (c) Eduardo Julian. All rights reserved. -;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -;; If a copy of the MPL was not distributed with this file, -;; You can obtain one at http://mozilla.org/MPL/2.0/. - -(ns leiningen.luxc.test - (:refer-clojure :exclude [test]) - (:require [leiningen.core.classpath :as classpath] - (leiningen.luxc [utils :as &utils] - [packager :as &packager]))) - -(defn test [project] - (if-let [tests-module (get-in project [:lux :tests])] - (do (&utils/run-process (&utils/compile-path project tests-module (concat (:test-paths project) (:source-paths project))) - nil - "[COMPILATION BEGIN]" - "[COMPILATION END]") - (let [java-cmd (get project :java-cmd "java") - jvm-opts (->> (get project :jvm-opts) (interpose " ") (reduce str "")) - output-package (str (get-in project [:lux :target] &utils/output-dir) "/" - (get project :jar-name &utils/output-package))] - (do (&packager/package project tests-module (get project :resource-paths (list))) - (&utils/run-process (str java-cmd " " jvm-opts " -jar " output-package) - nil - "[TEST BEGIN]" - "[TEST END]")))) - (println "Please provide a test module in [:lux :tests]"))) diff --git a/lux-lein/src/leiningen/luxc/utils.clj b/lux-lein/src/leiningen/luxc/utils.clj deleted file mode 100644 index bae02d365..000000000 --- a/lux-lein/src/leiningen/luxc/utils.clj +++ /dev/null @@ -1,97 +0,0 @@ -;; Copyright (c) Eduardo Julian. All rights reserved. -;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -;; If a copy of the MPL was not distributed with this file, -;; You can obtain one at http://mozilla.org/MPL/2.0/. - -(ns leiningen.luxc.utils - (:refer-clojure :exclude [compile]) - (:require [leiningen.core.classpath :as classpath]) - (:import (java.io File - InputStreamReader - BufferedReader))) - -(def ^:const ^String output-dir "target/jvm") -(def ^:const ^String output-package "program.jar") - -(def ^:private unit-separator (str (char 31))) - -(def ^:private vm-options "-server -Xms2048m -Xmx2048m -XX:+OptimizeStringConcat") - -(defn compile-path [project module source-paths] - (let [output-dir (get-in project [:lux :target] output-dir) - jar-paths (->> ^java.net.URLClassLoader (ClassLoader/getSystemClassLoader) - (.getURLs) - (map #(.getFile ^java.net.URL %)) - (filter #(.endsWith ^String % ".jar"))) - compiler-path (some (fn [^:private path] - (if (.contains path "com/github/luxlang/luxc-jvm") - path - nil)) - jar-paths) - stdlib-path (some (fn [^:private path] - (if (.contains path "com/github/luxlang/lux-stdlib") - path - nil)) - jar-paths) - deps-paths (filter (fn [^:private path] - (or (.contains path "org/ow2/asm/asm-all") - (.contains path "org/clojure/core.match") - (.contains path "org/clojure/clojure"))) - jar-paths) - sdk-path (get-in project [:lux :android :sdk]) - android-path (str sdk-path "/platforms/android-" (get-in project [:lux :android :version]) "/android.jar") - deps-paths (if (.exists (new File android-path)) - (cons android-path deps-paths) - deps-paths)] - (let [class-path (->> (classpath/get-classpath project) - (filter #(.endsWith % ".jar")) - (concat deps-paths) - (list* stdlib-path) - (interpose java.io.File/pathSeparator) - (reduce str "")) - java-cmd (get project :java-cmd "java") - jvm-opts (->> (get project :jvm-opts) (interpose " ") (reduce str ""))] - (str java-cmd " " jvm-opts " " vm-options " -cp " (str compiler-path ":" class-path) - " lux release " module - " " (->> (get project :resource-paths (list)) (interpose unit-separator) (apply str)) - " " (->> source-paths (interpose unit-separator) (apply str)) - " " output-dir)))) - -(defn repl-path [project source-paths] - (let [jar-paths (->> ^java.net.URLClassLoader (ClassLoader/getSystemClassLoader) - (.getURLs) - (map #(.getFile ^java.net.URL %)) - (filter #(.endsWith ^String % ".jar"))) - compiler-path (some (fn [^:private path] - (if (.contains path "com/github/luxlang/luxc-jvm") - path - nil)) - jar-paths) - deps-paths (filter (fn [^:private path] - (or (.contains path "org/ow2/asm/asm-all") - (.contains path "org/clojure/core.match") - (.contains path "org/clojure/clojure"))) - jar-paths)] - (let [class-path (->> (classpath/get-classpath project) (filter #(.endsWith % ".jar")) (concat deps-paths) (interpose ":") (reduce str "")) - java-cmd (get project :java-cmd "java") - jvm-opts (->> (get project :jvm-opts) (interpose " ") (reduce str ""))] - (str java-cmd " " jvm-opts " " vm-options " -cp " (str compiler-path ":" class-path) - " lux repl " (->> source-paths (interpose unit-separator) (apply str)))))) - -(defn run-process [command working-directory pre post] - (let [process (.exec (Runtime/getRuntime) command nil working-directory)] - (with-open [std-out (->> process .getInputStream (new InputStreamReader) (new BufferedReader)) - std-err (->> process .getErrorStream (new InputStreamReader) (new BufferedReader))] - (println pre) - (loop [line (.readLine std-out)] - (when line - (println line) - (recur (.readLine std-out)))) - (loop [had-error? false - line (.readLine std-err)] - (if line - (do (println line) - (recur true (.readLine std-err))) - (when had-error? - (System/exit 1)))) - (println post)))) -- cgit v1.2.3