一、Qt License 分析
1.1 LGPL V2 与 LGPL V3
GPLv3 协议中讨论最为广泛的新要求,即要求在"用户产品"中提供 GPLv3 代码的"安装信息”。
提供"安装信息"要求旨在保护用户权利,让用户可以修改其所购买和使用的产品中嵌入的 GPLv3 代码,并运行修改后的版本。
如果没有此条款,则"锁定"设备以阻止法定持有人修改软件便会损害 GPL 许可证作者希望用户拥有的自由权利。如果所有嵌入式设备都执行此类锁定,则如美国最高法院曾经说过的一样,GPL 所保证的自由权就会变成"空头支票”。
"用户产品"指"消费品",即通常用于个人、家庭或日常使用的有形个人财产,任何为了安装到住所而设计或销售的产品。
“用户产品"在通过永久转让所有权或控制权,或者基于固定期限出借或出租时,产品中 GPL 程序的非源码形式副本便已向用户发布。向用户提供对应源码时应随附足够的技术信息,方法、过程、授权密匙,或安装和执行用户产品中的修改版 GPL 软件所需的其他信息。这些信息必须足以保证修改后的目标码不会仅因遭到修改而无法继续执行,除非设备中采用了技术措施来阻止修改版本的安装和执行,否则此要求无关紧要。
因此从 2007 年以来的经验可以看出,如果生产厂商想要锁定其产品,则应避免使用 GPLv3软件。(注:锁定产品的意思,就是禁止用户可以修改软件)
1.2 LGPL 开发闭源程序
LGPL 协议是一个商业友好的协议,使用 LGPL 开发闭源程序,有以下两种情况:
- 使用动态链接的形式,那么可以以任何形式发布你的应用程序,商业的、非商业的、开源的、非开源的。
- 因某种原因必须静态链接一个基于 LGPL 协议发布的库,那么,你有义务进行下面的工作
- 你必须在你的文档中说明,你的程序中使用了 LGPL 库,并且说明这个库是基于 LGPL 发布的
- 你必须在你的应用程序发布中包含一份 LGPL 协议,通常就是那个文本文件
- 你必须开放使用了 LGPL 库代码的所有代码,例如某些封装器。但是,其他使用这些封装器的代码就不需要开放了
- 你必须包含你的应用程序的余下部分的目标文件(通常就是我们所说的 .o 等等),或者是其他等价的文件。源代码并不是必须的
但是对于嵌入式来说,如果生产厂商想要锁定其产品,不允许用户修改,则应避免使用 LGPLv3 协议发布的软件。
1.3 Qt 的 License 变化历程
Qt 2 后源码授权许可证开始使用GPL,Qt 4.0 发布时它拥抱了 GPLv2,2009年收购 Trolltech 诺基亚为 Qt 加入了 LGPLv2.1,LGPLv2.1 存在漏洞,没有澄清使用修改库的问题,这个漏洞被企业广泛利用开发锁定的设备,开发者认为,使用 LGPLv2.1 授权的修改版 Qt 去创建锁定设备伤害了 Qt 的生态系统。
因为设备不对第三方公开,对生态系统没有任何贡献。LGPLv2.1 没有保护用户的自由,自由软件基金会的 LGPLv3 解决了这个问题。LGPLv3 开源许可证将能在用户使用开源版的 Qt 时确保用户自由,LGPLv3 明确禁止封闭嵌入式设备分发 LGPLv3 授权的软件。
从 5.4 开始 Qt 将采用 LGPL v2.1、LGPL v3 和商业许可证授权,而新的附加模组将只在 LGPL v3 和商业许可证发布。在 Qt 4.0 到 Qt 5.3 的版本使用 LGPLv2.1,并且随着版本的更新越来越多的模块不再使用 LGPLv2.1。
Qt License 更改的官方新闻:Adding LGPL v3 to Qt
二、Qt 开源版与商业版的区别
2.1 桌面端
对于桌面应用,不管是 Window,还是 Linux 上的桌面应用,只要不用静态编译别修改 Qt 源码就可以了,就一堆 dll 或者 .so 加上 exe 这种方式就是合法的。默认你用 windeployqt 生成的那个打包下就可以了。这个理论上还要求你写软件说明的时候声明下用了 Qt 程序库,Qt 程序库是 LGPL 协议的,把 LGPL 协议的文档弄个文本文件跟你的程序放一起。就类似下面这种,exe 跟 dll 一起,有个 LGPL 文档说明,软件的帮助或者配套文件里说下用了 LGPL 协议的 Qt 就行了。国内用 Qt 商用的很多,商业完全没问题的。Qt 的 Python 绑定特意出了个 PySide 就是为了支持 LGPL 好支持商用,PyQt 不支持LGPL,商用不友好。
2.2 嵌入式
由于从 5.4 开始 Qt 主要采用 LGPL v3 授权,而 LGPLv3 明确禁止封闭嵌入式设备分发 LGPLv3 授权的软件,所以在嵌入式下不能使用 Qt 5.4 以及以上的版本进行商用,当然 Qt 5.3 以及以下的版本还是可以。
Qt 有三个许可证:GPL、LGPL 和 Commercial(商业协议)。
这几个协议在现在的 Qt 版本中的代码是完全一致的(Qt 的早期版本,商业版的 Qt 通常包含有一些开源版本所没有的库,比如 QtSingleApplication 这个库)。
Commerical License
Commercial License相较于GPL和LGPL,对于商业客户提供了更多的灵活性,客户可以任意的修改Qt的源代码,开发商业软件,而不需要公开任何源代码。并且,在Commercial License中,还提供了技术支持服务。
除了商业授权,目前 Qt 的开源授权有两种,一种是 GPL 授权,另一种是 LGPL 授权(诺基亚收购后新增)。
GPL
简单来说,使用 GPL 版本的软件一定还是 GPL 的开源软件,无论是使用了 Qt 的程序代码还是修改了 Qt 库代码,都必须按照 GPL 来发布,这是 GPL 的传染性。
如果你打算开发真正的开源软件,并希望使用者也可以保持开源,那么GPL是更好的选择,因为所有人,不论你自己还是将来基于你的代码进行再次开发都必须开源。
GPL 是什么都要开源,这对商业软件应用是不利的,所以诺基亚增加了 LGPL 授权 (第一个 L 可以叫 Lesser 宽松版或 Library 开发库版)。使用 LGPL 授权就可以利用 Qt 官方动态链接库,而不必开放商业代码。只要不修改和定制 Qt 库,仅使用 Qt 官方发布的动态链接库就可以不开源,这是商业友好的授权模式。
LGPL
LGPL 是一个开源协议,因此,有人会担心 LGPL 能否用于开发闭源程序,能够拿来卖钱。尽管现在国内有些公司不是很重视这方面的问题,不过,如果你违反了协议,某一天被别人发来一纸律师函的时候,真的是欲哭无泪了哦。所以,我们还是先来研究一下这个协议,LGPL 究竟能不能用于开发闭源程序。
以下内容是我查找了 N 多网站总结出来的,因为不是律师,所以 LGPL 协议基本看不懂。究竟怎样去理解这个协议,还是希望能够有专业人士说出来。这里就算做是一种抛砖引玉吧!尽管没有十分的确定,但是这里所说的理解基本也是八九不离十的了。
我们关心的是,如何使用 LGPL 协议开发商业程序。请注意,这里所说的闭源程序,是指不以某种形式开放源代码,也就是说,用户(包括其他开发者)不能获取其源代码的程序。
首先说明一点,LGPL协议是一个商业友好的协议。这里的含义是,你可以用 LGPL协议开发商业程序,当然也可以是非商业的闭源程序。但是,它是有一些限制的。这就是我们要讨论的重点。
既然我们已经对其定性,那么我们直接进入主题:
一、使用 LGPL 协议开发闭源程序,如果你使用动态链接的形式,那么,你可以以任何形式发布你的应用程序,商业的、非商业的、开源的、非开源的,随你。
二、如果你因某种原因必须静态链接一个基于 LGPL 协议发布的库(以下我们简称为 LGPL 库),那么,你有义务进行下面的工作:
1> 你必须在你的文档中说明,你的程序中使用了 LGPL 库,并且说明这个库是基于 LGPL 发布的;
2> 你必须在你的应用程序发布中包含一份 LGPL协议,通常就是那个文本文件;
3> 你必须开放使用了 LGPL 库代码的所有代码,例如某些封装器。但是,其他使用这些封装器的代码就不需要开放了;
4> 你必须包含你的应用程序的余下部分的目标文件(通常就是我们所说的 .o 等等),或者是其他等价的文件。源代码并不是必须的。
首先,如果只涉及到动态链接,按照第一条规则,基本不需要做任何事情,正常发布商业应用。
如果涉及到基于LGPL协议发布的静态库,按照第二条规则就比较难理解,我们需要详细的说一下:
第1条很容易理解;
第2条也很容易理解,你可以在这里找到 LGPL 协议的内容,复制下来随你的程序一起发布就可以了。
第3条就不那么好理解了。简单来说,LGPL协议要求,如果你的类使用了LGPL库的代码,那么必须把这个类开源。例如,如果你的程序 app.exe 每个源文件都使用了 LGPL 库的代码,那么你的所有源代码都要开源。为了避免这种情况,我们通常编写一个封装器,把 LGPL库的代码封装起来,这样就只需要开放这个封装器的代码,而其他使用了这个封装器的代码就不需要开放。
第4条是对第三条的一种补充:那些使用了封装器的程序不需要开源,但是你必须把你编译的那些中间文件开放出来,Windows 下就是那些 .o 文件。
你很奇怪,为什么 LGPL协议要这样规定呢?
LGPL 所做的工作是,它保证了用户能够有这样一种能力:修改你使用 LGPL 库函数的方式(那些封装器就是你使用 LGPL库的方式,那些已经开源了),重新编译这些代码,然后重新对程序进行连接(连接所需要的目标文件也是包含了的,这是第4条规定的),就可以得到一个新的可执行程序。
好了,如果你还不明白如何使用,我们来看一个例子:
假设我们使用一个名为 Lib 的库,这个库是基于 LGPL协议发布的。如果你使用 Lib.dll 做动态链接(Windows 下),好,一切 OK。无论你的程序怎么样,你都可以做你所做的事情。
我们主要是来看,如果你要使用静态链接,那么你需要如何组织你的代码。如果你有一个 main.cpp(我们假设所有 Lib 库的函数都是用了 lib_ 前缀):
// main.cpp
int main()
{
lib_init();
lib_do_something();
lib_done();
lib_close();
return 0;
}
现在你已经完成了 main.cpp,但是你必须把它开源!因为它使用了 LGPL 库的代码。
这是上面第3条规定的。我不想把它开源,怎么办呢?好,我们建一个新的文件 lib_wrapper.cpp:
void my_lib_init()
{
lib_init();
}
void my_lib_do_something()
{
lib_do_something();
}
void my_lib_done()
{
lib_done();
}
void my_lib_close()
{
lib_close();
}
在 main.cpp 中,我们做相应的修改:
int main() {
my_lib_init();
my_lib_do_something();
my_lib_done();
my_lib_close();
return 0;
}
现在,main.cpp 不再是直接使用了 LGPL 库的代码了,因此它不需要开源,而我们的封装器 lib_wrapper.cpp 必须开源。
好,编译一下我们的程序,你会得到 main.o(Windows 下)这个目标文件。
在最终程序的发布中,你需要包含一下文件:
1) 一份文档,其中声明:这个程序使用了 Lib库,这个库是基于 LGPL 协议发布的;
2) LGPL.txt;
3) lib_wrapper.cpp
4) main.o
这样,用户可以通过修改 lib_wrapper.cpp 的内容改变你使用 LGPL 库的方式,例如:
void my_lib_done()
{
lib_done();
lib_close();
}
void my_lib_close()
{
// lib_close();
}
然后编译这个 lib_wrapper.cpp,最终重新链接,一个新的可执行程序诞生啦!
好了,这就是在使用 LGPL库开发闭源程序所需要遵守的东西了。
还是建议大家能够遵守协议,尊重作者的劳动成果哦~。
本文参考了下列文章的资料,在此表示感谢:
https://blog.csdn.net/aisq2008/article/details/72867134?spm=1001.2014.3001.5501
如果只使用Qt的动态链接库(大多数是这种方式):
闭源商业软件免费使用LGPL版的Qt必须满足如下条件:
1、不修改Qt源代码。
2、必须用动态链接的方式使用Qt库。
3、在软件版权声明中说明使用了LGPL版本的Qt、说明具体使用了那些Qt库,并确保软件使用者了解。
4、在发布的软件中包含Qt原有版权声明。