<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Volodymyr Kozieiev</title>
    <description>The latest articles on DEV Community by Volodymyr Kozieiev (@kozieiev).</description>
    <link>https://dev.to/kozieiev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F741697%2F4cb7cb30-3ac0-4dcb-ae4d-ca45bc564cb5.png</url>
      <title>DEV Community: Volodymyr Kozieiev</title>
      <link>https://dev.to/kozieiev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kozieiev"/>
    <language>en</language>
    <item>
      <title>Full Clojure project in 5 seconds!</title>
      <dc:creator>Volodymyr Kozieiev</dc:creator>
      <pubDate>Tue, 18 Oct 2022 14:44:12 +0000</pubDate>
      <link>https://dev.to/kozieiev/full-clojure-project-in-5-seconds-5b32</link>
      <guid>https://dev.to/kozieiev/full-clojure-project-in-5-seconds-5b32</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/2K7cQ8UYRzo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Every time you start a new Clojure project, there is a lot of boilerplate that needs to be added: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;deps.edn&lt;/code&gt; with aliases to run tests and build actions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;build.clj&lt;/code&gt; with build actions&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.gitignore&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;you name it…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Creating all these can be easily automated with &lt;a href="https://github.com/seancorfield/deps-new"&gt;deps-new&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install &lt;code&gt;deps-new&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;deps-new&lt;/code&gt; intended to be installed as a "tool" for Clojure CLI.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Tools" in Clojure CLI
&lt;/h3&gt;

&lt;p&gt;Tools are 3rd party libraries that can be installed and than invoked from Clojure CLI using &lt;code&gt;clj -T&lt;/code&gt; option. They use their own classpath and do not interfere with the project's &lt;code&gt;deps.edn&lt;/code&gt; if you run tool commands from the project directory. &lt;/p&gt;

&lt;p&gt;Few commands you may need:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clj -Ttools list&lt;/code&gt; - to view already installed tools&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clj -Ttools remove :tool tool-name&lt;/code&gt; - to remove the tool&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clj -Ttools install tool-path tool-version :as tool-name&lt;/code&gt; - to install a new tool&lt;/p&gt;

&lt;p&gt;More info about tools you can find in &lt;a href="https://www.youtube.com/watch?v=8aCO_wNuScQ&amp;amp;t=506s"&gt;this video&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing &lt;code&gt;deps-new&lt;/code&gt; tool
&lt;/h3&gt;

&lt;p&gt;Here is a command to add &lt;code&gt;deps-new&lt;/code&gt; to your system&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clojure &lt;span class="nt"&gt;-Ttools&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;io.github.seancorfield/deps-new &lt;span class="s1"&gt;'{:git/tag "v0.4.13"}'&lt;/span&gt; :as new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;:as new&lt;/code&gt; part of the command means that "new" is now a name for &lt;code&gt;deps-new&lt;/code&gt; tool on your system. You can use any name you want.&lt;/p&gt;

&lt;p&gt;Let's check our list of tools now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-Ttools&lt;/span&gt; list
TOOL   LIB                              TYPE  VERSION
new    io.github.seancorfield/deps-new  :git  v0.4.13
tools  io.github.clojure/tools.tools    :git  v0.2.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To check what functions &lt;code&gt;new&lt;/code&gt; tool exposes you can run the command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clojure -A:deps -Tnew help/doc&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a library
&lt;/h2&gt;

&lt;p&gt;Now, when &lt;code&gt;deps-new&lt;/code&gt; is installed, we can use it to create a new library.&lt;/p&gt;

&lt;p&gt;The following command will create a library with root namespace &lt;code&gt;vkjr&lt;/code&gt; and one source file &lt;code&gt;mycoollib.clj&lt;/code&gt; in it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clojure &lt;span class="nt"&gt;-Tnew&lt;/span&gt; lib :name vkjr/mycoollib
  Creating project from org.corfield.new/lib &lt;span class="k"&gt;in &lt;/span&gt;mycoollib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is a content of new library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mycoollib
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build.clj
├── deps.edn
├── doc
│   └── intro.md
├── pom.xml
├── resources
│   └── .keep
├── src
│   └── vkjr
│       └── mycoollib.clj
└── &lt;span class="nb"&gt;test&lt;/span&gt;
    └── vkjr
        └── mycoollib_test.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Top level directory of the library was also named &lt;code&gt;mycoollib&lt;/code&gt; but you can override this behavior by providing additional key/value pair to the library creation command &lt;code&gt;:target-dir some-folder-name&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Content of created library
&lt;/h3&gt;

&lt;p&gt;As you can see, there are plenty of automatically generated files in our new lib.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;deps.edn&lt;/code&gt; from the start contains aliases for testing and build actions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org.clojure/clojure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.11.1"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:test&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:extra-paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:extra-deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org.clojure/test.check&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.1.1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;io.github.cognitect-labs/test-runner&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"v0.5.1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"dfb30dd"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="no"&gt;:build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io.github.seancorfield/build-clj&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"v0.8.2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0ffdb4c"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;:ns-default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;src/vkjr/mycoollib.clj&lt;/code&gt; contains a dummy function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vkjr.mycoollib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s"&gt;"I don't do a whole lot."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;prn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in &lt;code&gt;test/vkjr/mycoollib_test.clj&lt;/code&gt; already exists one failing test&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vkjr.mycoollib-test&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:refer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:all&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vkjr.mycoollib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:refer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:all&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;deftest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-test&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;testing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"FIXME, I fail."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;build.clj&lt;/code&gt; contains build actions &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;ci&lt;/code&gt;, &lt;code&gt;install&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:refer-clojure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:exclude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.tools.build.api&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; for b/git-count-revs&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;org.corfield.build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'net.clojars.vkjr/mycoollib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.1.0-SNAPSHOT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; alternatively, use MAJOR.MINOR.COMMITS:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.0.%s"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/git-count-revs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Run the tests."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bb/run-tests&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ci&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Run the CI pipeline of tests (and build the JAR)."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bb/run-tests&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bb/clean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bb/jar&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Install the JAR locally."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bb/install&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Deploy the JAR to Clojars."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bb/deploy&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note, that &lt;code&gt;build.clj&lt;/code&gt; implements actions using the &lt;a href="https://github.com/seancorfield/build-clj"&gt;build-clj&lt;/a&gt; library instead of standard Clojure's &lt;code&gt;tools.build&lt;/code&gt;. That library hides some unnecessary details and provides the functionality of deploying to Clojars, which is missed in &lt;code&gt;tools.build&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There are a bunch of other useful files also: &lt;code&gt;.gitignore&lt;/code&gt;, &lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;pom.xml&lt;/code&gt;, &lt;code&gt;LICENSE&lt;/code&gt;.. real time-saver, ha?&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an application
&lt;/h2&gt;

&lt;p&gt;Creating an application with &lt;code&gt;deps-new&lt;/code&gt; as simple as a library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clojure &lt;span class="nt"&gt;-Tnew&lt;/span&gt; app :name vkjr/mycoolapp
Creating project from org.corfield.new/app &lt;span class="k"&gt;in &lt;/span&gt;mycoolapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is a folder structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mycoolapp
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build.clj
├── deps.edn
├── doc
│   └── intro.md
├── pom.xml
├── resources
│   └── .keep
├── src
│   └── vkjr
│       └── mycoolapp.clj
└── &lt;span class="nb"&gt;test&lt;/span&gt;
    └── vkjr
        └── mycoolapp_test.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Main differences from the library project:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/vkjr/mycoolapp.clj&lt;/code&gt; contains the &lt;code&gt;(-main)&lt;/code&gt; and &lt;code&gt;(greet)&lt;/code&gt; functions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vkjr.mycoolapp&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:gen-class&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s"&gt;"Callable entry point to the application."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Hello, "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"!"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s"&gt;"I don't do a whole lot ... yet."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;deps.edn&lt;/code&gt; has additional aliases &lt;code&gt;run-m&lt;/code&gt; and &lt;code&gt;run-x&lt;/code&gt; to run (main) and (greet) functions respectively&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="n"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:run-m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:main-opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-m"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"vkjr.mycoolapp"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:run-x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:ns-default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vkjr.mycoolapp&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="no"&gt;:exec-fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="no"&gt;:exec-args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Clojure"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;build.clj&lt;/code&gt; creates an uberjar instead of a jar and doesn't have (install) and (deploy) functions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="n"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ci&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Run the CI pipeline of tests (and build the uberjar)."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bb/run-tests&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bb/clean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bb/uber&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create a minimal "scratch" project
&lt;/h2&gt;

&lt;p&gt;For the cases when you don't need a full-blown application, but merely a playground, &lt;code&gt;deps-new&lt;/code&gt; supports creating a "scratch" projects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clojure &lt;span class="nt"&gt;-Tnew&lt;/span&gt; scratch :name playground                                            
Creating project from org.corfield.new/scratch &lt;span class="k"&gt;in &lt;/span&gt;playground 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Folder structure for such "scratch":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;playground
├── deps.edn
└── src
    └── scratch.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With almost empty &lt;code&gt;deps.edn&lt;/code&gt; and &lt;code&gt;scratch.clj&lt;/code&gt; with (-main) and (greet) functions, like in the application example&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;deps-new&lt;/code&gt; you can create your own project template, but this is another story… ;)&lt;/p&gt;

&lt;p&gt;originally posted at &lt;a href="https://kozieiev.com/blog/full-clojure-project-in-5-seconds/"&gt;kozieiev.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>application</category>
      <category>template</category>
    </item>
    <item>
      <title>Is Clojure the only language you need?</title>
      <dc:creator>Volodymyr Kozieiev</dc:creator>
      <pubDate>Wed, 12 Oct 2022 19:01:17 +0000</pubDate>
      <link>https://dev.to/kozieiev/is-clojure-the-only-language-you-need-olj</link>
      <guid>https://dev.to/kozieiev/is-clojure-the-only-language-you-need-olj</guid>
      <description>&lt;h2&gt;
  
  
  Video version
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/oguZnsrUQBo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The question
&lt;/h2&gt;

&lt;p&gt;Clojure is a &lt;strong&gt;hosted&lt;/strong&gt; programming language. This means what you wrote in Clojure will run in an environment of another language.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9lxgogubfblysqy49zg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9lxgogubfblysqy49zg.png" alt="Clojure implementations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most popular implementation of Clojure turns Clojure code into Java bytecode that runs on Java Virtual Machine.&lt;/p&gt;

&lt;p&gt;Another popular implementation is ClojureScript. And its compiler turns your Clojure code into JavaScript.&lt;/p&gt;

&lt;p&gt;And there are a lot of &lt;a href="https://en.wikipedia.org/wiki/Clojure#Other_Implementations" rel="noopener noreferrer"&gt;other implementations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you can run Clojure where Java or JavaScript runs, can you learn Clojure and conveniently use it in &lt;strong&gt;ALL&lt;/strong&gt; areas of software development?&lt;/p&gt;

&lt;p&gt;Well, no. There is no silver bullet. &lt;/p&gt;

&lt;p&gt;But can Clojure be the only language YOU need? Yes, if you write software in areas where Clojure proved to be good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;Here Clojure fits perfectly. Running on JVM, with its immutable data structures and built-in concurrency support, Clojure is very good at dealing with simultaneous connections and processing big amounts of data.&lt;/p&gt;

&lt;p&gt;One of the main examples of a production Clojure backend is a &lt;a href="https://nubank.com.br/" rel="noopener noreferrer"&gt;Nubank&lt;/a&gt;. It is a Latin American digital bank that used Clojure so heavily, that in 2020 they decided to &lt;a href="https://building.nubank.com.br/nubank-acquires-cognitect-press-release/" rel="noopener noreferrer"&gt;acquire&lt;/a&gt; the Cognitect company that develops Clojure.&lt;/p&gt;

&lt;p&gt;On job boards, you can find backend Clojure roles in advertising or sports data processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  FrontEnd
&lt;/h2&gt;

&lt;p&gt;FrontEnd is also an area where Clojure fits, particularly &lt;a href="https://clojurescript.org/" rel="noopener noreferrer"&gt;ClojureScript&lt;/a&gt;. If you don’t know the difference - &lt;a href="https://youtu.be/ABQk9iMUypY" rel="noopener noreferrer"&gt;watch this video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The most popular approach for building frontend with ClojureScript is using &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;. You can use it via a wrapper library called &lt;a href="https://github.com/reagent-project/reagent" rel="noopener noreferrer"&gt;Reagent&lt;/a&gt; and describe UI components as pure functions returning Clojure data structures.&lt;/p&gt;

&lt;p&gt;One of the biggest Ukrainian internet-shops &lt;a href="https://kasta.ua/" rel="noopener noreferrer"&gt;Kasta&lt;/a&gt; uses ClojureScript with React.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gwtudbnk23m1n8nydto.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gwtudbnk23m1n8nydto.png" alt="Kasta frontend"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mobile
&lt;/h2&gt;

&lt;p&gt;Mobile development is also possible with Clojure. The stack you can use here is ClojureScript + &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;ReactNative&lt;/a&gt;. Though it is not as popular as frontend or backend.&lt;/p&gt;

&lt;p&gt;I did a quick search on job boards and didn’t find Clojure mobile positions published now.&lt;/p&gt;

&lt;p&gt;But they exist. For example &lt;a href="https://status.im/" rel="noopener noreferrer"&gt;Status&lt;/a&gt; company where I met Clojure for the first time and worked for a few years has a mature blockchain-based mobile messenger written in ClojureScript with ReactNative.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0gsn3cghhu0xbvonfi6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0gsn3cghhu0xbvonfi6.png" alt="Status app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Scripting
&lt;/h3&gt;

&lt;p&gt;Another area where you can use Clojure is scripting. Whatever you write in Bash, you can write in  Clojure and without switching your brain context to another syntax.&lt;/p&gt;

&lt;p&gt;But If you will write the scripts with JVM Clojure there will be an issue - long startup time.&lt;/p&gt;

