libftdi1-sys, a binding to
libFTDI that I've long neglected, I bumped into an interesting problem that boils down to feature-dependent licensing.
First, a bit of background.
libFTDI is an open library for working with FTDI chips that are USB-to-something converters, where "something" can be set to various configurations ranging from plain old serial port to high-speed FIFOs operating close to the USB 2.0 bandwidth limit. Unlike the proprietary vendor drivers,
libFTDI core components are licensed under GNU LGPL 2.1. There are also non-core components like the C++ bindings that are under GPL, but these are out of scope for this binding.
So I want to have a binding that would be both well-behaved and easy to use. Roughly I'd like it to have the following set of features:
- uses system libraries by default, finding them with
vcpkg(no idea about Macs, sorry) and generating bindings with
bindgenon the fly
- has an option to use pregenerated bindings to avoid the bindgen and clang dependency
- has an option to use a vendored copy of the library for the cases where the system one is not available
- is under
MIT OR Apache-2.0to match the community preferred licensing and avoid LGPL...
- unless the vendored copy is used because that definitely makes the executable a derivative of LGPL-licensed code.
IANAL, but from reading LGPL I think that none of these should be a problem on their own. However, the cargo-native way of indicating the package license, which is the
package.license field in
Cargo.toml, cannot depend on any crate features. So, what can I do?
Option 1. Just make the crate LGPL. Advantages: trivial. Drawbacks: for Rust's static linking this is basically equivalent to GPL, so really restrictive.
Option 2. Use
package.license-file instead and write that in prose. Advantages: no real changes needed. Drawbacks: not machine-readable, so does not work with tooling like
Option 2a: Just write that all in the README and leave one of the licenses for all cases. Advantages: stupid simple. Drawbacks: the machine-readable information is incorrect and actively misleading the user into either rejecting the crate without real need to, or, worse, accepting the crate without noticing the problem.
Option 3. Make a separate crate
libftdi1-vendored-lgpl-internal under LGPL, move the actual vendored source to it and link to it only with the
vendored feature (but still generate all bindings in the main crate). Advantages: correct and machine-readable. Drawbacks: non-obvious for possible contributors (especially the "the library and bindings to it are compiled in different crates" part).
Option 4. Make a separate crate
libftdi1-sys-vendored under LGPL that both contains code and generates bindings for it; with the
libftdi1-sys just reexports the bindings from it. Advantages: correct and machine-readable. Drawbacks: the binding generation logic is duplicated between the two crates.
Option 5: Create a generic
marker-includes-LGPL-code crate and depend on it with the
vendored feature without splitting anything. Advantages: almost correct (the license is not on the correct crate, but it is in the dependency tree) and machine-readable. Disadvantages: may be not exactly obvious for users, may be "hacked around" (well, I hope no one would replace that crate with a permissively-licensed version just to silence the tooling, but still).
For me options 1-2 look like non-options. Anything else? Am I missing some standard and accepted solution? Which option would you prefer?