How to make and use independent libraries in rust/cargo

Almost, but not quite, mvn install
- 2019-June
This article is based on a stackoverflow answer

After a few days of learning rust I got to the point where I wanted to create a library that I could reuse in multiple projects. I could not find a coherent article that explained the process from start to finish. The individual facts exist, but were not tied together in a single narrative.

I wanted to create a library called embroidery_stitcher. cargo new --lib embroidery_stitcher will give you

embroidery_stitcher/src/lib.rs
embroidery_stitcher/Cargo.toml
Inside Cargo.toml is
[package]
name = "embroidery_stitcher"
version = "0.1.0"
authors = ["Robert Forsman "]

[dependencies]
You put your library functions and structures inside lib.rs (and as your library grows it will probably branch out into more modules).

This is the first bit of code I migrated into the library (although this is the fixed version, after I encountered one of the mistakes mentioned below):

pub fn svg_header(w: i32, h: i32) -> String
{
    let header = format!(r#"<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="{}px"
   height="{}px"
   viewBox="0 0 {} {}"
   version="1.1">
"#, w, h, w, h);

    let named_view = format!(r##"<sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="{}"
     inkscape:cx="{}"
     inkscape:cy="{}"
     inkscape:document-units="mm"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="1200"
     inkscape:window-height="800"
     inkscape:window-x="0"
     inkscape:window-y="0"
     inkscape:window-maximized="0" />
"##, 800.0 / 2.0 / w as f32, w as f32 / 2.0, h as f32 / 2.0);

    let rval = [header, named_view].concat();

    return rval;
}

Back in the main application you need the following clause in your Cargo.toml:

[dependencies]
embroidery_stitcher = { path = "../embroidery_stitcher" }
This is actually somewhat inferior to how tools like mvn install work because it hard-codes the relative path between your application and the library. (It is currently June 2019, so maybe cargo has been improved since this article was written).

There are two other mistakes I made before I got all this working:

/usr/bin/cargo run --color=always --package re5 --bin re5
   Compiling re5 v0.1.0 (file:///home/thoth/art/2019/radial-embroidery/re5)
error[E0432]: unresolved import `embroidery_stitcher`
 --> re5/src/main.rs:5:5
  |
5 | use embroidery_stitcher;
  |     ^^^^^^^^^^^^^^^^^^^ no `embroidery_stitcher` in the root
use is wrong. extern crate embroidery_stitcher; is the correct way to refer to a crate from outside the current project.

The next mistake looked like this:

/usr/bin/cargo run --color=always --package re5 --bin re5
   Compiling embroidery_stitcher v0.1.0 (file:///home/thoth/art/2019/radial-embroidery/embroidery_stitcher)
warning: function is never used: `svg_header`
 --> embroidery_stitcher/src/lib.rs:2:1
  |
2 | fn svg_header(w: i32, h: i32) -> String
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(dead_code)] on by default

   Compiling re5 v0.1.0 (file:///home/thoth/art/2019/radial-embroidery/re5)
error[E0603]: function `svg_header` is private
 --> re5/src/main.rs:8:19
  |
8 |     let mut svg = embroidery_stitcher::svg_header(100,100);
  |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This one is super-basic. svg_header needs to be marked pub.
pub fn svg_header(w: i32, h: i32) -> String
Hopefully this fills a gap in the existing Rust articles and will give you what you need to migrate your code into a reusable library.