&lt;p&gt;Instead, you can use a tool called &lt;a href="https://github.com/babashka/babashka" rel="noopener noreferrer"&gt;Babashka&lt;/a&gt;. It is a &lt;strong&gt;native&lt;/strong&gt; Clojure interpreter that implements a sufficient subset of Clojure and goes with a bunch of prepacked libs to work with the filesystem, command line arguments, json. All these packed in a standalone binary, that you can deploy anywhere and run Clojure without JVM.&lt;/p&gt;

&lt;p&gt;On my local machine, I use babashka script that generates folder structure for the new blogpost and new video project when I start preparing them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Desktop
&lt;/h2&gt;

&lt;p&gt;With desktop development, the situation is more complicated than with all mentioned before. There are different approaches to creating interfaces.&lt;/p&gt;

&lt;p&gt;If you decide to use JVM Clojure, you can use one of Java UI kits. Either directly, or via more idiomatic wrapper libraries.&lt;/p&gt;

&lt;p&gt;You can use Clojure + JavaFX like the guys from &lt;a href="https://defold.com/" rel="noopener noreferrer"&gt;Defold&lt;/a&gt;. They wrote an editor for their game engine this way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ho3yykim55dxcsv6lsb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ho3yykim55dxcsv6lsb.jpeg" alt="Defold game editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or you can use Clojure + Swing, like in &lt;a href="https://github.com/Deep-Symmetry/beat-link-trigger#beat-link-trigger" rel="noopener noreferrer"&gt;this tool&lt;/a&gt; (beat-link-trigger). Unfortunately, I have no idea what it is for but will leave a link in the description.&lt;/p&gt;

&lt;p&gt;You can create web-UI with ClojureScript + React and wrap it in Electron.&lt;/p&gt;

&lt;p&gt;One more approach - to write an app in ClojureScript + &lt;a href="https://microsoft.github.io/react-native-windows/" rel="noopener noreferrer"&gt;Microsoft’s version of react-native&lt;/a&gt; for windows or macOS.&lt;/p&gt;

&lt;p&gt;Or you can try to write an ipad-compatible app with standard React-Native and run it on Mac using apple’s project Catalyst :)&lt;/p&gt;

&lt;p&gt;So you can see, there are really a lot of choices but none of them dominates, which means they all have flaws. You can read a good &lt;a href="https://tonsky.me/blog/clojure-ui/" rel="noopener noreferrer"&gt;article&lt;/a&gt; from Niki Tonsky where Clojure UI problems are discussed. Also to address the problems Niki Tonsky started the development of a new UI for Clojure, called &lt;a href="https://github.com/HumbleUI/HumbleUI" rel="noopener noreferrer"&gt;Humble UI&lt;/a&gt;. So now we have one more option :)&lt;/p&gt;

&lt;p&gt;Ah, and there is also a new version of Clojure in active development - &lt;a href="https://github.com/Tensegritics/ClojureDart" rel="noopener noreferrer"&gt;ClojureDart&lt;/a&gt;. It is a port of Clojure language to Dart with the primary goal of using Flutter framework and getting a native mobile and desktop UI.&lt;/p&gt;

&lt;p&gt;So one more option, yes :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Embedded
&lt;/h2&gt;

&lt;p&gt;As for embedded, I haven’t heard about production Clojure in this area, sorry.&lt;/p&gt;

&lt;p&gt;But &lt;a href="https://www.youtube.com/watch?v=u1jr4v7dhoo" rel="noopener noreferrer"&gt;here is the video&lt;/a&gt; with an experimental running ClojureScript on ESP32 chip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;As you can see, there are situations when Clojure is not very convenient. But there are plenty of situations where it is. And if you are, for example, fullstack developer who occasionally writes scripts, you can use different flavors of Clojure in all your tasks ;)&lt;/p&gt;

&lt;p&gt;originally posted at &lt;a href="https://kozieiev.com/blog/is-clojure-the-only-language-you-need/" rel="noopener noreferrer"&gt;kozieiev.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>clojurescript</category>
      <category>backend</category>
      <category>frontend</category>
    </item>
    <item>
      <title>How to create a library that works with Clojure and ClojureScript</title>
      <dc:creator>Volodymyr Kozieiev</dc:creator>
      <pubDate>Sun, 21 Aug 2022 16:14:54 +0000</pubDate>
      <link>https://dev.to/kozieiev/how-to-create-a-library-that-works-with-clojure-and-clojurescript-54hn</link>
      <guid>https://dev.to/kozieiev/how-to-create-a-library-that-works-with-clojure-and-clojurescript-54hn</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KVWxr9dvGZ8"&gt;
&lt;/iframe&gt;
&lt;br&gt;
this article originally posted at &lt;a href="https://kozieiev.com/blog/how-to-create-library-for-clojure-and-clojurescript/"&gt;https://kozieiev.com&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Content:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Creating Clojure version of logger library&lt;/li&gt;
&lt;li&gt;Creating Clojure app to use logger library&lt;/li&gt;
&lt;li&gt;Introducing reader conditionals&lt;/li&gt;
&lt;li&gt;Making the logger library work with ClojureScript&lt;/li&gt;
&lt;li&gt;Creating ClojureScript app to use logger library&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clojure and ClojureScript are forms of the same language targeting different hosts - JVM and JavaScript respectively. If you are creating a library, there is a big chance that a significant part of the code will work for both hosts but a part of it will be host-dependent. &lt;/p&gt;

&lt;p&gt;Here we will discuss how to isolate the host-dependent parts of code to be used only when appropriate in order to write a single library that works for both Clojure and ClojureScript.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps that we are going to do:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a simple logger Clojure library. Its &lt;code&gt;(log)&lt;/code&gt; function will print the passed object with added timestamp and information from what language it was invoked.&lt;/li&gt;
&lt;li&gt;Create a Clojure app that uses the &lt;code&gt;logger&lt;/code&gt; library&lt;/li&gt;
&lt;li&gt;Modify &lt;code&gt;logger&lt;/code&gt; library to work with ClojureScript as well&lt;/li&gt;
&lt;li&gt;Create a ClojureScript app that uses the &lt;code&gt;logger&lt;/code&gt; library to check that our modifications worked correctly&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Creating Clojure version of logger library
&lt;/h2&gt;

&lt;p&gt;Here is a folder structure for our &lt;code&gt;logger&lt;/code&gt; library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;logger
├── deps.edn
└── src
    └── vkjr
        └── logger.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s &lt;code&gt;deps.edn&lt;/code&gt; can be an empty map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is a code of the &lt;code&gt;logger.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vkjr.logger&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.pprint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;.format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;java.text.SimpleDateFormat.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"d/M/yyyy, HH:mm:ss"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;java.util.Date&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pprint/cl-format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s"&gt;"Time: ~S | Host: ~S | Object: ~S\n"&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s"&gt;"Clojure"&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;(timestamp)&lt;/code&gt; is a helper function that uses Java host features to get a formatted timestamp.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(log)&lt;/code&gt; is the function visible to the library users. It takes the user argument and using &lt;code&gt;(cl-format)&lt;/code&gt; prints it prepended with timestamp and language name (”Clojure” in this case). &lt;/p&gt;

&lt;p&gt;The first argument of &lt;code&gt;(cl-format)&lt;/code&gt; - &lt;code&gt;true&lt;/code&gt;, means that printing should be done to the default output. You can read more about this function in the &lt;a href="https://clojuredocs.org/clojure.pprint/cl-format"&gt;official documentation&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Clojure app to use logger library
&lt;/h2&gt;

&lt;p&gt;Now let’s create a Clojure app to use the library. It will be called &lt;code&gt;cljapp&lt;/code&gt; and put on the same lever with the logger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;playground
├── logger      &amp;lt;- logger library
└── cljapp      &amp;lt;- our new app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a folder structure for &lt;code&gt;cljapp&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cljapp
├── deps.edn
└── src
    └── core.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;deps.edn&lt;/code&gt; we’ll reference &lt;code&gt;logger&lt;/code&gt; library by location on the filesystem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;vkjr/logger&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:local/root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"../logger"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is the code inside &lt;code&gt;core.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vkjr.logger&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;logger/log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Hi there!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;logger/log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;logger/log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We required the namespace of the logger library and used &lt;code&gt;(logger/log)&lt;/code&gt; inside the &lt;code&gt;(main)&lt;/code&gt; to print different arguments.&lt;br&gt;
Now let’s run the main function using Clojure CLI (from &lt;code&gt;cljapp&lt;/code&gt; folder) to make sure it works correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; core                                          
Time: &lt;span class="s2"&gt;"18/8/2022, 16:39:30"&lt;/span&gt; | Host: &lt;span class="s2"&gt;"Clojure"&lt;/span&gt; | Object: &lt;span class="s2"&gt;"Hi there!"&lt;/span&gt;
Time: &lt;span class="s2"&gt;"18/8/2022, 16:39:30"&lt;/span&gt; | Host: &lt;span class="s2"&gt;"Clojure"&lt;/span&gt; | Object: &lt;span class="o"&gt;{&lt;/span&gt;:a 1, :b 2&lt;span class="o"&gt;}&lt;/span&gt;
Time: &lt;span class="s2"&gt;"18/8/2022, 16:39:30"&lt;/span&gt; | Host: &lt;span class="s2"&gt;"Clojure"&lt;/span&gt; | Object: &lt;span class="o"&gt;[&lt;/span&gt;1 2 3 4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice, as we see, it does)&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing reader conditionals
&lt;/h2&gt;

&lt;p&gt;There is a part of Clojure tooling called &lt;strong&gt;Reader.&lt;/strong&gt;  It takes a textual code representation and turns it into the Clojure data structures. When you compile Clojure code, Reader will be responsible for processing your sources.&lt;/p&gt;

&lt;p&gt;Reader supports two &lt;strong&gt;reader conditionals&lt;/strong&gt; which allow you to specify different pieces of code and choose between them depending on the platform where the reader is invoked.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;standard reader&lt;/strong&gt; starts with &lt;code&gt;#?&lt;/code&gt; and looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:clj&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Clojure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:cljs&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ClojureScript&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="no"&gt;:default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When Reader encounters such a conditional, it will leave only one expression in the result data structure - the one corresponding to the current host or the default one if the current host is not listed.&lt;/p&gt;

&lt;p&gt;So after reading this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:clj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:cljs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On ClojureScript host Reader will return this datastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;splicing reader&lt;/strong&gt; starts with &lt;code&gt;#?@&lt;/code&gt; and looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;?&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:clj&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;vector&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;:cljs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;another&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;vector&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it encountered, Reader will choose the vector depending on the host and will put the &lt;strong&gt;content of vector&lt;/strong&gt; in the surrounding context. &lt;strong&gt;Not the vector itself!&lt;/strong&gt; It’s content.&lt;/p&gt;

&lt;p&gt;And after reading this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;?&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:clj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:cljs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;on Clojure platform Reader will return the datastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note: in the source code reader conditionals work only in files with &lt;code&gt;*.cljc&lt;/code&gt; file extension!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To grasp reader conditionals better you can experiment in REPL by feeding different code pieces to the &lt;code&gt;read-string&lt;/code&gt; function (with &lt;code&gt;{:read-cond :allow}&lt;/code&gt; as a first argument) and inspecting the output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj                               &amp;lt;- run repl
&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;read-string &lt;span class="o"&gt;{&lt;/span&gt;:read-cond :allow&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="s2"&gt;"#?(:clj (+ 1 2) :cljs (+ 3 4))"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;+ 1 2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Making the logger library work with ClojureScript
&lt;/h2&gt;

&lt;p&gt;Now with all that knowledge about reader conditionals, it is time to revamp &lt;code&gt;logger&lt;/code&gt; to make it work for ClojureScript.&lt;/p&gt;

&lt;p&gt;First, we need to rename &lt;code&gt;logger.clj&lt;/code&gt; → &lt;code&gt;logger.cljc&lt;/code&gt; to enable reader conditionals. &lt;/p&gt;

&lt;p&gt;Folder structure now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;logger
├── deps.edn
└── src
    └── vkjr
        └── logger.cljc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to add ClojureScript-related code in &lt;code&gt;(comment)&lt;/code&gt; function in &lt;code&gt;logger.cljc&lt;/code&gt;. It will be wrapped with standard reader conditional:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:clj&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;.format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;java.text.SimpleDateFormat.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"d/M/yyyy, HH:mm:ss"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;java.util.Date&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;:cljs&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;js/Date&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;.toLocaleString&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"en-US"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:hour12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And as the last step, we modify &lt;code&gt;(log)&lt;/code&gt; function to display the correct language name depending on the host. We use splicing reader conditional on doing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pprint/cl-format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s"&gt;"Time: ~S | Host: ~S | Object: ~S\n"&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;?&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:clj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Clojure"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="no"&gt;:cljs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"ClojureScript"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full content of &lt;code&gt;logger.cljc&lt;/code&gt; now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vkjr.logger&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.pprint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:clj&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;.format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;java.text.SimpleDateFormat.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"d/M/yyyy, HH:mm:ss"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;java.util.Date&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="no"&gt;:cljs&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;js/Date&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;.toLocaleString&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"en-US"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:hour12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}))))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pprint/cl-format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s"&gt;"Time: ~S | Host: ~S | Object: ~S\n"&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;?&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:clj&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Clojure"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="no"&gt;:cljs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"ClojureScript"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to check that changes didn’t affect the work of existing &lt;code&gt;cljapp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Calling core namespace again from &lt;code&gt;cljapp&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; core                                          
