Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Survey: Crates you use for embedded development #12

Closed
japaric opened this issue Oct 5, 2016 · 57 comments
Closed

Survey: Crates you use for embedded development #12

japaric opened this issue Oct 5, 2016 · 57 comments
Labels
feb-2019-cleanup These issues are proposed to be closed, as part of a cleanup of issues in February 2019 survey

Comments

@japaric
Copy link
Member

japaric commented Oct 5, 2016

Ultimately, we'd like to have a list of curated crates that are nicely categorized in a presentable format (a website with search function, etc.). But, for starters, let's list here all the crates we use for embedded development.

Just add a comment here with the list of crates that you use The crate can be a library or a tool (binary). Try to stick to the following format:

[`$crate_name`]($crates_io_url_or_github_repo_url) - $description
Tags: `$tag1` `$tag2` ...

I'll be collecting them here in the top comment. Try to not to list a crate that has already been mentioned unless you'd like to propose more tags for it.

The tags at this point are free form and can be anything you think will be useful to someone that has to decide whether they can use that crate or not (is it for my target architecture/device? Is it no_std? etc.).

This is also a good opportunity to figure out what are common tags that we could use for #11.


Here's the list so far:

bitflags - A macro for C-like bit flags, pretty useful for modeling hardware registers.
Tags: no_std macro bitflags

lazy_static - A macro that allows to initialize a static using arbitrary code.
Tags: no_std macro static lazy

rustc_builtins - Current state of the Rust port of compiler-rt. Provides various intrinsics that are required by the compiler.
Tags: no_std compiler-rt instrinsics

DEPRECATED in favor of the official compiler_builtins crate (see below)

xargo - A drop-in replacement for Cargo that compiles the sysroot for custom targets on the fly.
Tags: cargo sysroot core libcore liballoc libcollections

intrusive-collections - Intrusive (non-allocating) singly/doubly linked lists and red-black trees.
Tags: no_std intrusive rbtree collections

log - Supports logging in no_std environments, as long as you define your own logger type.
Tags: no_std log

cortex-m - Low level access to Cortex-M processors
Tags: arm cortex-m hardware no_std register peripheral

meta-rust - Yocto layer providing from-source version of the Rust compiler and Cargo
Tags: build yocto

meta-rust-bin - Yocto layer that uses pre-built Rust and Cargo from rust-lang.org
Tags: build yocto

fixedvec - Vec-like interface to a pre-sized buffer of memory. Allows using something like Vec when doing heapless programming.
Tags: no_std

sysfs-gpio - A Rust Interface to the Linux sysfs GPIO interface
Tags: hardware linux gpio

i2cdev - Rust library for interfacing with i2c devices under Linux
Tags: hardware linux i2c

spidev - Rust library providing access to spidev devices under Linux
Tags: hardware linux spi

log_buffer - Rust library for logging into a circular string buffer
Tags: no_std

slog - Supports logging in no_std environments, as long as you implement your own Drain
Tags: log no_std

teensy3 - Rust interface layer for the Teensy 3.1/3.2 microcontroller
Tags: arm cortex-m hardware no_std

cpuio. Bare metal (no_std) inb, outb, inw, outw, inl, outw instructions, with a Rust-friendly API.
Tags: no_std x86

alloc_buddy_simple. Simple, drop-in replacement allocator for Rust running on bare metal. This intended for small, known-size heaps that contain simple collections, such as lists of USB devices discovered on the bus.
Tags: allocator no_std

pic8259_simple. Kernel-space interface to the 8259 and 8259A interrupt controllers.
Tags: no_std interrupts

volatile_register - for memory mapped registers
Tags: kernel_mode no_std registers

spin - a spinlock Mutex
Tags: no_std

linked_list_allocator - basic memory allocation
Tags: bare_metal no_std allocator

rlibc - pure Rust implementation of some required C library functions (like memset)
Tags: no_std intrinsics
NOTE the compiler_builtins crate also provides memset (see below)

compiler_builtins - Instrinsics LLVM needs
Tags: no_std intrinsics

x86. Library to program x86 (amd64) hardware. Contains x86 specific data structure descriptions, data-tables, as well as convenience function to call assembly instructions typically not exposed in higher level languages.
Tags: x86 no_std

