<?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>DEV Community: Joshua Matthews</title>
    <description>The latest articles on DEV Community by Joshua Matthews (@jmatth11).</description>
    <link>https://dev.to/jmatth11</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%2F809692%2F36f84146-5b45-4a91-840e-3704401055b6.jpeg</url>
      <title>DEV Community: Joshua Matthews</title>
      <link>https://dev.to/jmatth11</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jmatth11"/>
    <language>en</language>
    <item>
      <title>Named Params in C</title>
      <dc:creator>Joshua Matthews</dc:creator>
      <pubDate>Tue, 14 Oct 2025 18:05:43 +0000</pubDate>
      <link>https://dev.to/jmatth11/named-params-in-c-2a2n</link>
      <guid>https://dev.to/jmatth11/named-params-in-c-2a2n</guid>
      <description>&lt;p&gt;Table of Contents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Implementation in C&lt;/li&gt;
&lt;li&gt;Using our Implementation&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In a language like python you have the concept of &lt;code&gt;**kwargs&lt;/code&gt; as a function parameter. This special double &lt;code&gt;*&lt;/code&gt; syntax allows you to pass in named arguments captured as a dictionary, like the example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# kwargs is a dictionary
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Item name: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kind&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Kind: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;kind&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Quantity: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Liters: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;liters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Milk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;liters&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="c1"&gt;# output:
# Item name: Milk
# Quantity: 2
# Liters: 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows for a convenient way to pass arguments by their name in any order you'd like and have optional parameters without complicating the function signature.&lt;/p&gt;

&lt;p&gt;What if we could do this in C? (spoiler: there is a way)&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation in C
&lt;/h2&gt;

&lt;p&gt;Through the magic of the preprocessor we can accomplish this effect, optional parameters and all.&lt;/p&gt;

&lt;p&gt;First lets define our &lt;code&gt;item&lt;/code&gt; structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;item_t&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;liters&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;Next we'll define our print function like you would normally in C.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// name it with `__t` for the concrete function.&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_item__t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;item_t&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Item name: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Kind: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Quantity: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Liters: %f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;liters&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;Now we can write the &lt;em&gt;magically&lt;/em&gt; preprocessor part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// name the macro what we want and use `...` to signify va_args&lt;/span&gt;
&lt;span class="c1"&gt;// Then call our function with a structure with default values&lt;/span&gt;
&lt;span class="c1"&gt;// and the va_args at the end to overwrite any values.&lt;/span&gt;
&lt;span class="cp"&gt;#define print_item(...)            \
    print_item__t((struct item_t){ \
        .name = "default",         \
        .kind = NULL,              \
        .quantity = 0,             \
        .liters = 0,               \
        __VA_ARGS__                \
    })
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So lets break down this macro.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First we define the macro name and specify we are using va_args with &lt;code&gt;...&lt;/code&gt; as the parameter.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define print_item(...)            \
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Next we call the function with a structure of our &lt;code&gt;item_t&lt;/code&gt; with default values.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    print_item__t((struct item_t){ \
        .name = "default",         \
        .kind = NULL,              \
        .quantity = 0,             \
        .liters = 0,               \
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Last we pass in the &lt;code&gt;__VA_ARGS__&lt;/code&gt; values at the end of our default structure. This works because C allows the later defined properties to overwrite earlier ones.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        .liters = 0,               \
        __VA_ARGS__                \
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's how all of this would be structured in actual files.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;item.h&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#ifndef ITEM_H
#define ITEM_H
&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;item_t&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;liters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_item__t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;item_t&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cp"&gt;#define print_item(...)            \
    print_item__t((struct item_t){ \
        .name = "default",         \
        .kind = NULL,              \
        .quantity = 0,             \
        .liters = 0,               \
        __VA_ARGS__                \
    })
&lt;/span&gt;
&lt;span class="cp"&gt;#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;item.c&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"item.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_item__t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;item_t&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Item name: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Kind: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Quantity: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Liters: %f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;liters&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;h2&gt;
  
  
  Using our Implementation
&lt;/h2&gt;

&lt;p&gt;Now we can use our macro similar to the python example in the introduction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"item.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print_item&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Milk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quantity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;liters&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="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// output:&lt;/span&gt;
&lt;span class="c1"&gt;// Item name: Milk&lt;/span&gt;
&lt;span class="c1"&gt;// Quantity: 2&lt;/span&gt;
&lt;span class="c1"&gt;// Liters: 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Through preprocessor magic we can achieve a syntax convenience with calling functions that have struct parameters as options. This can be extremely useful for functions with lots of optional parameters and\or default values. However, preprocessor magic is something that is either loved or hated so you may want to consider if it's worth implementing in your project or not.&lt;/p&gt;

</description>
      <category>c</category>
      <category>python</category>
      <category>preprocessor</category>
      <category>programming</category>
    </item>
    <item>
      <title>Automated Cleanup in C</title>
      <dc:creator>Joshua Matthews</dc:creator>
      <pubDate>Wed, 18 Jun 2025 18:31:10 +0000</pubDate>
      <link>https://dev.to/jmatth11/automated-cleanup-in-c-1oli</link>
      <guid>https://dev.to/jmatth11/automated-cleanup-in-c-1oli</guid>
      <description>&lt;p&gt;Table of Contents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intro&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;
Usage

&lt;ul&gt;
&lt;li&gt;Errors and Branching&lt;/li&gt;
&lt;li&gt;Inside Loops&lt;/li&gt;
&lt;li&gt;Structures&lt;/li&gt;
&lt;li&gt;Deferring Operations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Macro Helpers&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;House-keeping in C can be tedious with manually freeing memory and providing cleanup code at every logical branch of your functions. However, compilers have added attributes that you can take advantage of to help with memory cleanup nowadays. I will step through and show case some of the powerful ways to use &lt;code&gt;__attribute__((cleanup(&amp;lt;function&amp;gt;)))&lt;/code&gt; within your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;This feature is supported by &lt;a href="https://clang.llvm.org/docs/AttributeReference.html#cleanup" rel="noopener noreferrer"&gt;Clang&lt;/a&gt; and &lt;a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute" rel="noopener noreferrer"&gt;GCC&lt;/a&gt; and their documentation provide small descriptions on how the feature is meant to be used. The quick overview is that this attribute allows you to register a callback function to a variable definition and gets called when the variable leaves the scope it was defined in. The basic structure is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;free_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free_char&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;strncpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test string = &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// free_char is called when this function exits&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&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;We start with defining our cleanup function &lt;code&gt;free_char&lt;/code&gt;. It accepts a &lt;code&gt;char **&lt;/code&gt; because the cleanup function passes the local variable as a pointer to the function. Since our variable is a pointer, it gets passed in as a double pointer.&lt;/p&gt;

&lt;p&gt;We then attach the attribute to the variable we want the cleanup function to happen to. This attribute can be in a few places and it will work.&lt;br&gt;
All of these definitions are valid:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;__attribute__((cleanup(free_char))) char *test = malloc(/* size */);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;char __attribute__((cleanup(free_char))) *test = malloc(/* size */);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;char *test __attribute__((cleanup(free_char))) = malloc(/* size */);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When defining your cleanup function you could technically get away with something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;generic_cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if you use a proper linter it'll throw warnings that the types don't match, so it's better to use explicit cleanup functions for your types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;With a basic overview of the feature understood, we'll cover a few more use cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Errors and Branching
&lt;/h3&gt;

&lt;p&gt;The immediate use-case is clean up of allocated variables. This can be very advantageous for functions with lots of error handling or branching logic with multiple return statements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;free_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;http_message_set_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;http_message_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;key_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free_char&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;normalized_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;normalized_cstr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// free previous value.&lt;/span&gt;
  &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;http_message_get_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// set new value, we copy the value to have ownership&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;hash_map_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;normalized_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;str_dup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"failed to set header.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// normalize_key is freed here&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// normalize_key is freed here&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;true&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;In the above example we attach a clean up function to the &lt;code&gt;normalized_key&lt;/code&gt; variable because it's only a temporary variable that we always want to free by the end of the function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inside Loops
&lt;/h3&gt;

&lt;p&gt;Another example with temporary variables is cleanup with variables inside loops.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;debug_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;item_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free_char&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item_detailed_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// tmp is freed here&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 is a trivial example but can be quite useful to not deal with cleanup inside loops.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structures
&lt;/h3&gt;

&lt;p&gt;Cleaning up structures are made easy as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;item_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;item_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// free item internals&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;item_operation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_free&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;item_t&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;item_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// handle error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// performa operations&lt;/span&gt;
    &lt;span class="c1"&gt;// tmp is freed here.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deferring Operations
&lt;/h3&gt;

&lt;p&gt;The last most useful example is deferred actions. This can range from needing DB operations called by the end of a scope, freeing mutexes, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;state_free_mutex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;state_t&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="n"&gt;pthread_mutex_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;state_update_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;state_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;item_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;item_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state_free_mutex&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;state_t&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;pthread_mutex_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// operate on items array and state&lt;/span&gt;

    &lt;span class="c1"&gt;// state's mutex is unlocked&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Macro Helpers
&lt;/h2&gt;

&lt;p&gt;The use-cases showcase how powerful this attribute can be, but it does come with cumbersome syntax. However, we can alleviate this with simple macros.&lt;/p&gt;

&lt;p&gt;The simplest approach is with the following macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define DEFER(cb) __attribute__((cleanup(cb)))
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! Now we can change the original example to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DEFER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;free_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;strncpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test string = &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// free_char is called when this function exits&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&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;That's much easier to read and type.&lt;/p&gt;

&lt;p&gt;You can take this a step further, if you'd like, and add predefined simple macros for common types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;free_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cp"&gt;#define AUTO_C DEFER(free_char)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which then allows the example to turn into this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;AUTO_C&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;strncpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test string = &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\"\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// free_char is called when this function exits&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The cleanup attribute is a versatile and powerful tool to utilize within your projects. Though C can be a tedious language to work with, compiler features like these help make working with C less problematic and provide a more robust way of interacting with the language.&lt;/p&gt;

</description>
      <category>c</category>
      <category>cleanup</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The 90% Makefile</title>
      <dc:creator>Joshua Matthews</dc:creator>
      <pubDate>Mon, 05 May 2025 23:27:03 +0000</pubDate>
      <link>https://dev.to/jmatth11/the-90-makefile-ai4</link>
      <guid>https://dev.to/jmatth11/the-90-makefile-ai4</guid>
      <description>&lt;p&gt;Contents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Project Setup&lt;/li&gt;
&lt;li&gt;Makefile&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I've been doing a lot of side projects in the C language lately.&lt;br&gt;
Which has lead me to write Makefiles for all the scenarios I encounter with each new project.&lt;/p&gt;

&lt;p&gt;The more I modified the Makefiles I was using to satisfy each new project structure&lt;br&gt;
has lead to a Makefile I barely need to change now.&lt;/p&gt;

&lt;p&gt;!!&lt;br&gt;
I know this Makefile won't solve all usecases but it tends to cover most of my needs.&lt;br&gt;
!!&lt;/p&gt;
&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;To start, I'll show what a typical project setup looks like for me.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;├── LICENSE
├── Makefile
├── README.md
├── compile_flags.txt
├── install_deps.sh
├── run.sh
├── resources
│   └── &amp;lt;resource files&amp;gt;
├── bin
│   ├── lib.&lt;span class="o"&gt;(&lt;/span&gt;so|a&lt;span class="o"&gt;)&lt;/span&gt;
│   └── exe
├── obj
│   └── &amp;lt;object files&amp;gt;
├── deps
│   └── &amp;lt;third party deps&amp;gt;
└── src
    ├── lib
    └── main.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll quickly give a highlight of everything, but the folders are the important part.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LICENSE&lt;/code&gt; the license.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Makefile&lt;/code&gt; The Makefile.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;README.md&lt;/code&gt; The readme.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;compile_flags.txt&lt;/code&gt; Clangd file for LSP configuration.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;install_deps.sh&lt;/code&gt; Shell file to install dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run.sh&lt;/code&gt; Shell script to run the generated executable.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resources&lt;/code&gt; The resources folder.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bin&lt;/code&gt; The folder for the target executable or library.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;obj&lt;/code&gt; The object files when compiling.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deps&lt;/code&gt; The third party dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src&lt;/code&gt; The source code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/lib&lt;/code&gt; The common code (like for a library).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Makefile
&lt;/h2&gt;

&lt;p&gt;Now that you know what folder structure to expect we can look at the Makefile.&lt;br&gt;
First I'll present the Makefile and then we will break it down.&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;# define our compiler
&lt;/span&gt;&lt;span class="nv"&gt;CC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gcc
&lt;span class="c"&gt;# define our generic compiler flags
&lt;/span&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt; &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c11
&lt;span class="c"&gt;# define the paths to our third party libraries
&lt;/span&gt;&lt;span class="nv"&gt;LIBS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-L&lt;/span&gt;./deps/example_lib/build &lt;span class="nt"&gt;-lexample_lib&lt;/span&gt;.so &lt;span class="nt"&gt;-lm&lt;/span&gt;
&lt;span class="c"&gt;# define the paths to our include directories
&lt;/span&gt;&lt;span class="nv"&gt;INCLUDES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-I&lt;/span&gt;./src &lt;span class="nt"&gt;-I&lt;/span&gt;./deps/example_lib/include

&lt;span class="c"&gt;# define variables for our source files
# we use find to grab them
&lt;/span&gt;&lt;span class="nv"&gt;SOURCES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;shell find ./src &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.c'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# define variable for our dependencies' Makefiles.
# we use find to grab only the top level Makefiles and also some convenient ignores.
&lt;/span&gt;&lt;span class="nv"&gt;DEPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;shell find ./deps &lt;span class="nt"&gt;-maxdepth&lt;/span&gt; 2 &lt;span class="nt"&gt;-name&lt;/span&gt; Makefile &lt;span class="nt"&gt;-printf&lt;/span&gt; &lt;span class="s1"&gt;'%h\n'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s1"&gt;'unittest'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s1"&gt;'^.$$'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# define folder paths and names
&lt;/span&gt;&lt;span class="nv"&gt;OBJ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;obj
&lt;span class="nv"&gt;BIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bin
&lt;span class="nv"&gt;TARGET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main

&lt;span class="c"&gt;# setup up conditional build flags
# if debug is set to 1, add debug specific flags
&lt;/span&gt;&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;($(DEBUG), 1)&lt;/span&gt;
    &lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nt"&gt;-DDEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-ggdb&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;span class="c"&gt;# Release specific flags
&lt;/span&gt;&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;($(RELEASE), 1)&lt;/span&gt;
    &lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nt"&gt;-O2&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;span class="c"&gt;# if SHARED flag is set, we prepare variables for building a shared/static library.
# we change the SOURCES variable to point to only the common source files.
# we also rename the TARGET to our library name.
&lt;/span&gt;&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;($(SHARED), 1)&lt;/span&gt;
    &lt;span class="nv"&gt;SOURCES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;shell find ./src/lib &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.c'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;TARGET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my_lib
&lt;span class="k"&gt;endif&lt;/span&gt;

&lt;span class="c"&gt;# This variable is for our object files.
# We take the files in SOURCES and rename them to end in .o
# Then we add our OBJ folder prefix to all files.
&lt;/span&gt;&lt;span class="nv"&gt;OBJECTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;addprefix &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/,&lt;span class="p"&gt;$(&lt;/span&gt;SOURCES:%.c&lt;span class="o"&gt;=&lt;/span&gt;%.o&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c"&gt;# We setup our default job
# it will build dependencies first then our source files.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;
&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;deps src&lt;/span&gt;

&lt;span class="c"&gt;# Build the source files.
# Conditional change to building for an executable or libraries.
# We also create the output BIN directory if it doesn't exist.
# This job depends on the OBJECT files.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;src&lt;/span&gt;
&lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(OBJECTS)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;($(SHARED), 1)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;TARGET&lt;span class="p"&gt;)&lt;/span&gt;.so &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LIBS&lt;span class="p"&gt;)&lt;/span&gt;
    ar &lt;span class="nt"&gt;-rcs&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;TARGET&lt;span class="p"&gt;)&lt;/span&gt;.a &lt;span class="nv"&gt;$^&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LIBS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;TARGET&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;