Time: &lt;span class="s2"&gt;"18/8/2022, 16:50:39"&lt;/span&gt; | Host: &lt;span class="s2"&gt;"Clojure"&lt;/span&gt; | Object: &lt;span class="s2"&gt;"Hi there!"&lt;/span&gt;
Time: &lt;span class="s2"&gt;"18/8/2022, 16:50:39"&lt;/span&gt; | Host: &lt;span class="s2"&gt;"Clojure"&lt;/span&gt; | Object: &lt;span class="o"&gt;{&lt;/span&gt;:a 1, :b 2&lt;span class="o"&gt;}&lt;/span&gt;
Time: &lt;span class="s2"&gt;"18/8/2022, 16:50:39"&lt;/span&gt; | Host: &lt;span class="s2"&gt;"Clojure"&lt;/span&gt; | Object: &lt;span class="o"&gt;[&lt;/span&gt;1 2 3 4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating ClojureScript app to use logger library
&lt;/h2&gt;

&lt;p&gt;And finally, we need to check that the library also works for the ClojureScript project.&lt;br&gt;
Let’s create one, called &lt;code&gt;cljsapp&lt;/code&gt; on the same level as &lt;code&gt;logger&lt;/code&gt; and &lt;code&gt;cljapp&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;playground
├── logger
├── cljsapp   &amp;lt;- ClojureScript app
└── cljapp      
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cljsapp
├── deps.edn
└── src
    └── core.cljs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;deps.edn&lt;/code&gt; content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org.clojure/clojurescript&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.11.60"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;vkjr/logger&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:local/root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"../logger"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;core.cljs&lt;/code&gt; content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vkjr.logger&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;logger/log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Hi there!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;logger/log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;logger/log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;logger/log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;js/Date&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the actual check using Clojure CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; cljs.main &lt;span class="nt"&gt;-re&lt;/span&gt; node &lt;span class="nt"&gt;-m&lt;/span&gt; core
Time: &lt;span class="s2"&gt;"8/19/2022, 13:45:03"&lt;/span&gt; | Lang: &lt;span class="s2"&gt;"ClojureScript"&lt;/span&gt; | Object: &lt;span class="s2"&gt;"Hi there!"&lt;/span&gt;

Time: &lt;span class="s2"&gt;"8/19/2022, 13:45:03"&lt;/span&gt; | Lang: &lt;span class="s2"&gt;"ClojureScript"&lt;/span&gt; | Object: &lt;span class="o"&gt;{&lt;/span&gt;:a 1, :b 2&lt;span class="o"&gt;}&lt;/span&gt;

Time: &lt;span class="s2"&gt;"8/19/2022, 13:45:03"&lt;/span&gt; | Lang: &lt;span class="s2"&gt;"ClojureScript"&lt;/span&gt; | Object: &lt;span class="o"&gt;[&lt;/span&gt;1 2 3 4]

Time: &lt;span class="s2"&gt;"8/19/2022, 13:45:03"&lt;/span&gt; | Lang: &lt;span class="s2"&gt;"ClojureScript"&lt;/span&gt; | Object: &lt;span class="c"&gt;#inst "2022-08-19T12:45:03.775-00:00"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect, now we have a library that works for both Clojure and ClojureScript :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/vkjr/code-examples/tree/main/005-crosshost-library-example"&gt;Complete code for on github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://clojure.org/guides/reader_conditionals"&gt;Official documentation on reader conditionals&lt;/a&gt;&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>clojurescript</category>
    </item>
    <item>
      <title>Packaging Clojure projects into jars and uberjars with tools.build</title>
      <dc:creator>Volodymyr Kozieiev</dc:creator>
      <pubDate>Fri, 03 Jun 2022 20:22:00 +0000</pubDate>
      <link>https://dev.to/kozieiev/packaging-clojure-projects-into-jars-and-uberjars-with-toolsbuild-1mdf</link>
      <guid>https://dev.to/kozieiev/packaging-clojure-projects-into-jars-and-uberjars-with-toolsbuild-1mdf</guid>
      <description>&lt;p&gt;This article was originally posted at &lt;a href="https://kozieiev.com/blog/packaging-clojure-into-jar-uberjar-with-tools-build/"&gt;kozieiev.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Video version of this article&lt;/li&gt;
&lt;li&gt;
Jars and uberjars

&lt;ul&gt;
&lt;li&gt;jar/uberjar content&lt;/li&gt;
&lt;li&gt;Resouces&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MANIFEST.mf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pom.xml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tools.build&lt;/code&gt; library

&lt;ul&gt;
&lt;li&gt;adding &lt;code&gt;tools.build&lt;/code&gt; to a project&lt;/li&gt;
&lt;li&gt;creating a jar for the library&lt;/li&gt;
&lt;li&gt;creating a runnable ubjerjar&lt;/li&gt;
&lt;li&gt;more &lt;code&gt;tools.build&lt;/code&gt; functions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Video version of this article
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/OgV-ALpmXUI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Jars and uberjars
&lt;/h2&gt;

&lt;p&gt;The most common way to prepare your Clojure project for distribution is to pack it into a &lt;code&gt;*.jar&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;JAR format came from the Java world and it stands for "Java ARchive". It is a &lt;strong&gt;zip&lt;/strong&gt; archive with a &lt;code&gt;*.jar&lt;/code&gt; extension that contains Java class files, resources, and metadata.&lt;/p&gt;

&lt;p&gt;To distribute Clojure library you can create a jar with library's source files or with compiled code (Java *.class files with bytecode). Optionally you can put both - source files and compiled files. Compiled files will be preferred over a source files unless source files are newer.&lt;/p&gt;

&lt;p&gt;To distribute a Clojure application you have to create a jar that contains compiled Clojure code of the app along with all its dependencies. Such self-contained archive called &lt;strong&gt;uberjar&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  jar/uberjar content
&lt;/h3&gt;

&lt;p&gt;In addition to Clojure sources and Java bytecode files, jars can contain resources and metadata files.&lt;/p&gt;

&lt;h4&gt;
  
  
  Resouces
&lt;/h4&gt;

&lt;p&gt;When preparing the jar you can put there any resource files that your library or app needs (images, text, etc). From the Clojure code, those resources can be accessed via &lt;a href="https://clojuredocs.org/clojure.java.io/resource"&gt;&lt;code&gt;(io/resource)&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;MANIFEST.mf&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Manifest is a special file that contains information about jar content. Here can be specified the entry point of an application but you won't need to do that manually.  &lt;code&gt;tools.build&lt;/code&gt; will generate a default manifest for every jar automatically. If you will need to extend manifest with custom fields, you can use &lt;code&gt;:manifest&lt;/code&gt; option in &lt;code&gt;(jar)&lt;/code&gt; and &lt;code&gt;(uber)&lt;/code&gt; functions of &lt;code&gt;tools.build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;More info about manifest can be found in &lt;a href="https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html"&gt;Java documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;pom.xml&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;In the Java world, there is a super-popular buiid framework called &lt;code&gt;Maven&lt;/code&gt;. it uses &lt;code&gt;pom.xml&lt;/code&gt; files to store project information and configuration. This framework also has its own type of repository for built projects called "maven repository". &lt;/p&gt;

&lt;p&gt;In Clojure, we don't have to use Maven to build projects but we extensively use maven repositories to store build artifacts (jars). Dependencies of our project could be downloaded from maven repos and the resulting artifact of our project (its jar) can be uploaded to maven repo to be accessible by others. &lt;/p&gt;

&lt;p&gt;The most popular maven repo for Clojure artifacts is &lt;a href="https://clojars.org/"&gt;Clojars&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you are planning to upload your project's jar to some maven repository, that jar should contain a &lt;code&gt;pom.xml&lt;/code&gt; with artifact info.&lt;/p&gt;

&lt;p&gt;More info about POM can be found in &lt;a href="https://maven.apache.org/guides/introduction/introduction-to-the-pom.html"&gt;maven documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;tools.build&lt;/code&gt; library
&lt;/h2&gt;

&lt;p&gt;Not so long ago you had to use 3rd-party tools to create jars for your own Clojure projects. But now the official &lt;a href="https://github.com/clojure/tools.build"&gt;&lt;code&gt;tools.build&lt;/code&gt;&lt;/a&gt; library can be used.&lt;/p&gt;

&lt;p&gt;The main idea behind &lt;code&gt;tools.build&lt;/code&gt; is that project's build is also a program and it can be written in Clojure code. And &lt;code&gt;tools.build&lt;/code&gt; is a library that provides functions commonly needed for builds. &lt;/p&gt;

&lt;h3&gt;
  
  
  adding &lt;code&gt;tools.build&lt;/code&gt; to a project
&lt;/h3&gt;

&lt;p&gt;Let's imagine that we have a simple project structured like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;project
├── deps.edn
└── src
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To start using &lt;code&gt;tools.build&lt;/code&gt; we need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a Clojure namespace to keep build functions&lt;/li&gt;
&lt;li&gt;add a new alias to &lt;code&gt;deps.edn&lt;/code&gt; to call build functions with its help&lt;/li&gt;
&lt;li&gt;invoke build function via Clojure CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's add a &lt;code&gt;build.clj&lt;/code&gt; to the root of the project. This is where we are going to keep all the build tasks. For now, there will be only one function - &lt;code&gt;(clean)&lt;/code&gt; . It removes &lt;code&gt;target&lt;/code&gt; directory using &lt;code&gt;(b/delete)&lt;/code&gt;  from &lt;a href="https://clojure.github.io/tools.build/clojure.tools.build.api.html"&gt;&lt;code&gt;tools.build.api&lt;/code&gt;&lt;/a&gt;. Inside &lt;code&gt;target&lt;/code&gt;, we will keep all our build artifacts, so it should be cleaned between builds.&lt;/p&gt;

&lt;p&gt;We don't use any arguments inside &lt;code&gt;(clean)&lt;/code&gt;  but it should be defined as a function with one argument because, when invoked from Clojure CLI, it will be called with one - map of the arguments passed via the command line (&lt;code&gt;nil&lt;/code&gt; if you didn't pass any).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;build.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.tools.build.api&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="c1"&gt;; requiring tools.build&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;                                 &lt;/span&gt;&lt;span class="c1"&gt;; removing artifacts folder with (b/delete)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Build folder \"%s\" removed"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make build functions accessible via Clojure CLI, let's create a new alias in &lt;code&gt;deps.edn&lt;/code&gt;. In that alias there should be &lt;code&gt;:deps&lt;/code&gt; key with &lt;code&gt;tools.build&lt;/code&gt; dependency and &lt;code&gt;:ns-default&lt;/code&gt; key which tells CLI in what namespace it should look for the function mentioned in the command line. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;deps.edn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;; ... other deps.edn content ...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;; ... other aliases ...&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;; build alias:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;:build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io.github.clojure/tools.build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"v0.8.1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"7d40500"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="no"&gt;:ns-default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;; &amp;lt;-- set build namespace as default&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, to run &lt;code&gt;(clean)&lt;/code&gt; from the command line using the new alias, we need to call Clojure CLI with &lt;code&gt;-T&lt;/code&gt; option. That option ignores the rest of &lt;code&gt;deps.edn&lt;/code&gt; content and uses the dependencies only from the current alias. In this way, we do not interfere with the other project dependencies and source files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build clean
Build folder &lt;span class="s2"&gt;"target"&lt;/span&gt; removed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  creating a jar for the library
&lt;/h3&gt;

&lt;p&gt;Now let's review an example of creating a jar for the library with the following folder structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mymathlibary
├── build.clj
├── deps.edn
├── resources
│   └── lib_resource.txt
└── src
    └── mymath
        └── sum.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;sum.clj&lt;/code&gt; there is a &lt;code&gt;sum&lt;/code&gt; function that adds two values and prints text from the resource file (please promise me to not do like this in real-world libs). &lt;/p&gt;

&lt;p&gt;&lt;code&gt;sum.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mymath.sum&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.java.io&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Lib resource content:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;slurp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;io/resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"mymath_resource.txt"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Text inside &lt;code&gt;lib_resource.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello from mymath lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's say we want our jar to contain only source code, without compiled bytecode. To achieve this, in &lt;code&gt;build.clj&lt;/code&gt; we need to add a new function named &lt;code&gt;(jar)&lt;/code&gt; that does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cleans &lt;code&gt;target&lt;/code&gt; directory from leftovers&lt;/li&gt;
&lt;li&gt;copies sources and resources to &lt;code&gt;target&lt;/code&gt;. They should go into the result jar.&lt;/li&gt;
&lt;li&gt;creates &lt;code&gt;pom.xml&lt;/code&gt; file. You will need it if you are going to put the library into maven repositories.&lt;/li&gt;
&lt;li&gt;creates the jar file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the code of our new &lt;code&gt;build.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.tools.build.api&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"/classes"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;; folder where we collect files to pack in a jar&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'com.github.YOURNAME/mymath-lib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;; library name&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.0.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                               &lt;/span&gt;&lt;span class="c1"&gt;; library version&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/create-basis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"deps.edn"&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;; basis structure (read details in the article)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"%s/%s-%s.jar"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib-name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;; path for result jar file&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Build folder \"%s\" removed"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;clean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                                     &lt;/span&gt;&lt;span class="c1"&gt;; clean leftovers&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/copy-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:src-dirs&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;; prepare jar content&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="no"&gt;:target-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-content&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/write-pom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:class-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-content&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;; create pom.xml&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="no"&gt;:lib&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;lib-name&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="no"&gt;:version&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="no"&gt;:basis&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;basis&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="no"&gt;:src-dirs&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/jar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:class-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-content&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="c1"&gt;; create jar&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;:jar-file&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;jar-file-name&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Jar file created: \"%s\""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-file-name&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code of &lt;code&gt;(jar)&lt;/code&gt; we use three functions from &lt;code&gt;tools.build&lt;/code&gt; to achieve steps mentioned before: &lt;code&gt;(b/copy-dir)&lt;/code&gt;, &lt;code&gt;(b/write-pom)&lt;/code&gt; and &lt;code&gt;(b/jar)&lt;/code&gt;. Their names and arguments are pretty self-explanatory except one - &lt;code&gt;:basis&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The basis is a big structure that contains a superset of all &lt;code&gt;deps.edn&lt;/code&gt; files, project classpath, and description of all dependencies. In the official Clojure documentation, it is mentioned &lt;a href="https://clojure.org/reference/deps_and_cli#_basis_and_classpath"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;tools.build&lt;/code&gt; uses basis in a few functions and gives a function to create it - &lt;code&gt;(b/create-basis)&lt;/code&gt;. The &lt;code&gt;(b/write-pom)&lt;/code&gt; function uses basis to correctly reflect the library dependencies in &lt;code&gt;pom.xml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now to create the jar we can run &lt;code&gt;(jar)&lt;/code&gt; function using Clojure CLI (assuming your &lt;code&gt;deps.edn&lt;/code&gt; already contains &lt;code&gt;:build&lt;/code&gt; alias):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build jar
Build folder &lt;span class="s2"&gt;"target"&lt;/span&gt; removed
Jar file created: &lt;span class="s2"&gt;"target/mymath-lib-0.0.1.jar"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it can be uploaded to a maven repo and used as a dependency in other projects.&lt;/p&gt;

