2020-04-27 13:33:26 +02:00
import setuptools
2022-06-10 11:27:31 +02:00
import sys
2026-08-27 23:38:29 +02:00
import os
import shutil
import subprocess
2022-06-10 11:27:31 +02:00
pure_python = False
2026-08-27 23:38:29 +02:00
native_build = False
2022-06-10 12:46:20 +02:00
pure_notice = " \n \n **Warning!** *This package is the zero-dependency version of Reticulum. You should almost certainly use the [normal package](https://pypi.org/project/rns) instead. Do NOT install this package unless you know exactly why you are doing it!* "
2022-06-10 11:27:31 +02:00
if ' --pure ' in sys . argv :
pure_python = True
sys . argv . remove ( ' --pure ' )
print ( " Building pure-python wheel " )
2020-04-27 13:33:26 +02:00
2026-08-27 23:38:29 +02:00
if ' --native ' in sys . argv :
native_build = True
sys . argv . remove ( ' --native ' )
2026-09-10 19:37:24 +02:00
print ( " Building native wheel " )
2026-08-27 23:38:29 +02:00
2021-08-19 14:10:37 +02:00
exec ( open ( " RNS/_version.py " , " r " ) . read ( ) )
2020-04-27 13:33:26 +02:00
with open ( " README.md " , " r " ) as fh :
long_description = fh . read ( )
2026-05-18 13:46:18 +02:00
if " --getversion " in sys . argv :
print ( __version__ , end = " " )
exit ( 0 )
2022-06-10 11:27:31 +02:00
if pure_python :
pkg_name = " rnspure "
requirements = [ ]
2022-06-10 12:46:20 +02:00
long_description = long_description . replace ( " </p> " , " </p> " + pure_notice )
2022-06-10 11:27:31 +02:00
else :
pkg_name = " rns "
2023-05-04 23:19:43 +02:00
requirements = [ ' cryptography>=3.4.7 ' , ' pyserial>=3.5 ' ]
2022-06-10 11:27:31 +02:00
2025-04-08 14:36:59 +02:00
excluded_modules = [ " tests.* " , " tests " ]
2026-08-27 23:38:29 +02:00
DIRECTIVES = { " annotation_typing " : False }
NATIVE_EXCLUDES = { " RNS.Interfaces.AX25KISSInterface " ,
" RNS.Interfaces.I2PInterface " ,
" RNS.Interfaces.KISSInterface " ,
" RNS.Interfaces.RNodeInterface " ,
" RNS.Interfaces.RNodeMultiInterface " ,
" RNS.Interfaces.SerialInterface " ,
" RNS.Interfaces.WeaveInterface " ,
2026-08-27 23:56:19 +02:00
" RNS.Utilities.rngit.client " ,
" RNS.Utilities.rngit.commitsigs " ,
" RNS.Utilities.rngit.highlight " ,
" RNS.Utilities.rngit.main " ,
" RNS.Utilities.rngit.pages " ,
" RNS.Utilities.rngit.server " ,
2026-09-10 19:37:24 +02:00
" RNS.Utilities.rngit.media " ,
2026-08-27 23:56:19 +02:00
" RNS.Utilities.rngit.util " ,
" RNS.Utilities.rnsh._version " ,
" RNS.Utilities.rnsh.args " ,
" RNS.Utilities.rnsh.exception " ,
" RNS.Utilities.rnsh.helpers " ,
" RNS.Utilities.rnsh.initiator " ,
" RNS.Utilities.rnsh.listener " ,
" RNS.Utilities.rnsh.loop " ,
" RNS.Utilities.rnsh.process " ,
" RNS.Utilities.rnsh.protocol " ,
" RNS.Utilities.rnsh.retry " ,
" RNS.Utilities.rnsh.rnsh " ,
" RNS.Utilities.rnsh.session " ,
2026-08-27 23:38:29 +02:00
" RNS.Utilities.rnsd " ,
" RNS.Utilities.rncp " ,
" RNS.Utilities.rnid " ,
" RNS.Utilities.rnir " ,
" RNS.Utilities.rnodeconf " ,
2026-08-27 23:56:19 +02:00
" RNS.Utilities.rnpath " ,
" RNS.Utilities.rnprobe " ,
2026-08-27 23:38:29 +02:00
" RNS.Utilities.rnpkg " ,
2026-08-27 23:56:19 +02:00
" RNS.Utilities.rnstatus " ,
" RNS.Utilities.rnx " ,
" RNS._version " }
2026-08-27 23:38:29 +02:00
ext_modules = [ ]
compiled_modules = set ( )
build_cmdclass = { }
from setuptools . command . build_ext import build_ext as _build_ext
from setuptools . command . build_py import build_py as _build_py
if native_build :
from setuptools import Extension
from Cython . Build import cythonize
2026-08-28 00:09:16 +02:00
native_opt = os . environ . get ( " RNS_NATIVE_OPT " , " -O3 " )
2026-08-27 23:38:29 +02:00
if sys . platform == " win32 " : native_cargs = [ ]
else : native_cargs = [ native_opt , " -g0 " , " -fno-lto " ]
rns_root = " RNS "
for root , dirs , files in os . walk ( rns_root ) :
dirs [ : ] = [ d for d in dirs if d != " __pycache__ " ]
for fn in files :
if not fn . endswith ( " .py " ) : continue
if fn == " __init__.py " : continue
path = os . path . join ( root , fn ) . replace ( os . sep , " / " )
if path . startswith ( " RNS/vendor/i2plib/ " ) : continue
if path == " RNS/vendor/configobj.py " : continue
modname = path [ : - 3 ] . replace ( " / " , " . " )
if modname in NATIVE_EXCLUDES : continue
compiled_modules . add ( modname )
ext_modules . append ( Extension ( modname , [ path ] , extra_compile_args = list ( native_cargs ) ) )
ext_modules = cythonize ( ext_modules , language_level = 3 , compiler_directives = DIRECTIVES )
if pure_python : print ( " Warning: --pure is ignored when building --native " )
# Exclude the CRNS development shim from built wheels
excluded_modules + = [ " CRNS " , " CRNS.* " ]
# Trim superfluous symbol tables
class NativeBuildExt ( _build_ext ) :
def run ( self ) :
super ( ) . run ( )
if sys . platform == " win32 " : return
strip = shutil . which ( " strip " )
if strip is None : return
for output in self . get_outputs ( ) :
if output . endswith ( ( " .so " , " .pyd " ) ) :
try :
if sys . platform == " darwin " : subprocess . run ( [ strip , " -x " , output ] , check = True )
else : subprocess . run ( [ strip , " --strip-unneeded " , output ] , check = True )
except Exception : pass
# Exclude sources of files that were compiled
# to an so, and inject build info.
class NativeBuildPy ( _build_py ) :
def run ( self ) :
super ( ) . run ( )
if native_build : self . _write_buildinfo ( )
def find_package_modules ( self , package , package_dir ) :
modules = super ( ) . find_package_modules ( package , package_dir )
if native_build :
modules = [ ( pkg , mod , fname ) for ( pkg , mod , fname ) in modules
if ( pkg + " . " + mod ) not in compiled_modules ]
return modules
def get_outputs ( self , include_bytecode = True ) :
outputs = super ( ) . get_outputs ( include_bytecode )
if native_build : outputs . append ( self . _buildinfo_path ( ) )
return outputs
def _buildinfo_path ( self ) :
return os . path . join ( self . build_lib , " RNS " , " _buildinfo.py " )
def _write_buildinfo ( self ) :
path = self . _buildinfo_path ( )
os . makedirs ( os . path . dirname ( path ) , exist_ok = True )
with open ( path , " w " ) as fh :
fh . write ( " # Generated build information \n " )
fh . write ( " compiled = True \n " )
if native_build : build_cmdclass = { " build_ext " : NativeBuildExt , " build_py " : NativeBuildPy }
2023-03-07 16:30:40 +01:00
packages = setuptools . find_packages ( exclude = excluded_modules )
2020-04-27 13:33:26 +02:00
setuptools . setup (
2022-06-10 11:27:31 +02:00
name = pkg_name ,
2021-08-19 14:10:37 +02:00
version = __version__ ,
2020-04-27 13:33:26 +02:00
author = " Mark Qvist " ,
author_email = " mark@unsigned.io " ,
description = " Self-configuring, encrypted and resilient mesh networking stack for LoRa, packet radio, WiFi and everything in between " ,
long_description = long_description ,
long_description_content_type = " text/markdown " ,
2022-07-01 17:31:07 +02:00
url = " https://reticulum.network/ " ,
2023-03-07 16:30:40 +01:00
packages = packages ,
2025-05-09 12:04:55 +02:00
license = " Reticulum License " ,
license_files = ( " LICENSE " ) ,
2026-08-27 23:38:29 +02:00
classifiers = [ " Programming Language :: Python :: 3 " ,
" Operating System :: OS Independent " ,
" Development Status :: 5 - Production/Stable " ] ,
2021-09-24 11:21:08 +02:00
entry_points = {
2026-08-27 23:38:29 +02:00
' console_scripts ' : [ ' rnsd=RNS.Utilities.rnsd:main ' ,
' rnstatus=RNS.Utilities.rnstatus:main ' ,
' rnprobe=RNS.Utilities.rnprobe:main ' ,
' rnpath=RNS.Utilities.rnpath:main ' ,
' rnid=RNS.Utilities.rnid:main ' ,
' rncp=RNS.Utilities.rncp:main ' ,
' rnx=RNS.Utilities.rnx:main ' ,
' rnir=RNS.Utilities.rnir:main ' ,
' rnpkg=RNS.Utilities.rnpkg:main ' ,
' rnsh=RNS.Utilities.rnsh.rnsh:main ' ,
' rngit=RNS.Utilities.rngit.server:main ' ,
' rngcs=RNS.Utilities.rngit.commitsigs:main ' ,
' git-remote-rns=RNS.Utilities.rngit.client:main ' ,
' rnodeconf=RNS.Utilities.rnodeconf:main ' ]
2021-09-24 11:21:08 +02:00
} ,
2022-06-10 11:27:31 +02:00
install_requires = requirements ,
2023-05-04 12:23:16 +02:00
python_requires = ' >=3.7 ' ,
2026-08-27 23:38:29 +02:00
ext_modules = ext_modules ,
cmdclass = build_cmdclass ,
2021-09-04 22:58:42 -04:00
)