&lt;span class="c"&gt;# Compile all source files to object files
# This job executes because the `src` job depends on all the files in OBJECTS
# which has the `$(OBJ)/%.o` file signature.
&lt;/span&gt;&lt;span class="nl"&gt;$(OBJ)/%.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;%.c&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;INCLUDES&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Job to clean out all object files and exe/libs.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clean&lt;/span&gt;
&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt; 2&amp;gt; /dev/null
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt; 2&amp;gt; /dev/null

&lt;span class="c"&gt;# Job to run `make clean` on all dependencies.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clean_deps&lt;/span&gt;
&lt;span class="nl"&gt;clean_deps&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;foreach &lt;span class="nb"&gt;dir&lt;/span&gt;, &lt;span class="p"&gt;$(&lt;/span&gt;DEPS&lt;span class="p"&gt;)&lt;/span&gt;, &lt;span class="p"&gt;$(&lt;/span&gt;shell &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;MAKE&lt;span class="p"&gt;)&lt;/span&gt; clean&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c"&gt;# Job to clean dependencies and our files.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clean_all&lt;/span&gt;
&lt;span class="nl"&gt;clean_all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clean clean_deps&lt;/span&gt;

&lt;span class="c"&gt;# Job to run `make` on all of our dependencies.
# This only works if the dependencies' Makefile is at the top and implements a
# default job.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;deps&lt;/span&gt;
&lt;span class="nl"&gt;deps&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;foreach &lt;span class="nb"&gt;dir&lt;/span&gt;, &lt;span class="p"&gt;$(&lt;/span&gt;DEPS&lt;span class="p"&gt;)&lt;/span&gt;, &lt;span class="p"&gt;$(&lt;/span&gt;shell &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;MAKE&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Common Variables
&lt;/h3&gt;

&lt;p&gt;At the top we have our common variables to define our compiler, compiler flags,&lt;br&gt;
library paths, and includes paths.&lt;/p&gt;

&lt;p&gt;Add or remove anything from these variables to fit your project's requirements.&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;# define our compiler
&lt;/span&gt;&lt;span class="nv"&gt;CC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gcc
&lt;span class="c"&gt;# define our generic compiler flags
&lt;/span&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-Wall&lt;/span&gt; &lt;span class="nt"&gt;-Wextra&lt;/span&gt; &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c11
&lt;span class="c"&gt;# define the paths to our third party libraries
&lt;/span&gt;&lt;span class="nv"&gt;LIBS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-L&lt;/span&gt;./deps/example_lib/build &lt;span class="nt"&gt;-lexample_lib&lt;/span&gt;.so &lt;span class="nt"&gt;-lm&lt;/span&gt;
&lt;span class="c"&gt;# define the paths to our include directories
&lt;/span&gt;&lt;span class="nv"&gt;INCLUDES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-I&lt;/span&gt;./src &lt;span class="nt"&gt;-I&lt;/span&gt;./deps/example_lib/include
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Source Files
&lt;/h3&gt;

&lt;p&gt;We expect all of our source files to be under the &lt;code&gt;src&lt;/code&gt; folder. So we use&lt;br&gt;
&lt;code&gt;find&lt;/code&gt; to grab all of them. By default we assume we are compiling for an executable,&lt;br&gt;
we can change this later with some conditional logic.&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;# define variables for our source files
# we use find to grab them
&lt;/span&gt;&lt;span class="nv"&gt;SOURCES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;shell find ./src &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.c'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Dependencies
&lt;/h3&gt;

&lt;p&gt;We want to automate compiling our third party dependencies as well so we grab their&lt;br&gt;
Makefiles at the top of their directories. We exclude any unittest directories.&lt;/p&gt;

&lt;p&gt;This might need to change as well depending on what third party dependencies you use.&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;# define variable for our dependencies' Makefiles.
# we use find to grab only the top level Makefiles and also some convenient ignores.
&lt;/span&gt;&lt;span class="nv"&gt;DEPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;shell find ./deps &lt;span class="nt"&gt;-maxdepth&lt;/span&gt; 2 &lt;span class="nt"&gt;-name&lt;/span&gt; Makefile &lt;span class="nt"&gt;-printf&lt;/span&gt; &lt;span class="s1"&gt;'%h\n'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s1"&gt;'unittest'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Folders &amp;amp; Target
&lt;/h3&gt;

&lt;p&gt;We always need a &lt;code&gt;bin&lt;/code&gt; and &lt;code&gt;obj&lt;/code&gt; folder. We default the target to an executable&lt;br&gt;
name (this can change with conditional logic).&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;# define folder paths and names
&lt;/span&gt;&lt;span class="nv"&gt;OBJ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;obj
&lt;span class="nv"&gt;BIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bin
&lt;span class="nv"&gt;TARGET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conditional Flags
&lt;/h3&gt;

&lt;p&gt;We setup some conditional flags we can pass to &lt;code&gt;make&lt;/code&gt;. We define &lt;code&gt;DEBUG&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;RELEASE&lt;/code&gt;, and &lt;code&gt;SHARED&lt;/code&gt; already. The &lt;code&gt;DEBUG&lt;/code&gt; and &lt;code&gt;RELEASE&lt;/code&gt; modify the &lt;code&gt;CFLAGS&lt;/code&gt;&lt;br&gt;
to better align with their respective states.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SHARED&lt;/code&gt; flag is independant from the other conditional flags because it changes&lt;br&gt;
what source files we use and the &lt;code&gt;TARGET&lt;/code&gt; name.&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;# setup up conditional build flags
# if debug is set to 1, add debug specific flags
&lt;/span&gt;&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;($(DEBUG), 1)&lt;/span&gt;
    &lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nt"&gt;-DDEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-ggdb&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;span class="c"&gt;# Release specific flags
&lt;/span&gt;&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;($(RELEASE), 1)&lt;/span&gt;
    &lt;span class="nv"&gt;CFLAGS&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nt"&gt;-O2&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;span class="c"&gt;# if SHARED flag is set, we prepare variables for building a shared/static library.
# we change the SOURCES variable to point to only the common source files.
# we also rename the TARGET to our library name.
&lt;/span&gt;&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;($(SHARED), 1)&lt;/span&gt;
    &lt;span class="nv"&gt;SOURCES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;shell find ./src/lib &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s1"&gt;'*.c'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;TARGET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my_lib
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Object Files
&lt;/h3&gt;

&lt;p&gt;We setup our Object files next so we can construct them based on what the &lt;code&gt;SOURCES&lt;/code&gt;&lt;br&gt;
variable is conditionally set to.&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;# This variable is for our object files.
# We take the files in SOURCES and rename them to end in .o
# Then we add our OBJ folder prefix to all files.
&lt;/span&gt;&lt;span class="nv"&gt;OBJECTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;addprefix &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/,&lt;span class="p"&gt;$(&lt;/span&gt;SOURCES:%.c&lt;span class="o"&gt;=&lt;/span&gt;%.o&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Jobs
&lt;/h3&gt;

&lt;p&gt;The rest of the Makefile are the jobs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Default Job
&lt;/h4&gt;

&lt;p&gt;The first one is the default job. It's an empty job but we use it to set&lt;br&gt;
up the dependency tree for our Makefile.&lt;/p&gt;

&lt;p&gt;We first depend on &lt;code&gt;deps&lt;/code&gt; then &lt;code&gt;src&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="c"&gt;# We setup our default job
# it will build dependencies first then our source files.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;
&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;deps src&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Source Job
&lt;/h4&gt;

&lt;p&gt;We setup our &lt;code&gt;src&lt;/code&gt; job to have a dependency on the Object files we defined.&lt;/p&gt;

&lt;p&gt;Inside the job we create the &lt;code&gt;bin&lt;/code&gt; directory if it doesn't exist then we conditionally&lt;br&gt;
execute code to build either libraries or an executable.&lt;/p&gt;

&lt;p&gt;All the places you see &lt;code&gt;$^&lt;/code&gt; is Makefile magic to reference everything in the dependency&lt;br&gt;
list (which are all the files in &lt;code&gt;OBJECTS&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="c"&gt;# Build the source files.
# Conditional change to building for an executable or libraries.
# We also create the output BIN directory if it doesn't exist.
# This job depends on the OBJECT files.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;src&lt;/span&gt;
&lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;$(OBJECTS)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;($(SHARED), 1)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;TARGET&lt;span class="p"&gt;)&lt;/span&gt;.so &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LIBS&lt;span class="p"&gt;)&lt;/span&gt;
    ar &lt;span class="nt"&gt;-rcs&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;TARGET&lt;span class="p"&gt;)&lt;/span&gt;.a &lt;span class="nv"&gt;$^&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;LIBS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$^&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="p"&gt;$(&lt;/span&gt;TARGET&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Object Files Job
&lt;/h4&gt;

&lt;p&gt;The object files job looks a little weird at first but the job name is a wildcard.&lt;br&gt;
It matches anything with the signature &lt;code&gt;$(OBJ)/%.o&lt;/code&gt; which is what all of our files&lt;br&gt;
listed in the &lt;code&gt;OBJECTS&lt;/code&gt; variable match.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;%.c&lt;/code&gt; dependency is some Makefile magic to find the source file with the same path&lt;br&gt;
except the &lt;code&gt;$(OBJ)/&lt;/code&gt; part.&lt;/p&gt;

&lt;p&gt;There are 2 other Makefile magic symbols that need some explaining in here.&lt;br&gt;
First is the &lt;code&gt;$@&lt;/code&gt; symbol to reference the left side of the job signature&lt;br&gt;
(the &lt;code&gt;$(OBJ)/%.o&lt;/code&gt; side).&lt;br&gt;
Second is the &lt;code&gt;$&amp;lt;&lt;/code&gt; symbol to reference the first item in the dependency side of the&lt;br&gt;
job signature (the &lt;code&gt;%.c&lt;/code&gt; side).&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;# Compile all source files to object files
# This job executes because the `src` job depends on all the files in OBJECTS
# which has the `$(OBJ)/%.o` file signature.
&lt;/span&gt;&lt;span class="nl"&gt;$(OBJ)/%.o&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;%.c&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;CC&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt; &lt;span class="nv"&gt;$&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;CFLAGS&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;INCLUDES&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Clean Jobs
&lt;/h4&gt;

&lt;p&gt;The next section are all the jobs related to clean up.&lt;/p&gt;

&lt;p&gt;The first job is to clean our project. You'll notice we pipe the errors to&lt;br&gt;
&lt;code&gt;/dev/null&lt;/code&gt; this is because we get errors if the folders are empty when cleaning.&lt;/p&gt;

&lt;p&gt;The second job is to run &lt;code&gt;make clean&lt;/code&gt; on all of the dependencies. We need to call&lt;br&gt;
make as &lt;code&gt;$(MAKE)&lt;/code&gt; for it to execute properly.&lt;/p&gt;

&lt;p&gt;The last job is to do both of the cleanup jobs together.&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;# Job to clean out all object files and exe/libs.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clean&lt;/span&gt;
&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;OBJ&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt; 2&amp;gt; /dev/null
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;BIN&lt;span class="p"&gt;)&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt; 2&amp;gt; /dev/null