prusst - Rust interface to the PRU subsystem on AM335x processors (BeagleBone & other SBC)
Tags: hardware linux pru beaglebone

m - A C free / pure Rust mathematical library ("libm") for no_std code
Tags: no_std math float

lm4f120 - A set of drivers for the TI LM4F120.
Tags: bare-metal drivers

fel-cli - CLI tools for dealing with Allwinner devices in FEL mode, in pure Rust.
Tags: arm sunxi allwiner fel

alloc-cortex-m - A heap allocator for Cortex-M processors
Tags: arm cortex-m allocator

cortex-m-semihosting - Semihosting for ARM Cortex-M processors
Tags: cortex-m arm semihosting

cortex-m-template - A Cargo project template for ARM Cortex-M bare metal development
Tags: arm cortex-m Cargo template

DEPRECATED in favor of cortex-m-quickstart (see below)

byteorder - Library for reading/writing numbers in big-endian and little-endian.
Tags: endian big-endian little-endian byte binary

cortex-m-quickstart - A template for building applications for ARM Cortex-M microcontrollers
Tags: arm cortex-m template

cortex-m-rtfm - Real Time For the Masses (RTFM), a framework for building concurrent applications, for ARM Cortex-M microcontrollers
Tags: arm cortex-m concurrency

heapless - static friendly data structures that don't require dynamic memory allocation
Tags: no-heap static

build-const - a helper library for computing constants at compile time in build.rs or a script. Also includes no_std macros for importing them
Tags: embedded no_std build const static

defrag - safe defragmenting memory manager for microcontrollers
Tags: no_std embedded memory manager microcontroller

bridge-rpc - (in development) a protocol designed to allow a system of different devices, to communicate with each other and issue commands through (optionally) guaranteed unique remote procedural calls. It allows inter-network communication through the concept of "bridges". Both nodes and bridges can be highly resource constrained devices (such as microcontrollers). Intended supported networks include tcp/ip, UART, CAN and ZigBee.

aligned - Statically allocated arrays with guaranteed memory alignments
Categories: embedded memory-management no-std
Tags: alignment aligned array

cty - Type aliases to C types like c_int for use with bindgen
Categories: embedded ffi no-std
Tags: bindgen ffi c types

scroll A suite of powerful, extensible, generic, endian-aware Read/Write traits and contextual conversion traits (Byte serializing and deserializing)
Tags: pread bytes endian pwrite

ssmarshal - stupid simple (no_std) serde serialzation library
Tags: no_std, (TODO)

smoltcp - A TCP/IP stack designed for bare-metal, real-time systems without a heap.
Tags: tcp network udp ethernet ip

byte - A low-level, zero-copy, panic-free, binary serializer and deserializer. (parser and encoder)
Tags: no_std byte encode binary parser

clerk - A hardware agnostic HD44780 LCD controlling library.
Tags: embedded driver

stlog A lightweight logging framework for resource constrained devices
Categories: embedded no-std development-tools::debugging
Keywords: log elf symtab

lcd - Yet another HD44780/LCD display library (third, at least)! Batteries are not included: all binding to the hardware/GPIO initialization is the responsibility of the user (including the sleep function).
Tags: no_std embedded

genio - io::{Read, Write} traits for no_std. It has wrappers for std::io::{Read, Write} to allow use in crates that support std and no_std. Its Read, Write traits have associated type parameters to support custom error types.

framed - Rust crate to send and receive data over lossy streams of bytes.

cstr_core - #[no_std] port of std::ffi::CStr and std::ffi::CString. CString support is optional, and uses the alloc crate instead of std.

hashmap_core - #[no_std] port of std::collections::HashMap and std::collections::HashSet. This crate uses alloc instead of std and uses FNV as the default hash function since SipHash requires a source of random numbers.

@japaric japaric changed the title Survey: List of crates you use in embedded development Survey: Crates you use for embedded development Oct 5, 2016
@phil-opp
Copy link
Contributor

phil-opp commented Oct 6, 2016

bitflags - A macro for C-like bit flags, pretty useful for modeling hardware registers.
Tags: no_std macro bitflags

lazy_static - A macro that allows to initialize a static using arbitrary code.
Tags: no_std marco static lazy

