<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://sgeos.github.io/feed/jekyll.xml" rel="self" type="application/atom+xml" /><link href="https://sgeos.github.io/" rel="alternate" type="text/html" /><updated>2026-07-12T01:04:06+00:00</updated><id>https://sgeos.github.io/feed/jekyll.xml</id><title type="html">Brendan A R Sechter’s Development Blog | Jekyll</title><subtitle>A personal technical notebook covering systems programming, systems philosophy, tooling, mathematics, and emerging software paradigms.
</subtitle><author><name>Brendan Sechter</name></author><entry><title type="html">WASM on a Jekyll Blog with Rust and wasm-bindgen</title><link href="https://sgeos.github.io/rust/wasm/jekyll/2026/01/26/webasm_on_jekyll.html" rel="alternate" type="text/html" title="WASM on a Jekyll Blog with Rust and wasm-bindgen" /><published>2026-01-26T04:19:39+00:00</published><updated>2026-01-26T04:19:39+00:00</updated><id>https://sgeos.github.io/rust/wasm/jekyll/2026/01/26/webasm_on_jekyll</id><content type="html" xml:base="https://sgeos.github.io/rust/wasm/jekyll/2026/01/26/webasm_on_jekyll.html"><![CDATA[<!-- A72 -->
<script>console.log("A72");</script>

<p>Jekyll generates static pages from templates.
It is often used for blogs, like this one.
Sometimes you want to include interactive elements, like calculators.</p>

<p>This post documents how web assembly (WASM) driven UI widget
can be included in a Jekyll blog post with Rust
and <code class="language-plaintext highlighter-rouge">wasm-bindgen</code>.
It is a tutorial on getting the WASM to work, not a deep dive
into <code class="language-plaintext highlighter-rouge">wasm-bindgen</code>.</p>

<p>The post largely documents the steps taken to get the following
UI-widget up and running on this page.</p>

<style>
  .wasm-greeting-ui {
    max-width: 300px;
    font-family: sans-serif;
    border: 2px solid red;   /* red outline */
    padding: 0.75rem;        /* some space inside the box */
    border-radius: 4px;      /* optional: slightly rounded corners */
    background-color: #fff;  /* optional: white background */
  }

  .wasm-greeting-ui .line1 {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
  }

  .wasm-greeting-ui .line2 {
    font-weight: bold;
  }
</style>

<script type="module" id="wasm_ui">
  import init, { inject_ui } from "/assets/wasm/post_webasm_on_jekyll/post_webasm_on_jekyll.js";
  async function run() {
    await init();
    inject_ui("wasm_ui");
  }
  run();
</script>

<h2 id="software-versions">Software Versions</h2>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Date (UTC)</span>
<span class="nv">$ </span><span class="nb">date</span> <span class="nt">-u</span> <span class="s2">"+%Y-%m-%d %H:%M:%S +0000"</span>
2026-01-26 04:19:39 +0000

<span class="c"># OS and Version</span>
<span class="nv">$ </span><span class="nb">uname</span> <span class="nt">-vm</span>
Darwin Kernel Version 23.6.0: Mon Jul 29 21:14:30 PDT 2024<span class="p">;</span> root:xnu-10063.141.2~1/RELEASE_ARM64_T6000 arm64

<span class="nv">$ </span>sw_vers
ProductName:		macOS
ProductVersion:		14.6.1
BuildVersion:		23G93

<span class="c"># Hardware Information</span>
<span class="nv">$ </span>system_profiler SPHardwareDataType | <span class="nb">sed</span> <span class="nt">-n</span> <span class="s1">'8,10p'</span>
      Chip: Apple M1 Max
      Total Number of Cores: 10 <span class="o">(</span>8 performance and 2 efficiency<span class="o">)</span>
      Memory: 32 GB

<span class="c"># Shell and Version</span>
<span class="nv">$ </span><span class="nb">echo</span> <span class="s2">"</span><span class="k">${</span><span class="nv">SHELL</span><span class="k">}</span><span class="s2">"</span>
/bin/bash

<span class="nv">$ </span><span class="s2">"</span><span class="k">${</span><span class="nv">SHELL</span><span class="k">}</span><span class="s2">"</span> <span class="nt">--version</span>  | <span class="nb">head</span> <span class="nt">-n</span> 1
GNU bash, version 3.2.57<span class="o">(</span>1<span class="o">)</span><span class="nt">-release</span> <span class="o">(</span>arm64-apple-darwin23<span class="o">)</span>

<span class="c"># Rust Installation Versions</span>
<span class="nv">$ </span>cargo <span class="nt">--version</span>
cargo 1.93.0 <span class="o">(</span>083ac5135 2025-12-15<span class="o">)</span>
</code></pre></div></div>

<h2 id="instructions">Instructions</h2>

<p>First, create a new library project.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">PROJECT_NAME</span><span class="o">=</span><span class="s2">"post_webasm_on_jekyll"</span>
cargo new <span class="nt">--lib</span> <span class="s2">"</span><span class="k">${</span><span class="nv">PROJECT_NAME</span><span class="k">}</span><span class="s2">"</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="k">${</span><span class="nv">PROJECT_NAME</span><span class="k">}</span><span class="s2">"</span>
</code></pre></div></div>

<p>Next, add the <code class="language-plaintext highlighter-rouge">js-sys</code>, <code class="language-plaintext highlighter-rouge">wasm-bindgen</code>, and <code class="language-plaintext highlighter-rouge">web-sys</code> dependencies for this project.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo add js-sys
cargo add wasm-bindgen
cargo add web-sys <span class="se">\</span>
  <span class="nt">-F</span> Document <span class="nt">-F</span> Element <span class="nt">-F</span> Event <span class="nt">-F</span> EventTarget <span class="se">\</span>
  <span class="nt">-F</span> HtmlElement <span class="nt">-F</span> HtmlInputElement <span class="nt">-F</span> Node <span class="nt">-F</span> Window
</code></pre></div></div>

<p>WASM needs to be packaged as a dynamic library, so
set the library type to a C dynamic library using your editor of choice.</p>

<p><code class="language-plaintext highlighter-rouge">Cargo.toml</code> partial listing</p>
<div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[lib]</span>
<span class="py">crate-type</span> <span class="p">=</span> <span class="nn">["cdylib"]</span>
</code></pre></div></div>

<p>Your complete <code class="language-plaintext highlighter-rouge">Cargo.toml</code> should look something like this.</p>

<p><code class="language-plaintext highlighter-rouge">Cargo.toml</code> full listing</p>
<div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[package]</span>
<span class="py">name</span> <span class="p">=</span> <span class="s">"post_webasm_on_jekyll"</span>
<span class="py">version</span> <span class="p">=</span> <span class="s">"0.1.0"</span>
<span class="py">edition</span> <span class="p">=</span> <span class="s">"2024"</span>

<span class="nn">[lib]</span>
<span class="py">crate-type</span> <span class="p">=</span> <span class="nn">["cdylib"]</span>

<span class="nn">[dependencies]</span>
<span class="py">js-sys</span> <span class="p">=</span> <span class="s">"0.3.85"</span>
<span class="py">wasm-bindgen</span> <span class="p">=</span> <span class="s">"0.2.108"</span>
<span class="nn">web-sys</span> <span class="o">=</span> <span class="p">{</span> <span class="py">version</span> <span class="p">=</span> <span class="s">"0.3.85"</span><span class="p">,</span> <span class="py">features</span> <span class="p">=</span> <span class="p">[</span><span class="s">"Document"</span><span class="p">,</span> <span class="s">"Element"</span><span class="p">,</span> <span class="s">"Event"</span><span class="p">,</span> <span class="s">"EventTarget"</span><span class="p">,</span> <span class="s">"HtmlElement"</span><span class="p">,</span> <span class="s">"HtmlInputElement"</span><span class="p">,</span> <span class="s">"Node"</span><span class="p">,</span> <span class="s">"Window"</span><span class="p">,</span> <span class="p">]</span> <span class="p">}</span>
</code></pre></div></div>

<p>Replace <code class="language-plaintext highlighter-rouge">src/lib.rs</code> with the following contents.</p>

<p><code class="language-plaintext highlighter-rouge">src/lib.rs</code> full listing</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">wasm_bindgen</span><span class="p">::</span><span class="nn">prelude</span><span class="p">::</span><span class="o">*</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">wasm_bindgen</span><span class="p">::</span><span class="n">JsCast</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">web_sys</span><span class="p">::{</span><span class="n">HtmlElement</span><span class="p">,</span> <span class="n">HtmlInputElement</span><span class="p">,</span> <span class="n">Event</span><span class="p">};</span>

