<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Yevhenii Babichenko</title>
    <description>The latest articles on Forem by Yevhenii Babichenko (@eugenebabichenko).</description>
    <link>https://forem.com/eugenebabichenko</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F238276%2Fe146673a-7dab-4c1a-a761-e7e818cb6a28.jpeg</url>
      <title>Forem: Yevhenii Babichenko</title>
      <link>https://forem.com/eugenebabichenko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/eugenebabichenko"/>
    <language>en</language>
    <item>
      <title>WezTerm: an actually good config key binding recipe</title>
      <dc:creator>Yevhenii Babichenko</dc:creator>
      <pubDate>Mon, 03 Jun 2024 16:54:01 +0000</pubDate>
      <link>https://forem.com/eugenebabichenko/wezterm-an-actually-good-config-key-binding-recipe-3lp5</link>
      <guid>https://forem.com/eugenebabichenko/wezterm-an-actually-good-config-key-binding-recipe-3lp5</guid>
      <description>&lt;p&gt;While &lt;a href="https://wezfurlong.org/wezterm/"&gt;WezTerm&lt;/a&gt; is a great terminal with sane defaults, it doesn't provide&lt;br&gt;
the default key binding to open the configuration file and edit it. That is&lt;br&gt;
understandable, everyone may have their own preference for that. Here we will&lt;br&gt;
figure out the recipe that would work everywhere and abide by modern standards.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The original article was posted at my homepage: &lt;a href="https://eugene-babichenko.github.io/blog/2024/06/03/wezterm-open-config/"&gt;https://eugene-babichenko.github.io/blog/2024/06/03/wezterm-open-config/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In my opinion, the proper way to go is to open the configuration file with the&lt;br&gt;
editor specified in the &lt;code&gt;EDITOR&lt;/code&gt; environment variable. I am also using macOS&lt;br&gt;
most of the time, so the most natural key binding to configure something is&lt;br&gt;
&lt;code&gt;Cmd+,&lt;/code&gt;. In many applications this key binding is universal for all operating&lt;br&gt;
systems.&lt;/p&gt;

&lt;p&gt;It is easy to find out where the WezTerm configuration file is located: there is&lt;br&gt;
always the &lt;code&gt;WEZTERM_CONFIG_FILE&lt;/code&gt; variable. Also there is always the&lt;br&gt;
&lt;code&gt;WEZTERM_CONFIG_DIR&lt;/code&gt; variable that should allow us to specify the working&lt;br&gt;
directory for our editor.&lt;/p&gt;

&lt;p&gt;The problem with the &lt;code&gt;EDITOR&lt;/code&gt; variable is that it may not be immediately&lt;br&gt;
accessible to WezTerm config via &lt;code&gt;os.getenv("EDITOR")&lt;/code&gt; if it was specified in&lt;br&gt;
your shell configuration (e.g. &lt;code&gt;.bashrc&lt;/code&gt;) and not it some other magical place.&lt;br&gt;
To solve this we will obviously need to load our editor inside the shell, which&lt;br&gt;
is conveniently accessible via the &lt;code&gt;SHELL&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Considering all of the above, we end up with the code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;wezterm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"wezterm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wezterm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config_builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SUPER"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;act&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SpawnCommandInNewWindow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="n"&gt;cwd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;os.getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"WEZTERM_CONFIG_DIR"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;os.getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SHELL"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;"-c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"$EDITOR $WEZTERM_CONFIG_FILE"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This greatness of this specific recipe is that it will work regardless of your&lt;br&gt;
preferred shell end editor as long as the &lt;code&gt;EDITOR&lt;/code&gt; variable is set. The &lt;code&gt;-c&lt;/code&gt;&lt;br&gt;
flag is accepted by all major *nix shells. Also, regardless of the fact your&lt;br&gt;
editor is running with an shell, the window will close immediately after you&lt;br&gt;
close the editor. And of course, you can swap &lt;code&gt;SpawnCommandInNewWindow&lt;/code&gt; with&lt;br&gt;
&lt;code&gt;SpawnCommandInNewTab&lt;/code&gt; or any custom &lt;code&gt;SpawnCommand&lt;/code&gt; call.&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>wezterm</category>
    </item>
    <item>
      <title>Automated multi-platform releases with GitHub Actions</title>
      <dc:creator>Yevhenii Babichenko</dc:creator>
      <pubDate>Sat, 09 May 2020 14:15:21 +0000</pubDate>
      <link>https://forem.com/eugenebabichenko/automated-multi-platform-releases-with-github-actions-1abg</link>
      <guid>https://forem.com/eugenebabichenko/automated-multi-platform-releases-with-github-actions-1abg</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://eugene-babichenko.github.io/blog/2020/05/09/github-actions-cross-platform-auto-releases/"&gt;The original article published in my blog&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;GitHub Actions allows you to create releases, build binaries, and upload them. Unfortunately, there is no official tutorial on how to create a release, build the code for multiple platforms, and upload binaries to the release. I will cover how to do that without any 3rd-party actions in this post. I assume that you are familiar with the basics of GitHub Actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selecting the workflow trigger
