indygreg / python-build-standalone

Produce redistributable builds of Python
Mozilla Public License 2.0
2.14k stars 133 forks source link

Enable Bluetooth support #331

Open tysonclugg opened 2 months ago

tysonclugg commented 2 months ago

CPython has has supported Bluetooth with socket.AF_BLUETOOTH since version 2.4 alpha 1, but it seems the builds weren't compiled with the necessary header files:

The socket module now supports Bluetooth sockets, if the system has <bluetooth/bluetooth.h>

$ python
Python 3.13.0rc2 (main, Sep  9 2024, 22:13:26) [Clang 18.1.8 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> socket.AF_BLUETOOTH
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    socket.AF_BLUETOOTH
AttributeError: module 'socket' has no attribute 'AF_BLUETOOTH'
>>> import sysconfig
>>> {k:v for k,v in sysconfig.get_config_vars().items() if 'blue' in k.lower() or k=='MODDISABLED_NAMES'}
{'HAVE_BLUETOOTH_BLUETOOTH_H': 0, 'HAVE_BLUETOOTH_H': 0, 'MODDISABLED_NAMES': '_gdbm  _scproxy  _testcapi  xx  xxlimited  xxlimited_35'}

The relevant headers appear to be part of libbluetooth-dev (from BlueZ, the "Official Linux Bluetooth protocol stack") on Debian.

Would you like me to submit a PR?

tysonclugg commented 2 months ago

Might be a good time for a quick sanity check to confirm if any other things are missing. This issue is about ~HAVE_BLUETOOTH_H=0~ HAVE_BLUETOOTH_BLUETOOTH_H=0, can anyone else see other possible issues that might arise given the report below?

$ python
Python 3.13.0rc2 (main, Sep  9 2024, 22:13:26) [Clang 18.1.8 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print("\n".join(f"{k}={v}" for k,v in sysconfig.get_config_vars().items() if k.startswith("HAVE") and v==0))
HAVE_ALIGNED_REQUIRED=0
HAVE_ALTZONE=0
HAVE_BLUETOOTH_BLUETOOTH_H=0
HAVE_BLUETOOTH_H=0
HAVE_BROKEN_MBSTOWCS=0
HAVE_BROKEN_NICE=0
HAVE_BROKEN_PIPE_BUF=0
HAVE_BROKEN_POLL=0
HAVE_BROKEN_POSIX_SEMAPHORES=0
HAVE_BROKEN_PTHREAD_SIGMASK=0
HAVE_BROKEN_SEM_GETVALUE=0
HAVE_BROKEN_UNSETENV=0
HAVE_CHFLAGS=0
HAVE_CLOSEFROM=0
HAVE_CLOSE_RANGE=0
HAVE_CONIO_H=0
HAVE_COPY_FILE_RANGE=0
HAVE_CTERMID_R=0
HAVE_DECL_RTLD_MEMBER=0
HAVE_DECL_TZNAME=0
HAVE_DEV_PTC=0
HAVE_DIRECT_H=0
HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH=0
HAVE_EXPLICIT_BZERO=0
HAVE_EXPLICIT_MEMSET=0
HAVE_FDWALK=0
HAVE_FORK1=0
HAVE_FSEEK64=0
HAVE_FTELL64=0
HAVE_GCC_ASM_FOR_MC68881=0
HAVE_GDBM_DASH_NDBM_H=0
HAVE_GDBM_H=0
HAVE_GDBM_NDBM_H=0
HAVE_GETENTROPY=0
HAVE_GETHOSTBYNAME_R_3_ARG=0
HAVE_GETHOSTBYNAME_R_5_ARG=0
HAVE_GETRANDOM=0
HAVE_GETRANDOM_SYSCALL=0
HAVE_GLIBC_MEMMOVE_BUG=0
HAVE_IO_H=0
HAVE_IPA_PURE_CONST_BUG=0
HAVE_KQUEUE=0
HAVE_LARGEFILE_SUPPORT=0
HAVE_LCHFLAGS=0
HAVE_LCHMOD=0
HAVE_LIBB2=0
HAVE_LIBDLD=0
HAVE_LIBIEEE=0
HAVE_LIBRESOLV=0
HAVE_LIBSENDFILE=0
HAVE_LIBSQLITE3=0
HAVE_LIBUTIL_H=0
HAVE_LINUX_CAN_J1939_H=0
HAVE_LINUX_CAN_RAW_JOIN_FILTERS=0
HAVE_LINUX_QRTR_H=0
HAVE_LINUX_VM_SOCKETS_H=0
HAVE_MEMFD_CREATE=0
HAVE_MINIX_CONFIG_H=0
HAVE_NCURSES=0
HAVE_NCURSESW=0
HAVE_NCURSES_CURSES_H=0
HAVE_NCURSES_NCURSES_H=0
HAVE_NCURSES_PANEL_H=0
HAVE_NDBM_H=0
HAVE_NDIR_H=0
HAVE_NETCAN_CAN_H=0
HAVE_NETLINK_NETLINK_H=0
HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION=0
HAVE_PANEL=0
HAVE_PANELW=0
HAVE_PLOCK=0
HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP=0
HAVE_PREADV2=0
HAVE_PROCESS_H=0
HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP=0
HAVE_PTHREAD_DESTRUCTOR=0
HAVE_PTHREAD_INIT=0
HAVE_PTHREAD_STUBS=0
HAVE_PWRITEV2=0
HAVE_READLINE_READLINE_H=0
HAVE_RL_APPEND_HISTORY=0
HAVE_RL_CATCH_SIGNAL=0
HAVE_RL_COMPDISP_FUNC_T=0
HAVE_RL_COMPLETION_APPEND_CHARACTER=0
HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK=0
HAVE_RL_COMPLETION_MATCHES=0
HAVE_RL_COMPLETION_SUPPRESS_APPEND=0
HAVE_RL_PRE_INPUT_HOOK=0
HAVE_RL_RESIZE_TERMINAL=0
HAVE_RTPSPAWN=0
HAVE_SEM_CLOCKWAIT=0
HAVE_SOCKADDR_SA_LEN=0
HAVE_STAT_TV_NSEC2=0
HAVE_STRLCPY=0
HAVE_STRUCT_STAT_ST_BIRTHTIME=0
HAVE_STRUCT_STAT_ST_FLAGS=0
HAVE_STRUCT_STAT_ST_GEN=0
HAVE_SYS_AUDIOIO_H=0
HAVE_SYS_BSDTTY_H=0
HAVE_SYS_DEVPOLL_H=0
HAVE_SYS_DIR_H=0
HAVE_SYS_ENDIAN_H=0
HAVE_SYS_EVENT_H=0
HAVE_SYS_KERN_CONTROL_H=0
HAVE_SYS_LOADAVG_H=0
HAVE_SYS_LOCK_H=0
HAVE_SYS_MEMFD_H=0
HAVE_SYS_MKDEV_H=0
HAVE_SYS_MODEM_H=0
HAVE_SYS_NDIR_H=0
HAVE_SYS_RANDOM_H=0
HAVE_SYS_SYS_DOMAIN_H=0
HAVE_SYS_TERMIO_H=0
HAVE_TZNAME=0
HAVE_USABLE_WCHAR_T=0
HAVE_UTIL_H=0
HAVE_UUID_CREATE=0
HAVE_UUID_ENC_BE=0
HAVE_UUID_H=0
HAVE_ZLIB_H=0
HAVE__GETPTY=0
bluss commented 1 month ago

Hi, good notion to check all the HAVE flags.

zanieb commented 1 month ago

I'm pretty hesitant to add more build configurations, the matrix is already huge.

tysonclugg commented 1 month ago

OK, so this issue (as well as #91 and #338) stem from GPL licensed modules being removed from the build. The use case for avoiding GPL licensed code is absolutely valid for some people and organisations, but I wasn't expecting the builds here to exclude parts of the Python standard library.

Sorry to be nitpicky, but I feel the following question is pertinent: When does Python cease to be Python?

In the case of MicroPython, the case for only including a small subset of the standard library is pretty clear cut, and a desired feature for the embedded use case. MicroPython is upfront about this, so there's no cause for concern:

MicroPython is a lean and efficient implementation of the Python 3 programming language that includes a small subset of the Python standard library and is optimised to run on microcontrollers and in constrained environments.

If a Python distribution doesn't include the standard library, it could be argued that it's not really Python, and instead it's something else (like MicroPython). Once again, if the project is upfront about the incomplete standard library, then there's no issue.

I am asking for one (or both) of the following to be implemented in order to resolve this issue (#331):

  1. Make it clear and upfront that parts of the standard library have been omitted from the non-GPL version of the build.
  2. Optional: Make a GPL version of the build available, and optionally make it the default version (as per project maintainer wishes).

Once again, I'm offering to submit pull requests for both of the above - let me know what you want. :slightly_smiling_face:

P.S. (regarding tone of this message): The intent of this comment is to be "constructive criticism" of the project, I've tried my best to avoid directing criticism at any people. I've often had trouble conveying things like this to others in the past. Please be nice in your replies if you feel I could do better in this regard - I'm trying my best!

tysonclugg commented 1 month ago

Looking at bluetooth/bluetooth.h in the Linux kernel Bluetooth sources, the license is there is GPL v2:

/*
   BlueZ - Bluetooth protocol stack for Linux
   Copyright (C) 2000-2001 Qualcomm Incorporated
   Copyright 2023 NXP

   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 as
   published by the Free Software Foundation;

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
   SOFTWARE IS DISCLAIMED.
*/

Further we can see the following license exceptions: GCC-exception-2.0:

SPDX-Exception-Identifier: GCC-exception-2.0
SPDX-URL: https://spdx.org/licenses/GCC-exception-2.0.html
SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-2.0-only, GPL-2.0-or-later
Usage-Guide:
  This exception is used together with one of the above SPDX-Licenses to
  allow linking the compiled version of code to non GPL compliant code.
  To use this exception add it with the keyword WITH to one of the
  identifiers in the SPDX-Licenses tag:
    SPDX-License-Identifier: <SPDX-License> WITH GCC-exception-2.0
License-Text:

In addition to the permissions in the GNU Library General Public License,
the Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs, and to
distribute those programs without any restriction coming from the use of
this file. (The General Public License restrictions do apply in other
respects; for example, they cover modification of the file, and
distribution when not linked into another program.)

Linux-syscall-note:

SPDX-Exception-Identifier: Linux-syscall-note
SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+, GPL-2.0-only, GPL-2.0-or-later
Usage-Guide:
  This exception is used together with one of the above SPDX-Licenses
  to mark user space API (uapi) header files so they can be included
  into non GPL compliant user space application code.
  To use this exception add it with the keyword WITH to one of the
  identifiers in the SPDX-Licenses tag:
    SPDX-License-Identifier: <SPDX-License> WITH Linux-syscall-note
License-Text:

   NOTE! This copyright does *not* cover user programs that use kernel
 services by normal system calls - this is merely considered normal use
 of the kernel, and does *not* fall under the heading of "derived work".
 Also note that the GPL below is copyrighted by the Free Software
 Foundation, but the instance of code that it refers to (the Linux
 kernel) is copyrighted by me and others who actually wrote it.

 Also note that the only valid version of the GPL as far as the kernel
 is concerned is _this_ particular version of the license (ie v2, not
 v2.2 or v3.x or whatever), unless explicitly otherwise stated.

            Linus Torvalds

IANAL, but does the above mean that building against bluetooth/bluetooth.h is specifically allowed in this instance, so long as the appropriate SPDX license identifiers (ie: WITH GCC-exception-2.0 AND Linux-syscall-note) are included with the correct syntax?

indygreg commented 1 month ago

The exclusion of Bluetooth support is a side-effect of the build environment lacking appropriate dependencies, not an explicit decision on my part.

zanieb commented 1 month ago

Do you want to submit a pull request adding support? It sounds like it should be fine, per the licensing exceptions.

tysonclugg commented 1 month ago

Eep, seems like it's not so clear cut, I got confused because of the situation outlined below.

The CPython source references bluetooth/bluetooth.h instead of net/bluetooth/bluetooth.h (note the net/ prefix on the latter). The former is provided by libbluetooth-dev which is provided from the BlueZ source package on Debian, the latter is provided via kernel headers files (eg: linux-headers-6.8.0-45).

Weirdly, both bluetooth/bluetooth.h in the BlueZ source mirrored on kernel.org and net/bluetooth/bluetooth.h in the kernel source are essentially the same at first glance, but the former (BlueZ, as linked from CPython) doesn't include the license exceptions. I've not tried building Python against the kernel headers, it might be a good thing to try and see if they do indeed work the same.

There's a good case that CPython itself ought to reference net/bluetooth/bluetooth.h instead of bluetooth/bluetooth.h to avoid the issue we're facing here. I guess this also raises questions about why the licenses are different, and how the BlueZ project managed to drop the license exceptions, or how the exceptions were granted for the kernel, or...

I'm not sure how to proceed at this point, but perhaps a previous comment provides a clue:

The exclusion of Bluetooth support is a side-effect of the build environment lacking appropriate dependencies, not an explicit decision on my part.

Does that mean we proceed with a GPL version of the build, and treat the inclusion of a GPL free Bluetooth build as a separate concern?

indygreg commented 1 month ago

I've gone to great lengths to not have the CPython distributions of this project tainted by GPL because this would in turn taint projects embedding these distributions.

So understanding the licensing requirements of the Bluetooth integration and ensuring it doesn't incur new copyleft requirements is a prerequisite to enabling the Bluetooth integration.

tysonclugg commented 1 month ago

I've gone to great lengths to not have the CPython distributions of this project tainted by GPL because this would in turn taint projects embedding these distributions.

Fair enough, I respect that. But I do ask that this is made clear and upfront as per my comment last week, so that everyone understands this before more bugs about missing GPL linked standard library features are raised.

Would you like me to submit a PR for the relevant documentation updates?

tysonclugg commented 1 month ago

So understanding the licensing requirements of the Bluetooth integration and ensuring it doesn't incur new copyleft requirements is a prerequisite to enabling the Bluetooth integration.

I've raised issue #989 with BlueZ that might help to resolve some of the confusion here. It seems the confusion may be very deep rooted, stemming from changes made nearly 20 years ago.

zanieb commented 3 weeks ago

Wow.. that's quite the saga. Thanks for opening the upstream issue and detailing the timeline.

I'll try to figure out who to talk to in CPython about this, given that the commit adding bluetooth support is 21 years old.