Bambu Lab 多次违反开源许可证,知名 YouTuber 彻底弃用

2026-05-18 16 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:11 分钟

Jeff Geerling——树莓派和 3D 打印圈子里拥有百万订阅的 YouTuber——最近发了一则声明:他已彻底弃用 Bambu Lab 的 3D 打印机。这不是一时冲动。早在 2025 年他就公开表示"可能不会再推荐任何 Bambu Lab 打印机",但后续发生的事让他把"可能"变成了"确定"。

核心原因:Bambu Lab 多次违反开源许可证。

违规的具体指向

Bambu Lab 的打印机固件和配套软件中,大量使用了 GPL、LGPL 等强 Copyleft 许可证的开源组件。按照这些许可证的要求,如果你分发基于 GPL 代码的衍生作品,必须同时提供完整的源代码,且不得施加额外限制。

社区反复指出的问题包括:

  • 固件中使用了 GPL 组件但未公开对应源码。Bambu Lab 曾发布过部分源码包,但社区比对后发现缺失关键模块,版本也不与实际分发固件匹配——这直接违反 GPL v2/v3 的"对应源码"条款。
  • 云端服务与本地固件深度绑定,用户无法自由修改或替换软件。GPL 许可证赋予用户修改和再分发的权利,但 Bambu Lab 的架构设计实际上让本地修改变得不可行:固件强制连接云端,绕过云端则功能受限甚至无法使用。
  • 锁闭硬件接口。部分社区开发者尝试刷入自编译固件时发现,Bambu Lab 对硬件接口做了限制,使得替换固件的操作风险极高或直接不可行。GPL v3 明确要求不得用硬件锁阻止用户运行修改后的软件。

这不是一次疏忽,而是反复出现、被社区多次指出后仍未彻底纠正的模式性行为。

为什么这不是"小节"

开源许可证不是建议,是法律合同。GPL 的 Copyleft 机制是整个开源生态的基石之一:

  • 对开发者而言:你贡献代码时选择了 GPL,意味着你要求下游也必须开源。企业拿走你的代码、闭源分发、还锁住硬件——这直接剥夺了你选择 GPL 的初衷。
  • 对用户而言:GPL 保证你能审查、修改、改进你设备上运行的软件。3D 打印机固件直接控制加热、运动等安全相关参数,用户无法审查源码意味着无法确认安全逻辑是否可靠。
  • 对行业而言:如果一家公司能反复违反 GPL 而不承担实质后果,其他公司也会跟进。开源社区的信任成本会急剧上升。

Jeff Geerling 的弃用声明之所以引发广泛关注,正是因为他不是普通用户——他的推荐和批评直接影响大量消费者的购买决策。一个百万级影响力的创作者公开说"不再推荐",对品牌的打击远超论坛帖子的抱怨。

实践:用脚本检查你的项目是否合规

如果你是开发者,无论你是使用开源组件还是发布基于 GPL 的项目,都应该主动检查许可证合规性。下面是一个可直接运行的 Python 脚本,扫描指定目录下的源码文件,报告缺失许可证头或使用了 GPL 但未在项目根目录提供 COPYING/LICENSE 文件的情况。

#!/usr/bin/env python3
"""
license_check.py — 扫描目录,检查开源许可证合规性
用法: python3 license_check.py /path/to/project
"""

import os
import re
import sys

GPL_PATTERN = re.compile(
    r'(GPL|gpl|General Public License)', re.IGNORECASE
)
LICENSE_FILE_NAMES = [
    'COPYING', 'LICENSE', 'LICENCE', 'COPYING.txt', 'LICENSE.txt',
    'LICENSE.md', 'LICENCE.md',
]

def find_license_files(root):
    """在项目根目录查找许可证声明文件"""
    found = []
    for name in LICENSE_FILE_NAMES:
        path = os.path.join(root, name)
        if os.path.isfile(path):
            found.append(path)
    return found