<span class="nd">#[wasm_bindgen]</span>
<span class="k">pub</span> <span class="k">fn</span> <span class="nf">inject_ui</span><span class="p">(</span><span class="n">anchor_id</span><span class="p">:</span> <span class="o">&amp;</span><span class="nb">str</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">let</span> <span class="n">document</span> <span class="o">=</span> <span class="nn">web_sys</span><span class="p">::</span><span class="nf">window</span><span class="p">()</span>
        <span class="nf">.unwrap</span><span class="p">()</span>
        <span class="nf">.document</span><span class="p">()</span>
        <span class="nf">.unwrap</span><span class="p">();</span>

    <span class="k">let</span> <span class="n">anchor</span> <span class="o">=</span> <span class="n">document</span>
        <span class="nf">.get_element_by_id</span><span class="p">(</span><span class="n">anchor_id</span><span class="p">)</span>
        <span class="nf">.expect</span><span class="p">(</span><span class="s">"anchor element not found"</span><span class="p">);</span>

    <span class="k">let</span> <span class="n">parent</span> <span class="o">=</span> <span class="n">anchor</span>
        <span class="nf">.parent_node</span><span class="p">()</span>
        <span class="nf">.expect</span><span class="p">(</span><span class="s">"anchor has no parent"</span><span class="p">);</span>

    <span class="k">let</span> <span class="n">container</span> <span class="o">=</span> <span class="n">document</span>
        <span class="nf">.create_element</span><span class="p">(</span><span class="s">"div"</span><span class="p">)</span>
        <span class="nf">.unwrap</span><span class="p">();</span>
    <span class="n">container</span><span class="nf">.set_class_name</span><span class="p">(</span><span class="s">"wasm-greeting-ui"</span><span class="p">);</span>

    <span class="c1">// --- Line 1: label + input ---</span>
    <span class="k">let</span> <span class="n">line1</span> <span class="o">=</span> <span class="n">document</span><span class="nf">.create_element</span><span class="p">(</span><span class="s">"div"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
    <span class="n">line1</span><span class="nf">.set_class_name</span><span class="p">(</span><span class="s">"line1"</span><span class="p">);</span>

    <span class="k">let</span> <span class="n">label</span> <span class="o">=</span> <span class="n">document</span><span class="nf">.create_element</span><span class="p">(</span><span class="s">"label"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
    <span class="n">label</span><span class="nf">.set_text_content</span><span class="p">(</span><span class="nf">Some</span><span class="p">(</span><span class="s">"Name: "</span><span class="p">));</span>
    <span class="n">label</span><span class="nf">.set_attribute</span><span class="p">(</span><span class="s">"for"</span><span class="p">,</span> <span class="s">"name-input"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>

    <span class="k">let</span> <span class="n">input</span><span class="p">:</span> <span class="n">HtmlInputElement</span> <span class="o">=</span> <span class="n">document</span>
        <span class="nf">.create_element</span><span class="p">(</span><span class="s">"input"</span><span class="p">)</span>
        <span class="nf">.unwrap</span><span class="p">()</span>
        <span class="nf">.dyn_into</span><span class="p">()</span>
        <span class="nf">.unwrap</span><span class="p">();</span>
    <span class="n">input</span><span class="nf">.set_type</span><span class="p">(</span><span class="s">"text"</span><span class="p">);</span>
    <span class="n">input</span><span class="nf">.set_id</span><span class="p">(</span><span class="s">"name-input"</span><span class="p">);</span>
    <span class="n">input</span><span class="nf">.set_placeholder</span><span class="p">(</span><span class="s">"Enter your name"</span><span class="p">);</span>

    <span class="c1">// append label + input to line1 container</span>
    <span class="n">line1</span><span class="nf">.append_child</span><span class="p">(</span><span class="o">&amp;</span><span class="n">label</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
    <span class="n">line1</span><span class="nf">.append_child</span><span class="p">(</span><span class="o">&amp;</span><span class="n">input</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>

    <span class="c1">// --- Line 2: message ---</span>
    <span class="k">let</span> <span class="n">message</span><span class="p">:</span> <span class="n">HtmlElement</span> <span class="o">=</span> <span class="n">document</span>
        <span class="nf">.create_element</span><span class="p">(</span><span class="s">"div"</span><span class="p">)</span>
        <span class="nf">.unwrap</span><span class="p">()</span>
        <span class="nf">.dyn_into</span><span class="p">()</span>
        <span class="nf">.unwrap</span><span class="p">();</span>
    <span class="n">message</span><span class="nf">.set_class_name</span><span class="p">(</span><span class="s">"line2"</span><span class="p">);</span>

    <span class="nf">update_message</span><span class="p">(</span><span class="o">&amp;</span><span class="n">message</span><span class="p">,</span> <span class="nb">None</span><span class="p">);</span>

    <span class="c1">// Append line1 and line2 to the main container</span>
    <span class="n">container</span><span class="nf">.append_child</span><span class="p">(</span><span class="o">&amp;</span><span class="n">line1</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
    <span class="n">container</span><span class="nf">.append_child</span><span class="p">(</span><span class="o">&amp;</span><span class="n">message</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>

    <span class="c1">// Replace the anchor with the new UI</span>
    <span class="n">parent</span><span class="nf">.replace_child</span><span class="p">(</span><span class="o">&amp;</span><span class="n">container</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">anchor</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>

    <span class="c1">// --- Event listener ---</span>
    <span class="k">let</span> <span class="n">message_clone</span> <span class="o">=</span> <span class="n">message</span><span class="nf">.clone</span><span class="p">();</span>
    <span class="k">let</span> <span class="n">input_clone</span> <span class="o">=</span> <span class="n">input</span><span class="nf">.clone</span><span class="p">();</span>
    <span class="k">let</span> <span class="n">closure</span> <span class="o">=</span> <span class="nn">Closure</span><span class="p">::</span><span class="nf">wrap</span><span class="p">(</span><span class="nn">Box</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="k">move</span> <span class="p">|</span><span class="n">_event</span><span class="p">:</span> <span class="n">Event</span><span class="p">|</span> <span class="p">{</span>
        <span class="k">let</span> <span class="n">value</span> <span class="o">=</span> <span class="n">input_clone</span><span class="nf">.value</span><span class="p">();</span>
        <span class="k">if</span> <span class="n">value</span><span class="nf">.trim</span><span class="p">()</span><span class="nf">.is_empty</span><span class="p">()</span> <span class="p">{</span>
            <span class="nf">update_message</span><span class="p">(</span><span class="o">&amp;</span><span class="n">message_clone</span><span class="p">,</span> <span class="nb">None</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="nf">update_message</span><span class="p">(</span><span class="o">&amp;</span><span class="n">message_clone</span><span class="p">,</span> <span class="nf">Some</span><span class="p">(</span><span class="o">&amp;</span><span class="n">value</span><span class="p">));</span>
        <span class="p">}</span>
    <span class="p">})</span> <span class="k">as</span> <span class="nb">Box</span><span class="o">&lt;</span><span class="k">dyn</span> <span class="nf">FnMut</span><span class="p">(</span><span class="n">Event</span><span class="p">)</span><span class="o">&gt;</span><span class="p">);</span>

    <span class="n">input</span>
        <span class="nf">.add_event_listener_with_callback</span><span class="p">(</span><span class="s">"input"</span><span class="p">,</span> <span class="n">closure</span><span class="nf">.as_ref</span><span class="p">()</span><span class="nf">.unchecked_ref</span><span class="p">())</span>
        <span class="nf">.unwrap</span><span class="p">();</span>

    <span class="n">closure</span><span class="nf">.forget</span><span class="p">();</span>
<span class="p">}</span>

<span class="k">fn</span> <span class="nf">update_message</span><span class="p">(</span><span class="n">message</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">HtmlElement</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">Option</span><span class="o">&lt;&amp;</span><span class="nb">str</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">let</span> <span class="n">name</span> <span class="o">=</span> <span class="n">name</span><span class="nf">.unwrap_or</span><span class="p">(</span><span class="s">"USERNAME"</span><span class="p">);</span>
    <span class="n">message</span><span class="nf">.set_text_content</span><span class="p">(</span><span class="nf">Some</span><span class="p">(</span><span class="o">&amp;</span><span class="nd">format!</span><span class="p">(</span><span class="s">"Hello, {}!"</span><span class="p">,</span> <span class="n">name</span><span class="p">)));</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Install <code class="language-plaintext highlighter-rouge">wasm-pack</code> with <code class="language-plaintext highlighter-rouge">cargo</code> if you need to.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo <span class="nb">install </span>wasm-pack
</code></pre></div></div>

<p>Build the WASM with the following command.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wasm-pack build <span class="nt">--target</span> web
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">wasm-pack</code> produces files in <code class="language-plaintext highlighter-rouge">pkg/</code>, which Jekyll will not serve automatically.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tree pkg/
</code></pre></div></div>

<p><strong>Expected Output</strong></p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pkg/
├── post_webasm_on_jekyll.d.ts
├── post_webasm_on_jekyll.js
├── post_webasm_on_jekyll_bg.wasm
├── post_webasm_on_jekyll_bg.wasm.d.ts
└── package.json

1 directory, 5 files
</code></pre></div></div>

<p>To serve these files, they need to be copied into
<code class="language-plaintext highlighter-rouge">${JEKYLL_PATH}/assets</code>, ideally in something like the
<code class="language-plaintext highlighter-rouge">wasm/${PROJECT_NAME}</code> subdirectory to keep things organized.
Note that you probably do not want to copy the generated <code class="language-plaintext highlighter-rouge">.gitignore</code>.
Using <code class="language-plaintext highlighter-rouge">pkg/*</code> ensures we copy all build artifacts while ignoring the hidden
<code class="language-plaintext highlighter-rouge">.gitignore</code> file that wasm-pack creates, which would otherwise hide your
WASM files from <code class="language-plaintext highlighter-rouge">git</code> and complicate deployment.
Use the following command to copy the files.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">PROJECT_NAME</span><span class="o">=</span><span class="s2">"post_webasm_on_jekyll"</span>
<span class="nv">JEKYLL_PATH</span><span class="o">=</span><span class="s2">"/path/to/jekyll/blog"</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> <span class="s2">"</span><span class="k">${</span><span class="nv">JEKYLL_PATH</span><span class="k">}</span><span class="s2">/assets/wasm/</span><span class="k">${</span><span class="nv">PROJECT_NAME</span><span class="k">}</span><span class="s2">"</span>
<span class="nb">cp</span> <span class="nt">-r</span> pkg/<span class="k">*</span> <span class="s2">"</span><span class="k">${</span><span class="nv">JEKYLL_PATH</span><span class="k">}</span><span class="s2">/assets/wasm/</span><span class="k">${</span><span class="nv">PROJECT_NAME</span><span class="k">}</span><span class="s2">/"</span>
</code></pre></div></div>

<p>If you want to <strong>overwrite</strong> existing files automatically, add <code class="language-plaintext highlighter-rouge">-f</code>.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cp</span> <span class="nt">-rf</span> pkg/<span class="k">*</span> <span class="s2">"</span><span class="k">${</span><span class="nv">JEKYLL_PATH</span><span class="k">}</span><span class="s2">/assets/wasm/</span><span class="k">${</span><span class="nv">PROJECT_NAME</span><span class="k">}</span><span class="s2">/"</span>
</code></pre></div></div>

<p>After copying, all files should be present in the <code class="language-plaintext highlighter-rouge">assets</code> directory.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ls</span> <span class="nt">-1</span> <span class="s2">"</span><span class="k">${</span><span class="nv">JEKYLL_PATH</span><span class="k">}</span><span class="s2">/assets/wasm/</span><span class="k">${</span><span class="nv">PROJECT_NAME</span><span class="k">}</span><span class="s2">/"</span>
</code></pre></div></div>

<p><strong>Expected Output</strong></p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>package.json
post_webasm_on_jekyll.d.ts
post_webasm_on_jekyll.js
post_webasm_on_jekyll_bg.wasm
post_webasm_on_jekyll_bg.wasm.d.ts
</code></pre></div></div>

<p>Inline an HTML <code class="language-plaintext highlighter-rouge">script</code> tag in the blog post to load the WASM. 
Note that the <code class="language-plaintext highlighter-rouge">id</code> of the <code class="language-plaintext highlighter-rouge">script</code> tag is used as an anchor, 
which the Rust code will replace with the WASM-driven UI. 
Alternatively, you can use an empty <code class="language-plaintext highlighter-rouge">div</code> (<code class="language-plaintext highlighter-rouge">&lt;div id="wasm_ui"&gt;&lt;/div&gt;</code>) 
or a self-closing tag like <code class="language-plaintext highlighter-rouge">&lt;input type="hidden" id="wasm_ui" /&gt;</code> 
as your anchor if you prefer to keep the script logic and the 
UI placement separate.</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;script </span><span class="na">type=</span><span class="s">"module"</span> <span class="na">id=</span><span class="s">"wasm_ui"</span><span class="nt">&gt;</span>
  <span class="k">import</span> <span class="nx">init</span><span class="p">,</span> <span class="p">{</span> <span class="nx">inject_ui</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">/assets/wasm/post_webasm_on_jekyll/post_webasm_on_jekyll.js</span><span class="dl">"</span><span class="p">;</span>
  <span class="k">async</span> <span class="kd">function</span> <span class="nx">run</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">await</span> <span class="nx">init</span><span class="p">();</span>
    <span class="nx">inject_ui</span><span class="p">(</span><span class="dl">"</span><span class="s2">wasm_ui</span><span class="dl">"</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="nx">run</span><span class="p">();</span>
<span class="nt">&lt;/script&gt;</span>
</code></pre></div></div>

<p>Also, you can add CSS in a <code class="language-plaintext highlighter-rouge">style</code> block above the <code class="language-plaintext highlighter-rouge">script</code> tag,
or put it in an included external file if you want to style your UI.</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&lt;</span><span class="nt">style</span><span class="o">&gt;</span>
  <span class="nc">.wasm-greeting-ui</span> <span class="p">{</span>
    <span class="nl">max-width</span><span class="p">:</span> <span class="m">300px</span><span class="p">;</span>
    <span class="nl">font-family</span><span class="p">:</span> <span class="nb">sans-serif</span><span class="p">;</span>
    <span class="nl">border</span><span class="p">:</span> <span class="m">2px</span> <span class="nb">solid</span> <span class="no">red</span><span class="p">;</span>   <span class="c">/* red outline */</span>
    <span class="nl">padding</span><span class="p">:</span> <span class="m">0.75rem</span><span class="p">;</span>        <span class="c">/* some space inside the box */</span>
    <span class="nl">border-radius</span><span class="p">:</span> <span class="m">4px</span><span class="p">;</span>      <span class="c">/* optional: slightly rounded corners */</span>
    <span class="nl">background-color</span><span class="p">:</span> <span class="m">#fff</span><span class="p">;</span>  <span class="c">/* optional: white background */</span>
  <span class="p">}</span>

  <span class="nc">.wasm-greeting-ui</span> <span class="nc">.line1</span> <span class="p">{</span>
    <span class="nl">display</span><span class="p">:</span> <span class="n">flex</span><span class="p">;</span>
    <span class="nl">align-items</span><span class="p">:</span> <span class="nb">center</span><span class="p">;</span>
    <span class="py">gap</span><span class="p">:</span> <span class="m">0.5rem</span><span class="p">;</span>
    <span class="nl">margin-bottom</span><span class="p">:</span> <span class="m">0.5rem</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="nc">.wasm-greeting-ui</span> <span class="nc">.line2</span> <span class="p">{</span>
    <span class="nl">font-weight</span><span class="p">:</span> <span class="nb">bold</span><span class="p">;</span>
  <span class="p">}</span>
<span class="o">&lt;/</span><span class="nt">style</span><span class="o">&gt;</span>
</code></pre></div></div>

<h2 id="future-reading">Future Reading</h2>

<p>If you want to explore more about WebAssembly, Rust, and integrating dynamic
UIs in static sites, these resources are highly recommended:</p>

<ul>
  <li>
    <p><strong>Rust and WASM Fundamentals:</strong>
Learn how Rust compiles to WebAssembly, how to use <code class="language-plaintext highlighter-rouge">wasm-bindgen</code>, and best
practices for building interactive web apps. See the official
<a href="https://rustwasm.github.io/docs/book/">Rust and WebAssembly Book</a>.</p>
  </li>
  <li>
    <p><strong>Jekyll Assets &amp; Static Sites:</strong>
Tips on structuring static assets in Jekyll, managing JavaScript/CSS, and
optimizing for WASM loading can be found in the
<a href="https://jekyllrb.com/docs/assets/">Jekyll Assets Documentation</a>.</p>
  </li>
</ul>

<h2 id="references">References:</h2>

<ul>
  <li><a href="https://rustwasm.github.io/docs/book/">Rust and WebAssembly Book</a></li>
  <li><a href="https://jekyllrb.com/docs/assets/">Jekyll Assets</a></li>
</ul>]]></content><author><name>Brendan Sechter</name></author><category term="rust" /><category term="wasm" /><category term="jekyll" /></entry><entry><title type="html">Adding Images and Downloads to a GitHub Pages Jekyll Blog</title><link href="https://sgeos.github.io/github/jekyll/2016/08/30/adding_images_and_downloads_to_a_github_pages_jekyll_blog.html" rel="alternate" type="text/html" title="Adding Images and Downloads to a GitHub Pages Jekyll Blog" /><published>2016-08-30T19:45:55+00:00</published><updated>2016-08-30T19:45:55+00:00</updated><id>https://sgeos.github.io/github/jekyll/2016/08/30/adding_images_and_downloads_to_a_github_pages_jekyll_blog</id><content type="html" xml:base="https://sgeos.github.io/github/jekyll/2016/08/30/adding_images_and_downloads_to_a_github_pages_jekyll_blog.html"><![CDATA[<!-- A40 -->
<script>console.log("A40");</script>

<p>This post covers adding images to a <a href="https://pages.github.com">GitHub Pages</a> <a href="https://jekyllrb.com">Jekyll blog</a>.
This solution also works for downloads, like PDFs.</p>

<h2 id="software-versions">Software Versions</h2>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nv">$ </span><span class="nb">date</span> <span class="nt">-u</span> <span class="s2">"+%Y-%m-%d %H:%M:%S +0000"</span>
2016-08-30 19:45:55 +0000
<span class="nv">$ </span><span class="nb">uname</span> <span class="nt">-vm</span>
FreeBSD 12.0-CURRENT <span class="c">#0 r304324: Thu Aug 18 13:27:23 JST 2016     root@mirage.sennue.com:/usr/obj/usr/src/sys/MIRAGE_KERNEL  amd64</span>
<span class="nv">$ </span>ruby <span class="nt">--version</span>
ruby 2.2.5p319 <span class="o">(</span>2016-04-26 revision 54774<span class="o">)</span> <span class="o">[</span>amd64-freebsd11]
<span class="nv">$ </span>jekyll <span class="nt">--version</span>
jekyll 3.0.1</code></pre></figure>

<h2 id="instructions">Instructions</h2>

<p>First, create an <strong>assets</strong> directory.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nb">mkdir </span>assets</code></pre></figure>

<p>Add an image to the <strong>assets</strong> directory.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nb">cp </span>path/to/image.png ./assets/</code></pre></figure>

<p>The image can be displayed as follows.</p>

<figure class="highlight"><pre><code class="language-liquid" data-lang="liquid">![useful image](<span class="p">{{</span><span class="w"> </span><span class="nv">site</span><span class="p">.</span><span class="nv">url</span><span class="w"> </span><span class="p">}}</span>/assets/image/post_adding_images_and_downloads_to_a_github_pages_jekyll_blog/image.png)</code></pre></figure>

<p><img src="https://sgeos.github.io/assets/image/post_adding_images_and_downloads_to_a_github_pages_jekyll_blog/image.png" alt="useful image" /></p>

<p>Note that downloads can be made available with the same strategy.</p>

<figure class="highlight"><pre><code class="language-liquid" data-lang="liquid">You can download the PDF [here](<span class="p">{{</span><span class="w"> </span><span class="nv">site</span><span class="p">.</span><span class="nv">url</span><span class="w"> </span><span class="p">}}</span>/assets/pdf/post_adding_images_and_downloads_to_a_github_pages_jekyll_blog/document.pdf).</code></pre></figure>

<p>You can download the PDF <a href="https://sgeos.github.io/assets/pdf/post_adding_images_and_downloads_to_a_github_pages_jekyll_blog/document.pdf">here</a>.</p>

<h2 id="references">References:</h2>

<ul>
  <li><a href="https://pages.github.com">GitHub Pages</a></li>
  <li><a href="https://jekyllrb.com">Jekyll</a></li>
  <li><a href="https://jekyllrb.com/docs/posts/">Jekyll, Writing posts</a></li>
</ul>]]></content><author><name>Brendan Sechter</name></author><category term="github" /><category term="jekyll" /></entry><entry><title type="html">Adding MathJax to a GitHub Pages Jekyll Blog</title><link href="https://sgeos.github.io/github/jekyll/2016/08/21/adding_mathjax_to_a_jekyll_github_pages_blog.html" rel="alternate" type="text/html" title="Adding MathJax to a GitHub Pages Jekyll Blog" /><published>2016-08-21T23:41:54+00:00</published><updated>2016-08-21T23:41:54+00:00</updated><id>https://sgeos.github.io/github/jekyll/2016/08/21/adding_mathjax_to_a_jekyll_github_pages_blog</id><content type="html" xml:base="https://sgeos.github.io/github/jekyll/2016/08/21/adding_mathjax_to_a_jekyll_github_pages_blog.html"><![CDATA[<!-- A39 -->
<script>console.log("A39");</script>

<p>This post covers adding <a href="https://www.mathjax.org">MathJax</a> support to a <a href="https://pages.github.com">GitHub Pages</a> <a href="https://jekyllrb.com">Jekyll blog</a>.</p>

<h2 id="software-versions">Software Versions</h2>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nv">$ </span><span class="nb">date</span> <span class="nt">-u</span> <span class="s2">"+%Y-%m-%d %H:%M:%S +0000"</span>
2016-08-21 23:41:54 +0000
<span class="nv">$ </span><span class="nb">uname</span> <span class="nt">-vm</span>
FreeBSD 11.0-ALPHA6 <span class="c">#0 r302384: Thu Jul  7 22:40:47 JST 2016     root@mirage.sennue.com:/usr/obj/usr/src/sys/MIRAGE_KERNEL  amd64</span>
<span class="nv">$ </span>ruby <span class="nt">--version</span>
ruby 2.2.5p319 <span class="o">(</span>2016-04-26 revision 54774<span class="o">)</span> <span class="o">[</span>amd64-freebsd11]
<span class="nv">$ </span>jekyll <span class="nt">--version</span>
jekyll 3.0.1</code></pre></figure>

<h2 id="instructions">Instructions</h2>

<p>Add the following code to <strong>_includes/mathjax.html</strong>.</p>

<p><strong>_includes/mathjax.html</strong>.</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html">{% if page.mathjax %}
<span class="nt">&lt;script </span><span class="na">type=</span><span class="s">"text/x-mathjax-config"</span><span class="nt">&gt;</span>
  <span class="nx">MathJax</span><span class="p">.</span><span class="nx">Hub</span><span class="p">.</span><span class="nx">Config</span><span class="p">({</span>
    <span class="na">tex2jax</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">inlineMath</span><span class="p">:</span> <span class="p">[</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">$</span><span class="dl">'</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="se">\\</span><span class="s2">(</span><span class="dl">"</span><span class="p">,</span><span class="dl">"</span><span class="se">\\</span><span class="s2">)</span><span class="dl">"</span><span class="p">]</span> <span class="p">],</span>
      <span class="na">processEscapes</span><span class="p">:</span> <span class="kc">true</span>
    <span class="p">}</span>
  <span class="p">});</span>
<span class="nt">&lt;/script&gt;</span>
<span class="nt">&lt;script
  </span><span class="na">type=</span><span class="s">"text/javascript"</span>
  <span class="na">charset=</span><span class="s">"utf-8"</span>
  <span class="na">src=</span><span class="s">"https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"</span>
<span class="nt">&gt;</span>
<span class="nt">&lt;/script&gt;</span>
<span class="nt">&lt;script
  </span><span class="na">type=</span><span class="s">"text/javascript"</span>
  <span class="na">charset=</span><span class="s">"utf-8"</span>
  <span class="na">src=</span><span class="s">"https://vincenttam.github.io/javascripts/MathJaxLocal.js"</span>
<span class="nt">&gt;</span>
<span class="nt">&lt;/script&gt;</span>
{% endif %}</code></pre></figure>

<p>Add the following line to the header in <strong>_layouts/post.html</strong> or anywhere else you want to use MathJax.</p>

<p><strong>_layouts/post.html</strong> partial listing</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html">{% include mathjax.html %}</code></pre></figure>

<p>Add the following line to the <a href="http://jekyllrb.com/docs/frontmatter/">YAML front matter</a> of a post to enable MathJax on a post by post basis.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">mathjax</span><span class="pi">:</span> <span class="no">true</span></code></pre></figure>

<p>For example, the front matter of this post looks like this.
Note that <a href="https://disqus.com">Disqus</a> comments have been added with the <a href="https://sgeos.github.io/jekyll/disqus/2016/02/14/adding-disqus-to-a-jekyll-blog.html">same strategy</a>.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="nn">---</span>
<span class="na">layout</span><span class="pi">:</span> <span class="s">post</span>
<span class="na">mathjax</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">comments</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">title</span><span class="pi">:</span>  <span class="s2">"</span><span class="s">Adding</span><span class="nv"> </span><span class="s">MathJax</span><span class="nv"> </span><span class="s">to</span><span class="nv"> </span><span class="s">a</span><span class="nv"> </span><span class="s">GitHub</span><span class="nv"> </span><span class="s">Pages</span><span class="nv"> </span><span class="s">Jekyll</span><span class="nv"> </span><span class="s">Blog"</span>
<span class="na">date</span><span class="pi">:</span>   <span class="s">2016-08-21 23:41:54 +0000</span>
<span class="na">categories</span><span class="pi">:</span> <span class="s">github jekyll</span>
<span class="nn">---</span></code></pre></figure>

<p>If all goes well, you should be able to use MathJax inline and display modes.
Note that the <a href="https://cdn.mathjax.org/mathjax/latest/test/sample-dynamic-2.html">MathJax dynamic preview</a> can be useful when formatting complex equations.</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html">In N-dimensional simplex noise, the squared kernel summation radius $r^2$ is $\frac 1 2$
for all values of N. This is because the edge length of the N-simplex $s = \sqrt {\frac {N} {N + 1}}$
divides out of the N-simplex height $h = s \sqrt {\frac {N + 1} {2N}}$.
The kerel summation radius $r$ is equal to the N-simplex height $h$.

$$ r = h = \sqrt{\frac {1} {2}} = \sqrt{\frac {N} {N+1}} \sqrt{\frac {N+1} {2N}} $$</code></pre></figure>

<p>In N-dimensional simplex noise, the squared kernel summation radius $r^2$ is $\frac 1 2$
for all values of N. This is because the edge length of the N-simplex $s = \sqrt {\frac {N} {N + 1}}$
divides out of the N-simplex height $h = s \sqrt {\frac {N + 1} {2N}}$.
The kerel summation radius $r$ is equal to the N-simplex height $h$.</p>

\[r = h = \sqrt{\frac {1} {2}} = \sqrt{\frac {N} {N+1}} \sqrt{\frac {N+1} {2N}}\]

<h2 id="references">References:</h2>

<ul>
  <li><a href="https://pages.github.com">GitHub Pages</a></li>
  <li><a href="https://jekyllrb.com">Jekyll</a></li>
  <li><a href="http://jekyllrb.com/docs/frontmatter/">Jekyll, YAML Front Matter</a></li>
  <li><a href="https://sgeos.github.io/jekyll/disqus/2016/02/14/adding-disqus-to-a-jekyll-blog.html">Jekyll, Adding Disqus to a Jekyll Blog</a></li>
  <li><a href="https://www.mathjax.org">MathJax</a></li>
  <li><a href="http://docs.mathjax.org/en/latest/configuration.html">MathJax, Loading and Configuring MathJax</a></li>
  <li><a href="https://cdn.mathjax.org/mathjax/latest/test/sample-dynamic-2.html">MathJax, Dynamic Preview</a></li>
  <li><a href="https://vincenttam.github.io/blog/2014/11/09/mathjax-local-configuration-file/">MathJax, Local Configuration File (Blog Post)</a></li>
  <li><a href="http://tex.stackexchange.com/questions/27633/mathjax-inline-mode-not-rendering">MathJax, Mathjax inline mode not rendering</a></li>
  <li><a href="http://stackoverflow.com/questions/34347818/using-mathjax-on-a-github-page">MathJax, Using MathJax on a Github Page?</a></li>
</ul>]]></content><author><name>Brendan Sechter</name></author><category term="github" /><category term="jekyll" /></entry><entry><title type="html">Adding Disqus to a Jekyll Blog</title><link href="https://sgeos.github.io/jekyll/disqus/2016/02/14/adding-disqus-to-a-jekyll-blog.html" rel="alternate" type="text/html" title="Adding Disqus to a Jekyll Blog" /><published>2016-02-14T20:56:57+00:00</published><updated>2016-02-14T20:56:57+00:00</updated><id>https://sgeos.github.io/jekyll/disqus/2016/02/14/adding-disqus-to-a-jekyll-blog</id><content type="html" xml:base="https://sgeos.github.io/jekyll/disqus/2016/02/14/adding-disqus-to-a-jekyll-blog.html"><![CDATA[<!-- A15 -->
<script>console.log("A15");</script>

<p>A <a href="https://jekyllrb.com">Jekyll</a> blog is not backed by a database.
Out of the box, there is no way for people to comment on or discuss blog posts.
<a href="https://disqus.com">Disqus</a> is a third party service that can be used to get around that limitation.
This post covers <a href="https://help.disqus.com/customer/portal/articles/472138-jekyll-installation-instructions">adding Disqus</a> to a <a href="https://jekyllrb.com">Jekyll</a> blog.</p>

<h2 id="software-versions">Software Versions</h2>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nv">$ </span><span class="nb">date
</span>February 15, 2016 at 05:56:57 PM JST
<span class="nv">$ </span><span class="nb">uname</span> <span class="nt">-vm</span>
FreeBSD 11.0-CURRENT <span class="c">#0 r287598: Thu Sep 10 14:45:48 JST 2015     root@:/usr/obj/usr/src/sys/MIRAGE_KERNEL  amd64</span>
<span class="nv">$ </span>ruby <span class="nt">--version</span>
ruby 2.1.8p440 <span class="o">(</span>2015-12-16 revision 53160<span class="o">)</span> <span class="o">[</span>amd64-freebsd11]
<span class="nv">$ </span>jekyll <span class="nt">--version</span>
jekyll 3.0.1</code></pre></figure>

<h2 id="instructions">Instructions</h2>

<p>First, <a href="https://sgeos.github.io/jekyll/github/freebsd/2016/01/07/creating-a-jekyll-github-pages-blog-and-managing-it-with-freebsd.html">install Jekyll</a> and <a href="https://disqus.com/admin/create/">register your site with Disqus</a>.</p>

<p>Add the following code to <strong>_includes/disqus.html</strong>.
Remember to change the <strong>this.page.url</strong> line to the URL of your blog.
The <strong>s.src</strong> line will need to point to your Disqus short name URL.
Consider copying the <a href="https://disqus.com/admin/universalcode/">Universal Embed Code directly from Disqus</a> instead of this post.</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html">{% if page.comments %}
<span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">"disqus_thread"</span><span class="nt">&gt;&lt;/div&gt;</span>
<span class="nt">&lt;script&gt;</span>
<span class="kd">var</span> <span class="nx">disqus_config</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">page</span><span class="p">.</span><span class="nx">url</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">http://BLOG.host.com{{ page.url }}</span><span class="dl">"</span><span class="p">;</span> <span class="c1">// </span><span class="o">&lt;---</span> <span class="nx">use</span> <span class="nx">canonical</span> <span class="nx">URL</span>
<span class="k">this</span><span class="p">.</span><span class="nx">page</span><span class="p">.</span><span class="nx">identifier</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">{{ page.id }}</span><span class="dl">"</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// DON'T EDIT BELOW THIS LINE</span>
<span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="nb">document</span><span class="p">,</span> <span class="nx">s</span> <span class="o">=</span> <span class="nx">d</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">script</span><span class="dl">'</span><span class="p">);</span>

<span class="nx">s</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">//SHORTNAME.disqus.com/embed.js</span><span class="dl">'</span><span class="p">;</span> <span class="c1">// </span><span class="o">&lt;---</span> <span class="nx">use</span> <span class="nx">Disqus</span> <span class="nx">shortname</span>

<span class="nx">s</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="dl">'</span><span class="s1">data-timestamp</span><span class="dl">'</span><span class="p">,</span> <span class="o">+</span><span class="k">new</span> <span class="nb">Date</span><span class="p">());</span>
<span class="p">(</span><span class="nx">d</span><span class="p">.</span><span class="nx">head</span> <span class="o">||</span> <span class="nx">d</span><span class="p">.</span><span class="nx">body</span><span class="p">).</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">s</span><span class="p">);</span>
<span class="p">})();</span>
<span class="nt">&lt;/script&gt;</span>
<span class="nt">&lt;noscript&gt;</span>Please enable JavaScript to view the <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"https://disqus.com/?ref_noscript"</span> <span class="na">rel=</span><span class="s">"nofollow"</span><span class="nt">&gt;</span>comments powered by Disqus.<span class="nt">&lt;/a&gt;&lt;/noscript&gt;</span>
{% endif %}</code></pre></figure>

