343 lines
24 KiB
HTML
343 lines
24 KiB
HTML
<!DOCTYPE html>
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||
<head>
|
||
<meta charset="utf-8"/>
|
||
<title>Clojure Guides: Library Development and Distribution</title>
|
||
|
||
|
||
<meta name="description" content="This short guide covers how to create your own typical pure Clojure
|
||
library and distribute it to the community via Clojars. It uses
|
||
Clojure 1.4 and Leiningen 2.0-previewX, and requires you have git
|
||
installed (though very little familiarity with git is required).It's assumed that you're already somewhat familiar with Clojure. If
|
||
not, see the Getting Started and
|
||
Introduction guides.">
|
||
|
||
<meta property="og:description" content="This short guide covers how to create your own typical pure Clojure
|
||
library and distribute it to the community via Clojars. It uses
|
||
Clojure 1.4 and Leiningen 2.0-previewX, and requires you have git
|
||
installed (though very little familiarity with git is required).It's assumed that you're already somewhat familiar with Clojure. If
|
||
not, see the Getting Started and
|
||
Introduction guides.">
|
||
|
||
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/libraries_authoring/" />
|
||
<meta property="og:title" content="Library Development and Distribution" />
|
||
<meta property="og:type" content="article" />
|
||
|
||
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/libraries_authoring/">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
|
||
type="text/css">
|
||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
|
||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
|
||
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
|
||
</head>
|
||
<body>
|
||
|
||
|
||
<nav class="navbar navbar-default">
|
||
<div class="container">
|
||
<div class="navbar-header">
|
||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||
<span class="sr-only">Toggle navigation</span>
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
</button>
|
||
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
|
||
</div>
|
||
<div id="navbar" class="navbar-collapse collapse">
|
||
<ul class="nav navbar-nav navbar-right">
|
||
<li ><a href="../../../index.html">Home</a></li>
|
||
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
|
||
</ul>
|
||
</div><!--/.nav-collapse -->
|
||
</div><!--/.container-fluid -->
|
||
</nav>
|
||
|
||
|
||
<div class="container">
|
||
|
||
|
||
<div class="row">
|
||
<div class="col-lg-9">
|
||
<div id="content">
|
||
|
||
<div id="custom-page">
|
||
<div id="page-header">
|
||
<h2>Library Development and Distribution</h2>
|
||
</div>
|
||
|
||
<p>This short guide covers how to create your own typical pure Clojure
|
||
library and distribute it to the community via Clojars. It uses
|
||
Clojure 1.4 and Leiningen 2.0-previewX, and requires you have git
|
||
installed (though very little familiarity with git is required).</p><p>It's assumed that you're already somewhat familiar with Clojure. If
|
||
not, see the <a href="https://clojure-doc.org/articles/ecosystem/libraries_authoring/getting_started/">Getting Started</a> and
|
||
<a href="https://clojure-doc.org/articles/ecosystem/libraries_authoring/introduction/">Introduction</a> guides.</p><p>For the purposes of this guide, the library we'll be making is named
|
||
"<a href="https://clojars.org/trivial-library-example">trivial-library-example</a>".</p><p>This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
|
||
Attribution 3.0 Unported License</a> (including images &
|
||
stylesheets). The source is available <a href="https://github.com/clojure-doc/clojure-doc.github.io">on
|
||
Github</a>.</p><h2 id="create-the-project">Create the Project</h2><p>Create your new library project. Names are usually hyphen-separated
|
||
lowercase words:</p><pre><code>lein new trivial-library-example
|
||
cd trivial-library-example
|
||
</code></pre><p>Typical lein usage is <code>lein new <proj-type> <proj-name></code>, but if you
|
||
leave out <code><proj-type></code> (as we've done above), lein defaults to
|
||
creating a library project for you.</p><p>Our trivial library example project will have a dependency on
|
||
<a href="https://clojars.org/org.flatland/useful">flatland's "useful"</a>
|
||
library.</p><p>Open up our new project.clj file and make a few changes:</p><ol><li>Add our dependency (<code>[org.flatland/useful "0.9.0"]</code>) to the <code>:dependencies</code> vector.</li><li>Remove "-SNAPSHOT" from version string.</li><li>Write a short description.</li><li>Add a url (if not a homepage, then where it's source is hosted online).</li><li>If you're using a different license, change the value for <code>:license</code>.</li></ol><p>Regarding your choice of license, probably the three most common for
|
||
Clojure libs (along with a grossly oversimplified blurb (by this
|
||
author) for each) are:</p><ul><li>The <a href="http://directory.fsf.org/wiki/License:EPLv1.0">Eclipse Public License</a> (the default).</li><li>The <a href="http://www.gnu.org/licenses/lgpl.html">LGPL</a> (focused most on
|
||
code and additions always being free; includes language addressing
|
||
s/w patent concerns). See the <a href="http://www.gnu.org/licenses/license-recommendations.html">FSF's recommendations</a> and their
|
||
<a href="http://www.gnu.org/licenses/gpl-howto.html">instructions for use</a>.</li><li>The <a href="http://opensource.org/licenses/MIT">MIT</a> License (focused most on the user's freedom to do what
|
||
they want with the code). The FSF calls this the <a href="http://directory.fsf.org/wiki/License:Expat">"Expat"
|
||
License</a>.</li></ul><p>Whichever one you choose, update your project.clj (if necessary) to
|
||
reflect that choice and save the text of the license as a file named
|
||
"LICENSE" or "COPYING" in your project directory.</p><h3 id="a-note-regarding-project-naming">A Note Regarding Project Naming</h3><p>The top line of your project.clj includes something like <code>defproject my-project-name</code>. This means that your project has an <em>artifact-id</em>
|
||
of "my-project-name", but it also implies a <em>group-id</em> of
|
||
"my-project-name" (group-id = artifact-id).</p><p>The artifact-id is the name of your project. The group-id is used for
|
||
namespacing (not the same thing as Clojure namespaces) --- it
|
||
identifies to which group/organization a project belongs. Some
|
||
examples of group-id's: clojurewerkz, sonian, and org.<em>your-domain</em>.</p><p>You may choose to explicitly use a group-id for your project, if you
|
||
like. For example:</p><pre><code>(defproject org.my-domain/my-project-name ...
|
||
...)
|
||
</code></pre><p>The maintainers of Clojars
|
||
<a href="https://github.com/clojars/clojars-web/wiki/Verified-Group-Names">require that new libs be published using verified groups</a>,
|
||
such as org.my-domain.</p><p>Read more about groups at
|
||
<a href="https://github.com/clojars/clojars-web/wiki/Groups">https://github.com/clojars/clojars-web/wiki/Groups</a>.</p><h2 id="update-the-readme">Update the README</h2><p>Aside from providing a good overview, rationale, and introduction at
|
||
the top, you're encouraged to provide some usage examples as well. A
|
||
link to the lib's (future) Clojars page (which we'll get to below)
|
||
might also be appreciated. Add acknowledgements near the end, if
|
||
appropriate. Adjust the copyright and license info at the bottom of
|
||
the README as needed.</p><p>Lein provides you with a doc directory and a starter doc/intro.md
|
||
file. If you find that you have more to say than will comfortably fit
|
||
into the README.md, consider moving content into the doc dir.</p><p>Other goodies you might include in your README.md or doc/*.md files:
|
||
tutorial, news, bugs, limitations, alternatives, troubleshooting,
|
||
configuration.</p><p>Note that you generally won't add hand-written API documentation into
|
||
your readme or other docs, as there are tools for creating that
|
||
directly from your source (discussed later).</p><h2 id="create-your-projects-local-git-repository">Create your project's local git repository</h2><p>Before going much further, you probably want to get your project under
|
||
version control. Make sure you've got git installed and configured to
|
||
know your name and email address (i.e., that at some point you've run
|
||
<code>git config --global user.name "Your Name"</code> and <code>git config --global user.email "your-email@somewhere.org"</code>).</p><p>Then, in your project dir, run:</p><pre><code>git init
|
||
git add .
|
||
git commit -m "The initial commit."
|
||
</code></pre><p>At any time after you've made changes and want to inspect them and
|
||
commit them to the repository:</p><pre><code>git diff
|
||
git add -p
|
||
git commit -m "The commit message."
|
||
</code></pre><h2 id="write-tests">Write Tests</h2><p>In test/trivial_library_example/core_test.clj, add tests as needed.
|
||
An example is provided in there to get you started.</p><h2 id="write-code">Write Code</h2><p>Write code to make your tests pass.</p><p>Remember to add a note at the top of each file indicating copyright
|
||
and the license under which the code is distributed.</p><h2 id="run-tests">Run Tests</h2><p>In your project dir:</p><pre><code>lein test
|
||
</code></pre><h2 id="commit-any-remaining-changes">Commit any remaining changes</h2><p>Before continuing to the next step, make sure all tests pass and
|
||
you've committed all your changes. Check to see the status of your
|
||
repo at any time with <code>git status</code> and view changes with <code>git diff</code>.</p><h2 id="create-github-project-and-upload-there">Create github project and Upload there</h2><p>This guide makes use of <a href="https://github.com/">github</a> to host your
|
||
project code. If you don't already have a github account, create one,
|
||
then log into it. Github provides good documentation on how to <a href="https://help.github.com/articles/set-up-git">get
|
||
started</a> and how to
|
||
<a href="https://help.github.com/articles/generating-ssh-keys">create an SSH key
|
||
pair</a>. If you
|
||
haven't already done so, get that set up before continuing.</p><p>Create a new repo there for your project using the icon/button/link
|
||
near the top-right.</p><blockquote><p>You will have your local repository, and also a remote duplicate of
|
||
it at github.</p></blockquote><p>For the repository name, use the same name as your project directory.
|
||
Provide a one-line description and hit "Create repository".</p><p>Once this remote repo has been created, follow the instructions on the
|
||
resulting page to "Push an existing repository from the command
|
||
line". You'll of course run the <code>git</code> commands from your project
|
||
directory:</p><pre><code>git remote add origin git@github.com:uvtc/trivial-library-example.git
|
||
git push -u origin master
|
||
</code></pre><p>You can now access your online repo. For this tutorial, it's
|
||
<a href="https://github.com/uvtc/trivial-library-example">https://github.com/uvtc/trivial-library-example</a>.</p><p>Any changes you commit to your local repository can now be pushed
|
||
to the remote one at github:</p><pre><code class="bash"># work work work
|
||
git add -p
|
||
git commit -m "commit message here"
|
||
git push
|
||
</code></pre><h2 id="create-a-gpg-key-for-signing-your-releases">Create a GPG key for signing your releases</h2><p>You'll need to create a <a href="http://www.gnupg.org/">gpg</a> key pair, which
|
||
will be used by lein to sign any release you make to Clojars. Make
|
||
sure you've got gpg installed and kick the tires:</p><pre><code>gpg --list-keys
|
||
</code></pre><p>(The first time that command is run, you'll see some notices about
|
||
it creating necessary files in your home dir.)</p><p>To create a key pair:</p><pre><code>gpg --gen-key
|
||
</code></pre><p>Take the default key type (RSA and RSA), and default key size (2048).
|
||
When asked for how long the key should remain valid, choose a year or
|
||
two. Give it your real name and email address. When it prompts you for
|
||
a comment, you might add one as it can be helpful if you have multiple
|
||
keys to keep track of. When prompted for a passphrase, come up with one
|
||
that is different from the one used with your ssh key.</p><p>When gpg has completed generating your keypair, you can have it list
|
||
what keys it knows about:</p><pre><code>gpg --list-keys
|
||
</code></pre><p>We'll use that public key in the next section.</p><h2 id="upload-to-clojars">Upload to Clojars</h2><p>If you don't already have an account at <a href="https://clojars.org/">https://clojars.org/</a>, create
|
||
one. After doing so, you'll need to supply your ssh and gpg public
|
||
keys to Clojars. For the ssh public key, you can use the same one as
|
||
used with github. For the gpg public key, get it by running:</p><pre><code>gpg --export -a <your-key-id>
|
||
</code></pre><p>where <code><your-key-id></code> is in the output of <code>gpg --list-keys</code> (the
|
||
8-character part following the forward slash on the line starting with
|
||
"pub"). Copy/paste that output (including the "-----BEGIN PGP PUBLIC
|
||
KEY BLOCK-----" and "-----END PGP PUBLIC KEY BLOCK-----") into the
|
||
form on your Clojars profile page.</p><p>For more info on working with Clojars, see <a href="https://github.com/clojars/clojars-web/wiki/About">the Clojars
|
||
wiki</a>.</p><p>Once your Clojars account is all set up, and it has your public keys,
|
||
upload your library to Clojars like so:</p><pre><code>lein deploy clojars
|
||
</code></pre><p>You will be asked for your (Clojars) username and password.</p><p>Then you'll be asked for your gpg passphrase. (You won't be asked for
|
||
your ssh passphrase because <code>lein deploy clojars</code> uses http rather
|
||
than scp --- though Clojars supports both.)</p><p>You should now be able to see your lib's Clojars page: for example,
|
||
<a href="https://clojars.org/trivial-library-example">https://clojars.org/trivial-library-example</a>!</p><h2 id="generate-api-docs-optional">Generate API docs (optional)</h2><p>For larger library projects, you may want to automatically generate
|
||
API docs (from your docstrings). See
|
||
<a href="https://github.com/weavejester/codox">codox</a>. If your library project
|
||
is hosted at github, you can use <a href="http://pages.github.com/">github
|
||
pages</a> to host the resulting docs.</p><h2 id="announce-optional">Announce (optional)</h2><p>You're welcome to announce the availability of your new library
|
||
on the <a href="https://groups.google.com/forum/?fromgroups#!forum/clojure">Clojure Mailing List</a>.</p><h2 id="make-updates-to-your-library">Make Updates to your library</h2><p>Making updates to your lib follows the same pattern as described above:</p><pre><code class="bash"># work test work test
|
||
# update version string in project.clj
|
||
git add -p
|
||
git commit
|
||
git push
|
||
lein deploy clojars
|
||
</code></pre><p>And optionally announce the release on the ML.</p><h3 id="merging-pull-requests">Merging pull-requests</h3><p>Note that if you receive a pull-request at github, you can easily
|
||
merge those changes into your project (right there, via the web page
|
||
describing the pull-request). Afterwards, update your local repo to
|
||
grab those changes as well:</p><pre><code>git pull
|
||
</code></pre><h2 id="see-also">See Also</h2><p>For more detailed documentation on various aspects of the procedures
|
||
described here, see:</p><ul><li>the <a href="https://github.com/clojars/clojars-web/wiki">Clojars wiki</a></li><li>the
|
||
<a href="https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md">Leiningen tutorial</a>
|
||
and <a href="https://github.com/technomancy/leiningen/blob/master/doc/DEPLOY.md">deploy
|
||
guide</a></li></ul><h2 id="contributors">Contributors</h2><p>John Gabriele <a href="mailto:jmg3000@gmail.com">jmg3000@gmail.com</a> (original author)</p>
|
||
|
||
<div id="prev-next">
|
||
|
||
<a href="../libraries_directory/index.html">« A Directory of Clojure Libraries</a>
|
||
|
||
|
||
||
|
||
|
||
|
||
<a href="../generating_documentation/index.html">Generating Documentation »</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-md-3">
|
||
<div id="sidebar">
|
||
<h3>Links</h3>
|
||
<ul id="links">
|
||
|
||
<li><a href="../../about/index.html">About</a></li>
|
||
|
||
<li><a href="../../content/index.html">Table of Contents</a></li>
|
||
|
||
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
|
||
|
||
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
|
||
|
||
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
|
||
|
||
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
|
||
|
||
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
|
||
|
||
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
|
||
|
||
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
|
||
|
||
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
|
||
|
||
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
|
||
|
||
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
|
||
|
||
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
|
||
|
||
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
|
||
|
||
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
|
||
|
||
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
|
||
|
||
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
|
||
|
||
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
|
||
|
||
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
|
||
|
||
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
|
||
|
||
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
|
||
|
||
<li><a href="index.html">Library Development and Distribution</a></li>
|
||
|
||
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
|
||
|
||
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
|
||
|
||
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
|
||
|
||
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
|
||
|
||
<li><a href="../community/index.html">Clojure Community</a></li>
|
||
|
||
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
|
||
|
||
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
|
||
|
||
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
|
||
|
||
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
|
||
|
||
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
|
||
|
||
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
|
||
|
||
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
|
||
|
||
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
|
||
|
||
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
|
||
|
||
<li><a href="../java_jdbc/home.html">java.jdbc - Getting Started</a></li>
|
||
|
||
<li><a href="../java_jdbc/using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
|
||
|
||
<li><a href="../java_jdbc/using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
|
||
|
||
<li><a href="../java_jdbc/reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
|
||
|
||
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
|
||
|
||
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
|
||
|
||
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
|
||
|
||
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
|
||
|
||
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
|
||
|
||
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
|
||
|
||
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
|
||
|
||
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
|
||
|
||
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
|
||
|
||
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
|
||
|
||
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
|
||
|
||
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
|
||
|
||
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
|
||
|
||
</ul>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<footer>Copyright © 2021 Multiple Authors
|
||
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
|
||
</div>
|
||
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
|
||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
|
||
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
|
||
<script>hljs.initHighlightingOnLoad();</script>
|
||
|
||
|
||
</body>
|
||
</html>
|