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:
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.
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).
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:
- 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;
}
- 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.