<p>Add the following line to the end of <strong>_layouts/post.html</strong> or anywhere else you want to display comments.</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html">{% include disqus.html %}</code></pre></figure>

<p>Add the following line to the <a href="http://jekyllrb.com/docs/frontmatter/">YAML front matter</a> of a post to enable comments on a post by post basis.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="na">comments</span><span class="pi">:</span> <span class="no">true</span></code></pre></figure>

<p>For example, the front matter of this post looks like this.</p>

<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="nn">---</span>
<span class="na">layout</span><span class="pi">:</span> <span class="s">post</span>
<span class="na">comments</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">title</span><span class="pi">:</span>  <span class="s2">"</span><span class="s">Adding</span><span class="nv"> </span><span class="s">Disqus</span><span class="nv"> </span><span class="s">to</span><span class="nv"> </span><span class="s">a</span><span class="nv"> </span><span class="s">Jekyll</span><span class="nv"> </span><span class="s">Blog"</span>
<span class="na">date</span><span class="pi">:</span>   <span class="s">2016-02-15 05:56:57 +0900</span>
<span class="na">categories</span><span class="pi">:</span> <span class="s">jekyll disqus</span>
<span class="nn">---</span></code></pre></figure>

<p>Optionally, to facilitate displaying comment counts
add the following to <strong>_layouts/default.html</strong> before the closing <strong>body</strong> tag.
Change <strong>SHORTNAME</strong> to the Disqus shortname you are using.</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;script </span><span class="na">id=</span><span class="s">"dsq-count-scr"</span> <span class="na">src=</span><span class="s">"//SHORTNAME.disqus.com/count.js"</span> <span class="na">async</span><span class="nt">&gt;&lt;/script&gt;</span></code></pre></figure>

