emacs.d/clones/clojure-doc.org/articles/ecosystem/libraries_authoring/index.html
2022-08-24 19:36:32 +02:00

343 lines
24 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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&#39;s assumed that you&#39;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&#39;s assumed that you&#39;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 &amp;
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 &lt;proj-type&gt; &lt;proj-name&gt;</code>, but if you
leave out <code>&lt;proj-type&gt;</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 &lt;your-key-id&gt;
</code></pre><p>where <code>&lt;your-key-id&gt;</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">&laquo; A Directory of Clojure Libraries</a>
||
<a href="../generating_documentation/index.html">Generating Documentation &raquo;</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 &copy; 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>