def scan_source_files(root):
    """扫描 .py/.c/.h/.cpp/.js 文件,检查是否包含 GPL 引用"""
    extensions = {'.py', '.c', '.h', '.cpp', '.js', '.ts', '.go', '.rs'}
    gpl_refs = []
    no_license_header = []

    for dirpath, _, filenames in os.walk(root):
        # 跳过常见非源码目录
        skip_dirs = {'node_modules', '.git', 'venv', '__pycache__', 'build', 'dist'}
        if any(s in dirpath for s in skip_dirs):
            continue
        for fn in filenames:
            ext = os.path.splitext(fn)[1]
            if ext not in extensions:
                continue
            full_path = os.path.join(dirpath, fn)
            try:
                with open(full_path, 'r', errors='ignore') as f:
                    content = f.read()
            except Exception:
                continue

            if GPL_PATTERN.search(content):
                gpl_refs.append(full_path)

            # 检查前 20 行是否有许可证/版权声明
            head = content.splitlines()[:20]
            has_header = any(
                'copyright' in line.lower() or 'license' in line.lower() or 'spdx' in line.lower()
                for line in head
            )
            if not has_header:
                no_license_header.append(full_path)

    return gpl_refs, no_license_header

def main():
    if len(sys.argv) < 2:
        print("用法: python3 license_check.py /path/to/project")
        sys.exit(1)

    root = sys.argv[1]
    if not os.path.isdir(root):
        print(f"目录不存在: {root}")
        sys.exit(1)

    license_files = find_license_files(root)
    gpl_refs, no_header = scan_source_files(root)

    print(f"=== 许可证合规扫描: {root} ===\n")

    print(f"根目录许可证文件: {len(license_files)}")
    for f in license_files:
        print(f"  ✓ {os.path.basename(f)}")

    if not license_files:
        print("  ⚠ 未找到 COPYING/LICENSE 文件!如果项目包含 GPL 代码,这是违规的。")

    print(f"\n引用 GPL 的源文件: {len(gpl_refs)}")
    for f in gpl_refs[:10]:
        print(f"  • {f}")
    if len(gpl_refs) > 10:
        print(f"  ... 还有 {len(gpl_refs) - 10} 个文件")

    if gpl_refs and not license_files:
        print("\n❌ 严重问题: 项目包含 GPL 引用但缺少许可证声明文件,违反 GPL 分发要求。")

    print(f"\n缺少版权/许可证头的文件: {len(no_header)}")
    for f in no_header[:10]:
        print(f"  • {f}")
    if len(no_header) > 10:
        print(f"  ... 还有 {len(no_header) - 10} 个文件")

    if no_header:
        print("  ⚠ 建议为这些文件添加 SPDX 或版权声明头,便于合规审计。")

    print("\n--- 扫描完成 ---")

if __name__ == '__main__':
    main()

运行方式:

# 扫描你自己的项目
python3 license_check.py ~/my-firmware-project

# 扫描一个你下载的第三方源码包,看看它是否合规
python3 license_check.py ./bambu-firmware-source

脚本会报告三类问题:根目录是否缺少 COPYING/LICENSE 文件、哪些源码引用了 GPL、哪些文件缺少版权声明头。这不是完整合规审计——完整审计需要比对二进制与源码版本、检查依赖树——但它是第一步快速筛查。

给开发者与用户的建议

如果你是 3D 打印机用户:

  • 购买前查清楚固件许可证。Prusa、Voron 等品牌的固件开源记录更透明。
  • 如果你关心安全审查权,优先选择允许刷入自编译固件且不强制云连接的机型。
  • 已有 Bambu Lab 打印机的用户,关注社区(如 GitHub issue、Reddit r/3Dprinting)的合规进展,保留要求源码的权利。

如果你是开源贡献者:

  • 在项目中明确声明许可证,使用 SPDX 头,让合规检查工具能自动识别。
  • 如果你发现某公司违反了你代码的 GPL 许可证,可以先在项目 issue 中正式记录,再考虑联系 FSF 或 SFLC 等组织寻求法律支持。
  • 定期用上述脚本或 licensee(GitHub 开源的许可证检查工具)扫描自己的项目,确保分发时没有遗漏。

如果你是企业方:

  • 使用 GPL 组件前,确保你有完整的合规流程:源码包与分发二进制版本一一对应、COPYING 文件齐全、不施加硬件锁或云绑定限制。
  • 一次合规疏忽可以修补,反复无视社区指出的问题则会付出品牌信任的代价——Bambu Lab 正在演示这条路径的终点。

开源许可证的约束力来自社区持续的关注和行动。Jeff Geerling 的弃用声明是一个信号:当技术影响力者开始把许可证合规纳入推荐标准,闭源搭便车的商业模式会越来越难维持。


相关推荐