<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>github on
A Scripter's Notes</title><link>https://scripter.co/tags/github/</link><description>Recent content in github
on A Scripter's Notes</description><language>en-us</language><managingEditor>kaushal.modi@gmail.com (Kaushal Modi)</managingEditor><webMaster>kaushal.modi@gmail.com (Kaushal Modi)</webMaster><lastBuildDate>Wed, 22 Apr 2026 08:24:58 -0400</lastBuildDate><generator>Hugo -- gohugo.io</generator><docs>https://validator.w3.org/feed/docs/rss2.html</docs><atom:link href="https://scripter.co/tags/github/index.xml" rel="self" type="application/rss+xml"/><item><title>View GitHub Pull Requests in Magit</title><link>https://scripter.co/view-github-pull-requests-in-magit/</link><description>&lt;blockquote>How to view GitHub Pull Request branches locally in the cloned repo,
and more importantly, how to do that automatically from within Emacs.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#locally-creating-a-branch-for-a-pr">Locally creating a branch for a PR&lt;/a>&lt;/li>
&lt;li>&lt;a href="#getting-references-to-all-pull-requests">Getting references to all Pull Requests&lt;/a>&lt;/li>
&lt;li>&lt;a href="#automatically-adding-pr-refs">Automatically adding PR refs&lt;/a>&lt;/li>
&lt;li>&lt;a href="#summary">Summary&lt;/a>&lt;/li>
&lt;li>&lt;a href="#references">References&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>I have a few public projects in git repos, but I don&amp;rsquo;t get that much
traffic in &lt;em>Pull Requests (PR)&lt;/em>
&lt;span class="sidenote-number">&lt;small class="sidenote">
Gitlab calls these &lt;em>Merge Requests&lt;/em> or MRs.
&lt;/small>&lt;/span>
. So when I need to add additional commits to a PR, I would just add
the PR author&amp;rsquo;s &lt;em>remote&lt;/em> to my local repo, &lt;em>check out&lt;/em> their PR
branch, add my own commits and then merge that to my project&amp;rsquo;s &lt;em>main&lt;/em>
branch.&lt;/p>
&lt;p>As these occurrences were few and far apart, I didn&amp;rsquo;t have a need to
view the &lt;em>PR branches&lt;/em> directly from within Emacs/Magit. Though, I
somehow knew that each GitHub Pull Request&amp;rsquo;s &lt;em>HEAD&lt;/em> got assigned a &lt;a href="https://git-scm.com/book/en/v2/Git-Internals-Git-References">git
&lt;strong>reference&lt;/strong>&lt;/a>. But I didn&amp;rsquo;t need to use that knowledge until today
😃.&lt;/p>
&lt;p>Today, when discussing &lt;a href="https://github.com/protesilaos/denote/pull/20">PR # 20&lt;/a> on &lt;a href="https://protesilaos.com/">Prot&amp;rsquo;s&lt;/a> &lt;a href="https://protesilaos.com/emacs/denote">Denote&lt;/a> package&amp;rsquo;s GitHub
mirror
&lt;span class="sidenote-number">&lt;small class="sidenote">
Prot uses &lt;a href="https://git.sr.ht/~protesilaos/denote">SourceHut&lt;/a> as the primary git forge for his Emacs
packages. But I am glad that he doesn&amp;rsquo;t mind the activity in Issues
and Pull Requests on the GitHub mirror.
&lt;/small>&lt;/span>
, he wrote &lt;a href="https://github.com/protesilaos/denote/pull/20#issuecomment-1164676013">this comment&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>Now I just need to figure out how best to incorporate your changes
into the &lt;code>org-id&lt;/code> branch so I can add the final bits. I am not too
familiar with the PR workflow &amp;hellip;&lt;/p>
&lt;/blockquote>
&lt;p>.. and that inspired this post today.&lt;/p>
&lt;h2 id="locally-creating-a-branch-for-a-pr">Locally creating a branch for a PR&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#locally-creating-a-branch-for-a-pr">#&lt;/a>&lt;/h2>
&lt;p>From the &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally">GitHub docs&lt;/a>, the &lt;code>git&lt;/code> command to create a local branch for a
PR is this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git fetch origin pull/ID/head:BRANCHNAME
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I have the &lt;code>denote&lt;/code> package cloned from its GitHub mirror. So the
&lt;strong>origin&lt;/strong> remote&amp;rsquo;s &lt;strong>url&lt;/strong> is &lt;code>https://github.com/protesilaos/denote&lt;/code>.&lt;/p>
&lt;div class="note">
&lt;p>Make sure that the remote name used in this command is pointing to a
GitHub repo, and not a mirror forge like GitLab or SourceHut.&lt;/p>
&lt;/div>
&lt;p>When I ran the below command, I got a new branch &lt;strong>pr-20&lt;/strong> pointing to
the latest commit of that PR:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git fetch origin pull/20/head:pr-20
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Awesome!&lt;/p>
&lt;div class="verse">
&lt;p>.. But that wasn&amp;rsquo;t good enough&lt;br />
    .. Now I wanted more&lt;br />
        .. I didn&amp;rsquo;t want to manually create a branch for each PR.&lt;br />&lt;/p>