&lt;span class="c"&gt;# Job to run `make clean` on all dependencies.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clean_deps&lt;/span&gt;
&lt;span class="nl"&gt;clean_deps&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;foreach &lt;span class="nb"&gt;dir&lt;/span&gt;, &lt;span class="p"&gt;$(&lt;/span&gt;DEPS&lt;span class="p"&gt;)&lt;/span&gt;, &lt;span class="p"&gt;$(&lt;/span&gt;shell &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;MAKE&lt;span class="p"&gt;)&lt;/span&gt; clean&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c"&gt;# Job to clean dependencies and our files.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clean_all&lt;/span&gt;
&lt;span class="nl"&gt;clean_all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clean clean_deps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Dependency Job
&lt;/h4&gt;

&lt;p&gt;The last job in the Makefile is to compile our third party dependencies.&lt;br&gt;
This command iterates over the Makefiles we captured in the &lt;code&gt;DEPS&lt;/code&gt; variable&lt;br&gt;
and runs &lt;code&gt;make&lt;/code&gt;. This assumes the third party dependencies have a default job setup&lt;br&gt;
and it's the one you want to run.&lt;/p&gt;

&lt;p&gt;This section may need to change depending on your projects needs.&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;# Job to run `make` on all of our dependencies.
# This only works if the dependencies' Makefile is at the top and implements a
# default job.
&lt;/span&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;deps&lt;/span&gt;
&lt;span class="nl"&gt;deps&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;foreach &lt;span class="nb"&gt;dir&lt;/span&gt;, &lt;span class="p"&gt;$(&lt;/span&gt;DEPS&lt;span class="p"&gt;)&lt;/span&gt;, &lt;span class="p"&gt;$(&lt;/span&gt;shell &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;MAKE&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully this Makefile helps you, if not fully, maybe it at least gets you started&lt;br&gt;
in having something that can cover the uses you need.&lt;/p&gt;

</description>
      <category>makefile</category>
      <category>c</category>
      <category>linux</category>
      <category>development</category>
    </item>
    <item>
      <title>Unique Shared Library Problem</title>
      <dc:creator>Joshua Matthews</dc:creator>
      <pubDate>Tue, 28 Jan 2025 05:35:11 +0000</pubDate>
      <link>https://dev.to/jmatth11/unique-shared-library-problem-46ad</link>
      <guid>https://dev.to/jmatth11/unique-shared-library-problem-46ad</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I was trying to work with a library the other day that I built from source, however, I could not get it to work with my local C project. I was getting &lt;code&gt;undefined reference&lt;/code&gt; errors when linking to the shared library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/bin/ld: /tmp/ccHb7mJ8.o: in function `SDL_main':
main.c:(.text+0x3c): undefined reference to `SDL_EnterAppMainCallbacks'
/bin/ld: /tmp/ccHb7mJ8.o: in function `main':
main.c:(.text+0x6b): undefined reference to `SDL_RunApp'
/bin/ld: /tmp/ccHb7mJ8.o: in function `SDL_AppInit':
main.c:(.text+0xa7): undefined reference to `SDL_SetAppMetadata'
/bin/ld: main.c:(.text+0xb1): undefined reference to `SDL_Init'
/bin/ld: main.c:(.text+0xbd): undefined reference to `SDL_GetError'
/bin/ld: main.c:(.text+0xd4): undefined reference to `SDL_Log'
/bin/ld: main.c:(.text+0x107): undefined reference to `SDL_CreateWindowAndRenderer'
/bin/ld: main.c:(.text+0x113): undefined reference to `SDL_GetError'
/bin/ld: main.c:(.text+0x12a): undefined reference to `SDL_Log'
collect2: error: ld returned 1 exit status
make: *** [Makefile:7: all] Error 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Investigation
&lt;/h2&gt;

&lt;p&gt;I recompiled the library several times trying different methods and nothing helped. After searching google for a couple of hours I came across a forum where someone was having a similar issue but they were using a 32bit version of their toolchain instead of a 64bit. I figured this wasn't the issue but I investigated anyways. Everything I checked showed it was 64bit, so I was back to square one. Though after thinking about toolchains I did think maybe I could try a different compiler. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution?
&lt;/h2&gt;

&lt;p&gt;I was using &lt;code&gt;gcc&lt;/code&gt; at the time so I switched to &lt;code&gt;clang&lt;/code&gt; and reran my Makefile. &lt;/p&gt;

&lt;p&gt;To my surprise, everything worked! I was shocked. &lt;/p&gt;

&lt;p&gt;It couldn't be that simple? Why has this never been a problem before? &lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Solution
&lt;/h2&gt;

&lt;p&gt;So I decided to create a control project to test this phenomenon. I setup a small &lt;code&gt;add&lt;/code&gt; shared library built with &lt;code&gt;clang&lt;/code&gt; and then tried to compile a driver program with &lt;code&gt;gcc&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;lib.h&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#pragma once
&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;lib.c&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"lib.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&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;&lt;code&gt;main.c&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"lib.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="kt"&gt;int&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="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"4+3=%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&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;&lt;code&gt;build_so.sh&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clang &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c11 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; lib.o lib.c
clang &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; libm.so lib.o
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;build_main.sh&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c11 &lt;span class="nt"&gt;-L&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;:libm.so main.c &lt;span class="nt"&gt;-o&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It failed, just like in my C project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/bin/ld: /tmp/ccymm8ki.o: in function `main':
main.c:(.text+0x13): undefined reference to `add'
collect2: error: ld returned 1 exit status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changing the &lt;code&gt;build.sh&lt;/code&gt; to use &lt;code&gt;clang&lt;/code&gt; obviously fixes the problem but I wanted to know if this problem happens the other way round, so I tried to switch the compiler positions, to see if it would fail the other way. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;build_so.sh&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c11 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; lib.o lib.c
gcc &lt;span class="nt"&gt;-shared&lt;/span&gt; &lt;span class="nt"&gt;-fPIC&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; libm.so lib.o
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;build_main.sh&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clang &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c11 &lt;span class="nt"&gt;-L&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;:libm.so main.c &lt;span class="nt"&gt;-o&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time and everything worked. So this might be why I had never encountered this before. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;clang&lt;/code&gt; shared libraries have problems being used with &lt;code&gt;gcc&lt;/code&gt; for some reason, but &lt;code&gt;gcc&lt;/code&gt; shared libraries can be used with &lt;code&gt;clang&lt;/code&gt; no problem. &lt;/p&gt;

&lt;p&gt;If there is a way around this problem, I would love to know!&lt;/p&gt;

&lt;p&gt;I think in most cases you probably will use the same compiler for your projects but in my case where the project I was compiling from source decided to use &lt;code&gt;clang&lt;/code&gt; instead of &lt;code&gt;gcc&lt;/code&gt; to create this unique shared library problem I had not encountered before.&lt;/p&gt;

</description>
      <category>c</category>
      <category>sharedlibrary</category>
      <category>gcc</category>
      <category>clang</category>
    </item>
    <item>
      <title>Implementing I2C for the ATtiny85</title>
      <dc:creator>Joshua Matthews</dc:creator>
      <pubDate>Sun, 24 Nov 2024 06:05:38 +0000</pubDate>
      <link>https://dev.to/jmatth11/implementing-i2c-for-the-attiny85-48em</link>
      <guid>https://dev.to/jmatth11/implementing-i2c-for-the-attiny85-48em</guid>
      <description>&lt;p&gt;tl;dr&lt;/p&gt;

&lt;p&gt;Implemented the I2C protocol for controller devices on an ATtiny85 using just the AVR base library. Link to &lt;a href="https://github.com/jmatth11/i2c-avr-driver" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Precursor&lt;/li&gt;
&lt;li&gt;
Understanding the Protocol

&lt;ul&gt;
&lt;li&gt;High Level&lt;/li&gt;
&lt;li&gt;The Format&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

The Research

&lt;ul&gt;
&lt;li&gt;Pinouts&lt;/li&gt;
&lt;li&gt;Port Registers&lt;/li&gt;
&lt;li&gt;Universal Serial Interface&lt;/li&gt;
&lt;li&gt;Speed Support&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

The Implementation

&lt;ul&gt;
&lt;li&gt;Header File&lt;/li&gt;
&lt;li&gt;
Source File

&lt;ul&gt;
&lt;li&gt;Initialize&lt;/li&gt;
&lt;li&gt;Start&lt;/li&gt;
&lt;li&gt;Stop&lt;/li&gt;
&lt;li&gt;Transfer&lt;/li&gt;
&lt;li&gt;Write&lt;/li&gt;
&lt;li&gt;Read&lt;/li&gt;
&lt;li&gt;Write Target Address&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Conclusion and Demo&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Precursor
&lt;/h2&gt;

&lt;p&gt;I've done some Arduino projects &lt;a href="https://github.com/jmatth11/gardenometer" rel="noopener noreferrer"&gt;before&lt;/a&gt; but it was with using the Arduino IDE and their helper libraries. &lt;br&gt;
So I wanted to try my hand at programming something at the base level -- No Arduino IDE or helper libraries. &lt;/p&gt;

&lt;p&gt;I decided the I2C protocol would be a big enough project to get my feet wet with AVR programming but small enough to not feel overwhelmed. It would also be easy to debug with a target device (I used an Arduino Uno) to ensure everything was working appropriately.&lt;/p&gt;
&lt;h2&gt;
  
  
  Understanding the Protocol
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Reference: Historically the terms Master/Slave were used to refer to the relationship of these devices, but modern naming conventions use Controller/Target&lt;/em&gt; &lt;sup&gt;&lt;a href="https://en.wikipedia.org/wiki/I%C2%B2C#:~:text=multi%2Dcontroller/multi%2Dtarget%20(historically%20termed%20as%20multi%2Dmaster/multi%2Dslave)" rel="noopener noreferrer"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  High Level
&lt;/h3&gt;

&lt;p&gt;Inter-Integrated Circuit (or I2C) is a widely supported, simple synchronous method of communication between lower-speed peripherals. The setup usually involves a Controller with one or more Target devices talking across two bidirectional signal lines: Serial Data Line (SDA) and Serial Clock Line (SCL). &lt;sup&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The basic concept of these two lines is SDA is for data and SCL is for keeping the timing correct between the two devices. There are several speeds that are supported but the standard speed is 100kbit/s.&lt;sup&gt;1&lt;/sup&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Format
&lt;/h2&gt;

&lt;p&gt;The format for communication is pretty simple and I feel the easiest way to understand it is with this diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsalxj4cc3yx68uiemosw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsalxj4cc3yx68uiemosw.jpg" alt="I2C Diagram - (Sparkfun, 2013)" width="800" height="178"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://learn.sparkfun.com/tutorials/i2c/all" rel="noopener noreferrer"&gt;I2C Diagram - (Sparkfun, 2013)&lt;/a&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first thing to notice is both SDA and SCL are set to high at the beginning. SDA is then brought to the low state and after a short wait the SCL line is brought low as well. This will wake every target device on the line to check if they will be the one the controller is talking to.&lt;/p&gt;

&lt;p&gt;Next the controller sends the 7 bit address of the target device. We use a 7 bit address because the least significant bit is reserved as the Read/Write flag to tell the target device which mode it should be in (1 is Read, 0 is Write). Through this data exchange you'll notice the SCL line is toggled in the middle of the SDA line's state. This is important to not trigger the stop state (we'll talk about this soon).&lt;/p&gt;

&lt;p&gt;At this point the target devices that do not match the address go back to ignoring the messages. Then the controller changes its SDA line to input and the target device that matches the address sends an N/ACK to ACKnowledge or Not ACKnowledge that data transfer. &lt;/p&gt;

&lt;p&gt;Now the controller and target are connected and depending on the Read/Write flag the controller/target will execute accordingly until done. In the case of a Write, the controller sends data in 8 byte intervals until done or until the target returns a NACK. In the case of a Read, the controller reads data and sends back an ACK to the target until the controller is done, at that point the controller sends a NACK followed by a stop message.&lt;/p&gt;

&lt;p&gt;Last is the stop message, which is basically the opposite of the start message. Both SDA and SCL lines are forced to the low state. Then the SCL is brought high and after a short wait, the SDA line is brought high.&lt;/p&gt;

&lt;p&gt;That's the basics of the protocol, there are some extended rules for &lt;a href="https://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-i2c-slave-addressing/" rel="noopener noreferrer"&gt;8 or 10-bit addressing&lt;/a&gt;&lt;sup&gt;4&lt;/sup&gt; and some special cases like &lt;a href="https://learn.sparkfun.com/tutorials/i2c/all#:~:text=Repeated%20Start%20Conditions" rel="noopener noreferrer"&gt;repeat starts&lt;/a&gt;&lt;sup&gt;3&lt;/sup&gt; but we aren't really concerned with those for our purposes.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Research
&lt;/h2&gt;

&lt;p&gt;The research portion of this project took the longest. I knew I'd have to comb through the data sheet of the ATtiny85 to figure out most things, but still being quite new to bare-metal programming I found myself lost a few times searching through it.&lt;br&gt;
Using a combo of reference material from the &lt;a href="https://github.com/lucullusTheOnly/TinyWire" rel="noopener noreferrer"&gt;TinyWire&lt;/a&gt;&lt;sup&gt;5&lt;/sup&gt; library and the datasheet helped guide me through most of the troubles I encountered.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pinouts
&lt;/h3&gt;

&lt;p&gt;The first thing I needed to do was look at the pinout diagram to figure out what pins supported I2C on the ATtiny85. Looking through the &lt;a href="https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf" rel="noopener noreferrer"&gt;datasheet&lt;/a&gt;&lt;sup&gt;6&lt;/sup&gt; they have this handy diagram that explains all the pins.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpotqujfqnlxv3dqq2n5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpotqujfqnlxv3dqq2n5.png" alt="Pinout ATtiny25/45/85 - (Atmel, 2013 - Figure 1-1 pg. 2)" width="477" height="171"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf" rel="noopener noreferrer"&gt;Pinout ATtiny25/45/85 - (Atmel, 2013 - Figure 1-1 pg. 2)&lt;/a&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can see that PB0 and PB2 are our SDA and SCL pins respectively. So we will start here by searching how to configure these pins for I2C serial communication.&lt;/p&gt;
&lt;h3&gt;
  
  
  Port Registers
&lt;/h3&gt;

&lt;p&gt;Searching through the document we find chapter 10 on I/O Ports and within this chapter has this diagram for pin configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdsz9wpkvzyecuicmuoz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdsz9wpkvzyecuicmuoz.png" alt="Port Pin Configurations - (Atmel, 2013 - Table 10-1 pg. 55)" width="502" height="175"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf" rel="noopener noreferrer"&gt;Port Pin Configurations - (Atmel, 2013 - Table 10-1 pg. 55)&lt;/a&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Knowing that we need to use pullup resistors for our SDA and SCL lines we are interested in row two. This shows to setup pullup resistors we need to have the configuration (0, 1, 0) for our DDxn, PORTxn, PUD flag respectively.&lt;br&gt;
It is important to note that we are just using the internal pullup resistors for our use case, but depending on your device or the number of devices, you will need to use external pullups to ensure consistent results.&lt;/p&gt;

&lt;p&gt;Next we find these registers, which are defined in these tables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftozbvikn2armzsvp88je.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftozbvikn2armzsvp88je.png" alt="Register Descriptions - (Atmel, 2013 - Section 10.4 pg. 64)" width="626" height="454"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf" rel="noopener noreferrer"&gt;Register Descriptions - (Atmel, 2013 - Section 10.4 pg. 64)&lt;/a&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We see that the PUD flag and all of DDRB has initial values set to zero, so we really only need to worry about setting PORTB0 and PORTB2 to 1. If you are writing a drop in library you might want to be safe and write the other bits to zero to ensure correct behavior.&lt;/p&gt;
&lt;h3&gt;
  
  
  Universal Serial Interface
&lt;/h3&gt;

&lt;p&gt;Now that we've figured out the Port registers we need to figure out how serial communication works on the ATtiny85. Chapter 15 covers USI - Universal Serial Interface. This chapter has a lot to read through, but we can pull out the highlights.&lt;/p&gt;

&lt;p&gt;The first thing from this chapter, in the overview, we learn that this chip has hardware level helpers to aid in serial communication which will allow less overhead than a pure software implementation. This also allows us to take advantage of the hardware controls to allow for less code on our end. Things included are: Pullups, Interrupts for flags and overflows, control flags to toggle the clock, and a data register for sending and receiving.&lt;/p&gt;

&lt;p&gt;Further in the chapter we find the registers we will be using for communication. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;USIDR&lt;/code&gt; USI Data Register - For reading and sending data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;USISR&lt;/code&gt; USI Status Register - For checking and managing state with interrupt flags and timers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;USICR&lt;/code&gt; USI Control Register - For controlling and enabling different modes and timers
I listed these because it was a little difficult to get as a screenshot. But we'll look at them in detail later.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Speed Support
&lt;/h3&gt;

&lt;p&gt;The last bit of research I needed to find was how to implement and support the different speeds available for I2C. Judging from &lt;a href="https://ww1.microchip.com/downloads/en/Appnotes/Atmel-2561-Using-the-USI-Module-as-a-I2C-Master_AP-Note_AVR310.pdf" rel="noopener noreferrer"&gt;this document&lt;/a&gt;&lt;sup&gt;7&lt;/sup&gt;, the AVR controllers support standard (100kbps) and Fast mode (400kbps). So what do we need to do to maintain this bit rate?&lt;/p&gt;

&lt;p&gt;Looking back at the &lt;a href="https://github.com/lucullusTheOnly/TinyWire" rel="noopener noreferrer"&gt;TinyWire&lt;/a&gt;&lt;sup&gt;5&lt;/sup&gt; they seem to have these hardcoded values for timing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv95umq8z1tlv9tnqbsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv95umq8z1tlv9tnqbsc.png" alt="TWI Delay Constants - (TinyWire, 2019 - twi.h)" width="295" height="69"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/lucullusTheOnly/TinyWire/blob/5b93024f41aaab36e6bd5216350d2764090418c2/twi.h#L84" rel="noopener noreferrer"&gt;TWI Delay Constants - (TinyWire, 2019 - twi.h)&lt;/a&gt;&lt;sup&gt;5&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;But where did they get these values? It took me a while to track down but these values are from the &lt;a href="https://www.nxp.com/docs/en/user-guide/UM10204.pdf" rel="noopener noreferrer"&gt;NPX I2C Timing Specification&lt;/a&gt;&lt;sup&gt;8&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1dawsf5n44ybbk6vfzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1dawsf5n44ybbk6vfzd.png" alt="Characteristics of the SDA and SCL bus - (NXP I2C Timing Specification, 2021 - Table 11, pg. 44)" width="678" height="640"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.nxp.com/docs/en/user-guide/UM10204.pdf" rel="noopener noreferrer"&gt;Characteristics of the SDA and SCL bus - (NXP I2C Timing Specification, 2021 - Table 11, pg. 44)&lt;/a&gt;&lt;sup&gt;8&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The rows we care about are the &lt;code&gt;t_LOW&lt;/code&gt; and &lt;code&gt;t_HIGH&lt;/code&gt; rows. From this we can see to meet the Standard and Fast requirements we will need delays of (4.7 and 4.0) and (1.6 and 0.6) respectively.&lt;/p&gt;

&lt;p&gt;Now that we have most of our reference material we can start our implementation.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Implementation
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Header File
&lt;/h3&gt;

&lt;p&gt;First we will define out our header file to lay out our constants and functions.&lt;/p&gt;

&lt;p&gt;First we define the wait periods for the different bit rate speeds we can support.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// These numbers are from a calculation chart&lt;/span&gt;
&lt;span class="c1"&gt;// from I2C spec -- NXP I2C Timing Specification&lt;/span&gt;
&lt;span class="cp"&gt;#ifdef I2C_FAST_MODE // 400kHz fast
&lt;/span&gt;  &lt;span class="c1"&gt;// low period of SCL&lt;/span&gt;
  &lt;span class="cp"&gt;#define T2_TWI 2 // &amp;gt;1.3microseconds
&lt;/span&gt;  &lt;span class="c1"&gt;// high period of SCL&lt;/span&gt;
  &lt;span class="cp"&gt;#define T4_TWI 1 // &amp;gt;0.6microseconds
#else // 100kHz standard
&lt;/span&gt;  &lt;span class="c1"&gt;// low period of SCL&lt;/span&gt;
  &lt;span class="cp"&gt;#define T2_TWI 5 // &amp;gt;4.7microseconds
&lt;/span&gt;  &lt;span class="c1"&gt;// high period of SCL&lt;/span&gt;
  &lt;span class="cp"&gt;#define T4_TWI 4 // &amp;gt;4.0microseconds
#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, these numbers are defined in &lt;a href="https://www.nxp.com/docs/en/user-guide/UM10204.pdf" rel="noopener noreferrer"&gt;this document on page 44&lt;/a&gt;&lt;sup&gt;8&lt;/sup&gt;. You can see we didn't use the numbers exactly. From the &lt;a href="https://github.com/lucullusTheOnly/TinyWire" rel="noopener noreferrer"&gt;references&lt;/a&gt;&lt;sup&gt;5&lt;/sup&gt; I used, it seemed common to round up to the next whole number. This is the reasoning for the choice 2 over 1.3, as an example. &lt;br&gt;
I'm not completely sure for the reasoning behind this other than maybe it's safer to use whole numbers with the delay functions than the fractional values when making sure you are staying within the cut off point of the range.&lt;/p&gt;

&lt;p&gt;Next we define out the constants for the registers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#ifndef i2c_ddr
&lt;/span&gt;  &lt;span class="cp"&gt;#define i2c_ddr DDRB
#endif
#ifndef i2c_port
&lt;/span&gt;  &lt;span class="cp"&gt;#define i2c_port PORTB
#endif
#ifndef i2c_pin
&lt;/span&gt;  &lt;span class="cp"&gt;#define i2c_pin PINB
#endif
#ifndef i2c_scl
&lt;/span&gt;  &lt;span class="cp"&gt;#define i2c_scl PORTB2
#endif
#ifndef i2c_sda
&lt;/span&gt;  &lt;span class="cp"&gt;#define i2c_sda PORTB0
#endif
#ifndef i2c_data
&lt;/span&gt;  &lt;span class="cp"&gt;#define i2c_data USIDR
#endif
#ifndef i2c_status
&lt;/span&gt;  &lt;span class="cp"&gt;#define i2c_status USISR
#endif
#ifndef i2c_control
&lt;/span&gt;  &lt;span class="cp"&gt;#define i2c_control USICR
#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step isn't really necessary but I felt these names were a bit better at conveying what they are for.&lt;/p&gt;

&lt;p&gt;The last thing for the header are the functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Initialize I2C registers and ports.
 */&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;i2c_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Send start command.
 * @return True if the start successfully initiated, False otherwise.
 */&lt;/span&gt;
&lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;i2c_start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Send the stop command.
 */&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;i2c_stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Write the given byte.
 * @param[in] data The byte to send.
 * @return The N/ACK byte.
 */&lt;/span&gt;
&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="nf"&gt;i2c_write_byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Read the next byte.
 * @param[in] nack True for reading more, false otherwise.
 * @return The read byte.
 */&lt;/span&gt;
&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="nf"&gt;i2c_read_byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;nack&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Write the target's address out.
 *
 * @param[in] address The target address.
 * @param[in] write Flag for Write or Read bit.
 * @return The N/ACK byte.
 */&lt;/span&gt;
&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="nf"&gt;i2c_write_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should be the basics of the protocol with these functions. We will go into more detail in this next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source File
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Initialize
&lt;/h4&gt;

&lt;p&gt;First we will write out our initialization code. We need to set defaults and configure our registers properly.&lt;/p&gt;

&lt;p&gt;I'll show the function first and then break it down.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;i2c_init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// preload data register with default HIGH&lt;/span&gt;
  &lt;span class="n"&gt;i2c_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// setup for master&lt;/span&gt;
  &lt;span class="n"&gt;i2c_control&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// disable Start condition interrupt&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;USISIE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;// disable overflow interrupt&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;USIOIE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;// only set WM1 to high for normal 2wire mode&lt;/span&gt;
    &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIWM1&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;USIWM0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;// set CS1 and CLK to high to use external clock source&lt;/span&gt;
    &lt;span class="c1"&gt;// with positive edge. Software Clock Strobe (with USITC register)&lt;/span&gt;
    &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USICS1&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;USICS0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USICLK&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;USITC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;i2c_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// clear all flags&lt;/span&gt;
    &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USISIF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIOIF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIPF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIDC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;// reset overflow counter&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;USICNT0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// flip the ports to input mode so we can enable pullup resistors on the next line&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// set both pins to HIGH to enable pullup.&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="c1"&gt;// flip the ports to output mode&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&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;The first thing we do for house keeping is setting the data register to a default value of HIGH (&lt;code&gt;0xFF&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;i2c_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we configure the Control register, this will tell the controller how we want to interact with the Universal Serial Interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// setup for master&lt;/span&gt;
  &lt;span class="n"&gt;i2c_control&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// disable Start condition interrupt&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;USISIE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;// disable overflow interrupt&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;USIOIE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;// only set WM1 to high for normal 2wire mode&lt;/span&gt;
    &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIWM1&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;USIWM0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;// set CS1 and CLK to high to use external clock source&lt;/span&gt;
    &lt;span class="c1"&gt;// with positive edge. Software Clock Strobe (with USITC register)&lt;/span&gt;
    &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USICS1&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;USICS0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USICLK&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;USITC&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;The comments explain a lot of what we are doing here but I will link to the datasheet where these values are explained.&lt;/p&gt;

&lt;p&gt;On pages 116-117 of the &lt;a href="https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf" rel="noopener noreferrer"&gt;Atmel datasheet&lt;/a&gt;&lt;sup&gt;6&lt;/sup&gt; the control register is explained. The first two bits are just interrupt enable flags and since we are the controller we don't need these enabled.&lt;/p&gt;

&lt;p&gt;Next is setting the wire mode. Since the Universal Serial Interface can support multiple modes, we need to configure which one we are using. The configuration table shows us which values to set for two-wire mode (I2C).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6p2kjxn2ozg1243kouzq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6p2kjxn2ozg1243kouzq.png" alt="Wire Mode - (Atmel, 2013 - Table 15-1, pg. 117)" width="588" height="449"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf" rel="noopener noreferrer"&gt;Wire Mode - (Atmel, 2013 - Table 15-1, pg. 117)&lt;/a&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The next three bits are related to how we want to interact with the clock. We've configured the clock source to be an External, positive edge, and we want to use a software clock strobe.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxggvd9cvtouky551jjge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxggvd9cvtouky551jjge.png" alt="Clock Settings - (Atmel, 2013 - Table 15-2, pg. 118)" width="576" height="213"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf" rel="noopener noreferrer"&gt;Clock Settings - (Atmel, 2013 - Table 15-2, pg. 118)&lt;/a&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The jest of the clock source is we need to tell how the clock is sourced and how the data output latch changes with respect to the sampling of the data input. The 4-bit counter clock source is just to define how the clock is being controlled. Since we are the controller we want to strobe it ourselves.&lt;/p&gt;

&lt;p&gt;The last bit is turned off and this is the bit for toggling the clock. To toggle the clock you need to write a 1 to it.&lt;/p&gt;

&lt;p&gt;Next we initialize our status register to default values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;i2c_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// clear all flags&lt;/span&gt;
    &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USISIF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIOIF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIPF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIDC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="c1"&gt;// reset overflow counter&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;USICNT0&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;The first four bits are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start Condition Interrupt Flag&lt;/li&gt;
&lt;li&gt;Counter Overflow Interrupt Flag&lt;/li&gt;
&lt;li&gt;Stop Condition Flag&lt;/li&gt;
&lt;li&gt;Data Output Collision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writing a logical one to these bits clears them out if they were set. &lt;br&gt;
The remaining 4 bits in this register are the 4-bit counter value used for the SCL line. 4 bits allows for 16 values, which translates to 8 byte transactions, which is the size of our payload. So when this overflows we've sent one payload's worth. So we need to reset it to zero.&lt;/p&gt;

&lt;p&gt;The last portion of the initialization function is to enable the on-board pullups of the ATtiny85.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// flip the ports to input mode so we can enable pullup resistors on the next line&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// set both pins to HIGH to enable pullup.&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="c1"&gt;// flip the ports to output mode&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The datasheet explains that setting the DDRB in the off position while setting the associated port bits in the on position enables the pullups. We then finish by setting the DDRB bits for SDA and SCL to output mode. The settings and caveats of the registers and pullup resistors are talked about in Port registers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Start
&lt;/h4&gt;

&lt;p&gt;Next, the start condition. Most of this code should be understood from the Understanding the Protocol section. But there are a couple of bits that might need some explaining.&lt;/p&gt;

&lt;p&gt;Here is the code for the start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;i2c_start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ensure both lines are high&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="c1"&gt;// wait till clock pin is high&lt;/span&gt;
  &lt;span class="k"&gt;while&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="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
  &lt;span class="n"&gt;_delay_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T2_TWI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// pull data line low&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// this is sampling time for the attiny85 to recognize the start command&lt;/span&gt;
  &lt;span class="n"&gt;_delay_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SAMPLING_WAIT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// pull clock line low&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// release data line to high&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// check for valid start&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_status&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USISIF&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;We start off like normal, bringing both lines high. Then we need to wait for the SCL line to be high so we continually check to see if the pin value is set. Once it is, we wait a defined number of microseconds stated in the chart referenced in the Speed Support section. &lt;/p&gt;

&lt;p&gt;Next we bring the data line low and then wait a &lt;em&gt;sampling&lt;/em&gt; amount of time. This time frame is defined in both the &lt;a href="https://www.nxp.com/docs/en/user-guide/UM10204.pdf" rel="noopener noreferrer"&gt;NXP I2C Timing Specification&lt;/a&gt;&lt;sup&gt;8&lt;/sup&gt; on Table 11, page 44 and the &lt;a href="https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf" rel="noopener noreferrer"&gt;Atmel datasheet&lt;/a&gt;&lt;sup&gt;6&lt;/sup&gt; in section 15.3.5 on page 113. Both define it as a max of 300 nanoseconds with the Atmel datasheet defining the minimum as 50 nanoseconds.&lt;br&gt;
So I've defined the sample wait constant as so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// this is 0.2 microseconds which is 200 nanoseconds&lt;/span&gt;
&lt;span class="cp"&gt;#define SAMPLING_WAIT 0.2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, bring the clock line low and then release the data line to finish up. The last thing I've added is a validity check. If the &lt;code&gt;USISIF&lt;/code&gt; bit is set then the start condition was recognized, if not something went wrong.&lt;/p&gt;

&lt;h4&gt;
  
  
  Stop
&lt;/h4&gt;

&lt;p&gt;The stop condition is about the same except you don't have to worry about a sampling time with this one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;i2c_stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// ensure data line is low&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// relase clock line to high&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// wait for clock pin to read high&lt;/span&gt;
  &lt;span class="k"&gt;while&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="n"&gt;i2c_pin&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
  &lt;span class="n"&gt;_delay_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T4_TWI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// relase data line to high&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;_delay_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T2_TWI&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 pretty much follows the spec and uses the delays in accordance with the table specified in Speed Support. Bringing both lines low and then releasing the clock line. After it reaches the on state, release the data line.&lt;/p&gt;

&lt;h4&gt;
  
  
  Transfer
&lt;/h4&gt;

&lt;p&gt;Next we will handle the general transferring of data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ensure clock line is low&lt;/span&gt;
  &lt;span class="n"&gt;i2c_port&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;i2c_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// wait a little bit&lt;/span&gt;
    &lt;span class="n"&gt;_delay_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T2_TWI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// toggle clock&lt;/span&gt;
    &lt;span class="n"&gt;i2c_control&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USITC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// wait for SCL to go high&lt;/span&gt;
    &lt;span class="k"&gt;while&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="n"&gt;i2c_pin&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_scl&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="c1"&gt;// wait short&lt;/span&gt;
    &lt;span class="n"&gt;_delay_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T4_TWI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// toggle clock again&lt;/span&gt;
    &lt;span class="n"&gt;i2c_control&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USITC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&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="n"&gt;i2c_status&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIOIF&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
  &lt;span class="n"&gt;_delay_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T2_TWI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// clear counter overflow status&lt;/span&gt;
  &lt;span class="n"&gt;i2c_status&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USIOIF&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i2c_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;i2c_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&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;The first line is probably not necessary but we just want to ensure the clock is low before beginning. The next line is setting the status to the mask parameter. (we will touch on this in the write/read functions).&lt;/p&gt;

&lt;p&gt;Next we start our loop. The ATtiny85 will handle sending the data as we toggle the clock. So we wait the specified time between the HIGH and LOW of the clock line referenced in the table in the Speed Support section and toggle the clock on the control register by setting the &lt;code&gt;USITC&lt;/code&gt; bit flag.&lt;/p&gt;

&lt;p&gt;Once we receive the counter overflow condition we exit the loop, wait a little more and then clear out that overflow status flag. We then grab the data from the data register, reset the data register, and then return our received byte value.&lt;/p&gt;

&lt;h4&gt;
  
  
  Write
&lt;/h4&gt;

&lt;p&gt;With most of the scaffolding setup now the next few functions will be pretty easy to flesh out.&lt;/p&gt;

&lt;p&gt;Starting with the write function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="nf"&gt;i2c_write_byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;i2c_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STATUS_CLOCK_8_BITS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// change data pin to input&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;nack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STATUS_CLOCK_1_BIT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// change back to output&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;nack&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;Stepping through this function we see we are setting the data register to the data we would like to send over. Then we call the transfer function with this new &lt;code&gt;STATUS_CLOCK_8_BITS&lt;/code&gt; constant. This constant is to reset the status register to be ready for a full 8 bits transfer.&lt;/p&gt;

&lt;p&gt;It is defined as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define STATUS_CLOCK_8_BITS (_BV(USISIF)|_BV(USIOIF)|_BV(USIPF)|_BV(USIDC) | \
    (0x0 &amp;lt;&amp;lt; USICNT0)) // reset clock to allow for full 8 bit transfer
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We clear the status flags and reset the counter to 0.&lt;/p&gt;

&lt;p&gt;After sending our data we need to flip our pin to input mode to read the ACK bit from the target. We then call the transfer method with another constant which sets up the status register to clear status flags and set the counter to a value that will force an overflow after 1 bit transfer.&lt;/p&gt;

&lt;p&gt;It is defined as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define STATUS_CLOCK_1_BIT (_BV(USISIF) | \
   _BV(USIOIF) | \
   _BV(USIPF) | \
   _BV(USIDC) | \
   (0xE &amp;lt;&amp;lt; USICNT0))// we set the clock to 1110 so it overflows after 1 exchange
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the N/ACK is returned we set the SDA line back to output and return the received byte.&lt;/p&gt;

&lt;h4&gt;
  
  
  Read
&lt;/h4&gt;

&lt;p&gt;The read function has slightly more logic, because we need to tell the target if we would like to read more or to stop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="nf"&gt;i2c_read_byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;ack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// HIGH value means stop sending&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// LOW means read another byte&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// change data pin to input&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STATUS_CLOCK_8_BITS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// change back to output&lt;/span&gt;
  &lt;span class="n"&gt;i2c_ddr&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="n"&gt;_BV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i2c_sda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// send n/ack&lt;/span&gt;
  &lt;span class="n"&gt;i2c_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STATUS_CLOCK_1_BIT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&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;We change our response value based on if we want to read another byte or not. This is determined by the ACK (&lt;code&gt;0x00&lt;/code&gt;) or NACK (&lt;code&gt;0xFF&lt;/code&gt;) value.&lt;/p&gt;

&lt;p&gt;Next we operate similarly like the write function except we capture the data first and then send our N/ACK response.&lt;/p&gt;

&lt;h4&gt;
  
  
  Write Target Address
&lt;/h4&gt;

&lt;p&gt;We basically have everything we need to perform I2C now but I wanted a helper function to handle sending the target address properly for me. So we have this last method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="nf"&gt;i2c_write_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;rw_flag&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;rw_flag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// shift address over 1 because Least sig bit is RW flag&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;i2c_write_byte&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;rw_flag&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;In our case we are only dealing with the basic 7-bit addressing so we shift the address over by 1 bit and then logically or it with the &lt;code&gt;rw_flag&lt;/code&gt; bit. This format is explained in The Format section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and Demo
&lt;/h2&gt;

&lt;p&gt;After all that, we can now properly handle I2C on our ATtiny85. This project has helped me explore the embedded space more than I had experience with before. It's given me a new appreciation for the craft that goes into these projects and has me excited to tackle the next embedded journey I dig into.&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="https://github.com/jmatth11/i2c-avr-driver" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;sup&gt;9&lt;/sup&gt; and the demo video of the finished project.&lt;/p&gt;

&lt;p&gt;The demo has an ATtiny85 loaded with the I2C driver I wrote and hooked up to an Arduino uno using the Wire library to act as a target device to talk to.&lt;/p&gt;

&lt;p&gt;Actions performed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The controller (ATtiny85) sends "Hello, World!" to the target (Arduino Uno) device.&lt;/li&gt;
&lt;li&gt;The controller requests a read from the target to toggle the LED.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/PXm8ce8ncOg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/I%C2%B2C" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/I%C2%B2C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://embedjournal.com/two-wire-interface-i2c-protocol-in-a-nut-shell/" rel="noopener noreferrer"&gt;https://embedjournal.com/two-wire-interface-i2c-protocol-in-a-nut-shell/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.sparkfun.com/tutorials/i2c/all" rel="noopener noreferrer"&gt;https://learn.sparkfun.com/tutorials/i2c/all&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-i2c-slave-addressing/" rel="noopener noreferrer"&gt;https://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-i2c-slave-addressing/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lucullusTheOnly/TinyWire" rel="noopener noreferrer"&gt;https://github.com/lucullusTheOnly/TinyWire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf" rel="noopener noreferrer"&gt;https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ww1.microchip.com/downloads/en/Appnotes/Atmel-2561-Using-the-USI-Module-as-a-I2C-Master_AP-Note_AVR310.pdf" rel="noopener noreferrer"&gt;https://ww1.microchip.com/downloads/en/Appnotes/Atmel-2561-Using-the-USI-Module-as-a-I2C-Master_AP-Note_AVR310.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nxp.com/docs/en/user-guide/UM10204.pdf" rel="noopener noreferrer"&gt;https://www.nxp.com/docs/en/user-guide/UM10204.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jmatth11/i2c-avr-driver" rel="noopener noreferrer"&gt;https://github.com/jmatth11/i2c-avr-driver&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>i2c</category>
      <category>c</category>
      <category>avr</category>
      <category>arduino</category>
    </item>
    <item>
      <title>Quick Zig and C String Conversion Conundrums</title>
      <dc:creator>Joshua Matthews</dc:creator>
      <pubDate>Sun, 13 Oct 2024 22:10:36 +0000</pubDate>
      <link>https://dev.to/jmatth11/quick-zig-and-c-string-conversion-conundrums-203b</link>
      <guid>https://dev.to/jmatth11/quick-zig-and-c-string-conversion-conundrums-203b</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;My background is mostly in C and as I am still new to zig some of the type conversions needed for C and Zig to talk were not crystal clear at the beginning. Now I understand them and I'll give a quick rundown to hopefully help anyone else that needs it.&lt;/p&gt;

&lt;h2&gt;
  
  
  C String types
&lt;/h2&gt;

&lt;p&gt;Let's start off with what a C string type is in Zig. There are 2 recommended&lt;sup&gt;1&lt;/sup&gt; ways of denoting a C string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="c"&gt;// Sentinel slice of unknown amount&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;
&lt;span class="c"&gt;// Slice of unknown amount&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="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you can expect the string to be null-terminated you want the first option which can be converted into a Zig slice with the &lt;code&gt;std.mem.span&lt;/code&gt; function. Otherwise, you'll want the second option with you usually requiring a &lt;code&gt;length&lt;/code&gt; parameter passed into your exported function so you can get a slice-by-length.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;test_c_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;local_slice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c"&gt;// rest of function&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;test_c_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&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="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;local_slice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="c"&gt;// rest of the function&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's really all you need to know for your C string needs. The rest of Zig's strings can convert between Zig slice/array types fairly easily without much intervention.&lt;/p&gt;

&lt;p&gt;One type that confused me at first was array sentinel types (i.e. &lt;code&gt;[5:0]const u8&lt;/code&gt;) because I assumed it was similar to &lt;code&gt;[*:0]const u8&lt;/code&gt; but the difference is the comptime length (i.e. &lt;code&gt;5&lt;/code&gt;) which turns this slice into a &lt;em&gt;known&lt;/em&gt; length so Zig can do it's slice conversions between similar types easily.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can also do &lt;code&gt;[*c]&lt;/code&gt; to signify a C pointer but it is &lt;a href="https://devdocs.io/zig/index#C-Pointers" rel="noopener noreferrer"&gt;noted this should only be used in autogenerated code.&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>zig</category>
      <category>c</category>
      <category>beginners</category>
      <category>strings</category>
    </item>
    <item>
      <title>Using Postgres Notifications To Enhance Dev Testing</title>
      <dc:creator>Joshua Matthews</dc:creator>
      <pubDate>Wed, 09 Oct 2024 03:02:55 +0000</pubDate>
      <link>https://dev.to/jmatth11/the-curtain-of-db-tools-b56</link>
      <guid>https://dev.to/jmatth11/the-curtain-of-db-tools-b56</guid>
      <description>&lt;p&gt;tl;dr Link to &lt;a href="https://github.com/jmatth11/db_listener" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;Sometimes your database can seem like a black box. Especially as you are running your application and it makes tons of calls and actions out to it. So many inserts and updates it's hard to keep track of what's happening. &lt;/p&gt;

&lt;p&gt;"What was the ID of that latest entry?"&lt;/p&gt;

&lt;p&gt;"What does this foreign key point to again?"&lt;/p&gt;

&lt;p&gt;All valid questions as you debug your latest changes to your application. The DB keeps it's curtain drawn while you have to search for these new updates. Usually your front-end can help grab them all for you, but that won't be the case where you can view your DB changes easily through the front-end all the time.&lt;/p&gt;

&lt;p&gt;So what can you do?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Investigation
&lt;/h2&gt;

&lt;p&gt;In my case, our database is Postgres and Postgres supports a nifty feature called &lt;a href="https://pgpedia.info/p/pg_notify.html" rel="noopener noreferrer"&gt;&lt;code&gt;pg_notify&lt;/code&gt;&lt;/a&gt;. I'm sure other DBs support this feature in some form or another, but for the purposes of this article I will be focusing on my use case.&lt;/p&gt;

&lt;p&gt;The basic usage of this function is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;pg_notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'channel'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'notification text'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have the &lt;code&gt;channel&lt;/code&gt; you'd like to post the notification on and the &lt;code&gt;notification text&lt;/code&gt; data you'd like to send on that channel.&lt;/p&gt;

&lt;p&gt;So we know how to notify, how do we listen?&lt;/p&gt;

&lt;p&gt;In Postgres you can listen on a channel &lt;code&gt;LISTEN 'channel'&lt;/code&gt;. However, we don't want to listen &lt;em&gt;in&lt;/em&gt; Postgres, we want to listen &lt;em&gt;in&lt;/em&gt; our listener application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stomping on the Curtains
&lt;/h2&gt;

&lt;p&gt;To setup our own notifications for our tables we just need to setup a reusable trigger.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="k"&gt;replace&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;person_notif_fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="k"&gt;trigger&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt; &lt;span class="n"&gt;perform&lt;/span&gt; &lt;span class="n"&gt;pg_notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'person'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_jsonb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="k"&gt;language&lt;/span&gt; &lt;span class="n"&gt;plpgsql&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have a simple function that returns a trigger that performs a &lt;code&gt;pg_notify&lt;/code&gt; call to our channel (&lt;code&gt;person&lt;/code&gt;) and takes the incoming &lt;code&gt;new&lt;/code&gt; object and transforms it into a JSON string. Then we return &lt;code&gt;new&lt;/code&gt; back out.&lt;/p&gt;

&lt;p&gt;Now that we have our trigger function, we need to attach a trigger to call our trigger on our table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;trigger&lt;/span&gt; &lt;span class="n"&gt;person_notif_tr&lt;/span&gt; &lt;span class="k"&gt;after&lt;/span&gt; &lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="k"&gt;update&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;each&lt;/span&gt; &lt;span class="k"&gt;row&lt;/span&gt; &lt;span class="k"&gt;execute&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;table_notif_fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Now our database will notify us of any inserts or deletes on our &lt;code&gt;person&lt;/code&gt; table.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hookup
&lt;/h2&gt;

&lt;p&gt;Creating an application that can tap into this is pretty easy with certain libraries. I created my app in Zig so I'll be using &lt;a href="https://github.com/karlseguin/pg.zig" rel="noopener noreferrer"&gt;&lt;code&gt;pg.zig&lt;/code&gt;&lt;/a&gt; but you can use whatever you'd like.&lt;/p&gt;

&lt;p&gt;First we establish our connection to our DB&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;heap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;page_allocator&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="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;connect&lt;/span&gt; &lt;span class="o"&gt;=&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="py"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.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;span class="py"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&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="py"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10_000&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;We've created our Pool now we just need to create a listener and connect to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newListener&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our DB driver is listening on the &lt;code&gt;person&lt;/code&gt; channel for notifications. So let's listen for them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="c"&gt;// create a fixed buffer allocator for our JSON object&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;out_buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;undefined&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;fixed_alloc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;heap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;FixedBufferAllocator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;out_buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c"&gt;// infinite loop to continually listen for updates&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// iterate on our listener&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;notif&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// reset the allocator&lt;/span&gt;
        &lt;span class="n"&gt;fixed_alloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c"&gt;// create a dynamic string&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;string_writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ArrayList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fixed_alloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allocator&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="c"&gt;// this is a custom object we are creating to store our info&lt;/span&gt;
            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notif&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notif&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="c"&gt;// stringify the data&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;info&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="n"&gt;string_writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c"&gt;// write out to buffer/websocket/etc.&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;Here we've created an infinite loop to continually check our listener poll. It's an infinite loop because our listener times out every now and then when polling for updates. (There could be a way to fix this but I couldn't find it quickly). Then we &lt;code&gt;stringify&lt;/code&gt; the data and from there we can send it off to a buffer/web-socket/ whatever you want the data to be sent to.&lt;/p&gt;

&lt;p&gt;And that's pretty much it! From here we can let our imagination run wild with how we want to improve or customize on top of this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Next Level
&lt;/h2&gt;

&lt;p&gt;Looking further into some of the niceties that Postgres gives us with it's built in functions and metadata from it's schema tables, we can automate getting all table data for any DB and adding triggers to them dynamically when connecting. This could streamline our listener application and become a really powerful development tool for us to use.&lt;/p&gt;

&lt;p&gt;I won't go into full detail because you can reference my &lt;a href="https://github.com/jmatth11/db_listener" rel="noopener noreferrer"&gt;Github project&lt;/a&gt; for the full implementation, but here is a simple snippet to grab all base tables in a Postgres DB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;table_schema&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;table_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'BASE TABLE'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;table_schema&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s1"&gt;'pg_catalog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'information_schema'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'typeorm'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query will return a list of tables in the format &lt;code&gt;&amp;lt;table_schema&amp;gt;.&amp;lt;table_name&amp;gt;&lt;/code&gt; for the entire DB -- excluding &lt;code&gt;pg_catalog&lt;/code&gt;, &lt;code&gt;information_schema&lt;/code&gt;, and &lt;code&gt;typeorm&lt;/code&gt;. Below is an example output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public.acconuts
public.mail_info
public.log_info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I'm going to do some hand wavy magic to skip over setting up the pipeline of getting the Postgres metadata into my server and displaying on a webpage, since the purpose of this article was just to be an introduction to DB notifications.&lt;/p&gt;

&lt;p&gt;Nevertheless, here is a demo of the final prototype of setting up notifications and grabbing the metadata of all tables in my DB.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/p6pA_MwAcD4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The Conclusion
&lt;/h2&gt;

&lt;p&gt;There's probably a lot of untapped potential in the tools you integrate with that you could be using to amplify your developer experience. Don't leave any stone unturned and always ask if your tool could do more, because it probably can.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>zig</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Implementing UTF-8 Encoding in Zig</title>
      <dc:creator>Joshua Matthews</dc:creator>
      <pubDate>Tue, 24 Sep 2024 06:12:58 +0000</pubDate>
      <link>https://dev.to/jmatth11/using-zig-to-add-utf8-unicode-support-395e</link>
      <guid>https://dev.to/jmatth11/using-zig-to-add-utf8-unicode-support-395e</guid>
      <description>&lt;p&gt;tl;dr&lt;br&gt;
Created a library to read/write UTF-8 encoded Unicode values in Zig for my simple text editor. &lt;a href="https://github.com/jmatth11/utf8-zig" rel="noopener noreferrer"&gt;Link to GitHub repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;One of my side projects is a simple text editor in C called &lt;a href="https://github.com/jmatth11/editlite" rel="noopener noreferrer"&gt;"Editlite"&lt;/a&gt;. The purpose of this editor was to explore creating one from the ground up and implementing functionality like Plugins and loading files incrementally to support editing large files. For this article I'll focus on just the Unicode support I wanted to add, though I may do a deeper dive into the editor in a future article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intro&lt;/li&gt;
&lt;li&gt;The Beginning&lt;/li&gt;
&lt;li&gt;The Format&lt;/li&gt;
&lt;li&gt;The Build&lt;/li&gt;
&lt;li&gt;C Header&lt;/li&gt;
&lt;li&gt;The Integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Learning Zig has been on my todo list for some time now and I have been trying to find more excuses to work it into projects to become more familiar with the language. I finally found a little project I could get my feet wet while also producing something that wouldn't be just a throw away program. I have a simple text editor and it currently only supports the ASCII character set, so I thought adding a basic Unicode support library would be the perfect &lt;em&gt;byte-sized&lt;/em&gt; intro to Zig I wanted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Beginning
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.unicode.org/versions/Unicode16.0.0/UnicodeStandard-16.0.pdf" rel="noopener noreferrer"&gt;Unicode is a standard&lt;/a&gt; that lays out how numerous symbols are mapped to certain code points so that applications can read and correctly display the appropriate text on any system. For example the number 69 (Hex value: 45) maps to the character &lt;code&gt;E&lt;/code&gt;. However, number 42069 (Hex value: A455) maps to character &lt;code&gt;ꑕ&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;There are different encodings to support this standard but the one I chose to implement was the &lt;a href="https://en.wikipedia.org/wiki/UTF-8" rel="noopener noreferrer"&gt;UTF-8&lt;/a&gt; standard, which breaks these numbers up into 8bit unsigned integer type representations over the range of 1 to 4 bytes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Format
&lt;/h2&gt;

&lt;p&gt;The best way to visualize the UTF-8 encoding format is with this table from the &lt;a href="https://datatracker.ietf.org/doc/html/rfc3629" rel="noopener noreferrer"&gt;RFC&lt;/a&gt;. Also to note, there are two things we will not cover in this article and that is the &lt;a href="https://en.wikipedia.org/wiki/UTF-8#Byte-order_mark" rel="noopener noreferrer"&gt;Byte-order Mark&lt;/a&gt; which is not required (default is big-endian) and the &lt;a href="https://en.wikipedia.org/wiki/UTF-8#Surrogates" rel="noopener noreferrer"&gt;UTF-16 Surrogates&lt;/a&gt; (reserved byte range &lt;code&gt;U+D800&lt;/code&gt;-&lt;code&gt;U+DFFF&lt;/code&gt;) which should be considered invalid in the UTF-8 format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2u3x4u4xqg40w3lkoo3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2u3x4u4xqg40w3lkoo3.png" alt="UTF-8 format table" width="676" height="233"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 1)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We'll break down each line and start codifying it into Zig for the baseline rules of our library.&lt;/p&gt;

&lt;p&gt;The first example &lt;code&gt;0xxxxxxx&lt;/code&gt; allows for this standard to be backwards compatible with the ASCII character set. The first bit needs to be &lt;code&gt;0&lt;/code&gt; and you have 7 free bits to use. So we need to ensure that first bit is zeroed out to be a valid 1 byte UTF-8 octet sequence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnhedryxhg80wx1zvscw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnhedryxhg80wx1zvscw.png" alt="zig function checking the one octet marker" width="428" height="85"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 2)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The next row starts defining the main pattern we will follow for the other sequence types. The leading &lt;code&gt;110&lt;/code&gt; bits signify that this sequence is a 2 byte UTF-8 octet sequence and the following octet leads with &lt;code&gt;10&lt;/code&gt; to signify this is the &lt;em&gt;next&lt;/em&gt; byte in the current octet sequence. So we see this encoding uses a &lt;code&gt;0&lt;/code&gt; padding bit to differentiate between all of these octet sequences. &lt;/p&gt;

&lt;p&gt;This is how we could codify those two rules in Zig.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favn0175illor4x9fy85d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favn0175illor4x9fy85d.png" alt="zig functions to check the next and two octet marker" width="471" height="166"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 3)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The following rows follow the same rules but for the 3 byte and 4 byte octet sequences with &lt;code&gt;1110&lt;/code&gt; and &lt;code&gt;11110&lt;/code&gt; respectively. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj313r79dant94t5j0hc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj313r79dant94t5j0hc6.png" alt="zig functions to check the three and four octet marker" width="470" height="163"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 4)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now that we've codified these rules we can move forward with writing our library.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Library
&lt;/h2&gt;

&lt;p&gt;The first thing we'll do is define some convenience types to work with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2lg0gpvld5ydoatutx6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2lg0gpvld5ydoatutx6.png" alt="zig enum and structure to represent octet info" width="610" height="530"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 5)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I wanted an easy way to keep track of what type of octet sequence type a certain code point was without having to re-encode it. Also this library is meant to be used in an existing C project so we need to create our &lt;code&gt;enum&lt;/code&gt; using &lt;code&gt;c_int&lt;/code&gt; and add the &lt;code&gt;extern&lt;/code&gt; keyword to our structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7hmjbkmvifpzpd5ed2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7hmjbkmvifpzpd5ed2p.png" alt="zig function to verify utf8 octets" width="751" height="307"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 6)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next we define a convenient function to verify multi-byte octet sequences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwr3t15zohr5svkvg5kxm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwr3t15zohr5svkvg5kxm.png" alt="zig function to get the octet type from u8" width="621" height="188"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 7)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The last convenience function we will explain is this one which determines which octet type is the given 8bit value. We'll explain the &lt;code&gt;export&lt;/code&gt; keyword with the next screenshot.&lt;/p&gt;

&lt;p&gt;Now the core of the library! The first function we'll define is the parsing function. I like to start at the unit level so we'll write a function to read the "next" Unicode code point in a given u8 array. Here's the definition of the function:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhszxojs8dgl7gg0ig72b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhszxojs8dgl7gg0ig72b.png" alt="zig function definition for parsing next code point" width="800" height="53"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 8)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Of course, we add the &lt;code&gt;export&lt;/code&gt; keyword to tell Zig to compile this function with the C ABI and we also need to use C compatible types -- so the &lt;code&gt;arr&lt;/code&gt; parameter is a &lt;code&gt;[*]const u8&lt;/code&gt; which is a slice of "unknown" size.&lt;/p&gt;

&lt;p&gt;Alright, now to the meat of the function:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyd3p7v4qfewll53t8e3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyd3p7v4qfewll53t8e3.png" alt="zig function of implementation of parse functionality" width="800" height="779"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 9)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We start off with a reusable &lt;code&gt;invalid_point&lt;/code&gt; object to return on errors. Next we do some housekeeping checks. We then define our initial result which we grab the starting octet out of the array and determine it's octet type with &lt;code&gt;get_oct_type&lt;/code&gt;. Next we just switch on the type and try to parse from there.&lt;/p&gt;

&lt;p&gt;The first two cases are easy. If the initial type was &lt;code&gt;OCT_INVALID&lt;/code&gt; or &lt;code&gt;OCT_NEXT&lt;/code&gt; then this isn't a correctly formatted UTF-8 string so we return an "invalid" code point. For a &lt;code&gt;OCT_ONE&lt;/code&gt; type we just pull the value straight out.&lt;/p&gt;

&lt;p&gt;The rest of the cases are a little more involved but still straightforward. We check to make sure there are an expected number of bytes based on the type. We also verify the rest of the bytes are formatted properly with &lt;code&gt;verify_octets&lt;/code&gt;. Then we pull each value out and &lt;code&gt;&amp;amp;&lt;/code&gt; it with it's corresponding &lt;em&gt;free bits&lt;/em&gt;. Lastly, we shift the values based on their &lt;em&gt;free bits&lt;/em&gt; (6 * offset) and logical or the values into our code point in big-endian format.&lt;/p&gt;

&lt;p&gt;That's it for parsing! Now you can use this method to loop over your UTF-8 encoded buffers!&lt;/p&gt;

&lt;p&gt;The next crucial function to implement is the "write" function -- to take a &lt;code&gt;u32&lt;/code&gt; code point and write it back out to a UTF-8 encoded buffer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4660giqxqbi7j9cxg12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4660giqxqbi7j9cxg12.png" alt="zig function of write functionality" width="800" height="152"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 10)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This function is a thin function for the C API to take in a C-style array and turn it into a Zig slice then pass it onto the real write function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn522vf4e7dub2ptsrir7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn522vf4e7dub2ptsrir7.png" alt="zig function of write functionality, full" width="800" height="723"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 11)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The write function is also straightforward in it's implementation. Switching on the code point's type and pulling out the appropriate byte information from the &lt;code&gt;u32&lt;/code&gt; in big-endian format. You'll notice some convenience functions that are just thin inline functions to ensure the value is in the correct format of the UTF-8 octet sequence markers. &lt;/p&gt;

&lt;p&gt;Now we can continually write out code points to a given u8 buffer!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Build
&lt;/h2&gt;

&lt;p&gt;Next, the &lt;code&gt;build.zig&lt;/code&gt; file. Most of this is standard but we needed to bundle the Zig compiler runtime into the static build, so this is how the build file looked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9j06zeq0t9eg2gdceaye.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9j06zeq0t9eg2gdceaye.png" alt="zig build file" width="483" height="240"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 12)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  C Header
&lt;/h2&gt;

&lt;p&gt;Next we need to generate the C header file to accompany the static library. Luckily the types easily map over.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclt68q13ob6fczf2y72g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclt68q13ob6fczf2y72g.png" alt="C header file" width="800" height="527"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 13)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can ignore the &lt;code&gt;__THROWNL&lt;/code&gt; and &lt;code&gt;__nonnull(())&lt;/code&gt; calls, the important part to take away from this is we need to set the &lt;code&gt;extern&lt;/code&gt; keyword in front of our functions. Now we can use this in our C programs like you would normally include a static library!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Integration
&lt;/h2&gt;

&lt;p&gt;After integrating this library into my simple text editor I can now read/write and accept Unicode input.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmanj8cf7iqxli3m73zqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmanj8cf7iqxli3m73zqp.png" alt="Text editor displaying Unicode characters" width="800" height="579"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Fig. 14)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>zig</category>
      <category>unicode</category>
      <category>c</category>
      <category>text</category>
    </item>
  </channel>
</rss>