rustc_builtins - Current state of the Rust port of compiler-rt. Provides various intrinsics that are required by the compiler.
Tags: no_std compiler-rt instrinsics

xargo - A drop-in replacement for xargo that compiles the sysroot for custom targets on the fly.
Tags: cargo sysroot core libcore liballoc libcollections

@Amanieu
Copy link

Amanieu commented Oct 6, 2016

intrusive-collections - Intrusive (non-allocating) singly/doubly linked lists and red-black trees.
Tags: no_std intrusive rbtree collections

log - Supports logging in no_std environments, as long as you define your own logger type.
Tags: no_std log

@japaric
Copy link
Member Author

japaric commented Oct 6, 2016

xargo

❤️

rustc_builtins

if you use the rustc_builtins crate, you are morally obliged to contribute back to it by porting at least one compiler-rt intrinsic to Rust. 😈. (I should totally go and modify that crate to show that message as a warning everytime it gets compiled.)


cortex-m - Low level access to Cortex-M processors
Tags: arm cortex-m hardware no_std register peripheral

Inspired by the x86 crate, I created the cortex-m crate with the hope that everyone who works with Cortex-M microcontrollers can build upon it and help me improve it!

@japaric japaric added the survey label Oct 15, 2016
@nastevens
Copy link
Member

meta-rust - Yocto layer providing from-source version of the Rust compiler and Cargo
Tags: build yocto

meta-rust-bin - Yocto layer that uses pre-built Rust and Cargo from rust-lang.org
Tags: build yocto

fixedvec - Vec-like interface to a pre-sized buffer of memory. Allows using something like Vec when doing heapless programming.
Tags: no_std

sysfs-gpio - A Rust Interface to the Linux sysfs GPIO interface
Tags: hardware linux gpio

i2cdev - Rust library for interfacing with i2c devices under Linux
Tags: hardware linux i2c

spidev - Rust library providing access to spidev devices under Linux
Tags: hardware linux spi

@whitequark
Copy link

whitequark commented Oct 16, 2016

log_buffer - Rust library for logging into a circular string buffer
Tags: no_std

@dpc
Copy link

dpc commented Oct 16, 2016

slog - Supports logging in no_std environments, as long as you implement your own Drain
Tags: log no_std

@SimonSapin
Copy link

teensy3-rs - bindings for the official C/C++ stack for Teensy 3.x boards.

@flosse
Copy link

flosse commented Oct 16, 2016

here are some links to related posts: https://github.com/flosse/rust-os-comparison#embedded-systems

@Geal
Copy link

Geal commented Oct 16, 2016

