<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Robert Krahn</title>
    <link>https://robert.kra.hn/</link>
    <description>Recent content on Robert Krahn</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>robert@kra.hn (Robert Krahn)</managingEditor>
    <webMaster>robert@kra.hn (Robert Krahn)</webMaster>
    <copyright>&amp;copy; Robert Krahn 2009-2023</copyright>
    <lastBuildDate>Fri, 22 Jan 2021 00:00:00 +0000</lastBuildDate><atom:link href="https://robert.kra.hn/feed.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>org-ai — Emacs as your personal AI assistant</title>
      <link>https://robert.kra.hn/posts/2023-04-01-org-ai/</link>
      <pubDate>Sat, 01 Apr 2023 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/2023-04-01-org-ai/</guid>
      <description>&lt;p&gt;&lt;code&gt;org-ai&lt;/code&gt; is an Emacs extension that provides functionality by integrating various AI models into Emacs. This demo gives an impression:&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/fvBDxiFPG6I&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;The project can be found on &lt;a href=&#34;https://github.com/rksm/org-ai&#34;&gt;Github&lt;/a&gt;. Currently, features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use ChatGPT
&lt;ul&gt;
&lt;li&gt;in org-mode with &lt;code&gt;#+begin_ai...#+end_ai&lt;/code&gt; blocks&lt;/li&gt;
&lt;li&gt;directly with a prompt anywhere&lt;/li&gt;
&lt;li&gt;on selected text to ask questions or request other actions&lt;/li&gt;
&lt;li&gt;refactor code&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;generate images and image variations with DALL-E&lt;/li&gt;
&lt;li&gt;speech input and output&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Setting up Github Copilot in Emacs</title>
      <link>https://robert.kra.hn/posts/2023-02-22-copilot-emacs-setup/</link>
      <pubDate>Wed, 22 Feb 2023 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/2023-02-22-copilot-emacs-setup/</guid>
      <description>

&lt;div style=&#34;padding: 2em 3em 4em;&#34;&gt;
&lt;div style=&#34;border: 1px dashed gray; padding: 0.5em;&#34;&gt;
&lt;h4&gt;Quickstart&lt;/h4&gt;
&lt;div style=&#34;padding: 0 0.8em; margin-top: -0.5em; &#34;&gt;
&lt;summary&gt;
Either follow the instructions of &lt;a href=&#34;https://github.com/zerolfx/copilot.el#installation&#34;&gt;zerolfx/copilot.el&lt;/a&gt; or use a ready-to-roll config provided at &lt;a href=&#34;https://github.com/rksm/copilot-emacsd&#34;&gt;rksm/copilot-emacsd&lt;/a&gt;.
&lt;/summary&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This is a short walkthrough describing my current Emacs-Copilot setup. Copilot is primarily advertised as a VSCode utility but actually it works really well in Emacs. Given the ease of adjustments (e.g. when to see completions) I would even argue Emacs might provide a better experience.&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;display: flex; flex-direction: column; align-items: center; margin-bottom: 2.5em;&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/2023-02-22-copilot-emacs-setup/copilot-emacs-demo.gif&#34;
        style=&#34;object-fit: cover; object-position: -3px -2px;&#34;&gt;
  &lt;/figure&gt;


&lt;h4 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#changelog&#34;&gt;Changelog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#intro--disclaimer&#34;&gt;Intro &amp;amp; Disclaimer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#copilot-api--integration&#34;&gt;Copilot API &amp;amp; integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#copilot-emacs-packages&#34;&gt;Copilot Emacs packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#setup--customizations&#34;&gt;Setup &amp;amp; Customizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#restricting-when-to-show-completions&#34;&gt;Restricting when to show completions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#customizing-keys&#34;&gt;Customizing keys&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#copilot-specific&#34;&gt;Copilot-specific&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#tab-key&#34;&gt;Tab key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#ctrl-g--cancel&#34;&gt;Ctrl-g / cancel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;changelog&#34;&gt;Changelog&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2023-03-20: zerolfx/copilot.el has been updated, so switching to only referencing it instead of my fork. Thank you Jason H.!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;intro--disclaimer&#34;&gt;Intro &amp;amp; Disclaimer&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/features/copilot&#34;&gt;Github Copilot&lt;/a&gt; is a tool that uses machine learning to generate text completions, primarily meant for source code, even though it works surprisingly well for all kinds of texts.
It is a commercial Microsoft product, though it is currently free to use if you have a few public Github repositories that have garnered some stars.
It is based on &lt;a href=&#34;https://openai.com/blog/openai-codex/&#34;&gt;OpenAI&amp;rsquo;s Codex model&lt;/a&gt; which itself is derived from the GPT-3 large language model (LLM).
So in some sense it is ChatGPT for your editor.&lt;/p&gt;
&lt;p&gt;LLMs that are trained on open (source) data generally, and Copilot in particular, are controversial.
Among other things, many people have expressed concerns about the questionable legal grounds that these tools are build on, e.g. there is currently a &lt;a href=&#34;https://githubcopilotlitigation.com/&#34;&gt;pending lawsuit&lt;/a&gt; focusing on potential violations of open source licenses.
So let me say that I&amp;rsquo;m well aware of the controversy and I would suggest careful use of Copilot, in particular when used in code bases that are not your own.&lt;/p&gt;
&lt;p&gt;That said, it can be an astonishingly useful tool.
For example, when learning languages or frameworks or dealing with new libraries are APIs, it is surprisingly good at providing guidance that often saves you many trips to the documentation.
Moreover, it is really good at detecting certain patterns in your code while also seeing variations and suggesting new code based on that — clever copy/paste on steroids.
Also tests are a good area where Copilot can be helpful.&lt;/p&gt;
&lt;p&gt;And of course check the generated code.
That thing will make mistakes.
It is surprisingly good at getting the syntax right (though sometimes it won&amp;rsquo;t correctly close parentheses) but be aware of logical issues, anti-patterns, or outdated code.&lt;/p&gt;
&lt;h2 id=&#34;copilot-api--integration&#34;&gt;Copilot API &amp;amp; integration&lt;/h2&gt;
&lt;p&gt;Even though Copilot is primarily a VSCode utility, making it work in Emacs is fairly straightforward.
In essence it is not much different than a language server.
The &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=GitHub.copilot&#34;&gt;VSCode extension&lt;/a&gt; is not open source but since it is implemented in JavaScript you can extract the vsix package as a zip file and get hold of the JS files. As far as I know, the &lt;a href=&#34;https://github.com/github/copilot.vim/&#34;&gt;copilot.vim plugin&lt;/a&gt; was the first non-VSCode integration that used that approach. The &lt;code&gt;worker.js&lt;/code&gt; file that is part of the vsix extension can be started as a node.js process that will read JSON-RPC data from stdin. There are a number of commands that are implemented using this format, here is the current full list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getCompletions&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getCompletionsCycling&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getPanelCompletions&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getVersion&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setEditorInfo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;checkStatus&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;signInInitiate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;signInConfirm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;signOut&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notifyShown&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notifyAccepted&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notifyRejected&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;telemetry/exception&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;testing/createContext&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;testing/alwaysAuth&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;testing/neverAuth&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;testing/useTestingToken&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;testing/setCompletionDocuments&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;testing/setPanelCompletionDocuments&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;testing/triggerShowMessageRequest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;testing/getDocument&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;debug/verifyState&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;debug/verifyCertificate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;debug/verifyWorkspaceState&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An editor like Emacs or VIM can start the worker in a subprocess and then interact with, sending JSON messages and reading JSON responses back via stdout.&lt;/p&gt;
&lt;p&gt;Given that VSCode uses the exact same interface and from everything I&amp;rsquo;ve tried so far, I think it is safe to assume that using Copilot with Emacs is in no way inferior.
On the contrary, as shown below, customizing the way Copilot works is actually more convenient (at list if you know some elisp :).
I&amp;rsquo;m particularly mentioning that because &lt;a href=&#34;https://twitter.com/mark_l_watson/status/1627317557597450240&#34;&gt;some folks&lt;/a&gt; seem to believe that this is not the case. Should I be wrong on this (now or later), please let me know. It&amp;rsquo;s annoying that not event the Copilot agent isn&amp;rsquo;t open source (without open source none of this would be possible!) but it is not that complicated to figure out what it does. Which in turn means that other clients can catch up.&lt;/p&gt;
&lt;h3 id=&#34;copilot-emacs-packages&#34;&gt;Copilot Emacs packages&lt;/h3&gt;
&lt;p&gt;On Github I have found three Emacs packages that implement Copilot integration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/zerolfx/copilot.el&#34;&gt;zerolfx/copilot.el&lt;/a&gt; seems by far the most popular one and is the one I&amp;rsquo;m using below. It provides completions through an overlay, similar to the VSCodes extension.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/fkr-0/flight-attendant.el&#34;&gt;fkr-0/flight-attendant.el&lt;/a&gt; might be inactive, the last commit was a year ago. I have not tried it.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tyler-dodge/eglot-copilot/&#34;&gt;tyler-dodge/eglot-copilot/&lt;/a&gt; seems to be actively developed but has no documentation. It uses eglot for managing the subprocess and counsel for completions.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;setup--customizations&#34;&gt;Setup &amp;amp; Customizations&lt;/h3&gt;
&lt;p&gt;You can find a fully working config building on &lt;code&gt;zerolfx/copilot.el&lt;/code&gt; that can also be run standalone at &lt;a href=&#34;https://github.com/rksm/copilot-emacsd&#34;&gt;rksm/copilot-emacsd&lt;/a&gt;. In the following I explain some of the customizations.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zerolfx/copilot.el&lt;/code&gt; is not on MELPA so you have to install it through straight.el or other means (see the &lt;a href=&#34;https://github.com/zerolfx/copilot.el#configurations&#34;&gt;README&lt;/a&gt;).
I typically add an Emacs package like that as a submodule to my config:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;git submodule add https://github.com/zerolfx/copilot.el
git submodule update --init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The packages required for it to work are: &lt;code&gt;s&lt;/code&gt;, &lt;code&gt;dash&lt;/code&gt;, &lt;code&gt;editorconfig&lt;/code&gt; (and I also use &lt;code&gt;company&lt;/code&gt;, &lt;code&gt;use-package&lt;/code&gt; and Emacs built-in &lt;code&gt;cl&lt;/code&gt; package here as I find those very helpful).
Install them like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;require&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;&amp;#39;cl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;pkg-list&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;use-package&lt;/span&gt;
		          &lt;span class=&#34;nv&#34;&gt;s&lt;/span&gt;
		          &lt;span class=&#34;nv&#34;&gt;dash&lt;/span&gt;
		          &lt;span class=&#34;nv&#34;&gt;editorconfig&lt;/span&gt;
                  &lt;span class=&#34;nv&#34;&gt;company&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;package-initialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;when-let&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;to-install&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;map-filter&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;pkg&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;package-installed-p&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;pkg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;pkg-list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;package-refresh-contents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;mapc&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;pkg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;package-install&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;pkg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;pkg-list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Assuming the above git submodule was cloned into &lt;code&gt;copilot.el/&lt;/code&gt;, we can now load that package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;use-package&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot&lt;/span&gt;
  &lt;span class=&#34;nb&#34;&gt;:load-path&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;expand-file-name&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;copilot.el&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;user-emacs-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;c1&#34;&gt;;; don&amp;#39;t show in mode line&lt;/span&gt;
  &lt;span class=&#34;nb&#34;&gt;:diminish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can now run &lt;code&gt;M-x copilot-login&lt;/code&gt; to authenticate with your Github account (that needs to have a subscription to the Copilot product) followed by &lt;code&gt;M-x global-copilot-mode&lt;/code&gt; to activate Copilot everywhere.&lt;/p&gt;
&lt;h3 id=&#34;restricting-when-to-show-completions&#34;&gt;Restricting when to show completions&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;global-copilot-mode&lt;/code&gt; will sometimes be a bit too eager, so we disable in some modes completely:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defun&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/no-copilot-mode&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Helper for &lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;`rk/no-copilot-modes&amp;#39;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;.&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot-mode&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;-1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defvar&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/no-copilot-modes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;shell-mode&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;inferior-python-mode&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;eshell-mode&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;term-mode&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;vterm-mode&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;comint-mode&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;compilation-mode&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;debugger-mode&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;dired-mode-hook&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;compilation-mode-hook&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;flutter-mode-hook&lt;/span&gt;
                              &lt;span class=&#34;nv&#34;&gt;minibuffer-mode-hook&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Modes in which copilot is inconvenient.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defun&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-disable-predicate&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;When copilot should not automatically show completions.&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-manual-mode&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;member&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;major-mode&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/no-copilot-modes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;company--active-p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;add-to-list&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;&amp;#39;copilot-disable-predicates&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;rk/copilot-disable-predicate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, it is also convenient to have the overlays not appear automatically but on-demand:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defvar&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-manual-mode&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;When &lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;`t&amp;#39;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt; will only show completions when manually triggered, e.g. via M-C-&amp;lt;return&amp;gt;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defun&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-change-activation&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Switch between three activation modes:
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;- automatic: copilot will automatically overlay completions
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;- manual: you need to press a key (M-C-&amp;lt;return&amp;gt;) to trigger completions
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;- off: copilot is completely disabled.&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;interactive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot-mode&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-manual-mode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;progn&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;deactivating copilot&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;global-copilot-mode&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;-1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;setq&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-manual-mode&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot-mode&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;progn&lt;/span&gt;
          &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;activating copilot manual mode&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
          &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;setq&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-manual-mode&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;activating copilot mode&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;global-copilot-mode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;define-key&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;global-map&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;kbd&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;M-C-&amp;lt;escape&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;rk/copilot-change-activation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;M-C-&amp;lt;escape&amp;gt;&lt;/code&gt; will now cycle between three states automatic, manual and off.&lt;/p&gt;
&lt;h3 id=&#34;customizing-keys&#34;&gt;Customizing keys&lt;/h3&gt;
&lt;h4 id=&#34;copilot-specific&#34;&gt;Copilot-specific&lt;/h4&gt;
&lt;p&gt;I like my keybindings to be somewhat consistent and have assigned &lt;code&gt;M-C-...&lt;/code&gt; (Alt + Control + some other key) to Copilot related commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defun&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-complete-or-accept&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Command that either triggers a completion or accepts one if one
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;is available. Useful if you tend to hammer your keys like I do.&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;interactive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot--overlay-visible&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;progn&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot-accept-completion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;open-line&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;next-line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot-complete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;define-key&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot-mode-map&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;kbd&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;M-C-&amp;lt;next&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot-next-completion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;define-key&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot-mode-map&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;kbd&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;M-C-&amp;lt;prior&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot-previous-completion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;define-key&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot-mode-map&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;kbd&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;M-C-&amp;lt;right&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot-accept-completion-by-word&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;define-key&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot-mode-map&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;kbd&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;M-C-&amp;lt;down&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot-accept-completion-by-line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;define-key&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;global-map&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;kbd&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;M-C-&amp;lt;return&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;rk/copilot-complete-or-accept&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;tab-key&#34;&gt;Tab key&lt;/h4&gt;
&lt;p&gt;If you also want to use the &lt;code&gt;&amp;lt;tab&amp;gt;&lt;/code&gt; key for completion but still keep the normal functionality on it, do:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defun&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-tab&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Tab command that will complet with copilot if a completion is
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;available. Otherwise will try company, yasnippet or normal
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;tab-indent.&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;interactive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot-accept-completion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;company-yasnippet-or-completion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;indent-for-tab-command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;define-key&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;global-map&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;kbd&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;lt;tab&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;rk/copilot-tab&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;ctrl-g--cancel&#34;&gt;Ctrl-g / cancel&lt;/h4&gt;
&lt;p&gt;I like to cancel commands with &lt;code&gt;C-g&lt;/code&gt;. This does not work out of the box with canceling Copilot completions, be we can do:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;defun&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;rk/copilot-quit&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Run &lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;`copilot-clear-overlay&amp;#39;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt; or &lt;/span&gt;&lt;span class=&#34;ss&#34;&gt;`keyboard-quit&amp;#39;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;. If copilot is
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;cleared, make sure the overlay doesn&amp;#39;t come back too soon.&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;interactive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;condition-case&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;err&lt;/span&gt;
      &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;when&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot--overlay&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;lexical-let&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;pre-copilot-disable-predicates&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot-disable-predicates&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
          &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;setq&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot-disable-predicates&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
          &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;copilot-clear-overlay&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
          &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;run-with-idle-timer&lt;/span&gt;
           &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;
           &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt;
           &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
             &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;setq&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;copilot-disable-predicates&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;pre-copilot-disable-predicates&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))))&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;error&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;handler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;advice-add&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;&amp;#39;keyboard-quit&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;:before&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;rk/copilot-quit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that should be it!&lt;/p&gt;
&lt;p&gt;Thanks to all the awesome Emacs hackers who made all this possible!&lt;/p&gt;
</description>
    </item>
    
    
    
    
    
    <item>
      <title>Speeding up incremental Rust compilation with dylibs</title>
      <link>https://robert.kra.hn/posts/2022-09-09-speeding-up-incremental-rust-compilation-with-dylibs/</link>
      <pubDate>Fri, 09 Sep 2022 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/2022-09-09-speeding-up-incremental-rust-compilation-with-dylibs/</guid>
      <description>

&lt;div style=&#34;padding: 2em 3em 4em;&#34;&gt;
&lt;div style=&#34;border: 1px dashed gray; padding: 0.5em;&#34;&gt;
&lt;h4&gt;TL;DR&lt;/h4&gt;
&lt;div style=&#34;padding: 0 0.8em; margin-top: -0.5em; &#34;&gt;
&lt;summary&gt;
Creating a dynamic version of a Rust library can improve incremental compilation speed during development quite substantially.
&lt;a href=&#34;https://github.com/rksm/cargo-add-dynamic&#34;&gt;cargo add-dynamic&lt;/a&gt; automates the setup process.
&lt;/summary&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;




  &lt;script src=&#34;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js&#34;&gt;&lt;/script&gt;
  &lt;script&gt;
    mermaid.initialize({ startOnLoad: true });
  &lt;/script&gt;


&lt;p&gt;One of Rust&amp;rsquo;s biggest downsides is that it tends to be rather slow when compiling programs.
&lt;a href=&#34;https://blog.mozilla.org/nnethercote/2020/09/08/how-to-speed-up-the-rust-compiler-one-last-time/&#34;&gt;A lot of&lt;/a&gt; &lt;a href=&#34;work&#34;&gt;work&lt;/a&gt; has been put into improving the situation over the years with noticable impact.
In addition, there are a number of good guides out there that explain the impact of various optimization options and tooling choices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://endler.dev/2020/rust-compile-times/&#34;&gt;Tips for Faster Rust Compile Times (endler.dev)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://matklad.github.io/2021/09/04/fast-rust-builds.html&#34;&gt;Fast Rust Builds (matklad.github.io)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=pMiqRM5ooNw&#34;&gt;Making a Rust crate compile faster (Youtube/Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://jondot.medium.com/8-steps-for-troubleshooting-your-rust-build-times-2ffc965fd13e&#34;&gt;8 Solutions for Troubleshooting Your Rust Build Times (Medium)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bevyengine.org/learn/book/getting-started/setup/#enable-fast-compiles-optional&#34;&gt;bevy&amp;rsquo;s fast compilation tips&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One tip that I have not seen widely mentioned is the use of dynamic libraries that can help decreasing incremental compilation speed quite dramatically.
Bevy provides this as a feature flag (see last link above) but this approach can be used for most other dependencies as well.&lt;/p&gt;
&lt;p&gt;Incremental compilation matters so much because it directly affects development feedback.
This is not just re-running the application but also the wait time for feedback from the compiler and tools such as rust-analyzer.
When recompilation is slow, it is not rare to wait seconds for compiler errors to appear — infuriating!&lt;/p&gt;
&lt;h4 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#example-with-polars&#34;&gt;Example with polars&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#wrapping-dependencies-as-dylibs&#34;&gt;Wrapping dependencies as dylibs&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#crate-type--dylib&#34;&gt;&lt;code&gt;crate-type = [&amp;quot;dylib&amp;quot;]&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#polars-dynamic&#34;&gt;polars-dynamic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#limitation-the-diamond-dependency-problem&#34;&gt;Limitation: The diamond dependency problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#switching-between-static-and-dynamic-dependencies&#34;&gt;Switching between static and dynamic dependencies&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#controlling---feature-dynamic-with-an-environment-variable&#34;&gt;Controlling &lt;code&gt;--feature dynamic&lt;/code&gt; with an environment variable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-it-with-hot-reloading&#34;&gt;Using it with hot-reloading&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;changelog&#34;&gt;Changelog&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;2022-09-14: Mentioning diamond-dependency problem&lt;/li&gt;
&lt;li&gt;2022-09-10: Added breakdown about time spent, link to reddit, env var for feature&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;example-with-polars&#34;&gt;Example with polars&lt;/h2&gt;
&lt;p&gt;Here is an easy to produce example with &lt;a href=&#34;https://www.pola.rs/&#34;&gt;polars&lt;/a&gt;.
Polars is a dataframe library, a Rust (and python) alternative to the popular Python &lt;a href=&#34;https://pandas.pydata.org/&#34;&gt;pandas&lt;/a&gt; library.
I lately have used it a lot for data analysis and exploration, during which fast feedback cycles help a lot.&lt;/p&gt;
&lt;p&gt;So to get started, here is the baseline with a simple polars hello world:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# create a new project&lt;/span&gt;
cargo new polars-test
&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; polars-test

&lt;span class=&#34;c1&#34;&gt;# add polars as dependency&lt;/span&gt;
cargo add polars --features csv-file,lazy,list,describe,rows,fmt,strings,temporal