&lt;p&gt;You can examine jar content using &lt;code&gt;jar -tf&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;jar &lt;span class="nt"&gt;-tf&lt;/span&gt; target/mymath-lib-0.0.1.jar 
META-INF/MANIFEST.MF
lib_resource.txt
META-INF/
mymath/
META-INF/maven/
mymath/sum.clj
META-INF/maven/com.github.YOURNAME/
META-INF/maven/com.github.YOURNAME/mymath-lib/
META-INF/maven/com.github.YOURNAME/mymath-lib/pom.xml
META-INF/maven/com.github.YOURNAME/mymath-lib/pom.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/volodymyrk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_4tnISpR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7v0zsd3bxcdkmmeogot3.png" alt="Image description" width="273" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  creating a runnable ubjerjar
&lt;/h3&gt;

&lt;p&gt;Now we can take a look at how to create a runnable uberjar for a Clojure application.&lt;/p&gt;

&lt;p&gt;For example, we have a project with the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;simpleapp
├── build.clj
├── deps.edn
├── resources
│   └── app_resource.txt
└── src
    └── dev
        └── core.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;core.clj&lt;/code&gt; contains &lt;code&gt;(-main)&lt;/code&gt; function that will work as an entry point when the application invoked. The &lt;code&gt;(-main)&lt;/code&gt; calls &lt;code&gt;(sum)&lt;/code&gt; function from the library created in a previous section and prints text from the local resource file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;core.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dev.core&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mymath.sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.java.io&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:gen-class&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;; !!! instruction to generate bytecode for java class from this namespace&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Sum is:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;s/sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"App resource content:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;slurp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;io/resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"app_resource.txt"&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most important thing here is a &lt;code&gt;:gen-class&lt;/code&gt; directive to &lt;code&gt;(ns)&lt;/code&gt; function. It tells Clojure compiler to generate an additional bytecode file with java class corresponding to this namespace. That class will serve an entry point for our uberjar. &lt;/p&gt;

&lt;p&gt;Now in &lt;code&gt;build.clj&lt;/code&gt; we can create an &lt;code&gt;(uber)&lt;/code&gt; function that builds uberjar. Here is what it should do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clean &lt;code&gt;target&lt;/code&gt; directory from leftovers&lt;/li&gt;
&lt;li&gt;copy resources to &lt;code&gt;target&lt;/code&gt;. They should go into result uber.&lt;/li&gt;
&lt;li&gt;compile Clojure code&lt;/li&gt;
&lt;li&gt;create the uberjar with &lt;code&gt;(-main)&lt;/code&gt; entrypoint &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full code of &lt;code&gt;build.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.tools.build.api&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"/classes"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/create-basis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"deps.edn"&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.0.1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"myapp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uber-file-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"%s/%s-%s-standalone.jar"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; path for result uber file&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Build folder \"%s\" removed"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build-folder&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;clean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/copy-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:src-dirs&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;; copy resources&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="no"&gt;:target-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-content&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/compile-clj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:basis&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;basis&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="c1"&gt;; compile clojure code&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="no"&gt;:src-dirs&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="no"&gt;:class-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-content&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/uber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:class-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-content&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;; create uber file&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="no"&gt;:uber-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uber-file-name&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="no"&gt;:basis&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;basis&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="no"&gt;:main&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="ss"&gt;'dev.core&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;; here we specify the entry point for uberjar&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Uber file created: \"%s\""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uber-file-name&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is quite similar to the one where we were creating jar and probably doesn't require many explanations. New functions here are &lt;code&gt;(b/compile-clj)&lt;/code&gt; and &lt;code&gt;(b/uber)&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;By the way you could have used &lt;code&gt;(b/compile-clj)&lt;/code&gt; in library example to create a library jar with compiled code. &lt;/p&gt;

&lt;p&gt;Now let's bulid our uberjar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build uber
Build folder &lt;span class="s2"&gt;"target"&lt;/span&gt; removed
Uber file created: &lt;span class="s2"&gt;"target/myapp-0.0.1-standalone.jar"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run it using &lt;code&gt;java -jar&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; target/myapp-0.0.1-standalone.jar
Lib resource content: hello from mymath lib
Sum is: 3
App resource content: hello from app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, resource file content was printed from the app and the lib. That means uberjar was created successfully and contains all the necessary files.&lt;/p&gt;

&lt;p&gt;The output of &lt;code&gt;jar -tf target/myapp-0.0.1-standalone.jar&lt;/code&gt; will be too long to post it here but I encourage you to investigate the content of created uberjar to see how dependencies are included there. &lt;/p&gt;

&lt;h3&gt;
  
  
  more &lt;code&gt;tools.build&lt;/code&gt; functions
&lt;/h3&gt;

&lt;p&gt;Your &lt;code&gt;build.clj&lt;/code&gt; is not restricted to creating jars and uberjars. There are more functions in &lt;code&gt;tools.build&lt;/code&gt; that give you freedom to build scripts of an arbitrary complexity:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(process)&lt;/code&gt; - runs an arbitrary command with arguments&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(git-process)&lt;/code&gt; - runs git command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(zip)&lt;/code&gt; and &lt;code&gt;(unzip)&lt;/code&gt; - work with archives&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(install)&lt;/code&gt; - installs jar to a local maven repository&lt;/p&gt;

&lt;p&gt;More details can be found in the &lt;code&gt;tools.build&lt;/code&gt; &lt;a href="https://clojure.github.io/tools.build/clojure.tools.build.api.html#var-install"&gt;official api&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>cli</category>
      <category>build</category>
    </item>
    <item>
      <title>Build and run Clojure projects. CLI, tools.deps and deps.edn guide</title>
      <dc:creator>Volodymyr Kozieiev</dc:creator>
      <pubDate>Sat, 02 Apr 2022 15:42:00 +0000</pubDate>
      <link>https://dev.to/kozieiev/build-and-run-clojure-projects-cli-toolsdeps-and-depsedn-guide-5911</link>
      <guid>https://dev.to/kozieiev/build-and-run-clojure-projects-cli-toolsdeps-and-depsedn-guide-5911</guid>
      <description>&lt;p&gt;This article was originally posted at &lt;a href="https://kozieiev.com/blog/clojure-cli-tools-deps-deps-edn-guide/" rel="noopener noreferrer"&gt;kozieiev.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Note for readers&lt;/li&gt;
&lt;li&gt;Video version of this article&lt;/li&gt;
&lt;li&gt;
What is Clojure CLI?

&lt;ul&gt;
&lt;li&gt;Difference between clj and clojure executables&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Most usable &lt;code&gt;clj&lt;/code&gt; options

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-M&lt;/code&gt; option to work with &lt;code&gt;clojure.main&lt;/code&gt; namespace&lt;/li&gt;
&lt;li&gt;Running (-main) function from namespace&lt;/li&gt;
&lt;li&gt;Running clojure file as a script&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-X&lt;/code&gt; option to run specific functions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;code&gt;deps.edn&lt;/code&gt; configuration files

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:paths&lt;/code&gt; key&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:deps&lt;/code&gt; key&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:aliases&lt;/code&gt; key&lt;/li&gt;
&lt;li&gt;Aliases for &lt;code&gt;clj -M&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Aliases for &lt;code&gt;clj -X&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;code&gt;tools.deps&lt;/code&gt; library

&lt;ul&gt;
&lt;li&gt;Managing dependencies&lt;/li&gt;
&lt;li&gt;Building classpath&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Running REPL with &lt;code&gt;clj -A&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;

Real-world examples

&lt;ul&gt;
&lt;li&gt;Cognitect &lt;code&gt;test-runner&lt;/code&gt; setup&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;clj-new&lt;/code&gt; library setup&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Other &lt;code&gt;clj&lt;/code&gt; capabilities&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Note for readers
&lt;/h2&gt;

&lt;p&gt;This article was written for those who want to understand how to work with Clojure CLI (command line interface), and how to configure it with &lt;code&gt;deps.edn&lt;/code&gt; files. There are 2 official articles on this topic: &lt;a href="https://clojure.org/guides/deps_and_cli" rel="noopener noreferrer"&gt;Deps and CLI Guide&lt;/a&gt; and &lt;a href="https://clojure.org/reference/deps_and_cli" rel="noopener noreferrer"&gt;Deps and CLI Reference&lt;/a&gt;. These are both very helpful, but In my opinion, the first one is too brief to gain a good enough understanding of concepts, and the second one is too long for an introduction to the topic. So I tried to write something in between that gives the reader a deep enough explanation of how &lt;code&gt;clj&lt;/code&gt; works, but without all the nitty-gritty details.&lt;/p&gt;

&lt;p&gt;At the time of writing this, I used Clojure CLI version &lt;code&gt;1.10.3.855&lt;/code&gt; on Mac.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video version of this article
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/8aCO_wNuScQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Clojure CLI?
&lt;/h2&gt;

&lt;p&gt;Clojure CLI provides the tools to execute Clojure programs and manage their dependencies.&lt;br&gt;
To understand Clojure CLI, we should cover 3 main topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;clj&lt;/code&gt; and &lt;code&gt;clojure&lt;/code&gt; are executables that you invoke to run Clojure code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tools.deps&lt;/code&gt; is a library that works behind the scenes to manage dependencies and to create classpaths.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deps.edn&lt;/code&gt; configuration files that you create to customize work of &lt;code&gt;clj&lt;/code&gt;/&lt;code&gt;clojure&lt;/code&gt; and &lt;code&gt;tools.deps&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Difference between clj and clojure executables
&lt;/h3&gt;

&lt;p&gt;Both &lt;code&gt;clj&lt;/code&gt; and &lt;code&gt;clojure&lt;/code&gt; are scripts, and &lt;code&gt;clj&lt;/code&gt; is just a wrapper on &lt;code&gt;clojure&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's find where &lt;code&gt;clj&lt;/code&gt; is located:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;which clj
/usr/local/bin/clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And examine its content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /usr/local/bin/clj              
&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
...
  &lt;span class="nb"&gt;exec &lt;/span&gt;rlwrap &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s1"&gt;'\"'&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s2"&gt;"(){}[],^%#@&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;:'"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$bin_dir&lt;/span&gt;&lt;span class="s2"&gt;/clojure"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see ,&lt;code&gt;clj&lt;/code&gt;, behind the scenes, wraps a call to &lt;code&gt;$bin_dir/clojure&lt;/code&gt; with the &lt;code&gt;rlwrap&lt;/code&gt; tool. &lt;a href="https://github.com/hanslub42/rlwrap" rel="noopener noreferrer"&gt;&lt;code&gt;rlwrap&lt;/code&gt;&lt;/a&gt; provides a better command-line editing experience.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;clojure&lt;/code&gt; without arguments, REPL will be started. Try to type something in it, and press up/down/left/right keyboard keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clojure                                                                                                 