&lt;/h2&gt;

&lt;p&gt;First things first: let's select the trigger for our workflow. I &lt;code&gt;git&lt;/code&gt; tags for versioning, and for simplicity they begin with &lt;code&gt;v&lt;/code&gt;, so the simplest trigger we can use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;v[0-9]+.*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's continue to defining our jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the release
&lt;/h2&gt;

&lt;p&gt;Since we are going to do multiple builds defined in a matrix, creating the new release should be obviously done in a separate job. GitHub has the official &lt;a href="https://github.com/actions/create-release#example-workflow---create-a-release"&gt;example&lt;/a&gt; for that. The only difference from the example is that we add the job output. This output will be used by build jobs to upload their results to the created release.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;create_release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create release&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="c1"&gt;# Note this. We are going to use that in further jobs.&lt;/span&gt;
    &lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;upload_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.create_release.outputs.upload_url }}&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create release&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;create_release&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/create-release@v1&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;tag_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.ref }}&lt;/span&gt;
          &lt;span class="na"&gt;release_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Release ${{ github.ref }}&lt;/span&gt;
          &lt;span class="na"&gt;draft&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;prerelease&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Build and upload
&lt;/h2&gt;

&lt;p&gt;This is the final step. I won't dive into the details too much because you will have your own build scenarios. But here are a couple of things to highlight:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The build jobs will have &lt;code&gt;create_release&lt;/code&gt; as a dependency.&lt;/li&gt;
&lt;li&gt;The output of &lt;code&gt;create_release&lt;/code&gt; is used in the last "upload step".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can get more details on assets uploads &lt;a href="https://github.com/actions/upload-release-asset"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="na"&gt;release_assets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Release assets&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;create_release&lt;/span&gt; &lt;span class="c1"&gt;# we need to know the upload URL&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.config.os }}&lt;/span&gt; &lt;span class="c1"&gt;# we run many different builds&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# just an example matrix&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;macos-latest&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;windows-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# checkout of cource&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;
      &lt;span class="c1"&gt;# ... whatever build and packaging steps you need here&lt;/span&gt;
      &lt;span class="c1"&gt;# and finally do an upload!&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload release assets&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-release-asset@v1&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;upload_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ needs.create_release.outputs.upload_url }}&lt;/span&gt;
          &lt;span class="c1"&gt;# This is how it will be named on the release page. Put hatever name&lt;/span&gt;
          &lt;span class="c1"&gt;# you like, remember that they need to be different for each platform.&lt;/span&gt;
          &lt;span class="c1"&gt;# You can choose any build matrix parameters. For Rust I use the&lt;/span&gt;
          &lt;span class="c1"&gt;# target triple.&lt;/span&gt;
          &lt;span class="na"&gt;asset_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;program-name-${{ matrix.config.os }}&lt;/span&gt;
          &lt;span class="c1"&gt;# The path to the file you want to upload.&lt;/span&gt;
          &lt;span class="na"&gt;asset_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./path/to/your/file&lt;/span&gt;
          &lt;span class="c1"&gt;# probably you will need to change it, but most likely you are&lt;/span&gt;
          &lt;span class="c1"&gt;# uploading a binary file&lt;/span&gt;
          &lt;span class="na"&gt;asset_content_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/octet-stream&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A note on executable formats: if you are building for Windows and uploading an &lt;code&gt;.exe&lt;/code&gt; you can use two different steps for uploading the executable. One should have &lt;code&gt;if: matrix.config.os == 'windows-latest'&lt;/code&gt; and asset path &lt;code&gt;asset_path: ./path/to/your/file.exe&lt;/code&gt;. For *nix operating systems that usually are not using extensions for executables, use &lt;code&gt;if: matrix.config.os != 'windows-latest'&lt;/code&gt;. This is a very useful trick overall when creating jobs that should handle multiple platforms.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>github</category>
      <category>ci</category>
    </item>
    <item>
      <title>How to force Rust compiler to use several x86 instructions (popcount, etc)</title>
      <dc:creator>Yevhenii Babichenko</dc:creator>
      <pubDate>Wed, 13 Nov 2019 19:28:51 +0000</pubDate>
      <link>https://forem.com/eugenebabichenko/how-to-force-rust-compiler-to-use-several-x86-instructions-popcount-etc-496f</link>
      <guid>https://forem.com/eugenebabichenko/how-to-force-rust-compiler-to-use-several-x86-instructions-popcount-etc-496f</guid>
      <description>&lt;p&gt;Sometimes you need tricky operations on your binary data like counting bits, leading or trailing zeros and so on (for example, when you want to implement &lt;a href="https://en.wikipedia.org/wiki/Hash_array_mapped_trie"&gt;HAMT&lt;/a&gt; or sparse arrays). In Rust this is achieved by using methods like &lt;code&gt;.count_ones()&lt;/code&gt; and &lt;code&gt;.trailing_zeros()&lt;/code&gt;. The problem with those methods is that they are usually expanded in a huge pile of assembler code. But x86 (and some other architectures) have instructions to perform these counts (specifically, &lt;code&gt;popcnt&lt;/code&gt; and &lt;code&gt;tzcnt&lt;/code&gt;) and they are really fast (&lt;a href="https://software.intel.com/en-us/forums/intel-isa-extensions/topic/289168"&gt;1 cycle for execution and latency of 3 cycles&lt;/a&gt;). Today we will learn how to force Rust compiler to use those instructions and what are the possible pitfalls.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://eugene-babichenko.github.io/blog/2019/11/13/rust-popcount-intrinsics/"&gt;my website&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's start with an example. Here's the code that finds population counts of random integers (&lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=release&amp;amp;edition=2018&amp;amp;gist=2551cbb6a41adad36e45bc50bf26c3bb"&gt;on Rust Playground&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;// this is only to have this function separately in the asm output&lt;/span&gt;