<p>Add <strong>#disqus_thread</strong> to the end of a URL and Disqus will count the comments on the page the link points to.
For example, my <strong>_layouts/post.html</strong> contains the following code.
Note the comment count at the top of this post.</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html">{% if page.comments %} • <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"https://sgeos.github.io{{ page.url }}#disqus_thread"</span><span class="nt">&gt;</span>0 Comments<span class="nt">&lt;/a&gt;</span>{% endif %}</code></pre></figure>

<p><strong>index.html</strong> contains the following code to display the comment count for each post in the list.</p>

<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"https://sgeos.github.io{{ post.url }}#disqus_thread"</span><span class="nt">&gt;</span>0 Comments<span class="nt">&lt;/a&gt;</span></code></pre></figure>

<p>Note that moving a post from <strong>_drafts/</strong> to <strong>_posts/</strong> may change the URL of the post.
This will cause any comments added to the draft to disappear.
The <a href="https://help.disqus.com/customer/portal/articles/286778-migration-tools">Disqus Migration Tools</a> can be used move comments to the new URL.</p>

<h2 id="references">References:</h2>
<ul>
  <li><a href="https://jekyllrb.com">Jekyll</a></li>
  <li><a href="http://jekyllrb.com/docs/variables/">Jekyll, Variables</a></li>
  <li><a href="http://jekyllrb.com/docs/templates/">Jekyll, Templates</a></li>
  <li><a href="http://jekyllrb.com/docs/frontmatter/">Jekyll, YAML Front Matter</a></li>
  <li><a href="http://tesoriere.com/2010/08/25/liquid-code-in-a-liquid-template-with-jekyll/">Jekyll, Highlighting Liquid Code in a Liquid Template with Jekyll (Escape a Liquid Templating Tag)</a></li>
  <li><a href="http://joshualande.com/jekyll-github-pages-poole/">Jekyll, How I Created a Beautiful and Minimal Blog Using Jekyll, Github Pages, and poole</a></li>
  <li><a href="http://stackoverflow.com/questions/22725754/dynamic-links-in-jekyll">Jekyll, Dynamic Links in jekyll</a></li>
  <li><a href="https://sgeos.github.io/jekyll/github/freebsd/2016/01/07/creating-a-jekyll-github-pages-blog-and-managing-it-with-freebsd.html">Jekyll, Creating A Jekyll GitHub Pages Blog and Managing it With FreeBSD</a></li>
  <li><a href="https://disqus.com">Disqus</a></li>
  <li><a href="https://disqus.com/admin/create/">Disqus, Set Up Disqus On a New Site</a></li>
  <li><a href="https://disqus.com/admin/universalcode/">Disqus, Universal Embed Code</a></li>
  <li><a href="https://help.disqus.com/customer/portal/articles/472138-jekyll-installation-instructions">Disqus, Jekyll Installation Instructions</a></li>
  <li><a href="https://help.disqus.com/customer/en/portal/articles/2158629">Disqus, Use Configuration Variables to Avoid Split Threads and “Missing” Comments</a></li>
  <li><a href="https://help.disqus.com/customer/portal/articles/286778-migration-tools">Disqus, Migration Tools</a></li>
  <li><a href="http://www.perfectlyrandom.org/2014/06/29/adding-disqus-to-your-jekyll-powered-github-pages/">Disqus, Adding Disqus to your Jekyll</a></li>
  <li><a href="http://blog.pzheng.me/2014/07/03/Jekyll-Notes/">Disqus, Jekyll Notes</a></li>
  <li><a href="http://haacked.com/archive/2013/12/09/preserving-disqus-comments-with-jekyll/">Disqus, Preserve Disqus Comments with Jekyll</a></li>
  <li><a href="https://support.google.com/webmasters/answer/139066?hl=en">Google, Use canonical URLs</a></li>
