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_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()
|
2022-02-02 18:10:31 +08:00
|
|
|
|
min_version = int(py_version[1])
|
|
|
|
|
main_version = int(py_version[0])
|
2023-05-04 22:37:50 +08:00
|
|
|
|
#py_version = main_version * 10 + min_version if min_version < 10 else main_version * 100 + min_version
|
|
|
|
|
py_version = f"{main_version}.{min_version}"
|
|
|
|
|
print(f'current python version: {py_version}')
|
2020-01-12 00:55:15 +08:00
|
|
|
|
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_compile_info = {
|
|
|
|
|
'plat': sys.platform,
|
|
|
|
|
'arch': current_arch,
|
|
|
|
|
'mode': '',
|
|
|
|
|
'py_version': py_version,
|
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
2020-01-10 01:45:32 +08:00
|
|
|
|
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)
|
2019-02-18 22:49:21 +08:00
|
|
|
|
else:
|
2019-07-27 16:17:28 +08:00
|
|
|
|
print("************不支持的平台**************")
|
|
|
|
|
exit(0)
|
|
|
|
|
if os.path.lexists(build_pywrap_dir):
|
|
|
|
|
shutil.rmtree(build_pywrap_dir)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
|
# 执行构建
|
|
|
|
|
#------------------------------------------------------------------------------
|
2021-05-02 02:10:27 +08:00
|
|
|
|
def start_build(verbose=False, mode='release', worker_num=2):
|
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']
|
2019-07-27 16:17:28 +08:00
|
|
|
|
|
2020-01-12 00:55:15 +08:00
|
|
|
|
#如果 python版本或者编译模式发生变化,则编译依赖的 boost 库(boost.python)
|
|
|
|
|
history_compile_info = get_history_compile_info()
|
2020-04-08 00:24:12 +08:00
|
|
|
|
if py_version != history_compile_info[
|
|
|
|
|
'py_version'] or history_compile_info['mode'] != mode:
|
2020-01-10 01:45:32 +08:00
|
|
|
|
clear_with_python_changed(mode)
|
2023-05-04 22:37:50 +08:00
|
|
|
|
cmd = "xmake f {} -c -y -m {} --pyver={}".format(
|
|
|
|
|
"-v -D" if verbose else "", mode, py_version)
|
|
|
|
|
print(cmd)
|
|
|
|
|
os.system(cmd)
|
2020-01-12 00:55:15 +08:00
|
|
|
|
|
2020-04-08 00:24:12 +08:00
|
|
|
|
if mode == "release":
|
2021-05-02 02:10:27 +08:00
|
|
|
|
os.system("xmake -j {} -b {} core".format(worker_num,
|
|
|
|
|
"-v -D" if verbose else ""))
|
2023-09-27 02:49:36 +08:00
|
|
|
|
else:
|
|
|
|
|
os.system("xmake -j {} -b {} hikyuu".format(
|
|
|
|
|
worker_num, "-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='显示详细的编译信息')
|
2021-05-02 02:10:27 +08:00
|
|
|
|
@click.option('-j', '--j', default=2, help="并行编译数量")
|
2020-01-12 00:55:15 +08:00
|
|
|
|
@click.option('-m',
|
|
|
|
|
'--mode',
|
|
|
|
|
default='release',
|
2022-01-30 18:16:29 +08:00
|
|
|
|
type=click.Choice([
|
|
|
|
|
'release', 'debug', 'coverage', 'asan', 'tsan', 'msan',
|
|
|
|
|
'lsan'
|
|
|
|
|
]),
|
2020-01-12 00:55:15 +08:00
|
|
|
|
help='编译模式')
|
2021-05-02 02:10:27 +08:00
|
|
|
|
def build(verbose, mode, j):
|
2019-07-27 16:17:28 +08:00
|
|
|
|
""" 执行编译 """
|
2021-05-02 02:10:27 +08:00
|
|
|
|
start_build(verbose, mode, j)
|
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='强制重新编译')
|
2019-09-09 02:11:26 +08:00
|
|
|
|
@click.option('-v', '--verbose', is_flag=True, help='显示详细的编译信息')
|
2021-05-02 02:10:27 +08:00
|
|
|
|
@click.option('-j', '--j', default=2, help="并行编译数量")
|
2020-01-12 00:55:15 +08:00
|
|
|
|
@click.option('-m',
|
|
|
|
|
'--mode',
|
|
|
|
|
default='release',
|
2022-01-30 18:16:29 +08:00
|
|
|
|
type=click.Choice([
|
|
|
|
|
'release', 'debug', 'coverage', 'asan', 'msan', 'tsan',
|
|
|
|
|
'lsan'
|
|
|
|
|
]),
|
2020-01-12 00:55:15 +08:00
|
|
|
|
help='编译模式')
|
2020-09-19 00:48:05 +08:00
|
|
|
|
@click.option('-case', '--case', default='', help="执行指定的 TestCase")
|
2021-05-02 02:10:27 +08:00
|
|
|
|
def test(all, compile, verbose, mode, case, j):
|
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:
|
2023-08-18 02:22:19 +08:00
|
|
|
|
start_build(verbose, mode, j)
|
2019-09-20 02:58:03 +08:00
|
|
|
|
if all:
|
2021-05-02 02:10:27 +08:00
|
|
|
|
os.system("xmake -j {} -b {} unit-test".format(
|
|
|
|
|
j, "-v -D" if verbose else ""))
|
2022-02-11 00:22:57 +08:00
|
|
|
|
os.system("xmake r unit-test {}".format(
|
|
|
|
|
'' if case == '' else '--test-case={}'.format(case)))
|
2019-09-09 02:11:26 +08:00
|
|
|
|
else:
|
2021-05-02 02:10:27 +08:00
|
|
|
|
os.system("xmake -j {} -b {} small-test".format(
|
|
|
|
|
j, "-v -D" if verbose else ""))
|
2020-09-19 00:48:05 +08:00
|
|
|
|
os.system("xmake r small-test {}".format(
|
2022-02-11 00:22:57 +08:00
|
|
|
|
'' if case == '' else '--test-case={}'.format(case)))
|
2019-07-27 16:17:28 +08:00
|
|
|
|
|
|
|
|
|
|
2023-03-26 17:27:51 +08:00
|
|
|
|
def clear_build():
|
2019-07-27 16:17:28 +08:00
|
|
|
|
""" 清除当前编译设置及结果 """
|
2019-02-16 18:38:23 +08:00
|
|
|
|
if os.path.lexists('.xmake'):
|
2019-02-17 18:59:58 +08:00
|
|
|
|
print('delete .xmake')
|
2019-02-16 18:38:23 +08:00
|
|
|
|
shutil.rmtree('.xmake')
|
|
|
|
|
if os.path.lexists('build'):
|
2019-02-17 18:59:58 +08:00
|
|
|
|
print('delete build')
|
2019-02-16 18:38:23 +08:00
|
|
|
|
shutil.rmtree('build')
|
2019-02-17 18:59:58 +08:00
|
|
|
|
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-02-16 18:38:23 +08:00
|
|
|
|
print('clear finished!')
|
2020-09-26 00:14:44 +08:00
|
|
|
|
os.system("xmake clean")
|
2019-02-16 18:38:23 +08:00
|
|
|
|
|
2019-02-14 23:13:10 +08:00
|
|
|
|
|
2022-09-03 14:33:37 +08:00
|
|
|
|
@click.command()
|
2023-03-26 17:27:51 +08:00
|
|
|
|
def clear():
|
|
|
|
|
clear_build()
|
2022-09-03 14:33:37 +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('~')
|
2020-08-02 16:32:01 +08:00
|
|
|
|
py_version = get_python_version()
|
2023-05-04 22:37:50 +08:00
|
|
|
|
site_lib_dir = '{}/.local/lib/python{}/site-packages'.format(
|
|
|
|
|
usr_dir, py_version)
|
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)
|
2022-01-30 18:16:29 +08:00
|
|
|
|
if os.path.exists("./hikyuu.egg-info"):
|
|
|
|
|
shutil.rmtree("./hikyuu.egg-info")
|
2019-07-27 16:17:28 +08:00
|
|
|
|
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"
|
2019-02-18 22:49:21 +08:00
|
|
|
|
else:
|
|
|
|
|
usr_dir = os.path.expanduser('~')
|
2023-05-04 22:37:50 +08:00
|
|
|
|
install_dir = '{}/.local/lib/python{}/site-packages/hikyuu'.format(
|
|
|
|
|
usr_dir, get_python_version())
|
2019-03-07 22:56:12 +08:00
|
|
|
|
try:
|
|
|
|
|
shutil.rmtree(install_dir)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
os.makedirs(install_dir)
|
2019-04-17 02:38:37 +08:00
|
|
|
|
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()
|
2022-06-30 22:47:22 +08:00
|
|
|
|
@click.option('-j', '--j', default=2, help="并行编译数量")
|
|
|
|
|
def wheel(j):
|
2019-07-27 16:17:28 +08:00
|
|
|
|
""" 生成 python 的 wheel 安装包 """
|
2022-09-03 14:33:37 +08:00
|
|
|
|
# 清理之前遗留的打包产物
|
2023-03-26 17:27:51 +08:00
|
|
|
|
clear_build()
|
2022-09-03 14:33:37 +08:00
|
|
|
|
|
2019-07-27 16:17:28 +08:00
|
|
|
|
# 尝试编译
|
2022-06-30 22:47:22 +08:00
|
|
|
|
start_build(False, 'release', j)
|
2019-07-27 16:17:28 +08:00
|
|
|
|
|
|
|
|
|
# 构建打包命令
|
|
|
|
|
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"
|
2020-08-15 00:24:35 +08:00
|
|
|
|
elif current_plat == 'darwin' and current_bits == 32:
|
|
|
|
|
plat = "macosx_i686"
|
|
|
|
|
elif current_plat == 'darwin' and current_bits == 64:
|
|
|
|
|
plat = "macosx_10_9_x86_64"
|
2019-02-15 23:19:30 +08:00
|
|
|
|
else:
|
2019-07-27 16:17:28 +08:00
|
|
|
|
print("*********尚未实现该平台的支持*******")
|
|
|
|
|
return
|
2022-09-03 14:33:37 +08:00
|
|
|
|
|
|
|
|
|
py_version = get_python_version()
|
2023-08-13 18:22:01 +08:00
|
|
|
|
main_ver, min_ver = py_version.split('.')
|
2020-08-15 00:24:35 +08:00
|
|
|
|
if current_plat == 'win32':
|
2023-08-13 18:22:01 +08:00
|
|
|
|
cmd = 'python sub_setup.py bdist_wheel --python-tag cp{}{} -p {}'.format(
|
2023-05-04 22:37:50 +08:00
|
|
|
|
main_ver, min_ver, plat)
|
2020-08-15 00:24:35 +08:00
|
|
|
|
print(cmd)
|
|
|
|
|
os.system(cmd)
|
|
|
|
|
else:
|
2023-08-13 18:22:01 +08:00
|
|
|
|
cmd = 'python3 sub_setup.py bdist_wheel --python-tag cp{}{} -p {}'.format(
|
2023-05-04 22:37:50 +08:00
|
|
|
|
main_ver, min_ver, plat)
|
2020-08-15 00:24:35 +08:00
|
|
|
|
print(cmd)
|
|
|
|
|
os.system(cmd)
|
|
|
|
|
|
2019-07-27 16:17:28 +08:00
|
|
|
|
|
|
|
|
|
@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()
|