Vendoring and "Dynamic" Programming Languages

On the “Choose a License” page of Write Free Software, the main differences between Mozilla Public License 2.0 and GNU Lesser General Public License is whether vendoring is allowed. Vendoring is described as:

The practice of copying library files directly into another project instead of linking them separately

In “dynamic” programming languages like JavaScript, Python and Ruby, the concept of linking doesn’t really exist (I guess it is also true for languages like Rust, but yeah). So that means when I build an open source library for one of these languages, and I have the following goals:

  • People should be allowed to use any license they desire for their application using my library
  • People should offer all changes they do to the library as open source

MPL2 would be a good choice for me, right?

And, related to that, in browser-side JavaScript, in most cases, people use “bundling” to convert their code and all their dependencies into one or multiple output JavaScript files. This means that all the code of the dependencies is “vendored”, right?

MPL2 would be a good choice for me, right?

I think so, yes, given the description of your requirements.

And, related to that, in browser-side JavaScript, in most cases, people use “bundling” to convert their code and all their dependencies into one or multiple output JavaScript files. This means that all the code of the dependencies is “vendored”, right?

Sort of?

Vendoring is a term that applies to a practice used for distribution of source code, not executables, and the line is blurry: how does machine code materially differ from source code? How does minified JavaScript materially differ from the original? Vendoring is a practice that affects source code, linking affects executables (particularly machine code objects which use the linker), bundling is a common verb that is applied to a process which produces minified JavaScript combining many dependencies into one. What does it mean to “link” JavaScript? What does it mean to “bundle” C libraries? All of these are industry jargon with blurry applicability in various situations, and therefore inadequate for describing specific legal scenarios, which is why the word “vendoring” does not actually appear in the MPL even though it’s a useful approximation of a scenario that the MPL is designed to accomodate.

Let’s just read the source text instead. The applicable parts of the MPL text starts with a few definitions:

“Source Code Form” means the form of the work preferred for making modifications.

“Executable Form” means any form of the work other than Source Code Form.

“Covered Software” means Source Code Form to which the initial Contributor has attached the notice in Exhibit A [Exhibit A is a comment added to the source code indicating that it is covered by MPL 2.0], the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof.

“Larger Work” means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software.

So in this sense we can say, for the purposes of reading the MPL’s legal text, that unminified original JavaScript would be covered under “source code form”, the minified form is covered by the “executable form”, and the bundle is a “larger work”.

If You distribute Covered Software in Executable Form then:

a. such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and

b. You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients’ rights in the Source Code Form under this License.

You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s).

So, reading this, the assumption holds that you can bundle MPL 2.0-covered JavaScript libraries with webpack provided that you provide the MPL 2.0-covered source code and any modifications to it upon request – just as you might have suspected.

I’m curious about the LGPL in this regard. What, exactly, is it that would make the LGPL unsuitable vendoring as described here? Of course, under the condition that the bundled stuff is separated from the larger work clearly enough.

I’ve been reading the LGPL several times to try to figure out where the allowable - shall we call it “delineation” - goes. I know that everyone more or less that “as long as the LGPL’d stuff is in a shared library, you’re safe”, but that doesn’t really answer the question in my mind; it seems much more like a measure to keep a very safe distance from the grey areas.

My goal with these question is to find out the “worst case scenario” of what I allow when releasing with the different licenses. I have the answer for the MPL above, but still feel unsure about the LGPL.

(as always, i’m not a lawyer)

per LGPL 3.0 article 4, or LGPL 2.1 article 6, you have to either provide object files and/or source code of the software you are distributing, at least on request, or use it as a dynamically linked library that can be replaced. to put an example, you can take a copy of Electron or Chrome, which will have a libffmpeg.so or similar file next to it. the intention is that as a user, you can freely replace that library by yourself with a modified one, even without having the source code of Chrome.

if you go to different languages, an Electron analogy would be not putting an LGPL library in a big esbuild/webpack bundle. again, as an example, VSCode uses the jschardet node module, licensed LGPL-2.1-or-later. you can take a copy of VSCode, which just puts a copy of jschardet as downloaded from npmjs into an asar archive.

$ asar list resources/app/node_modules.asar | rg 'jschardet'
/jschardet/CONTRIBUTORS
/jschardet/LICENSE
/jschardet/dist/jschardet.min.js
/jschardet/package.json

in this case, you can find the source code of jschardet linked in ThirdPartyNotices.txt, modify it and build it yourself, and repack the archive with your own build.

many other Electron apps bundle source code of the most of the modules they use into one file, so you can’t simply replace the library. in this case LGPL compliance would still be easy - esbuild or webpack simply allow developers to not bundle specific libraries and load them separately.

but it gets very problematic in other environments. in a Flutter-based app, any Dart modules you use will end up in one AOT-compiled build of the app. that way, any Dart module licensed LGPL in your app very possibly requires you to just always release your app’s source code to comply, which effectively puts it at no difference from the GPL (unless you don’t use AOT or JIT compilation, but that’s suffering)

Ah right.

So to summarize, you could say that one of the LGPL compliance tests (spoken from a legal standpoint [*]) is whether any user can make a drop-in replacement of any LGPL-licensed part of the application.

I guess that makes for a vague answer. “Yes, on condition that the delineation is clear enough”, and otherwise seems a bit open ended.


[*] when speaking with lawyers, I’ve learned that they often think in terms of “tests”, i.e. you test a certain scenario or question against whatever legalese you have in front of you, and try to figure out if it holds or not.

More specifically, you just have to provide a means of replacing the LGPL’d code with the user’s own derivative work of the LGPL’d code. So that could mean a shared library or it could mean anything else that meets this requirement. You could make some form of webpack that tracked the provenance of each JavaScript object back to its source, then include a script which re-bundles the code with the user’s LGPL’d replacement library.