&lt;/div>
&lt;h2 id="getting-references-to-all-pull-requests">Getting references to all Pull Requests&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#getting-references-to-all-pull-requests">#&lt;/a>&lt;/h2>
&lt;p>Now that I was on that quest of &amp;ldquo;I want more&amp;rdquo;, it didn&amp;rsquo;t take me long
to re-discover &lt;a href="https://oremacs.com/2015/03/11/git-tricks/#illusion-2-quickly-get-github-pull-requests-on-your-system">this 7-year old nugget&lt;/a> by &lt;a href="https://oremacs.com">Oleh Krehel&lt;/a>. Here are the
relevant bits from that post:&lt;/p>
&lt;ol>
&lt;li>Open the local repo&amp;rsquo;s &lt;code>.git/config&lt;/code> file.&lt;/li>
&lt;li>Find the &lt;code>[remote &amp;quot;origin&amp;quot;]&lt;/code> section&lt;/li>
&lt;li>Modify it by adding this one line with &lt;strong>pull&lt;/strong> refs. &lt;em>This is the
same for all GitHub repositories.&lt;/em>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cfg" data-lang="cfg">&lt;span class="line">&lt;span class="cl">&lt;span class="k">[remote &amp;#34;origin&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">https://github.com/USER/REPO.git
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> fetch = +refs/heads/*:refs/remotes/origin/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line hl">&lt;span class="cl">&lt;span class="s"> fetch = +refs/pull/*/head:refs/pull/origin/*&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>With that edit in place, when I did &lt;kbd>l&lt;/kbd> &lt;kbd>a&lt;/kbd> (show
the log for all git references), followed by &lt;kbd>f&lt;/kbd> &lt;kbd>a&lt;/kbd>
(fetch all the remotes) in the Magit, I could see the references to
the &lt;code>denote&lt;/code> repo&amp;rsquo;s PRs!&lt;/p>
&lt;p>&lt;a id="figure--magit-denote-pr-refs">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/view-github-pull-requests-in-magit/pr-20-ref.png" alt="Figure 1: Viewing PR references from denote package&amp;rsquo;s GitHub repo"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>Viewing PR references from &lt;code>denote&lt;/code> package&amp;rsquo;s GitHub repo
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;div class="verse">
&lt;p>.. But that still wasn&amp;rsquo;t good enough&lt;br />
    .. I didn&amp;rsquo;t want to manually edit the &lt;code>.git/config&lt;/code> in each repo.&lt;br />&lt;/p>
&lt;/div>
&lt;h2 id="automatically-adding-pr-refs">Automatically adding PR refs&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#automatically-adding-pr-refs">#&lt;/a>&lt;/h2>
&lt;p>Of course, I wasn&amp;rsquo;t the first one to think of this!&lt;/p>
&lt;p>Another Emacs veteran &lt;a href="https://endlessparentheses.com/">Artur Malabarba&lt;/a> had already had this covered
also around &lt;a href="https://endlessparentheses.com/automatically-configure-magit-to-access-github-prs.html">7 years back&lt;/a>. Coincidentally, that post was written as a
response to that same blog post by Oleh where he shared the above
&lt;code>.git/config&lt;/code> tip.&lt;/p>
&lt;p>In that post, Artur shares an Emacs Lisp function that uses Magit
functions like &lt;code>magit-get&lt;/code>, &lt;code>magit-get-all&lt;/code> and &lt;code>magit-git-string&lt;/code> to
auto-add the &lt;code>fetch = +refs/pull/*/head:refs/pull/origin/*&lt;/code> line in
the &lt;code>.git/config&lt;/code>. This magic happens after checking that the &lt;strong>origin&lt;/strong>
remote points to a GitHub repo, and if that line doesn&amp;rsquo;t already
exist.&lt;/p>
&lt;p>Here, I am lightly modifying the function shared in that post so that
the &lt;strong>origin&lt;/strong> remote name is not hard-coded
&lt;span class="sidenote-number">&lt;small class="sidenote">
The reason is that sometimes, I name the original remote as &lt;strong>upstream&lt;/strong>
and my fork as &lt;strong>fork&lt;/strong>, and I might have no remote named &lt;strong>origin&lt;/strong>.
&lt;/small>&lt;/span>
. Credit for the main logic in this code still goes to Artur.&lt;/p>
&lt;p>&lt;a id="code-snippet--add-PR-fetch-ref">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/add-PR-fetch-ref&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kp">&amp;amp;optional&lt;/span> &lt;span class="nv">remote-name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;If refs/pull is not defined on a GH repo, define it.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">If REMOTE-NAME is not specified, it defaults to the &lt;/span>&lt;span class="ss">`remote&amp;#39;&lt;/span>&lt;span class="s"> set
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">for the \&amp;#34;main\&amp;#34; or \&amp;#34;master\&amp;#34; branch.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let*&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">remote-name&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">or&lt;/span> &lt;span class="nv">remote-name&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get&lt;/span> &lt;span class="s">&amp;#34;branch&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;main&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get&lt;/span> &lt;span class="s">&amp;#34;branch&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;master&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">remote-url&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span> &lt;span class="s">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">fetch-refs&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">and&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">stringp&lt;/span> &lt;span class="nv">remote-url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">string-match&lt;/span> &lt;span class="s">&amp;#34;github&amp;#34;&lt;/span> &lt;span class="nv">remote-url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get-all&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span> &lt;span class="s">&amp;#34;fetch&amp;#34;&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; https://oremacs.com/2015/03/11/git-tricks/&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">fetch-address&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;+refs/pull/*/head:refs/pull/%s/*&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">when&lt;/span> &lt;span class="nv">fetch-refs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">unless&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">member&lt;/span> &lt;span class="nv">fetch-address&lt;/span> &lt;span class="nv">fetch-refs&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-git-string&lt;/span> &lt;span class="s">&amp;#34;config&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;--add&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;remote.%s.fetch&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">fetch-address&lt;/span>&lt;span class="p">)))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">add-hook&lt;/span> &lt;span class="ss">&amp;#39;magit-mode-hook&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">modi/add-PR-fetch-ref&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--add-PR-fetch-ref">Code Snippet 1&lt;/a>:&lt;/span>
Function to auto-add GitHub PR references to the repo's &lt;code>.git/config&lt;/code>
&lt;/div>
&lt;h2 id="summary">Summary&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#summary">#&lt;/a>&lt;/h2>
&lt;p>With the above snippet added to your Emacs config and evaluated, each
time you visit a repo cloned from GitHub in the Magit Status buffer
(&lt;code>M-x magit-status&lt;/code>), the PR refs will get auto-added to that repo&amp;rsquo;s
&lt;code>.git/config&lt;/code> if needed.&lt;/p>
&lt;p>After that, you can easily view the commits from all the PRs by doing
&lt;kbd>l&lt;/kbd> &lt;kbd>a&lt;/kbd> &lt;kbd>f&lt;/kbd> &lt;kbd>a&lt;/kbd>.&lt;/p>
&lt;h2 id="references">References&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#references">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://oremacs.com/2015/03/11/git-tricks/#illusion-2-quickly-get-github-pull-requests-on-your-system">oremacs &amp;ndash; Some git/magit/github tricks&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://endlessparentheses.com/automatically-configure-magit-to-access-github-prs.html">endlessparentheses &amp;ndash; Automatically configure Magit to access Github PRs&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally">GitHub &amp;ndash; Checking out PR branches locally&lt;/a>&lt;/li>
&lt;/ul></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/elisp">elisp</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/magit">magit</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/github">github</category><category domain="https://scripter.co/tags/git-reference">git-reference</category><guid>https://scripter.co/view-github-pull-requests-in-magit/</guid><pubDate>Thu, 23 Jun 2022 17:51:00 -0400</pubDate></item><item><title>Nim: Deploying static binaries</title><link>https://scripter.co/nim-deploying-static-binaries/</link><description>&lt;blockquote>Deploying Nim applications as static binaries for GNU/Linux type
operating systems, built using &lt;strong>musl&lt;/strong>.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#problem-statement">Problem statement&lt;/a>&lt;/li>
&lt;li>&lt;a href="#solution">Solution&lt;/a>&lt;/li>
&lt;li>&lt;a href="#1-building-static-binaries">1 Building static binaries&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#what-is-musl">What is musl?&lt;/a>&lt;/li>
&lt;li>&lt;a href="#installing-musl">Installing musl&lt;/a>&lt;/li>
&lt;li>&lt;a href="#static-linking">Static linking&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#2-optimizing-the-binary-size">2 Optimizing the binary size&lt;/a>&lt;/li>
&lt;li>&lt;a href="#3-doing-the-above-two-easily">3 Doing the above two easily&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#nimscript">NimScript&lt;/a>&lt;/li>
&lt;li>&lt;a href="#config-dot-nims">&lt;code>config.nims&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#4-creating-and-deploying-the-builds-automatically">4 Creating and deploying the builds automatically&lt;/a>&lt;/li>
&lt;li>&lt;a href="#how-it-works-in-practice">How it works in practice&lt;/a>&lt;/li>
&lt;li>&lt;a href="#repo">Repo&lt;/a>&lt;/li>
&lt;li>&lt;a href="#references">References&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;h2 id="problem-statement">Problem statement&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#problem-statement">#&lt;/a>&lt;/h2>
&lt;p>I&amp;rsquo;d like to create Nim applications, and then be able to easily deploy
the static built binaries so that anyone on GNU/Linux type OS can just
download the binary and run them.&lt;/p>
&lt;p>&lt;em>If and when I figure out how to do the same for macOS and Windows
too, I&amp;rsquo;ll write a separate post for that. If you can help me out with
that, please comment below, or open an issue/PR in the repo linked at
the end.&lt;/em>&lt;/p>
&lt;h2 id="solution">Solution&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#solution">#&lt;/a>&lt;/h2>
&lt;p>The solution is multi-step:&lt;/p>
&lt;ol>
&lt;li>Building static binaries (only for GNU/Linux type OS).&lt;/li>
&lt;li>Optimizing the binary size.&lt;/li>
&lt;li>Doing the above two easily.&lt;/li>
&lt;li>Creating and deploying the builds automatcally (on GitHub).&lt;/li>
&lt;/ol>
&lt;h2 id="1-building-static-binaries">1 Building static binaries&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#1-building-static-binaries">#&lt;/a>&lt;/h2>
&lt;p>My primary OS for coding and development is RHEL 6.8.&lt;/p>
&lt;p>By default, Nim builds dynamically linked binaries using the &lt;em>glibc&lt;/em>
version present on the OS where those binaries are built.&lt;/p>
&lt;p>Living on a stable but &lt;span class="underline">old&lt;/span> OS like RHEL 6.8 (that has &lt;em>glibc 2.12&lt;/em>
by default), I have ended up with the issue many a times&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> where
the deployed binary would be compiled with a newer &lt;em>glibc&lt;/em> and so it
wouldn&amp;rsquo;t run on my system. I would need to eventually compile that
binary myself.&lt;/p>
&lt;p>I don&amp;rsquo;t want to inflict other people with the same problem.&lt;/p>
&lt;p>Inspired by how statically compiled binaries are distributed for tools
built in other languages (&lt;a href="https://github.com/gohugoio/hugo/releases">hugo&lt;/a> [Go], &lt;a href="https://github.com/BurntSushi/ripgrep/releases">ripgrep&lt;/a> [Rust], &lt;a href="https://github.com/jgm/pandoc/releases">pandoc&lt;/a> [Haskell],
etc), I wanted the same for whatever I build with Nim.&lt;/p>
&lt;p>I kept looking around for a &amp;ldquo;single press button&amp;rdquo; flow to do this in
Nim for a while, and after finding nothing, I came up a flow myself,
that I present in this post.&lt;/p>
&lt;p>I picked &lt;strong>musl&lt;/strong> to statically compile my binaries.&lt;/p>
&lt;h3 id="what-is-musl">What is musl?&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#what-is-musl">#&lt;/a>&lt;/h3>
&lt;p>Here&amp;rsquo;s a one-liner description from &lt;a href="https://en.wikipedia.org/wiki/Musl">Wikipedia&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>musl&lt;/strong> is a C standard library intended for operating systems based on
the Linux kernel, released under the MIT License.&lt;/p>
&lt;/blockquote>
&lt;p>Check out its &lt;a href="https://www.musl-libc.org/intro.html">introduction&lt;/a> on its official webpage for more details.&lt;/p>
&lt;h3 id="installing-musl">Installing musl&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#installing-musl">#&lt;/a>&lt;/h3>
&lt;p>Installing musl was as simple as &lt;a href="https://www.musl-libc.org/download.html">downloading&lt;/a> its &lt;em>.tar.gz&lt;/em> and running
&lt;code>make &amp;amp;&amp;amp; make install&lt;/code> with the &lt;code>--prefix&lt;/code> configured
appropriately. For the examples that follow, let&amp;rsquo;s say you set the
prefix to &lt;code>/usr/local/musl/&lt;/code>.&lt;/p>
&lt;div class="note">
&lt;p>Do &lt;strong>not&lt;/strong> install musl at the default &lt;em>prefix&lt;/em> location, else it will
override a lot of default header files &amp;ndash; an outcome that you probably
don&amp;rsquo;t want.&lt;/p>
&lt;/div>
&lt;ul>
&lt;li>With the &lt;em>prefix&lt;/em> set as above, the &lt;code>musl-gcc&lt;/code> binary would get
installed in the &lt;code>/usr/local/musl/bin/&lt;/code> directory.&lt;/li>
&lt;li>Add &lt;code>/usr/local/musl/bin/&lt;/code> to your &lt;code>PATH&lt;/code> environment variable.&lt;/li>
&lt;/ul>
&lt;h3 id="static-linking">Static linking&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#static-linking">#&lt;/a>&lt;/h3>
&lt;p>By default, Nim will use the &lt;code>gcc&lt;/code> executable that&amp;rsquo;s found in &lt;code>PATH&lt;/code>
for C compilation. But using the &lt;code>--gcc.exe&lt;/code> switch, we override to
use the &lt;code>musl-gcc&lt;/code> executable. Similarly, we use the &lt;code>--gcc.linkerexe&lt;/code>
switch to use &lt;code>musl-gcc&lt;/code> too, and then the &lt;code>-static&lt;/code> option is passed
to the linker using the &lt;code>--passL&lt;/code> switch.&lt;/p>
&lt;p>With a &lt;code>hello.nim&lt;/code> containing:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-nim" data-lang="nim">&lt;span class="line">&lt;span class="cl">&lt;span class="n">echo&lt;/span> &lt;span class="s">&amp;#34;Hello, World!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>running the below:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Assuming that musl-gcc binary is found in PATH.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nim --gcc.exe:musl-gcc --gcc.linkerexe:musl-gcc --passL:-static c hello.nim
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I got a &lt;em>98kB&lt;/em> statically linked &lt;code>hello&lt;/code> binary.&lt;/p>
&lt;h2 id="2-optimizing-the-binary-size">2 Optimizing the binary size&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#2-optimizing-the-binary-size">#&lt;/a>&lt;/h2>
&lt;p>The binary size can be optimized by Nim itself by doing a Release
build (&lt;code>-d:release&lt;/code>) which disables runtime checks used for debugging,
and enables certain optimizations. Adding &lt;code>--opt:size&lt;/code> does further
binary-size optimization.&lt;/p>
&lt;p>So, with the same &lt;code>hello.nim&lt;/code>, running the below:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Assuming that musl-gcc binary is found in PATH.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nim --gcc.exe:musl-gcc --gcc.linkerexe:musl-gcc --passL:-static -d:release --opt:size c hello.nim
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>shrunk down the binary size to &lt;em>43kB&lt;/em>.&lt;/p>
&lt;p>Upon running external utilities like &lt;a href="https://sourceware.org/binutils/docs/binutils/strip.html">&lt;code>strip&lt;/code> (from &lt;code>binutils&lt;/code>)&lt;/a>&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>
and &lt;a href="https://github.com/upx/upx">&lt;code>upx&lt;/code>&lt;/a>&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>, the binary size shrunk even further! &amp;ndash; &lt;strong>16kB&lt;/strong>.&lt;/p>
&lt;p>&lt;a id="code-snippet--musl-plus-opt">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Assuming that musl-gcc binary is found in PATH.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nim --gcc.exe:musl-gcc --gcc.linkerexe:musl-gcc --passL:-static -d:release --opt:size c hello.nim
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">strip -s ./hello
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">upx --best ./hello
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--musl-plus-opt">Code Snippet 1&lt;/a>:&lt;/span>
Static linking using &lt;code>musl-gcc&lt;/code> plus binary size optimization
&lt;/div>
&lt;h2 id="3-doing-the-above-two-easily">3 Doing the above two easily&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#3-doing-the-above-two-easily">#&lt;/a>&lt;/h2>
&lt;p>All of that is great, but it wouldn&amp;rsquo;t be fun or elegant to do all the
steps in &lt;a href="#code-snippet--musl-plus-opt">Code Snippet 1&lt;/a> manually (or even in a &lt;em>shell&lt;/em> script).&lt;/p>
&lt;p>Wouldn&amp;rsquo;t it be awesome if I could just run a &lt;code>nim musl hello.nim&lt;/code> command‽&lt;/p>
&lt;div class="verse">
&lt;p>    &amp;mdash; And that&amp;rsquo;s what I do! 😎&lt;br />&lt;/p>
&lt;/div>
&lt;h3 id="nimscript">NimScript&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#nimscript">#&lt;/a>&lt;/h3>
&lt;p>The &amp;ldquo;nim musl&amp;rdquo; command is not available out-of-box, but it is easy to
create one using a &lt;a href="https://nim-lang.org/docs/nims.html">NimScript config file&lt;/a>, which is in the form of a
project-specific &lt;code>config.nims&lt;/code>.&lt;/p>
&lt;div class="note">
&lt;p>Think of NimScripts as much superior &amp;ldquo;bash scripts&amp;rdquo; as they are
written in Nim 😄&lt;/p>
&lt;/div>
&lt;p>From the &lt;a href="https://nim-lang.org/docs/nims.html">NimScript docs&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>Strictly speaking, NimScript is the subset of Nim that can be
evaluated by Nim&amp;rsquo;s builtin virtual machine (VM). This VM is used for
Nim&amp;rsquo;s compiletime function evaluation features, but also replaces
Nim&amp;rsquo;s existing configuration system.&lt;/p>
&lt;p>The VM cannot deal with &lt;code>importc&lt;/code>, the FFI is not available, so there
are not many stdlib modules that you can use with Nim&amp;rsquo;s VM. However,
at least the following modules are available:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://nim-lang.org/docs/strutils.html">strutils&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://nim-lang.org/docs/math.html">math&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://nim-lang.org/docs/distros.html">distros&lt;/a>&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;p>That list of modules is not comprehensive. I believe that the &lt;a href="https://nim-lang.org/docs/macros.html">macros&lt;/a>
module should be added to that list too (we also happen to need it for
the &lt;code>error&lt;/code> macros in the &lt;code>config.nims&lt;/code> below 😄).&lt;/p>
&lt;p>So, instead of having to resort to the hacky bash scripts, NimScript
allows one to write scripts in the awesome Nim syntax, and it&amp;rsquo;s
platform-agnostic too!&lt;/p>
&lt;p>Also, as you see below, the &lt;em>tasks&lt;/em> in NimScripts basically become
user-defined Nim-subcommands. For example, &amp;ldquo;nim musl&amp;rdquo; command doesn&amp;rsquo;t
exist, but I could make one &lt;em>just like that&lt;/em> by defining a &amp;ldquo;musl&amp;rdquo;
NimScript &lt;em>task&lt;/em>.&lt;/p>
&lt;h3 id="config-dot-nims">&lt;code>config.nims&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#config-dot-nims">#&lt;/a>&lt;/h3>
&lt;p>Below &lt;code>config.nims&lt;/code> is generic and would work for most Nim
projects. You need to just put it in the directory from where you
compile the Nim code.&lt;/p>
&lt;p>&lt;em>Nim &lt;strong>devel&lt;/strong> (v0.18.1) is needed for the below NimScript to work,
because the &lt;code>findExe&lt;/code> I use in there was not present in Nim v0.18.0.&lt;/em>&lt;/p>
&lt;p>&lt;a id="code-snippet--musl-config-nims">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-nim" data-lang="nim">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># config.nims&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="n">macros&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">error&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="n">ospaths&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">splitFile&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">`&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="p">`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># -d:musl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">when&lt;/span> &lt;span class="n">defined&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">musl&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="n">muslGccPath&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kt">string&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">echo&lt;/span> &lt;span class="s">&amp;#34; [-d:musl] Building a static binary using musl ..&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">muslGccPath&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">findExe&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;musl-gcc&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># echo &amp;#34;debug: &amp;#34; &amp;amp; muslGccPath&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">muslGccPath&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;&amp;#39;musl-gcc&amp;#39; binary was not found in PATH.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">switch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;gcc.exe&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">muslGccPath&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">switch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;gcc.linkerexe&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">muslGccPath&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">switch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;passL&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;-static&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">proc &lt;/span>&lt;span class="nf">binOptimize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">binFile&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kt">string&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sd">## Optimize size of the ``binFile`` binary.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">echo&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">findExe&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;strip&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">echo&lt;/span> &lt;span class="s">&amp;#34;Running &amp;#39;strip -s&amp;#39; ..&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exec&lt;/span> &lt;span class="s">&amp;#34;strip -s &amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">binFile&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">findExe&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;upx&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># https://github.com/upx/upx/releases/&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">echo&lt;/span> &lt;span class="s">&amp;#34;Running &amp;#39;upx --best&amp;#39; ..&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exec&lt;/span> &lt;span class="s">&amp;#34;upx --best &amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">binFile&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># nim musl foo.nim&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">task&lt;/span> &lt;span class="n">musl&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Builds an optimized static binary using musl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sd">## Usage: nim musl &amp;lt;.nim file path&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">numParams&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">paramCount&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">numParams&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;The &amp;#39;musl&amp;#39; sub-command needs exactly 1 argument, the Nim file (but &amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">numParams&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34; were detected).&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s"> Usage Example: nim musl FILE.nim.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">nimFile&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">paramStr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">numParams&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="sd">## The nim file name *must* be the last.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="n">dirName&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">baseName&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">_&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">splitFile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">nimFile&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">binFile&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dirName&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">baseName&lt;/span> &lt;span class="c"># Save the binary in the same dir as the nim file&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">nimArgs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;c -d:musl -d:release --opt:size &amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">nimFile&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># echo &amp;#34;[debug] nimFile = &amp;#34; &amp;amp; nimFile &amp;amp; &amp;#34;, binFile = &amp;#34; &amp;amp; binFile&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Build binary&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">echo&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">Running &amp;#39;nim &amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">nimArgs&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;#39; ..&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">selfExec&lt;/span> &lt;span class="n">nimArgs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Optimize binary&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">binOptimize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">binFile&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">echo&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">Created binary: &amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">binFile&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--musl-config-nims">Code Snippet 2&lt;/a>:&lt;/span>
&lt;code>config.nims&lt;/code> defining the &lt;b>musl&lt;/b> NimScript &lt;i>task&lt;/i>
&lt;/div>
&lt;p>Here&amp;rsquo;s a quick breakdown of that script:&lt;/p>
&lt;ul>
&lt;li>We first import the modules we would need for the sugar-syntax
&lt;code>error&lt;/code> macro, and for basic file path operations.&lt;/li>
&lt;li>&lt;code>when defined(musl)&lt;/code> block is used to do something extra to the nim
command if user has passed a &lt;code>-d:musl&lt;/code> switch during compilation
(this custom compile-time define switch is used in the &amp;ldquo;musl&amp;rdquo; task).&lt;/li>
&lt;li>The &lt;code>binOptimize&lt;/code> is just a Nim &lt;em>proc&lt;/em> to contain the outside-Nim
binary size optimization commands.&lt;/li>
&lt;li>Finally, the NimScript &lt;a href="https://nim-lang.org/docs/nimscript.html#task.t,untyped,string,untyped">&lt;strong>task&lt;/strong>&lt;/a> &amp;ldquo;musl&amp;rdquo; allows me to define my custom
&amp;ldquo;musl&amp;rdquo; sub-command for &lt;code>nim&lt;/code> so that I can run &lt;code>nim musl FOO.nim&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>With a directory containing this &lt;code>config.nims&lt;/code> and a &lt;code>FOO.nim&lt;/code>,
running &lt;code>nim musl FOO.nim&lt;/code> will be analogous to manually running the
commands in &lt;a href="#code-snippet--musl-plus-opt">Code Snippet 1&lt;/a>.&lt;/p>
&lt;h2 id="4-creating-and-deploying-the-builds-automatically">4 Creating and deploying the builds automatically&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#4-creating-and-deploying-the-builds-automatically">#&lt;/a>&lt;/h2>
&lt;p>All of that is still great, but ..&lt;/p>
&lt;div class="verse">
&lt;p>    Wouldn&amp;rsquo;t it be awesome if I could do all of that &lt;strong>automatically&lt;/strong> to create static binary releases for my Nim projects‽&lt;br />&lt;/p>
&lt;/div>
&lt;p>And of course, I can do that too! &amp;ndash; At least on GitHub using Travis
CI.&lt;/p>
&lt;p>&lt;em>I would also like to know how to do the same on non-GitHub repos
too. If you know, please comment below.&lt;/em>&lt;/p>
&lt;p>Below is a generic &lt;code>.travis.yml&lt;/code> that works for a repo name &amp;ldquo;FOO&amp;rdquo; and
containing the Nim code in its &amp;ldquo;src/FOO.nim&amp;rdquo; file. Notes on what this
config file does follow after that snippet.&lt;/p>
&lt;p>&lt;a id="code-snippet--musl-travis">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">language&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">c&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">sudo&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">required&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">cache&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">directories&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">nim&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">upx&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">env&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">global&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">PROGNAME=&amp;#34;$(basename ${TRAVIS_BUILD_DIR})&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># /travis/build/kaushalmodi/hello_musl -&amp;gt; hello_musl&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">NIMFILE=&amp;#34;src/${PROGNAME}.nim&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">BINFILE=&amp;#34;src/${PROGNAME}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">ASSETFILE=&amp;#34;${PROGNAME}-${TRAVIS_TAG}.Linux_64bit_musl.tar.xz&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">NIMREPO=&amp;#34;https://github.com/nim-lang/Nim&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">NIMVER=&amp;#34;$(git ls-remote ${NIMREPO} devel | cut -f 1)&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">NIMDIR=&amp;#34;${TRAVIS_BUILD_DIR}/nim/${NIMVER}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">UPXVER=&amp;#34;3.95&amp;#34; &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Change this value when upgrading upx&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">addons&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">apt&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">packages&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># For building MUSL static builds on Linux.&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">musl-tools&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">install&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">echo &amp;#34;NIMDIR = ${NIMDIR}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># After building nim, wipe csources to save on cache space.&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;{ [ -f ${NIMDIR}/bin/nim ]; } ||
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> ( rm -rf nim;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> mkdir -p nim;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> git clone --single-branch --branch devel --depth=1 ${NIMREPO} ${NIMDIR};
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> cd ${NIMDIR};
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> [ -d csources ] || git clone --depth 1 https://github.com/nim-lang/csources.git;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> cd csources;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> sh build.sh;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> cd ..;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> ./bin/nim c koch;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> ./koch boot -d:release;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> rm -rf csources;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> )&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">export PATH=&amp;#34;${NIMDIR}/bin:${PATH}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">nim -v&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">echo &amp;#34;Installing upx ..&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;{ [ -f upx/${UPXVER}/upx ]; } ||
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> { curl -OL https://github.com/upx/upx/releases/download/v${UPXVER}/upx-${UPXVER}-amd64_linux.tar.xz;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> tar xvf upx-${UPXVER}-amd64_linux.tar.xz;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> mkdir -p upx;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> mv upx-${UPXVER}-amd64_linux upx/${UPXVER};
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> }&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">export PATH=&amp;#34;${TRAVIS_BUILD_DIR}/upx/${UPXVER}/:${PATH}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">upx --version | grep -E &amp;#39;^upx&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Ensure that you are in repo/build root now.&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">cd &amp;#34;${TRAVIS_BUILD_DIR}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">echo &amp;#34;NIMFILE = ${NIMFILE}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">echo &amp;#34;BINFILE = ${BINFILE}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Compile the static binary using musl.&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">nim musl &amp;#34;${NIMFILE}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># See that the binary is not dynamic.&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">ldd &amp;#34;${BINFILE}&amp;#34; || true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Run the binary.&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;${BINFILE}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">before_deploy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">cd &amp;#34;${TRAVIS_BUILD_DIR}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">cp &amp;#34;${BINFILE}&amp;#34; &amp;#34;${PROGNAME}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">tar caf &amp;#34;${ASSETFILE}&amp;#34; &amp;#34;${PROGNAME}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">deploy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">provider&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">releases&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">api_key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;${GITHUB_OAUTH_TOKEN}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">file&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;${ASSETFILE}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">skip_cleanup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--musl-travis">Code Snippet 3&lt;/a>:&lt;/span>
GitHub Travis CI config file to generate musl-built Release assets
&lt;/div>
&lt;ul>
&lt;li>I like environment variables to do all the configuration. So I do
that in the &lt;em>env / global&lt;/em> block.&lt;/li>
&lt;li>Caching is enabled for &amp;ldquo;nim&amp;rdquo; and &amp;ldquo;upx&amp;rdquo; directories, which are
created in the &lt;em>install&lt;/em> block.
&lt;ul>
&lt;li>So if the Nim &lt;em>devel&lt;/em> branch hasn&amp;rsquo;t been updated since the last
Travis build, the cached Nim build is used.&lt;/li>
&lt;li>And similar applies to the &lt;code>upx&lt;/code> binary, which relies on the value
of the &lt;code>UPXVER&lt;/code> env variable.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>In the &lt;em>install&lt;/em> block, &lt;code>nim&lt;/code> is built from the Nim &lt;em>devel&lt;/em> branch
HEAD, and &lt;code>upx&lt;/code> binary is downloaded from the Releases section of
its repo.&lt;/li>
&lt;li>The key command is &lt;code>nim musl &amp;quot;${NIMFILE}&amp;quot;&lt;/code> in the &lt;em>script&lt;/em> block,
which uses the &lt;strong>musl&lt;/strong> NimScript task defined in the &lt;a href="#code-snippet--musl-config-nims">&lt;code>config.nims&lt;/code>&lt;/a> in
the same repo.&lt;/li>
&lt;li>In &lt;em>before_deploy&lt;/em>, &lt;code>tar&lt;/code> is used to create an archive of the
generated binary.&lt;/li>
&lt;li>The &lt;em>deploy&lt;/em> section is mainly copy-paste of &lt;a href="https://docs.travis-ci.com/user/deployment/releases/">what&amp;rsquo;s suggested&lt;/a> in the
Travis CI documentation.
&lt;ul>
&lt;li>About the &lt;code>${GITHUB_OAUTH_TOKEN}&lt;/code>, the first step is to get your
GitHub account&amp;rsquo;s &lt;strong>repo&lt;/strong> level token from &lt;a href="https://github.com/settings/tokens">GitHub Tokens settings&lt;/a>.&lt;/li>
&lt;li>The second step is to create a custom environment variable named
&lt;strong>GITHUB_OAUTH_TOKEN&lt;/strong> in that repo&amp;rsquo;s Travis CI settings (ensure
that the variable&amp;rsquo;s value is not made public in the Travis CI&amp;rsquo;s
logs, though they are private by default), and assigning that
token string to that variable.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="how-it-works-in-practice">How it works in practice&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#how-it-works-in-practice">#&lt;/a>&lt;/h2>
&lt;p>Let&amp;rsquo;s assume that the one-time setup for a new repo is already
done. The &lt;code>config.nims&lt;/code> and &lt;code>.travis.yml&lt;/code> are committed and pushed to
the GitHub repo, and the &lt;code>GITHUB_OAUTH_TOKEN&lt;/code> environment variable is
set in the repo&amp;rsquo;s Travis settings.&lt;/p>
&lt;p>Now, to auto-generate the assets for each &lt;em>release&lt;/em>, all I need to do
is:&lt;/p>
&lt;ol>
&lt;li>Commit my changes to the Nim code.&lt;/li>
&lt;li>Tag the commit.&lt;/li>
&lt;li>Push the commit &lt;strong>and&lt;/strong> tag to GitHub.&lt;/li>
&lt;/ol>
&lt;h2 id="repo">Repo&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#repo">#&lt;/a>&lt;/h2>
&lt;p>You can find the latest versions of the above code in my &lt;em>Nim+musl&lt;/em>
template repo &lt;a href="https://github.com/kaushalmodi/hello_musl">&lt;strong>hello_musl&lt;/strong>&lt;/a>.&lt;/p>
&lt;p>You can also try downloading and running (on a GNU/Linux 64-bit OS)
the deployed static binary from &lt;a href="https://github.com/kaushalmodi/hello_musl/releases">its Releases section&lt;/a> and see this
printed in full glory! 😄&lt;/p>
&lt;blockquote>
&lt;p>Hello, World!&lt;/p>
&lt;/blockquote>
&lt;h2 id="references">References&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#references">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://www.reddit.com/r/programming/comments/2wk7q6/static_linking_with_nim/corwtl7/">r/nim &amp;ndash; Static Linking with Nim&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hookrace.net/blog/nim-binary-size/#using-the-c-standard-library">hookrace.net &amp;ndash; Statically linking against musl libc&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/nim-lang/Nim/wiki/Using-NimScript-for-configuration">Using NimScript for configuration&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://nim-lang.org/docs/nimscript.html">NimScript &amp;ldquo;API&amp;rdquo;&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;a href="https://github.com/dom96/choosenim/issues/15">One example&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>The &lt;em>binutils&lt;/em> &lt;strong>strip&lt;/strong> utility is used to remove complete
symbol tables and other debug info that are not needed for running the
executable.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>From &lt;a href="https://github.com/upx/upx/blob/master/README">its docs&lt;/a>, &lt;strong>UPX&lt;/strong> is an advanced executable file
compressor. UPX will typically reduce the file size of programs and
DLLs by around 50%-70%, thus reducing disk space, network load times,
download times and other distribution and storage costs.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/programming">programming</category><category domain="https://scripter.co/tags/nim">nim</category><category domain="https://scripter.co/tags/static">static</category><category domain="https://scripter.co/tags/binary">binary</category><category domain="https://scripter.co/tags/musl">musl</category><category domain="https://scripter.co/tags/gnu-linux">gnu-linux</category><category domain="https://scripter.co/tags/github">github</category><category domain="https://scripter.co/tags/travis-ci">travis-ci</category><guid>https://scripter.co/nim-deploying-static-binaries/</guid><pubDate>Mon, 24 Sep 2018 01:47:00 -0400</pubDate></item></channel></rss>