&lt;span class=&#34;c1&#34;&gt;# modify main.rs&lt;/span&gt;
cat &amp;gt; src/main.rs &lt;span class=&#34;s&#34;&gt;&amp;lt;&amp;lt; EOM
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;use polars::prelude::*;
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;fn main() {
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;    let df = df!(&amp;#34;col 1&amp;#34; =&amp;gt; [&amp;#34;a&amp;#34;]).unwrap();
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;    dbg!(df);
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;}
&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;EOM&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# first full build, this should take a while&lt;/span&gt;
cargo build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We create a new project, add polars as dependency and create a dataframe in the main function.
Polars offers a ton of (Rust) features, so much so that using it without a number of those does not make much sense.
The above is quite typical for what I would typically use for working on csv data.
The initial build is expected to take a while (on my computer&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; about 25 seconds).&lt;/p&gt;
&lt;p&gt;But now on to incremental changes. We make a small change to the main.rs file and rebuild.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;sed -i &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;s/&amp;#34;a&amp;#34;/&amp;#34;b&amp;#34;/&amp;#39;&lt;/span&gt; src/main.rs
&lt;span class=&#34;nb&#34;&gt;time&lt;/span&gt; cargo build
&lt;span class=&#34;c1&#34;&gt;# real	0m2.896s&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# user	0m2.080s&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# sys	0m0.237s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Almost 3 seconds, not great.
Let&amp;rsquo;s try the same thing with polars as a dynamic library:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;cargo rm polars
cargo install cargo-add-dynamic
cargo add-dynamic polars --features csv-file,lazy,list,describe,rows,fmt,strings,temporal
cargo build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are using the cargo command &lt;a href=&#34;https://github.com/rksm/cargo-add-dynamic&#34;&gt;cargo-add-dynamic&lt;/a&gt; to re-install polars and wrapping it as a dynamic library.
Using this command is optional, the setup can be done manually (see below).&lt;/p&gt;
&lt;p&gt;And now building incrementally:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;sed -i &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;s/&amp;#34;b&amp;#34;/&amp;#34;a&amp;#34;/&amp;#39;&lt;/span&gt; src/main.rs
&lt;span class=&#34;nb&#34;&gt;time&lt;/span&gt; cargo build
&lt;span class=&#34;c1&#34;&gt;# real	0m0.485s&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# user	0m0.391s&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# sys	0m0.110s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a 5x improvement over the static version!
Moreover, half a second is not all that noticable, 3 seconds gets quite annoying quickly.
So how does it work?&lt;/p&gt;
&lt;h2 id=&#34;wrapping-dependencies-as-dylibs&#34;&gt;Wrapping dependencies as dylibs&lt;/h2&gt;
&lt;p&gt;By default, Rust dependencies will be linked statically with the resulting binary file being build.
For production use, this is typically very desirable as this enables a number of optimizations like inlining and makes the resulting binary (mostly) &amp;ldquo;standalone&amp;rdquo;, i.e. no (or only some) libraries will need to be found and loaded at runtime.&lt;/p&gt;
&lt;p&gt;During development, the Rust compiler will need to do this work as well.
This means that for &amp;ldquo;heavy&amp;rdquo; dependencies that export a lot of symbols recompilation and linking can be expensive.
When forcing a dependency to by dynamic, the compiler will not need to do the same amount of work, however.&lt;/p&gt;
&lt;p&gt;We can can capture and then compare build times using the nightly &lt;code&gt;time-passes&lt;/code&gt; flag that will output time and memory usage for various compilation steps:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;nv&#34;&gt;RUSTFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;-Z time-passes&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;time&lt;/span&gt; cargo +nightly build &lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt;&amp;gt; time-passes.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This results in many lines of output, so redirecting this into a file is recommended.
The output of both a dynamic and a static recompilation can be diffed but the differences are quite visible directly when looking at the last few lines:&lt;/p&gt;
&lt;p&gt;With a static build:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;...
time:   2.352; rss:  105MB -&amp;gt;  105MB (   +0MB)	run_linker
time:   2.353; rss:  104MB -&amp;gt;  105MB (   +1MB)	link_binary
time:   2.353; rss:  104MB -&amp;gt;  105MB (   +1MB)	link_crate
time:   2.356; rss:  104MB -&amp;gt;  105MB (   +1MB)	link
time:   2.511; rss:   20MB -&amp;gt;   59MB (  +39MB)	total
    Finished dev [unoptimized + debuginfo] target(s) in 2.64s
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With a dynamic build:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;...
time:   0.202; rss:  103MB -&amp;gt;  103MB (   +0MB)	run_linker
time:   0.203; rss:  102MB -&amp;gt;  103MB (   +1MB)	link_binary
time:   0.203; rss:  102MB -&amp;gt;  103MB (   +1MB)	link_crate
time:   0.206; rss:  102MB -&amp;gt;  103MB (   +1MB)	link
time:   0.346; rss:   20MB -&amp;gt;   56MB (  +36MB)	total
    Finished dev [unoptimized + debuginfo] target(s) in 0.47s
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So the main differences really are just in the linking phase.
As was mentioned &lt;a href=&#34;https://www.reddit.com/r/rust/comments/x9z4cm/comment/inrscqd/?utm_source=share&amp;amp;utm_medium=web2x&amp;amp;context=3&#34;&gt;by u/valarauca14 on reddit&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Static linking is relatively complex while run-time dynamic linking is super straight forward.&lt;/p&gt;
&lt;p&gt;With Static Linking you need to index the object, respect the &amp;ldquo;weakness&amp;rdquo;/&amp;ldquo;strength&amp;rdquo; of symbols, resolve conflicts, and potentially rewrite offsets within functions/assembly when gluing things together. Potentially repair debug/data that now conflicts with one-another. Constants maybe merged/dropped. These constants are not necessarily_defined by the developer, they can be ABI specific stuff (like dynamic linking points/stack unwrapping heap reservations, etc.).&lt;/p&gt;
&lt;p&gt;This work is rather expensive computationally. Fast linkers like mold don&amp;rsquo;t support some of these things (or they&amp;rsquo;ve received the bug report and are working on a solution). While faster linkers like gold have the luxury of newer algorithms/fresh eyes on old problems.&lt;/p&gt;
&lt;p&gt;With dynamic-linking. The object file has a literal index to help you determine symbol -&amp;gt; start/end byte offset. This file will be pre-loaded into memory at start. It is a very quick operation, normally just a memcp (to put the function into executable memory) + mov to update the offset so the original program can link to. This also occurs lazily at runtime, so loading &amp;amp; linking is amortized into runtime.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And indeed, as all of the guides linked above recommend, switching to a faster linker such as &lt;a href=&#34;https://github.com/rui314/mold&#34;&gt;mold&lt;/a&gt; (on Linux) or &lt;a href=&#34;https://github.com/michaeleisel/zld&#34;&gt;zld&lt;/a&gt; (on macOS) does make a difference.
Switching to zld on my machine brings down the static compilation time to around 2 seconds while the dynamic compilation time stays at around 0.5 seconds.
So even though a faster linker improves the situation, there is still a notable difference.&lt;/p&gt;
&lt;h3 id=&#34;crate-type--dylib&#34;&gt;crate-type = [&amp;ldquo;dylib&amp;rdquo;]&lt;/h3&gt;
&lt;p&gt;How can a dependency be made dynamic?
The Rust compiler supports various methods to link crates together both statically and dynamically.
A dependency itself can specify it&amp;rsquo;s output type in its &lt;code&gt;Cargo.toml&lt;/code&gt; using the &lt;code&gt;crate-type&lt;/code&gt; setting:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;lib&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;crate-type&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;dylib&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When a crate is only available as &lt;code&gt;dylib&lt;/code&gt;, the compiler will be forced to link to it dynamically.&lt;/p&gt;
&lt;h3 id=&#34;polars-dynamic&#34;&gt;polars-dynamic&lt;/h3&gt;
&lt;p&gt;Going back to the example above and the &lt;code&gt;cargo add-dynamic polars&lt;/code&gt; command.
It automated the creation of a sub-package &lt;code&gt;polars-dynamic&lt;/code&gt; that wrapped the original library.
It has the following content:&lt;/p&gt;
&lt;h4 id=&#34;polars-dynamiccargotoml&#34;&gt;&lt;code&gt;polars-dynamic/Cargo.toml&lt;/code&gt;&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;polars-dynamic&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0.1.0&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;edition&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2021&amp;#34;&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;dependencies&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;polars&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0.23.2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;features&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;csv-file&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lazy&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;list&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;describe&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;rows&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;temporal&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;lib&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;crate-type&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;dylib&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;polars-dynamicsrclibrs&#34;&gt;&lt;code&gt;polars-dynamic/src/lib.rs&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;polars&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;cargotoml&#34;&gt;&lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;And then instead of depending on directly on &lt;code&gt;polars&lt;/code&gt;, the main project can use the local wrapped sub-package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;c&#34;&gt;# ...&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;dependencies&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;polars&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;polars-dynamic&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;polars-dynamic&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;limitation-the-diamond-dependency-problem&#34;&gt;Limitation: The diamond dependency problem&lt;/h2&gt;
&lt;p&gt;As was brought up in a &lt;a href=&#34;https://github.com/rksm/cargo-add-dynamic/issues/3&#34;&gt;github issue&lt;/a&gt;, there is an important limitation in this approach.
&lt;a href=&#34;https://github.com/rust-lang/rust/issues/34909#issuecomment-274643453&#34;&gt;Because of how Rust deals with transitive dependencies during linking&lt;/a&gt;, if two dylibs (B and C) depend both on a static dependency (A) and a binary (D) uses B and C then you will see a compile error along the lines of &lt;code&gt;error: cannot satisfy dependencies so A only shows up once&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In particular this comes up when trying to dynamically link against both &lt;code&gt;serde&lt;/code&gt; and &lt;code&gt;serde_json&lt;/code&gt;.
If both of these are wrapped as dylibs as shown above, we end up with a dependency graph such as:&lt;/p&gt;


&lt;figure class=&#34;center-figure&#34;&gt;
&lt;div class=&#34;mermaid&#34;&gt;
  graph TD;
      bin[&#34;binary&#34;]-.-&gt;serde_dylib[&#34;serde (dylib)&#34;];
      bin-.-&gt;serde_json_dylib[&#34;serde_json (dylib)&#34;];
      serde_json_dylib--&gt;serde_json;
      serde_json--&gt;serde1[&#34;serde&#34;];
      serde_dylib--&gt;serde2[&#34;serde&#34;];
&lt;/div&gt;
&lt;/figure&gt;


&lt;p&gt;The problem is that the &lt;code&gt;serde (dylib)&lt;/code&gt; dependency provides a copy of serde to the binary and &lt;code&gt;serde_json&lt;/code&gt; pulls in another copy of serde as well.
Even though the versions are the same, Rust cannot deal with this because of global state mentioned in the linked issue above.&lt;/p&gt;
&lt;p&gt;The solution is to make &lt;code&gt;serde_json&lt;/code&gt; depend on serde dynamically as well so that the same dylib can be linked to &lt;code&gt;serde-dynamic&lt;/code&gt; and &lt;code&gt;serde_json&lt;/code&gt;.&lt;/p&gt;


&lt;figure class=&#34;center-figure&#34;&gt;
&lt;div class=&#34;mermaid&#34;&gt;
  graph TD;
      bin[&#34;binary&#34;]-.-&gt;serde_dylib[&#34;serde (dylib)&#34;];
      bin-.-&gt;serde_json_dylib[&#34;serde_json (dylib)&#34;];
      serde_json_dylib--&gt;serde_json;
      serde_json-.-&gt;serde_dylib;
      serde_dylib--&gt;serde;
&lt;/div&gt;
&lt;/figure&gt;


&lt;p&gt;However, this unfortunately is not straightforward.
If serde would specify a &lt;code&gt;crate-type&lt;/code&gt; of dylib in addition to &lt;code&gt;rlib&lt;/code&gt;, we could use &lt;code&gt;RUSTFLAGS=&amp;quot;-C prefer-dynamic&amp;quot;&lt;/code&gt; to build it as a dylib and have both our binary as well as &lt;code&gt;serde_json&lt;/code&gt; depend on it dynamically.
Unfortunately, serde does not specify that &lt;code&gt;crate-type&lt;/code&gt; so the only solution that makes this currently work is to clone &lt;a href=&#34;https://github.com/serde-rs/json&#34;&gt;https://github.com/serde-rs/json&lt;/a&gt; and use a modified version of it that points to a dynamic &lt;code&gt;serde&lt;/code&gt; lib.
Now this is certainly undesirable.&lt;/p&gt;
&lt;p&gt;For this specific scenario, a pull request against serde to allow for opt-in dylib builds might be one solution.
But generally, this seems like a shortcoming of how dylib builds can be specified: The crate that is to be consumed needs to do it via &lt;code&gt;crate-type&lt;/code&gt;.
Dependent crates cannot override this.
In my opinion this is something that could be added to Rust/Cargo as it looks like a backwards compatible addition.
Though there might be complications that I do not consider.&lt;/p&gt;
&lt;h2 id=&#34;switching-between-static-and-dynamic-dependencies&#34;&gt;Switching between static and dynamic dependencies&lt;/h2&gt;
&lt;p&gt;And this is how re-compilation can be improved when depending on &amp;ldquo;heavy&amp;rdquo; libraries.
You will probably not want to use this for production as this would mean having to ship additional libraries and making sure they can be found at runtime.
In addition, a number of optimizations won&amp;rsquo;t be available.&lt;/p&gt;
&lt;p&gt;So switching between a development and production version is advisable.
You can do this quite easily with a feature flag as just loading the dynamic library will force dynamic linking:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#![allow(unused_imports)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[cfg(feature = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;dynamic&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;polars_dynamic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;polars&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;prelude&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And &lt;code&gt;Cargo.toml&lt;/code&gt; would then specify:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;dependencies&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;polars&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0.23.2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;features&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[...]}&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;polars-dynamic&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;polars-dynamic&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;optional&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;features&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;default&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;dynamic&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;dep:polars-dynamic&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now &lt;code&gt;cargo build --feature dynamic&lt;/code&gt; will make use of the dynamic polars dependency.&lt;/p&gt;
&lt;h3 id=&#34;controlling---feature-dynamic-with-an-environment-variable&#34;&gt;Controlling &lt;code&gt;--feature dynamic&lt;/code&gt; with an environment variable&lt;/h3&gt;
&lt;p&gt;To make the feature selection automated based on environment variables, a suggestion from &lt;a href=&#34;https://beyermatthias.de/&#34;&gt;Matthias Beyer&lt;/a&gt; (thanks!) is to employ a &lt;code&gt;build.rs&lt;/code&gt; script such as&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;cargo:rerun-if-env-changed=DYNAMIC&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;env&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;DYNAMIC&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_ok&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;cargo:rustc-cfg=feature=\&amp;#34;dynamic\&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which can then be set like &lt;code&gt;DYNAMIC=1 cargo run&lt;/code&gt; or in a &lt;code&gt;.env&lt;/code&gt; file or similar.&lt;/p&gt;
&lt;h2 id=&#34;using-it-with-hot-reloading&#34;&gt;Using it with hot-reloading&lt;/h2&gt;
&lt;p&gt;This can be used in combination with &lt;a href=&#34;https://robert.kra.hn/posts/hot-reloading-rust/&#34;&gt;hot-reloading Rust code&lt;/a&gt;.
In particular, having the ability to replace behavior on-the-fly but having to wait for a long time on the compilation process makes little sense.
And indeed, several of the &lt;a href=&#34;https://github.com/rksm/hot-lib-reloader-rs/tree/master/examples&#34;&gt;hot-reload examples&lt;/a&gt; make use of this approach.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;MacBooPro M1 (MacBookPro18,3), 32GB RAM&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Hot Reloading Rust — for Fun and Faster Feedback Cycles</title>
      <link>https://robert.kra.hn/posts/hot-reloading-rust/</link>
      <pubDate>Thu, 04 Aug 2022 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/hot-reloading-rust/</guid>
      <description>

&lt;style&gt;
.figure-2 &gt; img {
   max-width: 500px;
}
@media only screen and (max-device-width: 768px) {
    .figure-2 &gt; img {
       max-width: 100%;
    }
}
&lt;/style&gt;




&lt;div style=&#34;padding: 2em 3em 4em;&#34;&gt;
&lt;div style=&#34;border: 1px dashed gray; padding: 0.5em;&#34;&gt;
&lt;h4&gt;TL;DR&lt;/h4&gt;
&lt;div style=&#34;padding: 0 0.8em; margin-top: -0.5em; &#34;&gt;
&lt;summary&gt;
&lt;a href=&#34;https://github.com/rksm/hot-lib-reloader-rs&#34;&gt;hot-lib-reloader&lt;/a&gt; allows to change Rust code on the fly without restarts.
It works on Linux, macOS, and Windows.
For why, how it works and, how to use it (as well as the limitations of this approach) read the post below.
&lt;/summary&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;




  &lt;figure class=&#34;center-figure figure-1&#34; style=&#34;display: flex; flex-direction: column; align-items: center; margin-bottom: 2.5em;&#34;&gt;
    &lt;a href=&#34;https://robert.kra.hn/posts/hot-reloading-rust/hot-reload-demo-short-2.gif&#34;&gt;
        &lt;img src=&#34;https://robert.kra.hn/posts/hot-reloading-rust/hot-reload-demo-short-2.gif&#34;&gt;
    &lt;/a&gt;
    &lt;div&gt;Hot-reloading a Bevy app&lt;/div&gt;
  &lt;/figure&gt;


&lt;p&gt;Development with Rust can be a lot of fun and the rich type system in combination with &lt;a href=&#34;https://robert.kra.hn/posts/rust-emacs-setup/&#34;&gt;good tooling&lt;/a&gt; such as &lt;a href=&#34;https://rust-analyzer.github.io/&#34;&gt;rust-analyzer&lt;/a&gt; can provide helpful hints and guidance continuously while writing code.&lt;/p&gt;
&lt;p&gt;This, however, does not fully compensate for slower workflows that come from edit-compile-run cycles that require full program restarts plus the time it takes to recompile the entire program.
Rust provides &lt;a href=&#34;https://blog.rust-lang.org/2016/09/08/incremental.html&#34;&gt;incremental compilation&lt;/a&gt; support that reduces the time for rebuilds often down to few seconds or for lightweight programs even less.
But relying on, for example, macro-heavy code or types that make ample use of generics, compile times can go up quickly.
This makes development with Rust quite different from &lt;a href=&#34;https://lively-next.org/&#34;&gt;lively&lt;/a&gt; environments and dynamic languages that might not just come with less build time but that might even provide feedback &lt;a href=&#34;https://youtu.be/wP5rdR1jc6o?t=2&#34;&gt;at the tip of a key&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Whether or not this impedes the ability to build software depends of course on what is built and on the approach a developer generally takes. For use cases such as games, UIs, or exploratory data analysis, quick feedback can certainly be an advantage — it might even allow you to make experiments that you would not have tried otherwise.&lt;/p&gt;
&lt;p&gt;To enable such dynamic workflows when programming Rust, I have long wanted a tool that makes immediate feedback possible and hopefully easy to use. This blog post presents my take on the matter by introducing the &lt;a href=&#34;https://crates.io/crates/hot-lib-reloader&#34;&gt;hot-lib-reloader crate&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#where-this-idea-comes-from&#34;&gt;Where this idea comes from&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#hello-world-example&#34;&gt;&amp;ldquo;Hello World&amp;rdquo; example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#caveats-and-asterisks&#34;&gt;Caveats and Asterisks&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#global-state&#34;&gt;Global state&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#dlopendlclose-behavior&#34;&gt;dlopen/dlclose behavior&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#function-signatures&#34;&gt;Function signatures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#supported-platforms&#34;&gt;Supported platforms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#how-to-use-it-then&#34;&gt;How to use it then?&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#use-features-to-toggle-hot-reload-support&#34;&gt;Use features to toggle hot reload support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#if-necessary-create-indirections&#34;&gt;If necessary, create indirections&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#how-to-use-it-with-bevy&#34;&gt;How to use it with Bevy?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#hot-reload-template-for-cargo-generate&#34;&gt;Hot-reload Template for cargo-generate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#comments-and-feedback&#34;&gt;Comments and feedback&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;changelog&#34;&gt;Changelog&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;2022-08-15: Update for &lt;code&gt;hot-lib-reloader&lt;/code&gt; v0.6&lt;/li&gt;
&lt;li&gt;2022-08-09: Update for &lt;code&gt;hot-lib-reloader&lt;/code&gt; v0.5&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;where-this-idea-comes-from&#34;&gt;Where this idea comes from&lt;/h1&gt;
&lt;p&gt;None of this is new of course.
Lots of languages and tools were created to allow code changes at runtime.
&lt;a href=&#34;https://youtu.be/uknEhXyZgsg?t=3558&#34;&gt;&amp;ldquo;Live programming&amp;rdquo; in Smalltalk&lt;/a&gt; and Lisps is an essential part of those languages and which is enabled by reflection APIs the languages possess as well as by tools that&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.
Also Erlang&amp;rsquo;s &lt;a href=&#34;https://kennyballou.com/blog/2016/12/elixir-hot-swapping/index.html&#34;&gt;hot code swapping&lt;/a&gt; plays an important role for the reliability of Erlang programs — upgrading them is not an &amp;ldquo;exception&amp;rdquo;, it is well supported out of the box.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Static&amp;rdquo; languages have traditionally much less support for the runtime code reload.
An important part of it is certainly that optimizations become much harder to achieve when assembly code needs to support being patched up later&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.
But even though modifying code arbitrarily is hard, dynamically loaded libraries &lt;a href=&#34;https://en.wikipedia.org/wiki/Dynamic_loading#History&#34;&gt;are an old idea&lt;/a&gt;.
Support for those is available in every (popular) operating system and it has been used to implement hot code reloading many times.&lt;/p&gt;
&lt;p&gt;For C / C++, this mechanism has been made popular by the &lt;a href=&#34;https://handmadehero.org/&#34;&gt;Handmade Hero series&lt;/a&gt; which presents this approach in detail (&lt;a href=&#34;https://www.youtube.com/watch?v=WMSBRk5WG58&#34;&gt;1&lt;/a&gt;, &lt;a href=&#34;https://www.youtube.com/watch?v=oijEnriqqcs&#34;&gt;2&lt;/a&gt;, &lt;a href=&#34;https://www.youtube.com/watch?v=xrUSrVvB21c&#34;&gt;3&lt;/a&gt;). 
And also in Rust there have been posts and libraries around this idea (for example &lt;a href=&#34;https://johnaustin.io/articles/2022/hot-reloading-rust&#34;&gt;Hot Reloading Rust: Windows and Linux&lt;/a&gt;, &lt;a href=&#34;https://github.com/irh/rust-hot-reloading&#34;&gt;An Example of Hot-Reloading in Rust&lt;/a&gt;, &lt;a href=&#34;https://github.com/porglezomp-misc/live-reloading-rs&#34;&gt;Live reloading for Rust&lt;/a&gt;, &lt;a href=&#34;https://crates.io/crates/dynamic_reload&#34;&gt;dynamic_reload&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Dynamic library (re-)loading is also what I am using in the approach presented here.
The fundamental implementation is quite similar to the work linked above.
Where this differs somewhat is in how you can interface with the reloader.
By using a macro that can figure out the exposed library functions, it is possible to avoid a lot of boilerplate.
In addition I will later show how this can be further customized to play nice in the context of frameworks such as Bevy.&lt;/p&gt;
&lt;h1 id=&#34;hello-world-example3&#34;&gt;&amp;ldquo;Hello World&amp;rdquo; example&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/h1&gt;
&lt;p&gt;The simplest example will require a binary with some kind of main loop and a library that contains the code to be reloaded.
Let&amp;rsquo;s assume the following project layout where the binary is the root package of a Cargo workspace and the library is a sub-package:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ tree
.
├── Cargo.toml
└── src
│   └── main.rs
└── lib
    ├── Cargo.toml
    └── src
        └── lib.rs
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The root &lt;code&gt;Cargo.toml&lt;/code&gt; defines the workspace and the binary. It will depend on the &lt;a href=&#34;https://crates.io/crates/hot-lib-reloader&#34;&gt;hot-lib-reloader crate&lt;/a&gt; that takes care of watching the library and reloading it when it changes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;workspace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;resolver&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;members&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;bin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;bin&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0.1.0&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;edition&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2021&amp;#34;&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;dependencies&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;hot-lib-reloader&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;^0.6&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;lib&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The library should expose functions and state.
It should have specify &lt;code&gt;dylib&lt;/code&gt; as crate type, meaning it will produce a dynamics library file such as &lt;code&gt;liblib.so&lt;/code&gt; (Linux), &lt;code&gt;liblib.dylib&lt;/code&gt; (macOS), and &lt;code&gt;lib.dll&lt;/code&gt; (Windows).
The &lt;code&gt;lib/Cargo.toml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0.1.0&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;edition&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2021&amp;#34;&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;lib&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;crate-type&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;rlib&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;dylib&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;lib/lib.rs&lt;/code&gt; is providing a single public and unmangled function &lt;code&gt;do_stuff&lt;/code&gt; that accepts some state parameter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// When using the source_files: [&amp;#34;path/to/lib.rs&amp;#34;] auto discovery
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// reloadable functions need to be public and have the #[no_mangle] attribute
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;State&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;counter&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;usize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[no_mangle]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;do_stuff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;: &lt;span class=&#34;kp&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;State&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;counter&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;doing stuff in iteration {}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;counter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally &lt;code&gt;src/main.rs&lt;/code&gt; where we define a sub-module &lt;code&gt;hot_lib&lt;/code&gt; using the &lt;code&gt;hot_module&lt;/code&gt; attribute macro:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// The value of `dylib = &amp;#34;...&amp;#34;` should be the library containing the hot-reloadable functions
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// It should normally be the crate name of your sub-crate.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[hot_lib_reloader::hot_module(dylib = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mod&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;hot_lib&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Reads public no_mangle functions from lib.rs and  generates hot-reloadable
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// wrapper functions with the same signature inside this module.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hot_functions_from_file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;lib/src/lib.rs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Because we generate functions with the exact same signatures,
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// we need to import types used
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lib&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;State&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hot_lib&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;State&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;counter&lt;/span&gt;: &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Running in a loop so you can modify the code and see the effects
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;loop&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hot_lib&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;do_stuff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;thread&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Duration&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;from_secs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Above is the part that matters: The &lt;code&gt;hot_lib&lt;/code&gt; module embeds a hot-reloadable version of &lt;code&gt;do_stuff(&amp;amp;mut State)&lt;/code&gt;.
It has the same signature as the original defined in &lt;code&gt;lib/lib.rs&lt;/code&gt; but it&amp;rsquo;s implementation will load it from the latest version of the dynamic library.
This means we can just use it like the original function but it will be automatically updated when the library file changes!
If you want to see the generated code that does all this you can run &lt;code&gt;cargo expand&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;OK, now we can actually run the app.
Start two cargo commands (this assumes you have &lt;a href=&#34;https://crates.io/crates/cargo-watch&#34;&gt;cargo-watch&lt;/a&gt; installed):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cargo watch -w lib -x &#39;build -p lib&#39;&lt;/code&gt; which will recompile the lib when it changes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cargo run&lt;/code&gt; which will start the app with hot-reloading enabled&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now modify the &lt;code&gt;do_stuff&lt;/code&gt; function, e.g. by changing the printed text or adding additional statements.
You should see the output of the running application change immediately.&lt;/p&gt;
&lt;h1 id=&#34;how-it-works&#34;&gt;How it works&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;hot-lib-reloader&lt;/code&gt; uses the &lt;a href=&#34;https://crates.io/crates/libloading&#34;&gt;libloading crate&lt;/a&gt; which provides a unified and safe(r) interface around functions provided by the operating system to load and unload dynamic libraries (&lt;code&gt;dlopen&lt;/code&gt;, &lt;code&gt;dlclose&lt;/code&gt;, &lt;code&gt;LoadLibraryEx&lt;/code&gt;,  etc.).
It watches the library file or files you specify using &lt;a href=&#34;https://crates.io/crates/notify&#34;&gt;notify&lt;/a&gt;.
When one of those changes it will mark the library as having a pending change.
&lt;a href=&#34;https://docs.rs/hot-lib-reloader/latest/hot_lib_reloader/struct.LibReloader.html#method.update&#34;&gt;LibReloader::update&lt;/a&gt; will then use &lt;code&gt;libloading&lt;/code&gt; to close the previously loaded library instance and load the new version.
The module generated with the &lt;a href=&#34;https://docs.rs/hot-lib-reloader/latest/hot_lib_reloader/attr.hot_module.html&#34;&gt;hot_module&lt;/a&gt; attribute macro above is a wrapper around a static instance of &lt;a href=&#34;https://docs.rs/hot-lib-reloader/latest/hot_lib_reloader/struct.LibReloader.html&#34;&gt;LibReloader::update&lt;/a&gt;.
Actual calls to library functions are then made by looking up a symbol with the matching function name, assuming it resolves to an actual function with the signature assumed, and then calling it.&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;


  &lt;figure class=&#34;center-figure figure-2&#34; style=&#34;display: flex; flex-direction: column; align-items: center; margin-bottom: 2.5em;&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/hot-reloading-rust/hot-lib-reloader.jpg&#34;
        style=&#34;object-fit: cover; object-position: -1px -1px;;&#34;&gt;
  &lt;/figure&gt;


&lt;p&gt;For various reasons the reloader will not actually load the library file that Rust created but will create a copy and load that. Among other things this prevents from holding a file lock on Windows, allowing the library file to change.&lt;/p&gt;
&lt;p&gt;In addition to that, the &lt;code&gt;hot_module&lt;/code&gt; macro takes care of some boilerplate. When declaring and using a reloader.
A desugared version of the function &lt;code&gt;do_stuff(&amp;amp;mut State)&lt;/code&gt; shown above will look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;do_stuff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;: &lt;span class=&#34;kp&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;State&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lib_loader&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;__lib_loader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lib_loader&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lib_loader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;lib loader RwLock read failed&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;unsafe&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lib_loader&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;           &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_symbol&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;State&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;b&amp;#34;do_stuff&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\x00&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;           &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Cannot load library function do_stuff&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sym&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In particular, without the macro it is necessary to keep the function signatures between where they are declared and where they are used in sync.
To avoid that boilerplate, the macro can automatically implement the correct interface by looking at the exported function in the specified source files.
In addition, &lt;code&gt;LibReloader&lt;/code&gt; actively watches for file changes and runs lib updates in its own thread.&lt;/p&gt;
&lt;h1 id=&#34;caveats-and-asterisks&#34;&gt;Caveats and Asterisks&lt;/h1&gt;
&lt;p&gt;This approach comes unfortunately with several caveats.
The runtime of the program that the lib reloader operates in is a compiled Rust application with everything that involves.
The memory layout of all types such as structs, enums, call frames, static string slices etc is fixed at compile time.
If it diverges between the running application and the (re-)loaded library the effect is &lt;a href=&#34;https://doc.rust-lang.org/reference/behavior-considered-undefined.html&#34;&gt;undefined&lt;/a&gt;.
In that case the program will probably segfault but it might keep running with incorrect behavior.
Because of that, all use of the reloader should be considered unsafe and I would highly advise against using it in situations where correctness and robustness of your application is required.
This means, don&amp;rsquo;t use it for production environments or anything critical.
The approach shown here is meant for development and fast feedback in situations where a crash is OK and nothing is at risk.&lt;/p&gt;
&lt;h3 id=&#34;global-state&#34;&gt;Global state&lt;/h3&gt;
&lt;p&gt;Because of that, what can actually be changed while maintaining the dynamic library re-loadable is limited.
You can expose functions with signatures that shouldn&amp;rsquo;t change or static global variables.
If exposing structs and enums, changing their struct fields is undefined behavior.
Using generics across the dynamic library border isn&amp;rsquo;t possible either as generic signatures will always be mangled.&lt;/p&gt;
&lt;p&gt;But state can get tricky in other ways as well. If global state is used by parts of a program that get reloaded, the state will no longer be accessible by the new code.
This for example can be observed when trying to reload the &lt;a href=&#34;https://github.com/not-fl3/macroquad&#34;&gt;macroquad&lt;/a&gt; / &lt;a href=&#34;https://github.com/not-fl3/miniquad&#34;&gt;miniquad&lt;/a&gt; game frameworks.
Those initialize and maintain OpenGL state globally.
When trying to call reloaded code that uses the OpenGL context such as emitting render instructions, the program will panic.
Even though it would be possible to externalize and transfer this state on reload and using the reloader with those frameworks won&amp;rsquo;t work, at least when directly accessing OpenGL related behavior.
For strategies around this see &lt;em&gt;&lt;a href=&#34;#how-to-use-it-then&#34;&gt;How to use it then?&lt;/a&gt;&lt;/em&gt; below.&lt;/p&gt;
&lt;h3 id=&#34;dlopendlclose-behavior&#34;&gt;dlopen/dlclose behavior&lt;/h3&gt;
&lt;p&gt;Furthermore, as pointed out &lt;a href=&#34;https://fasterthanli.me/articles/so-you-want-to-live-reload-rust#and-now-some-reloading&#34;&gt;in this really great blog post from Amos&lt;/a&gt; the behavior of &lt;code&gt;dlclose&lt;/code&gt; on Linux in combination with &lt;a href=&#34;https://github.com/rust-lang/rust/issues/59629&#34;&gt;how Rust deals with thread local storage&lt;/a&gt; can actually prevent a library from properly unloading.
Even though the approach presented here will actually allow you to load the changed behavior into your program, memory leaks cannot be prevented.
So while you reload on Linux you will leak some (tiny) amount of memory on each library update.&lt;/p&gt;
&lt;h3 id=&#34;function-signatures&#34;&gt;Function signatures&lt;/h3&gt;
&lt;p&gt;The function names of reloadable functions need to be not mangled, so a &lt;code&gt;#[no_mangle]&lt;/code&gt; attribute is mandatory.
This in turn means that functions cannot be generic (with the exception of lifetimes).
Assuming the rustc version of the code that compiles the binary and library are identical, the functions can be loaded even if not declared with &lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt;.
This in turn means that passing &amp;ldquo;normal&amp;rdquo; Rust types works fine.
I do not know enough about how the Rust compiler chooses the memory layout of structs and enums to know if the same (non-generic) struct / enum definition can be laid out differently between compilations when the code remains unchanged.
I assume not but if you run into problems making using &lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt; and &lt;code&gt;#[repr(C)]&lt;/code&gt; might be worth trying.&lt;/p&gt;
&lt;h3 id=&#34;supported-platforms&#34;&gt;Supported platforms&lt;/h3&gt;
&lt;p&gt;The current version of hot-lib-reloader has been tested successfully on Linux, Windows, and Intel macOS.&lt;/p&gt;
&lt;h1 id=&#34;how-to-use-it-then&#34;&gt;How to use it then?&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;2022-08-15: Also check the &lt;a href=&#34;https://github.com/rksm/hot-lib-reloader-rs#usage-tips&#34;&gt;usage tips section&lt;/a&gt; of the hot-lib-reloader readme.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The above mentioned limitations restrict the possibilities of what changes can be made to running code.&lt;/p&gt;
&lt;p&gt;What typically works well is to expose one or a few functions whose signatures remain unchanged.
Those can then be called from throughout your application.
If you want to split up your code further, using multiple libraries and reloaders at the same time is no problem.
The reloaders should regularly check if watched libraries have changed, for that purpose they provide an
&lt;a href=&#34;https://docs.rs/hot-lib-reloader/latest/hot_lib_reloader/struct.LibReloader.html#method.update&#34;&gt;update method&lt;/a&gt; that returns true if the library was indeed reloaded.
This gives you control over when reloads should happen and also allows you to run code to e.g. re-initialize state if the library changed.&lt;/p&gt;
&lt;p&gt;For example, for developing a game a simple approach would be to expose a &lt;code&gt;update(&amp;amp;mut State)&lt;/code&gt; function that modifies the game state and a &lt;code&gt;render(&amp;amp;State)&lt;/code&gt; function that takes care of rendering that.
Inside the game loop you call the update function of the lib reloader to process code changes and optionally re-initialize the game state.&lt;/p&gt;
&lt;p&gt;For frameworks such as Bevy where the main loop is controlled elsewhere, you can normally register callbacks or event handlers that will be invoked. For dealing with Bevy systems in particular, see below.&lt;/p&gt;
&lt;h3 id=&#34;use-features-to-toggle-hot-reload-support&#34;&gt;Use features to toggle hot reload support&lt;/h3&gt;
&lt;p&gt;Since only few parts of the application need to differ between a hot reloadable and a static version, using &lt;a href=&#34;https://doc.rust-lang.org/cargo/reference/features.html&#34;&gt;Rust features&lt;/a&gt; is the recommended way to selectively use hot code reloading and to also produce production code without any dependencies on dynamic library loading.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/rksm/hot-lib-reloader-rs/blob/master/examples/reload-feature/&#34;&gt;The reload-feature example&lt;/a&gt; shows how you can modify the minimal code example presented above to achieve this.&lt;/p&gt;
&lt;h3 id=&#34;if-necessary-create-indirections&#34;&gt;If necessary, create indirections&lt;/h3&gt;
&lt;p&gt;In cases like miniquad where global state prevents reloading a library you can fall back to creating an indirection.
For example if you want to have a render function that can be changed, you could use a function that decoratively constructs shapes / a scene graph that then gets rendered in the binary with calls that depend on OpenGL.&lt;/p&gt;
&lt;p&gt;When you have full control over the main loop&lt;/p&gt;
&lt;p&gt;Also, frameworks that follow a more &amp;ldquo;functional&amp;rdquo; style such as Bevy can be supported.
For Bevy in particular there exists specific support in hot-lib-reloader, see the next section for details.&lt;/p&gt;
&lt;h3 id=&#34;how-to-use-it-with-bevy&#34;&gt;How to use it with Bevy&lt;/h3&gt;
&lt;p&gt;Bevy manages the programs main loop by default and allows the user to specify functions (which represent the &amp;ldquo;systems&amp;rdquo; in Bevy&amp;rsquo;s ECS implementation) which are then invoked while the game is running.
It turns out this approach allows fits a hot-reloading mechanism really well.
The system functions can be seamlessly provided by either a statically linked or dynamically loaded library. All input they need they can specify by function parameters.
Bevy&amp;rsquo;s type-based &amp;ldquo;dependency injection&amp;rdquo; mechanism will then make sure to pass the right state to them.
In addition, Bevy&amp;rsquo;s resource system is a good fit to manage the lib reloader instance. A separate system can deal with the update cycle.&lt;/p&gt;
&lt;p&gt;You can find a ready-to-use example in the &lt;a href=&#34;https://github.com/rksm/hot-lib-reloader-rs/tree/master/examples/bevy&#34;&gt;examples section of hot-lib-reloader&lt;/a&gt;.
I will go through it step by step below.&lt;/p&gt;
&lt;p&gt;The project structure can be identical to the example show above. We will rename &lt;code&gt;lib&lt;/code&gt; to &lt;code&gt;systems&lt;/code&gt; to make our intentions explicit:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ tree
.
├── Cargo.toml
├── src
│   └── main.rs
└── systems
    ├── Cargo.toml
    └── src
        └── lib.rs
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;bevy-app-binary&#34;&gt;Bevy app binary&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;src/main.rs&lt;/code&gt; then defines a &lt;code&gt;systems_hot&lt;/code&gt; module which loads the functions provide by &lt;code&gt;systems/src/lib.rs&lt;/code&gt; that would normally be available through the &lt;code&gt;systems&lt;/code&gt; module.
In particular, &lt;code&gt;systems&lt;/code&gt; and &lt;code&gt;systems_hot&lt;/code&gt; are 1:1 replaceable when you export the static items from &lt;code&gt;systems&lt;/code&gt;, like we do below by adding &lt;code&gt;use systems::*;&lt;/code&gt; inside &lt;code&gt;mod systems_hot {/**/}&lt;/code&gt;.
A &lt;code&gt;reload&lt;/code&gt; feature is used to allow switching between static and hot-reload version.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bevy&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;prelude&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[cfg(not(feature = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;reload&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;))]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;systems&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[cfg(feature = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;reload&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;systems_hot&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[cfg(feature = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;reload&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[hot_lib_reloader::hot_module(dylib = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;systems&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mod&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;systems_hot&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bevy&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;prelude&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;systems&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hot_functions_from_file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;systems/src/lib.rs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can then define the &lt;code&gt;main&lt;/code&gt; function that does not differ from other Bevy apps.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;App&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_plugins&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DefaultPlugins&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_startup_system&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_system&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;player_movement_system&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_system&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bevy&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;window&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;close_on_esc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;bevy-systems&#34;&gt;Bevy systems&lt;/h4&gt;
&lt;p&gt;The two systems used in the example that are located in &lt;code&gt;systems/src/lib.rs&lt;/code&gt; are run-of-the-mill bevy system functions that I&amp;rsquo;ll abbreviate here to save some room.
The only notable piece here is the &lt;code&gt;#[no_mangle]&lt;/code&gt; attribute of &lt;code&gt;player_movement_system&lt;/code&gt; — and the absence of such an attribute with &lt;code&gt;setup&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;setup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;commands&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Commands&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/*...*/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[no_mangle]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;player_movement_system&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;keyboard_input&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KeyCode&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Query&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Transform&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;With&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Player&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/*...*/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Only public functions with &lt;code&gt;#[no_mangle]&lt;/code&gt; will be recognized as reloadable functions by the &lt;code&gt;hot_module&lt;/code&gt;&amp;rsquo;s &lt;code&gt;hot_functions_from_file!&lt;/code&gt; macro above.&lt;/p&gt;
&lt;p&gt;To build both the executable and reloadable systems library you can start two cargo processes.
Building the library:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# watch ./systems/, build the library&lt;/span&gt;
$ cargo watch -w systems -x &lt;span class=&#34;s1&#34;&gt;&amp;#39;build -p systems&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Building the executable (for the reason why Windows needs special treatment see &lt;a href=&#34;https://github.com/rksm/hot-lib-reloader-rs/tree/master/examples/bevy#windows&#34;&gt;this note&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# watch everything but ./systems and run the app&lt;/span&gt;
$ cargo watch -i systems -x &lt;span class=&#34;s1&#34;&gt;&amp;#39;run --features reload&amp;#39;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# Note: on windows use&lt;/span&gt;
$ env &lt;span class=&#34;nv&#34;&gt;CARGO_TARGET_DIR&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;target-bin cargo watch -i systems -x &lt;span class=&#34;s1&#34;&gt;&amp;#39;run --features reload&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using &lt;code&gt;cargo watch&lt;/code&gt; for the excutable is not strictly necessary but it allows you to quickly change it as well when you make modifications that aren&amp;rsquo;t compatible with hot-reload.&lt;/p&gt;
&lt;h3 id=&#34;hot-reload-template-for-cargo-generate&#34;&gt;Hot-reload Template for cargo-generate&lt;/h3&gt;
&lt;p&gt;To quickly setup new projects that come with the stuff presented here out of the box, you can use a &lt;a href=&#34;https://cargo-generate.github.io/cargo-generate/&#34;&gt;cargo-generate&lt;/a&gt; template available at: &lt;a href=&#34;https://github.com/rksm/rust-hot-reload&#34;&gt;https://github.com/rksm/rust-hot-reload&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;cargo generate rksm/rust-hot-reload&lt;/code&gt; to setup a new project.&lt;/p&gt;
&lt;h1 id=&#34;comments-and-feedback&#34;&gt;Comments and feedback&lt;/h1&gt;
&lt;p&gt;I just started to use hot-lib-reloader and so far I am surprised how well it works.
It is not bringing Rust on-par with Lisp or Smalltalk but with code that requires lots of twiddling and changes it is enjoyable to use!
Let me know what your impressions are either directly or via the discussions of this article on&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://news.ycombinator.com/item?id=32362836&#34;&gt;Hackernews&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/rust/comments/wfq0s5/hot_reloading_rust_for_fun_and_faster_feedback/&#34;&gt;Reddit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://lobste.rs/s/gqmbhl/hot_reloading_rust_for_fun_faster&#34;&gt;Lobsters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, if you find bugs or run into problems I&amp;rsquo;m watching the &lt;a href=&#34;https://github.com/rksm/hot-lib-reloader-rs/issues&#34;&gt;Github issues&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Over and out.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;For a detailed look on how Smalltalk achieves this, &lt;a href=&#34;http://soft.vub.ac.be/Publications/2002/vub-prog-tr-02-25.pdf&#34;&gt;Assisting System Evolution: A Smalltalk Retrospective&lt;/a&gt; is a recommended read.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Although with or without built-in support, &lt;a href=&#34;https://frida.re/&#34;&gt;folks are able to achieve it regardsless&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;No need to type that up or anything. &lt;a href=&#34;https://github.com/rksm/hot-lib-reloader-rs/tree/master/examples/minimal&#34;&gt;This&lt;/a&gt; and more examples can be found in the hot-lib-reloader example section.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    
    
    <item>
      <title>A Rust web server / frontend setup like it&#39;s 2022 (with axum and yew)</title>
      <link>https://robert.kra.hn/posts/2022-04-03_rust-web-wasm/</link>
      <pubDate>Sun, 03 Apr 2022 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/2022-04-03_rust-web-wasm/</guid>
      <description>

  &lt;script src=&#34;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js&#34;&gt;&lt;/script&gt;
  &lt;script&gt;
    mermaid.initialize({ startOnLoad: true });
  &lt;/script&gt;


&lt;p&gt;WebAssembly tooling for Rust has made big improvements and has matured tremendously over the previous two years. The build and packaging steps are now simpler thanks to tools like &lt;a href=&#34;https://trunkrs.dev/&#34;&gt;Trunk&lt;/a&gt;, as well as being able to write frontend code with various frameworks such as &lt;a href=&#34;https://yew.rs/&#34;&gt;yew&lt;/a&gt; or &lt;a href=&#34;https://dioxuslabs.com/&#34;&gt;dioxus&lt;/a&gt;. Also support for wasm is now supported in quite a few crates, basic ones such as &lt;a href=&#34;https://github.com/chronotope/chrono&#34;&gt;chrono&lt;/a&gt; or higher level libraries such as &lt;a href=&#34;https://plotters-rs.github.io&#34;&gt;plotters&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Additionally, the available options on the Rust server-side have increased. With projects like &lt;a href=&#34;https://github.com/tower-rs/tower&#34;&gt;tower&lt;/a&gt; that provide reusable building blocks for clients / servers, web servers like &lt;a href=&#34;https://github.com/tokio-rs/axum&#34;&gt;axum&lt;/a&gt; came about that allow to quickly put together web apps without much boilerplate.&lt;/p&gt;
&lt;p&gt;In this walkthrough I will describe my current default project setup for web projects that use Rust for frontend and backend. It is suitable for typical single-page web apps that use WASM/JS for rendering and routing. I have used it for dashboards, browser games and such but it should be suitable for any web app that wants to use a Rust server and frontend. I am choosing axum for the server part and yew for the frontend but it should work similarly with other choices. As for the features it will provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Running server / frontend in dev mode with automatic reload&lt;/li&gt;
&lt;li&gt;Running server / client in production mode with pre-compiled sources&lt;/li&gt;
&lt;li&gt;Serving additional files from a &lt;code&gt;dist/&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Stub to allow adding more custom server logic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can find the full code at &lt;a href=&#34;https://github.com/rksm/axum-yew-setup&#34;&gt;https://github.com/rksm/axum-yew-setup&lt;/a&gt;. You can also use this code as a template to generate a new project using &lt;a href=&#34;https://cargo-generate.github.io/cargo-generate/&#34;&gt;cargo-generate&lt;/a&gt;: &lt;code&gt;cargo generate rksm/axum-yew-template&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#changelog&#34;&gt;Changelog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#tools-required&#34;&gt;Tools required&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#project-structure&#34;&gt;Project structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#server&#34;&gt;Server&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#adding-logging-to-the-server&#34;&gt;Adding logging to the server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#frontend&#34;&gt;Frontend&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#connecting-frontend-and-server&#34;&gt;Connecting frontend and server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#custom-server-requests-and-frontend-routing&#34;&gt;Custom server requests and frontend routing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#making-the-file-server-support-a-spa-app&#34;&gt;Making the file server support a SPA app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#conveniently-running-it&#34;&gt;Conveniently running it&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#a-note-on-trunk-watch-and-serve&#34;&gt;A note on Trunk watch and serve&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#what-to-deploy&#34;&gt;What to deploy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;changelog&#34;&gt;Changelog&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2023-03-13: No more axum-extra SPA router (thanks &lt;a href=&#34;https://www.reddit.com/user/harunahi/&#34;&gt;u/harunahi&lt;/a&gt; and &lt;a href=&#34;https://www.reddit.com/user/LiftingBanana/&#34;&gt;u/LiftingBanana&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;2023-01-15: Don&amp;rsquo;t need cargo-edit anymore (thanks &lt;a href=&#34;https://www.reddit.com/user/lucca_huguet/&#34;&gt;u/lucca_huguet&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;2023-01-09: Update for yew  v0.20 (thanks to &lt;a href=&#34;https://www.reddit.com/user/dvmitto/&#34;&gt;reddit user dvmitto&lt;/a&gt; for the nudge!)&lt;/li&gt;
&lt;li&gt;2022-09-13: Note about &lt;code&gt;strip = &amp;quot;symbols&amp;quot;&lt;/code&gt; breaks wasm code&lt;/li&gt;
&lt;li&gt;2022-07-11: Trunk now seems to support workspace projects and won&amp;rsquo;t recompile from scratch when the server code changes. So this guide now uses a workspace setup. Also fix adding the dependencies, there was an issue with specifying the crate features.&lt;/li&gt;
&lt;li&gt;2022-04-19: Fixed Trunk command (&lt;code&gt;trunk serve&lt;/code&gt;, not &lt;code&gt;trunk dev&lt;/code&gt;) and slightly shorter invocation of cargo watch. Thanks @trysetnull!&lt;/li&gt;
&lt;li&gt;2022-04-14: Update requirements (Rust wasm target and trunk &lt;a href=&#34;#A-note-on-Trunk-watch-and-serve&#34;&gt;always-rebuild-from-scratch-issue&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;2022-04-08: Fix for the &lt;code&gt;prod.sh&lt;/code&gt; script when using &lt;code&gt;SpaRouter&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;tools-required&#34;&gt;Tools required&lt;/h2&gt;
&lt;p&gt;This walkthrough relies on the following Rust tooling:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Rust wasm32 target. You can install it with &lt;code&gt;rustup target add wasm32-unknown-unknown&lt;/code&gt; (The target specification &amp;ldquo;triple&amp;rdquo; is the architecture, vendor and OS type. &lt;a href=&#34;https://rust-lang.github.io/rfcs/0131-target-specification.html&#34;&gt;&amp;ldquo;unknown&amp;rdquo; means don&amp;rsquo;t assume a runtime&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://trunkrs.dev/&#34;&gt;Trunk&lt;/a&gt;, a WASM web application bundler for Rust. Install with &lt;code&gt;cargo install trunk&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://watchexec.github.io/#cargo-watch&#34;&gt;cargo-watch&lt;/a&gt; for restarting commands on file change with &lt;code&gt;cargo watch ...&lt;/code&gt;. Install with &lt;code&gt;cargo install cargo-watch&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;project-structure&#34;&gt;Project structure&lt;/h2&gt;
&lt;p&gt;The directory and file structure is simple, we will setup a rust workspace with &lt;code&gt;server&lt;/code&gt; and &lt;code&gt;frontend&lt;/code&gt; subdirectories that host the server and frontend sub-projects.&lt;/p&gt;


&lt;div class=&#34;mermaid&#34;&gt;
flowchart TD;
    root([web-wasm-project])
    server([server]);
    frontend([frontend]);
    
    root --- server;
    root --- cargo_root(&#34;Cargo.toml (workspace)&#34;)
    root --- frontend;
    
    subgraph a
    server --- cargo_1(Cargo.toml)
    server --- main_1(src/main.rs)
    end

    subgraph b
    frontend --- cargo_2(Cargo.toml)
    frontend --- trunk_2(Trunk.toml)
    frontend --- index_2(index.html)
    frontend --- main_2(src/main.rs)
    end
&lt;/div&gt;


&lt;p&gt;We can set this up like that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;mkdir web-wasm-project
&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; web-wasm-project
cargo new --bin server --vcs none
cargo new --bin frontend --vcs none
&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; -e &lt;span class=&#34;s1&#34;&gt;&amp;#39;[workspace]\nmembers = [&amp;#34;server&amp;#34;, &amp;#34;frontend&amp;#34;]&amp;#39;&lt;/span&gt; &amp;gt; Cargo.toml
&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;target/\ndist/&amp;#34;&lt;/span&gt; &amp;gt; .gitignore
git init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;server&#34;&gt;Server&lt;/h2&gt;
&lt;p&gt;First, we add the depencies for the server:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; server
cargo add &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  axum &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  tower &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  tracing &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  tracing-subscriber &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  clap --features clap/derive &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  tokio --features tokio/full &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  tower-http --features tower-http/full
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can now add code for starting the axum server and serving a simple text output to get started. Edit &lt;code&gt;server/src/main.rs&lt;/code&gt; to match:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axum&lt;/span&gt;::&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;IntoResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;routing&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Router&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clap&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Parser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;net&lt;/span&gt;::&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IpAddr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ipv6Addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SocketAddr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;::&lt;span class=&#34;kt&#34;&gt;str&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;FromStr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Setup the command line interface with clap.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[derive(Parser, Debug)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[clap(name = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;server&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;, about = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;A server for our wasm project!&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Opt&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;/// set the listen addr
&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[clap(short = &amp;#39;a&amp;#39;, long = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;addr&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;, default_value = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;::1&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;addr&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;/// set the listen port
&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[clap(short = &amp;#39;p&amp;#39;, long = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;, default_value = &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;port&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;u16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[tokio::main]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;opt&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Opt&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;parse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Router&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;route&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sock_addr&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SocketAddr&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IpAddr&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;from_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;opt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unwrap_or&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IpAddr&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;V6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ipv6Addr&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;LOCALHOST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;opt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;listening on http://{}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sock_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axum&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Server&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sock_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;serve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;into_make_service&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Unable to start server&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IntoResponse&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;hello from server!&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The server can be started with &lt;code&gt;cargo run --bin server&lt;/code&gt; from the project root directory. You should see the &amp;ldquo;hello from server!&amp;rdquo; response at &lt;a href=&#34;http://%5B::1%5D:8080&#34;&gt;[::1]:8080&lt;/a&gt; and &lt;a href=&#34;http://localhost:8080&#34;&gt;localhost:8080&lt;/a&gt; (if you want to use the IPv4 address).&lt;/p&gt;
&lt;h3 id=&#34;adding-logging-to-the-server&#34;&gt;Adding logging to the server&lt;/h3&gt;
&lt;p&gt;For an HTTP server it is useful to log requests. Axum and tower already use &lt;a href=&#34;https://docs.rs/tracing/latest/tracing/&#34;&gt;tracing&lt;/a&gt; to provide async-aware structured logging. We can setup &lt;a href=&#34;https://docs.rs/tracing-subscriber/latest/tracing_subscriber/&#34;&gt;tracing-subscriber&lt;/a&gt; to log those traces to stdout and also extend the command-line interface to accept setting the log verbosity via cli arguments.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/server/src/main.rs b/server/src/main.rs
&lt;/span&gt;&lt;span class=&#34;gh&#34;&gt;index 0000000..0000000 100644
&lt;/span&gt;&lt;span class=&#34;gh&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;--- a/server/src/main.rs
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+++ b/server/src/main.rs
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;@@ -2,11 +2,17 @@ use axum::{response::IntoResponse, routing::get, Router};
&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt; use clap::Parser;
 use std::net::{IpAddr, Ipv6Addr, SocketAddr};
 use std::str::FromStr;
&lt;span class=&#34;gi&#34;&gt;+use tower::ServiceBuilder;
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+use tower_http::trace::TraceLayer;
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; 
 // Setup the command line interface with clap.
 #[derive(Parser, Debug)]
 #[clap(name = &amp;#34;server&amp;#34;, about = &amp;#34;A server for our wasm project!&amp;#34;)]
 struct Opt {
&lt;span class=&#34;gi&#34;&gt;+    /// set the log level
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    #[clap(short = &amp;#39;l&amp;#39;, long = &amp;#34;log&amp;#34;, default_value = &amp;#34;debug&amp;#34;)]
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    log_level: String,
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;     /// set the listen addr
     #[clap(short = &amp;#39;a&amp;#39;, long = &amp;#34;addr&amp;#34;, default_value = &amp;#34;::1&amp;#34;)]
     addr: String,
&lt;span class=&#34;gu&#34;&gt;@@ -20,14 +26,23 @@ struct Opt {
&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt; async fn main() {
     let opt = Opt::parse();
 
&lt;span class=&#34;gd&#34;&gt;-    let app = Router::new().route(&amp;#34;/&amp;#34;, get(hello));
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    // Setup logging &amp;amp; RUST_LOG from args
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    if std::env::var(&amp;#34;RUST_LOG&amp;#34;).is_err() {
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+        std::env::set_var(&amp;#34;RUST_LOG&amp;#34;, format!(&amp;#34;{},hyper=info,mio=info&amp;#34;, opt.log_level))
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    }
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    // enable console logging
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    tracing_subscriber::fmt::init();
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    let app = Router::new()
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+        .route(&amp;#34;/&amp;#34;, get(hello))
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+        .layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()));
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; 
     let sock_addr = SocketAddr::from((
         IpAddr::from_str(opt.addr.as_str()).unwrap_or(IpAddr::V6(Ipv6Addr::LOCALHOST)),
         opt.port,
     ));
 
&lt;span class=&#34;gd&#34;&gt;-    println!(&amp;#34;listening on http://{}&amp;#34;, sock_addr);
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    log::info!(&amp;#34;listening on http://{}&amp;#34;, sock_addr);
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; 
     axum::Server::bind(&amp;amp;sock_addr)
         .serve(app.into_make_service())
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will modify the server later to serve static content as well but for now let&amp;rsquo;s stop it (Ctrl-C) and first setup the frontend.&lt;/p&gt;
&lt;h2 id=&#34;frontend&#34;&gt;Frontend&lt;/h2&gt;
&lt;p&gt;We will use &lt;a href=&#34;https://trunkrs.dev/&#34;&gt;Trunk&lt;/a&gt; to bundle and serve (for development) the frontend code. You can install trunk with &lt;code&gt;cargo install trunk&lt;/code&gt;. (As of this writing trunk version 0.16 is the most recent version and what was used for testing.)&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s first add all the dependencies we (eventually) need:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; frontend&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
cargo add &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  console_error_panic_hook &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  gloo-net &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  wasm-bindgen-futures &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  wasm-logger &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  yew --features yew/csr &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  yew-router
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are missing &lt;code&gt;frontend/index.html&lt;/code&gt; which Trunk will use as the base html template. Create that file and edit it to match:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;meta&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;charset&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;utf-8&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;link&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;rel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;shortcut icon&amp;#34;&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;image/x-icon&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;data:image/x-icon;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Yew App&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;loading...&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now edit &lt;code&gt;frontend/src/main.rs&lt;/code&gt; for rendering a simple yew component:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;yew&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;prelude&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;yew_router&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;prelude&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[derive(Clone, Routable, PartialEq)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Route&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[at(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Home&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;switch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;routes&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Route&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Html&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;routes&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Route&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Home&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hello Frontend&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[function_component(App)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Html&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BrowserRouter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Switch&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Route&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;render&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;switch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BrowserRouter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wasm_logger&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;init&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wasm_logger&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Config&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;log&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Level&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Trace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;console_error_panic_hook&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;set_once&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;yew&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Renderer&lt;/span&gt;::&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;App&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;render&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are already using the yew router to make it easier to extend the app later. Running &lt;code&gt;trunk serve&lt;/code&gt; (from the frontend directory) will now start the frontend in dev mode at &lt;a href=&#34;http://localhost:8080&#34;&gt;localhost:8080&lt;/a&gt;. Making a change to the frontend code will automatically reload that page. Hot-reload &amp;amp; Rust — finally :)&lt;/p&gt;
&lt;h3 id=&#34;connecting-frontend-and-server&#34;&gt;Connecting frontend and server&lt;/h3&gt;
&lt;p&gt;Right now, the frontend and server only run individually but are not connected in a way that would allow them to run together in development or production mode. For production mode (serving pre-compiled frontend files without Trunk) to work properly we will need to serve those static files. To also allow a single-page app (SPA) app that uses different URL path in the frontend, we need to fallback to serve &lt;code&gt;index.html&lt;/code&gt; for non-existing paths.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s first modify the frontend to compile into a &lt;code&gt;dist/&lt;/code&gt; directory in the project root folder where files can be found by the server. Create a file &lt;code&gt;frontend/Trunk.toml&lt;/code&gt; with the content:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;build&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;target&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;index.html&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nx&#34;&gt;dist&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;../dist&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can now modify the server to deliver the pre-compiled files. We make three changes to the server code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We will allow to configure a &lt;code&gt;static_dir&lt;/code&gt; directory that defaults to the &lt;code&gt;dist/&lt;/code&gt; folder in the project root directory. This is where we have configured Trunk to output compiled files in &lt;code&gt;Trunk.toml&lt;/code&gt; above.&lt;/li&gt;
&lt;li&gt;We will use &lt;code&gt;tower_http::services::ServeDir&lt;/code&gt; to actually create a response for requests matching a file path. We will do that by adding a &lt;code&gt;fallback&lt;/code&gt; handler to the server-side &lt;code&gt;Router&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We move our &amp;ldquo;hello&amp;rdquo; route to &lt;code&gt;/api/hello&lt;/code&gt;, we will query that later from the frontend to showcase client-server interaction.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/server/src/main.rs b/server/src/main.rs
&lt;/span&gt;&lt;span class=&#34;gh&#34;&gt;index 0000000..0000000 100644
&lt;/span&gt;&lt;span class=&#34;gh&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;@@ -1,8 +1,11 @@
&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+use axum::body::{boxed, Body};
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+use axum::http::{Response, StatusCode};
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; use axum::{response::IntoResponse, routing::get, Router};
 use clap::Parser;
 use std::net::{IpAddr, Ipv6Addr, SocketAddr};
 use std::str::FromStr;
&lt;span class=&#34;gd&#34;&gt;-use tower::ServiceBuilder;
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+use tower::{ServiceBuilder, ServiceExt};
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+use tower_http::services::ServeDir;
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; use tower_http::trace::TraceLayer;
 
 // Setup the command line interface with clap.
&lt;span class=&#34;gu&#34;&gt;@@ -20,6 +23,10 @@ struct Opt {
&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt;     /// set the listen port
     #[clap(short = &amp;#39;p&amp;#39;, long = &amp;#34;port&amp;#34;, default_value = &amp;#34;8080&amp;#34;)]
     port: u16,
&lt;span class=&#34;gi&#34;&gt;+
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    /// set the directory where static files are to be found
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    #[clap(long = &amp;#34;static-dir&amp;#34;, default_value = &amp;#34;./dist&amp;#34;)]
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    static_dir: String,
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; }
 
 #[tokio::main]
&lt;span class=&#34;gu&#34;&gt;@@ -34,7 +41,16 @@ async fn main() {
&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt;     tracing_subscriber::fmt::init();
 
     let app = Router::new()
&lt;span class=&#34;gd&#34;&gt;-        .route(&amp;#34;/&amp;#34;, get(hello))
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+        .route(&amp;#34;/api/hello&amp;#34;, get(hello))
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+        .fallback_service(get(|req| async move {
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+            match ServeDir::new(opt.static_dir).oneshot(req).await {
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                Ok(res) =&amp;gt; res.map(boxed),
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                Err(err) =&amp;gt; Response::builder()
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                    .status(StatusCode::INTERNAL_SERVER_ERROR)
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                    .body(boxed(Body::from(format!(&amp;#34;error: {err}&amp;#34;))))
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                    .expect(&amp;#34;error response&amp;#34;),
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+            }
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+        }))
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;         .layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()));
 
     let sock_addr = SocketAddr::from((
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you now run &lt;code&gt;trunk build&lt;/code&gt; in the &lt;code&gt;frontend/&lt;/code&gt; directory and &lt;code&gt;cargo run --bin server&lt;/code&gt; in the root directory, the server should startup again, this time bringing up the yew app at &lt;a href=&#34;http://localhost:8080&#34;&gt;localhost:8080&lt;/a&gt; again, but served statically!&lt;/p&gt;
&lt;h3 id=&#34;custom-server-requests-and-frontend-routing&#34;&gt;Custom server requests and frontend routing&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s query the &lt;code&gt;/api/hello&lt;/code&gt; from the frontend.&lt;/p&gt;
&lt;p&gt;First we will create a new yew component whose whole purpose it is to make a HTTP request to &lt;code&gt;/api/hello&lt;/code&gt; and display it. Add it to &lt;code&gt;frontend/main.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#[function_component(HelloServer)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;hello_server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Html&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;use_state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Request `/api/hello` once
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;use_effect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;move&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_none&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spawn_local&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;move&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Request&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/api/hello&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unwrap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                            &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;format!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                                &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Error fetching data {} ({})&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                                &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                                &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;await&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map_err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as_ref&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;No server response&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Ok&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Got server response: &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Error requesting data from server: &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition we will also setup an additional frontend route to render the new component at &lt;a href=&#34;http://localhost:8080/hello-server&#34;&gt;localhost:8080/hello-server&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/frontend/src/main.rs b/frontend/src/main.rs
&lt;/span&gt;&lt;span class=&#34;gh&#34;&gt;index 0000000..0000000 100644
&lt;/span&gt;&lt;span class=&#34;gh&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;--- a/frontend/src/main.rs
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+++ b/frontend/src/main.rs
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;@@ -1,3 +1,5 @@
&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+use gloo_net::http::Request;
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+use wasm_bindgen_futures::spawn_local;
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; use yew::prelude::*;
 use yew_router::prelude::*;
 
&lt;span class=&#34;gu&#34;&gt;@@ -5,11 +7,14 @@ use yew_router::prelude::*;
&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt; enum Route {
     #[at(&amp;#34;/&amp;#34;)]
     Home,
&lt;span class=&#34;gi&#34;&gt;+    #[at(&amp;#34;/hello-server&amp;#34;)]
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    HelloServer,
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; }
 
 fn switch(routes: &amp;amp;Route) -&amp;gt; Html {
     match routes {
         Route::Home =&amp;gt; html! { &amp;lt;h1&amp;gt;{ &amp;#34;Hello Frontend&amp;#34; }&amp;lt;/h1&amp;gt; },
&lt;span class=&#34;gi&#34;&gt;+        Route::HelloServer =&amp;gt; html! { &amp;lt;HelloServer /&amp;gt; },
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;     }
 } 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s test it! Start the server on port 8081 and the frontend in dev mode with a proxy for api requests:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cargo run --bin server -- --port 8081&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd frontend; trunk serve --proxy-backend=http://[::1]:8081/api/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you open your web browser at &lt;a href=&#34;http://localhost:8080/hello-server&#34;&gt;localhost:8080/hello-server&lt;/a&gt; you should now see:&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/2022-04-03_rust-web-wasm/ohyeah.png&#34; style=&#34;max-height: 130px&#34;&gt; 
  &lt;/figure&gt;


&lt;p&gt;But what happens when we serve the app statically?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cd frontend; trunk build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cargo run --bin server&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://localhost:8080/hello-server&#34;&gt;localhost:8080/hello-server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


  &lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/2022-04-03_rust-web-wasm/ohno.png&#34; style=&#34;max-height: 330px&#34;&gt; 
  &lt;/figure&gt;


&lt;p&gt;Oh no.&lt;/p&gt;
&lt;h3 id=&#34;making-the-file-server-support-a-spa-app&#34;&gt;Making the file server support a SPA app&lt;/h3&gt;
&lt;p&gt;The reason for that is of course that the server tries to find the path &lt;code&gt;/hello-server&lt;/code&gt; in the file system due to the fallback handler as no other server-side route matches it. The client-side routes require &lt;code&gt;index.html&lt;/code&gt; to be loaded so that the JavaScript / WASM code can handle the request as we expect in a single-page application. In order to make it work we will need to have our fallback handler not give a 404 response when it cannot find a resource but return the index file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/server/src/main.rs b/server/src/main.rs
&lt;/span&gt;&lt;span class=&#34;gh&#34;&gt;index 0000000..0000000 100644
&lt;/span&gt;&lt;span class=&#34;gh&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;@@ -3,7 +3,9 @@ use axum::http::{Response, StatusCode};
&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt; use axum::{response::IntoResponse, routing::get, Router};
 use clap::Parser;
 use std::net::{IpAddr, Ipv6Addr, SocketAddr};
&lt;span class=&#34;gi&#34;&gt;+use std::path::PathBuf;
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; use std::str::FromStr;
&lt;span class=&#34;gi&#34;&gt;+use tokio::fs;
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt; use tower::{ServiceBuilder, ServiceExt};
 use tower_http::services::ServeDir;
 use tower_http::trace::TraceLayer;
&lt;span class=&#34;gu&#34;&gt;@@ -43,8 +45,28 @@ async fn main() {
&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt;     let app = Router::new()
         .route(&amp;#34;/api/hello&amp;#34;, get(hello))
         .fallback(get(|req| async move {
&lt;span class=&#34;gd&#34;&gt;-            match ServeDir::new(opt.static_dir).oneshot(req).await {
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;-                Ok(res) =&amp;gt; res.map(boxed),
&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+            match ServeDir::new(&amp;amp;opt.static_dir).oneshot(req).await {
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                Ok(res) =&amp;gt; {
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                    let status = res.status();
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                    match status {
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                        StatusCode::NOT_FOUND =&amp;gt; {
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                            let index_path = PathBuf::from(&amp;amp;opt.static_dir).join(&amp;#34;index.html&amp;#34;);
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                            let index_content = match fs::read_to_string(index_path).await {
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                Err(_) =&amp;gt; {
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                    return Response::builder()
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                        .status(StatusCode::NOT_FOUND)
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                        .body(boxed(Body::from(&amp;#34;index file not found&amp;#34;)))
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                        .unwrap()
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                }
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                Ok(index_content) =&amp;gt; index_content,
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                            };
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                            Response::builder()
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                .status(StatusCode::OK)
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                .body(boxed(Body::from(index_content)))
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                                .unwrap()
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                        }
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                        _ =&amp;gt; res.map(boxed),
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                    }
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+                }
&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;                 Err(err) =&amp;gt; Response::builder()
                     .status(StatusCode::INTERNAL_SERVER_ERROR)
                     .body(boxed(Body::from(format!(&amp;#34;error: {err}&amp;#34;))))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;conveniently-running-it&#34;&gt;Conveniently running it&lt;/h3&gt;
&lt;p&gt;For running the dev or static version I prefer putting the necessary cargo commands into scripts. &lt;code&gt;dev.sh&lt;/code&gt; runs both Trunk and the server at the same time. The server is started using &lt;a href=&#34;https://watchexec.github.io/#cargo-watch&#34;&gt;cargo-watch&lt;/a&gt;, a useful utility to detect file changes. In combination with &lt;code&gt;trunk serve&lt;/code&gt; this will auto-reload both client and server!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -euo pipefail
&lt;span class=&#34;nv&#34;&gt;IFS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;$&amp;#39;\n\t&amp;#39;&lt;/span&gt;

&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;trap&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;kill 0&amp;#39;&lt;/span&gt; SIGINT&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt; bash -c &lt;span class=&#34;s1&#34;&gt;&amp;#39;cd frontend; trunk serve --proxy-backend=http://[::1]:8081/api/&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt; bash -c &lt;span class=&#34;s1&#34;&gt;&amp;#39;cargo watch -- cargo run --bin server -- --port 8081&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;prod.sh&lt;/code&gt; will build the frontend and run the server:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -euo pipefail
&lt;span class=&#34;nv&#34;&gt;IFS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;$&amp;#39;\n\t&amp;#39;&lt;/span&gt;

&lt;span class=&#34;nb&#34;&gt;pushd&lt;/span&gt; frontend
trunk build
&lt;span class=&#34;nb&#34;&gt;popd&lt;/span&gt;

cargo run --bin server --release -- --port &lt;span class=&#34;m&#34;&gt;8080&lt;/span&gt; --static-dir ./dist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this is it! A complete starter pack for a full Rust web app!&lt;/p&gt;
&lt;h4 id=&#34;a-note-about-a-bug-stripping-symbols-in-wasm-code&#34;&gt;A note about a bug stripping symbols in wasm code&lt;/h4&gt;
&lt;p&gt;Please note that &lt;a href=&#34;https://github.com/rust-lang/rust/issues/93294&#34;&gt;there is an open rust compiler bug&lt;/a&gt; when enabling stripping symbols that breaks wasm code.&lt;/p&gt;
&lt;p&gt;As &lt;a href=&#34;https://github.com/rksm/axum-yew-setup/issues/5&#34;&gt;reported by&lt;/a&gt; &lt;a href=&#34;https://github.com/malaire&#34;&gt;@malaire&lt;/a&gt;, a setting like &lt;code&gt;profile.release.strip = true&lt;/code&gt; will result in the example above not loading.
For the time being, only &lt;code&gt;strip = &amp;quot;debuginfo&amp;quot;&lt;/code&gt; is working.&lt;/p&gt;
&lt;h4 id=&#34;a-note-on-trunk-watch-and-serve&#34;&gt;A note on Trunk watch and serve&lt;/h4&gt;
&lt;p&gt;Should you observe that &lt;code&gt;trunk serve&lt;/code&gt; is rebuilding your frontend project from scratch each time you save a file, this can be one of two things:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/thedodd/trunk/issues/238&#34;&gt;There is an open issue&lt;/a&gt; with the file watcher that won&amp;rsquo;t debounce file change events. &lt;a href=&#34;https://github.com/thedodd/trunk/pull/350&#34;&gt;Just recently (2022-04-13) a fix was merged&lt;/a&gt; that is currently only on Trunk master. Use &lt;code&gt;cargo install trunk --git https://github.com/thedodd/trunk&lt;/code&gt; for installing the most recent version. (Update on 2023-01-09: This seems now to be in the Trunk release version as well.)&lt;/p&gt;
&lt;p&gt;On Linux even this did not fix the behavior for me. I needed to specify I separate cargo target dir to untangle rust-analyzer from trunks build directory: Using &lt;code&gt;bash -c &#39;cd frontend; CARGO_TARGET_DIR=target-trunk trunk serve&#39;&lt;/code&gt; in &lt;code&gt;dev.sh&lt;/code&gt; fixed that.&lt;/p&gt;
&lt;h4 id=&#34;what-to-deploy&#34;&gt;What to deploy&lt;/h4&gt;
&lt;p&gt;If you want to deploy just the server and dist repo to some machine, you will only need to build the frontend and the server binary (&lt;code&gt;cd server; cargo build --release&lt;/code&gt;), take &lt;code&gt;server/target/release/server&lt;/code&gt; and &lt;code&gt;dist/&lt;/code&gt; and put it into the same directory. If you then start the server with &lt;code&gt;--static-dir ./dist&lt;/code&gt; it will run as well.&lt;/p&gt;
</description>
    </item>
    
    
    
    
    
    
    
    <item>
      <title>Configuring Emacs for Rust development</title>
      <link>https://robert.kra.hn/posts/rust-emacs-setup/</link>
      <pubDate>Sun, 07 Feb 2021 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/rust-emacs-setup/</guid>
      <description>

  &lt;figure class=&#34;center-figure&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/rust-emacs-setup/demo.png&#34; style=&#34;max-height: 620px&#34;&gt; 
  &lt;/figure&gt;


&lt;p&gt;Rust support in Emacs improved &lt;em&gt;a lot&lt;/em&gt; during the past two years. This post will walk you through setting up Emacs to allow for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Navigating the source code (go to to implementation, list references, outline module structure)&lt;/li&gt;
&lt;li&gt;Code completion&lt;/li&gt;
&lt;li&gt;Code snippets&lt;/li&gt;
&lt;li&gt;Highlighting errors and warnings inline&lt;/li&gt;
&lt;li&gt;Apply code fixes and refactorings&lt;/li&gt;
&lt;li&gt;Automatically import definitions if necessary (such as for Traits)&lt;/li&gt;
&lt;li&gt;Code formatting with rustfmt&lt;/li&gt;
&lt;li&gt;Building &amp;amp; running other cargo commands&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This setup will be based on &lt;a href=&#34;https://rust-analyzer.github.io/&#34;&gt;rust-analyzer&lt;/a&gt;, a LSP server that is under very active development and powers the Rust support in VS Code as well.&lt;/p&gt;
&lt;p&gt;This post is accompanied by a &lt;a href=&#34;https://github.com/rksm/emacs-rust-config&#34;&gt;github repository&lt;/a&gt; that you can use as a reference or directly checkout and run Emacs with (&lt;a href=&#34;#quickstart&#34;&gt;see below&lt;/a&gt;). I&amp;rsquo;ve tested the configuration with Emacs 28.2, rust stable 1.66.0 and on macOS 13.1, Ubuntu 22.04 and Windows 10.&lt;/p&gt;
&lt;p&gt;For a setup that uses the emacs-racer backend&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; please see &lt;a href=&#34;https://github.crookster.org/my-emacs-rust-language-config/&#34;&gt;David Crook&amp;rsquo;s guide&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#changelog&#34;&gt;Changelog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#quickstart&#34;&gt;Quickstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#prerequisites&#34;&gt;Prerequisites&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#rust&#34;&gt;Rust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#rust-analyzer&#34;&gt;rust-analyzer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#rust-analyzer&#34;&gt;Emacs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#rust-emacs-configuration-in-detail&#34;&gt;Rust Emacs Configuration in Detail&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#rustic&#34;&gt;rustic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#lsp-mode-and-lsp-ui-mode&#34;&gt;lsp-mode and lsp-ui-mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#code-navigation&#34;&gt;Code navigation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#code-actions&#34;&gt;Code actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#code-completion-and-snippets&#34;&gt;Code completion and snippets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#inline-errors&#34;&gt;Inline errors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#inline-type-hints&#34;&gt;Inline type hints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#rust-playground&#34;&gt;Rust playground&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#additional-packages&#34;&gt;Additional packages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#debugging&#34;&gt;Debugging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#thanks-to-all-the-package-maintainers&#34;&gt;Thanks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;changelog&#34;&gt;Changelog&lt;/h2&gt;
&lt;p&gt;Changes made to this guide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2023-07-23: &lt;code&gt;lsp-rust-analyzer-server-display-inlay-hints&lt;/code&gt; was removed, use &lt;code&gt;lsp-inlay-hint-enable&lt;/code&gt; instead (thank you Wojciech!)&lt;/li&gt;
&lt;li&gt;2023-02-22: Inlay hints work well again (&lt;a href=&#34;https://github.com/emacs-lsp/lsp-mode/issues/3896&#34;&gt;https://github.com/emacs-lsp/lsp-mode/issues/3896&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;2023-01-10: Currently inlay hints on rust-analyzer versions newer than 2022-12-19 won&amp;rsquo;t work&lt;/li&gt;
&lt;li&gt;2022-09-13: Use &lt;code&gt;lsp-format-buffer&lt;/code&gt; instead of &lt;code&gt;rustic-format-on-save&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;2022-06-19: Note about potential &lt;code&gt;LSP :: rust-analyzer failed to discover workspace&lt;/code&gt; error (thanks Fred Xia!)&lt;/li&gt;
&lt;li&gt;2022-03-26: Clarified that rustic derives from rust-mode&lt;/li&gt;
&lt;li&gt;2022-03-24: Inlay hints fixed &amp;amp; more inlay hints available&lt;/li&gt;
&lt;li&gt;2022-03-14: Note about broken lsp-lens-mode / inlay hints&lt;/li&gt;
&lt;li&gt;2021-11-28: Note about rust-playground&lt;/li&gt;
&lt;li&gt;2021-11-15: rust-analyzer installation / compatibility note&lt;/li&gt;
&lt;li&gt;2021-06-17: fix for &lt;a href=&#34;https://github.com/brotzeit/rustic/issues/253&#34;&gt;buffer-save-without-query&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;2021-03-06: add &lt;code&gt;lsp-rust-analyzer-server-display-inlay-hints&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;2021-02-08: Add dap debugging setup&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;quickstart&#34;&gt;Quickstart&lt;/h2&gt;
&lt;p&gt;If you have already Rust and Emacs installed (see &lt;a href=&#34;#prerequisites&#34;&gt;prerequisites&lt;/a&gt;) you can get quickly up and running without modifying any of your existing configuration. The &lt;a href=&#34;https://github.com/rksm/emacs-rust-config&#34;&gt;rksm/emacs-rust-config github repo&lt;/a&gt; contains a &lt;code&gt;standalone.el&lt;/code&gt; file that you can use to start Emacs with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ git clone https://github.com/rksm/emacs-rust-config
$ emacs -q --load ./emacs-rust-config/standalone.el
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will start Emacs with an &lt;code&gt;.emacs.d&lt;/code&gt; directory set to the location of the checked out repository (and a different elpa directory). This means, it will not use or modify your &lt;code&gt;$HOME/.emacs.d&lt;/code&gt;. If you are unsure if you are happy with what is described here, this is an easy way to figure it out.&lt;/p&gt;
&lt;p&gt;All dependencies will be installed on first startup, this means the first start will take a few seconds.&lt;/p&gt;
&lt;p&gt;On windows you can use a shortcut to start Emacs with those parameters. If you are on macOS and have installed the Emacs.app you will need to start Emacs from the command line with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;/Applications//Emacs.app/Contents/MacOS/Emacs -q --load ./emacs-rust-config/standalone.el
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Before we get to the actual Emacs configuration, please make sure your system is setup with the following.&lt;/p&gt;
&lt;h4 id=&#34;rust&#34;&gt;Rust&lt;/h4&gt;
&lt;p&gt;Install the rust toolchain with cargo. &lt;a href=&#34;https://rustup.rs/&#34;&gt;rustup&lt;/a&gt; makes that easy. Install rust stable and make sure that the &lt;code&gt;.cargo/bin&lt;/code&gt; directory is in your PATH. rustup will do this by default. rust-analyzer will also need the Rust source code and you can install that with &lt;code&gt;rustup component add rust-src&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;rust-analyzer&#34;&gt;rust-analyzer&lt;/h4&gt;
&lt;p&gt;You need the rust-analyzer server binary. You can install it following the rust &lt;a href=&#34;https://rust-analyzer.github.io/manual.html#rust-analyzer-language-server-binary&#34;&gt;analyzer manual&lt;/a&gt;, &lt;a href=&#34;https://github.com/rust-analyzer/rust-analyzer/releases&#34;&gt;pre-compiled binaries&lt;/a&gt; are available. However, since rust-analyzer is so actively developed I usually just clone the github repository and build the binary myself. This makes upgrading (and downgrading should it be necessary) very straightforward.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ git clone https://github.com/rust-analyzer/rust-analyzer.git -b release
$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; rust-analyzer
$ cargo xtask install --server &lt;span class=&#34;c1&#34;&gt;# will install rust-analyzer into $HOME/.cargo/bin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve heard that (very) occasionally the most recent version might not work. In that case I can recommend to take a look at the &lt;a href=&#34;https://rust-analyzer.github.io/thisweek&#34;&gt;rust-analyzer changelog&lt;/a&gt; which contains links to a git commit for each weeks update. In case you run into trouble, build from an earlier version, which will likely succeed.&lt;/p&gt;
&lt;p&gt;Please also make sure that your emacs packages are up-to-date, in particular &lt;code&gt;lsp-mode&lt;/code&gt; and &lt;code&gt;rustic-mode&lt;/code&gt; to ensure that the newest rust-analyzer features are supported.&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;If you need to run with an older version of rust-analyzer you can look for an older release tag with &lt;code&gt;git tag&lt;/code&gt; and then build against it like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;git checkout 2022-12-19
cargo xtask install --server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should work with older versions of the relevant emacs packages as well.&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;h4 id=&#34;emacs&#34;&gt;Emacs&lt;/h4&gt;
&lt;p&gt;I have tested the setup with Emacs 28.2. On macOS I normally use &lt;a href=&#34;https://emacsformacosx.com/&#34;&gt;emacsformacosx.com&lt;/a&gt;. On Windows I use the &amp;ldquo;nearby GNU mirror&amp;rdquo; link at &lt;a href=&#34;https://www.gnu.org/software/emacs/download.html&#34;&gt;gnu.org/software/emacs&lt;/a&gt;. On Ubuntu &lt;a href=&#34;https://ubuntuhandbook.org/index.php/2020/09/install-emacs-27-1-ppa-ubuntu-20-04/&#34;&gt;adding another apt repository&lt;/a&gt; is necessary. Note that the config will likely work with older Emacs versions but Emacs 27 got substantial improvements around JSON parsing which speeds up LSP clients quite a bit.&lt;/p&gt;
&lt;p&gt;Note that I use &lt;a href=&#34;https://github.com/jwiegley/use-package&#34;&gt;use-package&lt;/a&gt; for Emacs package management. It will be auto-installed in the standalone version of this config. Otherwise you can add a snippet like below to your &lt;code&gt;init.el&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(unless (package-installed-p &#39;use-package)
  (package-refresh-contents)
  (package-install &#39;use-package))
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;rust-emacs-configuration-in-detail&#34;&gt;Rust Emacs Configuration in Detail&lt;/h2&gt;
&lt;p&gt;The essential modes being used are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rustic&lt;/li&gt;
&lt;li&gt;lsp-mode&lt;/li&gt;
&lt;li&gt;company&lt;/li&gt;
&lt;li&gt;yasnippet&lt;/li&gt;
&lt;li&gt;flycheck&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;rustic&#34;&gt;Rustic&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/brotzeit/rustic&#34;&gt;rustic&lt;/a&gt; is an extension of &lt;code&gt;rust-mode&lt;/code&gt; which adds a number of useful features (see the its github readme) to it. It is the core of the setup and you can use just it without any other Emacs packages (and without rust-analyzer) if you just want code highlighting, compilation and cargo commands bound to emacs shortcuts, and a few other features.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(use-package rustic
  :ensure
  :bind (:map rustic-mode-map
              (&amp;quot;M-j&amp;quot; . lsp-ui-imenu)
              (&amp;quot;M-?&amp;quot; . lsp-find-references)
              (&amp;quot;C-c C-c l&amp;quot; . flycheck-list-errors)
              (&amp;quot;C-c C-c a&amp;quot; . lsp-execute-code-action)
              (&amp;quot;C-c C-c r&amp;quot; . lsp-rename)
              (&amp;quot;C-c C-c q&amp;quot; . lsp-workspace-restart)
              (&amp;quot;C-c C-c Q&amp;quot; . lsp-workspace-shutdown)
              (&amp;quot;C-c C-c s&amp;quot; . lsp-rust-analyzer-status))
  :config
  ;; uncomment for less flashiness
  ;; (setq lsp-eldoc-hook nil)
  ;; (setq lsp-enable-symbol-highlighting nil)
  ;; (setq lsp-signature-auto-activate nil)

  ;; comment to disable rustfmt on save
  (setq rustic-format-on-save t)
  (add-hook &#39;rustic-mode-hook &#39;rk/rustic-mode-hook))

(defun rk/rustic-mode-hook ()
  ;; so that run C-c C-c C-r works without having to confirm, but don&#39;t try to
  ;; save rust buffers that are not file visiting. Once
  ;; https://github.com/brotzeit/rustic/issues/253 has been resolved this should
  ;; no longer be necessary.
  (when buffer-file-name
    (setq-local buffer-save-without-query t))
  (add-hook &#39;before-save-hook &#39;lsp-format-buffer nil t))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Most of rustics features are bound to the &lt;code&gt;C-c C-c&lt;/code&gt; prefix (that is press Control-c twice and then another key):&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;display: flex; flex-direction: column; align-items: center; margin-bottom: 2.5em;&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/rust-emacs-setup/rustic-shortcuts-1.png&#34;
        style=&#34;object-fit: cover; object-position: -1px -1px;&#34;&gt;
    &lt;!-- &lt;div&gt;&lt;pre style=&#34;font-size: small; display: inline;&#34;&gt;C-c C-c&lt;/pre&gt; which key&lt;/div&gt; --&gt;
  &lt;/figure&gt;


&lt;p&gt;You can use &lt;code&gt;C-c C-c C-r&lt;/code&gt; to run the program via &lt;code&gt;cargo run&lt;/code&gt;. You will be asked for parameters and can for example specify &lt;code&gt;--release&lt;/code&gt; to run in release mode or &lt;code&gt;--bin other-bin&lt;/code&gt; to run the target named &amp;ldquo;other-bin&amp;rdquo; (instead of main.rs). To pass parameters to the executable itself use &lt;code&gt;-- --arg1 --arg2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The shortcut &lt;code&gt;C-c C-c C-c&lt;/code&gt; will run the test at point. Very handy to run inline tests and to not always have switch back-and-forth between a terminal and Emacs.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C-c C-p&lt;/code&gt; opens a popup buffer that will give you similar access to the commands shown above but will stick around.&lt;/p&gt;
&lt;p&gt;Rustic provides even more helpful integration with cargo, e.g. &lt;code&gt;M-x rustic-cargo-add&lt;/code&gt; will allow you to add dependencies to your projects &lt;code&gt;Cargo.toml&lt;/code&gt; (via &lt;a href=&#34;https://crates.io/crates/cargo-edit&#34;&gt;cargo-edit&lt;/a&gt; that will be installed on demand).&lt;/p&gt;
&lt;p&gt;If you would like to share a code snippet with others, &lt;code&gt;M-x rustic-playpen&lt;/code&gt; will open your current buffer in &lt;a href=&#34;https://play.rust-lang.org&#34;&gt;https://play.rust-lang.org&lt;/a&gt; where you can run the Rust code online and get a shareable link.&lt;/p&gt;
&lt;p&gt;Code formatting on save is enabled and will use rustfmt. To disable it set &lt;code&gt;(setq rustic-format-on-save nil)&lt;/code&gt;. You can still format a buffer on demand using &lt;code&gt;C-c C-c C-o&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;lsp-mode-and-lsp-ui-mode&#34;&gt;lsp-mode and lsp-ui-mode&lt;/h4&gt;
&lt;p&gt;lsp-mode provides &lt;a href=&#34;https://emacs-lsp.github.io/lsp-mode/page/lsp-rust/&#34;&gt;the integration&lt;/a&gt; with rust-analyzer. It enables the IDE features such as navigating through source code, highlighting errors via flycheck (see below) and provides the auto-completion source for company (also below).&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(use-package lsp-mode
  :ensure
  :commands lsp
  :custom
  ;; what to use when checking on-save. &amp;quot;check&amp;quot; is default, I prefer clippy
  (lsp-rust-analyzer-cargo-watch-command &amp;quot;clippy&amp;quot;)
  (lsp-eldoc-render-all t)
  (lsp-idle-delay 0.6)
  ;; enable / disable the hints as you prefer:
  (lsp-inlay-hint-enable t)
  ;; These are optional configurations. See https://emacs-lsp.github.io/lsp-mode/page/lsp-rust-analyzer/#lsp-rust-analyzer-display-chaining-hints for a full list
  (lsp-rust-analyzer-display-lifetime-elision-hints-enable &amp;quot;skip_trivial&amp;quot;)
  (lsp-rust-analyzer-display-chaining-hints t)
  (lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names nil)
  (lsp-rust-analyzer-display-closure-return-type-hints t)
  (lsp-rust-analyzer-display-parameter-hints nil)
  (lsp-rust-analyzer-display-reborrow-hints nil)
  :config
  (add-hook &#39;lsp-mode-hook &#39;lsp-ui-mode))

(use-package lsp-ui
  :ensure
  :commands lsp-ui-mode
  :custom
  (lsp-ui-peek-always-show t)
  (lsp-ui-sideline-show-hover t)
  (lsp-ui-doc-enable nil))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;lsp-ui is optional. It provides inline overlays over the symbol at point and enables code fixes at point. If you find it to flashy and prefer not activating it just remove &lt;code&gt;:config (add-hook &#39;lsp-mode-hook &#39;lsp-ui-mode)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The config shown above already disables the documentation normally shown inline by lsp-ui. This is too much for my taste as it often covers up source code. If you want to also deactivate the documentation shown in the minibuffer you can add &lt;code&gt;(setq lsp-eldoc-hook nil)&lt;/code&gt;. To do less when your cursor moves consider &lt;code&gt;(setq lsp-signature-auto-activate nil)&lt;/code&gt; and &lt;code&gt;(setq lsp-enable-symbol-highlighting nil)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;lsp-mode will try to figure out the project directory that rust-analyzer should use to index the project. When you first open a file inside a new project, you will be asked which directory to import:&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;display: flex; flex-direction: column; align-items: center; margin-bottom: 2.5em;&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/rust-emacs-setup/lsp-workspace-discovery.png&#34;
        style=&#34;object-fit: cover; object-position: -1px -1px;&#34;&gt;
  &lt;/figure&gt;


&lt;p&gt;The first selection (press i) will use the directory in which a &lt;code&gt;Cargo.toml&lt;/code&gt; file was found, potentially the workspace root if the crate you work on is inside a workspace. The second selection (I) will allow you to select the root project directory manually. The last selection (n) will prevent lsp from starting. Sometimes when you follow a reference to a library crate it can be useful to not enable lsp for it as the lsp startup and indexing well take some time for large code bases.&lt;/p&gt;
&lt;p&gt;lsp-mode remembers the choice for the project directory so the next time you open a file of a known project you do not need to make that selection again. If you ever want that, you can invoke the &lt;code&gt;lsp-workspace-folders-remove&lt;/code&gt; command to interactively remove directories from the list of known projects.&lt;/p&gt;
&lt;p&gt;Should you ever see an error such as &lt;code&gt;LSP :: rust-analyzer failed to discover workspace&lt;/code&gt; when trying to open a .rs file, try invoking the &lt;code&gt;lsp-workspace-folders-add&lt;/code&gt; manually and add the root project directory.&lt;/p&gt;
&lt;h4 id=&#34;code-navigation&#34;&gt;Code navigation&lt;/h4&gt;
&lt;p&gt;Having setup lsp-mode, you can use &lt;code&gt;M-.&lt;/code&gt; to jump to the definition of function, structs, packages etc. when your cursor is over a symbol. &lt;code&gt;M-,&lt;/code&gt; to jump back. With &lt;code&gt;M-?&lt;/code&gt; you can list all references of a symbol. A little demo:&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;display: flex; flex-direction: column; align-items: center; margin-bottom: 2.5em;&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/rust-emacs-setup/rust-lsp-demo-1.png&#34;
        style=&#34;object-fit: cover; object-position: -3px -2px;&#34;&gt;
  &lt;/figure&gt;


&lt;p&gt;With &lt;code&gt;M-j&lt;/code&gt; you can open up an outline of the current module that allows you to quickly navigate between functions and other definitions.&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;display: flex; flex-direction: column;&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/rust-emacs-setup/imenu.png&#34;/&gt;
  &lt;/figure&gt;


&lt;h4 id=&#34;code-actions&#34;&gt;Code actions&lt;/h4&gt;
&lt;p&gt;Refactorings are possible using &lt;code&gt;M-x lsp-rename&lt;/code&gt; and &lt;code&gt;lsp-execute-code-action&lt;/code&gt;. Code actions are basically code transformation and fixes. For example the linter may find a way to express code more idiomatically:&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;display: flex; flex-direction: column; align-items: center; margin-bottom: 2.5em;&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/rust-emacs-setup/rust-lsp-demo-2.gif&#34;
        style=&#34;object-fit: cover; object-position: -3px -2px;&#34;&gt;
  &lt;/figure&gt;


&lt;p&gt;The number of available code actions continuously growth. A full list is available in the &lt;a href=&#34;https://rust-analyzer.github.io/manual.html#assists-code-actions&#34;&gt;rust-analyzer documentation&lt;/a&gt;. Favorites include automatically importing functions or fully qualifying symbols. E.g. in a module that does not yet use HashMap, type &lt;code&gt;HashMap&lt;/code&gt; and then select the option to &lt;code&gt;Import std::collections::HashMap&lt;/code&gt;. Other code actions allow you to add all possible arms in a match expression or converting a &lt;code&gt;#[derive(Trait)]&lt;/code&gt; into the code needed for a custom implementation. And many, many more.&lt;/p&gt;
&lt;p&gt;If you developing macros, quickly seeing how they expand can be really useful. Use &lt;code&gt;M-x lsp-rust-analyzer-expand-macro&lt;/code&gt; or the shortcut &lt;code&gt;C-c C-c e&lt;/code&gt; to macroexpand.&lt;/p&gt;
&lt;h4 id=&#34;code-completion-and-snippets&#34;&gt;Code completion and snippets&lt;/h4&gt;
&lt;p&gt;lsp-mode directly integrates with &lt;a href=&#34;https://company-mode.github.io/&#34;&gt;company-mode&lt;/a&gt;, a completion framework for emacs. It will display a list of possible symbols that could be inserted at the cursor. It is very helpful when working with unknown libraries (or the std lib) and reduces the need for looking up documentation. Rust&amp;rsquo;s type system is used as a source for the completions and thus what you can insert makes (mostly) sense.&lt;/p&gt;
&lt;p&gt;By default the code completion popup will appear after &lt;code&gt;company-idle-delay&lt;/code&gt; which is set to 0.5 seconds by default. You can modify that value or disable the auto popup completely by setting &lt;code&gt;company-begin-commands&lt;/code&gt; to &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(use-package company
  :ensure
  :custom
  (company-idle-delay 0.5) ;; how long to wait until popup
  ;; (company-begin-commands nil) ;; uncomment to disable popup
  :bind
  (:map company-active-map
	      (&amp;quot;C-n&amp;quot;. company-select-next)
	      (&amp;quot;C-p&amp;quot;. company-select-previous)
	      (&amp;quot;M-&amp;lt;&amp;quot;. company-select-first)
	      (&amp;quot;M-&amp;gt;&amp;quot;. company-select-last)))

(use-package yasnippet
  :ensure
  :config
  (yas-reload-all)
  (add-hook &#39;prog-mode-hook &#39;yas-minor-mode)
  (add-hook &#39;text-mode-hook &#39;yas-minor-mode))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will also enable code snippets via &lt;a href=&#34;https://joaotavora.github.io/yasnippet/&#34;&gt;yasnippet&lt;/a&gt;. I have added the list of my &lt;a href=&#34;https://github.com/rksm/emacs-rust-config/tree/master/snippets/rustic-mode&#34;&gt;most commonly used snippets to the github repository&lt;/a&gt;. Feel free to copy and modify them. They work by typing a certain character sequence and then pressing TAB. For example &lt;code&gt;for&amp;lt;TAB&amp;gt;&lt;/code&gt; will expand into a for loop. You can customize what is being pre-filled and the number of stops while expanding and even run custom elisp code. See the yasnippet documentation.&lt;/p&gt;
&lt;p&gt;To enable snippet expansion, code completion and indentation when you press the TAB key, we need to &lt;a href=&#34;https://www.emacswiki.org/emacs/CompanyMode#h5o-11&#34;&gt;customize&lt;/a&gt; the command that is running when pressing TAB:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(use-package company
  ;; ... see above ...
  (:map company-mode-map
	(&amp;quot;&amp;lt;tab&amp;gt;&amp;quot;. tab-indent-or-complete)
	(&amp;quot;TAB&amp;quot;. tab-indent-or-complete)))

(defun company-yasnippet-or-completion ()
  (interactive)
  (or (do-yas-expand)
      (company-complete-common)))

(defun check-expansion ()
  (save-excursion
    (if (looking-at &amp;quot;\\_&amp;gt;&amp;quot;) t
      (backward-char 1)
      (if (looking-at &amp;quot;\\.&amp;quot;) t
        (backward-char 1)
        (if (looking-at &amp;quot;::&amp;quot;) t nil)))))

(defun do-yas-expand ()
  (let ((yas/fallback-behavior &#39;return-nil))
    (yas/expand)))

(defun tab-indent-or-complete ()
  (interactive)
  (if (minibufferp)
      (minibuffer-complete)
    (if (or (not yas/minor-mode)
            (null (do-yas-expand)))
        (if (check-expansion)
            (company-complete-common)
          (indent-for-tab-command)))))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;My most commonly used snippets are &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;log&lt;/code&gt;, &lt;code&gt;ifl&lt;/code&gt;, &lt;code&gt;match&lt;/code&gt; and &lt;code&gt;fn&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;inline-errors&#34;&gt;Inline errors&lt;/h4&gt;
&lt;p&gt;That one is easy, rustic does the heavy lifting. We just need to make sure flycheck is being loaded:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(use-package flycheck :ensure)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can display a list of errors and warnings using &lt;code&gt;M-x flycheck-list-errors&lt;/code&gt; or by pressing &lt;code&gt;C-c C-c l&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;inline-type-hints&#34;&gt;Inline type hints&lt;/h4&gt;
&lt;p&gt;Rust-analyzer and lsp-mode &lt;a href=&#34;https://emacs-lsp.github.io/lsp-mode/page/lsp-rust-analyzer/#inlay-hints&#34;&gt;are able to show inline type annotations&lt;/a&gt;. Normally, those would appear via eldoc when placing the cursor over the defined variable, with the annotations you will always see the inferred types. Use &lt;code&gt;(setq lsp-inlay-hint-enable t)&lt;/code&gt; to enable them&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. To actually insert an inferred type into the source code you can move your cursor over the defined variable and run &lt;code&gt;M-x lsp-execute-code-action&lt;/code&gt; or &lt;code&gt;C-c C-c a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that they might not interact well with &lt;code&gt;lsp-ui-sideline-mode&lt;/code&gt;. If you prefer the hints but want to disable sideline mode, you can add &lt;code&gt;(lsp-ui-sideline-enable nil)&lt;/code&gt; to a &lt;code&gt;rustic-mode-hook&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As of the rust-analyzer and lsp-mode versions of 2022-03-24 there are even more kinds of inline hints available which now include lifetime hints, intermediate types in method chains and more!&lt;/p&gt;
&lt;h2 id=&#34;debugging&#34;&gt;Debugging&lt;/h2&gt;
&lt;p&gt;Emacs integrates with gdb and lldb via the &lt;a href=&#34;https://emacs-lsp.github.io/dap-mode/&#34;&gt;dap-mode&lt;/a&gt; package&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. In order to setup debugging support for Rust, you will need to do some additional setup and build steps. In particular, you will need to have &lt;a href=&#34;https://github.com/lldb-tools/lldb-mi&#34;&gt;lldb-mi&lt;/a&gt; which is not part of the official llvm distribution that Apple provides via XCode.&lt;/p&gt;
&lt;p&gt;I only tested building &lt;code&gt;lldb-mi&lt;/code&gt; on macOS. Here is how I got it working:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install llvm and cmake via homebrew&lt;/li&gt;
&lt;li&gt;Checkout the lldb-mi repo&lt;/li&gt;
&lt;li&gt;Build the lldb-mi binary&lt;/li&gt;
&lt;li&gt;Link to a location in my PATH&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ brew install cmake llvm
$ git clone https://github.com/lldb-tools/lldb-mi
$ mkdir -p lldb-mi/build
$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; lldb-mi/build
$ cmake ..
$ cmake --build .
$ ln -s &lt;span class=&#34;nv&#34;&gt;$PWD&lt;/span&gt;/src/lldb-mi /usr/local/bin/lldb-mi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In order to have Emacs find that executable you will need to make sure &lt;code&gt;exec-path&lt;/code&gt; is setup correctly at startup. The full dap-mode config looks like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(use-package exec-path-from-shell
  :ensure
  :init (exec-path-from-shell-initialize))

(use-package dap-mode
  :ensure
  :config
  (dap-ui-mode)
  (dap-ui-controls-mode 1)

  (require &#39;dap-lldb)
  (require &#39;dap-gdb-lldb)
  ;; installs .extension/vscode
  (dap-gdb-lldb-setup)
  (dap-register-debug-template
   &amp;quot;Rust::LLDB Run Configuration&amp;quot;
   (list :type &amp;quot;lldb&amp;quot;
         :request &amp;quot;launch&amp;quot;
         :name &amp;quot;LLDB::Run&amp;quot;
	 :gdbpath &amp;quot;rust-lldb&amp;quot;
         :target nil
         :cwd nil)))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;(dap-gdb-lldb-setup)&lt;/code&gt; will install a VS Code extension into &lt;code&gt;user-emacs-dir&lt;/code&gt;/&lt;code&gt;.extension/vscode/webfreak.debug&lt;/code&gt;. One problem I observed was that this installation is not always successful. Should you end up without a &amp;ldquo;&lt;code&gt;webfreak.debug&lt;/code&gt;&amp;rdquo; directory you might need to delete the &lt;code&gt;vscode/&lt;/code&gt; folder and run &lt;code&gt;(dap-gdb-lldb-setup)&lt;/code&gt; again.&lt;/p&gt;
&lt;p&gt;I also needed to run &lt;code&gt;sudo DevToolsSecurity --enable&lt;/code&gt; once to allow the debugger access to processes.&lt;/p&gt;
&lt;p&gt;Additionally I ran into another issue. When starting the debug target I would see:&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;margin-bottom: 2em;&#34;&gt;
    &lt;img controls
        src=&#34;https://robert.kra.hn/posts/rust-emacs-setup/dap-error.png&#34;&gt; 
  &lt;/figure&gt;


&lt;p&gt;Even though &lt;code&gt;lldb-mi&lt;/code&gt; was on my path and I could start it from within Emacs. It turns out that the error does not come from &lt;code&gt;lldb-mi&lt;/code&gt; but from the path to the target you start with. When you start debugging with &lt;code&gt;M-x dap-debug&lt;/code&gt; or via &lt;code&gt;dap-hydra&lt;/code&gt; &lt;code&gt;d d&lt;/code&gt;, after you select &lt;code&gt;Rust::LLDB Run Configuration&lt;/code&gt; make sure that &lt;em&gt;the path to the target executable&lt;/em&gt; you want to debug is not a relative path and does not containt &lt;code&gt;~&lt;/code&gt;. If it&amp;rsquo;s an absolute path it should work.&lt;/p&gt;
&lt;p&gt;Example that would fail with above error (note the unexpanded &lt;code&gt;~/&lt;/code&gt;):&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;margin-bottom: 2em;&#34;&gt;
    &lt;img controls
        src=&#34;https://robert.kra.hn/posts/rust-emacs-setup/dap-fail.png&#34;&gt; 
  &lt;/figure&gt;


&lt;p&gt;I needed to specify the full path &lt;code&gt;/Users/robert/projects/rust/emacs/test-project/target/debug/test-project&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once it is working it should look like that:&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;margin-bottom: 2em;&#34;&gt;
    &lt;video controls
        src=&#34;https://robert.kra.hn/posts/rust-emacs-setup/emacs-debugging-dap.mp4&#34;
        style=&#34;max-height: 620px&#34;&gt; 
  &lt;/figure&gt;


&lt;p&gt;In that example I first activate &lt;code&gt;dab-hydra&lt;/code&gt; with &lt;code&gt;C-c C-c d&lt;/code&gt;. I then select a Rust debug target (that I build using cargo before) with &lt;code&gt;d d&lt;/code&gt;. Before I already set a breakpoint with &lt;code&gt;b p&lt;/code&gt;. I then step through and into the code with &lt;code&gt;n&lt;/code&gt; and &lt;code&gt;i&lt;/code&gt;. Note that you can also use the mouse to set breakpoints and step.&lt;/p&gt;
&lt;p&gt;Setting up debugging is still not as smooth as it could be but once it is running it is a joy!&lt;/p&gt;
&lt;h4 id=&#34;rust-playground&#34;&gt;Rust playground&lt;/h4&gt;
&lt;p&gt;You probably have seen the online Rust playground &lt;a href=&#34;https://play.rust-lang.org/&#34;&gt;https://play.rust-lang.org/&lt;/a&gt; that quickly allows you to run and share snippets of Rust code. A somewhat similar project for Emacs is &lt;a href=&#34;https://github.com/grafov/rust-playground&#34;&gt;grafov/rust-playground&lt;/a&gt; which allows you to quickly create (and remove) Rust scratch projects. By default, the &lt;code&gt;rust-playground&lt;/code&gt; command will create Rust project directories at &lt;code&gt;~/.emacs.d/rust-playground/&lt;/code&gt; and open up &lt;code&gt;main.rs&lt;/code&gt; with keybindings to quickly run the project (&lt;code&gt;C-c C-c&lt;/code&gt;). This is very handy if you want to quicky test a Rust code snippet or tryout a library. All from the comfort of your own editor!&lt;/p&gt;
&lt;h4 id=&#34;additional-packages&#34;&gt;Additional packages&lt;/h4&gt;
&lt;p&gt;I will not cover it here but there are a number of other emacs packages that will improve the Emacs developing experience for Rust and other languages vastly. Just some pointers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/bbatsov/projectile&#34;&gt;projectile&lt;/a&gt;: Adds the notion of projects to emacs and a large number of commands that operate on them. E.g. open shell in project, search code in project etc.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://emacs-helm.github.io/helm/&#34;&gt;helm&lt;/a&gt;, &lt;a href=&#34;https://github.com/raxod502/selectrum&#34;&gt;selectrum&lt;/a&gt; or &lt;a href=&#34;https://github.com/abo-abo/swiper#ivy&#34;&gt;ivy&lt;/a&gt;: We spend a lot of time selecting one or multiple choices from lists. Be it to open files, switch between buffers or run commands (&lt;code&gt;M-x&lt;/code&gt;). All of these packages make it easier to select options via keyboard input in emacs and allow to filter large lists. helm is my personal daily driver but selectrum is a good alternative and more light-weight. It is used in the &lt;code&gt;standalone.el&lt;/code&gt; version of the associated gitub project.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://depp.brause.cc/shackle/&#34;&gt;shackle&lt;/a&gt;: The default emacs window behavior is&amp;hellip; not optimal. Shackle allows to define rules matching buffer names. My default rules are in &lt;a href=&#34;https://gist.github.com/rksm/8c07d9ccc9e15adf752d3dd73dd9a61e&#34;&gt;this gist&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html&#34;&gt;dired&lt;/a&gt; Built-in to Emacs. The last file manager you will need.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;thanks-to-all-the-package-maintainers&#34;&gt;Thanks to all the package maintainers!&lt;/h2&gt;
&lt;p&gt;Last but not least a big Thank You! to all the people developing and maintaining the open source software referenced here. The rust-analyzer project is amazing and has improved the state of Rust Emacs tooling considerably. That of course would not be half as useful without lsp-mode and lsp-ui. rustic simplifies a lot of the otherwise necessary configuration around rust-mode and adds very helpful features. Company and flycheck are my defaults for other language modes anyway. And of course also thanks to all the Emacs maintainers and everyone I forgot who had a hand in all this!&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/racer-rust/emacs-racer&#34;&gt;Racer&lt;/a&gt; used to be the best option for getting IDE features (code navigation etc) into Emacs. It is a non-LSP solution which is still faster than RLS and rust-analyzer. However, the number of features especially around code completion are not up to par with rust-analyzer anymore.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Setting &lt;code&gt;lsp-inlay-hint-enable&lt;/code&gt; globally to &lt;code&gt;t&lt;/code&gt; will also enable inlay hints in other language modes. If you don&amp;rsquo;t want that, insert &lt;code&gt;(setq-local lsp-inlay-hint-enable t)&lt;/code&gt; into &lt;code&gt;rk/rustic-mode-hook&lt;/code&gt; instead.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Emacs has also built-in support for gdb via &lt;a href=&#34;https://www.gnu.org/software/emacs/manual/html_node/emacs/GDB-Graphical-Interface.html&#34;&gt;GUD&lt;/a&gt; but needs to control the gdb process directly. &lt;a href=&#34;https://microsoft.github.io/debug-adapter-protocol/&#34;&gt;DAP&lt;/a&gt; is more similar to LSP in that it is used to control a debugging process remotely and makes it easier for editors to integrate with.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Is Rust a Functional Programming Language?</title>
      <link>https://robert.kra.hn/posts/2021-02-03_is-rust-fp/</link>
      <pubDate>Wed, 03 Feb 2021 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/2021-02-03_is-rust-fp/</guid>
      <description>&lt;hr&gt;
&lt;p&gt;Update: There was a delightful discussion about functional programming and the nature of Rust at &lt;a href=&#34;https://lobste.rs/s/434bly/is_rust_functional_programming_language&#34;&gt;lobste.rs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some quotes...&lt;/p&gt;
&lt;div class=&#34;collapsible-wrapper&#34;&gt;
  &lt;div class=&#34;collapsible-content&#34;&gt;
    &lt;blockquote&gt;
&lt;p&gt;Functional languages take away mutability from the “mutability + aliasing = bugs” equation; Rust takes away the aliasing — or at least, the uncontrolled aliasing. To me, it then makes sense to feel comfortable using mutability (and the advantages it offers), safe in the knowledge that the compiler is helping you avoid bugs. [&lt;a href=&#34;https://lobste.rs/s/434bly/is_rust_functional_programming_language#c_slxmwj&#34;&gt;vfoley&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I guess I don’t really agree with all of this. I agree that Rust gets the nice properties of functional languages at least when it comes to mutation, but if someone read the body of Rust code I have written and came back and said, “it really resembles the code I typically write on Lisp/ML/Haskell,” then I would be really surprised. I rarely write higher order functions. I rarely write recursive functions or folds. I rarely use persistent data structures and instead use mutation without reservation. [&lt;a href=&#34;https://lobste.rs/s/434bly/is_rust_functional_programming_language#c_aucsix&#34;&gt;burntsushi&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://lobste.rs/s/434bly/is_rust_functional_programming_language#c_zbcp7s&#34;&gt;andyc&lt;/a&gt; pointed to &lt;a href=&#34;https://boats.gitlab.io/blog/post/notes-on-a-smaller-rust/&#34;&gt;Notes on a smaller Rust
&lt;/a&gt; and quoted:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As I said once, pure functional programming is an ingenious trick to show you can code without mutation, but Rust is an even cleverer trick to show you can just have mutation.&lt;/p&gt;
&lt;/blockquote&gt;

  &lt;/div&gt;
  &lt;a class=&#34;collapsible-link collapsed&#34; href=&#34;&#34;&gt;expand&amp;nbsp;&lt;/a&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;The book &lt;a href=&#34;https://www.oreilly.com/library/view/programming-rust/9781491927274/&#34;&gt;Programming Rust&lt;/a&gt; introduces Rust as...&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;not really an object-oriented language, although it has some object-oriented characteristics. Rust is not a functional language [&amp;hellip;] It’s probably best to reserve judgement about what sort of language Rust is, and see what you think once you’ve become comfortable with the language.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Time for judgement has come! In the following I will lay out my view on how Rust&amp;rsquo;s language features influence programming style. I do agree with the aforementioned quote that Rust is not a single-paradigm language. Yet, the code written in idiomatic and safe Rust shares quite some similarities with code of functional programming languages.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Functional programming language&amp;rdquo; is not a clearly defined term. From the various properties that are typically associated with functional programming I only want to focus on one: &amp;ldquo;Immutability&amp;rdquo; and referential transparency. Immutability means that data structures can be treated as values - once you have them, they will not change underneath you. If you want to express modification, you can construct a new data structure, maybe reusing (unchanged) parts of existing data. This enables referential transparency: If a function (or method) cannot change anything internally, its output only depends on its input. Given some input the function evaluation and the result it returns can be treated as the same. The function is said to be pure.&lt;/p&gt;
&lt;p&gt;Immutability is often regarded as a very positive property:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pure code is deterministic and considered to be easier to reason about as the number of possible state combinations is limited.&lt;/li&gt;
&lt;li&gt;If a function only depends on explicitly defined parameters, testing it is often easier.&lt;/li&gt;
&lt;li&gt;Immutable data can be passed to concurrent code without worrying about synchron^izing access.&lt;/li&gt;
&lt;li&gt;And it is free of cycles (unless you allow &lt;a href=&#34;https://wiki.haskell.org/Tying_the_Knot&#34;&gt;lazily evaluation&lt;/a&gt;), making it easier to serialize and deserialize.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now Rust clearly allows for data to be mutable. Rust also does not provide &lt;a href=&#34;https://en.wikipedia.org/wiki/Persistent_data_structure&#34;&gt;persistent data structures&lt;/a&gt; in its standard library (although there are &lt;a href=&#34;https://crates.io/crates/im&#34;&gt;third-party&lt;/a&gt; &lt;a href=&#34;https://crates.io/crates/rpds&#34;&gt;options&lt;/a&gt;) which are typically used to model immutable data efficiently. Yet, Rust&amp;rsquo;s rules around ownership require full control over what can be changed and when. To the extent that I have been working with Rust, a lot of it feels quite similar to programming Clojure from the point of view of designing programs.&lt;/p&gt;
&lt;h2 id=&#34;ownership-sharing-exclusivity&#34;&gt;Ownership, sharing, exclusivity&lt;/h2&gt;
&lt;p&gt;Each piece of data in (safe) Rust has exactly one owner. In the following example the variable &lt;code&gt;val&lt;/code&gt; owns the String:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hello World&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using &lt;code&gt;val&lt;/code&gt; we can create references to the string:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val_ref&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// both val and val_ref can be used to read the string value:
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val_ref&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However we cannot modify either &lt;code&gt;val&lt;/code&gt; or &lt;code&gt;val_ref&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// cannot borrow `val` as mutable, as it is not declared as mutable
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;push_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34; World&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// error: &amp;#34;cannot borrow `*val_ref` as mutable, as it is behind a `&amp;amp;` reference&amp;#34;
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val_ref&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;push_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34; World&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So in order to change &lt;code&gt;val&lt;/code&gt; we need to declare it &lt;code&gt;mut&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;push_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34; World&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// OK
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But now we cannot take a reference at the same time anymore:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// error: cannot borrow `val` as mutable because it is also borrowed as immutable
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val_ref&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;push_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34; World&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And similarly we can write to the reference if we declare it &lt;code&gt;mut&lt;/code&gt; but then we cannot get another reference at the same time:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val_ref&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// error: cannot borrow `val` as mutable because it is also borrowed as immutable
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val_ref2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This example demonstrates Rust&amp;rsquo;s ownership rules: We can get multiple shared (read-only) references to one piece of data but as soon as we indicate to modify the data by declaring either the owning variable or a reference as &lt;code&gt;mut&lt;/code&gt; we cannot hold shared references at the same time. &lt;code&gt;mut&lt;/code&gt; means first and foremost &lt;em&gt;exclusive&lt;/em&gt; access to the underlying data (and only secondarily &lt;em&gt;mutable&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Similarly, functions that want to modify parameters (or &lt;em&gt;self&lt;/em&gt; in case of methods) need to indicate that they need exclusive access. This means that the caller can only use this function it has exclusive access to the parameters to be passed as &lt;code&gt;mut&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;add_world&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val_ref&lt;/span&gt;: &lt;span class=&#34;kp&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val_ref&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;push_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34; World&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// ...
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_world&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All this is to say: Mutability in Rust needs to be explicitly declared and the rules around exclusive access are statically enforced. A thing can only change if no one is looking — reducing the number of accidental state combinations and highlighting the parts of the code base that can introduce change clearly. A Rust function that only accepts shared references and owned values (that do not provide interior mutability) and that does not use unsafe code&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, is referentially transparent.&lt;/p&gt;
&lt;h2 id=&#34;interior-mutability&#34;&gt;Interior mutability&lt;/h2&gt;
&lt;p&gt;There are a number of use cases where not being able to modify shared references can become very limiting. For example consider this &lt;a href=&#34;https://gtk-rs.org/&#34;&gt;GTK+3&lt;/a&gt; app:&lt;/p&gt;


  &lt;figure class=&#34;center-figure&#34; style=&#34;margin-bottom: 1em;&#34;&gt;
    &lt;img src=&#34;https://robert.kra.hn/posts/2021-02-03_is-rust-fp/interior_mutability.gif&#34;
         style=&#34;object-fit: cover; object-position: -1px -1px;&#34;&gt; 
  &lt;/figure&gt;


&lt;p&gt;The implementation for this looks something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;container&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gtk&lt;/span&gt;::&lt;span class=&#34;nb&#34;&gt;Box&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gtk&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Orientation&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Vertical&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// A label that will be modified
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;label&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gtk&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Label&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Button not yet clicked&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gtk&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Button&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;with_label&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Click me&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// We clone label so we can send it into the closure.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;label_clone&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;label&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connect_clicked&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;move&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;label_clone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set_label&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Button has been clicked!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;container&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;container&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;label&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see the &lt;code&gt;label&lt;/code&gt; is added to the container so that it gets displayed &lt;em&gt;and&lt;/em&gt; is bound inside the closure where it gets modified.&lt;/p&gt;
&lt;p&gt;Rust uses two mechanisms in combination for that to work: The &lt;a href=&#34;https://doc.rust-lang.org/book/ch15-05-interior-mutability.html#having-multiple-owners-of-mutable-data-by-combining-rct-and-refcellt&#34;&gt;&lt;code&gt;Rc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; pattern&lt;/a&gt;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. First, a reference counted pointer &lt;code&gt;std::rc::Rc&lt;/code&gt; that is quite similar to C++&amp;rsquo;s &lt;code&gt;shared_ptr&lt;/code&gt;. &lt;code&gt;Rc&lt;/code&gt; takes ownership of another object. &lt;code&gt;Rc&lt;/code&gt; implements &lt;code&gt;Clone&lt;/code&gt; that will increase the ref count and hand out a new pointer. Those can be passed freely around. Inside of the ref-counted pointer a &lt;a href=&#34;https://doc.rust-lang.org/std/cell/struct.RefCell.html&#34;&gt;RefCell&lt;/a&gt; can be placed. It will allow to request exclusive access to the data owned. I.e. it will — at runtime! — produce a &lt;code&gt;mut&lt;/code&gt; reference to the object wrapped and check that it is indeed not borrowed somewhere else. Should this not be the case, the borrow will fail (and possibly panic if &lt;code&gt;borrow_mut()&lt;/code&gt; was used).&lt;/p&gt;
&lt;p&gt;For more details about the internals of smart pointers and interior mutability I can highly highly recommend &lt;a href=&#34;https://www.youtube.com/watch?v=8O0Nt9qY_vo&#34;&gt;this screen cast by Jon Gjengset&lt;/a&gt; that walks you through possible implementations of (among others) &lt;code&gt;Rc&lt;/code&gt; and &lt;code&gt;RefCell&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So Rust provides ways&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; around the statically enforced access rules that normally restrict modification of data. This provides enough abstractions to even implement an interface to an object-oriented system such as Glib / GTK+. Following that, you might argue that Rust is supporting multiple paradigms, and I will agree. Yet, similar to Clojure that provides &amp;ldquo;interior mutability&amp;rdquo;-equivalents like &lt;a href=&#34;https://clojure.org/reference/atoms&#34;&gt;atoms&lt;/a&gt; I will point out that overly relying on those features is not considered idiomatic. In Clojure the best practice is to use atoms sparingly. Mostly at the outside of the app, extracting state that is passed into the inner layers of the app that will then transform the state immutably into a new derived version. Atoms then clearly highlight where state changes can be expected. In practice, this then provides a good compromise. In case of stateful bugs, you only have to have a limited amount of possible sources to check and possible combinations of state transitions are still limited to simplify reasoning.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Rc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; pattern is also not all that ergonomic. Yes, you can define type aliases like Glib does, Rust still makes it easier to not have nested, cyclic relationships between objects. To say it with book Programming Rust again (from the section &amp;ldquo;Taking Arms Against a Sea of Objects&amp;rdquo;):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When everything depends on everything else like this, it&amp;rsquo;s hard to test, evolve, or even think about any component in isolation.
One fascinating thing about Rust is that the ownership model puts a speed bump on the highway to hell. [&amp;hellip;] It works unreasonably well: not only can Rust force you to understand why your program is thread-safe, it can even require some amount of high-level architectural design.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And this is exactly the point I would like to convey with this article and the reason why I&amp;rsquo;m personally so fascinated with Rust: The set of features it does (not) provide are forcefully guiding the design of systems you build. This is quite contrary to how a lot of programming languages that attempt to provide a high degree of flexibility work (looking at you, Scala).&lt;/p&gt;
&lt;p&gt;And then this is my claim: The ownership model, standard library, emphasize on iterators, and numerous other things do lead to code that is usually most idiomatic when written in a functional style. It will unlikely be completely equivalent to a solution written in Haskell or Clojure. Of course it also depends on the programmer, the problem domain, libraries, and frameworks. But applying best practices and designs from the functional realm are effective in Rust and the positive properties listed above can be built into Rust programs, and, to a degree, are even statically enforced by the compiler. For me, that is a joy!&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Unsafe code is marked very visibly by unsafe blocks or function signatures and best practice around it is to require a thorough explanation as to why this code is safe and what the contract around it is. Unsafe code can cast &lt;code&gt;*const&lt;/code&gt; into &lt;code&gt;*mut&lt;/code&gt; pointers and can thus potentially modify shared references.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;For the GTK+ example this is only partially true. GTK uses GLib bindings, a wrapper around the C library. GLib implements its own object-oriented abstractions via &lt;a href=&#34;https://developer.gnome.org/gobject/stable/chapter-gobject.html&#34;&gt;GObject&lt;/a&gt;. The label and other objects from the example are instances of the &lt;a href=&#34;https://docs.rs/glib/0.10.3/glib/index.html#objects&#34;&gt;GObject&lt;/a&gt; representation that the glib Rust wrapper provides. It implements the functionality of &lt;code&gt;Rc&lt;/code&gt; / &lt;code&gt;RefCell&lt;/code&gt; internally but does not use Rust&amp;rsquo;s stdlib implementation for that.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;code&gt;Rc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; is only for single threaded, Rust statically enforces that you cannot pass it across thread boundaries. &lt;a href=&#34;https://doc.rust-lang.org/book/ch16-03-shared-state.html&#34;&gt;Arc&amp;lt;Mutex&lt;!-- raw HTML omitted --&gt;&amp;gt;&lt;/a&gt; is the thread-safe equivalent.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Building and deploying Rust utilities</title>
      <link>https://robert.kra.hn/posts/2021-02-01_cross-compile-rust/</link>
      <pubDate>Mon, 01 Feb 2021 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/2021-02-01_cross-compile-rust/</guid>
      <description>&lt;p&gt;Over the past year I build a number of tools and utilities in Rust. Previously, I would mostly do this in node.js or shell scripts but Rust has some advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More reliable for long running and mostly unobserved applications (&amp;ldquo;once it runs is runs&amp;rdquo;), in particular no memory (leak) issues&lt;/li&gt;
&lt;li&gt;Needs less resources, upping the utility value of my various Raspberry Pis&lt;/li&gt;
&lt;li&gt;Setup and deployment are simple mostly due to the cargo package management and build tool&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last point I&amp;rsquo;ll describe in more detail. In particular, the project setup around file / directory organization, package tooling and cross-compilation. Rust has comparatively strict (but in my opinion well designed) best practices and &amp;ldquo;opinionated&amp;rdquo; defaults. Most of them come simply with the tools you use: &lt;code&gt;cargo run&lt;/code&gt; expects binaries to be defined in certain ways for example.&lt;/p&gt;
&lt;p&gt;To make this a little more concrete I will use my last holiday project as an example. &lt;code&gt;fritzctrl&lt;/code&gt; wraps the API of &lt;a href=&#34;https://en.avm.de/products/fritzdect/&#34;&gt;AVM Fritz devices&lt;/a&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; into a command line utility that allows to schedule turning on and off outlets and controlling thermostats. The code is open source and can be found in a &lt;a href=&#34;https://github.com/rksm/fritz-homeautomation-rs&#34;&gt;github repository&lt;/a&gt;. This project is still quite small (~1000 loc), yet I took care to follow common guidelines when organizing the code base to allow the project to be easily maintained and grown in the future.&lt;/p&gt;
&lt;h2 id=&#34;project-organization&#34;&gt;Project organization&lt;/h2&gt;
&lt;p&gt;Apart from github, the fritzctrl command line utility was also &lt;a href=&#34;https://crates.io/crates/fritzctrl&#34;&gt;added to crates.io&lt;/a&gt; which allows installing it by running &lt;code&gt;cargo install fritzctrl&lt;/code&gt; (this requires a local rust installation via rustup). This is all that is needed to get the utility installed - cargo will put it into it&amp;rsquo;s binary location (&lt;code&gt;~/.cargo/bin/&lt;/code&gt;) that one can add to &lt;code&gt;PATH&lt;/code&gt;. From that point on the utility is ready to use.&lt;/p&gt;
&lt;p&gt;While building the tool I started to split up the user interface related code and the code that provides an interface (to the &lt;a href=&#34;https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AHA-HTTP-Interface.pdf&#34;&gt;slightly obscure&lt;/a&gt;) Fritz API. The latter was published in a &lt;a href=&#34;https://crates.io/crates/fritzapi&#34;&gt;separate crate&lt;/a&gt; which allows other projects to directly interface with that. The recommended way of organizing a project into multiple crates and libraries / binaries is a &lt;a href=&#34;https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html&#34;&gt;cargo feature called workspaces&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note that organizing a project into a workspace is not absolutely necessary to separate the code. You can easily define one or many &lt;a href=&#34;https://doc.rust-lang.org/cargo/reference/cargo-targets.html#binaries&#34;&gt;binaries&lt;/a&gt; simply by putting &lt;code&gt;.rs&lt;/code&gt; files into &lt;code&gt;src/bin/&lt;/code&gt;. You can even use sub-directories if you want a binary to have sub-modules. But if your binary starts to have extra dependencies that are not required for the library, things get a bit more complicated. See &lt;a href=&#34;https://stackoverflow.com/questions/35711044/how-can-i-specify-binary-only-dependencies&#34;&gt;this stackoverflow answer&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;Since workspaces are very well supported by cargo and related tooling, it&amp;rsquo;s advisable to go down that route if in doubt.&lt;/p&gt;
&lt;p&gt;In case of my project the structure looks like this: The top-level &lt;code&gt;Cargo.toml&lt;/code&gt; just points to the &lt;code&gt;fritzapi&lt;/code&gt; and &lt;code&gt;fritzctrl&lt;/code&gt; directories. &lt;code&gt;fritzctrl/Cargo.toml&lt;/code&gt; references the lib via &lt;code&gt;fritzapi = { path = &amp;quot;../fritzapi&amp;quot;, version = &amp;quot;0.3&amp;quot; }&lt;/code&gt;. Note that there is also a version number, this will be used when the crate gets published and installed by other users via cargo. The path dependency is what gets when installing the crate locally.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;├── Cargo.toml
├── Cargo.lock
├── fritzapi
│   ├── Cargo.toml
│   ├── README.md  &amp;lt;== generated using cargo readme
│   └── src
│       └── ...
└── fritzctrl
    ├── Cargo.toml
    ├── README.md  &amp;lt;== generated using cargo readme
    └── src
        └── ...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The project can be easily build an run from the workspace root directory. &lt;code&gt;cargo run&lt;/code&gt;, &lt;code&gt;cargo test&lt;/code&gt;, &lt;code&gt;cargo doc&lt;/code&gt; etc. all work as expected.&lt;/p&gt;
&lt;h2 id=&#34;publishing-to-cratesio&#34;&gt;Publishing to crates.io&lt;/h2&gt;
&lt;p&gt;If you have used a package management system like npm, crates.io will be quite familiar. You&amp;rsquo;ll first need to login to the &lt;a href=&#34;https://crates.io&#34;&gt;crates.io website&lt;/a&gt;, which requires a github account. You then need to confirm your email address. Afterwards you can generate a token that when used on the command line with &lt;code&gt;cargo login&lt;/code&gt;, allows you to publish and update crates. The &lt;code&gt;cargo publish&lt;/code&gt; command can be run inside a project directory and will check and upload your project. However, I would recommend the &lt;a href=&#34;https://github.com/sunng87/cargo-release&#34;&gt;cargo release plugin&lt;/a&gt; which automates some housekeeping tasks around publishing. It&amp;rsquo;ll bump versions (across all packages when run from a workspace root!), git tag and upload. It&amp;rsquo;s very handy, I like it a lot.&lt;/p&gt;
&lt;p&gt;While we&amp;rsquo;re talking about cargo plugins: I can also recommend &lt;a href=&#34;https://github.com/livioribeiro/cargo-readme&#34;&gt;cargo readme&lt;/a&gt; which extracts rustdoc comments into markdown format that can be put directly into a &lt;code&gt;README.md&lt;/code&gt; file. This will be automatically picked up by crates.io and will be what is visible on the project page such as &lt;a href=&#34;https://crates.io/crates/fritzctrl&#34;&gt;crates.io/crates/fritzctrl&lt;/a&gt;. All of the content there was extracted from &lt;a href=&#34;https://github.com/rksm/fritz-homeautomation-rs/blob/master/fritzctrl/src/main.rs&#34;&gt;&lt;code&gt;fritzctrl/src/main.rs&lt;/code&gt;&lt;/a&gt; with &lt;code&gt;cd path/to/fritzctrl; cargo readme &amp;gt; README.md&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In order to publish a new version of both fritzctrl and fritzapi I would then commit all changes and switch to the workspace root directory of the project. There I&amp;rsquo;ll run &lt;code&gt;cargo release --dry-run -vv --no-dev-version patch&lt;/code&gt; which provides a preview of the release commands that would be run.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://robert.kra.hn/posts/2021-02-01_cross-compile-rust/cargo-release.png&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;If all looks good just run without the dry-run option and you should be done!&lt;/p&gt;
&lt;h2 id=&#34;cross-compiling&#34;&gt;Cross-compiling&lt;/h2&gt;
&lt;p&gt;A big reason for me to choose rust is the ability to create stand-alone binaries that can simply be copied onto a server, into a docker container or onto a Raspberry Pi without much installation overhead in the deploy environment. Often, compiling on the target device itself is not desirable or possible. Raspberry Pi&amp;rsquo;s are very capable devices but compiling a lot of code will take ages.&lt;/p&gt;
&lt;p&gt;The first step is to figure out what processor and instruction set you need to target. In the following I describe how to cross-compile for Raspberry Pi devices which use ARM processors with AVMv6 (Pi Zero, Pi 1) and ARVv7 (Pi 2 and later) instructions sets. To figure out the CPU / instruction set for linux devices, running &lt;code&gt;cat /proc/cpuinfo&lt;/code&gt; or &lt;code&gt;uname -a&lt;/code&gt; should give the necessary information. Running the latter on a Raspberry Pi 2 outputs:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Linux rpi-home 5.4.79-v7+ #1373 SMP Mon Nov 23 13:22:33 GMT 2020 armv7l GNU/Linux
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In particular, for my project I want to deploy the fritzctl binary in order to run a &lt;code&gt;fritzctrl schedule&lt;/code&gt; command to turn my outside lighting on and off at sunrise and sunset.&lt;/p&gt;
&lt;h3 id=&#34;raspberry-pi-2-and-later&#34;&gt;Raspberry Pi 2 and later&lt;/h3&gt;
&lt;p&gt;The first thing you need to do is to make sure the stdlib for the target architecture is installed. For the purpose of targeting a Raspberry Pi 2, the ARMv7 target will do as determined above. You can either use the gnu or musl variant, I used&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;rustup target add armv7-unknown-linux-musleabihf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note the &amp;ldquo;hf&amp;rdquo; here which is normally what you want. It means that floating point operations will use the hardware support provided by the chip as noted in the &lt;a href=&#34;https://wiki.musl-libc.org/getting-started.html#Notes_on_ARM_Float_Mode&#34;&gt;musl-libc wiki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This alone didn&amp;rsquo;t do as dependencies also required to be compiled native using gcc. The gcc of your host system (MacOS in my case) will not be able to output the right format and might even have an incompatible compiler / linker interface. So you&amp;rsquo;ll likely need to install a gcc toolchain as well. Over at &lt;a href=&#34;https://lisa.musl.cc/9.3.0/&#34;&gt;lisa.musl.cc&lt;/a&gt; you can download &lt;code&gt;armv7l-linux-musleabihf-cross.tgz&lt;/code&gt; which will contain gcc and linker binaries (the binaries from &lt;a href=&#34;https://mac.musl.cc&#34;&gt;mac.musl.cc&lt;/a&gt; did not work for me for some reason). &lt;a href=&#34;https://lisa.musl.cc/9.3.0/armv7l-linux-musleabihf-cross.tgz&#34;&gt;Direct link to the .tgz file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then, we&amp;rsquo;ll need to inform cargo to use a different linker. Create a file &lt;code&gt;.cargo/config.toml&lt;/code&gt; and specify the linker, in my case the file looks like&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[target.armv7-unknown-linux-musleabihf]
linker = &amp;quot;armv7l-linux-musleabihf-gcc&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now the last step is to run &lt;code&gt;cargo build&lt;/code&gt; using the ARM target &lt;em&gt;and&lt;/em&gt; making sure that the different linker can be found:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/path/to/armv7l-linux-musleabihf-cross/bin:&lt;span class=&#34;nv&#34;&gt;$PATH&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    cargo build --release --target&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;armv7-unknown-linux-musleabihf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When you run that on MacOS you&amp;rsquo;ll probably see a MacOS warning like:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://robert.kra.hn/posts/2021-02-01_cross-compile-rust/toolchain-warning.png&#34; width=&#34;280&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;You&amp;rsquo;ll need to open the MacOS Preferences &amp;gt; Security &amp;amp; Privacy and allow the binary to run.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://robert.kra.hn/posts/2021-02-01_cross-compile-rust/toolchain-warning-2.png&#34; width=&#34;520&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;If everything works you should end up with a binary in &lt;code&gt;target/armv7-unknown-linux-musleabihf/release/&lt;/code&gt;. You should then be able to copy that binary directly onto the target machine and run it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ scp target/armv7-unknown-linux-musleabihf/release/fritzctl rpi:bin/fritzctl
$ ssh rpi
pi@rpi-home:~ $ ./bin/fritzctl
&lt;span class=&#34;c1&#34;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For other architectures you&amp;rsquo;ll need to install the appropriate targets such as &lt;code&gt;x86_64-unknown-linux-musl&lt;/code&gt; for example. &lt;code&gt;rustup&lt;/code&gt; makes this very straightforward. I have some build issues from time to time with crates that have native dependencies. However, more and more crates now run purely on Rust or provide features to use pure rust dependencies.&lt;/p&gt;
&lt;p&gt;If you need an http client for example, the &lt;a href=&#34;https://crates.io/crates/reqwest&#34;&gt;reqwest crate&lt;/a&gt; will allow to be build using &lt;code&gt;rustls-tls&lt;/code&gt; instead of &lt;code&gt;rust-native-tls&lt;/code&gt; which might make it easier to compile.&lt;/p&gt;
&lt;h3 id=&#34;raspberry-pi-zero-w&#34;&gt;Raspberry Pi Zero W&lt;/h3&gt;
&lt;p&gt;The rpi0 (similar to the original Raspbarry Pi version 1) uses the ARMv6 instruction set. Running &lt;code&gt;uname -a&lt;/code&gt; gives&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Linux rpi0 4.19.66+ #1253 Thu Aug 15 11:37:30 BST 2019 armv6l GNU/Linux
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This means the above instructions (for ARMv7) will not produce runnable binaries for it. To compile a compatible binary install the &lt;code&gt;arm-unknown-linux-musleabihf&lt;/code&gt; rust target:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;rustup target add arm-unknown-linux-musleabihf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next you will need the right toolchain: &lt;a href=&#34;https://lisa.musl.cc/9.3.0/arm-linux-musleabihf-cross.tgz&#34;&gt;arm-linux-musleabihf-cross&lt;/a&gt; worked for me. Unpack it and modify your projects &lt;code&gt;.cargo/config.toml&lt;/code&gt; to read&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[target.arm-unknown-linux-musleabihf]
linker = &amp;quot;arm-linux-musleabihf-gcc&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should now be able to build a &amp;ldquo;hello-world&amp;rdquo; program (e.g. created with &lt;code&gt;cargo new&lt;/code&gt;) using&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/path/to/arm-linux-musleabihf-cross/bin:&lt;span class=&#34;nv&#34;&gt;$PATH&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    cargo build --release --target&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;arm-unknown-linux-musleabihf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Try copying it to your Raspberry Pi 0 and run it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;scp ./target/arm-unknown-linux-musleabihf/release/hello-world pi@rpi0:
ssh rpi0 &lt;span class=&#34;s1&#34;&gt;&amp;#39;./hello-world&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(replace &lt;code&gt;rpi0&lt;/code&gt; with whatever hostname or ip address your rpi0 is reachable at)&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Rust is fun to work with not just because the language is well designed but also the accompanying tooling is well thought out. Rust and in particular cargo come with a number of &amp;ldquo;opinionated&amp;rdquo; defaults such as how projects are organized that (at least if you agree with and follow them) make it quite straightforward to setup and deploy projects. I&amp;rsquo;ve never been a fan of strict rules around build systems, in the case of Rust I do, however. This might be because those guidelines come in a large part from the learnings of other such systems like node.js / npm and try to enshrine the best practices used there. Additionally, cargo and rustup are excellent and well documented tools (&lt;a href=&#34;https://doc.rust-lang.org/cargo/&#34;&gt;the cargo book&lt;/a&gt; is quite helpful). I look forward to build many more systems in the Rust ecosystem.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;AVM is a Berlin-based company and mostly known for their routers. In my opinion they make excellent products (I&amp;rsquo;ve owned several routers and DECT devices so far) that are also fairly hackable. Recommended.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Clojure Conj 2019</title>
      <link>https://robert.kra.hn/posts/2019-11-29_clojure-conj/</link>
      <pubDate>Fri, 29 Nov 2019 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/2019-11-29_clojure-conj/</guid>
      <description>&lt;figure class=&#34;right-figure&#34;&gt;&lt;img src=&#34;https://robert.kra.hn/img/2019-11-29_clojure-conj/clojure_conj_tshirt.jpeg&#34; width=&#34;300px&#34;/&gt;
&lt;/figure&gt;

&lt;p&gt;I just returned from last weeks &lt;a href=&#34;http://2019.clojure-conj.org/&#34;&gt;Clojure/conj&lt;/a&gt; in Durham, NC. All the talks &lt;a href=&#34;https://www.youtube.com/watch?v=MnvtPzEH-d8&amp;amp;list=PLZdCLR02grLqSy15ALLAZDU6LGpAJDrAQ&#34;&gt;seem
to be online now&lt;/a&gt;. Talks I really liked included &lt;a href=&#34;https://www.youtube.com/watch?v=MnvtPzEH-d8&amp;amp;list=PLZdCLR02grLqSy15ALLAZDU6LGpAJDrAQ&amp;amp;index=1&#34;&gt;Follow the Data&lt;/a&gt;, &lt;a href=&#34;https://www.youtube.com/watch?v=OUZZKtypink&amp;amp;list=PLZdCLR02grLqSy15ALLAZDU6LGpAJDrAQ&amp;amp;index=11&#34;&gt;Sherlock
Holmes&lt;/a&gt;, and &lt;a href=&#34;https://www.youtube.com/watch?v=5mbp3SEha38&amp;amp;list=PLZdCLR02grLqSy15ALLAZDU6LGpAJDrAQ&amp;amp;index=12&#34;&gt;Love Letter To Clojure&lt;/a&gt;. No big surprises or releases there but what
was an overarching impression is that Clojure now really has become a very
stable language and ecosystem. Not huge by any means but &lt;a href=&#34;http://2019.clojure-conj.org/sponsors/&#34;&gt;a fair amount of
companies&lt;/a&gt; participated and among the conference attendees many more worked
professionally with Clojure (and that does not even count in Clojure&amp;rsquo;s presence
in Europe where it seems to find increasing adoption, e.g. at companies like
&lt;a href=&#34;https://pitch.com&#34;&gt;Pitch&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;From the companies present at the conj, most notable is properly &lt;a href=&#34;https://en.wikipedia.org/wiki/Nubank&#34;&gt;Nubank&lt;/a&gt; which
had a number of developers and multiple talks there. They are in the process of
&lt;a href=&#34;https://www.youtube.com/watch?v=ct5aWqhHARs&amp;amp;list=PLZdCLR02grLqSy15ALLAZDU6LGpAJDrAQ&amp;amp;index=3&#34;&gt;really scaling up their business&lt;/a&gt; with hundreds of developers in multiple
locations, including Berlin.&lt;/p&gt;
&lt;p&gt;Clojure&amp;rsquo;s continued relevance doesn&amp;rsquo;t seem to simply derive from a single
&amp;ldquo;killer feature&amp;rdquo;, it&amp;rsquo;s a mix of properties that make the language useful in
todays world. On the one hand it&amp;rsquo;s Clojure&amp;rsquo;s approach of being hosted on the JVM
and web browsers that enable adoption fairly easily, allow it to run almost
anywhere and that &lt;a href=&#34;http://www.modulecounts.com/&#34;&gt;opens up a large number of available libraries&lt;/a&gt;. Then there are
features that are not completely unique to Clojure but can&amp;rsquo;t really be found in
other mainstream languages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s dynamic workflow and the &amp;ldquo;repl-driven&amp;rdquo; development style that pretty much
every Clojure development tool supports (and which is my personal favorite),&lt;/li&gt;
&lt;li&gt;a small language core library that makes working with and transforming data
easy by providing a sensible set of core data structure and operations and
that focuses on state management and immutability,&lt;/li&gt;
&lt;li&gt;various useful additions such as clojure.spec that address real world concerns&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So all in all Clojure seems to be pretty healthy and I continue to enjoy working
with it!&lt;/p&gt;
</description>
    </item>
    
    
    
    
    
    <item>
      <title>Org Analyzer</title>
      <link>https://robert.kra.hn/posts/2019-08-13_org_analyzer/</link>
      <pubDate>Tue, 13 Aug 2019 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/2019-08-13_org_analyzer/</guid>
      <description>&lt;p&gt;Here is the project link: &lt;a href=&#34;https://github.com/rksm/clj-org-analyzer&#34;&gt;github.com/rksm/clj-org-analyzer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I started using Emacs org mode &amp;ldquo;for real&amp;rdquo; a little less than two years ago and
have been tracking my work related activities ever since using &lt;code&gt;org-clock-in&lt;/code&gt;.
Since the end of 2017 this has generated quite a bit of data but I have found
that actually digging into that is rather hard due to the limited reporting
functionality in Emacs.&lt;/p&gt;
&lt;p&gt;I do have a few concrete use cases in mind. For example, one of my biggest
weaknesses is to reliably estimate the effort for software projects. To get at
least a little better at this I want to try learning from the past. To make it
easier to get an overview and &amp;ldquo;slice and dice&amp;rdquo; my time tracked activities I
created org analyzer:&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/qBgvGDOxmUw&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;It turns out it is actually pretty fun to explore question such as &amp;ldquo;what was the
biggest project last year&amp;rdquo;, &amp;ldquo;what are my core work hours&amp;rdquo;, &amp;ldquo;what thing that I
thought took a long time was rather quickly done&amp;rdquo;, etc.&lt;/p&gt;
&lt;p&gt;So, yeah, a fun little project that actually took way longer than I thought ;)&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>Developer Efficiency</title>
      <link>https://robert.kra.hn/posts/2019-06-20_developer_efficiency/</link>
      <pubDate>Thu, 20 Jun 2019 00:00:00 +0000</pubDate>
      <author>robert@kra.hn (Robert Krahn)</author>
      <guid>https://robert.kra.hn/posts/2019-06-20_developer_efficiency/</guid>
      <description>&lt;p&gt;Much has been written about the productivity of software developers. The term
&amp;ldquo;10x programmer&amp;rdquo; has been used and abused. It can be traced back to the &lt;a href=&#34;%5Bhttps://apps.dtic.mil/docs/citations/AD0645438%5D&#34;&gt;paper by Sackman et al.&lt;/a&gt; that first described the variations in ability of individuals
to program and debug. Even though I&amp;rsquo;m not writing about individual differences
here I&amp;rsquo;m mentioning this publication for another reason: It set out to compare
how well people do when they should debug a problem and have or have not access
to a computer: &lt;em&gt;Online&lt;/em&gt; and &lt;em&gt;offline&lt;/em&gt; debugging&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Now using pen and paper every once in a while can be really helpful to
facilitate thinking (or to whiteboard with a colleague) but in general the
computer itself can guide and support a human programmer in programming and
debugging tasks very well. This functionality was either very new (and available
to only few programmers) or non-existing in 1968 when the paper above was
written. But a lot changed in the decade or so thereafter. Smalltalk and Lisp
developers know all about that. And yet, it sometimes seems to me that the rest
of the world hasn&amp;rsquo;t really caught on yet.&lt;/p&gt;
&lt;p&gt;Fundamentally computer programs are extremely dynamic processes. Understanding
them requires not only to know about the abstractions and their static structure
and interdependencies but also how they work together, how control flows, what
data and objects are used. Programming then means to nudge both the abstractions
as well as their dynamic relationships towards achieving a particular goal, step
by step.&lt;/p&gt;
&lt;p&gt;Imagine building a web shop and adding the &amp;ldquo;add item to shopping cart&amp;rdquo; feature:
There is some UI in which items to buy are listed. Clicking on one should modify
the state of a users cart and be reflected in the UI as well. Even in this
overly simplistic and contrived example we have a couple of static objects and
dynamic interactions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Items to buy&lt;/li&gt;
&lt;li&gt;A user&lt;/li&gt;
&lt;li&gt;A user&amp;rsquo;s cart&lt;/li&gt;
&lt;li&gt;A user interface rendering all of the above&lt;/li&gt;
&lt;li&gt;A user&amp;rsquo;s interactions (clicks) modifying some or all of the above&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let&amp;rsquo;s consider what likely needs to happen:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The UI will likely provide some on-click handling so we need to add an
handler that gets triggered when a click on an item occurs&lt;/li&gt;
&lt;li&gt;The handler needs to get hold of the user or maybe a user&amp;rsquo;s cart&lt;/li&gt;
&lt;li&gt;The user or the cart needs to expose a method like &lt;code&gt;addItem&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;addItem&lt;/code&gt; method needs to modify the cart state (maybe add the item as a
reference to a list internally) and this needs to be reflected in the
rendering logic of the cart, e.g. by rendering the list length as a number
label somewhere.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So how could a task like this be done in a programming environment like
Smalltalk?&lt;/p&gt;
&lt;p&gt;We would start the app and then locate the on-click handler which might be a
method or a block (an anonymous function). The first thing we do is to add a
breakpoint to it (the statement &lt;code&gt;self halt&lt;/code&gt;. in Smalltalk parlance). We then click
on an item, a debugger window appears. We have now halted the execution in
mid-stride and have access to the item, the click event. Let&amp;rsquo;s say the item has
a reference to the user&amp;rsquo;s cart. We modify the handler code so that the &lt;code&gt;addItem&lt;/code&gt;
method gets called /right inside the debugger/, while having direct access (for
inspection or code completion) to all the objects involved. Let&amp;rsquo;s assume the
&lt;code&gt;addItem&lt;/code&gt; method does not exist but we continue the execution anyway. The debugger
will pop open again telling us that the item has no such method but also
offering us to create it. We choose the latter action and end up in the debugger
being able to fill the body of the &lt;code&gt;addItem&lt;/code&gt; method similarly as before with
access to all the objects involved.&lt;/p&gt;
&lt;p&gt;Compare that to the typical edit-compile-run approach. Consider that the
incremental changes map nicely to the &amp;ldquo;plan&amp;rdquo; we made before. In particular there
was no need for multiple program restarts including getting to a program state
we could use for testing the changes. Apart from not having to wait for
compilation we were placed right into the control flow with /concrete/ access to
all data and objects. This directness and immediacy lowers the abstraction level
we have to deal with: Instead of thinking in (abstract) classes we have concrete
objects at our fingertips, decreasing the cognitive load we have to deal with.
David Buck described this much more beautifully in his post &lt;a href=&#34;http://simberon.blogspot.com/2013/01/swimming-with-fish.html&#34;&gt;Swimming with the Fish&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Why am I writing about this? Because even though computers are able to guide us
in this manner since at least 40 years, the state of the art of development
tools has not caught up. Even more, this topic does not even seem to be on the
radar of most people working on programming languages, tools and frameworks. If
it does than often as reminiscent memories to the &amp;ldquo;good old days&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;I consider this to be an extremely important issue for a number of reasons. Two
of the more important ones: I believe that the average efficiency of software
developers working in the industry is only a fraction of what it could be. I
find it at least reasonable to think that there could be huge potential cost
savings with more efficient tooling.&lt;/p&gt;
&lt;p&gt;Much more important than that, though: Dynamic, incremental, and explorative
interaction with programs is just a stepping stone for creating computers that
really are &amp;ldquo;bicycles for the mind&amp;rdquo; — personal assistants that facilitate
thinking, learning, and simulating. But how can we build truly flexible
assistants for everyone if we can&amp;rsquo;t even get the tooling for professional
developers caught up to decades old insights?&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;The authors concluded that individual performance differences are too
high to answer the original question.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    
  </channel>
</rss>