</ul>]]></content><author><name>Brendan Sechter</name></author><category term="jekyll" /><category term="disqus" /></entry><entry><title type="html">UNIX ARM Assembler on Android</title><link href="https://sgeos.github.io/jekyll/github/freebsd/2016/01/07/unix-arm-assembler-on-android.html" rel="alternate" type="text/html" title="UNIX ARM Assembler on Android" /><published>2016-01-07T22:12:57+00:00</published><updated>2016-01-07T22:12:57+00:00</updated><id>https://sgeos.github.io/jekyll/github/freebsd/2016/01/07/unix-arm-assembler-on-android</id><content type="html" xml:base="https://sgeos.github.io/jekyll/github/freebsd/2016/01/07/unix-arm-assembler-on-android.html"><![CDATA[<!-- A3 -->
<script>console.log("A3");</script>

<p>Months ago, someone on the FreeBSD forums <a href="https://forums.freebsd.org/threads/assembly-simple-hello-world.53274/#post-299410">wanted help</a> getting an assebly language program running on a 64 bit intel machine.  I read through the <a href="https://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/x86.html">FreeBSD Developers’ Handbook x86 Assembly Language Programming section</a>, and sure enough the 32 bit examples did not work.  x86 and x86-64 assembler are just plain different.  Also, the <a href="https://en.wikipedia.org/wiki/Application_binary_interface">ABI</a> is completely different.</p>

<p>I managed to find an <a href="https://thebrownnotebook.wordpress.com/2009/10/27/native-64-bit-hello-world-with-nasm-on-freebsd/">x86-64 hello world example for FreeBSD</a>.  The environment works.  Great!  Now what?  The problem with hello world examples is that there is no input.  Without knowing where to go next, a hello world example is not very useful.  Between the <a href="https://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/x86.html">Developer’s Handbook</a>, the <a href="http://x86-64.org/documentation/abi.pdf">System V AMD64 ABI Reference</a> and an x86-64 tutorial (that has since disappeared) I managed to write a command line utility in x86-64 ASM that processes command line arguments.</p>

<p>Then I thought back to the days when I wrote ARM assembler for the Gameboy Advance and Nintendo DS and wanted to write a command line UNIX utility in ARM assembler.  My Raspberry Pi was halfway around the world at the time, but my Android phone was handy.  No FreeBSD on my phone, but a few people had written hello world examples for android <a href="http://www.amccormack.net/2012-11-03-getting-started-arm-assembly-for-android.html">(1)</a> <a href="http://www.androidpentesting.com/2014/01/arm-assembly-part-3-hello-world-in-arm.html">(2)</a> <a href="http://peterdn.com/post/e28098Hello-World!e28099-in-ARM-assembly.aspx">(3)</a>.  FreeBSD and Linux appear to use the same ARM EABI documented on the <a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html">ARM site</a>.  Also, Android’s bionic C libaray has a <a href="https://mail-index.netbsd.org/tech-userlevel/2012/07/25/msg006571.html">lot of BSD in it</a>.</p>

<p>The <a href="https://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/x86.html">Developer’s Handbook</a> notes that “Assembly language programming under UNIX® is highly undocumented”.  I am writing this post to document writing a command line UNIX application in assembler that conforms to the ARM EABI.  Specifically, this application will run on Android.  Remember, there has never been an easier time to learn assembler!</p>

<p>My GitHub repository for this project can be found <a href="https://github.com/Sennue/AndroidARM">here</a>.  Please note that manually linking object files is probably not standard Android NDK usage.  The build instructions may break in the future.  If that happens, good luck figuring the necessary flags to build the examples.  =)</p>

