mirror of
https://github.com/bspeice/speice.io
synced 2024-12-23 00:58:09 -05:00
88 lines
67 KiB
HTML
88 lines
67 KiB
HTML
|
<!doctype html><html lang=en dir=ltr class="blog-wrapper blog-post-page plugin-blog plugin-id-default" data-has-hydrated=false><meta charset=UTF-8><meta name=generator content="Docusaurus v3.6.0"><title data-rh=true>Captain's Cookbook: Project setup | The Old Speice Guy</title><meta data-rh=true name=viewport content="width=device-width,initial-scale=1.0"><meta data-rh=true name=twitter:card content=summary_large_image><meta data-rh=true property=og:url content=https://speice.io/2018/01/captains-cookbook-part-1><meta data-rh=true property=og:locale content=en><meta data-rh=true name=docusaurus_locale content=en><meta data-rh=true name=docusaurus_tag content=default><meta data-rh=true name=docsearch:language content=en><meta data-rh=true name=docsearch:docusaurus_tag content=default><meta data-rh=true property=og:title content="Captain's Cookbook: Project setup | The Old Speice Guy"><meta data-rh=true name=description content="A basic introduction to getting started with Cap'N Proto."><meta data-rh=true property=og:description content="A basic introduction to getting started with Cap'N Proto."><meta data-rh=true property=og:type content=article><meta data-rh=true property=article:published_time content=2018-01-16T12:00:00.000Z><link data-rh=true rel=icon href=/img/favicon.ico><link data-rh=true rel=canonical href=https://speice.io/2018/01/captains-cookbook-part-1><link data-rh=true rel=alternate href=https://speice.io/2018/01/captains-cookbook-part-1 hreflang=en><link data-rh=true rel=alternate href=https://speice.io/2018/01/captains-cookbook-part-1 hreflang=x-default><script data-rh=true type=application/ld+json>{"@context":"https://schema.org","@id":"https://speice.io/2018/01/captains-cookbook-part-1","@type":"BlogPosting","author":{"@type":"Person","name":"Bradlee Speice"},"dateModified":"2024-11-10T01:23:31.000Z","datePublished":"2018-01-16T12:00:00.000Z","description":"A basic introduction to getting started with Cap'N Proto.","headline":"Captain's Cookbook: Project setup","isPartOf":{"@id":"https://speice.io/","@type":"Blog","name":"Blog"},"keywords":[],"mainEntityOfPage":"https://speice.io/2018/01/captains-cookbook-part-1","name":"Captain's Cookbook: Project setup","url":"https://speice.io/2018/01/captains-cookbook-part-1"}</script><link rel=alternate type=application/rss+xml href=/rss.xml title="The Old Speice Guy RSS Feed"><link rel=alternate type=application/atom+xml href=/atom.xml title="The Old Speice Guy Atom Feed"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css integrity=sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM crossorigin><link rel=stylesheet href=/assets/css/styles.ae6ff4a3.css><script src=/assets/js/runtime~main.751b419d.js defer></script><script src=/assets/js/main.62ce6156.js defer></script><body class=navigation-with-keyboard><script>!function(){var t,e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();t=null!==e?e:"light",document.documentElement.setAttribute("data-theme",t)}(),function(){try{for(var[t,e]of new URLSearchParams(window.location.search).entries())if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id=__docusaurus><div role=region aria-label="Skip to main content"><a class=skipToContent_fXgn href=#__docusaurus_skipToContent_fallback>Skip to main content</a></div><nav aria-label=Main class="navbar navbar--fixed-top"><div class=navbar__inner><div class=navbar__items><button aria-label="Toggle navigation bar" aria-expanded=false class="navbar__toggle clean-btn" type=button><svg width=30 height=30 viewBox="0 0 30 30" aria-hidden=true><path stroke=currentColor stroke-linecap=round stroke-miterlimit=10 stroke-width=2 d="M4 7h22M4 15h22M4 23h22"/></svg></button><a class=navbar__brand href=/><div class=navbar__logo><img src=/img/logo.svg alt="Sierpinski Gasket" class="themedComponent_mlkZ themedCompone
|
|||
|
<p>I've been working a lot with <a href=https://capnproto.org/ target=_blank rel="noopener noreferrer">Cap'N Proto</a> recently with Rust, but there's a real dearth of information
|
|||
|
on how to set up and get going quickly. In the interest of trying to get more people using this (because I think it's
|
|||
|
fantastic), I'm going to work through a couple of examples detailing what exactly should be done to get going.</p>
|
|||
|
<p>So, what is Cap'N Proto? It's a data serialization library. It has contemporaries with <a href=https://developers.google.com/protocol-buffers/ target=_blank rel="noopener noreferrer">Protobuf</a>
|
|||
|
and <a href=https://google.github.io/flatbuffers/ target=_blank rel="noopener noreferrer">FlatBuffers</a>, but is better compared with FlatBuffers. The whole point behind it
|
|||
|
is to define a schema language and serialization format such that:</p>
|
|||
|
<ol>
|
|||
|
<li>Applications that do not share the same base programming language can communicate</li>
|
|||
|
<li>The data and schema you use can naturally evolve over time as your needs change</li>
|
|||
|
</ol>
|
|||
|
<p>Accompanying this are typically code generators that take the schemas you define for your application and give you back
|
|||
|
code for different languages to get data to and from that schema.</p>
|
|||
|
<p>Now, what makes Cap'N Proto different from, say, Protobuf, is that there is no serialization/deserialization step the same way
|
|||
|
as is implemented with Protobuf. Instead, the idea is that the message itself can be loaded in memory and used directly there.</p>
|
|||
|
<p>We're going to take a look at a series of progressively more complex projects that use Cap'N Proto in an effort to provide some
|
|||
|
examples of what idiomatic usage looks like, and shorten the startup time needed to make use of this library in Rust projects.
|
|||
|
If you want to follow along, feel free. If not, I've posted <a href=https://github.com/bspeice/capnp_cookbook_1 target=_blank rel="noopener noreferrer">the final result</a>
|
|||
|
for reference.</p>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id=step-1-installing-capnp>Step 1: Installing <code>capnp</code><a href=#step-1-installing-capnp class=hash-link aria-label="Direct link to step-1-installing-capnp" title="Direct link to step-1-installing-capnp"></a></h2>
|
|||
|
<p>The <code>capnp</code> binary itself is needed for taking the schema files you write and turning them into a format that can be used by the
|
|||
|
code generation libraries. Don't ask me what that actually means, I just know that you need to make sure this is installed.</p>
|
|||
|
<p>I'll refer you to <a href=https://capnproto.org/install.html target=_blank rel="noopener noreferrer">Cap'N Proto's installation instructions</a> here. As a quick TLDR though:</p>
|
|||
|
<ul>
|
|||
|
<li>Linux users will likely have a binary shipped by their package manager - On Ubuntu, <code>apt install capnproto</code> is enough</li>
|
|||
|
<li>OS X users can use <a href=https://brew.sh/ target=_blank rel="noopener noreferrer">Homebrew</a> as an easy install path. Just <code>brew install capnp</code></li>
|
|||
|
<li>Windows users are a bit more complicated. If you're using <a href=https://chocolatey.org/ target=_blank rel="noopener noreferrer">Chocolatey</a>, there's <a href=https://chocolatey.org/packages/capnproto/ target=_blank rel="noopener noreferrer">a package</a> available. If that doesn't work however, you need to download <a href=https://capnproto.org/capnproto-c++-win32-0.6.1.zip target=_blank rel="noopener noreferrer">a release zip</a> and make sure that the <code>capnp.exe</code> binary is in your <code>%PATH%</code> environment variable</li>
|
|||
|
</ul>
|
|||
|
<p>The way you know you're done with this step is if the following command works in your shell:</p>
|
|||
|
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">capnp </span><span class="token function" style="color:hsl(221, 87%, 60%)">id</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id=step-2-starting-a-capn-proto-rust-project>Step 2: Starting a Cap'N Proto Rust project<a href=#step-2-starting-a-capn-proto-rust-project class=hash-link aria-label="Direct link to Step 2: Starting a Cap'N Proto Rust project" title="Direct link to Step 2: Starting a Cap'N Proto Rust project"></a></h2>
|
|||
|
<p>After the <code>capnp</code> binary is set up, it's time to actually create our Rust project. Nothing terribly complex here, just a simple</p>
|
|||
|
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">mkdir</span><span class="token plain"> capnp_cookbook_1</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">cd</span><span class="token plain"> capnp_cookbook_1</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">cargo</span><span class="token plain"> init </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--bin</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|||
|
<p>We'll put the following content into <code>Cargo.toml</code>:</p>
|
|||
|
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">[package]</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">name = "capnp_cookbook_1"</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">version = "0.1.0"</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">authors = ["Bradlee Speice <bspeice@kcg.com>"]</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain" style=display:inline-block></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">[build-dependencies]</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">capnpc = "0.8" # 1</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain" style=display:inline-block></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">[dependencies]</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">capnp = "0.8" # 2</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|||
|
<p>This sets up:</p>
|
|||
|
<ol>
|
|||
|
<li>The Rust code generator (CAPNProto Compiler)</li>
|
|||
|
<li>The Cap'N Proto runtime library (CAPNProto runtime)</li>
|
|||
|
</ol>
|
|||
|
<p>We've now got everything prepared that we need for writing a Cap'N Proto project.</p>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id=step-3-writing-a-basic-schema>Step 3: Writing a basic schema<a href=#step-3-writing-a-basic-schema class=hash-link aria-label="Direct link to Step 3: Writing a basic schema" title="Direct link to Step 3: Writing a basic schema"></a></h2>
|
|||
|
<p>We're going to start with writing a pretty trivial data schema that we can extend later. This is just intended to make sure
|
|||
|
you get familiar with how to start from a basic project.</p>
|
|||
|
<p>First, we're going to create a top-level directory for storing the schema files in:</p>
|
|||
|
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Assuming we're starting from the `capnp_cookbook_1` directory created earlier</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain" style=display:inline-block></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">mkdir</span><span class="token plain"> schema</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">cd</span><span class="token plain"> schema</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|||
|
<p>Now, we're going to put the following content in <code>point.capnp</code>:</p>
|
|||
|
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">@0xab555145c708dad2;</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain" style=display:inline-block></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">struct Point {</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> x @0 :Int32;</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> y @1 :Int32;</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">}</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|||
|
<p>Pretty easy, we've now got structure for an object we'll be able to quickly encode in a binary format.</p>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id=step-4-setting-up-the-build-process>Step 4: Setting up the build process<a href=#step-4-setting-up-the-build-process class=hash-link aria-label="Direct link to Step 4: Setting up the build process" title="Direct link to Step 4: Setting up the build process"></a></h2>
|
|||
|
<p>Now it's time to actually set up the build process to make sure that Cap'N Proto generates the Rust code we'll eventually be using.
|
|||
|
This is typically done through a <code>build.rs</code> file to invoke the schema compiler.</p>
|
|||
|
<p>In the same folder as your <code>Cargo.toml</code> file, please put the following content in <code>build.rs</code>:</p>
|
|||
|
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">extern</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">crate</span><span class="token plain"> </span><span class="token module-declaration namespace">capnpc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain" style=display:inline-block></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">capnpc</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">CompilerCommand</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">src_prefix</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"schema"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// 1</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">file</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"schema/point.capnp"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// 2</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">run</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">expect</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span clas
|
|||
|
<p>This sets up the protocol compiler (<code>capnpc</code> from earlier) to compile the schema we've built so far.</p>
|
|||
|
<ol>
|
|||
|
<li>Because Cap'N Proto schema files can re-use types specified in other files, the <code>src_prefix()</code> tells the compiler
|
|||
|
where to look for those extra files at.</li>
|
|||
|
<li>We specify the schema file we're including by hand. In a much larger project, you could presumably build the <code>CompilerCommand</code>
|
|||
|
dynamically, but we won't worry too much about that one for now.</li>
|
|||
|
</ol>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id=step-5-running-the-build>Step 5: Running the build<a href=#step-5-running-the-build class=hash-link aria-label="Direct link to Step 5: Running the build" title="Direct link to Step 5: Running the build"></a></h2>
|
|||
|
<p>If you've done everything correctly so far, you should be able to actually build the project and see the auto-generated code.
|
|||
|
Run a <code>cargo build</code> command, and if you don't see <code>cargo</code> complaining, you're doing just fine!</p>
|
|||
|
<p>So where exactly does the generated code go to? I think it's critically important for people to be able to see what the generated
|
|||
|
code looks like, because you need to understand what you're actually programming against. The short answer is: the generated code lives
|
|||
|
somewhere in the <code>target/</code> directory.</p>
|
|||
|
<p>The long answer is that you're best off running a <code>find</code> command to get the actual file path:</p>
|
|||
|
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Assuming we're running from the capnp_cookbook_1 project folder</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">find</span><span class="token plain"> </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">.</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-name</span><span class="token plain"> point_capnp.rs</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|||
|
<p>Alternately, if the <code>find</code> command isn't available, the path will look something like:</p>
|
|||
|
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">./target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|||
|
<p>See if there are any paths in your target directory that look similar.</p>
|
|||
|
<p>Now, the file content looks pretty nasty. I've included an example <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs target=_blank rel="noopener noreferrer">here</a>
|
|||
|
if you aren't following along at home. There are a couple things I'll try and point out though so you can get an idea of how
|
|||
|
the schema we wrote for the "Point" message is tied to the generated code.</p>
|
|||
|
<p>First, the Cap'N Proto library splits things up into <code>Builder</code> and <code>Reader</code> structs. These are best thought of the same way
|
|||
|
Rust separates <code>mut</code> from non-<code>mut</code> code. <code>Builder</code>s are <code>mut</code> versions of your message, and <code>Reader</code>s are immutable versions.</p>
|
|||
|
<p>For example, the <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L90 target=_blank rel="noopener noreferrer"><code>Builder</code> impl</a> for <code>point</code> defines <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L105 target=_blank rel="noopener noreferrer"><code>get_x()</code></a>, <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L109 target=_blank rel="noopener noreferrer"><code>set_x()</code></a>, <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L113 target=_blank rel="noopener noreferrer"><code>get_y()</code></a>, and <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L117 target=_blank rel="noopener noreferrer"><code>set_y()</code></a> methods.
|
|||
|
In comparison, the <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L38 target=_blank rel="noopener noreferrer"><code>Reader</code> impl</a> only defines <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L47 target=_blank rel="noopener noreferrer"><code>get_x()</code></a> and <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L51 target=_blank rel="noopener noreferrer"><code>get_y()</code></a> methods.</p>
|
|||
|
<p>So now we know that there are some <code>get</code> and <code>set</code> methods available for our <code>x</code> and <code>y</code> coordinates;
|
|||
|
but what do we actually do with those?</p>
|
|||
|
<h2 class="anchor anchorWithStickyNavbar_LWe7" id=step-6-making-a-point>Step 6: Making a point<a href=#step-6-making-a-point class=hash-link aria-label="Direct link to Step 6: Making a point" title="Direct link to Step 6: Making a point"></a></h2>
|
|||
|
<p>So we've install Cap'N Proto, gotten a project set up, and can generate schema code now. It's time to actually start building
|
|||
|
Cap'N Proto messages! I'm going to put the code you need here because it's small, and put some extra long comments inline. This code
|
|||
|
should go in <a href=https://github.com/bspeice/capnp_cookbook_1/blob/master/src/main.rs target=_blank rel="noopener noreferrer"><code>src/main.rs</code></a>:</p>
|
|||
|
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)">// Note that we use `capnp` here, NOT `capnpc`</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">extern</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">crate</span><span class="token plain"> </span><span class="token module-declaration namespace">capnp</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain" style=display:inline-block></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// We create a module here to define how we are to access the code</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// being included.</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mod</span><span class="token plain"> </span><span class="token module-declaration namespace">point_capnp</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// The environment variable OUT_DIR is set by Cargo, and</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// is the location of all the code that was built as part</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// of the codegen step.</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// point_capnp.rs is the actual file to include</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">include!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token macro property" style="color:hsl(5, 74%, 59%)">concat!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token macro property" style="color:hsl(5, 74%, 59%)">env!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"OUT_DIR"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/point_capnp.rs"</span><span class="token punctuation"
|
|||
|
<p>And with that, we've now got a functioning project. Here's the content I'm planning to go over next as we build up
|
|||
|
some practical examples of Cap'N Proto in action:</div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Blog post page navigation"><a class="pagination-nav__link pagination-nav__link--prev" href=/2016/11/pca-audio-compression><div class=pagination-nav__sublabel>Older post</div><div class=pagination-nav__label>PCA audio compression</div></a><a class="pagination-nav__link pagination-nav__link--next" href=/2018/01/captains-cookbook-part-2><div class=pagination-nav__sublabel>Newer post</div><div class=pagination-nav__label>Captain's Cookbook: Practical usage</div></a></nav></main><div class="col col--2"><div class="tableOfContents_bqdL thin-scrollbar"><ul class="table-of-contents table-of-contents__left-border"><li><a href=#step-1-installing-capnp class="table-of-contents__link toc-highlight">Step 1: Installing <code>capnp</code></a><li><a href=#step-2-starting-a-capn-proto-rust-project class="table-of-contents__link toc-highlight">Step 2: Starting a Cap'N Proto Rust project</a><li><a href=#step-3-writing-a-basic-schema class="table-of-contents__link toc-highlight">Step 3: Writing a basic schema</a><li><a href=#step-4-setting-up-the-build-process class="table-of-contents__link toc-highlight">Step 4: Setting up the build process</a><li><a href=#step-5-running-the-build class="table-of-contents__link toc-highlight">Step 5: Running the build</a><li><a href=#step-6-making-a-point class="table-of-contents__link toc-highlight">Step 6: Making a point</a></ul></div></div></div></div></div><footer class=footer><div class="container container-fluid"><div class="footer__bottom text--center"><div class=footer__copyright>Copyright © 2024 Bradlee Speice</div></div></div></footer></div>
|