I don't know if you'd do much parsing in embedded dev, but nom can build in no_std (and if it fails for you, I'm willing to fix it and support no_std correctly).

@emk
Copy link

emk commented Oct 16, 2016

I have three very minor crates that were all building on nightly as of a couple of weeks ago:

  • cpuio. Bare metal (no_std) inb, outb, inw, outw, inl, outw instructions, with a Rust-friendly API.
  • alloc_buddy_simple. Simple, drop-in replacement allocator for Rust running on bare metal. This intended for small, known-size heaps that contain simple collections, such as lists of USB devices discovered on the bus.
  • pic8259_simple. Kernel-space interface to the 8259 and 8259A interrupt controllers.

@japaric
Copy link
Member Author

japaric commented Oct 16, 2016

If you are working with Cortex-M microcontrollers, need register maps for their peripherals but
don't feel like writing an API that involves thousands of LoCs, you can use:

svd2rust - Generate Rust register maps (structs) from SVD files
Tags: tool arm cortex-m registers peripherals

to save yourself lots of time. Many thanks to @brandonedens for porting my initial version that used
quasi/aster to quote/syn! ❤️


@flosse that link seems more appropriate for #15

@Geal Some embedded applications must not use any heap memory. Can nom produce parsers that don't
rely on the alloc / collections crates? Some bare-metal targets, like the thumbv6m-none-eabi,
can't even compile the alloc crate because they don't support atomics and the alloc crate uses
atomics for its oom handler :-(.

@emk nice, an allocator! I've been looking for one. Is this one x86 specific? Do you know if it will
run on a Cortex-M processor? (usize = 32, single core, no MMU, no virtual memory, no memory pages, etc.)

@aochagavia
Copy link

I guess "xargo - A drop-in replacement for xargo..." should be "xargo - A drop-in replacement for cargo"

@thejpster
Copy link
Contributor

My launchpad project uses these (according to my extern crate statements anyway...)

volatile_register - for memory mapped registers
Tags: kernel_mode

spin - a spinlock Mutex
Tags: no_std

linked_list_allocator - basic memory allocation
Tags: bare_metal

rlibc - pure Rust implementation of some required C library functions (like memset)
Tags: no_std

compiler_builtins - Instrinsics LLVM needs
Tags: no_std

@emk
Copy link

emk commented Oct 16, 2016

@japaric:

nice, an allocator! I've been looking for one. Is this one x86 specific? Do you know if it will
run on a Cortex-M processor?

I've only tried it on x86_64, but it can probably be made to work almost anywhere with a few tweaks. The major advantage of alloc_buddy_simple is that it's tiny, and you can understand the whole thing front-to-back in an hour or so. And it's good enough to make collections basically usable. The biggest drawbacks are that (1) it can't grow its heap, and (2) it hasn't been tested under heavy allocation load, so there might still be some bugs.

Buddy allocators are one of the simplest allocators. It's a fun algorithm.

@thejpster
Copy link
Contributor

thejpster commented Oct 16, 2016

linked_list_allocator is from Phil Opperman's x86-64 blog but it works on a Cortex-M4. It's just pointer math at the end of the day,

@emk
Copy link

emk commented Oct 16, 2016

I also note that nobody has mentioned this popular crate yet:

x86. Library to program x86 (amd64) hardware. Contains x86 specific data structure descriptions, data-tables, as well as convenience function to call assembly instructions typically not exposed in higher level languages.

@Geal
Copy link

Geal commented Oct 16, 2016

some parsers can allocate and return a Vec, but the rest won't rely on
allocations. You can provide your own alloc and collections replacement.
Even without, it should build correctly, since the code using Vec is in
macros.

Le 16 oct. 2016 20:50, "Jorge Aparicio" notifications@github.com a écrit :

If you are working with Cortex-M microcontrollers, need register maps for
their peripherals but
don't feel like writing an API that involves thousands of LoCs, you can
use:

svd2rust https://crates.io/crates/svd2rust - Generate Rust register
maps (structs) from SVD files
Tags: tool arm cortex-m registers peripherals

to save yourself lots of time. Many thanks to @brandonedens
https://github.com/brandonedens for porting my initial version that used

quasi/aster to quote/syn! ❤️

@flosse https://github.com/flosse that link seems more appropriate for
#15 #15

@Geal https://github.com/Geal Some embedded applications must not use
any heap memory. Can nom produce parsers that don't
rely on the alloc / collections crates? Some bare-metal targets, like the
thumbv6m-none-eabi,
can't even compile the alloc crate because they don't support atomics and
the alloc crate uses
atomics for its oom handler :-(.

@emk https://github.com/emk nice, an allocator! I've been looking for
one. Is this one x86 specific? Do you know if it will
run on a Cortex-M processor? (usize = 32, single core, no MMU, no virtual
memory, no memory pages, etc.)


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#12 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAHSAK3ytaub-9FnOIJYgc0EkyDkZzdTks5q0nH9gaJpZM4KPGQm
.

@japaric
Copy link
Member Author

japaric commented Oct 16, 2016

@aochagavia yes, thank you.

@thejpster @emk Thanks for the pointers. I'll read more about these allocators. 👍

@whitequark
Copy link

Some bare-metal targets, like the thumbv6m-none-eabi,
can't even compile the alloc crate because they don't support atomics and the alloc crate uses
atomics for its oom handler :-(.

@japaric This is of course not the case, thumbv6m supports atomic reads/writes via regular read/write instructions and atomic read/modify/writes through a cpsid/cpsie sequence. LLVM only needs to be taught that.

@sbarral
Copy link

sbarral commented Oct 17, 2016

A crate to load and control bare-metal programs on the PRU, an ARM co-processor found among others on the BeagleBone.

prusst - Rust interface to the PRU subsystem on AM335x processors (BeagleBone & other SBC)
Tags: hardware linux pru beaglebone

@japaric
Copy link
Member Author

japaric commented Oct 21, 2016

I've started porting libm to Rust because I needed to do some floating point math on my microcontroller. The crate has very few functions right now though.

m - A C free / pure Rust mathematical library ("libm") for no_std code
Tags: no_std math float


@whitequark

thumbv6m supports atomic reads/writes via regular read/write instructions

That's true. I personally don't know how one would implement the Atomic* Rust API with just that but I suppose it should be possible.

atomic read/modify/writes through a cpsid/cpsie sequence.

I'm unsure about an implementation like that. cpsid/spsie only work in privileged mode and are no-op in user mode. An implementation of Atomic* that is not atomic in some cases doesn't sound compelling to me.

@cwoodall
Copy link

There are a few other ways to do atomics.

You can set basepri to max which will mask out all interrupts (except those with 0 priority). This is what brittle and freertos seem to do. I suppose this is more for critical sections than atomics.

You can also use the strex and ldrex instructions to form some form of a to. Uc operation (this is what the gcc atomic primatives seem to do) http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s02s01.html

@cwoodall
Copy link

This stackoverflow.com article appears to be somewhat insightful: http://stackoverflow.com/questions/11894059/atomic-operations-in-arm

Might be hard to wrap this properly.

@japaric
Copy link
Member Author

japaric commented Oct 21, 2016

You can set basepri to max which will mask out all interrupts

This, like cpsid/cpsie, can only be done in privileged mode.

You can also use the strex and ldrex instructions

These are not available for the thumbv6m target (which is what I said is doesn't support atomics -- keep reading). For thumbv7 and newer, rustc (or rather LLVM) lowers Atomic*'s methods to strex/ldrex instructions.

@whitequark
Copy link

@japaric

I personally don't know how one would implement the Atomic* Rust API with just that but I suppose it should be possible.

You cannot. You need RMW cycles to implement the complete API.

I'm unsure about an implementation like that. cpsid/spsie only work in privileged mode and are no-op in user mode. An implementation of Atomic* that is not atomic in some cases doesn't sound compelling to me.

Indeed. Fortunately... thumbv6m doesn't have the concept of user mode, as far as I'm aware! So this is not a problem.

@thejpster
Copy link
Contributor

I pulled out the drivers from my Stellaris Launchpad project, so I'd like to add:

lm4f120 - A set of drivers for the TI LM4F120.
Tags: bare-metal drivers

@japaric
Copy link
Member Author

japaric commented Jun 2, 2017

aligned - Statically allocated arrays with guaranteed memory alignments
Categories: embedded memory-management no-std
Tags: alignment aligned array

cty - Type aliases to C types like c_int for use with bindgen
Categories: embedded ffi no-std
Tags: bindgen ffi c types

@andylokandy
Copy link

scroll A suite of powerful, extensible, generic, endian-aware Read/Write traits and contextual conversion traits (Byte serializing and deserializing)
Tags: pread bytes endian pwrite

@vitiral
Copy link
Contributor

vitiral commented Jun 7, 2017

I just started work on ubyte, a rust library for serialization/deserialization on microcontrollers. The API is still in progress, but I got serde::Serializer to compile so I'm well on my way to a functional library

Edit: it looks like ssmarshal is pretty much exactly the same -- I would use that instead if I were you.

@vitiral
Copy link
Contributor

vitiral commented Jun 8, 2017

on the above note:

ssmarshal - stupid simple (no_std) serde serialzation library

Tags: no_std, see issue

@vitiral
Copy link
Contributor

vitiral commented Jun 8, 2017

Also, one I recently wrote:

build_const - library for creating importable constants from build.rs or a script (can replace lazy_static and suffers no run-time penalty)

Tags: no_std, embedded, const, static, build

@whitequark
Copy link

smoltcp ­— a no_std TCP/IP stack

@andylokandy
Copy link

byte A low-level, zero-copy, panic-free, binary serializer and deserializer. (parser and encoder)

Tags: no_std byte encode binary parser

@kunerd
Copy link

kunerd commented Jun 30, 2017

clerk - A hardware agnostic HD44780 LCD controlling library.
Tags: embedded driver

@japaric
Copy link
Member Author

japaric commented Jul 7, 2017

stlog A lightweight logging framework for resource constrained devices

Categories: embedded no-std development-tools::debugging
Keywords: log elf symtab

stlog can log strings of arbitrary size to a host in a constant number of instructions (O(1) runtime). Furthermore these strings are not stored in the device memory (O(0) memory usage). stlog supports 5 logging levels: TRACE, DEBUG, INFO, WARN and ERROR; each level can be individually disabled at compile time (there's no branching cost at runtime). stlog also offers a global logging mode: info!("Hello") will log the string using the global logger; the global logger can be configured using the set_global_logger! macro.

Due to its focus on minimal overhead stlog doesn't support formatting -- only literal strings can be logged.

cc @SimonSapin ^

@idubrov
Copy link

idubrov commented Sep 16, 2017

lcd - Yet another HD44780/LCD display library (third, at least)! Batteries are not included: all binding to the hardware/GPIO initialization is the responsibility of the user (including the sleep function).
Tags: no_std embedded

@fluffysquirrels
Copy link

genio - io::{Read, Write} traits for no_std. It has wrappers for std::io::{Read, Write} to allow use in crates that support std and no_std. Its Read, Write traits have associated type parameters to support custom error types.

@fluffysquirrels
Copy link

framed - Rust crate to send and receive data over lossy streams of bytes.

  • Supports sending slices of bytes or serde-serialized types.
  • Uses a checksum to detect and skip corrupted frames.
  • Includes a command-line tool to decode and display serialized types.

Full disclosure: I wrote this.

@Amanieu
Copy link

Amanieu commented Dec 31, 2017

cstr_core - #[no_std] port of std::ffi::CStr and std::ffi::CString. CString support is optional, and uses the alloc crate instead of std.

hashmap_core - #[no_std] port of std::collections::HashMap and std::collections::HashSet. This crate uses alloc instead of std and uses FNV as the default hash function since SipHash requires a source of random numbers.

@whitequark
Copy link

@Amanieu any plans to push this through the RFC process? In particular HashMap not being in alloc is ridiculous.

@Amanieu
Copy link

Amanieu commented Dec 31, 2017

@whitequark The problem is that the default HashMap constructor uses SipHash, which requires a call to the system RNG to get a random seed.

@whitequark
Copy link

@Amanieu I know. Can't the libstd facade provide it, though?

@DoumanAsh
Copy link

DoumanAsh commented Dec 6, 2018

Just wanted to mention my logging crate, I've been working in past.

cortex-m-log - It provides generics over possible outputs (for now it is only semihosting, itm and dummy), I didn't have much of feedback so far and I haven't been working with embedded stuff for quite some time, but I appreciate increased visibility since I'd like to start working on embedded again.
It also contains simple integration with log crate and allows you to implement own writers/printers to be used with log integration.
It also allows to configure interrupt mode for printers

Tags: no_std log

@therealprof
Copy link
Contributor

@DoumanAsh Interesting. Have to check it out, I've been using the log crate previously to log output to a UART and wrote an adapter to use that for panics, too. It's a bit foot-in-mouth to use though...

@DoumanAsh
Copy link

DoumanAsh commented Dec 6, 2018

@therealprof Here is example in my playground with log DoumanAsh/2B@35d6bc5

If you want to write custom destination for logs, you need to implement Printer then it will just work

Specifically you only need to provide how to retrieve &mut io::Write for printer.
Example: https://github.com/DoumanAsh/cortex-m-log/blob/master/src/printer/semihosting.rs#L64-L72

@eldruin
Copy link
Member

eldruin commented Dec 6, 2018

embedded-hal-mock - A collection of mocked devices that implement the embedded-hal traits.
Tags: testing hal

@jamesmunns
Copy link
Member

I believe that this issue has been superseded by the github.com/rust-embedded/awesome-embedded-rust repo. I would propose that we close this issue.

Marking this for a cleanup sweep. If we would like this to stay open, please provide an update to what this issue should be focused on.

@jamesmunns jamesmunns added the feb-2019-cleanup These issues are proposed to be closed, as part of a cleanup of issues in February 2019 label Feb 3, 2019
@jamesmunns
Copy link
Member

I am closing this issue, please feel free to open another issue if you would like this discussed further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feb-2019-cleanup These issues are proposed to be closed, as part of a cleanup of issues in February 2019 survey
Projects
None yet
Development

No branches or pull requests