<h2 id="software-versions">Software Versions</h2>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nv">$ </span><span class="nb">date
</span>January  8, 2016 at 11:32:13 AM JST
<span class="nv">$ </span><span class="nb">uname</span> <span class="nt">-a</span>
Darwin siderite.local 15.2.0 Darwin Kernel Version 15.2.0: Fri Nov 13 19:56:56 PST 2015<span class="p">;</span> root:xnu-3248.20.55~2/RELEASE_X86_64 x86_64
<span class="nv">$ </span>adb version
Android Debug Bridge version 1.0.32
<span class="nv">$ $ANDROID_NDK_STANDALONE_TOOLCHAIN</span>/bin/clang <span class="nt">--version</span>
clang version 3.6 
Target: armv5te-none-linux-androideabi
Thread model: posix
<span class="nv">$ $ANDROID_NDK_STANDALONE_TOOLCHAIN</span>/bin/arm-linux-androideabi-as <span class="nt">--version</span>
GNU assembler <span class="o">(</span>GNU Binutils<span class="o">)</span> 2.24.90
This assembler was configured <span class="k">for </span>a target of <span class="sb">`</span>arm-linux-androideabi<span class="s1">'.
$ $ANDROID_NDK_STANDALONE_TOOLCHAIN/bin/arm-linux-androideabi-ld --version
GNU gold (GNU Binutils 2.24.90) 1.11
$ $ANDROID_NDK_STANDALONE_TOOLCHAIN/bin/arm-linux-androideabi-gdb --version
GNU gdb (GDB) 7.7
This GDB was configured as "--host=x86_64-apple-darwin --target=arm-linux-android".
$ adb shell "uname -a" # Nexus 5; Cyanogenmod CM-13.0-20160108-NIGHTLY; Android 6.0.1
Linux localhost 3.4.0-cyanogenmod-g9e39333 #1 SMP PREEMPT Wed Jan 6 19:02:34 PST 2016 armv7l
$ adb shell "toybox --version" # for chmod; busybox will work
ac4365b3c292-android</span></code></pre></figure>

<h2 id="instructions">Instructions</h2>
<p>First, install the <a href="http://developer.android.com/sdk/installing/index.html">Android SDK</a> and <a href="http://developer.android.com/tools/sdk/ndk/index.html">Android NDK</a>.  Make sure <a href="http://developer.android.com/tools/help/adb.html">ADB</a> has been installed and you connect to your test device.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nv">$ </span>adb devices
List of devices attached 
071f7b2ef0e95581	device

<span class="nv">$ </span>adb shell <span class="s2">"uname"</span>
Linux</code></pre></figure>

<p>A rooted device is required to run ASM programs on Android with these instructions.  Running ADB as root is handy.  You will need chmod, so you will need to install busybox or some other box that provides the same functionality.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nv">$ </span>adb root
restarting adbd as root
<span class="nv">$ </span>adb shell <span class="s2">"chmod +x /root/does_not_exist"</span>
<span class="nb">chmod</span>: /root/does_not_exist: No such file or directory</code></pre></figure>

<p>Next, install the <a href="https://developer.android.com/ndk/guides/standalone_toolchain.html">Android NDK standalone toolchain</a>.  The sysroot path probably needs to be defined.  Also adding paths for the SDK, NDK and the to be generated standalone NDK is a good idea.  I added these lines to my .profile.  Adjust pathnames as necessary.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nb">export </span><span class="nv">ANDROID_SDK</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/android-sdk"</span>
<span class="nb">export </span><span class="nv">ANDROID_NDK</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/android-ndk"</span>
<span class="nb">export </span><span class="nv">ANDROID_NDK_STANDALONE_TOOLCHAIN</span><span class="o">=</span><span class="s2">"</span><span class="nv">$HOME</span><span class="s2">/android-ndk-standalone-toolchain"</span>
<span class="nb">export </span><span class="nv">SYSROOT</span><span class="o">=</span><span class="s2">"</span><span class="nv">$ANDROID_NDK_STANDALONE_TOOLCHAIN</span><span class="s2">/sysroot"</span>
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="s2">"</span><span class="nv">$ANDROID_SDK</span><span class="s2">/tools:</span><span class="nv">$ANDROID_SDK</span><span class="s2">/platform-tools:</span><span class="nv">$ANDROID_NDK_STANDALONE_TOOLCHAIN</span><span class="s2">/bin:</span><span class="nv">$PATH</span><span class="s2">"</span></code></pre></figure>

<p>Next, reload .profile and  generate the standalone toolchain.  The <a href="https://developer.android.com/ndk/guides/standalone_toolchain.html">Android NDK standalone toolchain</a> page has instructions for targetting different architectures and <a href="https://developer.android.com/guide/topics/manifest/uses-sdk-element.html">Android versions</a>.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nb">.</span> .profile
<span class="nv">$ANDROID_NDK</span>/build/tools/make-standalone-toolchain.sh <span class="se">\</span>
  <span class="nt">--toolchain</span><span class="o">=</span>arm-linux-androideabi-clang3.6 <span class="se">\</span>
  <span class="nt">--install-dir</span><span class="o">=</span><span class="nv">$ANDROID_NDK_STANDALONE_TOOLCHAIN</span></code></pre></figure>

<p>64 bit ARM devices use aarch64 instead of arm.  The following commands may be useful when trying to figure out the architecture of your device.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh">adb shell <span class="s2">"getprop ro.product.cpu.abi"</span>
adb shell <span class="s2">"getprop ro.product.cpu.abi2"</span></code></pre></figure>

<p>The first program to build and run is a hello world example written in C.  In general, it is generally a good idea to have a working C implementation before writing anything in ASM.</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="c1">// main.c</span>
<span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">printf</span><span class="p">(</span><span class="s">"Hello, World! [C]</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>Build it with the following commands.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nv">CRT</span><span class="o">=</span><span class="s2">"</span><span class="nv">$SYSROOT</span><span class="s2">/usr/lib/crtbegin_dynamic.o </span><span class="nv">$SYSROOT</span><span class="s2">/usr/lib/crtend_android.o"</span>
<span class="nv">$ANDROID_NDK_STANDALONE_TOOLCHAIN</span>/bin/clang <span class="nt">--sysroot</span><span class="o">=</span><span class="nv">$SYSROOT</span> <span class="nt">-fPIE</span> <span class="nt">-DANDROID</span> <span class="nt">-g</span> <span class="nt">-c</span> main.c <span class="nt">-o</span> main.o 
<span class="nv">$ANDROID_NDK_STANDALONE_TOOLCHAIN</span>/bin/arm-linux-androideabi-ld <span class="nt">--sysroot</span><span class="o">=</span><span class="nv">$SYSROOT</span> <span class="nt">-pie</span> <span class="nt">--dynamic-linker</span><span class="o">=</span>/system/bin/linker main.o <span class="nv">$CRT</span> <span class="nt">-o</span> c-hello-world <span class="nt">-lc</span></code></pre></figure>

<p>This is a funny way of building a C program.  What is going on?  The end goal is to build and run assembler programs.  Assembly files need to run through the assebler and the linker.  In order to link ASM object files with C object files all object files need to be manually linked.  The entry point to a C program is main, but the program really takes control in the _start function.  The CRT files contain this _start function.  It has all of the setup code for the “C runtime”.  This code zeros memory and does other boilerplate tasks.  Your compiler usually includes the C runtime automatically so you do not need to think about it.  The -lc flag links the standard C library.  This is another step your compiler usually handles automatically.</p>

<p>Running the program on the phone should print “Hello, World! [C]”.  This will remount the system partition of your phone in read write mode.  If you do not know what that means stop reading and do not proceed.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh">adb root
adb remount
adb shell <span class="s2">"mkdir /system/test"</span>
adb push c-hello-world /system/test
adb shell <span class="s2">"chmod +x /system/test/c-hello-world"</span>
adb shell /system/test/c-hello-world</code></pre></figure>

<p>With the C version working, it is time to rewrite the program in ARM ASM.  Let us start with a header that defines <a href="https://code.google.com/p/android-source-browsing/source/browse/libc/SYSCALLS.TXT?repo=platform--bionic&amp;r=cd15bacf334ab254a5f61c3bba100adde1b6b80a">Android system calls</a>.</p>

<figure class="highlight"><pre><code class="language-asm" data-lang="asm">@ system.inc
@ Android Syscall Reference https://code.google.com/p/android-source-browsing/source/browse/libc/SYSCALLS.TXT?repo=platform--bionic&amp;r=cd15bacf334ab254a5f61c3bba100adde1b6b80a

.set stdin,  0
.set stdout, 1
.set stderr, 2

.set SYS_nosys, 0
.set SYS_exit,  1
.set SYS_fork,  2
.set SYS_read,  3
.set SYS_write, 4
.set SYS_open,  5
.set SYS_close, 6

.macro sys.syscall id
	mov	r7, \id
	swi	$0
.endm

.macro sys.exit
	sys.syscall $SYS_exit
.endm

.macro sys.fork
	sys.syscall $SYS_fork
.endm

.macro sys.read
	sys.syscall $SYS_read
.endm

.macro sys.write
	sys.syscall $SYS_write
.endm

.macro sys.open
	sys.syscall $SYS_open
.endm

.macro sys.close
	sys.syscall $SYS_close
.endm</code></pre></figure>

<p>Next, the main assembler file.</p>

<figure class="highlight"><pre><code class="language-asm" data-lang="asm">@ start.s
.include "system.inc"
	.syntax unified
	.set ALIGNMENT,8

.text
	.align ALIGNMENT
	.global _start
_start:
	nop @ for gbd breakpoint

	@ Hello World
	@ sys.write(stdout, message, length)
	mov	r0,$stdout
	adr	r1,message
	mov	r2,$length
	sys.write

	@ sys.exit(0)
	mov	r0,$0
	sys.exit

@ Data needs to be in .text for PIE
@.data
message:
	.asciz "Hello, World! [ASM]\n"
length = . - message
	.align ALIGNMENT</code></pre></figure>

<p>The next step is building the ASM version.</p>

<figure class="highlight"><pre><code class="language-asm" data-lang="asm">$ANDROID_NDK_STANDALONE_TOOLCHAIN/bin/arm-linux-androideabi-as --gdwarf2 start.s -o start.o
$ANDROID_NDK_STANDALONE_TOOLCHAIN/bin/arm-linux-androideabi-ld --sysroot=$SYSROOT -pie --dynamic-linker=/system/bin/linker start.o -o asm-hello-world</code></pre></figure>

<p>The start.s file contains a start function, so the C runtime is not necessary.  Functions from the C library can be called from assebler, but this function is using system calls, so -lc is not necessary.</p>

<p>Running it on the phone should print “Hello, World! [ASM]”.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh">adb push asm-hello-world /system/test
adb shell <span class="s2">"chmod +x /system/test/asm-hello-world"</span>
adb shell /system/test/asm-hello-world</code></pre></figure>

<p>A Makefile for the hello world project looks like this.</p>

<figure class="highlight"><pre><code class="language-make" data-lang="make"><span class="nv">TOOLCHAIN</span><span class="o">=</span><span class="nv">$(ANDROID_NDK_STANDALONE_TOOLCHAIN)</span>
<span class="nv">SYSROOT</span><span class="o">=</span><span class="nv">$(TOOLCHAIN)</span>/sysroot
<span class="nv">CC</span><span class="o">=</span><span class="nv">$(TOOLCHAIN)</span>/bin/clang <span class="nt">--sysroot</span><span class="o">=</span><span class="nv">$(SYSROOT)</span>
<span class="nv">AS</span><span class="o">=</span><span class="nv">$(TOOLCHAIN)</span>/bin/arm-linux-androideabi-as
<span class="nv">LD</span><span class="o">=</span><span class="nv">$(TOOLCHAIN)</span>/bin/arm-linux-androideabi-ld <span class="nt">--sysroot</span><span class="o">=</span><span class="nv">$(SYSROOT)</span>
<span class="nv">CRT</span><span class="o">=</span><span class="nv">$(SYSROOT)</span>/usr/lib/crtbegin_dynamic.o <span class="nv">$(SYSROOT)</span>/usr/lib/crtend_android.o
<span class="nv">INSTALL</span><span class="o">=</span>/system/test

<span class="nv">CFLAGS</span><span class="o">=</span><span class="nt">-fPIE</span> <span class="nt">-DANDROID</span> <span class="nt">-g</span>
<span class="nv">ASFLAGS</span><span class="o">=</span><span class="nt">--gdwarf2</span>
<span class="nv">LDFLAGS</span><span class="o">=</span><span class="nt">-pie</span> <span class="nt">--dynamic-linker</span><span class="o">=</span>/system/bin/linker

<span class="nv">ASM_TARGET</span><span class="o">=</span>asm-hello-world
<span class="nv">ASM_PARAM</span><span class="o">=</span>
<span class="nv">ASM_DEPS</span><span class="o">=</span>system.inc
<span class="nv">ASM_OBJ</span><span class="o">=</span>start.o
<span class="nv">ASM_LIBS</span><span class="o">=</span>

<span class="nv">C_TARGET</span><span class="o">=</span>c-hello-world
<span class="nv">C_PARAM</span><span class="o">=</span>
<span class="nv">C_DEPS</span><span class="o">=</span>
<span class="nv">C_OBJ</span><span class="o">=</span>main.o <span class="nv">$(CRT)</span>
<span class="nv">C_LIBS</span><span class="o">=</span><span class="nt">-lc</span>

<span class="nl">all</span><span class="o">:</span> <span class="nf">$(ASM_TARGET) $(C_TARGET)</span>

<span class="nl">force</span><span class="o">:</span> <span class="nf">clean all</span>

<span class="nl">$(C_TARGET)</span><span class="o">:</span> <span class="nf">$(C_OBJ)</span>
	<span class="nv">$(LD)</span> <span class="nv">$(LDFLAGS)</span> <span class="nv">$^</span> <span class="nt">-o</span> <span class="nv">$@</span> <span class="nv">$(C_LIBS)</span>

<span class="nl">$(ASM_TARGET)</span><span class="o">:</span> <span class="nf">$(ASM_OBJ)</span>
	<span class="nv">$(LD)</span> <span class="nv">$(LDFLAGS)</span> <span class="nv">$^</span> <span class="nt">-o</span> <span class="nv">$@</span> <span class="nv">$(ASM_LIBS)</span>

<span class="nl">%.o</span><span class="o">:</span> <span class="nf">%.c $(C_DEPS)</span>
	<span class="nv">$(CC)</span> <span class="nv">$(CFLAGS)</span> <span class="nt">-c</span> <span class="nv">$&lt;</span> <span class="nt">-o</span> <span class="nv">$@</span>

<span class="nl">%.o</span><span class="o">:</span> <span class="nf">%.s $(ASM_DEPS)</span>
	<span class="nv">$(AS)</span> <span class="nv">$(ASFLAGS)</span> <span class="nv">$&lt;</span> <span class="nt">-o</span> <span class="nv">$@</span>

<span class="nl">install</span><span class="o">:</span> <span class="nf">all</span>
	adb root
	adb remount
	adb shell <span class="s2">"mkdir </span><span class="nv">$(INSTALL)</span><span class="s2">"</span>
	adb push <span class="nv">$(ASM_TARGET)</span> <span class="nv">$(INSTALL)</span>
	adb push <span class="nv">$(C_TARGET)</span> <span class="nv">$(INSTALL)</span>
	adb shell <span class="s2">"chmod +x </span><span class="nv">$(INSTALL)</span><span class="s2">/</span><span class="nv">$(ASM_TARGET)</span><span class="s2"> </span><span class="nv">$(INSTALL)</span><span class="s2">/</span><span class="nv">$(C_TARGET)</span><span class="s2">"</span>

<span class="nl">uninstall</span><span class="o">:</span>
	adb root
	adb remount
	adb shell <span class="s2">"mkdir </span><span class="nv">$(INSTALL)</span><span class="s2">"</span>
	adb shell <span class="s2">"rm -rf </span><span class="nv">$(INSTALL)</span><span class="s2">/</span><span class="nv">$(ASM_TARGET)</span><span class="s2"> </span><span class="nv">$(INSTALL)</span><span class="s2">/</span><span class="nv">$(C_TARGET)</span><span class="s2">"</span>
	adb shell <span class="s2">"rmdir </span><span class="nv">$(INSTALL)</span><span class="s2">"</span>

<span class="nl">test</span><span class="o">:</span>
	adb root
	adb shell <span class="s2">"</span><span class="nv">$(INSTALL)</span><span class="s2">/</span><span class="nv">$(ASM_TARGET)</span><span class="s2"> </span><span class="nv">$(ASM_PARAM)</span><span class="s2"> &amp;&amp; </span><span class="nv">$(INSTALL)</span><span class="s2">/</span><span class="nv">$(C_TARGET)</span><span class="s2"> </span><span class="nv">$(C_PARAM)</span><span class="s2">"</span>

<span class="nl">clean</span><span class="o">:</span>
	<span class="nb">rm</span> <span class="nt">-rf</span> <span class="nv">$(ASM_TARGET)</span> <span class="nv">$(C_TARGET)</span> <span class="k">*</span>.o</code></pre></figure>

<p>The next program will echo all of the command line arguments.  This is the C source code:</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="c1">// main.c</span>
<span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;sys/syscall.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp">
</span>
<span class="c1">// newer NDK removed SYS macros</span>
<span class="cp">#ifndef SYS_exit
</span>  <span class="cp">#define SYS_exit __NR_exit
#endif
#ifndef SYS_write
</span>  <span class="cp">#define SYS_write __NR_write
#endif
</span>
<span class="cp">#define BUFFER_SIZE  2048
#define MESSAGE      "Args: [C]\n"
</span>
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="n">BUFFER_SIZE</span><span class="p">];</span>

<span class="k">const</span> <span class="kt">char</span> <span class="n">message</span><span class="p">[]</span> <span class="o">=</span> <span class="n">MESSAGE</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">int</span>  <span class="n">length</span>    <span class="o">=</span> <span class="k">sizeof</span> <span class="n">MESSAGE</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// sizeof inclues \0</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">**</span> <span class="n">argv</span><span class="p">)</span>
<span class="p">{</span>
  <span class="c1">// write message</span>
  <span class="n">syscall</span><span class="p">(</span><span class="n">SYS_write</span><span class="p">,</span> <span class="n">STDOUT_FILENO</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">length</span><span class="p">);</span>

  <span class="c1">// loop over argv until argvn_ptr is null</span>
  <span class="kt">char</span> <span class="o">*</span><span class="n">argvn_ptr</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">argv</span><span class="o">++</span><span class="p">);</span>
  <span class="k">while</span> <span class="p">(</span><span class="nb">NULL</span> <span class="o">!=</span> <span class="n">argvn_ptr</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">char</span> <span class="o">*</span><span class="n">buffer_ptr</span> <span class="o">=</span> <span class="n">buffer</span><span class="p">;</span>
    <span class="c1">// copy from argvn_ptr to buffer_ptr until \0 is encountered</span>
    <span class="k">while</span> <span class="p">(</span><span class="sc">'\0'</span> <span class="o">!=</span> <span class="o">*</span><span class="n">argvn_ptr</span><span class="p">)</span> <span class="p">{</span>
      <span class="o">*</span><span class="p">(</span><span class="n">buffer_ptr</span><span class="o">++</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">argvn_ptr</span><span class="o">++</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="c1">// append \n and write buffer</span>
    <span class="o">*</span><span class="n">buffer_ptr</span><span class="o">++</span> <span class="o">=</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="n">syscall</span><span class="p">(</span><span class="n">SYS_write</span><span class="p">,</span> <span class="n">STDOUT_FILENO</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">buffer_ptr</span> <span class="o">-</span> <span class="n">buffer</span><span class="p">);</span>
    <span class="c1">// next arg</span>
    <span class="n">argvn_ptr</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">argv</span><span class="o">++</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="c1">// done</span>
  <span class="n">syscall</span><span class="p">(</span><span class="n">SYS_exit</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>This is probably not what you expected to see.  To be fair, the first version looped over argv and used printf.  The C version is, however, supposed to be a C representation of the ASM.  This version of C main uses the same algorithm as the following ASM.  The following start.s uses the same system.inc.</p>

<figure class="highlight"><pre><code class="language-asm" data-lang="asm">@ start.s
.include "system.inc"
        .syntax unified
	.set ALIGNMENT,8
	.set BUFFER_SIZE,2048

.bss
	.comm buffer,BUFFER_SIZE,ALIGNMENT

.text
	.align ALIGNMENT
        .global _start
_start:
	nop @ for gbd breakpoint

	@ Intro Message
	@ sys.write(stdout, message, length)
	mov	r0,$stdout
	adr	r1,message
	mov	r2,$length
	sys.write

	@ Load Buffer via Global Offset Table
	ldr	r0,.Lgot	@ got_ptr = &amp;GOT - X
	add	r0,r0,pc	@ got_ptr += X
	ldr	r4,.Lbuffer	@ buffer_offset
.Lpie0:	ldr	r4,[r4,r0]	@ buffer = *(got_ptr+buffer_offset)

	@ Write Args
	pop	{r0,r1}	@ pop argc, argvn_ptr = argv[0]
proc_arg:
	teq	r1,$0	@ if NULL != argvn_ptr
	beq	done
	mov	r2,r4	@ buffer_ptr = buffer
copy_char:
	ldrb	r0,[r1],$1	@ c = *argv_ptr++
	teq	r0,$0
	beq	output
	strb	r0,[r2],$1	@ *buffer_ptr++ = c
	b	copy_char
output:
	mov	r0,$0x0A	@ c = '\n'
	strb	r0,[r2],$1	@ *buffer_ptr++ = '\n'
	mov	r0,$stdout
	mov	r1,r4		@ buffer
	sub	r2,r2,r1	@ length = buffer - buffer_ptr
	sys.write
	pop	{r1}	@ argv_ptr = argv[n]
	b	proc_arg
done:
	@ sys.exit(0)
	mov	r0,$0
	sys.exit

@ Data needs to be in .text for PIE
@.data
message:
        .asciz "Args: [ASM]\n"
length = . - message
	.align ALIGNMENT

	@ Global Offset Table
.Lgot:
	.long	_GLOBAL_OFFSET_TABLE_-.Lpie0
.Lbuffer:
	.word	buffer(GOT)
	.align ALIGNMENT</code></pre></figure>

<p>The Makefile is more or less the same, but it has these changes.</p>

<figure class="highlight"><pre><code class="language-make" data-lang="make"><span class="nv">ASM_TARGET</span><span class="o">=</span>asm-arg-echo
<span class="nv">ASM_PARAM</span><span class="o">=</span>1 2
<span class="nv">ASM_DEPS</span><span class="o">=</span>system.inc
<span class="nv">ASM_OBJ</span><span class="o">=</span>start.o
<span class="nv">ASM_LIBS</span><span class="o">=</span>

<span class="nv">C_TARGET</span><span class="o">=</span>c-arg-echo
<span class="nv">C_PARAM</span><span class="o">=</span>1 2
<span class="nv">C_DEPS</span><span class="o">=</span>
<span class="nv">C_OBJ</span><span class="o">=</span>main.o <span class="nv">$(CRT)</span>
<span class="nv">C_LIBS</span><span class="o">=</span><span class="nt">-lc</span></code></pre></figure>

<p>Build and test both versions with the following commands.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh">make all
make <span class="nb">install
</span>make <span class="nb">test</span></code></pre></figure>

<p>The output should be as follows:</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nv">$ </span>make <span class="nb">test
</span>adb shell <span class="s2">"/system/test/asm-arg-echo 1 2 &amp;&amp; /system/test/c-arg-echo 1 2"</span>
Args: <span class="o">[</span>ASM]
/data/data/test/asm-arg-echo
1
2
Args: <span class="o">[</span>C]
/data/data/test/c-arg-echo
1
2</code></pre></figure>

<p>The programs can be uninstalled as follows.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh">make uninstall</code></pre></figure>

<p>The <a href="https://github.com/Sennue/AndroidARM">GitHub repository</a> has six projects.  The <a href="https://github.com/Sennue/AndroidARM/tree/master/hello_world">hello world</a> and <a href="https://github.com/Sennue/AndroidARM/tree/master/arg_echo">arg_echo</a> projects are listed above.  There are a couple more versions of hello world.  The <a href="https://github.com/Sennue/AndroidARM/tree/master/puts_hello_world">puts_hello_world</a> project links to libc and replaces the system call with puts().  The <a href="https://github.com/Sennue/AndroidARM/tree/master/main_hello_world">main_hello_world</a> project goes a step furthur and uses an ASM main function and the CRT instead of a _start function.  The <a href="https://github.com/Sennue/AndroidARM/tree/master/interoperate">interoperate</a> project calls C, ASM and inline ASM from both C and ASM.  The <a href="https://github.com/Sennue/AndroidARM/tree/master/arg_sort">arg_sort</a> project uses structs and malloc to sort command line arguments with a binary tree.  The GitHub Makefiles have targets for working with GDB.  <a href="https://github.com/Sennue/AndroidARM/blob/master/NOTES.txt">NOTES.txt</a> contains project notes and references.</p>

<h2 id="todo">Todo</h2>
<ul>
  <li>EABI command line arguments (kind of pushed on the stack; _start and main are different) (EABI post?)</li>
  <li>EABI function calls (first few parameters in registers, everything else on the stack) (EABI post?)</li>
  <li>Position independent code / Global offset table / Procedure linkage table (probably another post)</li>
  <li>GDB (probably another post)</li>
  <li>Work more references into post</li>
</ul>

<h2 id="references">References:</h2>
<ul>
  <li><a href="https://github.com/Sennue/AndroidARM">Android ASM GitHub Main Project Page</a></li>
  <li><a href="https://github.com/Sennue/AndroidARM/blob/master/NOTES.txt">Android ASM GitHub Project Notes</a></li>
  <li><a href="https://github.com/Sennue/AndroidARM/tree/master/hello_world">Android ASM GitHub hello_world Project</a></li>
  <li><a href="https://github.com/Sennue/AndroidARM/tree/master/arg_echo">Android ASM GitHub arg_echo Project</a></li>
  <li><a href="https://github.com/Sennue/AndroidARM/tree/master/puts_hello_world">Android ASM GitHub puts_hello_world Project</a></li>
  <li><a href="https://github.com/Sennue/AndroidARM/tree/master/main_hello_world">Android ASM GitHub main_hello_world Project</a></li>
  <li><a href="https://github.com/Sennue/AndroidARM/tree/master/interoperate">Android ASM GitHub interoperate Project</a></li>
  <li><a href="https://github.com/Sennue/AndroidARM/tree/master/arg_sort">Android ASM GitHub arg_sort Project</a></li>
  <li><a href="http://developer.android.com/sdk/installing/index.html">Android SDK</a></li>
  <li><a href="http://developer.android.com/tools/sdk/ndk/index.html">Android NDK</a></li>
  <li><a href="https://developer.android.com/ndk/guides/standalone_toolchain.html">Android NDK Standalone Toolchain</a></li>
  <li><a href="https://developer.android.com/guide/topics/manifest/uses-sdk-element.html">Android Version to API Level</a></li>
  <li><a href="http://developer.android.com/tools/help/adb.html">Android Debug Bridge</a></li>
  <li><a href="https://code.google.com/p/android-source-browsing/source/browse/libc/SYSCALLS.TXT?repo=platform--bionic&amp;r=cd15bacf334ab254a5f61c3bba100adde1b6b80a">Android Syscall Reference</a></li>
  <li><a href="https://mail-index.netbsd.org/tech-userlevel/2012/07/25/msg006571.html">Android, getting bionic C library back in sync with upstream</a></li>
  <li><a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html">ARM EABI Documentation</a></li>
  <li><a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0473c/CJAJBFHC.html">ARM Predeclared Core Register Names</a></li>
  <li><a href="http://www.amccormack.net/2012-11-03-getting-started-arm-assembly-for-android.html">ARM, Getting Started: ARM Assembly for Android</a></li>
  <li><a href="http://www.androidpentesting.com/2014/01/arm-assembly-part-3-hello-world-in-arm.html">ARM Assembly Part 3 - “Hello world” in ARM assembly</a></li>
  <li><a href="http://peterdn.com/post/e28098Hello-World!e28099-in-ARM-assembly.aspx">ARM, ‘Hello World!’ in ARM assembly</a></li>
  <li><a href="http://www.peter-cockerell.net/aalp/html/ch-3.html">ARM AALP: 3. The Instruction Set</a></li>
  <li><a href="http://www.coranac.com/tonc/text/asm.htm">ARM, Whirlwind Tour</a></li>
  <li><a href="http://www.sokoide.com/wp/2015/06/14/learning-arm-assembly-basics/">ARM, Learning Assembly Basics</a></li>
  <li><a href="https://sourceware.org/ml/binutils/2014-02/msg00157.html">ARM position-independent code in Gas</a></li>
  <li><a href="http://www.airs.com/blog/archives/41">ARM, Shared Libraries</a></li>
  <li><a href="http://web.mit.edu/gnu/doc/html/as_7.html">GAS, Assembler Directives</a></li>
  <li><a href="https://blackfin.uclinux.org/doku.php?id=toolchain:gas:structs">GAS, Working with C structures and GAS</a></li>
  <li><a href="https://mhandroid.wordpress.com/2011/01/25/how-cc-debugging-works-on-android/">GDB, How C/C++ Debugging Works on Android</a></li>
  <li><a href="https://github.com/mapbox/mapbox-gl-native/wiki/Android-debugging-with-remote-GDB">GDB, Android debugging with remote GDB</a></li>
  <li><a href="https://forums.freebsd.org/threads/assembly-simple-hello-world.53274/#post-299410">FreeBSD Forums: Assembly - simple Hello World</a></li>
  <li><a href="https://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/x86.html">FreeBSD Developers’ Handbook: x86 Assembly Language Programming section</a></li>
  <li><a href="https://thebrownnotebook.wordpress.com/2009/10/27/native-64-bit-hello-world-with-nasm-on-freebsd/">FreeBSD x86-64 Hello World</a></li>
  <li><a href="http://x86-64.org/documentation/abi.pdf">System V AMD64 ABI Reference</a></li>
  <li><a href="https://en.wikipedia.org/wiki/Application_binary_interface">Wikipedia: Application Binary Interface</a></li>
</ul>]]></content><author><name>Brendan Sechter</name></author><category term="jekyll" /><category term="github" /><category term="freebsd" /></entry><entry><title type="html">Creating A Jekyll GitHub Pages Blog and Managing it With FreeBSD</title><link href="https://sgeos.github.io/jekyll/github/freebsd/2016/01/07/creating-a-jekyll-github-pages-blog-and-managing-it-with-freebsd.html" rel="alternate" type="text/html" title="Creating A Jekyll GitHub Pages Blog and Managing it With FreeBSD" /><published>2016-01-07T18:07:15+00:00</published><updated>2016-01-07T18:07:15+00:00</updated><id>https://sgeos.github.io/jekyll/github/freebsd/2016/01/07/creating-a-jekyll-github-pages-blog-and-managing-it-with-freebsd</id><content type="html" xml:base="https://sgeos.github.io/jekyll/github/freebsd/2016/01/07/creating-a-jekyll-github-pages-blog-and-managing-it-with-freebsd.html"><![CDATA[<!-- A1 -->
<script>console.log("A1");</script>

<p>I have wanted a low maintenance technical blogging solution for a while.  A Jekyll blog on GitHub Pages meets all of my criteria.  Write posts in markdown, commit and push.  The people at GitHub Pages will almost certainly keep the servers up.</p>

<p>These instructions are written for FreeBSD because that is what I use.  The same general approach should work for any operating system.</p>

<h2 id="software-versions">Software Versions</h2>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="nv">$ </span><span class="nb">date
</span>January  8, 2016 at 03:07:15 AM JST
<span class="nv">$ </span><span class="nb">uname</span> <span class="nt">-a</span>
FreeBSD mirage.sennue.com 11.0-CURRENT FreeBSD 11.0-CURRENT <span class="c">#0 r287598: Thu Sep 10 14:45:48 JST 2015     root@:/usr/obj/usr/src/sys/MIRAGE_KERNEL  amd64</span>
<span class="nv">$ </span>ruby <span class="nt">--version</span>
ruby 2.1.8p440 <span class="o">(</span>2015-12-16 revision 53160<span class="o">)</span> <span class="o">[</span>amd64-freebsd11]
<span class="nv">$ </span>jekyll <span class="nt">--version</span>
jekyll 3.0.1</code></pre></figure>

<h2 id="instructions">Instructions</h2>
<p>First, create a new GitHub repository named <em>my_username</em>.github.io, where <em>my_username</em> is your GitHub username.  The repository needs to have “.github.io” at the end.</p>

<p>Next, install Jekyll, create a new blog and push it to github.</p>

<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="c"># install jekyll</span>
su
portmaster devel/ruby-gems
gem <span class="nb">install </span>jekyll
gem <span class="nb">install </span>github-pages <span class="c"># optional, for local preview</span>
<span class="nb">exit</span>

<span class="c"># create a new blog</span>
<span class="c"># replace my_username with your username</span>
<span class="c"># replace my_blog directory with your preferred project organization</span>
<span class="nb">cd</span> <span class="c"># if you need to get $HOME</span>
<span class="nb">mkdir </span>my_blog
<span class="nb">cd </span>my_blog
jekyll new my_username.github.io
<span class="nb">cd </span>my_username.github.io

<span class="c"># add ssh key to session using the sh shell</span>
<span class="c"># assumes you are set up to use ssh</span>
<span class="c"># use the following link to set up ssh</span>
<span class="c"># https://help.github.com/articles/generating-ssh-keys/</span>
sh
<span class="nb">eval</span> <span class="s2">"</span><span class="si">$(</span>ssh-agent <span class="nt">-s</span><span class="si">)</span><span class="s2">"</span>
ssh-add ~/.ssh/id_rsa

<span class="c"># add project to git and push to github</span>
<span class="c"># replace my_username with your username</span>
<span class="c"># use the https github url if ssh is not set up</span>
<span class="c"># https://github.com/my_username/my_username.github.io.git</span>
git init
git add <span class="nb">.</span>
git commit <span class="nt">-m</span> <span class="s2">"Initial commit."</span>
git remote add origin git@github.com:my_username/my_username.github.io.git
git remote <span class="nt">-v</span>
git push origin master

<span class="c"># configure blog</span>
vim _config.yml

<span class="c"># save welcome post in drafts for future reference</span>
<span class="c"># replace YYYY-MM-DD with the post date</span>
<span class="c"># the archived welcome post can be deleted when it is no longer needed</span>
<span class="nb">mkdir </span>_drafts
<span class="nb">mv </span>_posts/YYYY-MM-DD-welcome-to-jekyll.markdown _drafts/

<span class="c"># save default about in drafts for future reference</span>
<span class="c"># the archived about file can be deleted when it is no longer needed</span>
<span class="c"># customize about page</span>
<span class="nb">cp </span>about.md _drafts/about.markdown
vim _drafts/about.markdown <span class="c"># remove permalink line, change layout to post</span>
vim about.md

<span class="c"># create post</span>
<span class="c"># replace YYYY-MM-DD the post date</span>
<span class="c"># replace name-of-post with the title of the post</span>
vim _posts/YYYY-MM-DD-title-of-post.markdown

<span class="c"># local build / test for errors</span>
jekyll build <span class="nt">--incremental</span> <span class="nt">--drafts</span>

<span class="c"># local preview</span>
jekyll serve <span class="nt">--host</span> 0.0.0.0 <span class="nt">--port</span> 4000 <span class="nt">--drafts</span> <span class="nt">--watch</span>

<span class="c"># sync changes</span>
git add <span class="nb">.</span>
git commit <span class="nt">-m</span> <span class="s2">"Change message."</span>
git push</code></pre></figure>

<h2 id="references">References:</h2>
<ul>
  <li><a href="https://pages.github.com">GitHub Pages Setup Instructions</a></li>
  <li><a href="https://help.github.com/articles/markdown-basics/">GitHub Markdown Basics</a></li>
  <li><a href="https://help.github.com/articles/generating-ssh-keys/">GitHub Generating SSH Keys</a></li>
  <li><a href="https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/">GitHub Add Existing Project</a></li>
  <li><a href="http://jekyllrb.com/docs/quickstart/">Jekyll Quick-Start Guide</a></li>
  <li><a href="http://jekyllrb.com/docs/configuration/">Jekyll Configuration</a></li>
  <li><a href="http://jekyllrb.com/docs/posts/">Jekyll Writing posts</a></li>
  <li><a href="http://jekyllrb.com/docs/drafts/">Jekyll Working with drafts</a></li>
  <li><a href="https://www.smashingmagazine.com/2014/08/build-blog-jekyll-github-pages/">Jekyll, Build A Blog With Jekyll And GitHub Pages</a></li>
  <li><a href="http://blog.slaks.net/2013-08-09/jekyll-tag-was-never-closed/">Jekyll bug: Tag was never closed</a></li>
  <li><a href="https://www.freebsd.org/doc/handbook/ports-using.html">FreeBSD Handbook Using the Ports Collection</a></li>
</ul>]]></content><author><name>Brendan Sechter</name></author><category term="jekyll" /><category term="github" /><category term="freebsd" /></entry></feed>