setup.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
  4. # Copyright (C)2013-2023 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen
  9. # https://gitlab.com/mmgen/mmgen
  10. # MSYS2 Note (2023-10-26):
  11. # mingw-w64-ucrt-x86_64-python package is missing static lib, so we must build dynamic extmod
  12. # linked to installed libsecp256k1
  13. import os,platform
  14. from pathlib import Path
  15. from subprocess import run,PIPE
  16. from setuptools import setup,Extension
  17. from setuptools.command.build_ext import build_ext
  18. have_arm = platform.uname().machine in ('aarch64','armv7l') # x86_64 (linux), AMD64 (win), aarch64, armv7l
  19. have_msys2 = platform.system() == 'Windows'
  20. home = Path(os.environ['HOME'])
  21. cache_path = home.joinpath('.cache','mmgen')
  22. src_path = home.joinpath('.cache','mmgen','secp256k1')
  23. if have_msys2:
  24. root = Path().resolve().anchor
  25. installed_lib_file = Path(root, 'msys64', 'ucrt64', 'lib', 'libsecp256k1.dll.a')
  26. lib_file = src_path.joinpath('.libs', 'libsecp256k1.dll.a')
  27. else:
  28. installed_lib_file = None
  29. lib_file = src_path.joinpath('.libs', 'libsecp256k1.a')
  30. def build_libsecp256k1():
  31. if installed_lib_file and installed_lib_file.exists(): # see ‘MSYS2 Note’ above
  32. return
  33. def fix_broken_aclocal_path():
  34. os.environ['ACLOCAL_PATH'] = '/C/msys64/ucrt64/share/aclocal:/C/msys64/usr/share/aclocal'
  35. if have_msys2:
  36. fix_broken_aclocal_path()
  37. if not cache_path.exists():
  38. cache_path.mkdir(parents=True)
  39. if not src_path.exists():
  40. print('\nCloning libsecp256k1')
  41. run(['git','clone','https://github.com/bitcoin-core/secp256k1.git'],check=True,cwd=cache_path)
  42. if not lib_file.exists():
  43. print(f'\nBuilding libsecp256k1 (cwd={str(src_path)})')
  44. cmds = {
  45. 'Windows': (
  46. ['sh','./autogen.sh'],
  47. ['sh','./configure','CFLAGS=-g -O2 -fPIC','--disable-dependency-tracking'],
  48. ['mingw32-make','MAKE=mingw32-make']
  49. ),
  50. 'Linux': (
  51. ['./autogen.sh'],
  52. ['./configure','CFLAGS=-g -O2 -fPIC'],
  53. ['make'] + ([] if have_arm else ['-j4']),
  54. ),
  55. }[platform.system()]
  56. for cmd in cmds:
  57. print('Executing {}'.format(' '.join(cmd)))
  58. run(cmd,check=True,cwd=src_path)
  59. if installed_lib_file and not installed_lib_file.exists(): # see ‘MSYS2 Note’ above
  60. run(['mingw32-make','install','MAKE=mingw32-make'],check=True,cwd=src_path)
  61. class my_build_ext(build_ext):
  62. def build_extension(self,ext):
  63. build_libsecp256k1()
  64. build_ext.build_extension(self,ext)
  65. setup(
  66. cmdclass = { 'build_ext': my_build_ext },
  67. ext_modules = [Extension(
  68. name = 'mmgen.proto.secp256k1.secp256k1',
  69. sources = ['extmod/secp256k1mod.c'],
  70. libraries = ['gmp'] if have_msys2 else [],
  71. include_dirs = [str(src_path.joinpath('include'))],
  72. extra_objects = [str(lib_file)],
  73. extra_compile_args = ['-shared'] if have_msys2 else [],
  74. extra_link_args = ['-shared'] if have_msys2 else [],
  75. )]
  76. )