86 lines
No EOL
33 KiB
HTML
86 lines
No EOL
33 KiB
HTML
<!doctype html>
|
||
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-tutorial/projects/packages-systems" data-has-hydrated="false">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="generator" content="Docusaurus v3.0.1">
|
||
<title data-rh="true">Packages and Systems | Common Lisp Docs</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:image" content="https://lisp-docs.github.io/img/1024px-Lisp_logo.svg.png"><meta data-rh="true" name="twitter:image" content="https://lisp-docs.github.io/img/1024px-Lisp_logo.svg.png"><meta data-rh="true" property="og:url" content="https://lisp-docs.github.io/docs/tutorial/projects/packages-systems"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="google-site-verification" content="Vzaw013_bfdKeUVG89Ch3W1zC9_vH9ID2dPB9Dz0vr0"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Packages and Systems | Common Lisp Docs"><meta data-rh="true" name="description" content="Original Author: Steve Losh"><meta data-rh="true" property="og:description" content="Original Author: Steve Losh"><link data-rh="true" rel="icon" href="../../../img/favicon.ico"><link data-rh="true" rel="canonical" href="packages-systems.html"><link data-rh="true" rel="alternate" href="packages-systems.html" hreflang="en"><link data-rh="true" rel="alternate" href="packages-systems.html" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://C1F2Q5VM6X-dsn.algolia.net" crossorigin="anonymous"><link rel="alternate" type="application/rss+xml" href="../../../blog/rss.xml" title="Common Lisp Docs RSS Feed">
|
||
<link rel="alternate" type="application/atom+xml" href="../../../blog/atom.xml" title="Common Lisp Docs Atom Feed">
|
||
|
||
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml" title="Common Lisp Docs" href="../../../opensearch.xml"><link rel="stylesheet" href="../../../assets/css/styles.d316d1e5.css">
|
||
<script src="../../../assets/js/runtime~main.eb788e4f.js" defer="defer"></script>
|
||
<script src="../../../assets/js/main.8eecaa6d.js" defer="defer"></script>
|
||
</head>
|
||
<body class="navigation-with-keyboard">
|
||
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return localStorage.getItem("theme")}catch(t){}}();t(null!==e?e:"light")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="packages-systems.html#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="../../../index.html"><div class="navbar__logo"><img src="../../../img/logo.svg" alt="Lisp Logo" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="../../../img/logo.svg" alt="Lisp Logo" class="themedComponent_mlkZ themedComponent--dark_xIcU"></div><b class="navbar__title text--truncate">Common Lisp Docs</b></a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="../../tutorial.html">Tutorial</a><a href="../../../cl-language-reference/index.html" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Technical Reference</a><a class="navbar__item navbar__link" href="../../whylisp.html">Why Lisp?</a><a class="navbar__item navbar__link" href="../../howto.html">Guides</a></div><div class="navbar__items navbar__items--right"><a class="navbar__item navbar__link" href="../../contribute.html">Contribute!</a><a class="navbar__item navbar__link" href="../../help.html">Getting Help</a><a class="navbar__item navbar__link" href="../../about.html">About</a><a class="navbar__item navbar__link" href="../../../blog.html">Blog</a><a href="https://github.com/lisp-docs" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type="button" disabled="" title="Switch between dark and light mode (currently light mode)" aria-label="Switch between dark and light mode (currently light mode)" aria-live="polite"><svg viewBox="0 0 24 24" width="24" height="24" class="lightToggleIcon_pyhR"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" class="darkToggleIcon_wfgR"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg></button></div><div class="navbarSearchContainer_Bca1"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="main-wrapper mainWrapper_z2l0"><div class="docsWrapper_hBAB"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_sjWU" type="button"></button><div class="docRoot_UBD9"><aside class="theme-doc-sidebar-container docSidebarContainer_YfHR"><div class="sidebarViewport_aRkj"><div class="sidebar_njMd"><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_SIkG"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../../tutorial.html">Tutorial Introduction</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../for_beginners.html">Beginner Programmers</a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist" aria-expanded="false" href="../for_programmers.html">Experienced Programmers</a><button aria-label="Expand sidebar category 'Experienced Programmers'" type="button" class="clean-btn menu__caret"></button></div></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../macros.html">Macros</a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist menu__link--active" aria-expanded="true" href="../projects.html">Structuring projects</a><button aria-label="Collapse sidebar category 'Structuring projects'" type="button" class="clean-btn menu__caret"></button></div><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="guide_to_packages.html">The Complete Idiot’s Guide to Common Lisp Packages</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="packages-systems.html">Packages and Systems</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="package_inferred.html">Package Inferred Systems</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="structuring_large_projects.html">Structuring Large Projects</a></li></ul></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../documentation.html">Documenting your Code</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../motivation.html">Motivation</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../using-cl-implementation.html">Using a Common Lisp Implementation</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../informal-introduction-to-lisp.html">An Informal Introduction to Common Lisp</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../control-flows.html">Control Flow</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../data-structures.html">Data Structures</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../processing-data.html">Processing Data</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../io.html">Input and Output</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../errors.html">Dealing with Errors</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../classes-methods.html">Classes and Methods</a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist" aria-expanded="false" href="../../category/advanced-topics.html">Advanced Topics</a><button aria-label="Expand sidebar category 'Advanced Topics'" type="button" class="clean-btn menu__caret"></button></div></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="https://lisp-docs.github.io/docs/tutorial/index">Index</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="../glossary.html">Glossary</a></li></ul></nav></div></div></aside><main class="docMainContainer_TBSr"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_VOVn"><div class="docItemContainer_Djhp"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_Z_bl" aria-label="Breadcrumbs"><ul class="breadcrumbs" itemscope="" itemtype="https://schema.org/BreadcrumbList"><li class="breadcrumbs__item"><a aria-label="Home page" class="breadcrumbs__link" href="../../../index.html"><svg viewBox="0 0 24 24" class="breadcrumbHomeIcon_YNFT"><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill="currentColor"></path></svg></a></li><li itemscope="" itemprop="itemListElement" itemtype="https://schema.org/ListItem" class="breadcrumbs__item"><a class="breadcrumbs__link" itemprop="item" href="../projects.html"><span itemprop="name">Structuring projects</span></a><meta itemprop="position" content="1"></li><li itemscope="" itemprop="itemListElement" itemtype="https://schema.org/ListItem" class="breadcrumbs__item breadcrumbs__item--active"><span class="breadcrumbs__link" itemprop="name">Packages and Systems</span><meta itemprop="position" content="2"></li></ul></nav><div class="tocCollapsible_ETCw theme-doc-toc-mobile tocMobile_ITEo"><button type="button" class="clean-btn tocCollapsibleButton_TO0P">On this page</button></div><div class="theme-doc-markdown markdown"><h1>Packages and Systems</h1>
|
||
<blockquote>
|
||
<p>Original Author: <a href="https://stevelosh.com" target="_blank" rel="noopener noreferrer">Steve Losh</a></p>
|
||
<p><a href="https://stevelosh.com/blog/2018/08/a-road-to-common-lisp/#s30-modern-common-lisp" target="_blank" rel="noopener noreferrer">Source</a></p>
|
||
<p>Slightly modified to fit this tutorial.</p>
|
||
</blockquote>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="structure">Structure<a href="packages-systems.html#structure" class="hash-link" aria-label="Direct link to Structure" title="Direct link to Structure"></a></h2>
|
||
<p>Common Lisp's terminology for various parts of projects is often confusing to new people because it's old and uses a lot of words that we use now (like <span><i><a href="../../../cl-language-reference/chap-11/bb-b-package-concepts.html" target="_blank" rel="noopener noreferrer">“package”</a></i></span>) to mean subtly different things than people mean today. Things get easier once you internalize what Common Lisp means by the terms.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="packages">Packages<a href="packages-systems.html#packages" class="hash-link" aria-label="Direct link to Packages" title="Direct link to Packages"></a></h2>
|
||
<p>We often see questions in IRC and Discord that look something like: "How do I export a class from a package"? Questions worded like this are a sign of a very common misunderstanding about what packages in Common Lisp <em>actually are</em>.</p>
|
||
<p><strong>A package in Common Lisp is a container for symbols.</strong> That's it. They're a way to group related names (<span><span><b>symbols</b></span></span>) together so you don't have to do the miserable prefixing of every name with <code>mylibrary-...</code> like you need to do in Emacs Lisp or C to avoid name clashes.</p>
|
||
<p>You don't export a class from a package, you export a <span><span><b>symbol</b></span></span>. You don't import a function, you import the symbol it's attached to. This sounds pedantic, but is important to keep clear in your head as you start using the package system. If you're not clear on what exactly a symbol is, I wrote a <a href="https://stevelosh.com/blog/2016/06/symbolic-computation/" target="_blank" rel="noopener noreferrer">separate post</a> just about symbols which you might find helpful.</p>
|
||
<p>Another major tripping point for new people is the relationship between packages and files. Or, rather: the completely lack of any relationship in Common Lisp.</p>
|
||
<p>In many languages like Python, Java, or Clojure, a file's package and its location on the hard drive are tied together. For example: when you say import <code>foo.bar.baz</code> in Python, Python will look for a <code>baz.py</code> file inside the <code>foo/bar/</code> directory (it's a little more complicated than this, but that doesn't matter for this example).</p>
|
||
<p>In Common Lisp, this is not the case. <strong>Files and packages are completely unrelated in Common Lisp.</strong> You can have many files that all work in the same package, or one file that switches between many packages, or even create or modify packages at runtime.</p>
|
||
<p>This gives you the flexibility to work however you want. For example: in my procedural art library <a href="https://github.com/sjl/flax" target="_blank" rel="noopener noreferrer">Flax</a> most of the packages are each used in one specific file, much like you would do in modern languages. But the flax.drawing package contains not only a drawing protocol but also several implementations of that protocol (PNG, SVG, etc), and so I split the code into a <a href="https://github.com/sjl/flax/tree/master/src/drawing" target="_blank" rel="noopener noreferrer">series of separate files</a>, each one dealing with how to draw a single format (plus one for the protocol itself).</p>
|
||
<p>I could have created separate packages for each implementation and set up the imports/exports between them, but I didn't feel like the extra boilerplate was worth it. Common Lisp is flexible enough to let you make such choices.</p>
|
||
<p>So if files and packages aren't related, the next question is: how does Common Lisp know where to <em>find</em> anything on disk when it comes time to load the code?</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="systems">Systems<a href="packages-systems.html#systems" class="hash-link" aria-label="Direct link to Systems" title="Direct link to Systems"></a></h2>
|
||
<p>A system in Common Lisp is a collection of serveral things:</p>
|
||
<ul>
|
||
<li>Some code.</li>
|
||
<li>A description of how to load that code.</li>
|
||
<li>A list of other systems this system depends on, which need to be loaded prior to loading this one.</li>
|
||
<li>Some metadata like author, license, version, homepage, etc.</li>
|
||
</ul>
|
||
<p>The Common Lisp language itself has no knowledge of systems. If you look at <a href="https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node120.html" target="_blank" rel="noopener noreferrer">section 11.9</a> of CLtL2 you'll see that it was imagined that each author would write their own custom file to load their code. But since Common Lisp gives you the power to abstract almost anything, people eventually abstracted the process of loading Common Lisp code.</p>
|
||
<p><a href="https://asdf.common-lisp.dev/" target="_blank" rel="noopener noreferrer">ASDF</a> is a Common Lisp library bundled with most modern implementations which handles defining and loading systems. The name ASDF stands for "Another System Definition Facility", so as you might guess there have been several other such libraries. ASDF is the one everyone uses today.</p>
|
||
<p>ASDF standardizes the process of defining a system into something like this:</p>
|
||
<p>The system definition(s) for a project called <code>foo</code> would be in a file named <code>foo.asd</code>.
|
||
Each system is defined with a <code>(defsystem ...)</code> form inside this file.
|
||
We'll talk more about what a "project" is shortly. Note the extension of the file is <code>asd</code>, not <code>asdf</code>, which is a little confusing, but was probably chosen to work in environments with three-letter-extension limits.</p>
|
||
<p>The <a href="https://asdf.common-lisp.dev/#documentation" target="_blank" rel="noopener noreferrer">ASDF manual</a> is the definitive resource for the syntax and semantics of <code>defsystem</code>, but can be a little heavy to read if you're just getting started. Another way to get started is to read some .asd files of some small-to-medium sized open source projects and see how they handle things.</p>
|
||
<p>Systems and packages are orthogonal in Common Lisp. Some systems (like small libraries) will define exactly one package. Some systems will define multiple packages. Rarely a system might not define any new packages, but will use or add to an existing one.</p>
|
||
<p>For example:</p>
|
||
<ul>
|
||
<li>My directed graph library <a href="https://github.com/sjl/cl-digraph" target="_blank" rel="noopener noreferrer">cl-digraph</a> contains a system called <code>cl-digraph</code>.</li>
|
||
<li>That system has a description of how to load the code, which lives in the <a href="https://github.com/sjl/cl-digraph/blob/master/cl-digraph.asd" target="_blank" rel="noopener noreferrer"><code>cl-digraph.asd</code></a> file.</li>
|
||
<li>One of the files specified for loading is <a href="https://github.com/sjl/cl-digraph/blob/master/package.lisp" target="_blank" rel="noopener noreferrer"><code>package.lisp</code></a>, which creates a package called <code>digraph</code>.</li>
|
||
</ul>
|
||
<p>Even though ASDF standardizes some aspects of system definition, it still gives you plenty of flexibility. As you read projects by different authors you'll encounter different ways of organizing systems — this can be a little overwhelming at first, but it means you can organize a system in the way that works <em>best for that system</em>, which is really nice once you've got some experience under your belt.</p>
|
||
<p>One example of this is how people define packages for their systems. There are a couple of common ways to do this you'll see in the wild:</p>
|
||
<ul>
|
||
<li>A single <code>package.lisp</code> file which contains all the definitions for all the packages in the project, and gets loaded before all other files. This is the strategy I usually prefer.</li>
|
||
<li>Each file defines its package at the top of the file, much like you would in Clojure or other modern languages. Care is taken in the system definition to load the files in the correct order so that each package is defined before it is ever used.
|
||
To review: a system is a collection of code and a description of how to load it, a list of its dependencies, and some metadata. Now let's move up one level higher to the final layer of structure you need to know about.</li>
|
||
</ul>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="projects">Projects<a href="packages-systems.html#projects" class="hash-link" aria-label="Direct link to Projects" title="Direct link to Projects"></a></h2>
|
||
<p>A project in Common Lisp is not an official term defined anywhere that I know of, but is a word that's generally used to mean something like a library, a framework, an application, etc.</p>
|
||
<p>A project will usually define at least one system, because systems are where you describe how to load the code, and if a project didn't define a system how would you know how to load its code? My string-wrapping library <a href="https://github.com/sjl/bobbin" target="_blank" rel="noopener noreferrer">Bobbin</a> is a project that defines <em>two</em> systems:</p>
|
||
<ul>
|
||
<li>The <code>bobbin</code> system contains the actual data structure and API. It has no dependencies.</li>
|
||
<li>The <code>bobbin/test</code> system contains the unit tests. It depends on the <code>bobbin</code> system (because that's the code it's going to test) and the <code>1am</code> system (a unit test framework). I made this a separate system because it allows users to load the main code without also having to load the unit testing framework if they're not going to be running the tests.</li>
|
||
</ul>
|
||
<p>Both of these systems are defined in the <a href="https://github.com/sjl/bobbin/blob/master/bobbin.asd" target="_blank" rel="noopener noreferrer"><code>bobbin.asd</code></a> file. ASDF <a href="https://asdf.common-lisp.dev/asdf.html#index-find_002dsystem" target="_blank" rel="noopener noreferrer">treats systems with a forward slash in their name specially</a> and knows to look for them in the asd file named with the text before the slash.</p>
|
||
<p>We saw how Common Lisp has no concept of a system — that concept comes from ASDF. Similarly, ASDF has no concept of the internet or of reaching out to somewhere to download things. ASDF assumes you have somehow acquired the systems you want to load and stored them on your hard drive, perhaps by sending a check to an address and receiving a copy of the code on floppy disk, as many of my old Lisp books offer in their final pages.</p>
|
||
<p><a href="https://www.quicklisp.org/beta/" target="_blank" rel="noopener noreferrer">Quicklisp</a> is another library that works on top of ASDF to provide the "download projects from the internet automatically if necessary" functionality that people expect in the modern world. So when you say <code>(ql:quickload :bobbin)</code> you’re asking Quicklisp to download Bobbin (and any dependencies) if necessary, and then hand it off to ASDF to actually load the code of the bobbin system.</p>
|
||
<p>Unlike ASDF, Quicklisp is relatively new in the Common Lisp world (it's only about eight years old) and so is not bundled with any modern Lisp implementations that I know of, which is why you need to install it separately.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="recap">Recap<a href="packages-systems.html#recap" class="hash-link" aria-label="Direct link to Recap" title="Direct link to Recap"></a></h2>
|
||
<p>Here's a quick recap of the different layers of project structure you'll encounter in Common Lisp. Jot these down on a post it note you can refer to as you're learning.</p>
|
||
<ul>
|
||
<li><strong>Files</strong> are files on your hard drive.</li>
|
||
<li><strong>Packages</strong> are containers of symbols. They are orthogonal to files.</li>
|
||
<li><strong>Systems</strong> are collections of code, instructions on how to load that code, dependency lists, and metadata. They are orthogonal to packages.</li>
|
||
<li><strong>Projects</strong> are high-level collections of... "stuff" such as code, documentation, maybe some image assets, etc. They are (mostly) orthogonal to systems (are you seeing a trend here?).</li>
|
||
<li>Common Lisp itself knows about files and packages.</li>
|
||
<li>ASDF adds systems.</li>
|
||
<li>Quicklisp adds the internet.</li>
|
||
</ul></div><footer class="theme-doc-footer docusaurus-mt-lg"><div class="theme-doc-footer-edit-meta-row row"><div class="col"><a href="https://github.com/lisp-docs/lisp-docs.github.io/tree/main/docs/tutorial/projects/packages-systems.md" target="_blank" rel="noopener noreferrer" class="theme-edit-this-page"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_Z9Sw" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col lastUpdated_vwxv"><span class="theme-last-updated">Last updated<!-- --> by <b>Daniel Nussenbaum</b></span></div></div></footer></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="guide_to_packages.html"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">The Complete Idiot’s Guide to Common Lisp Packages</div></a><a class="pagination-nav__link pagination-nav__link--next" href="package_inferred.html"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Package Inferred Systems</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="packages-systems.html#structure" class="table-of-contents__link toc-highlight">Structure</a></li><li><a href="packages-systems.html#packages" class="table-of-contents__link toc-highlight">Packages</a></li><li><a href="packages-systems.html#systems" class="table-of-contents__link toc-highlight">Systems</a></li><li><a href="packages-systems.html#projects" class="table-of-contents__link toc-highlight">Projects</a></li><li><a href="packages-systems.html#recap" class="table-of-contents__link toc-highlight">Recap</a></li></ul></div></div></div></div></main></div></div></div><footer class="footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="col footer__col"><div class="footer__title">Docs</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="../../tutorial.html">Common Lisp Tutorial</a></li><li class="footer__item"><a href="../../../cl-language-reference/index.html" target="_blank" rel="noopener noreferrer" class="footer__link-item">Common Lisp Technical Reference</a></li><li class="footer__item"><a class="footer__link-item" href="../../help.html">Help</a></li></ul></div><div class="col footer__col"><div class="footer__title">Community</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://stackoverflow.com/questions/tagged/common-lisp" target="_blank" rel="noopener noreferrer" class="footer__link-item">Stack Overflow<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://discord.gg/hhk46CE" target="_blank" rel="noopener noreferrer" class="footer__link-item">Discord<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://www.reddit.com/r/common_lisp" target="_blank" rel="noopener noreferrer" class="footer__link-item">Reddit<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://irclog.tymoon.eu/libera/commonlisp" target="_blank" rel="noopener noreferrer" class="footer__link-item">IRC<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title">More</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="../../../blog.html">Blog</a></li><li class="footer__item"><a href="https://github.com/lisp-docs/lisp-docs.github.io" target="_blank" rel="noopener noreferrer" class="footer__link-item">Tutorial and General Content GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://github.com/lisp-docs/cl-language-reference/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Technical Reference GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a class="footer__link-item" href="../../contribute.html">Contribute to the Docs</a></li></ul></div><div class="col footer__col"><div class="footer__title">Common Lisp Docs</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="../../about.html">About</a></li><li class="footer__item"><a class="footer__link-item" href="../../whylisp.html">Why Lisp</a></li><li class="footer__item"><a class="footer__link-item" href="../../getting-started.html">Getting Started</a></li><li class="footer__item"><a class="footer__link-item" href="../../faq.html">FAQ</a></li><li class="footer__item"><a class="footer__link-item" href="../../help.html">Getting Help</a></li><li class="footer__item"><a class="footer__link-item" href="../../howto.html">How To Guides</a></li></ul></div></div><div class="footer__bottom text--center"><div class="footer__copyright">Copyright © 2024 Common Lisp Docs, MIT License (see GitHub Repo).</div></div></div></footer></div>
|
||
</body>
|
||
</html> |