I knew it was gonna happen someday, so we might as well do it. :D
COMEFROM #9:
plecra:
https://www.libsdl.org/license.php afaict SDL has been zlib for over a decade btw. I'm personally pretty anti-(L)GPL in FOSS. It seems sensible to leave licensing options up to maintainers of contrib libraries though - requring a license at least as permissive as LGPL, but publishing as zlib is also ok.
I do think that contrib should have a requirement that your API itself must be licensed zlib/BSD/public domain/MIT - to ensure users are allowed to replace libraries with their own code and use their own license
icefox:
Good point on the SDL license change, thanks. glibc is LGPL, so to me that seems like a pretty good precedent to use instead. For contrib libs, mixing licenses with GPL gets complicated, and that's intentional. GPL's design makes it a floor, not a ceiling. Figuring out all the details and ins and outs of that is important, but not urgent.
plecra:
I wholeheartedly agree that this is great, and I prefer most of my FOSS work to fall under these kinds of terms. Here's the specific situation I'm concerned about:
I've written some code in garnet and built a useful foss tool that I now want to commercialize with a few B2B features. I've used some of the contrib libraries fairly pervasively, as they're blessed by the language and kept in good condition I now want to rewrite (as in, completely rewrite them from scratch) a few of those contrib libraries so that I can use them in my closed source distribution.
However I can't because the API of the GPL'd libraries is under license! Even if I replace the implementation of the library, I still have a bunch of calls to the library API in the source code I've already written, and that's a bunch of GPL'd IP scattered across my whole project. The best I can do is now rewrite the whole project to use my new API, and the open source version suffers for it too.
To me, this makes any development on top of GPL'd libraries a massive hazard. I can never decide to use my own code in unshared projects without risking major rewrites (nor can anyone I might want to share my code with).
(edit: The default of MIT + Apache2 in rust's ecosystem is too permissive, I agree on that đ Using a license that ensures projects can stay public is a good idea)
Side note - glibc is positioned very differently from garnet libraries. LGPL suits libraries that will be present on the target system and dynamically linked (1). I'm guessing garnet will want to use the rusty static linking model instead, and we can't use glibc as precedent for that.
(1): There're caveats to this of course, but its a very important detail of glibc's situation
Why would you need to rewrite LGPL contrib libs to use them in your closed source software? If they're statically linked, I suppose. Might be worth considering using "GPL with linking exception", a la GNU Classpath instead of LGPL, given that's more or less what I want. It's somewhat squirrelly, given that imo "linking" is only going to become more of a gradual process as time goes on.
However I can't because the API of the GPL'd libraries is under license!
Is it? I didn't think it was; I thought you could make a cleanroom impl of it off of public docs. I could be wrong though, let me do some digging...
GPL v3 says:
For example, Corresponding Source includes interface definition files [headers] associated with source files for the work...
The âSystem Librariesâ of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form...
...A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
The GPL is very concerned with conveying the modified code; that is, distributing or selling it. So it might be that you're perfectly fine modifying and using the code if you don't distribute it? It miiiiight also be fine if your distribution includes the modified GPL'ed source code plus your own code as a binary object file ready to link.
If we go on to the LGPL, it says:
A âCombined Workâ is a work produced by combining or linking an Application with the Library...
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license document.
Soooo if you have a header file full of merely definitions and maybe some small macros/inline code, you can use it without conditions. If the header has more complicated stuff in it, then you have to say that the object code includes the header but the object code doesn't have to be LGPL. To me this implies that using the API of a LGPL library does not count as creating a derivative work? The actual text of the library really doesn't talk much about API's at all, or documentation for that matter. It's very much about what you can do to modify and distribute the code, not writing new code or dealing with intellectual property. I guess it leans a lot on the definition of "derivative work"? And I'm not qualified to comment on that, besides to say that US laws are currently bullshit.
The LGPL also states specifically in section 4d that "distribute LGPL source code + proprietary object code ready to link" is allowed. This makes sense with the intent being "you bought it, you own it", so you can modify the program and tinker with it. That's a very pre-21st-century intent, since lots and lots of software these days is a service rather than a product shipped once and then owned forever, but it's still a good intent. Makes a lot of sense when you consider hardware-hackerly things like reversing or repurposing embedded hardware devices.
It also says in section 5:
You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
So if you have a lib
foo
that depends on a LGPL libbar
, you can distributefoo
under any terms you want as long as it's again in the same "you can do whatever you want withbar
" form? ...I think. Section 5a there is pretty hard to parse.Anyway. It's a gnarly and fucked up problem, and IMO tech will continue to outpace law as the concept of "linking" becomes a less binary and more dynamic process. (Consider Zig's repatch-existing-exe functionality for example.) I'm not a lawyer but it looks like the LGPL is the closest thing out there to what I want. There could be something better though. I'm open to ideas, but writing our own license from scratch sounds painful, over-complicated and thankless. Modifying an existing one, a la GNU Classpath, is an option, but I'd prefer to just choose one that does what we want to begin with.
Considering design instead of implementation details for a moment, the invariants I want for Garnet compiler and foundation libs are:
- The code of the library must be public/libre
- If you modify the code of those libs, those modifications must also be public
- If you don't modify the code of those libs, you can do whatever you want with them, including static linking(?) and distributing code that relies on those libs
- The license for code built with the compiler + standard libs can be whatever you want.
- If you modify the code of the compiler, those modifications must also be public
Ok, MPL 2.0 miiiiiight actually do what we want. I'd be interested in your take on it ~plecra , if you ever want to dig into it.
Its main structural difference from the LGPL seems to be it explicitly licenses one file at a time, and explicitly allows derivative works to combine those files with works under other licenses. It explicitly allows you to "upgrade" portions of the Covered Work to GPL versions; idk what the GPL thinks of that.
Licensing one file at a time is kinda painful but maybe it actually very nicely dodges the whole "what is a derivative work" debate by forcing you to explicitly state it. Basically solving ambiguity via micromanagement, and the micromanagement can be automated via a tool to handle SPDX headers.
What I worry about with the per-file model is someone just plopping
proprietary_extensions.rs
into an otherwise-libre project, compiling it, and shipping it without having to make their extensions public. The exact wording in the MPL is a little obtuse, it defines "Modifications" as (among other things) "any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software". So if you have to adduse crate::proprietary_extensions;
to the MPL-covered portion of the program thenproprietary_extensions.rs
has to be MPL, but... by my reading, if you already haveuse crate::*;
in it, adding a new file that gets included by that wildcard does not mean that file has to be MPL. You haven't added to, removed from or modified the Covered Software, in the most technical sense of the meaning. Making that impossible involves removing wildcard imports from the programming language, and I rather want wildcard imports and will not alter the programming language design for motherfucking legal reasons. So here the license's explicitness and micromanagement is a weakness.Sooooooo MPL-2.0 looks appealing in general but I'm not convinced it sufficiently protects against people adding non-libre extensions to the existing code. Modifying/extending the license is also kinda hard, though not impossible. There might be a way to contort it into doing what I want, but the fact that I have to contort it in the first place is somewhat distasteful.
Looks like Eclipse Public License 2.0 also has the same file-based approach as MPL 2.0, with the explicit addition of "âModified Worksâ shall mean any work in Source Code or other form that results from an addition to, deletion from, or modification of the contents of the Program, including, for purposes of clarity any new file in Source Code form that contains any contents of the Program." So no copy-pasta'ing the whole program into a new file and modifying that. Jeez I didn't even think about that part. Shows how easy it can be to work around the file-based micromanagement. Otherwise it's Fine but I'd rather use MPL if possible, just 'cause it's more common.
The EUPL is nice in general, but is from a naive reading hard-copyleft like GPL is. Looking again, Derivative Works must be licensed under EUPL or a compatible license, and the definition of "derivative work" is left up to the rest of the legal system. So it might be a strict definition like GPL, a permissive definition like MPL, or anything in between. This is probably the right definition from a design point of view, but I really don't trust the rest of the legal system to get it right, especially with something as important as a stdlib.
And there don't seem to be many other options for copyleft-for-libraries. LGPL seems to be the right level of strictness but rather hairy, MPL is much less hairy but a biiiiit too easy to work around.
Welp, that's probably about the limits of what I can do without hiring an actual IP lawyer.
Ok, so now that I've had a couple days to ponder this here's my summary of copyleft licenses in descending order of strength:
- GPL -- too strong for libraries unless you wanna be real aggro
- LGPL -- Maaaaaaaaaaybe a bit stronger than I want, the wording is hairy enough it's hard to tell, not sure whether static linking is allowed (edit: this says static linking is not allowed unless you provide "everything necessary to re-link the application", which may be binary object files but is still a bit of a big ask.)
- GPL with linking exception(?????) -- kinda weird, not been tested in court but has resulted in settlements, might be stronger than LGPL or weaker depending on exact wording but there's no particularly standard form.
- EUPL -- Quite nice overall but maaaaaaaaaaybe a bit weaker than I want, just says "Derivative Works" and leaves the definition of that to EU courts. In practice they seem to come to sensible conclusions but I'm reluctant to rely on that. Could use stronger patent protection too.
- Eclipse PL -- Mozilla PL with one particular loophole closed, could maybe work but not popular enough to be worth it, other loopholes still exist
- Mozilla PL -- Too weak, its explicitness of what is and isn't licensed is nice but too easy to work around. If I can think of two different loopholes in ten minutes, imagine what a lawyer with an actual motivation can do.
Also, since this is by nature a defensive decision, it's worth considering the attacks it's intended to defend against. Since Garnet is a low-level language intended for use in embedded and stuff, I mostly think about it in terms of hardware support for proprietary systems like game consoles, Tensilica CPU's (ESP8266), NVidia GPU's, etc. So I would like to prevent:
- Someone adding a compiler target to Garnet and not contributing it back upstream
- Someone porting the stdlib to a new CPU and not contributing it back upstream
- Adding/optimizing/improving core or contrib libs and not contributing it back upstream
It's not intended to prevent:
- Writing proprietary software in Garnet, with or without the stdlib or contrib libs
- Writing proprietary libs in Garnet and distributing them as source or binaries
- Reading the language spec and API docs and writing a new implementation under whatever license
- Crazy Linker Shit like distributing applications as wasm blobs with a mixture of licenses and then recompiling them all together on a local machine
However, that last one is also dangerous; look at the bullshit that hardware vendors go through with the Linux kernel to "not link with it" by dumping in drivers that are just minimalist shims that load binary blobs of firmware. I think that this will be one of the places where you have to draw the line somewhere, and no matter where it will be in the wrong place for someone.
From https://copyleft.org/guide/comprehensive-gpl-guidech12.html#x15-11000011:
If you choose to statically link or otherwise combine your program with an LGPLv3âd work via mechanisms other than a shared library, you may choose your own license for the work provided the license terms limitations for user modification, reverse engineering and debugging are met, and given that the LGPLâd components are still governed by LGPLâs terms. You must offer or provide CCS for the LGPLâd components. The source code material provided must be sufficient to regenerate the combined work with a user-modified version of the LGPLâd components.
This is a bad idea but I'm tempted to have functionality to offer a "re-linkable .exe" of some kind. Inlining and LTO makes that more difficult, but not impossible; the simplest implementation would be just an archive file of all the generated object code or IR, plus some metadata for how to invoke the Garnet compiler to re-build it sith a replaced component.
Just doing "GPL with linking exception" seems far less work though.
Aha, the "GCC Runtime Library Exception" appears to be basically the formalization of what I want: https://www.gnu.org/licenses/gcc-exception-3.1.html The language and terminology is kinda a pedantic pain in the ass, like GPL 3's language is, but it's also maintained by GNU and probably will be for the forseeable future so it's probably the canonical choice. The GNAT Ada compiler uses it, and has a paid variant with lawyers standing behind it, so it's probably been vetted pretty thoroughly. Still needs closer inspection though.
EUPL is looking better all the time, under the circumstances. And apparently doesn't define linking to be a derivative work. From https://interoperable-europe.ec.europa.eu/collection/eupl/how-use-eupl:
If a covered work is modified, it becomes a derivative. But if the normal purpose of the work is to help producing other works (it is a library or a work tool) it would be abusive to consider everything that is produced with the tool as "derivative". Moreover, European law considers that linking two independent works for ensuring their interoperability is authorised regardless of their licence and therefore without changing it: no "viral" effect.
With that addendum, EUPL seems ideal. Though it doesn't include a patent retaliation clause, which is a little annoying.
Another option: https://opensource.org/license/osl-3-0-php Not widely deployed apparently but seems to fit the bill? Modifications/derivative works must be made available under the same license, linking does not create a derivative work apparently (kinda implied; the license covers source code, not object code), has patent protection with a retaliation clause. Has a slightly AGPL-like clause (5) which is a little sus but also kinda nice; will need thinking about more when I'm awake. Seems easier to say "modified OSL-3.0 without section 5" than "GPL with classpath exception". Per wikipedia though, it's never been tested in court. And section 9 is kinda scuffed too, it seems?
Per https://op.europa.eu/en/publication-detail/-/publication/c15c9e93-27e1-11ec-bd8e-01aa75ed71a1# :
Under the European law, elements needed to achieve interoperability (interfaces, data structures) may not be copyrightable.
So I think EUPL is the way to go. Just needs a bit of knowledge of the framework around it.
The SaaS provisions seem pretty simple too: the Work is the source code, and the Derivative Work is the modified source code, not linked object code or API design. If you make a Derivative Work, it has to be the same or compatible license, and the source has to be available. An online service using the modified code still counts as a Derivative Work.
So yeah EUPL is looking good. The lack of a patent retaliation clause makes me a little miffed, cause the people who make software patents deserve some grief, but it's explicitly under EU law and EU software patent laws appear... Well, better than the US, at least.