&lt;span class="nd"&gt;#[inline(never)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="nf"&gt;.count_ones&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;count&lt;/code&gt; function looks like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;playground::count:
    mov eax, edi
    shr eax
    and eax, 1431655765
    sub edi, eax
    mov eax, edi
    and eax, 858993459
    shr edi, 2
    and edi, 858993459
    add edi, eax
    mov eax, edi
    shr eax, 4
    add eax, edi
    and eax, 252645135
    imul    eax, eax, 16843009
    shr eax, 24
    ret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wow. A huge pile of instructions and magic numbers. This is clearly not something we would like to see, especially in performance-critical places. Let's make this a little bit better (&lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=release&amp;amp;edition=2018&amp;amp;gist=a91e315224c79f2d6c72bb85d3fdfe2d"&gt;on Rust Playground&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;// this is only to have this function separately in the asm output&lt;/span&gt;
&lt;span class="nd"&gt;#[inline(never)]&lt;/span&gt;
&lt;span class="nd"&gt;#[cfg_attr(target_arch&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"x86_64"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;target_feature(enable&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"popcnt"&lt;/span&gt;&lt;span class="nd"&gt;))]&lt;/span&gt;
&lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="nf"&gt;.count_ones&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And here is the assembly code of &lt;code&gt;count&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;playground::count:
    popcnt  eax, edi
    ret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Only a single &lt;a href="https://software.intel.com/en-us/forums/intel-isa-extensions/topic/289168"&gt;very fast&lt;/a&gt; instruction! And that this will work with all integer types. There is a pitfall though: Rust requires us to mark functions as &lt;code&gt;unsafe&lt;/code&gt; when we use &lt;code&gt;target_feature&lt;/code&gt; so it makes sense to make functions using those features as small as possible.&lt;/p&gt;