Clojure 1.10.3
&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;(&lt;/span&gt;+ 1 2&lt;span class="o"&gt;)&lt;/span&gt; ^[[A^[[B^[[D^[[C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will notice that those keys don't work properly. &lt;/p&gt;

&lt;p&gt;But if you run &lt;code&gt;clj&lt;/code&gt; instead, you will be able to use left/right keys to navigate the typed text, and up/down to navigate the calls history. This is exactly the function provided by &lt;code&gt;rlwrap&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I will be using only &lt;code&gt;clj&lt;/code&gt; later in the article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Most usable &lt;code&gt;clj&lt;/code&gt; options
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;-M&lt;/code&gt; and &lt;code&gt;-X&lt;/code&gt; are the most important options, and the ones you need to learn first.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;-M&lt;/code&gt; option to work with &lt;code&gt;clojure.main&lt;/code&gt; namespace
&lt;/h3&gt;

&lt;p&gt;Invoking &lt;code&gt;clj&lt;/code&gt; with the &lt;code&gt;-M&lt;/code&gt; option gives you access to functionality from the &lt;code&gt;clojure.main&lt;/code&gt; namespace. All arguments after &lt;code&gt;-M&lt;/code&gt; will be passed to the &lt;code&gt;clojure.main/main&lt;/code&gt; and interpreted by it. To see all available options of &lt;code&gt;clojure.main&lt;/code&gt;, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or take a look at &lt;a href="https://clojure.org/reference/repl_and_main" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. &lt;/p&gt;

&lt;h4&gt;
  
  
  Running (-main) function from namespace
&lt;/h4&gt;

&lt;p&gt;The most common usage of &lt;code&gt;clj -M&lt;/code&gt; is to run the entry point of your clojure code. To do this, you should pass &lt;code&gt;-m namespace-name&lt;/code&gt; options to the &lt;code&gt;clojure.main&lt;/code&gt;. It will find the specified namespace, and invoke its &lt;code&gt;(-main)&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;For example, if you have the following project directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project-dir        (project directory)
└─ src             (default sources directory)
   └─ core.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the &lt;code&gt;core.clj&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"(-main) invoked"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;core/main&lt;/code&gt; from the &lt;code&gt;project-dir&lt;/code&gt; directory looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; core
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-main&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; invoked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Running clojure file as a script
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;clojure.main&lt;/code&gt; also allows running Clojure file as a script. To do this via CLI, you should use the command, &lt;code&gt;clj -M /path/to/script/file.clj arg1 arg2 arg3&lt;/code&gt;. An arbitrary number of arguments passed after script path will be available in a script under &lt;code&gt;*command-line-args*&lt;/code&gt; var.&lt;br&gt;
If you have a &lt;code&gt;script.clj&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Script invoked with args: "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;*command-line-args*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling it will give you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; script.clj 1 2 3
Script invoked with args:  &lt;span class="o"&gt;(&lt;/span&gt;1 2 3&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;-X&lt;/code&gt; option to run specific functions
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;(-main)&lt;/code&gt; is not the only function you can run via CLI. You can run any other one using the &lt;code&gt;-X&lt;/code&gt; option as long as this function takes a map as an argument. The command should look like this: &lt;code&gt;clj -X namespace/fn [arg-key value]*&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With file &lt;code&gt;core.clj&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;print-args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"print-args function called with arg: "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;core.clj&lt;/code&gt; is located in your &lt;code&gt;project-dir/src&lt;/code&gt;,  you can call &lt;code&gt;(print-args)&lt;/code&gt; using CLI from the &lt;code&gt;project-dir&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-X&lt;/span&gt; core/print-args :key1 value1 :key2 value2
print-args &lt;span class="k"&gt;function &lt;/span&gt;called with arg:  &lt;span class="o"&gt;{&lt;/span&gt;:key1 value1, :key2 value2&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key-value pairs specified after the function name will be passed to the function as a map.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;deps.edn&lt;/code&gt; configuration files
&lt;/h2&gt;

&lt;p&gt;There are a few files with the name &lt;code&gt;deps.edn&lt;/code&gt;. One in the &lt;code&gt;clj&lt;/code&gt; installation itself. You can  also have another one in the &lt;code&gt;$HOME/.clojure&lt;/code&gt; folder to keep the common settings for all your projects. And, of course, you can create one in your project directory with project-specific settings. All of them store configuration settings in clojure maps. When &lt;code&gt;clj&lt;/code&gt; is invoked, it merges them all to create a final configuration map. You can read more about locations of different &lt;code&gt;deps.edn&lt;/code&gt; files in &lt;a href="https://clojure.org/reference/deps_and_cli#_deps_edn_sources" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Later in this article, I will mostly talk about &lt;code&gt;deps.edn&lt;/code&gt; that you create in a project directory.&lt;/p&gt;

&lt;p&gt;The most important keys in the configuration map are &lt;code&gt;:deps&lt;/code&gt;, &lt;code&gt;:paths&lt;/code&gt;, and &lt;code&gt;:aliases:&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;:paths&lt;/code&gt; key
&lt;/h3&gt;

&lt;p&gt;Under the &lt;code&gt;:path&lt;/code&gt; key, you specify the vector of directories where source code is located. &lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;deps.edn&lt;/code&gt; file doesn't exist in your project folder or it doesn't contain the&lt;code&gt;:path&lt;/code&gt; key, &lt;code&gt;clj&lt;/code&gt; uses the &lt;code&gt;src&lt;/code&gt; folder by default.&lt;/p&gt;

&lt;p&gt;For example, if you have the following directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project-dir        
├─ src             
│  └─ core.clj
└─ test  
   └─ test_runner.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;core.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"(-main) invoked"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;test_runner.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test-runner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Running tests.."&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run something from &lt;code&gt;core.clj&lt;/code&gt; because it is in the &lt;code&gt;src&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; core
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-main&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; invoked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But an attempt to run &lt;code&gt;test-runner/run&lt;/code&gt; will fail. The &lt;code&gt;test-runner&lt;/code&gt; namespace from the&lt;code&gt;test&lt;/code&gt; folder isn't available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-X&lt;/span&gt; test-runner/run
Execution error &lt;span class="o"&gt;(&lt;/span&gt;FileNotFoundException&lt;span class="o"&gt;)&lt;/span&gt; at clojure.run.exec/requiring-resolve&lt;span class="s1"&gt;' (exec.clj:31).
...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix this, add the &lt;code&gt;deps.edn&lt;/code&gt; file at the root of your &lt;code&gt;project-dir&lt;/code&gt;, and put a vector of all source folders under the &lt;code&gt;:paths&lt;/code&gt; key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the content of the &lt;code&gt;test&lt;/code&gt; folder is visible to &lt;code&gt;clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-X&lt;/span&gt; test-runner/run
Running tests..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note, that you should specify both the &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; folders under the&lt;code&gt;:paths&lt;/code&gt; key.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;:deps&lt;/code&gt; key
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Under&lt;/strong&gt; the &lt;code&gt;:deps&lt;/code&gt; key , you can place a map of external libraries that your project relies on. Libraries will be downloaded along with their dependencies, and become available for use.&lt;/p&gt;

&lt;p&gt;Dependencies can be taken from the Maven repository, git repository, or local disk.&lt;/p&gt;

&lt;p&gt;For Maven dependencies, you should specify their version. By default, two Maven repos are used for the search:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://repo1.maven.org/maven2/" rel="noopener noreferrer"&gt;https://repo1.maven.org/maven2/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://clojars.org/repo" rel="noopener noreferrer"&gt;https://clojars.org/repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Git dependencies, you should specify &lt;code&gt;:git/url&lt;/code&gt; with the repo address, and the &lt;code&gt;:git/sha&lt;/code&gt; or &lt;code&gt;:git/tag&lt;/code&gt; keys to specify the library version. &lt;/p&gt;

&lt;p&gt;Let's &lt;strong&gt;declare&lt;/strong&gt; &lt;code&gt;deps.edn&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;com.taoensso/timbre&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"5.1.2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;io.github.cognitect-labs/test-runner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"https://github.com/cognitect-labs/test-runner.git"&lt;/span&gt;&lt;span class="w"&gt;
                                              &lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s"&gt;"705ad25bbf0228b1c38d0244a36001c2987d7337"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;clj&lt;/code&gt; is invoked, two libraries will be available in our code: &lt;a href="https://github.com/ptaoussanis/timbre" rel="noopener noreferrer"&gt;&lt;code&gt;timbre&lt;/code&gt;&lt;/a&gt; logging library which artifacts taken from Maven, and &lt;a href="https://github.com/cognitect-labs/test-runner/" rel="noopener noreferrer"&gt;&lt;code&gt;test-runner&lt;/code&gt;&lt;/a&gt;, taken from GitHub.&lt;/p&gt;

&lt;p&gt;From &lt;code&gt;core.clj&lt;/code&gt; &lt;code&gt;timbre&lt;/code&gt; now can be used after importing its namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;taoensso.timbre&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;log/info&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Logged with taoensso.timbre"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;test-runner&lt;/code&gt; main function can be invoked by &lt;code&gt;clj&lt;/code&gt; with already known &lt;code&gt;-M&lt;/code&gt; switch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; cognitect.test-runner
Running tests &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="c"&gt;#{"test"}&lt;/span&gt;

Testing user

Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More details on how to use local dependencies and meaning of different keys can be found in &lt;a href="https://clojure.org/reference/deps_and_cli#_dependencies" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;:aliases&lt;/code&gt; key
&lt;/h3&gt;

&lt;p&gt;The "alias" is the main concept in &lt;code&gt;deps.edn&lt;/code&gt;. It is where concentrates all convenience of &lt;code&gt;clj&lt;/code&gt; tool. Let's explore it with examples.&lt;/p&gt;

&lt;h4&gt;
  
  
  Aliases for &lt;code&gt;clj -M&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;So far, we've been using &lt;code&gt;clj&lt;/code&gt; with the &lt;code&gt;-M&lt;/code&gt; option to run the &lt;code&gt;(-main)&lt;/code&gt; function in a specified namespace. Let's imagine that our project has two different entry namespaces with &lt;code&gt;(-main)&lt;/code&gt; functions. One is used for development and one for production. Our project folder looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project-dir        
└─ src             
   └─ dev
   │  └─ core.clj
   └─ prod
      └─ core.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command line for the dev build is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; dev.core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for prod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; prod.core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To minimize typing, we can declare two different aliases in the &lt;code&gt;deps.edn&lt;/code&gt; file, and store all options after &lt;code&gt;clj -M&lt;/code&gt; under that aliases.&lt;/p&gt;

&lt;p&gt;Here is the content of &lt;code&gt;deps.edn&lt;/code&gt; with two declared aliases &lt;code&gt;:dev&lt;/code&gt; and &lt;code&gt;:prod&lt;/code&gt;. You can use any keywords as alias names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:dev&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:main-opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-m"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"dev.core"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="no"&gt;:prod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:main-opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-m"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"prod.core"&lt;/span&gt;&lt;span class="p"&gt;]}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To invoke an alias, you add its name right after the &lt;code&gt;-M&lt;/code&gt; option. Now, running the dev build using an alias looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt;:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's similar for prod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt;:prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, &lt;code&gt;:aliases&lt;/code&gt; is a key in the &lt;code&gt;deps.edn&lt;/code&gt; map where you store a map with user-defined aliases. &lt;/p&gt;

&lt;p&gt;Every alias is a key-value pair, where the key is a user-defined name of the alias, and value is a map with &lt;strong&gt;pre-defined&lt;/strong&gt; keys. In the example above, we used &lt;code&gt;:main-opts&lt;/code&gt;, a pre-defined key that keeps a vector of options to be passed to the &lt;code&gt;clojure.main&lt;/code&gt; namespace. When &lt;code&gt;clj -M&lt;/code&gt; is invoked with an alias, it runs &lt;code&gt;clojure.main&lt;/code&gt; with arguments taken from  &lt;code&gt;:main-opts&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Aliases for &lt;code&gt;clj -X&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;We can also create aliases to run specific functions. They look pretty much the same as aliases from the example above, but rely on other pre-defined keys.&lt;/p&gt;

&lt;p&gt;Let's imagine you have a function for generating reports. It is located in the &lt;code&gt;db.reports&lt;/code&gt; namespace, named &lt;code&gt;generate&lt;/code&gt;. The only argument is a map with two possible keys: &lt;code&gt;:settings&lt;/code&gt; for a map of settings, and &lt;code&gt;:tables&lt;/code&gt; with a vector of tables for which we want to get reports. If the &lt;code&gt;:tables&lt;/code&gt; key is absent, we generate reports for all tables.&lt;/p&gt;

&lt;p&gt;Let's make a stub for our &lt;code&gt;reports.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;db.reports&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="no"&gt;:keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="p"&gt;]}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"generated report with settings:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"for tables:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"all"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run reports for all tables from the command line, we can invoke:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clj &lt;span class="nt"&gt;-X&lt;/span&gt; db.reports/generate &lt;span class="s1"&gt;'{:settings {:brief true}}'&lt;/span&gt;
generated report with settings: &lt;span class="o"&gt;{&lt;/span&gt;:brief &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;tables: all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;orders&lt;/code&gt; and &lt;code&gt;users&lt;/code&gt; tables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-X&lt;/span&gt; db.reports/generate &lt;span class="s1"&gt;'{:settings {:brief true} :tables ["users" "orders"]}'&lt;/span&gt;
generated report with settings: &lt;span class="o"&gt;{&lt;/span&gt;:brief &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;tables: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;users &lt;/span&gt;orders]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since typing all arguments in the command line is quite tedious, let's create aliases in &lt;code&gt;deps.edn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:generate-all&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:exec-fn&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;db.reports/generate&lt;/span&gt;&lt;span class="w"&gt;
                           &lt;/span&gt;&lt;span class="no"&gt;:exec-args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:settings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:brief&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="no"&gt;:generate-some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:exec-fn&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;db.reports/generate&lt;/span&gt;&lt;span class="w"&gt;
                           &lt;/span&gt;&lt;span class="no"&gt;:exec-args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:settings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:brief&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                                       &lt;/span&gt;&lt;span class="no"&gt;:tables&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"users"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"orders"&lt;/span&gt;&lt;span class="p"&gt;]}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can generate reports more conveniently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-X&lt;/span&gt;:generate-all
generated report with settings: &lt;span class="o"&gt;{&lt;/span&gt;:brief &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;tables: all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clj &lt;span class="nt"&gt;-X&lt;/span&gt;:generate-some
generated report with settings: &lt;span class="o"&gt;{&lt;/span&gt;:brief &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;tables: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;users &lt;/span&gt;orders]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you probably noticed, we don't use the &lt;code&gt;:main-opts&lt;/code&gt;'s pre-defined key anymore, because it works only with &lt;code&gt;clj -M&lt;/code&gt;. Instead, we use the &lt;code&gt;:exec-fn&lt;/code&gt; key to specify the namespace/function to run, and &lt;code&gt;:exec-args&lt;/code&gt; to pass arguments map.&lt;/p&gt;

&lt;p&gt;If you will try to run one of these aliases with &lt;code&gt;clj -M&lt;/code&gt;, you will see a REPL started instead of the invoked function. This is because &lt;code&gt;clj&lt;/code&gt; starts &lt;code&gt;clojure.core&lt;/code&gt; when it sees the &lt;code&gt;-M&lt;/code&gt; option, and since there is no &lt;code&gt;:main-opts&lt;/code&gt; key, it won't pass any arguments to it. And &lt;code&gt;clojure.core&lt;/code&gt; invoked without arguments will simply start REPL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt;:generate-some
Clojure 1.10.3
&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are pre-defined keys common to the &lt;code&gt;-X&lt;/code&gt; and &lt;code&gt;-M&lt;/code&gt; options, but we will discuss them later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/volodymyrk" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7v0zsd3bxcdkmmeogot3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;tools.deps&lt;/code&gt; library
&lt;/h2&gt;

&lt;p&gt;When &lt;code&gt;clj&lt;/code&gt; runs clojure programs, it runs a JVM process and needs to pass a classpath to it. (To read more about how Clojure works on top of JVM, you can check &lt;a href="https://kozieiev.com/posts/000-clojure-vs-clojurescript/" rel="noopener noreferrer"&gt;this article&lt;/a&gt;) Classpath is a list of all paths where java should look for classes used in your program, including classes for your dependencies. So to build a classpath, all dependencies should be resolved first. Both these tasks, resolving dependencies and creating a classpath, is done by the&lt;code&gt;tools.deps&lt;/code&gt; library that goes with Clojure. &lt;code&gt;clj&lt;/code&gt; calls &lt;code&gt;tools.deps&lt;/code&gt; internally.&lt;/p&gt;

&lt;p&gt;Two main functions in &lt;code&gt;tools.deps&lt;/code&gt; that resolve and build classpaths are &lt;code&gt;(resolve-deps)&lt;/code&gt; and &lt;code&gt;(make-classpath-map)&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;p&gt;Let's take a look at their work and arguments:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpo508ijgmhu54dlwuwel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpo508ijgmhu54dlwuwel.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Managing dependencies
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;(resolve-deps)&lt;/code&gt; is the first one that comes into play. As a first argument, it takes a list of dependencies declared in a top-level &lt;code&gt;:deps&lt;/code&gt; key of &lt;code&gt;deps.edn&lt;/code&gt;.  And as a second argument, map of pre-defined keys taken from an alias that you used when launched &lt;code&gt;clj&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:extra-deps&lt;/code&gt; allows you to add dependencies only when a particular alias is invoked. For example, you don't need to use the &lt;code&gt;test-runner&lt;/code&gt; dependency, unless you are running a test. So you can put it in an alias under &lt;code&gt;:extra-deps&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org.clojure/clojure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.10.3"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:extra-deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io.github.cognitect-labs/test-runner&lt;/span&gt;&lt;span class="w"&gt;
                               &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"https://github.com/cognitect-labs/test-runner.git"&lt;/span&gt;&lt;span class="w"&gt;
                                &lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="s"&gt;"705ad25bbf0228b1c38d0244a36001c2987d7337"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="no"&gt;:main-opts&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-m"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"cognitect.test-runner"&lt;/span&gt;&lt;span class="p"&gt;]}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other keys that can be used in an alias on this step are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;:override-deps - overrides the library version chosen by the version resolution to force a particular version instead.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:default-deps&lt;/code&gt; - provides a set of default versions to use. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:replace-deps&lt;/code&gt; - a map from libs to versions of dependencies that will fully replace the project &lt;code&gt;:deps&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When invoked, &lt;code&gt;(resolve-deps)&lt;/code&gt; will combine the original list of dependencies with modifications provided in aliases, resolve all transitive dependencies, download required artifacts, and will build a flat libraries map of all dependencies needed for current invokation.&lt;/p&gt;

&lt;p&gt;Since managing dependencies step happens at any kind of &lt;code&gt;clj&lt;/code&gt; invocation, pre-defined keys &lt;code&gt;:extra-deps&lt;/code&gt;, &lt;code&gt;:override-deps&lt;/code&gt; and &lt;code&gt;:default-deps&lt;/code&gt; can be used with any &lt;code&gt;clj&lt;/code&gt; option we described before. &lt;/p&gt;

&lt;h3&gt;
  
  
  Building classpath
&lt;/h3&gt;

&lt;p&gt;After the libraries map is created, the classpath building function comes into play. &lt;code&gt;(make-classpath-map)&lt;/code&gt; takes three arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;libraries map that is a result of the &lt;code&gt;(resolve-deps)&lt;/code&gt; step.&lt;/li&gt;
&lt;li&gt;content of &lt;code&gt;:paths&lt;/code&gt; key in &lt;code&gt;deps.edn&lt;/code&gt; map.&lt;/li&gt;
&lt;li&gt;map of pre-defined keys &lt;code&gt;:extra-paths&lt;/code&gt;,  &lt;code&gt;:classpath-overrides&lt;/code&gt; and &lt;code&gt;:replace-paths&lt;/code&gt; taken from executed alias.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;:extra-paths&lt;/code&gt; allows you to add new paths when a specific alias is invoked. For example, if you have source code for all the tests in a specific &lt;code&gt;test&lt;/code&gt; folder, you can include it in a dedicated alias and not include it in other builds. &lt;code&gt;deps.edn&lt;/code&gt; will look similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:extra-paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                  &lt;/span&gt;&lt;span class="no"&gt;:main-opts&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-m"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"cognitect.test-runner"&lt;/span&gt;&lt;span class="p"&gt;]}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other pre-defined keys for this stage are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:classpath-overrides&lt;/code&gt; specifies a location to pull a dependency that overrides the path found during dependency resolution; for example, to replace a dependency with a local debug version.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:classpath-overrides&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org.clojure/clojure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"/my/clojure/target"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:replace-paths&lt;/code&gt;: a collection of string paths that will replace the ones in a &lt;code&gt;:paths&lt;/code&gt; key.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Running REPL with &lt;code&gt;clj -A&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;There is one more &lt;code&gt;clj&lt;/code&gt; option that can work with aliases that we haven't talked about yet.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clj -A&lt;/code&gt; runs REPL. If you invoke it with some alias, it will take into account all dependency-related and path-related predefined keys mentioned in the alias. There are no pre-defined keys that are specific only to the &lt;code&gt;-A&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;Let's say we have the following project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project-dir        
├─ src             
│  └─ core.clj
└─ test  
   └─ test_runner.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;core.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;print-hello&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Hello from core"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;test_runner.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test-runner&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;taoensso.timbre&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;print-hello&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;log/info&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Hello from test-runner"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;deps.edn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:test&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:extra-deps&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;com.taoensso/timbre&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"5.1.2"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="no"&gt;:extra-paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we start a REPL with the &lt;code&gt;clj&lt;/code&gt; command, we will be able to run something from &lt;code&gt;core&lt;/code&gt;, but won't be able to reach &lt;code&gt;test-runner&lt;/code&gt;, because &lt;code&gt;test&lt;/code&gt; folder is not in the &lt;code&gt;:paths&lt;/code&gt; key of &lt;code&gt;deps.edn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj
Clojure 1.10.3
&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;require &lt;span class="s1"&gt;'[core :as c])
nil
user=&amp;gt; (core/print-hello)
Hello from core
nil
user=&amp;gt; (require '&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;test-runner :as &lt;span class="nb"&gt;tr&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
Execution error &lt;span class="o"&gt;(&lt;/span&gt;FileNotFoundException&lt;span class="o"&gt;)&lt;/span&gt; at user/eval151 &lt;span class="o"&gt;(&lt;/span&gt;REPL:1&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Could not locate test_runner__init.class, test_runner.clj or test_runner.cljc on classpath. Please check that namespaces with dashes use underscores &lt;span class="k"&gt;in &lt;/span&gt;the Clojure file name.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if we run &lt;code&gt;clj -A:test&lt;/code&gt;, there won't be an error, because the&lt;code&gt;:extra-paths&lt;/code&gt; key in the alias adds a &lt;code&gt;test&lt;/code&gt; folder. Also, note that &lt;code&gt;test-runner&lt;/code&gt; can use the &lt;code&gt;taoensso.timbre&lt;/code&gt; library because that lib is listed in &lt;code&gt;:extra-deps&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clj &lt;span class="nt"&gt;-A&lt;/span&gt;:test
Clojure 1.10.3
&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;require &lt;span class="s1"&gt;'[core :as c])
nil
user=&amp;gt; (core/print-hello)
Hello from core
nil
user=&amp;gt; (require '&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;test-runner :as &lt;span class="nb"&gt;tr&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
nil
&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;tr&lt;/span&gt;/print-hello&lt;span class="o"&gt;)&lt;/span&gt;
2021-09-05T11:12:00.459Z MacBook-Pro.local INFO &lt;span class="o"&gt;[&lt;/span&gt;test-runner:5] - Hello from test-runner

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-world examples
&lt;/h2&gt;

&lt;p&gt;Let's analyze some real-world &lt;code&gt;deps.edn&lt;/code&gt; files to understand how they work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cognitect &lt;code&gt;test-runner&lt;/code&gt; setup
&lt;/h3&gt;

&lt;p&gt;We already mentioned &lt;a href="https://github.com/cognitect-labs/test-runner/" rel="noopener noreferrer"&gt;cognitect's test-runner&lt;/a&gt;  above. It is a library for discovering and running tests in your project.&lt;/p&gt;

&lt;p&gt;Its documentation suggests adding the following alias to your &lt;code&gt;deps.edn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:extra-paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="no"&gt;:extra-deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io.github.cognitect-labs/test-runner&lt;/span&gt;&lt;span class="w"&gt; 
                              &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"https://github.com/cognitect-labs/test-runner.git"&lt;/span&gt;&lt;span class="w"&gt;
                               &lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"8c3f22363d63715de4087b038d79ae0de36a3263"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="no"&gt;:main-opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-m"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"cognitect.test-runner"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="no"&gt;:exec-fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cognitect.test-runner.api/test&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:extra-paths&lt;/code&gt; says that &lt;code&gt;clj&lt;/code&gt; should consider the "test" folder to build our classpath when using the&lt;code&gt;:test&lt;/code&gt; alias.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:extra-deps&lt;/code&gt; specifies that the &lt;code&gt;test-runner&lt;/code&gt; library can be downloaded from github.&lt;/li&gt;
&lt;li&gt;having &lt;code&gt;:main-opts&lt;/code&gt; means that we can run tests using &lt;code&gt;clj -M:test ...args...&lt;/code&gt; Args description can be found on the documentation page.&lt;/li&gt;
&lt;li&gt;having &lt;code&gt;:exec-fn&lt;/code&gt; means that we can also run testing with &lt;code&gt;clj -X:test args-map&lt;/code&gt;. Args-map description can be found on the documentation page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;clj-new&lt;/code&gt; library setup
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/seancorfield/clj-new" rel="noopener noreferrer"&gt;&lt;code&gt;clj-new&lt;/code&gt; library&lt;/a&gt; allows you to generate new projects from templates. In contrast to the previous example, this time you suggested adding a new alias globally in &lt;code&gt;~/.clojure/deps.edn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:extra-deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;com.github.seancorfield/clj-new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.1.331"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="no"&gt;:exec-fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clj-new/create&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="no"&gt;:exec-args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;}}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:extra-deps&lt;/code&gt; says we can get &lt;code&gt;clj-new&lt;/code&gt; from Maven.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:exec-fn&lt;/code&gt; means that we can run the alias via &lt;code&gt;clj -X:new&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;and by defining alias in &lt;code&gt;~/.clojure/deps.edn&lt;/code&gt; you make it available in any folder on your system. So you can run something like &lt;code&gt;clojure -X:new :name myname/myapp&lt;/code&gt; to create &lt;code&gt;myapp&lt;/code&gt; project. Arguments &lt;code&gt;:name myname/myapp&lt;/code&gt; will be put in a map, merged with a map under &lt;code&gt;:exec-args&lt;/code&gt;, and passed to &lt;code&gt;clj-new/create&lt;/code&gt; function.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Other &lt;code&gt;clj&lt;/code&gt; capabilities
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;clj&lt;/code&gt; has a bunch of other functionality that you can explore by reading the output of &lt;code&gt;clj --help&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clj -Sdescribe&lt;/code&gt; will print environment info. In the output you can find the &lt;code&gt;:config-files&lt;/code&gt; key with a list of &lt;code&gt;deps.edn&lt;/code&gt; files used in the current run.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clj -Spath&lt;/code&gt; will print you the result classpath. Try running it with different aliases to figure out the impact on the resulting classpath; for example, by running with &lt;code&gt;:test&lt;/code&gt; alias: &lt;code&gt;clj -Spath -A:test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://clojure.org/reference/deps_and_cli" rel="noopener noreferrer"&gt;Deps and CLI Reference&lt;/a&gt; you will find a full explanation of &lt;code&gt;clj&lt;/code&gt; capabilities.&lt;br&gt;
In &lt;a href="https://clojure.org/guides/deps_and_cli" rel="noopener noreferrer"&gt;Deps and CLI Guide&lt;/a&gt; you can find a bunch of useful examples of &lt;code&gt;clj&lt;/code&gt; and &lt;code&gt;deps.edn&lt;/code&gt; usage, like running a socket server remote REPL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we've covered how &lt;code&gt;clj&lt;/code&gt;, &lt;code&gt;tools.deps&lt;/code&gt;, and &lt;code&gt;deps.edn&lt;/code&gt; work together. The key concept of "alias" is explained in different examples. Also, the process of building a classpath was reviewed in detail to provide a better understanding of how pre-defined keys from your aliases impact it.&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>cli</category>
    </item>
    <item>
      <title>Creating and publishing Clojure libraries</title>
      <dc:creator>Volodymyr Kozieiev</dc:creator>
      <pubDate>Sun, 31 Oct 2021 18:42:00 +0000</pubDate>
      <link>https://dev.to/kozieiev/creating-and-publishing-clojure-libraries-3kpp</link>
      <guid>https://dev.to/kozieiev/creating-and-publishing-clojure-libraries-3kpp</guid>
      <description>&lt;h2&gt;
  
  
  Table of contents:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Notes for readers&lt;/li&gt;
&lt;li&gt;Forms and locations of Clojure libraries&lt;/li&gt;
&lt;li&gt;Creating local library&lt;/li&gt;
&lt;li&gt;Creating git-based library&lt;/li&gt;
&lt;li&gt;Packaging library to a JAR file&lt;/li&gt;
&lt;li&gt;Installing JAR to local Maven repo&lt;/li&gt;
&lt;li&gt;Installing JAR to remote repo&lt;/li&gt;
&lt;li&gt;Modifying library to be suitable for ClojureScript&lt;/li&gt;
&lt;li&gt;&lt;a href="//#Addingpom.xmltolibraryroot"&gt;Adding pom.xml to library root&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Creating library project with &lt;code&gt;clj-new&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here we are going to create a Clojure library, pack it to a JAR file, deploy it to a Maven repository and make its code available from Clojure and ClojureScript projects. We will create the simplest project and will grow it step by step. At the end, we will discuss the &lt;code&gt;build-clj&lt;/code&gt; tool that can be used to create the library template projects. &lt;/p&gt;

&lt;h2&gt;
  
  
  Video version of this article
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/8aCO_wNuScQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes for readers
&lt;/h2&gt;

&lt;p&gt;Projects here are organized using &lt;code&gt;deps.edn&lt;/code&gt; configuration files.&lt;/p&gt;

&lt;p&gt;All examples in this post use single-segment namespaces, like &lt;code&gt;(ns basic-math)&lt;/code&gt;. It makes examples simpler but please don't use this approach for production code. Both Clojure and ClojureScript have subtle issues with single-segment namespaces. Also this can lead to name clashes when your library published and imported along with another library with the same name. So please use something like &lt;code&gt;(ns basic-math.core)&lt;/code&gt; or &lt;code&gt;(ns your-name/basic-math)&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;At the time of writing Clojure CLI with version &lt;code&gt;1.10.3.986&lt;/code&gt; was used on Mac.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forms and locations of Clojure libraries
&lt;/h2&gt;

&lt;p&gt;Clojure library can exist in a form of a source code or as a JAR file. JAR stands for "java-archive" and it is a zip-archive with all the library files - sources and resources.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tools.deps&lt;/code&gt; library that is used behind the scenes when we invoke &lt;code&gt;clj&lt;/code&gt; command has a concept of "&lt;a href="https://clojure.org/reference/deps_and_cli#_procurers"&gt;procurer&lt;/a&gt;". Each procurer knows how to download the library and its dependencies. Currently, three procurers exist: &lt;code&gt;local&lt;/code&gt;, &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;mvn&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;local&lt;/code&gt; procurer allows you to use a library from a local disk. It can be a folder with a source code or a JAR file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git&lt;/code&gt; procurer allows you to download a library source code from a git repository. Downloaded libraries will be stored in a local folder &lt;code&gt;~/.gitlibs&lt;/code&gt; by default.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mvn&lt;/code&gt; procurer gives access to the Maven repositories. These are storages of files widely used in a java-world. Libraries are stored there as JARs. When the library is downloaded from a remote Maven repo it is cached in a local repo on your disk. By default, it lives in &lt;code&gt;~/.m2/repository&lt;/code&gt;. Library JAR should be published to a Maven repo along with the &lt;code&gt;pom.xml&lt;/code&gt; file. It is a configuration file for the Maven that contains information about an artifact, for example, its name and version. More information about the POM files can be found in the &lt;a href="https://maven.apache.org/guides/introduction/introduction-to-the-pom.html"&gt;official documentation&lt;/a&gt;. &lt;br&gt;
Later in this article we will use Maven repository called &lt;a href="https://clojars.org/"&gt;Clojars&lt;/a&gt;. It is a community repo for open-source Clojure libraries.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating local library
&lt;/h2&gt;

&lt;p&gt;The simplest form of a library is a local folder with a source code. It can be referenced from another project by a relative path.&lt;/p&gt;

&lt;p&gt;As an example let's create a &lt;code&gt;test-lib&lt;/code&gt; that defines the simple &lt;code&gt;sum&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;The folder structure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;playground
└── test-lib
    ├── deps.edn
    └── src
        └── basic_math.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;test-lib/basic_math.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basic-math&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;test-lib/deps.edn&lt;/code&gt; contains an empty map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another project in a &lt;code&gt;playground&lt;/code&gt; folder will be the one that uses the &lt;code&gt;test-lib&lt;/code&gt;. Let's call it &lt;code&gt;adder&lt;/code&gt;. Its main function will take arbitrary number of arguments, sum them and print the result. &lt;/p&gt;

&lt;p&gt;Updated folder structure now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;playground
├── adder
│   ├── deps.edn
│   └── src
│       └── core.clj
└── test-lib
    ├── deps.edn
    └── src
        └── basic_math.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;adder/core.clj&lt;/code&gt; references &lt;code&gt;basic-math&lt;/code&gt; namespace from test library, uses the &lt;code&gt;sum&lt;/code&gt; function and prints the sum of arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basic-math&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Args sum: "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basic-math/sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Integer/parseInt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the content of &lt;code&gt;deps.edn&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;test-lib/test-lib&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:local/root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"../test-lib"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make &lt;code&gt;basic-math&lt;/code&gt; namespace available, &lt;code&gt;test-lib&lt;/code&gt; added under &lt;code&gt;:deps&lt;/code&gt; key and pointed to a local folder &lt;code&gt;../test-lib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that lib name should be qualified, so if you write &lt;code&gt;{test-lib {:local/root "../test-lib"}}&lt;/code&gt;, you'll get a warning. At the same time the name itself is not really important because later in the code we won't use it, we use only name of the namespace. So you can write &lt;code&gt;{any-name/any-name {:local/root "../test-lib"}}&lt;/code&gt; and that won't be an error.&lt;/p&gt;

&lt;p&gt;To check that library successfully used we can switch to &lt;code&gt;adder&lt;/code&gt; folder and run main function of &lt;code&gt;core&lt;/code&gt; namespace with couple arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;adder
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; core 1 2 3
Args &lt;span class="nb"&gt;sum&lt;/span&gt;:  6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating git-based library
&lt;/h2&gt;

&lt;p&gt;Libraries can be stored in a git. Let's push the lib from the previous section to the github and reuse it from there.&lt;/p&gt;

&lt;p&gt;First, let's create an empty github repo named &lt;code&gt;clojure-test-lib&lt;/code&gt;. After that we need to push there an already existing code of our library.&lt;/p&gt;

&lt;p&gt;Here is a series of commands to do this. &lt;strong&gt;Note&lt;/strong&gt;: you have to be inside the &lt;code&gt;test-lib&lt;/code&gt; folder when invoking them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;test-lib
&lt;span class="nv"&gt;$ &lt;/span&gt;git init
&lt;span class="nv"&gt;$ &lt;/span&gt;git add deps.edn
&lt;span class="nv"&gt;$ &lt;/span&gt;git add src/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"init"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-M&lt;/span&gt; main
&lt;span class="nv"&gt;$ &lt;/span&gt;git remote add origin https://github.com/YOUR-GITHUB-NAME/clojure-test-lib.git
&lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use the library from the github we need to update an &lt;code&gt;adder/deps.edn&lt;/code&gt; file. &lt;code&gt;:git/sha&lt;/code&gt; value can be taken from github. It specifies revision of library you want to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io.github.YOUR-GITHUB-NAME/clojure-test-lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"4c42a56d9dec002d5a198b61a5d8dcc30b69d3dc"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By contrast with referencing local libraries, here the library name is important. From that name the git url will be deducted for downloading the source code. List of possible library name formats can be found in the &lt;a href="https://clojure.org/reference/deps_and_cli#_coord_attributes"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now when we run the updated &lt;code&gt;adder&lt;/code&gt; app, we see the notification that our library was downloaded from git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;adder
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; core 1 2 3
Cloning: https://github.com/YOUR-GITHUB-NAME/clojure-test-lib.git
Checking out: https://github.com/YOUR-GITHUB-NAME/clojure-test-lib.git at 4c42a56d9dec002d5a198b61a5d8dcc30b69d3dc
Args &lt;span class="nb"&gt;sum&lt;/span&gt;:  6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use tags to make referencing of particular library version easier. Let's create one by running commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;test-lib
&lt;span class="nv"&gt;$ &lt;/span&gt;git tag &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s1"&gt;'v0.0.1'&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s1"&gt;'initial release'&lt;/span&gt; 
&lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;--tags&lt;/span&gt;   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;adder/deps.edn&lt;/code&gt; can be extended with &lt;code&gt;:git/tag&lt;/code&gt; key referencing our newly created tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io.github.YOUR-GITHUB-NAME/clojure-test-lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"v0.0.1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"4c42a5"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;:git/sha&lt;/code&gt; key still should exist but it can contain a brief version of &lt;code&gt;sha&lt;/code&gt; just to make sure that tag wasn't moved to other commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Packaging library to a JAR file
&lt;/h2&gt;

&lt;p&gt;Not so long ago you had to use 3rd-party tools to build JAR for own Clojure library. But now official &lt;a href="https://github.com/clojure/tools.build"&gt;&lt;code&gt;tools.build&lt;/code&gt;&lt;/a&gt; can be used to create project artificats.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tools.build&lt;/code&gt; itself is a Clojure library and it provides API that allows developers to run build actions from Clojure code. &lt;strong&gt;It is the core idea of the project that building process should be also written in Clojure and build scripts are just Clojure scripts.&lt;/strong&gt;  Examples can be found in an &lt;a href="https://clojure.org/guides/tools_build"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's use &lt;code&gt;tools.build&lt;/code&gt; to create JAR for our &lt;code&gt;test-lib&lt;/code&gt; project.&lt;/p&gt;

&lt;p&gt;First, we need to add build library to &lt;code&gt;test-lib/deps.edn&lt;/code&gt;. That file had empty map before and now should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io.github.clojure/tools.build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"v0.6.2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"226fb52"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;:ns-default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we created &lt;code&gt;build&lt;/code&gt; alias that uses dependency on &lt;code&gt;tools.build&lt;/code&gt; when invoked. That alias should be used as a tool, with &lt;code&gt;-T&lt;/code&gt; option when running &lt;code&gt;clj&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;By providing &lt;code&gt;:ns-default build&lt;/code&gt; we tell that all commands passed to this alias will be found in the &lt;code&gt;build&lt;/code&gt; namespace. So if we run &lt;code&gt;clj -T:build clean&lt;/code&gt;, the &lt;code&gt;(clean)&lt;/code&gt; function from &lt;code&gt;build.clj&lt;/code&gt; file will run.&lt;/p&gt;

&lt;p&gt;Now it is time to create the &lt;code&gt;build.clj&lt;/code&gt; file itself. It is placed in a root of &lt;code&gt;test-lib&lt;/code&gt; project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;playground
├── adder
│   └── ...
└── test-lib
    ├── build.clj      &amp;lt;---
    ├── deps.edn
    └── src
        └── basic_math.clj

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the content of &lt;code&gt;build.clj&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.tools.build.api&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;'com.github.YOUR-GITHUB-NAME/clojure-test-lib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.0.%s"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/git-count-revs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;class-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"target/classes"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/create-basis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"deps.edn"&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"target/%s-%s.jar"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/write-pom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:class-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;class-dir&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="no"&gt;:lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="no"&gt;:version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="no"&gt;:basis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basis&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="no"&gt;:src-dirs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/copy-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:src-dirs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="no"&gt;:target-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;class-dir&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/jar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:class-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;class-dir&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;:jar-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-file&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the top of the file we require an API from &lt;code&gt;tools.build&lt;/code&gt; library. Than go few declared vars:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;lib&lt;/code&gt; - fully qualified name of our library. &lt;strong&gt;Note&lt;/strong&gt;: here we used &lt;code&gt;com.github.YOUR-GITHUB-NAME&lt;/code&gt; as an organization part of the name. But you are free to use any, without mentioning github. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;version&lt;/code&gt; - lib's version. In this code versioning depends on amount of git commits made so far. So after every commit your version will bump.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;class-dir&lt;/code&gt; - folder were we put all files that will go to a JAR file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;basis&lt;/code&gt; - it is a clojure map with all project settings obtained from project &lt;code&gt;deps.edn&lt;/code&gt; and its parents. Probably the most important among them are classpath and dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jar-file&lt;/code&gt; - name of result JAR file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are two declared functions in a &lt;code&gt;build.clj&lt;/code&gt;. &lt;code&gt;(clean)&lt;/code&gt; removes our build directory. And &lt;code&gt;(jar)&lt;/code&gt; does the main work - fills the build directory with all required files and creates a JAR file with our library.&lt;/p&gt;

&lt;p&gt;There are 3 calls to the &lt;code&gt;tools.build&lt;/code&gt; inside the  &lt;code&gt;(jar)&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;(b/write-pom)&lt;/code&gt; - creates a &lt;code&gt;pom.xml&lt;/code&gt; file inside the build directory. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(b/copy-dir)&lt;/code&gt; - copies the source files and the resources (if we'd have any) to a build directory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(b/jar)&lt;/code&gt; - packs the content of a build directory to a JAR file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now when everything is ready we can generate JAR file for our library with commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;test-lib
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build jar
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;target
classes                    clojure-test-lib-0.0.1.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our library now stored in &lt;code&gt;test-lib/target/clojure-test-lib-0.0.1.jar&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lets change &lt;code&gt;adder/deps.edn&lt;/code&gt; to use the library from the local jar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;com.github.YOUR-GITHUB-NAME/clojure-test-lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:local/root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"../test-lib/target/clojure-test-lib-0.0.1.jar"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run the &lt;code&gt;adder&lt;/code&gt; again to make sure everything works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;adder
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; core 1 2 3
Args &lt;span class="nb"&gt;sum&lt;/span&gt;:  6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/volodymyrk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_4tnISpR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7v0zsd3bxcdkmmeogot3.png" alt="Image description" width="273" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing JAR to local Maven repo
&lt;/h2&gt;

&lt;p&gt;Now we have a JAR file but referencing it by relative path doesn't look nice. Ideally we'd like to have it in some remote Maven repo. But before lets install it in a local repo - &lt;code&gt;~/.m2/repository&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;To do this we'll add a new function to the &lt;code&gt;test-lib/build.clj&lt;/code&gt; called &lt;code&gt;(install)&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="c1"&gt;; ... previous content of build.clj ...&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:basis&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;basis&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="no"&gt;:lib&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="no"&gt;:version&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="no"&gt;:jar-file&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;jar-file&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="no"&gt;:class-dir&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;class-dir&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside our new function we call a function with the same name from the &lt;code&gt;tools.build&lt;/code&gt; library that does actual work. &lt;/p&gt;

&lt;p&gt;Now we can create and install JAR of our test library with commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;test-lib
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build clean
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build jar
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To check that the library was added to the local repo we can inspect the local folder &lt;code&gt;~/.m2/repository/com/github/YOUR-GITHUB-NAME/clojure-test-lib/&lt;/code&gt;. There should be our JAR inside the folder for version &lt;code&gt;0.0.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now &lt;code&gt;adder/deps.edn&lt;/code&gt; should be changed to use library from maven repo instead of local JAR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:paths&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;com.github.YOUR-GITHUB-NAME/clojure-test-lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.0.1"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's run &lt;code&gt;adder&lt;/code&gt; again to confirm that changes work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;adder
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; core 1 2 3
Args &lt;span class="nb"&gt;sum&lt;/span&gt;:  6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing JAR to remote repo
&lt;/h2&gt;

&lt;p&gt;Now it is a time to make our extremely useful library publicly available. We want to push it to the &lt;a href="https://clojars.org/"&gt;Clojars&lt;/a&gt;. As you probably already guessed, we are going to add a new function to &lt;code&gt;deps-edn/build.clj&lt;/code&gt; that will be responsible for this action. It will be named &lt;code&gt;(deploy)&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Unfortunately the standard &lt;code&gt;tools.build&lt;/code&gt; library that we were using before doesn't provide functionality to deploy to Clojars. So we will use a 3rd-party library called &lt;a href="https://github.com/slipset/deps-deploy"&gt;&lt;code&gt;deps-deploy&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's add it as another dependency of the &lt;code&gt;build&lt;/code&gt; alias in the &lt;code&gt;test-lib/deps.edn&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io.github.clojure/tools.build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:git/tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"v0.6.2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:git/sha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"226fb52"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="n"&gt;slipset/deps-deploy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"RELEASE"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;                            &lt;/span&gt;&lt;span class="c1"&gt;; &amp;lt;-- new dependency&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;:ns-default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changes to the &lt;code&gt;test-lib/build.clj&lt;/code&gt; add the new &lt;code&gt;(deploy)&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.tools.build.api&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;deps-deploy.deps-deploy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;; &amp;lt;--- don't foget to add a new require&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;; ... previous content of build.clj ...&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dd/deploy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:installer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:remote&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="no"&gt;:artifact&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jar-file&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="no"&gt;:pom-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;b/pom-path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:class-dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;class-dir&lt;/span&gt;&lt;span class="p"&gt;})}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, our &lt;code&gt;(deploy)&lt;/code&gt; function relies on the function with the same name from &lt;code&gt;deps-deploy&lt;/code&gt; package. Being invoked it will take the JAR file and &lt;code&gt;pom.xml&lt;/code&gt; and publish them to Clojars. &lt;code&gt;(b/pom-path)&lt;/code&gt; is a helper function from &lt;code&gt;tools.build&lt;/code&gt; that retuns path to the &lt;code&gt;pom.xml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before you will be able to publish anything to the Clojars, you need to go to &lt;a href="https://clojars.org/"&gt;clojars.org&lt;/a&gt;, create an account there and add a "deploy token". It is used in a place of a password when deploying from the command line. &lt;/p&gt;

&lt;p&gt;When you've created an account and a deploy token, deploying the lib will be as simple as running our newly created build command with couple additionl environment variables set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;env &lt;/span&gt;&lt;span class="nv"&gt;CLOJARS_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;USER-NAME &lt;span class="nv"&gt;CLOJARS_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CLOJARS_XXXXXXXX clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CLOJARS_USERNAME&lt;/code&gt; - your Clojars account name&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CLOJARS_PASSWORD&lt;/code&gt; - your created deploy token. &lt;strong&gt;Not a login password.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After executing previous command you should see the shell messages saying that *.jar and *.pom were successfully uploaded to Clojars. Also you will see a new library on the Clojars dashboard.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;adder/deps.edn&lt;/code&gt; doesn't need to be changed, because the way we reference &lt;code&gt;test-lib&lt;/code&gt; dependency is the same for local and remote Maven repos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modifying library to be suitable for ClojureScript
&lt;/h2&gt;

&lt;p&gt;Our &lt;code&gt;test-lib&lt;/code&gt; contains pure Clojure code and doesn't depend on anything Java-specific, so it would be nice to make it available for ClojureScript as well.&lt;/p&gt;

&lt;p&gt;At first, let's create a simple ClojureScript project called &lt;code&gt;adder-cljs&lt;/code&gt; and try to use &lt;code&gt;test-lib&lt;/code&gt; as is.&lt;/p&gt;

&lt;p&gt;Here is a structure of the new project created in the &lt;code&gt;playground&lt;/code&gt; folder on the same level as the already existing &lt;code&gt;adder&lt;/code&gt; and &lt;code&gt;test-lib&lt;/code&gt; projects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adder-cljs
├── deps.edn
└── src
    └── core.cljs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;core.cljs&lt;/code&gt; implements the same logic that we had before in the &lt;code&gt;adder/src/core.clj&lt;/code&gt;. The only difference is that we use the &lt;code&gt;js/parseInt&lt;/code&gt; for turning arguments to integers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basic-math&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Args sum: "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basic-math/sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;js/parseInt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;adder-cljs/deps.edn&lt;/code&gt; contains dependencies for ClojureScript itself and our &lt;code&gt;test-lib&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org.clojure/clojurescript&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.10.879"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;com.github.YOUR-GITHUB-NAME/clojure-test-lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.0.1"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command for running the script from a terminal will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; cljs.main &lt;span class="nt"&gt;-re&lt;/span&gt; node &lt;span class="nt"&gt;-m&lt;/span&gt; core 1 2 3  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And as a result we will get an exception:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Unexpected error &lt;span class="o"&gt;(&lt;/span&gt;ExceptionInfo&lt;span class="o"&gt;)&lt;/span&gt; compiling at &lt;span class="o"&gt;(&lt;/span&gt;REPL:1&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
No such namespace: basic-math, could not locate basic_math.cljs, basic_math.cljc, or JavaScript &lt;span class="nb"&gt;source &lt;/span&gt;providing &lt;span class="s2"&gt;"basic-math"&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;Please check that namespaces with dashes use underscores &lt;span class="k"&gt;in &lt;/span&gt;the ClojureScript file name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;file core.cljs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It says that &lt;code&gt;basic-math&lt;/code&gt; can't be found because it is not in a &lt;em&gt;.cljs or *.cljc file. As we remember &lt;code&gt;test_lib&lt;/code&gt; keeps this namespace in the &lt;code&gt;basic_math.clj&lt;/code&gt;. **Fortunately the only change we need to make clojure code usable from both Clojure and ClojureScript is simply store it in *.cljc file.&lt;/em&gt;* More sophisticated libraries can also use "reader conditionals" to add the Clojure- or ClojureScript-specific expressions to the code. More info can be found in the &lt;a href="https://clojure.org/guides/reader_conditionals"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So let's rename &lt;code&gt;test-lib/src/basic_math.clj&lt;/code&gt; to &lt;code&gt;test-lib/src/basic_math.cljc&lt;/code&gt; and publish a new version of the library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;test-lib
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;src/basic_math.clj src/basic_math.cljc
&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"make library usable for ClojureScript"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build clean
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build jar
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;env &lt;/span&gt;&lt;span class="nv"&gt;CLOJARS_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;USER-NAME &lt;span class="nv"&gt;CLOJARS_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CLOJARS_XXXXXXXX clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you remember, &lt;code&gt;build.clj&lt;/code&gt; file of our library uses commits count for changing version name. This is why we've made a commit here before deploying the library.&lt;/p&gt;

&lt;p&gt;As a result, version &lt;code&gt;0.0.2&lt;/code&gt; of our library now should be pushed to the Clojars.&lt;/p&gt;

&lt;p&gt;To use it let's change &lt;code&gt;adder-cljs/deps.edn&lt;/code&gt; and bump library version there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;org.clojure/clojurescript&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1.10.879"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;com.github.YOUR-GITHUB-NAME/clojure-test-lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:mvn/version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0.0.2"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;; !!!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run &lt;code&gt;adder-cljs&lt;/code&gt; again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-M&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; cljs.main &lt;span class="nt"&gt;-re&lt;/span&gt; node &lt;span class="nt"&gt;-m&lt;/span&gt; core 1 2 3
Args &lt;span class="nb"&gt;sum&lt;/span&gt;:  6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding pom.xml to library root
&lt;/h2&gt;

&lt;p&gt;Up to now the  &lt;code&gt;pom.xml&lt;/code&gt; file for our library was generated automatically by a call to the &lt;code&gt;(write-pom)&lt;/code&gt; function in the &lt;code&gt;test-lib/build.clj&lt;/code&gt; and stored in the temporary &lt;code&gt;target&lt;/code&gt; folder. Drawback of this is that we can't add any persistent changes to this file because they will be wiped out when &lt;code&gt;clj -T:bulid clean&lt;/code&gt; invoked.  But fortunately &lt;code&gt;(write-pom)&lt;/code&gt; is clever enough and if you have some &lt;code&gt;pom.xml&lt;/code&gt; file in the root of the project, it will be taken as a basis and merged with a generated one.&lt;/p&gt;

&lt;p&gt;Let's use this feature to add a description and a homepage url to our library so they can be seen on the Clojars page.&lt;/p&gt;

&lt;p&gt;First, let's go to the &lt;code&gt;test-lib&lt;/code&gt; directory and copy an already generated &lt;code&gt;pom.xml&lt;/code&gt; to the root of a project for future modification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;test-lib
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;target/classes/META-INF/maven/com.github.YOUR-GITHUB-NAME/clojure-test-lib/pom.xml &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we are going to modify the new &lt;code&gt;pom.xml&lt;/code&gt;. We want to replace the actual version of the library with "VERSION" placeholder just to avoid future confusion. Also the &lt;code&gt;description&lt;/code&gt; and &lt;code&gt;url&lt;/code&gt; fields need to be added. Here is an updated content of the &lt;code&gt;pom.xml&lt;/code&gt;, slightly truncated for readability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;project&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://maven.apache.org/POM/4.0.0"&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt; &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;modelVersion&amp;gt;&lt;/span&gt;4.0.0&lt;span class="nt"&gt;&amp;lt;/modelVersion&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;packaging&amp;gt;&lt;/span&gt;jar&lt;span class="nt"&gt;&amp;lt;/packaging&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.github.YOUR-GITHUB-NAME&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;clojure-test-lib&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;VERSION&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;                                               &lt;span class="c"&gt;&amp;lt;!-- changed --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;clojure-test-lib&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;Test library for article on Clojure libraries&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- added --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;https://github.com/YOUR-GITHUB-NAME/clojure-test-lib&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;          &lt;span class="c"&gt;&amp;lt;!-- added --&amp;gt;&lt;/span&gt;
  .....
&lt;span class="nt"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now let's commit these changes and push the updated library to the Clojars:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;test-lib
&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Added root pom.xml with description and homepage url"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build clean
&lt;span class="nv"&gt;$ &lt;/span&gt;clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build jar
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;env &lt;/span&gt;&lt;span class="nv"&gt;CLOJARS_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;USER-NAME &lt;span class="nv"&gt;CLOJARS_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CLOJARS_XXXXXXXX clj &lt;span class="nt"&gt;-T&lt;/span&gt;:build deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when we go to Clojars, on the page of our library we can see that the version number was bumped, description added and there is a link to our homepage. That means that the &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; fields of root &lt;code&gt;pom.xml&lt;/code&gt; were successfully used and merged with the generated fields like &lt;code&gt;version&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating library project with &lt;code&gt;clj-new&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;So far to setup the &lt;code&gt;test-lib&lt;/code&gt; project we've made the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;added dependencies for &lt;code&gt;tools.build&lt;/code&gt; and &lt;code&gt;deps-deploy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;created the &lt;code&gt;build.clj&lt;/code&gt;  with own build commands&lt;/li&gt;
&lt;li&gt;added the root &lt;code&gt;pom.xml&lt;/code&gt; file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These steps aren't unique for the &lt;code&gt;test-lib&lt;/code&gt; and you'll need to repeat them again when creating another libraries. Fortunately, there is a project called  &lt;a href="https://github.com/seancorfield/clj-new"&gt;&lt;code&gt;clj-new&lt;/code&gt;&lt;/a&gt; that will save you from doing similar work again and again.&lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;clj-new&lt;/code&gt; you can generate a project template that already equipped with all the features we've discussed and even more.&lt;/p&gt;

&lt;p&gt;Here we'll cover the basic steps to create a library with &lt;code&gt;clj-new&lt;/code&gt; but please go and read the &lt;a href="https://github.com/seancorfield/clj-new"&gt;official docs&lt;/a&gt; for the detailed instructions and up to date version of the library. &lt;/p&gt;

&lt;p&gt;First, we need to install the &lt;code&gt;clj-new&lt;/code&gt; as a tool to make it available for use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clojure &lt;span class="nt"&gt;-Ttools&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;com.github.seancorfield/clj-new &lt;span class="s1"&gt;'{:git/tag "v1.2.362"}'&lt;/span&gt; :as clj-new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to create a library we need to run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;clojure &lt;span class="nt"&gt;-Tclj-new&lt;/span&gt; lib :name com.github.YOUR-GITHUB-NAME/clojure-test-lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that we'll get the library template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clojure-test-lib
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build.clj
├── deps.edn
├── doc
│   └── intro.md
├── pom.xml
├── resources
├── src
│   └── YOUR-GITHUB-NAME
│       └── clojure_test_lib.clj
└── test
    └── YOUR-GITHUB-NAME
        └── clojure_test_lib_test.clj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please take a look at &lt;code&gt;build.clj&lt;/code&gt; file that contains available build commands. Note, that the command for creating a JAR file called here &lt;code&gt;ci&lt;/code&gt; (which stands for "continuous integration"), because it doesn't only create a JAR but also runs tests. &lt;/p&gt;

&lt;p&gt;Also please read the &lt;code&gt;README.md&lt;/code&gt; file. It has the examples of the build commands and an important note that you have to fix the existing test to get a successfull build ;)&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>library</category>
      <category>clojars</category>
      <category>maven</category>
    </item>
  </channel>
</rss>
