2

I asked about dynamic linking in C++ in stackoverflow (https://stackoverflow.com/q/64039902/14321464), however, I got intrigued on the responses about my desire to keep my source code uncovered by LGPL copyleft. I've been asking this as well myself and searching about it for days here in stackexchange, reading many clarifications made by various teams (such as from Teems: http://teem.sourceforge.net/lgpl.html), and googling around. This is what I understand so far:

  1. If I write and compile my source code and link LGPL library statically (via .a in Linux or .lib in Windows (...maybe? I'm not sure what is the equivalent of .a file in Windows)), I am bound to at least provide the output file (.o) from compilation of my source code so people can use their linker of choice to relink and compile the .o file into final executable using library of their choice.

  2. If I write and compile your source code and link LGPL library dynamically (via .so in Linux, or .dll in Windows), and if i decide to redistribute the .SO file as part of my software distribution, then I must provide the source code of the LGPL library that is in use and distributed (I assume, by self-hosting only, I might even be inclined to just pack the source code as part of the distribution).

  3. If I write and compile my source code and link LGPL library dynamically (via .so in Linux, or .dll in Windows), and only states that to run this program users must acquire the LGPL libraries themselves, then no source code needs to be provided to end user. I just need to state how and where those files need to be placed so the program can run.

And after reading the LGPL v2.1 and LGPL v3 back and forth, I still have 2 questions in my head:

  1. Consider this case: a LGPL v2.1 library provides set of .so / .dll files, as well as an include folder containing all .h (header) files that relates to .so / .dll (describing all the structures, classes, constructors and destructors, and all function declarations in the compiled .so / .dll).

As far as I understand, dynamic linking means that the program must be able to be run (either via terminal using ./(executable name), double clicking on the executable, or some other forms of running the executable as intended by the host Operating System) and still able to run even without the .so / .dll present (by popping up an error screen or even just force closing itself).

So, in that case, consider this example:

sampleso.hpp

#IFNDEF SAMPLESO_HPP__
#DEFINE SAMPLESO_HPP__

struct carDesc
{
    const char *model;
    int prod_year;
    int wheel_num;
    const char *license_plate;
    const char *colour;
} car;

carDesc fillCarID(void);

sampleso.cpp

#include "sampleso.hpp"

carDesc fillCarID(void)
{
    car.name = "Ford Fiesta";
    car.prod_year = 2014;
    car.wheel_num = 4;
    car.license_plate = "D 1234 ABC";
    car.colour = "Midnight blue";
    
    return car;
}

and those 2 are compiled to become libsampleso.so (g++ sampleso.cpp -fPIC -shared -Wall -ldl -o libsampleso.so). I then distribute this code as LGPL v2.1 with both the libsampleso.so and sampleso.hpp. If, later on, I use libsampleso.so by:

main.cpp (v1)

#include <iostream>
#include "sampleso.h" //<< THIS IS THE INTERESTING BIT

int main (void)
{
     carDesc fordCar;
    
     fordCar = fillCarID(); //I know this function will produce NOTHING USEFUL, but let's just pretend it is
     ...
     return EXIT_SUCCESS;
}

and compile it by dynamic linking (g++ main.cpp -Wall -Wextra -std=c++17 -L. -ldl -lsampleso -o main), is the addition of #include "sampleso.h" makes my main.cpp (V1) counted as derivative works, hence forcing main.cpp source code to be disclosed as copyleft, or not? Or do I have to go as far as using dlopen, dlsym, and dlclose to be considered dynamic linking (see main.cpp V2)? How far does FSF and LGPL count a program as dynamic linking (by just mentioning it as part of -l param enough? or do i have to literally call the library using dlopen and remove every #include "sampleso.h" anywhere in my code to be count as dynamic enough?). Everyone talked about .so and .dll, but no one talks about the inclusion of the LGPL header file and compilation of any code with LGPL header included.

main.cpp (v2)

#include <iostream>
#include <dlfcn.h> //Completely has no sampleso.hpp in it

int main (void)
{
     //... some dlopen codes here to find the libsampleso.so, and handle the error if it failed to be found in the aformentioned location ...

     struct carDesc * fordCar;
     fordCar = reinterpret_cast<struct carDesc*>(dlsym(hHandler,"car"));
    
     carDesc(*__fn_fillCarIDv)(void);
     __fn_fillCarIDv = reinterpret_cast<carDesc(*)(void)>(dlsym(hHandler,"_Z9fillCarIDv"));

     fordCar = __fn_fillCarIDv(); //doesn't work, error: function returns incomplete type "carDesc" C/C++(862), still working on how to make it work
     return EXIT_SUCCESS;
}
  1. Since LGPL v2.1 and v3 demands the ability to user to upgrade/downgrade the shared library as they see fit, while keeping the executable's ability to run, what about an executable that requires specific library version (still with dynamic linking, but specific version of .so / .dll file is made mandatory by the programmer)? That makes the user unable to upgrade or downgrade as they see fit anymore, since users are bounded to that specific library version, and if they upgrade or downgrade, the program would break too.

I'm very sorry if this question more like an essay, but coming from a country other than US, it is very difficult to interpret clearly what LGPL constitutes and where are the boundaries where LGPL applies or not to applications.

EDIT: I know about all other legal stuff required by LGPL license (mentioning the use of it in my license, providing LGPL license text in full, and hosting of LGPL codes, etc.) I just want to focus on the section 4, 5 and 6 which is still debated by many as how far someone can say that something is derivate work.

3

The LGPLv2.1 contains these paragraphs that is directly relevant to your question

When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.

If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work.

The LGPLv3 has a similar section:

3. Object Code Incorporating Material from Library Header Files.

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: [...]

In terms that can also be understood by normal humans, if you use a header file from an LGPL library which contains only

  • numerical parameters
  • data structure layouts
  • accessors for that data structure
  • small macros (less than 10 lines each)
  • small inline functions (less than 10 lines each)

then your code does not get "infected" by the LGPL terms and you can distribute your code under any license you like, including a closed source license.

It is accepted by the FSF that there is no guarantee that those portions of the library can be replaced by the end users.

| improve this answer | |
  • Thanks for the clarification on header file. That's what I sorely need after days of search. What about version lock-in tho? Is LGPL okay with it? Let say I, as the programmer, limit my program to only able to use a LGPL lib with version 1.1. And if the end user decided to upgrade & replace my .so file with version 1.2, it won't work (for tech reason, like deprecated key functions, etc. The .so file was checked for a version tag by my program and only accept specifically lib with v. 1.1)? – Jacobson123 Sep 24 at 14:18
  • 1
    @Jacobson123, the harder you try to lock your application to a single version (or even a particular build) of an LGPL library, the harder people will start to look if you are fulfilling the obligations that the LGPL places on you. And keep in mind that you are not required to give warranty and/or support on your application after people have replaced the LGPL library. – Bart van Ingen Schenau Sep 24 at 14:31
  • @BartVanIngenSchnenau Understood, thank you very much :) – Jacobson123 Sep 24 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.