&lt;p&gt;Also, you can do something similar with &lt;code&gt;.trailing_zeros()&lt;/code&gt; or &lt;code&gt;.leading_zeros()&lt;/code&gt; by using &lt;code&gt;target_feature(enable = "bmi1")&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To find feature names you can refer to architecture-specific &lt;a href="https://doc.rust-lang.org/std/intrinsics/index.html"&gt;intrinsics&lt;br&gt;
documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That's all, hope you find it useful!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>optimization</category>
      <category>tutorial</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Generating pretty version strings (including nightly) with Git and Makefiles</title>
      <dc:creator>Yevhenii Babichenko</dc:creator>
      <pubDate>Sat, 28 Sep 2019 13:55:40 +0000</pubDate>
      <link>https://forem.com/eugenebabichenko/generating-pretty-version-strings-including-nightly-with-git-and-makefiles-48p3</link>
      <guid>https://forem.com/eugenebabichenko/generating-pretty-version-strings-including-nightly-with-git-and-makefiles-48p3</guid>
      <description>&lt;p&gt;In my recent project, I faced the need to generate pretty version numbers for my&lt;br&gt;
local and nightly builds. Here I will describe the approach I came up with. In&lt;br&gt;
this tutorial, we will use Git, which stores version tags and the entire setup&lt;br&gt;
uses Makefiles. However, you should be able to adapt this approach to any build&lt;br&gt;
system.&lt;/p&gt;

&lt;p&gt;In the end, we will be able to get pretty and very informative version strings&lt;br&gt;
like &lt;code&gt;0.2.1-next-314da12-20190928&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can check out the code from this article in &lt;a href="https://gist.github.com/eugene-babichenko/f37d15626160914427563dff2edd57ed"&gt;this Gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First of all, we need to have versions based on git tags. Here, I will assume&lt;br&gt;
that version tags are in the format &lt;code&gt;v0.1.2&lt;/code&gt;. Given that, we can extract the&lt;br&gt;
latest tag and strip the &lt;code&gt;v&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;TAG_COMMIT&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nf"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shell&lt;/span&gt; git rev-list &lt;span class="nt"&gt;--abbrev-commit&lt;/span&gt; &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="nt"&gt;--max-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="nf"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# `2&amp;gt;/dev/null` suppress errors and `|| true` suppress the error codes.
&lt;/span&gt;&lt;span class="nv"&gt;TAG&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nf"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shell&lt;/span&gt; git describe &lt;span class="nt"&gt;--abbrev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="nv"&gt;${TAG_COMMIT}&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="nf"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# here we strip the version prefix
&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nv"&gt;$(TAG:v%=%)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script will not fail if there are no tags in the current repository, but&lt;br&gt;
this will generate an empty version string. In this case, we can build a version&lt;br&gt;
string from the latest git commit hash and add the commit date for additional&lt;br&gt;
info:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# get the latest commit hash in the short form
&lt;/span&gt;&lt;span class="nv"&gt;COMMIT&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nf"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shell&lt;/span&gt; git rev-parse &lt;span class="nt"&gt;--short&lt;/span&gt; HEAD&lt;span class="nf"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# get the latest commit date in the form of YYYYmmdd
&lt;/span&gt;&lt;span class="nv"&gt;DATE&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nf"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shell&lt;/span&gt; git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;%cd &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%Y%m%d"&lt;/span&gt;&lt;span class="nf"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# check if the version string is empty
&lt;/span&gt;&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;$(VERSION,)&lt;/span&gt;
    &lt;span class="nv"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nv"&gt;$(COMMIT)&lt;/span&gt;-&lt;span class="nv"&gt;$(DATA)&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give us a version string in a format like &lt;code&gt;314da12-20190928&lt;/code&gt; which&lt;br&gt;
gives us pretty much information about the build. Particularly, when the change&lt;br&gt;
was made and which commit we should look for.&lt;/p&gt;

