hikyuu2/setup.py

391 lines
14 KiB
C++
Raw Normal View History

2019-02-13 23:06:58 +08:00
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from setuptools import setup, find_packages
import sys
2020-01-12 00:55:15 +08:00
import json
2019-02-13 23:06:58 +08:00
import os
import shutil
import platform
2019-07-27 16:17:28 +08:00
import click
#------------------------------------------------------------------------------
# 前置检查
#------------------------------------------------------------------------------
def check_xmake():
"""检查是否按照了编译工具 xmake"""
print("checking xmake ...")
xmake = os.system("xmake --version")
return False if xmake != 0 else True
def get_boost_envrionment():
"""
BOOST
@return (current_boost_root, current_boost_lib)
"""
current_dir = os.getcwd()
2020-01-12 00:55:15 +08:00
current_boost_root = ''
current_boost_lib = ''
2019-09-22 23:02:08 +08:00
if 'BOOST_ROOT' in os.environ:
current_boost_root = os.environ['BOOST_ROOT']
if 'BOOST_LIB' in os.environ:
current_boost_lib = os.environ['BOOST_LIB']
else:
current_boost_lib = current_boost_root + '/stage/lib'
os.environ['BOOST_LIB'] = current_boost_lib
else:
2019-07-27 16:17:28 +08:00
for dir in os.listdir():
if len(dir) >= 5 and dir[:5] == 'boost' and os.path.isdir(dir):
current_boost_root = current_dir + '/' + dir
current_boost_lib = current_dir + '/' + dir + '/stage/lib'
os.environ['BOOST_ROOT'] = current_boost_root
os.environ['BOOST_LIB'] = current_boost_lib
return (current_boost_root, current_boost_lib)
def get_python_version():
2020-01-12 00:55:15 +08:00
"""获取当前 python版本"""
2019-07-27 16:17:28 +08:00
py_version = platform.python_version_tuple()
2020-01-12 00:55:15 +08:00
py_version = int(py_version[0]) * 10 + int(py_version[1])
print('current python version:', int(py_version) * 0.1)
return py_version
def get_current_compile_info():
"""获取当前编译信息, 其中 mode 无效"""
current_bits = 64 if sys.maxsize > 2**32 else 32
if sys.platform == 'win32':
current_arch = 'x64' if current_bits == 64 else 'x86'
2019-07-27 16:17:28 +08:00
else:
2020-01-12 00:55:15 +08:00
current_arch = 'x86_64' if current_bits == 64 else 'i386'
py_version = get_python_version()
current_boost_root, current_boost_lib = get_boost_envrionment()
current_compile_info = {
'plat': sys.platform,
'arch': current_arch,
'mode': '',
'py_version': py_version,
'boost_root': current_boost_root,
'boost_lib': current_boost_lib
}
return current_compile_info
def get_history_compile_info():
"""获取历史编译信息"""
try:
with open('compile_info', 'r') as f:
result = json.load(f)
except:
result = {
'plat': '',
'arch': '',
'mode': '',
'py_version': 0,
'boost_root': '',
'boost_lib': ''
}
return result
def save_current_compile_info(compile_info):
"""保持当前编译信息"""
with open('compile_info', 'w') as f:
json.dump(compile_info, f)
2019-07-27 16:17:28 +08:00
def build_boost(mode):
2019-07-27 16:17:28 +08:00
""" 编译依赖的 boost 库 """
current_boost_root, current_boost_lib = get_boost_envrionment()
2020-01-12 00:55:15 +08:00
if current_boost_root == '' or current_boost_lib == '':
2019-07-27 16:17:28 +08:00
print("Can't get boost environment!")
return
2019-08-03 23:07:32 +08:00
current_dir = os.getcwd()
2019-07-27 16:17:28 +08:00
if sys.platform == 'win32':
os.chdir(current_boost_root)
if not os.path.exists('b2.exe'):
os.system('bootstrap.bat')
2020-01-12 00:55:15 +08:00
os.system(
'b2 {} link=static runtime-link=shared address-model=64 -j 4 --with-date_time'
' --with-filesystem --with-system --with-test'.format(mode))
os.system(
'b2 {} link=shared runtime-link=shared address-model=64 -j 4 --with-python'
' --with-serialization'.format(mode))
2019-07-27 16:17:28 +08:00
os.chdir(current_dir)
else:
2019-10-19 22:25:06 +08:00
cmd = 'cd {boost} ; if [ ! -f "b2" ]; then ./bootstrap.sh ; fi; '\
'./b2 {mode} link=shared address-model=64 -j 4 --with-python --with-serialization; '\
'./b2 {mode} link=static address-model=64 cxxflags=-fPIC -j 4 --with-date_time '\
2019-10-23 01:59:54 +08:00
'--with-filesystem --with-system --with-test; '\
'cd {current}'.format(boost=current_boost_root, mode=mode, current=current_dir)
2019-07-27 16:17:28 +08:00
os.system(cmd)
def clear_with_python_changed(mode):
2019-07-27 16:17:28 +08:00
"""
python版本发生变化时python编译结果
pyhon
"""
current_plat = sys.platform
current_bits = 64 if sys.maxsize > 2**32 else 32
if current_plat == 'win32' and current_bits == 64:
2020-01-12 00:55:15 +08:00
build_pywrap_dir = 'build\\{mode}\\windows\\x64\\.objs\\windows\\x64\\{mode}\\hikyuu_pywrap'.format(
mode=mode)
2019-07-27 16:17:28 +08:00
elif current_plat == 'win32' and current_bits == 32:
2020-01-12 00:55:15 +08:00
build_pywrap_dir = 'build\\{mode}\\windows\\x86\\.objs\\windows\\x86\\{mode}\\hikyuu_pywrap'.format(
mode=mode)
2019-07-27 16:17:28 +08:00
elif current_plat == 'linux' and current_bits == 64:
2020-01-12 00:55:15 +08:00
build_pywrap_dir = 'build/{mode}/linux/x86_64/.objs/linux/x86_64/{mode}/hikyuu_pywrap'.format(
mode=mode)
elif current_plat == 'linux' and current_bits == 32:
build_pywrap_dir = 'build/{mode}/linux/i386/.objs/linux/i386/{mode}/hikyuu_pywrap'.format(
mode=mode)
2019-07-27 16:17:28 +08:00
elif current_plat == "darwin" and current_bits == 64:
2020-01-12 00:55:15 +08:00
build_pywrap_dir = 'build/{mode}/macosx/x86_64/.objs/macosx/x86_64/{mode}/hikyuu_pywrap'.format(
mode=mode)
elif current_plat == "darwin" and current_bits == 32:
build_pywrap_dir = 'build/{mode}/macosx/i386/.objs/macosx/i386/{mode}/hikyuu_pywrap'.format(
mode=mode)
else:
2019-07-27 16:17:28 +08:00
print("************不支持的平台**************")
exit(0)
if os.path.lexists(build_pywrap_dir):
shutil.rmtree(build_pywrap_dir)
current_boost_root, _ = get_boost_envrionment()
if os.path.lexists('{}/bin.v2/libs/python'.format(current_boost_root)):
shutil.rmtree('{}/bin.v2/libs/python'.format(current_boost_root))
#------------------------------------------------------------------------------
# 执行构建
#------------------------------------------------------------------------------
def start_build(verbose=False, mode='release'):
2019-07-27 16:17:28 +08:00
""" 执行编译 """
global g_verbose
g_verbose = verbose
if not check_xmake():
print("Please install xmake")
return
2020-01-12 00:55:15 +08:00
current_compile_info = get_current_compile_info()
current_compile_info['mode'] = mode
py_version = current_compile_info['py_version']
if py_version != 0 and py_version < 31:
2019-07-27 16:17:28 +08:00
print("Python version must >= 3.1 !")
return
2020-01-12 00:55:15 +08:00
current_boost_root = current_compile_info['boost_root']
current_boost_lib = current_compile_info['boost_lib']
if current_boost_root == '' or current_boost_lib == '':
2019-07-27 16:17:28 +08:00
print("Please configure BOOST")
exit(0)
print('BOOST_ROOT:', current_boost_root)
print('BOOST_LIB:', current_boost_lib)
2020-01-12 00:55:15 +08:00
#如果 python版本或者编译模式发生变化则编译依赖的 boost 库boost.python)
history_compile_info = get_history_compile_info()
if py_version != history_compile_info['py_version'] or history_compile_info['mode'] != mode:
clear_with_python_changed(mode)
2019-07-27 16:17:28 +08:00
print('\ncompile boost ...')
build_boost(mode)
os.system("xmake f -c -y -m {}".format(mode))
2019-07-27 16:17:28 +08:00
else:
os.system("xmake f -y -m {}".format(mode))
2020-01-12 00:55:15 +08:00
2019-09-22 23:02:08 +08:00
os.system("xmake -b {} hikyuu".format("-v -D" if verbose else ""))
os.system("xmake -b {} _hikyuu".format("-v -D" if verbose else ""))
os.system("xmake -b {} _indicator".format("-v -D" if verbose else ""))
os.system("xmake -b {} _trade_manage".format("-v -D" if verbose else ""))
os.system("xmake -b {} _trade_sys".format("-v -D" if verbose else ""))
os.system("xmake -b {} _trade_instance".format("-v -D" if verbose else ""))
os.system("xmake -b {} _data_driver".format("-v -D" if verbose else ""))
2019-07-27 16:17:28 +08:00
2020-01-12 00:55:15 +08:00
# 保存当前的编译信息
save_current_compile_info(current_compile_info)
2019-07-27 16:17:28 +08:00
#------------------------------------------------------------------------------
# 控制台命令
#------------------------------------------------------------------------------
2020-01-12 00:55:15 +08:00
2019-07-27 16:17:28 +08:00
@click.group()
def cli():
pass
@click.command()
@click.option('-v', '--verbose', is_flag=True, help='')
2020-01-12 00:55:15 +08:00
@click.option('-m',
'--mode',
default='release',
type=click.Choice(['release', 'debug']),
help='')
def build(verbose, mode):
2019-07-27 16:17:28 +08:00
""" 执行编译 """
start_build(verbose, mode)
2019-07-27 16:17:28 +08:00
@click.command()
2019-09-20 02:58:03 +08:00
@click.option('-all', "--all", is_flag=True, help="执行全部测试, 否则仅仅进行最小范围测试)")
@click.option("-compile", "--compile", is_flag=True, help='')
@click.option('-v', '--verbose', is_flag=True, help='')
2020-01-12 00:55:15 +08:00
@click.option('-m',
'--mode',
default='release',
type=click.Choice(['release', 'debug']),
help='')
def test(all, compile, verbose, mode):
2019-07-27 16:17:28 +08:00
""" 执行单元测试 """
2020-01-12 00:55:15 +08:00
current_compile_info = get_current_compile_info()
current_compile_info['mode'] = mode
history_compile_info = get_history_compile_info()
if compile or current_compile_info != history_compile_info:
start_build(verbose, mode)
2019-09-20 02:58:03 +08:00
if all:
os.system("xmake f --test=all --mode={}".format(mode))
os.system("xmake -b unit-test")
os.system("xmake r unit-test")
else:
os.system("xmake f --test=small --mode={}".format(mode))
os.system("xmake -b small-test")
os.system("xmake r small-test")
2019-07-27 16:17:28 +08:00
2020-01-12 00:55:15 +08:00
@click.command()
@click.option("-with_boost", "--with_boost", is_flag=True, help='BOOST库')
def clear(with_boost):
2019-07-27 16:17:28 +08:00
""" 清除当前编译设置及结果 """
2019-02-16 18:38:23 +08:00
if os.path.lexists('.xmake'):
print('delete .xmake')
2019-02-16 18:38:23 +08:00
shutil.rmtree('.xmake')
if os.path.lexists('build'):
print('delete build')
2019-02-16 18:38:23 +08:00
shutil.rmtree('build')
if os.path.lexists('Hikyuu.egg-info'):
print('delete Hikyuu.egg-info')
shutil.rmtree('Hikyuu.egg-info')
2020-01-12 00:55:15 +08:00
if os.path.exists('compile_info'):
print('delete compile_info')
os.remove('compile_info')
2019-07-27 16:17:28 +08:00
for r, _, f_list in os.walk('hikyuu'):
for name in f_list:
2019-02-28 19:59:42 +08:00
if (name != 'UnRAR.exe' and len(name) > 4 and name[-4:] in ('.dll','.exe','.pyd')) \
2019-02-28 21:56:13 +08:00
or (len(name) > 8 and name[:9] == 'libboost_') \
or (len(name) > 6 and name[-6:] == '.dylib'):
print('delete', r + '/' + name)
os.remove(os.path.join(r, name))
2019-02-16 18:38:23 +08:00
print('clear finished!')
2019-02-14 23:13:10 +08:00
2019-07-27 16:17:28 +08:00
@click.command()
def uninstall():
""" 卸载已安装的 python 包 """
if sys.platform == 'win32':
site_lib_dir = sys.base_prefix + "/lib/site-packages"
else:
usr_dir = os.path.expanduser('~')
py_version, _ = get_python_version()
2020-01-12 00:55:15 +08:00
site_lib_dir = '{}/.local/lib/python{:>.1f}/site-packages'.format(
usr_dir, py_version * 0.1)
2019-07-27 16:17:28 +08:00
for dir in os.listdir(site_lib_dir):
if dir == 'hikyuu' or (len(dir) > 6 and dir[:6] == 'Hikyuu'):
print('delete', site_lib_dir + '/' + dir)
shutil.rmtree(site_lib_dir + '/' + dir)
print("Uninstall finished!")
2019-02-17 01:06:01 +08:00
2019-07-27 16:17:28 +08:00
@click.command()
def install():
""" 编译并安装 Hikyuu python 库 """
2020-01-12 00:55:15 +08:00
start_build(False, 'release')
2019-07-27 16:17:28 +08:00
if sys.platform == 'win32':
2020-01-09 00:11:37 +08:00
install_dir = sys.base_prefix + "\\Lib\\site-packages\\hikyuu"
else:
usr_dir = os.path.expanduser('~')
2020-01-12 00:55:15 +08:00
install_dir = '{}/.local/lib/python{:>.1f}/site-packages/hikyuu'.format(
usr_dir, get_python_version() * 0.1)
2019-03-07 22:56:12 +08:00
try:
shutil.rmtree(install_dir)
except:
pass
os.makedirs(install_dir)
os.system('xmake install -o "{}"'.format(install_dir))
2019-02-14 23:13:10 +08:00
2019-07-27 16:17:28 +08:00
@click.command()
def wheel():
""" 生成 python 的 wheel 安装包 """
# 尝试编译
2020-01-12 00:55:15 +08:00
start_build(False, 'release')
2019-07-27 16:17:28 +08:00
# 清理之前遗留的打包产物
print("Clean up the before papackaging outputs ...")
2020-01-14 23:47:24 +08:00
py_version = get_python_version()
2019-07-27 16:17:28 +08:00
if os.path.lexists('Hikyuu.egg-info'):
shutil.rmtree('Hikyuu.egg-info')
if os.path.lexists('build/lib'):
shutil.rmtree('build/lib')
if os.path.lexists('build'):
for bdist in os.listdir('build'):
2020-01-12 00:55:15 +08:00
if len(bdist) >= 5 and bdist[:5] == 'bdist' and os.path.lexists(
bdist):
2019-07-27 16:17:28 +08:00
shutil.rmtree(bdist)
for x in os.listdir('hikyuu'):
if x[:12] == 'boost_python':
if x[12:14] != str(py_version):
os.remove('hikyuu/{}'.format(x))
# 构建打包命令
print("start pacakaging bdist_wheel ...")
current_plat = sys.platform
current_bits = 64 if sys.maxsize > 2**32 else 32
2019-02-15 23:19:30 +08:00
if current_plat == 'win32' and current_bits == 64:
2019-07-27 16:17:28 +08:00
plat = "win-amd64"
2019-02-15 23:19:30 +08:00
elif current_plat == 'win32' and current_bits == 32:
2019-07-27 16:17:28 +08:00
plat = "win32"
2019-02-15 23:19:30 +08:00
elif current_plat == 'linux' and current_bits == 64:
2019-07-27 16:17:28 +08:00
plat = "manylinux1_x86_64"
2019-02-15 23:19:30 +08:00
elif current_plat == 'linux' and current_bits == 32:
2019-07-27 16:17:28 +08:00
plat = "manylinux1_i386"
2019-02-15 23:19:30 +08:00
else:
2019-07-27 16:17:28 +08:00
print("*********尚未实现该平台的支持*******")
return
2020-01-12 00:55:15 +08:00
cmd = 'python sub_setup.py bdist_wheel --python-tag cp{} -p {}'.format(
py_version, plat)
2019-07-27 16:17:28 +08:00
os.system(cmd)
@click.command()
def upload():
""" 发布上传至 pypi仅供发布者使用 """
if not os.path.lexists('dist'):
print("Not found wheel package! Pleae wheel first")
return
print("current wheel:")
for bdist in os.listdir('dist'):
print(bdist)
print("")
val = input('Are you sure upload now (y/n)? (deault: n) ')
if val == 'y':
os.system("twine upload dist/*")
#------------------------------------------------------------------------------
# 添加 click 命令
#------------------------------------------------------------------------------
cli.add_command(build)
cli.add_command(test)
cli.add_command(clear)
cli.add_command(install)
cli.add_command(uninstall)
cli.add_command(wheel)
cli.add_command(upload)
if __name__ == "__main__":
cli()