|
14 | 14 |
|
15 | 15 | Use the 'build' function for end-to-end compilation.
|
16 | 16 |
|
17 |
| - build = compile -> add-dependencies -> optimize -> output |
| 17 | + build = find-sources -> add-dependencies -> compile -> optimize -> output |
18 | 18 |
|
19 | 19 | Two protocols are defined: IJavaScript and Compilable. The
|
20 | 20 | Compilable protocol is satisfied by something which can return one
|
|
389 | 389 | (-paths [this] [this]))
|
390 | 390 |
|
391 | 391 | (defprotocol Compilable
|
392 |
| - (-compile [this opts] "Returns one or more IJavaScripts.")) |
| 392 | + (-compile [this opts] "Returns one or more IJavaScripts.") |
| 393 | + (-find-sources [this opts] "Returns one or more IJavascripts, without compiling them.")) |
393 | 394 |
|
394 | 395 | (defn compile-form-seq
|
395 | 396 | "Compile a sequence of forms to a JavaScript source string."
|
|
477 | 478 | (let [file-on-disk (jar-file-to-disk this (util/output-directory opts))]
|
478 | 479 | (-compile file-on-disk opts))))
|
479 | 480 |
|
| 481 | +(defn find-jar-sources |
| 482 | + [this opts] |
| 483 | + [(comp/find-source (jar-file-to-disk this (util/output-directory opts)))]) |
| 484 | + |
480 | 485 | (extend-protocol Compilable
|
481 | 486 |
|
482 | 487 | File
|
483 | 488 | (-compile [this opts]
|
484 | 489 | (if (.isDirectory this)
|
485 | 490 | (compile-dir this opts)
|
486 | 491 | (compile-file this opts)))
|
| 492 | + (-find-sources [this _] |
| 493 | + (if (.isDirectory this) |
| 494 | + (comp/find-root-sources this) |
| 495 | + [(comp/find-source this)])) |
487 | 496 |
|
488 | 497 | URL
|
489 | 498 | (-compile [this opts]
|
490 | 499 | (case (.getProtocol this)
|
491 | 500 | "file" (-compile (io/file this) opts)
|
492 | 501 | "jar" (compile-from-jar this opts)))
|
| 502 | + (-find-sources [this opts] |
| 503 | + (case (.getProtocol this) |
| 504 | + "file" (-find-sources (io/file this) opts) |
| 505 | + "jar" (find-jar-sources this opts))) |
493 | 506 |
|
494 | 507 | clojure.lang.PersistentList
|
495 | 508 | (-compile [this opts]
|
496 | 509 | (compile-form-seq [this]))
|
| 510 | + ; FIXME: -find-sources |
497 | 511 |
|
498 | 512 | String
|
499 | 513 | (-compile [this opts] (-compile (io/file this) opts))
|
| 514 | + (-find-sources [this opts] (-find-sources (io/file this) opts)) |
500 | 515 |
|
501 | 516 | clojure.lang.PersistentVector
|
502 | 517 | (-compile [this opts] (compile-form-seq this))
|
| 518 | + ; FIXME: -find-sources |
503 | 519 | )
|
504 | 520 |
|
505 | 521 | (comment
|
506 | 522 | ;; compile a file in memory
|
507 | 523 | (-compile "samples/hello/src/hello/core.cljs" {})
|
| 524 | + (-find-sources "samples/hello/src/hello/core.cljs" {}) |
508 | 525 | ;; compile a file to disk - see file @ 'out/clojure/set.js'
|
509 | 526 | (-compile (io/resource "clojure/set.cljs") {:output-file "clojure/set.js"})
|
| 527 | + (-find-sources (io/resource "clojure/set.cljs") {:output-file "clojure/set.js"}) |
510 | 528 | ;; compile a project
|
511 | 529 | (-compile (io/file "samples/hello/src") {})
|
| 530 | + (-find-sources (io/file "samples/hello/src") {}) |
512 | 531 | ;; compile a project with a custom output directory
|
513 | 532 | (-compile (io/file "samples/hello/src") {:output-dir "my-output"})
|
| 533 | + (-find-sources (io/file "samples/hello/src") {:output-dir "my-output"}) |
514 | 534 | ;; compile a form
|
515 | 535 | (-compile '(defn plus-one [x] (inc x)) {})
|
516 | 536 | ;; compile a vector of forms
|
|
639 | 659 | (cljs-dependencies {} ["cljs.core" "clojure.string"])
|
640 | 660 | )
|
641 | 661 |
|
| 662 | +(defn find-cljs-dependencies |
| 663 | + "Given set of cljs namespace symbols, find IJavaScript objects for the namespaces." |
| 664 | + [requires] |
| 665 | + (letfn [(cljs-deps [namespaces] |
| 666 | + (->> namespaces |
| 667 | + (remove #(or ((@env/*compiler* :js-dependency-index) %) |
| 668 | + (deps/find-classpath-lib %))) |
| 669 | + (map cljs-source-for-namespace) |
| 670 | + (remove (comp nil? :uri))))] |
| 671 | + (loop [required-files (cljs-deps requires) |
| 672 | + visited (set required-files) |
| 673 | + cljs-namespaces #{}] |
| 674 | + (if (seq required-files) |
| 675 | + (let [next-file (first required-files) |
| 676 | + ns-info (ana/parse-ns (:uri next-file)) |
| 677 | + new-req (remove #(contains? visited %) (cljs-deps (cond-> (deps/-requires ns-info) |
| 678 | + (= 'cljs.js (:ns ns-info)) (conj "cljs.core$macros"))))] |
| 679 | + (recur (into (rest required-files) new-req) |
| 680 | + (into visited new-req) |
| 681 | + (conj cljs-namespaces ns-info))) |
| 682 | + (disj cljs-namespaces nil))))) |
| 683 | + |
642 | 684 | (defn add-dependencies
|
643 | 685 | "Given one or more IJavaScript objects in dependency order, produce
|
644 | 686 | a new sequence of IJavaScript objects which includes the input list
|
|
670 | 712 | required-cljs
|
671 | 713 | inputs)))))
|
672 | 714 |
|
| 715 | +(comment |
| 716 | + (alter-var-root #'env/*compiler* (constantly (env/default-compiler-env))) |
| 717 | + ;; only get cljs deps |
| 718 | + (find-cljs-dependencies ["goog.string" "cljs.core"]) |
| 719 | + ;; get transitive deps |
| 720 | + (find-cljs-dependencies ["clojure.string"]) |
| 721 | + ;; don't get cljs.core twice |
| 722 | + (find-cljs-dependencies ["cljs.core" "clojure.string"]) |
| 723 | + ) |
| 724 | + |
| 725 | +(defn add-dependency-sources |
| 726 | + "Given list of IJavaScript objects, produce a new sequence of IJavaScript objects |
| 727 | + of all dependencies of inputs." |
| 728 | + [inputs] |
| 729 | + (let [inputs (set inputs) |
| 730 | + requires (set (mapcat deps/-requires inputs))] |
| 731 | + (into inputs (find-cljs-dependencies requires)))) |
| 732 | + |
| 733 | +(defn check-unprovided |
| 734 | + [inputs] |
| 735 | + (let [requires (set (mapcat deps/-requires inputs)) |
| 736 | + provided (set (mapcat deps/-provides inputs)) |
| 737 | + unprovided (clojure.set/difference requires provided #{"constants-table"})] |
| 738 | + (when (seq unprovided) |
| 739 | + (ana/warning :unprovided @env/*compiler* {:unprovided (sort unprovided)})) |
| 740 | + inputs)) |
| 741 | + |
| 742 | +(defn compile-sources |
| 743 | + "Takes dependency ordered list of IJavaScript compatible maps from parse-ns |
| 744 | + and compiles them." |
| 745 | + [inputs compiler-stats opts] |
| 746 | + (util/measure compiler-stats |
| 747 | + "Compile sources" |
| 748 | + (binding [comp/*inputs* (zipmap (map :ns inputs) inputs)] |
| 749 | + (doall |
| 750 | + (for [ns-info inputs] |
| 751 | + ; TODO: compile-file calls parse-ns unnecessarily to get ns-info |
| 752 | + ; TODO: we could mark dependent namespaces for recompile here |
| 753 | + (-compile (:source-file ns-info) |
| 754 | + ; - ns-info -> ns -> cljs file relpath -> js relpath |
| 755 | + (merge opts {:output-file (comp/rename-to-js (util/ns->relpath (:ns ns-info)))}))))))) |
| 756 | + |
| 757 | +(defn add-goog-base |
| 758 | + [inputs] |
| 759 | + (cons (javascript-file nil (io/resource "goog/base.js") ["goog"] nil) |
| 760 | + inputs)) |
| 761 | + |
| 762 | +(defn add-js-sources |
| 763 | + "Given list of IJavaScript objects, add foreign-deps and constants-table |
| 764 | + IJavaScript objects to the list." |
| 765 | + [inputs opts] |
| 766 | + (let [requires (set (mapcat deps/-requires inputs)) |
| 767 | + required-js (js-dependencies opts requires)] |
| 768 | + (concat |
| 769 | + (map |
| 770 | + (fn [{:keys [foreign url file provides requires] :as js-map}] |
| 771 | + (let [url (or url (io/resource file))] |
| 772 | + (merge |
| 773 | + (javascript-file foreign url provides requires) |
| 774 | + js-map))) |
| 775 | + required-js) |
| 776 | + [(when (-> @env/*compiler* :options :emit-constants) |
| 777 | + (let [url (deps/to-url (str (util/output-directory opts) "/constants_table.js"))] |
| 778 | + (javascript-file nil url url ["constants-table"] ["cljs.core"] nil nil)))] |
| 779 | + inputs))) |
| 780 | + |
| 781 | +(comment |
| 782 | + (comp/find-sources-root "samples/hello/src") |
| 783 | + (find-dependency-sources (find-sources-root "samples/hello/src")) |
| 784 | + (find-sources "samples/hello/src")) |
| 785 | + |
673 | 786 | (defn preamble-from-paths [paths]
|
674 | 787 | (when-let [missing (seq (remove io/resource paths))]
|
675 | 788 | (ana/warning :preamble-missing @env/*compiler* {:missing (sort missing)}))
|
|
1653 | 1766 | #(-> %
|
1654 | 1767 | (update-in [:options] merge all-opts)
|
1655 | 1768 | (assoc :target (:target opts))
|
1656 |
| - (assoc :js-dependency-index (deps/js-dependency-index all-opts)))) |
| 1769 | + (assoc :js-dependency-index (deps/js-dependency-index all-opts)) |
| 1770 | + ;; Save list of sources for cljs.analyzer/locate-src - Juho Teperi |
| 1771 | + (assoc :sources (-find-sources source all-opts)))) |
1657 | 1772 | (binding [comp/*dependents* (when-not (false? (:recompile-dependents opts))
|
1658 | 1773 | (atom {:recompile #{} :visited #{}}))
|
1659 | 1774 | ana/*cljs-static-fns*
|
|
1683 | 1798 | compile-opts (if one-file?
|
1684 | 1799 | (assoc all-opts :output-file (:output-to all-opts))
|
1685 | 1800 | all-opts)
|
1686 |
| - compiled (util/measure compiler-stats |
1687 |
| - "Compile basic sources" |
1688 |
| - (doall (-compile source compile-opts))) |
1689 |
| - js-sources (util/measure compiler-stats |
1690 |
| - "Add dependencies" |
1691 |
| - (doall |
1692 |
| - (concat |
1693 |
| - (apply add-dependencies all-opts |
1694 |
| - (concat |
1695 |
| - (if (sequential? compiled) compiled [compiled]) |
1696 |
| - (when (= :nodejs (:target all-opts)) |
1697 |
| - [(-compile (io/resource "cljs/nodejs.cljs") all-opts)]))) |
1698 |
| - (when (= :nodejs (:target all-opts)) |
1699 |
| - [(-compile (io/resource "cljs/nodejscli.cljs") all-opts)])))) |
| 1801 | + js-sources (-> (-find-sources source all-opts) |
| 1802 | + add-dependency-sources |
| 1803 | + deps/dependency-order |
| 1804 | + (compile-sources compiler-stats compile-opts) |
| 1805 | + (add-js-sources all-opts) |
| 1806 | + (cond-> (= :nodejs (:target all-opts)) (concat [(-compile (io/resource "cljs/nodejs.cljs") all-opts)])) |
| 1807 | + deps/dependency-order |
| 1808 | + add-goog-base |
| 1809 | + (cond-> (= :nodejs (:target all-opts)) (concat [(-compile (io/resource "cljs/nodejscli.cljs") all-opts)]))) |
1700 | 1810 | _ (when (:emit-constants all-opts)
|
1701 | 1811 | (comp/emit-constants-table-to-file
|
1702 | 1812 | (::ana/constant-table @env/*compiler*)
|
|
0 commit comments