&lt;p&gt;On top of that, we can deal with nightly builds that appeared after a particular&lt;br&gt;
version like that: &lt;code&gt;0.2.1-next-314da12-20190928&lt;/code&gt;. This line contains even more&lt;br&gt;
information as it includes the last stable version. We can quickly grab the&lt;br&gt;
version number and compare our changes to it to see what went wrong. This is how&lt;br&gt;
we generate this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="k"&gt;ifneq&lt;/span&gt; &lt;span class="nv"&gt;($(COMMIT), $(TAG_COMMIT))&lt;/span&gt;
    &lt;span class="nv"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nv"&gt;$(VERSION)&lt;/span&gt;&lt;span class="nt"&gt;-next-&lt;/span&gt;&lt;span class="nv"&gt;$(COMMIT)&lt;/span&gt;-&lt;span class="nv"&gt;$(DATE)&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we can indicate that we were building from a dirty git state (e.g. we&lt;br&gt;
had uncommitted changes during the build):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# git status --porcelain outputs a machine-readable text and the output is empty
# if the working tree is clean
&lt;/span&gt;&lt;span class="k"&gt;ifneq&lt;/span&gt; &lt;span class="nv"&gt;($(shell git status --porcelain),)&lt;/span&gt;
    &lt;span class="nv"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nv"&gt;$(VERSION)&lt;/span&gt;&lt;span class="nt"&gt;-dirty&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how the script looks in the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;TAG_COMMIT&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nf"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shell&lt;/span&gt; git rev-list &lt;span class="nt"&gt;--abbrev-commit&lt;/span&gt; &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="nt"&gt;--max-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="nf"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;TAG&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nf"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shell&lt;/span&gt; git describe &lt;span class="nt"&gt;--abbrev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="nv"&gt;${TAG_COMMIT}&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="nf"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;COMMIT&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nf"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shell&lt;/span&gt; git rev-parse &lt;span class="nt"&gt;--short&lt;/span&gt; HEAD&lt;span class="nf"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;DATE&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nf"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shell&lt;/span&gt; git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;%cd &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s2"&gt;"%Y%m%d"&lt;/span&gt;&lt;span class="nf"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nv"&gt;$(TAG:v%=%)&lt;/span&gt;
&lt;span class="k"&gt;ifneq&lt;/span&gt; &lt;span class="nv"&gt;($(COMMIT), $(TAG_COMMIT))&lt;/span&gt;
    &lt;span class="nv"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nv"&gt;$(VERSION)&lt;/span&gt;&lt;span class="nt"&gt;-next-&lt;/span&gt;&lt;span class="nv"&gt;$(COMMIT)&lt;/span&gt;-&lt;span class="nv"&gt;$(DATE)&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;$(VERSION,)&lt;/span&gt;
    &lt;span class="nv"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nv"&gt;$(COMMIT)&lt;/span&gt;-&lt;span class="nv"&gt;$(DATA)&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;span class="k"&gt;ifneq&lt;/span&gt; &lt;span class="nv"&gt;($(shell git status --porcelain),)&lt;/span&gt;
    &lt;span class="nv"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nv"&gt;$(VERSION)&lt;/span&gt;&lt;span class="nt"&gt;-dirty&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all! For me, this looks very good, because it does not use any additional&lt;br&gt;
tools apart from Git and &lt;code&gt;make&lt;/code&gt;. Hope you will find this useful!&lt;/p&gt;

&lt;p&gt;As a bonus, I would like to show how I integrate that with Go builds.&lt;/p&gt;

&lt;p&gt;First, you need to specify the &lt;code&gt;version&lt;/code&gt; variable in your &lt;code&gt;main&lt;/code&gt; package (I do&lt;br&gt;
it exactly this way because this is compatible with GoReleaser):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dev"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is my &lt;code&gt;Makefile&lt;/code&gt; for filling in that variable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;FLAGS&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nt"&gt;-ldflags&lt;/span&gt; &lt;span class="s2"&gt;"-X main.version=&lt;/span&gt;&lt;span class="nv"&gt;$(VERSION)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nl"&gt;build&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    go build &lt;span class="nv"&gt;$(FLAGS)&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; projectname-&lt;span class="nv"&gt;$(VERSION)&lt;/span&gt; main.go

&lt;span class="nl"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    go run &lt;span class="nv"&gt;$(FLAGS)&lt;/span&gt; main.go

&lt;span class="nl"&gt;install&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    go &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nv"&gt;$(FLAGS)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The original article is placed at my &lt;a href="https://eugene-babichenko.github.io/blog/2019/09/28/nightly-versions-makefiles/"&gt;github.io site&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>git</category>
      <category>go</category>
      <category>makefile</category>
    </item>
  </channel>
</rss>
