Update setup.py to setuptools
https://github.com/overviewer/Minecraft-Overviewer/pull/1208
This commit is contained in:
266
setup.py
266
setup.py
@@ -1,7 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
|
||||||
|
|
||||||
|
|
||||||
# quick version check
|
# quick version check
|
||||||
@@ -10,22 +9,25 @@ if sys.version_info[0] == 2 or (sys.version_info[0] == 3 and sys.version_info[1]
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
from distutils.core import setup
|
from setuptools import setup
|
||||||
from distutils.extension import Extension
|
from setuptools.extension import Extension
|
||||||
from distutils.command.build import build
|
|
||||||
from distutils.command.clean import clean
|
from distutils.command.clean import clean
|
||||||
from distutils.command.build_ext import build_ext
|
from distutils.command.build import build
|
||||||
|
from setuptools.command.build_ext import build_ext
|
||||||
from distutils.command.sdist import sdist
|
from distutils.command.sdist import sdist
|
||||||
from distutils.cmd import Command
|
from distutils.cmd import Command
|
||||||
from distutils.dir_util import remove_tree
|
from distutils.dir_util import remove_tree
|
||||||
from distutils.sysconfig import get_python_inc
|
from distutils.sysconfig import get_python_inc
|
||||||
from distutils import log
|
from distutils import log
|
||||||
import os, os.path
|
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
import glob
|
import glob
|
||||||
import platform
|
import platform
|
||||||
import time
|
import time
|
||||||
import overviewer_core.util as util
|
import traceback
|
||||||
import numpy
|
|
||||||
|
from overviewer_core import util
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import py2exe
|
import py2exe
|
||||||
@@ -34,10 +36,17 @@ except ImportError:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import py2app
|
import py2app
|
||||||
from setuptools.extension import Extension
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
py2app = None
|
py2app = None
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_ERROR = """
|
||||||
|
Failed to build Overviewer!
|
||||||
|
Please review the errors printed above and the build instructions at
|
||||||
|
<http://docs.overviewer.org/en/latest/building/>. If you are still having
|
||||||
|
build problems, file an incident on the github tracker or find us in IRC.
|
||||||
|
"""
|
||||||
|
|
||||||
# make sure our current working directory is the same directory
|
# make sure our current working directory is the same directory
|
||||||
# setup.py is in
|
# setup.py is in
|
||||||
curdir = os.path.split(sys.argv[0])[0]
|
curdir = os.path.split(sys.argv[0])[0]
|
||||||
@@ -50,32 +59,27 @@ setup_kwargs = {}
|
|||||||
setup_kwargs['ext_modules'] = []
|
setup_kwargs['ext_modules'] = []
|
||||||
setup_kwargs['cmdclass'] = {}
|
setup_kwargs['cmdclass'] = {}
|
||||||
setup_kwargs['options'] = {}
|
setup_kwargs['options'] = {}
|
||||||
|
|
||||||
#
|
#
|
||||||
# metadata
|
# metadata
|
||||||
#
|
#
|
||||||
|
|
||||||
# Utility function to read the README file.
|
|
||||||
# Used for the long_description. It's nice, because now 1) we have a top level
|
|
||||||
# README file and 2) it's easier to type in the README file than to put a raw
|
|
||||||
# string in below ...
|
|
||||||
def read(fname):
|
|
||||||
return open(fname).read()
|
|
||||||
|
|
||||||
setup_kwargs['name'] = 'Minecraft-Overviewer'
|
|
||||||
setup_kwargs['version'] = util.findGitVersion()
|
|
||||||
setup_kwargs['description'] = 'Generates large resolution images of a Minecraft map.'
|
|
||||||
setup_kwargs['url'] = 'http://overviewer.org/'
|
|
||||||
setup_kwargs['author'] = 'Andrew Brown'
|
|
||||||
setup_kwargs['author_email'] = 'brownan@gmail.com'
|
|
||||||
setup_kwargs['license'] = 'GNU General Public License v3'
|
|
||||||
setup_kwargs['long_description'] = read('README.rst')
|
|
||||||
|
|
||||||
# top-level files that should be included as documentation
|
# top-level files that should be included as documentation
|
||||||
doc_files = ['COPYING.txt', 'README.rst', 'CONTRIBUTORS.rst', 'sample_config.py']
|
doc_files = ['COPYING.txt',
|
||||||
|
'README.rst',
|
||||||
|
'CONTRIBUTORS.rst',
|
||||||
|
'sample_config.py']
|
||||||
|
|
||||||
# helper to create a 'data_files'-type sequence recursively for a given dir
|
|
||||||
def recursive_data_files(src, dest=None):
|
def data_files(src, dest=None):
|
||||||
|
"""helper to create a 'data_files'-type sequence recursively for a given
|
||||||
|
dir
|
||||||
|
|
||||||
|
:param src: directory to include files from
|
||||||
|
:param dest:
|
||||||
|
:return: list
|
||||||
|
|
||||||
|
"""
|
||||||
if dest is None:
|
if dest is None:
|
||||||
dest = src
|
dest = src
|
||||||
|
|
||||||
@@ -92,15 +96,22 @@ def recursive_data_files(src, dest=None):
|
|||||||
ret.append((current_dest, current_sources))
|
ret.append((current_dest, current_sources))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# helper to create a 'package_data'-type sequence recursively for a given dir
|
|
||||||
def recursive_package_data(src, package_dir='overviewer_core'):
|
def package_data(src, package_dir='overviewer_core'):
|
||||||
|
"""Helper to create a 'package_data'-type sequence recursively for a given
|
||||||
|
dir
|
||||||
|
|
||||||
|
:param src: source directory
|
||||||
|
:param package_dir: package directory
|
||||||
|
:return: list
|
||||||
|
|
||||||
|
"""
|
||||||
full_src = os.path.join(package_dir, src)
|
full_src = os.path.join(package_dir, src)
|
||||||
ret = []
|
ret = []
|
||||||
for dirpath, dirnames, filenames in os.walk(full_src, topdown=False):
|
for dirpath, dirnames, filenames in os.walk(full_src, topdown=False):
|
||||||
current_path = os.path.relpath(dirpath, package_dir)
|
current_path = os.path.relpath(dirpath, package_dir)
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
ret.append(os.path.join(current_path, filename))
|
ret.append(os.path.join(current_path, filename))
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -108,23 +119,30 @@ def recursive_package_data(src, package_dir='overviewer_core'):
|
|||||||
#
|
#
|
||||||
|
|
||||||
if py2exe is not None:
|
if py2exe is not None:
|
||||||
setup_kwargs['comments'] = "http://overviewer.org"
|
setup_kwargs['comments'] = 'http://overviewer.org'
|
||||||
# py2exe likes a very particular type of version number:
|
# py2exe likes a very particular type of version number:
|
||||||
setup_kwargs['version'] = util.findGitVersion().replace("-",".")
|
setup_kwargs['version'] = setup_kwargs['version'].replace('-', '.')
|
||||||
|
|
||||||
setup_kwargs['console'] = ['overviewer.py', 'contribManager.py']
|
setup_kwargs['console'] = ['overviewer.py', 'contribManager.py']
|
||||||
setup_kwargs['data_files'] = [('', doc_files)]
|
setup_kwargs['data_files'] = [('', doc_files)]
|
||||||
setup_kwargs['data_files'] += recursive_data_files('overviewer_core/data/textures', 'textures')
|
setup_kwargs['data_files'] += data_files('overviewer_core/data/textures',
|
||||||
setup_kwargs['data_files'] += recursive_data_files('overviewer_core/data/web_assets', 'web_assets')
|
'textures')
|
||||||
setup_kwargs['data_files'] += recursive_data_files('overviewer_core/data/js_src', 'js_src')
|
setup_kwargs['data_files'] += data_files('overviewer_core/data/web_assets',
|
||||||
setup_kwargs['data_files'] += recursive_data_files('contrib', 'contrib')
|
'web_assets')
|
||||||
|
setup_kwargs['data_files'] += data_files('overviewer_core/data/js_src',
|
||||||
|
'js_src')
|
||||||
|
setup_kwargs['data_files'] += data_files('contrib', 'contrib')
|
||||||
setup_kwargs['zipfile'] = None
|
setup_kwargs['zipfile'] = None
|
||||||
if platform.system() == 'Windows' and '64bit' in platform.architecture():
|
if platform.system() == 'Windows' and '64bit' in platform.architecture():
|
||||||
b = 3
|
b = 3
|
||||||
else:
|
else:
|
||||||
b = 1
|
b = 1
|
||||||
setup_kwargs['options']['py2exe'] = {'bundle_files' : b, 'excludes': 'Tkinter', 'includes':
|
setup_kwargs['options']['py2exe'] = \
|
||||||
['fileinput', 'overviewer_core.items', 'overviewer_core.aux_files.genPOI']}
|
{'bundle_files': b,
|
||||||
|
'excludes': 'Tkinter',
|
||||||
|
'includes': ['fileinput',
|
||||||
|
'overviewer_core.items',
|
||||||
|
'overviewer_core.aux_files.genPOI']}
|
||||||
|
|
||||||
#
|
#
|
||||||
# py2app options
|
# py2app options
|
||||||
@@ -132,7 +150,7 @@ if py2exe is not None:
|
|||||||
|
|
||||||
if py2app is not None:
|
if py2app is not None:
|
||||||
setup_kwargs['app'] = ['overviewer.py']
|
setup_kwargs['app'] = ['overviewer.py']
|
||||||
setup_kwargs['options']['py2app'] = {'argv_emulation' : False}
|
setup_kwargs['options']['py2app'] = {'argv_emulation': False}
|
||||||
setup_kwargs['setup_requires'] = ['py2app']
|
setup_kwargs['setup_requires'] = ['py2app']
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -141,36 +159,60 @@ if py2app is not None:
|
|||||||
|
|
||||||
setup_kwargs['packages'] = ['overviewer_core', 'overviewer_core/aux_files']
|
setup_kwargs['packages'] = ['overviewer_core', 'overviewer_core/aux_files']
|
||||||
setup_kwargs['scripts'] = ['overviewer.py']
|
setup_kwargs['scripts'] = ['overviewer.py']
|
||||||
setup_kwargs['package_data'] = {'overviewer_core': recursive_package_data('data/textures') + recursive_package_data('data/web_assets') + recursive_package_data('data/js_src')}
|
setup_kwargs['package_data'] = \
|
||||||
|
{'overviewer_core': (package_data('data/textures') +
|
||||||
|
package_data('data/web_assets') +
|
||||||
|
package_data('data/js_src'))}
|
||||||
|
|
||||||
if py2exe is None:
|
if py2exe is None:
|
||||||
setup_kwargs['data_files'] = [('share/doc/minecraft-overviewer', doc_files)]
|
setup_kwargs['data_files'] = [('share/doc/minecraft-overviewer',
|
||||||
|
doc_files)]
|
||||||
|
|
||||||
|
|
||||||
#
|
def get_numpy_include():
|
||||||
# c_overviewer extension
|
"""Obtain the numpy include directory. This logic works across numpy
|
||||||
#
|
versions
|
||||||
|
|
||||||
|
:rtype: list
|
||||||
|
|
||||||
|
"""
|
||||||
|
print(sys.path)
|
||||||
|
try:
|
||||||
|
import numpy
|
||||||
|
except ImportError:
|
||||||
|
if sys.argv[1] != 'develop':
|
||||||
|
print('numpy not found, please run "python setup.py develop"')
|
||||||
|
sys.exit(1)
|
||||||
|
return []
|
||||||
|
try:
|
||||||
|
return numpy.get_include()
|
||||||
|
except AttributeError:
|
||||||
|
return numpy.get_numpy_include()
|
||||||
|
|
||||||
# Third-party modules - we depend on numpy for everything
|
# Third-party modules - we depend on numpy for everything
|
||||||
# Obtain the numpy include directory. This logic works across numpy versions.
|
numpy_include = get_numpy_include()
|
||||||
try:
|
|
||||||
numpy_include = numpy.get_include()
|
|
||||||
except AttributeError:
|
|
||||||
numpy_include = numpy.get_numpy_include()
|
|
||||||
|
|
||||||
try:
|
# Try and find the Imaging path automatically
|
||||||
pil_include = os.environ['PIL_INCLUDE_DIR'].split(os.pathsep)
|
pil_include = []
|
||||||
except Exception:
|
imaging_path = os.environ.get('PIL_INCLUDE_DIR',
|
||||||
pil_include = [ os.path.join(get_python_inc(plat_specific=1), 'Imaging') ]
|
os.path.normpath('./Imaging/libImaging'))
|
||||||
if not os.path.exists(pil_include[0]):
|
if not os.path.exists(imaging_path):
|
||||||
pil_include = [ ]
|
imaging_path = os.path.join(get_python_inc(plat_specific=1), 'Imaging')
|
||||||
|
if os.path.exists(imaging_path):
|
||||||
|
pil_include.append(imaging_path)
|
||||||
|
|
||||||
|
if not pil_include:
|
||||||
|
print('ERROR: Could not find Python Imaging library')
|
||||||
|
print(BUILD_ERROR)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
SRC_PATH = 'overviewer_core/src/'
|
||||||
|
|
||||||
# used to figure out what files to compile
|
# used to figure out what files to compile
|
||||||
# auto-created from files in primitives/, but we need the raw names so
|
# auto-created from files in primitives/, but we need the raw names so
|
||||||
# we can use them later.
|
# we can use them later.
|
||||||
primitives = []
|
primitives = []
|
||||||
for name in glob.glob("overviewer_core/src/primitives/*.c"):
|
for name in glob.glob(SRC_PATH + 'primitives/*.c'):
|
||||||
name = os.path.split(name)[-1]
|
name = os.path.split(name)[-1]
|
||||||
name = os.path.splitext(name)[0]
|
name = os.path.splitext(name)[0]
|
||||||
primitives.append(name)
|
primitives.append(name)
|
||||||
@@ -190,6 +232,17 @@ setup_kwargs['ext_modules'].append(Extension('overviewer_core.c_overviewer', c_o
|
|||||||
# (NOT in build/)
|
# (NOT in build/)
|
||||||
setup_kwargs['options']['build_ext'] = {'inplace' : 1}
|
setup_kwargs['options']['build_ext'] = {'inplace' : 1}
|
||||||
|
|
||||||
|
include_dirs = ['.', numpy_include] + pil_include
|
||||||
|
|
||||||
|
setup_kwargs['ext_modules'].append(Extension('overviewer_core.c_overviewer',
|
||||||
|
c_overviewer_files,
|
||||||
|
include_dirs=include_dirs,
|
||||||
|
depends=c_overviewer_includes,
|
||||||
|
extra_link_args=[]))
|
||||||
|
|
||||||
|
# tell build_ext to build the extension in-place (NOT in build/)
|
||||||
|
setup_kwargs['options']['build_ext'] = {'inplace': 1}
|
||||||
|
|
||||||
# custom clean command to remove in-place extension
|
# custom clean command to remove in-place extension
|
||||||
# and the version file, primitives header
|
# and the version file, primitives header
|
||||||
class CustomClean(clean):
|
class CustomClean(clean):
|
||||||
@@ -229,49 +282,38 @@ class CustomClean(clean):
|
|||||||
|
|
||||||
def generate_version_py():
|
def generate_version_py():
|
||||||
try:
|
try:
|
||||||
outstr = ""
|
with open('overviewer_core/overviewer_version.py', 'w') as f:
|
||||||
outstr += "VERSION=%r\n" % util.findGitVersion()
|
f.write('\n'.join(['VERSION=%r' % util.findGitVersion(),
|
||||||
outstr += "HASH=%r\n" % util.findGitHash()
|
'HASH=%r' % util.findGitHash(),
|
||||||
outstr += "BUILD_DATE=%r\n" % time.asctime()
|
'BUILD_DATE=%r' % time.asctime(),
|
||||||
outstr += "BUILD_PLATFORM=%r\n" % platform.processor()
|
'BUILD_PLATFORM=%r' % platform.processor(),
|
||||||
outstr += "BUILD_OS=%r\n" % platform.platform()
|
'BUILD_OS=%r' % platform.platform()]) + '\n')
|
||||||
f = open("overviewer_core/overviewer_version.py", "w")
|
|
||||||
f.write(outstr)
|
|
||||||
f.close()
|
|
||||||
except Exception:
|
except Exception:
|
||||||
print("WARNING: failed to build overviewer_version file")
|
print('WARNING: failed to build overviewer_version file')
|
||||||
|
|
||||||
|
|
||||||
def generate_primitives_h():
|
def generate_primitives_h():
|
||||||
global primitives
|
|
||||||
prims = [p.lower().replace('-', '_') for p in primitives]
|
prims = [p.lower().replace('-', '_') for p in primitives]
|
||||||
|
out = ['/* this file is auto-generated by setup.py */']
|
||||||
outstr = "/* this file is auto-generated by setup.py */\n"
|
|
||||||
for p in prims:
|
for p in prims:
|
||||||
outstr += "extern RenderPrimitiveInterface primitive_{0};\n".format(p)
|
out.append('extern RenderPrimitiveInterface primitive_{0};'.format(p))
|
||||||
outstr += "static RenderPrimitiveInterface *render_primitives[] = {\n"
|
out.append('static RenderPrimitiveInterface *render_primitives[] = {')
|
||||||
for p in prims:
|
for p in prims:
|
||||||
outstr += " &primitive_{0},\n".format(p)
|
out.append(' &primitive_{0},'.format(p))
|
||||||
outstr += " NULL\n"
|
out.append(' NULL')
|
||||||
outstr += "};\n"
|
out.append('};\n')
|
||||||
|
with open(SRC_PATH + 'primitives.h', 'w') as f:
|
||||||
|
f.write('\n'.join(out))
|
||||||
|
|
||||||
with open("overviewer_core/src/primitives.h", "w") as f:
|
|
||||||
f.write(outstr)
|
|
||||||
|
|
||||||
class CustomSDist(sdist):
|
|
||||||
def run(self):
|
|
||||||
# generate the version file
|
|
||||||
generate_version_py()
|
|
||||||
generate_primitives_h()
|
|
||||||
sdist.run(self)
|
|
||||||
|
|
||||||
class CustomBuild(build):
|
class CustomBuild(build):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# generate the version file
|
generate_version_py()
|
||||||
|
generate_primitives_h()
|
||||||
try:
|
try:
|
||||||
generate_version_py()
|
|
||||||
generate_primitives_h()
|
|
||||||
build.run(self)
|
build.run(self)
|
||||||
print("\nBuild Complete")
|
print('\nBuild Complete')
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc(limit=1)
|
traceback.print_exc(limit=1)
|
||||||
print("\nFailed to build Overviewer!")
|
print("\nFailed to build Overviewer!")
|
||||||
@@ -282,6 +324,7 @@ class CustomBuild(build):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
class CustomBuildExt(build_ext):
|
class CustomBuildExt(build_ext):
|
||||||
|
|
||||||
def build_extensions(self):
|
def build_extensions(self):
|
||||||
c = self.compiler.compiler_type
|
c = self.compiler.compiler_type
|
||||||
if c == "msvc":
|
if c == "msvc":
|
||||||
@@ -290,7 +333,7 @@ class CustomBuildExt(build_ext):
|
|||||||
e.extra_link_args.append("/MANIFEST")
|
e.extra_link_args.append("/MANIFEST")
|
||||||
e.extra_link_args.append("/DWINVER=0x060")
|
e.extra_link_args.append("/DWINVER=0x060")
|
||||||
e.extra_link_args.append("/D_WIN32_WINNT=0x060")
|
e.extra_link_args.append("/D_WIN32_WINNT=0x060")
|
||||||
if c == "unix":
|
elif c == "unix":
|
||||||
# customize the build options for this compilier
|
# customize the build options for this compilier
|
||||||
for e in self.extensions:
|
for e in self.extensions:
|
||||||
e.extra_compile_args.append("-Wno-unused-variable") # quell some annoying warnings
|
e.extra_compile_args.append("-Wno-unused-variable") # quell some annoying warnings
|
||||||
@@ -302,15 +345,56 @@ class CustomBuildExt(build_ext):
|
|||||||
# build in place, and in the build/ tree
|
# build in place, and in the build/ tree
|
||||||
self.inplace = False
|
self.inplace = False
|
||||||
build_ext.build_extensions(self)
|
build_ext.build_extensions(self)
|
||||||
|
|
||||||
self.inplace = True
|
self.inplace = True
|
||||||
build_ext.build_extensions(self)
|
build_ext.build_extensions(self)
|
||||||
|
|
||||||
|
|
||||||
|
class CustomClean(clean):
|
||||||
|
"""Custom clean command to remove in-place extension and the version file,
|
||||||
|
primitives header
|
||||||
|
|
||||||
|
"""
|
||||||
|
def run(self):
|
||||||
|
clean.run(self)
|
||||||
|
# try to remove '_composite.{so,pyd,...}' extension,
|
||||||
|
# regardless of the current system's extension name convention
|
||||||
|
build_ext = self.get_finalized_command('build_ext')
|
||||||
|
ext_fname = build_ext.get_ext_filename('overviewer_core.c_overviewer')
|
||||||
|
primspath = os.path.join('overviewer_core', 'src', 'primitives.h')
|
||||||
|
|
||||||
|
for fname in [ext_fname, primspath]:
|
||||||
|
if os.path.exists(fname):
|
||||||
|
try:
|
||||||
|
log.info("removing '%s'", fname)
|
||||||
|
if not self.dry_run:
|
||||||
|
os.remove(fname)
|
||||||
|
except OSError as error:
|
||||||
|
log.warn("'%s' could not be cleaned: %s", fname, error)
|
||||||
|
else:
|
||||||
|
log.debug("'%s' does not exist -- can't clean it", fname)
|
||||||
|
|
||||||
|
# now try to purge all *.pyc files
|
||||||
|
for root, dirs, files in \
|
||||||
|
os.walk(os.path.join(os.path.dirname(__file__), '.')):
|
||||||
|
for f in files:
|
||||||
|
if f.endswith('.pyc'):
|
||||||
|
if self.dry_run:
|
||||||
|
log.warn('Would remove %s', os.path.join(root, f))
|
||||||
|
else:
|
||||||
|
os.remove(os.path.join(root, f))
|
||||||
|
|
||||||
|
|
||||||
|
class CustomSDist(sdist):
|
||||||
|
def run(self):
|
||||||
|
generate_version_py()
|
||||||
|
generate_primitives_h()
|
||||||
|
sdist.run(self)
|
||||||
|
|
||||||
|
|
||||||
setup_kwargs['cmdclass']['clean'] = CustomClean
|
setup_kwargs['cmdclass']['clean'] = CustomClean
|
||||||
setup_kwargs['cmdclass']['sdist'] = CustomSDist
|
setup_kwargs['cmdclass']['sdist'] = CustomSDist
|
||||||
setup_kwargs['cmdclass']['build'] = CustomBuild
|
setup_kwargs['cmdclass']['build'] = CustomBuild
|
||||||
setup_kwargs['cmdclass']['build_ext'] = CustomBuildExt
|
setup_kwargs['cmdclass']['build_ext'] = CustomBuildExt
|
||||||
###
|
|
||||||
|
|
||||||
setup(**setup_kwargs)
|
setup(**setup_kwargs)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user