From bc616e41e7dd96025976f85493faf52377b35090 Mon Sep 17 00:00:00 2001 From: "Dmitriy A. Gerasimov" <dmitriy.gerasimov@demlabs.net> Date: Thu, 20 Feb 2020 15:28:23 +0700 Subject: [PATCH] [*] Upd and fix --- dists/examples/0.Beginning/MyChainsCli.py | 1 + setup.py | 296 +++++----------------- 2 files changed, 65 insertions(+), 232 deletions(-) diff --git a/dists/examples/0.Beginning/MyChainsCli.py b/dists/examples/0.Beginning/MyChainsCli.py index ca82cffe..863a4e3f 100644 --- a/dists/examples/0.Beginning/MyChainsCli.py +++ b/dists/examples/0.Beginning/MyChainsCli.py @@ -1,4 +1,5 @@ import sys +import os import CellFrame.AppCli app_name=’MyChains’ diff --git a/setup.py b/setup.py index 60f7125d..d7673bae 100644 --- a/setup.py +++ b/setup.py @@ -1,249 +1,81 @@ -from distutils.command.install_data import install_data -from setuptools import find_packages, setup, Extension +import os +import re +import sys +import sysconfig +import platform +import subprocess + +from distutils.version import LooseVersion +from setuptools import setup, Extension from setuptools.command.build_ext import build_ext -from setuptools.command.install_lib import install_lib -from setuptools.command.install_scripts import install_scripts -import struct -BITS = struct.calcsize("P") * 8 -PACKAGE_NAME = "example" class CMakeExtension(Extension): - """ - An extension to run the cmake build + def __init__(self, name, sourcedir=''): + Extension.__init__(self, name, sources=[]) + self.sourcedir = os.path.abspath(sourcedir) - This simply overrides the base extension class so that setuptools - doesn't try to build your sources for you - """ - - def __init__(self, name, sources=[]): - - super().__init__(name = name, sources = sources) - -class InstallCMakeLibsData(install_data): - """ - Just a wrapper to get the install data into the egg-info - - Listing the installed files in the egg-info guarantees that - all of the package files will be uninstalled when the user - uninstalls your package through pip - """ - - def run(self): - """ - Outfiles are the libraries that were built using cmake - """ - - # There seems to be no other way to do this; I tried listing the - # libraries during the execution of the InstallCMakeLibs.run() but - # setuptools never tracked them, seems like setuptools wants to - # track the libraries through package data more than anything... - # help would be appriciated - - self.outfiles = self.distribution.data_files - -class InstallCMakeLibs(install_lib): - """ - Get the libraries from the parent distribution, use those as the outfiles - - Skip building anything; everything is already built, forward libraries to - the installation step - """ +class CMakeBuild(build_ext): def run(self): - """ - Copy libraries from the bin directory and place them as appropriate - """ - - self.announce("Moving library files", level=3) - - # We have already built the libraries in the previous build_ext step - - self.skip_build = True - - bin_dir = self.distribution.bin_dir - - # Depending on the files that are generated from your cmake - # build chain, you may need to change the below code, such that - # your files are moved to the appropriate location when the installation - # is run - - libs = [os.path.join(bin_dir, _lib) for _lib in - os.listdir(bin_dir) if - os.path.isfile(os.path.join(bin_dir, _lib)) and - os.path.splitext(_lib)[1] in [".dll", ".so"] - and not (_lib.startswith("python") or _lib.startswith(PACKAGE_NAME))] - - for lib in libs: - - shutil.move(lib, os.path.join(self.build_dir, - os.path.basename(lib))) - - # Mark the libs for installation, adding them to - # distribution.data_files seems to ensure that setuptools' record - # writer appends them to installed-files.txt in the package's egg-info - # - # Also tried adding the libraries to the distribution.libraries list, - # but that never seemed to add them to the installed-files.txt in the - # egg-info, and the online recommendation seems to be adding libraries - # into eager_resources in the call to setup(), which I think puts them - # in data_files anyways. - # - # What is the best way? - - # These are the additional installation files that should be - # included in the package, but are resultant of the cmake build - # step; depending on the files that are generated from your cmake - # build chain, you may need to modify the below code - - self.distribution.data_files = [os.path.join(self.install_dir, - os.path.basename(lib)) - for lib in libs] - - # Must be forced to run after adding the libs to data_files - - self.distribution.run_command("install_data") - - super().run() - -class InstallCMakeScripts(install_scripts): - """ - Install the scripts in the build dir - """ - - def run(self): - """ - Copy the required directory to the build directory and super().run() - """ - - self.announce("Moving scripts files", level=3) - - # Scripts were already built in a previous step - - self.skip_build = True - - bin_dir = self.distribution.bin_dir - - scripts_dirs = [os.path.join(bin_dir, _dir) for _dir in - os.listdir(bin_dir) if - os.path.isdir(os.path.join(bin_dir, _dir))] - - for scripts_dir in scripts_dirs: - - shutil.move(scripts_dir, - os.path.join(self.build_dir, - os.path.basename(scripts_dir))) - - # Mark the scripts for installation, adding them to - # distribution.scripts seems to ensure that the setuptools' record - # writer appends them to installed-files.txt in the package's egg-info - - self.distribution.scripts = scripts_dirs - - super().run() - -class BuildCMakeExt(build_ext): - """ - Builds using cmake instead of the python setuptools implicit build - """ - - def run(self): - """ - Perform build_cmake before doing the 'normal' stuff - """ - - for extension in self.extensions: - - if extension.name == 'example_extension': - - self.build_cmake(extension) - - super().run() - - def build_cmake(self, extension: Extension): - """ - The steps required to build the extension - """ - - self.announce("Preparing the build environment", level=3) - - build_dir = pathlib.Path(self.build_temp) - - extension_path = pathlib.Path(self.get_ext_fullpath(extension.name)) - - os.makedirs(build_dir, exist_ok=True) - os.makedirs(extension_path.parent.absolute(), exist_ok=True) - - # Now that the necessary directories are created, build - - self.announce("Configuring cmake project", level=3) - - # Change your cmake arguments below as necessary - # Below is just an example set of arguments for building Blender as a Python module - - self.spawn(['cmake', '-H'+SOURCE_DIR, '-B'+self.build_temp, - '-DWITH_PLAYER=OFF', '-DWITH_PYTHON_INSTALL=OFF', - '-DWITH_PYTHON_MODULE=ON', - f"-DCMAKE_GENERATOR_PLATFORM=x" - f"{'86' if BITS == 32 else '64'}"]) - - self.announce("Building binaries", level=3) - - self.spawn(["cmake", "--build", self.build_temp, "--target", "INSTALL", - "--config", "Release"]) - - # Build finished, now copy the files into the copy directory - # The copy directory is the parent directory of the extension (.pyd) - - self.announce("Moving built python module", level=3) - - bin_dir = os.path.join(build_dir, 'bin', 'Release') - self.distribution.bin_dir = bin_dir - - pyd_path = [os.path.join(bin_dir, _pyd) for _pyd in - os.listdir(bin_dir) if - os.path.isfile(os.path.join(bin_dir, _pyd)) and - os.path.splitext(_pyd)[0].startswith(PACKAGE_NAME) and - os.path.splitext(_pyd)[1] in [".pyd", ".so"]][0] - - shutil.move(pyd_path, extension_path) - - # After build_ext is run, the following commands will run: - # - # install_lib - # install_scripts - # - # These commands are subclassed above to avoid pitfalls that - # setuptools tries to impose when installing these, as it usually - # wants to build those libs and scripts as well or move them to a - # different place. See comments above for additional information + try: + out = subprocess.check_output(['cmake', '--version']) + except OSError: + raise RuntimeError( + "CMake must be installed to build the following extensions: " + + ", ".join(e.name for e in self.extensions)) + + if platform.system() == "Windows": + cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)', + out.decode()).group(1)) + if cmake_version < '3.1.0': + raise RuntimeError("CMake >= 3.1.0 is required on Windows") + + for ext in self.extensions: + self.build_extension(ext) + + def build_extension(self, ext): + extdir = os.path.abspath( + os.path.dirname(self.get_ext_fullpath(ext.name))) + cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, + '-DPYTHON_EXECUTABLE=' + sys.executable] + + cfg = 'Debug' if self.debug else 'Release' + build_args = ['--config', cfg] + + if platform.system() == "Windows": + cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format( + cfg.upper(), + extdir)] + if sys.maxsize > 2**32: + cmake_args += ['-A', 'x64'] + build_args += ['--', '/m'] + else: + cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg] + build_args += ['--', '-j2'] + + env = os.environ.copy() + env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format( + env.get('CXXFLAGS', ''), + self.distribution.get_version()) + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, + cwd=self.build_temp, env=env) + subprocess.check_call(['cmake', '--build', '.'] + build_args, + cwd=self.build_temp) + print() # Add an empty line for cleaner outputimport sys setup( name="CellFrame", - version="0.9post3", + version="0.9-0", description="CellFrame SDK", - author='Demlabs (2017-2020)', + author='DEMLABS Inc. (2017-2020)', license="GNU GPLv3", - packages=find_packages(), - description='CellFrame SDK.Python: Blockchain toolkit', - keywords="ledger, blockchain, chains, crypto", + packages=['CellFrame'], ext_modules=[CMakeExtension('CellFrame')], # add custom build_ext command - classifiers=["Intended Audience :: Developers", - "License :: OSI Approved :: ", - "GNU Lesser General Public License v3 (LGPLv3)", - "Natural Language :: English", - "Programming Language :: C", - "Programming Language :: C++", - "Programming Language :: Python", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: Implementation :: CPython"], - license='GPL-3.0', - cmdclass={ - 'build_ext': BuildCMakeExt, - 'install_data': InstallCMakeLibsData, - 'install_lib': InstallCMakeLibs, - 'install_scripts': InstallCMakeScripts}, + cmdclass=dict(build_ext=CMakeBuild), zip_safe=False, # tests_require=['pytest'], # setup_requires=setup_requires -- GitLab