I know that a few years ago there was some discussion about which license to choose, with LGPL and MPLv2 being two strong contenders, and it was noted (by Neal himself actually) that MPLv2 is much easier to use when static linking (as is the norm in the Rust community).
Why was LGPL chosen instead? The LGPL requires that all applications that consume it as a static library provide the tools to re-link the binary against modified forms [0], which seems incredibly problematic to manage with the Rust toolchain.
I like the idea behind the LGPL conceptually, but in practice the LGPL is strongly tied to the way Linux applications and libraries were developed in the 90s and 2000s - namely, in C, with dependencies that are generally dynamically linked, with C-like toolchains that directly expose all of the intermediate object files. It just doesn't make a whole lot of sense for any software outside of that bubble.
Quite right. I contribute a Rust component to a larger AGPL-3.0 project and went with MPL-2.0 over LGPL for this reason.
A bit off-topic, but I wonder if the FSF's ideas about dynamic linking have been litigated yet. It has always seemed a pretty suspicious to me that a dynamically linked program, existing only in volatile memory, could really be a copyright work at all, let alone a derivative one. I found this LWN article that touches on this question[0] and links to some more discussion, which I will have to look into.
The LGPL text does not require dynamic linking. It's FUD.
What the LGPL requires is that the LGPL part can be replaced. That's possible with static linking, that's possible with other languages than the ones relying on a linker step, etc.
While it's true that the LGPL doesn't specifically require dynamic linking, it requires something that is effectively dynamic linking. The way you'd have to do static linking isn't something that is easy to set up in most build systems, and deprives you of the ability to do certain post-build steps (such as signing the build) or certain build options (LTO) without some pain.
If the source code for your application is available and buildable, that satisfies the LGPL’s definition of “Corresponding Application Code”, regardless of how it’s linked. You don’t need the object code if you have the source code; you can replace the library by rebuilding the application.
So this is only an inconvenience for proprietary closed-source applications. Making the library conveniently usable by closed-source applications is outside the stated objective in the blog post.
But what does buildable mean, no-one but you has access to your CI (which also might likely not be public).
So do you need to provide another CI, a make-file you maintain additionally, etc.? Or is it good enough so that someone could run "the right CLI commands to build and link the project".
> The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities.
A good open-source (or even source-available) project will include all the necessary build scripts and instructions needed for rebuilding it anyway, and it will be portable enough that this process isn’t tied down to a non-public CI environment.
If you’re asking exactly how much of this you can legally get away with omitting from a project using an LGPL library, then (a) you’re clearly not interested in providing a good open-source project, and (b) you should probably consult a lawyer rather than looking for free armchair legal advice from the community that you’re trying to avoid contributing to.
The license text just requires that the user "can" do it: "Accompany the work... with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library." Interpreting that is a question for the court; I would speculate that manual instructions are probably good enough as long as you provide instructions that actually work.
> I would speculate that manual instructions are probably good enough as long as you provide instructions that actually work.
Well, as long as the instructions rely only on things to which the user has access. If you document your internal build system beautifully, and nobody else is allowed to use it, that would not seem to pass muster.
> The way you'd have to do static linking isn't something that is easy to set up in most build systems,
it's trivial in CMake which is the most used buildsystem in languages with a linker, just set -DBUILD_SHARED_LIBS=0 on the command line
> and deprives you of the ability to do certain post-build steps (such as signing the build)
why would it ? I build my app as a set of static libs linked together in the end and there's no trouble signing it... and it does not make sense for people who will build their own custom version of your app to sign it.
here's a guide inspired by instructions given by Cisco to rebuild one of their proprietary apps for instance on iOS:
> it's trivial in CMake which is the most used buildsystem in languages with a linker, just set -DBUILD_SHARED_LIBS=0 on the command line
Building or using static libraries isn't hard. Doing so in a way that doesn't violate the LGPL's replacement requirement is. The document you yourself linked says this about developing statically-linked libraries with the GPL:
> If you statically link against an LGPLed library, you must also provide your application in an object (not necessarily source) format, so that a user has the opportunity to modify the library and relink the application.
If you're distributing an object format, you need a .o that could be linked with the user's custom version of the LGPLed library. Building such a .o file cannot be done easily with tools, and that is what I'm referring to.
I don't understand, if you can build your app statically then you have the .o ; a static library libfoo.a is just an archive of .o files that pretty much any Unix system can extract
The final link line in a build system for an application is generally `cc -o app file1.o file2.o file3.o ... -llib1 -lib2 -llib3`. Turning that link line into one that produces an app.o that can be combined with liblgpllib.a to produce an equivalent app file is nontrivial. (And before you say just add all the .o files into a single .a file, no, that is not equivalent. Because Unix linking sucks).
... how is that not equivalent ? ar is just tar with less features. At worse extract the .o's from the .a beforehand if that causes issues but I'd really like to know where this differs
If you provide intermediate binary build artifacts i.e. C object files, there it no problem with LTO or signing builds.
I.e. nothing in the LGPL requires you to sign the changed/re-linked binary as far as I known. Similar nothing requires you to sign the provided intermediate
artifacts.
Still only relay viable for C, and maybe C++ if no/few templates where used around the interface. (Or scripting languages bundles with a runtime into a binary.)
The parent comment literally posted the same link. I am aware of the replacement concept and how it is technically distinct from an outright ban on static linking.
> That's possible with static linking, that's possible with other languages than the ones relying on a linker step, etc.
We are talking about Rust, not languages other than Rust. Could you walk us through how you would offer a Rust binary with a statically linked LGPL Rust crate that is replaceable according to the license requirements (v2.0, 2.1, 3.0, pick your poison), without also releasing the binary's source code? I think it's technically possible, but how would you do it? * Edit: keep in mind that .rlib files are not stable across compiler versions. AFAIK very little about the target/ folder is stable at all, except the final product location.
> Could you walk us through how you would offer a Rust binary with a statically linked LGPL Rust crate that is replaceable according to the license requirements (v2.0, 2.1, 3.0, pick your poison), without also releasing the binary's source code?
I see that rustc has a "--emit obj" option, from there surely any decent build system would allow enough customization to do what you want but there's enough raw capability to write a user guide that says "build your stuff with rustc --emit obj lgpl_lib_1.rs -o lgpl_lib_1.o and link with our proprietary .o with lld" ; and you'd be good to go.
> * Edit: keep in mind that .rlib files are not stable across compiler versions.
sure, that's not an issue, just say that you used compiler version x.y ? the LGPL does not require that things work with any compiler version, only that there is a way to patch / rebuild the LGPL parts. e.g. if I ship a C++20 proprietary library with C++20-specific types in the API which interoperates with a C++20 LGPL lib, of course things won't work with GCC 2.95 and everyone will be fine with that.
> I see that rustc has a "--emit obj" option, from there surely any decent build system would allow enough customization to do what you want but there's enough raw capability to write a user guide that says "build your stuff with rustc --emit obj lgpl_lib_1.rs -o lgpl_lib_1.o and link with our proprietary .o with lld" ; and you'd be good to go.
No, that is not how it works, like not at all.
Rust doesn't use the same concepts for building as C.
1. You don't build stuff with `rustc` in general. (You build it with cargo.)
2. You don't produce object files in general, sure rust can produce them and if you link something over the C-ABI it can make sense. What the compiler produces in general for linking libraries are rlibs.
3. rlibs are not just unstable in their format, they are more like a implementation details, don't expect to be able to link in a library as rlib. Like at all.
4. Rust widely uses generics similar to C++ templates this means part of the code which is not supposed to become public will leak if the libary interface involves templates/generics.
5. In rust (and somewhat in C) you normally don't link two "objects" to produce the final binary you build it with a number of "object" dependencies. But this doesn't work with what LGPL requires from you. It can be easy to make a public open-source skeleton you link in all LGPL libraries and your code then to make the linking magic work.
6. `rust --emit` is mainly meant for debugging, and some special use cases around embedding. Don't expect good integration with build tools.
And most important:
What is theoretically possible doesn't matter, what matters is what is practical. I.e. simple, and fast to setup and maintain.
Even for a C CI the requirements the static linking of a LGPL library puts up can make it easily not worth it.
> only that there is a way to patch
No, you need to be able to provide a non LGPL object which you can re-link with the LGPLed libary, so "just" binary patching isn't a legal option.
> You don't build stuff with `rustc` in general. (You build it with cargo.)
It doesn't matter in the slightest what you do, just that there is a documented way for someone to be able to do it, as convoluted as it may be. I should be able to patch your LGPL dependency even if I had never written a line of Rust in my life, so considerations like using the mainstream buildsystem there do not apply. A build.sh shell script is fine - I've used cmake to generate those for instance.
> Rust widely uses generics similar to C++ templates this means part of the code which is not supposed to become public will leak if the libary interface involves templates/generics.
Design your API boundaries better if you don't want that. Pimpl is often used for this.
> What is theoretically possible doesn't matter, what matters is what is practical. I.e. simple, and fast to setup and maintain.
.. no, what matters is respecting the license
> In rust (and somewhat in C) you normally don't link two "objects" to produce the final binary you build it with a number of "object" dependencies.
Sure, just ship the link line that cmake generates or whatever ? I don't understand what is so hard in that and it's more than enough to comply with LGPL.
> binary patching
I was referring of the standard process of applying a patch to the source code of a LGPL library before rebuilding it and linking it against the rest
I don't think it matters that it is impractical. It isn't the FSF's job to write Rust tooling, it is to write licenses.
I do agree that that the concern is becoming much more orthogonal both to the FSF's goals and to the way software is built. But that doesn't change the fact that the license works the way it does, nor does it let you insert the words 'dynamic linking' in it.
> I don't think it matters that it is impractical.
But it does matter, it practice it matters more then what is legal if we are honest.
> It isn't the FSF's job to write Rust tooling
Yes, but it doesn't mean that it's not a bad license for the given use-case.
If it's impractical, then in practice there is not much difference to the license simply forbidding the usage (iff the company cares about what is legal).
Through the question is is it a bad license for the given use-case? I.e. does Sequoia provide a rust API or do they provide a C-API written in rust.
Licensing a rust "for-rust" library as LGPL is in practice so close to GPL, that you just could have made it GPL. But a rust C-ABI library/program (e.g. a system library) is a different matter and binding in a LGPL C-ABI library into a rust project still somewhat practical doable (but still quite annoying).
It's still meaningful. When I worked with an F500 corporation they wouldn't allow using GPLed libraries in internal tools without specific review from legal, but LGPL was fine. And it gives someone who wants to use the library in a proprietary product the option of improving rust toolchains to support dynamic linking better; given that proprietary code authors have done things like writing a wrapper for a GPL library that then uses pipes to talk to their main code, this gives them a better route.
At no point did I suggest it requires dynamic linking. Again, I understand how the license works. I’m talking about why you would choose it if it were this difficult for someone to use your technology.
In many projects, ensuring the freedom to replace a copy of the library just isn’t worth all this trouble. If I make my code LGPL, I’m mostly shifting that burden onto other people who want to use it, not myself, and so there are presumably very few LGPL authors who are actually motivated to fix all these problems for someone else. Further, most corps will simply not use the LGPL software, because difficulty looks like license trouble. In that sense, this does look a bit like a job for the FSF, to be honest. At this rate, LGPL use will die out, and not in favour of GPL.
In another sense, a proprietary product choosing to embed my component would be a massive victory for the ecosystem it is built to support. I think that is also true for Sequoia. I just straight up don’t care about the ability to replace my component within another proprietary program. If they are using it at all, they will presumably update it themselves, it would be a pretty central dependency; if they don’t want to, they can just build their own version. I'm just hoping to get anyone to pull the trigger and drop their commercial alternative in favour of the open standard my component implements. So is Sequoia; their livelihood depends on it. Will they hack on rustc to make it easier to use? Somehow I think they will not! This makes no sense to me.
A lot of open source today cares less about LGPL-style replaceability and more about adoption of an open standard that is separate from the code itself. In this case it’s PGP-compatible encryption and signing, which has famously never really taken off and by some odd coincidence never had a project of Sequoia's quality with e.g. a BSD-style license that you could simply slap in a project and depend on. (Although much of the blame deservedly goes to GPG providing over a hundred intricate and one must presume deliberately hard-to-reproduce APIs.) In Kubernetes-land, the concept of being k8s-compatible and interoperable is arguably responsible for more freedom than the core software itself. This is simply true of so many things, and further you must admit: Sequoia as code is 100% replaceable by a motivated corporation, if only there were more demand for being compatible with PGP. If you’re still thinking in 2021 that if PGP were in demand the only reason Amazon would be shipping software without a user-serviceable Sequoia package is the LGPL, you haven’t seen how many hundreds of thousands of dev job ads they posted in the last month. Adoption of the open standard is just more important than anyone’s actual code, up until the codebase is so big it would be prohibitively difficult to replicate. If you think your code in particular is special, maybe you're right, or maybe it's just the rare piece of software whose existence is not entirely justified by an open standard.
It would work the same way that it works for programs written in languages that aren't Rust. You're doing the classic thing where you're conflating a language with a given implementation.
The free software advocate's take: You say the toolchain from rust-lang.org makes this difficult? Granted—I'll take your word for it. Go fix that toolchain. (And as a side note, the fact that rust-lang.org chose LLVM is likely to do the opposite of cultivating sympathy.) It's a lot like the saying that goes something like, "poor planning on your end does not automatically make for an emergency on my end."
There’s a case to be made that Sequoia or another LGPL user should also invest in making it easier to comply with the LGPL with Rust tooling. But I doubt that will happen anytime soon.
I assume requiring a very specific compiler version would still satisfy the letter of the license. The compiler is publicly available, so you could replace the LGPL part. You get no promises about being able to replace or even maintain anything else.
BTW, Rust's objects/rlibs may contain bitcode and a high-level form of generic/inlineable code, so they should be much easier to reverse/decompile than an optimized binary. If the goal was to keep the non-LGPL part closed, it won't work well.
> (1) If you statically link against an LGPLed library, you must also provide your application in an object (not necessarily source) format, so that a user has the opportunity to modify the library and relink the application.
Now to get the "oh C objects" thing out of the way, GPLv3 defines:
> “Object code” means any non-source form of a work.
Still this means what you need is to distribute you application in a partial compiled state which can be relinked with the LGPL library (or a updated version)
to re-produce the final application. (You also might need to provide the tools to do so if they are not freely available.)
Also let's not forgot the context, i.e. you don't want (or can't) provide the source code of the "main application" which links against the LGPL library.
Now if you program in C, providing a (set-of) pre-compiled pre-symbol stripped objects is feasible.
But most (new) programs are not in C anymore and most new languages do not have clear ABI boundaries at library level. Only clear API boundaries.
A good example are generics or template programming.
E.g. even in C++ if there is heavy use of template programming around the library boundary can make LGP infeasible for that use case. And we are still in C++ which is rather close to C in how it compiles stuff.
If we go a step further, e.g. into Rust it becomes even more of a mess. (It is possible, at least theoretically, with a lot of hacks and restrictions, but totally a nightmare not worth even considering. And again if generics are used a lot, all the generic code at the interface boundary leaks.)
Then there is the additional complexity this introduces to CI.
So possible yes, but for many projects not worth considering.
> What the LGPL requires is that the LGPL part can be replaced.
Not quite, they require you to provide intermediates which can be re-linked with a alternate version of the library.
Which means if you want to e.g. provide the functionality through binary patching it gets tricky, because you need to provide a binary without the LGPled library (1) which you then can "patch" the library into. Instead of being able to provide a binary with the LGPled library in it and allowing you to replace/update it. Which means various approaches around binary patching just became way more complex.
(1): The reason for it is that the object you provide falls itself under license terms.
So ya, no dynamic linking requirement. But for some modern languages still a major problem. And conceptually too closely bound to the concept of the C-compilation process IMHO.
> A good example are generics or template programming. E.g. even in C++ if there is heavy use of template programming around the library boundary can make LGP infeasible for that use case. And we are still in C++ which is rather close to C in how it compiles stuff.
... You think people haven't solved this problem for literal decades in c++ ?
If your LGPL lib uses a template :
If it gets inlined the license says that it's fine and not breaking LGPL that you won't be able to change the call sites. All c++ compilers will still produce a non-inline version of the symbol with weak linkage that can be replaced in the cases where inlining did not happen. Surely rust does the same in order to comply with LD_PRELOAD semantics ? (Even MSVC does that inline symbol exporting afaik).
Like, you think people who wrote the LGPL did not consider the case of macros in C for instance ?
> If we go a step further, e.g. into Rust it becomes even more of a mess. (It is possible, at least theoretically, with a lot of hacks and restrictions, but totally a nightmare not worth even considering. And again if generics are used a lot, all the generic code at the interface boundary leaks.)
If that's such a nightmare then don't depend on the work of people who wrote LGPL libs and find an alternative instead ?
Linking weather dynamic and static is basically connecting interfaces.
Law is (in my understanding) normally based on concepts not technical implementation details.
As such for me the idea that there is a difference legal between static linking, dynamic linking or "linking together by a unix-pipe" sounds strange and irritating.
Instead I would argue weather or not something is a derivative of something else should depend on the conceptual usage of that thing, not some technical
implementation detail.
SequoiaPGP provides a C FFI interface, which can be dynamically linked against from any C-compatible language. Though safe wrappers would have to be written around that to be able to use it from Rust, which is kind of going full circle. It'd be interesting if a Rust FFI interface could be defined (using abi_stable[0] or something).
I believe git just uses the gpg commandline; in a quick grep of the source I don't see it use any GnuPG includes/functions at all (and gpg-interface.c just runs pipe_command()), but maybe I missed it.
That's great, but it's a Rust library, which would be nice to use from Rust, without going through a C FFI layer for the sole purpose of license compliance.
It feels like the Rust ecosystem is a second class citizen due to this license. The GPL or MPL would at least enforce the same rules for everyone, but the LGPL gives a relative advantage to the C and C++ ecosystem over the Rust ecosystem in terms of actually using the library.
Static linking good for vendor, dynamic linking good for maintainers. Some distros already made exception from "no bundled libraries" rule for Rust. Now we need to add another exception just for Rust. Maybe, it's time for Rust to catch up and implement dynamic linking instead?
Rust does support dynamic linking. But it suffers from the same issues C++ does: Code using generics will get inlined into your final binary, the ABI is unstable so you need to make sure you use the same compiler version, etc...
All those can technically be worked around, but it's more work for the maintainer. Dynamic linking is actually worse for the maintainer here, as it force them to have a stable ABI, which is a lot of work!
You don’t need to provide special tooling, you only have to provide the source code of your own program so that the program can be recompiled with a different version of the LGPL-licensed library.
Your source code can be released under another license, even a proprietary license, provided that the user can physically undertake the necessary steps to produce a new executable that interoperates with an updated or modified version of the LGPL-licensed package. The idea is that the LGPL-licensed portion of the final runtime program should itself be open source in the sense of being modifiable in a useful way by the end user.
From the article:
> Delta Chat planned an iOS app, but because Apple does not allow GPL software in their App store, the Delta Chat developers couldn’t use Sequoia.
I don't think this is true in theory or in practice, for the iOS App store or the Mac App Store. Take the WordPress app for example.
I took a brief look at a few of those and it looked like they either only included code that they owned the copyright to or that was under a more permissive license than GPL.
Putting your own GPL code in your iOS app is fine. The issue with GPL on the iOS store arises when you put someone else's GPL code in your iOS app.
The problem is that that the terms of use that the user must agree to in order to use the store place restrictions on what the user can do with the software they obtain through the store. These restriction are at odds with the GPL requirement that you not place additional restrictions on GPL software you distribute.
For Apple to distribute GPLed software on the Apple store, the copyright holder has to give them permission to do so on terms other than GPL. In the case where the developer who places the GPL app on the store is the copyright holder to the entire app this is no problem. They have had to agree to Apple's terms for developers in order to be allowed to upload. I've forgotten what exactly is in those terms, but I'm almost certain there is something in there that requires the developer to give Apple permission to distribute.
That permission that a developer of a GPLed app (or an app under any other license) gives to Apple to make and distribute copies only applies to code owned by that developer. If they have included any third party GPL code from owners who have not granted Apple that permission, then the app as a whole will not be legal for Apple to distribute.
In summary, distributing on the Apple app store requires that you give Apple a license to make and distribute copies under Apple's terms, which are not GPL compatible. Apple does not care what license you give to anyone else, so it is fine to go with "GPL for everyone plus this special license for Apple".
> The issue with GPL on the iOS store arises when you put someone else's GPL code in your iOS app.
If that were true, Cisco wouldn't be shipping iOS apps with LGPL code from GStreamer in it.
> These restriction are at odds with the GPL requirement that you not place additional restrictions on GPL software you distribute.
No, the GPL wording is that any additional restriction can be ignored by the end-user.
Quoting:
> If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term.
My understanding is that Apple's terms of service are incompatible with the GPL. If you hold the copyright yourself though, you have no need to abide by the license and can distribute it on the App Store under different terms.
If there are any GPL apps in the App Store, it's only because Apple is terrible and inconsistent in enforcement of their own rules.
App Store developer agreement requires you to license your app to Apple on Apple's terms, including geo restrictions, max number of installs, and other things that are incompatible with GPL.
There is a gpg program config key for Git[0], but beyond that I am not sure what else would need to be done. I am sure a blog post describing your experience would be well-received.
I tried a bit (i'm only using gpg for my pass keyring, but as pass is dead simple i wanted to write a clone and hack around sequoia), but i found the command-line interface to be missing some features. As a showstopper it doesn't seem to allow on-the-fly decryption of secret keys to sign/encrypt stuff (at least i didn't get it to work). Also, there are very few options for editing secret keys (subkeys, managing certifications). Keyrings are amusingly barebone: they are just concatenated keys (as armored ascii), seems to do the job.
I'm confident this will improve in the matter of a handful of months tho. I didn't check but i'd bet this is mostly a problem of writing the front-end cli code to advertise all the library features. They seem to be pretty active, 1.0 on the lib was cut not so long ago and 'sq' (the executable) is still pre 1.0. Other execs are sqv (verifier) and sqop ("stateless command interface", seems to be oriented at scripting, apparently aiming to drive interop between implementations).
This is an excellent UVP to have over GnuPG. I'll probably end up using sequoia for my app for this reason alone (amusing it's dependency graph is manageable).
i’ve still not seen a good reason for going to a “more permissive” license for “pragmatic” reasons, when the language being cast off is the gpl, 2, 2+, 3, you choose. not many good results either.
Why was LGPL chosen instead? The LGPL requires that all applications that consume it as a static library provide the tools to re-link the binary against modified forms [0], which seems incredibly problematic to manage with the Rust toolchain.
I like the idea behind the LGPL conceptually, but in practice the LGPL is strongly tied to the way Linux applications and libraries were developed in the 90s and 2000s - namely, in C, with dependencies that are generally dynamically linked, with C-like toolchains that directly expose all of the intermediate object files. It just doesn't make a whole lot of sense for any software outside of that bubble.
[0] www.gnu.org/licenses/gpl-faq.html#LGPLStaticVsDynamic