mirror of https://github.com/tp4a/teleport
435 lines
12 KiB
Python
435 lines
12 KiB
Python
# -*- coding: utf8 -*-
|
|
|
|
import os
|
|
import platform
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
from . import colorconsole as cc
|
|
from .env import env
|
|
|
|
|
|
from .configs import cfg
|
|
|
|
try:
|
|
CONFIG_FILE = os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')), 'config.ini')
|
|
if not cfg.init(CONFIG_FILE):
|
|
sys.exit(1)
|
|
except:
|
|
cc.e('can not load configuration.\n\nplease copy `config.ini.in` into `config.ini` and modify it to fit your condition and try again.')
|
|
sys.exit(1)
|
|
|
|
if cfg.is_py2:
|
|
import imp
|
|
elif cfg.is_py3:
|
|
import importlib
|
|
import importlib.machinery
|
|
|
|
if sys.platform == 'win32':
|
|
import winreg
|
|
|
|
THIS_PATH = os.path.abspath(os.path.dirname(__file__))
|
|
ROOT_PATH = os.path.abspath(os.path.join(THIS_PATH, '..'))
|
|
|
|
|
|
def download_file(desc, url, target_path, file_name):
|
|
cc.n('downloading {} ...'.format(desc))
|
|
|
|
local_file_name = os.path.join(target_path, file_name)
|
|
if os.path.exists(local_file_name):
|
|
cc.w('already exists, skip.')
|
|
return True
|
|
|
|
if env.is_win:
|
|
cmd = '"{}" --no-check-certificate {} -O "{}"'.format(env.wget, url, local_file_name)
|
|
sys_exec(cmd, True)
|
|
elif env.is_linux:
|
|
os.system('wget --no-check-certificate {} -O "{}"'.format(url, local_file_name))
|
|
else:
|
|
return False
|
|
|
|
if not os.path.exists(local_file_name):
|
|
cc.e('downloading {} from {} failed.'.format(desc, url))
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def extension_suffixes():
|
|
# imp.get_suffixes()
|
|
# 返回3元组列表(suffix, mode, type), 获得特殊模块的描述
|
|
# .suffix为文件后缀名;
|
|
# mode为打开文件模式;
|
|
# type为文件类型, 1代表PY_SOURCE, 2代表PY_COMPILED, 3代表C_EXTENSION
|
|
|
|
EXTENSION_SUFFIXES = list()
|
|
if cfg.is_py2:
|
|
suf = imp.get_suffixes()
|
|
for s in suf:
|
|
if s[2] == 3:
|
|
EXTENSION_SUFFIXES.append(s[0])
|
|
else:
|
|
EXTENSION_SUFFIXES = importlib.machinery.EXTENSION_SUFFIXES
|
|
|
|
if cfg.dist == 'windows':
|
|
if '.dll' not in EXTENSION_SUFFIXES:
|
|
EXTENSION_SUFFIXES.append('.dll')
|
|
|
|
elif cfg.dist == 'linux':
|
|
if '.so' not in EXTENSION_SUFFIXES:
|
|
EXTENSION_SUFFIXES.append('.so')
|
|
|
|
elif cfg.dist == 'macos':
|
|
raise RuntimeError('not support MacOS now.')
|
|
|
|
return EXTENSION_SUFFIXES
|
|
|
|
|
|
def remove(*args):
|
|
path = os.path.join(*args)
|
|
|
|
cc.v('remove [%s] ...' % path, end='')
|
|
if not os.path.exists(path):
|
|
cc.v('not exists, skip.')
|
|
return
|
|
|
|
for i in range(5):
|
|
cc.v('.', end='')
|
|
try:
|
|
if os.path.isdir(path):
|
|
shutil.rmtree(path, ignore_errors=True)
|
|
time.sleep(0.5)
|
|
else:
|
|
os.unlink(path)
|
|
except:
|
|
pass
|
|
|
|
if os.path.exists(path):
|
|
time.sleep(1)
|
|
else:
|
|
break
|
|
|
|
if os.path.exists(path):
|
|
cc.e('failed')
|
|
raise RuntimeError('')
|
|
else:
|
|
cc.i('done')
|
|
|
|
|
|
def makedirs(path, exist_ok=True):
|
|
if os.path.exists(path):
|
|
if not exist_ok:
|
|
raise RuntimeError('path already exists: %s' % path)
|
|
else:
|
|
return
|
|
|
|
for i in range(5):
|
|
try:
|
|
os.makedirs(path)
|
|
except:
|
|
time.sleep(1)
|
|
pass
|
|
|
|
if not os.path.exists(path):
|
|
time.sleep(1)
|
|
else:
|
|
break
|
|
|
|
if not os.path.exists(path):
|
|
raise RuntimeError('can not create: %s' % path)
|
|
|
|
|
|
def copy_file(s_path, t_path, f_name, force=True):
|
|
if isinstance(f_name, str):
|
|
f_from = f_name
|
|
f_to = f_name
|
|
elif isinstance(f_name, tuple):
|
|
f_from = f_name[0]
|
|
f_to = f_name[1]
|
|
else:
|
|
raise RuntimeError('utils.copy_file() got invalid param.')
|
|
|
|
s = os.path.join(s_path, f_from)
|
|
t = os.path.join(t_path, f_to)
|
|
if os.path.exists(t):
|
|
if force:
|
|
cc.v(' an exists version found, clean up...')
|
|
remove(t)
|
|
else:
|
|
cc.w(' an exists version found, skip copy.')
|
|
return
|
|
|
|
if not os.path.exists(t_path):
|
|
makedirs(t_path)
|
|
cc.v('copy [%s]\n -> [%s]' % (s, t))
|
|
shutil.copy(s, t)
|
|
|
|
|
|
def copy_ex(s_path, t_path, item_name=None, force=True):
|
|
if item_name is None:
|
|
s = s_path
|
|
t = t_path
|
|
else:
|
|
if isinstance(item_name, str):
|
|
f_from = item_name
|
|
f_to = item_name
|
|
elif isinstance(item_name, tuple):
|
|
f_from = item_name[0]
|
|
f_to = item_name[1]
|
|
else:
|
|
raise RuntimeError('utils.copy_ex() got invalid param.')
|
|
|
|
s = os.path.join(s_path, f_from)
|
|
t = os.path.join(t_path, f_to)
|
|
|
|
if os.path.exists(t):
|
|
if force:
|
|
remove(t)
|
|
else:
|
|
cc.w(t, 'already exists, skip copy.')
|
|
return
|
|
|
|
if os.path.isdir(s):
|
|
cc.v('copy [%s]\n -> [%s]' % (s, t))
|
|
shutil.copytree(s, t)
|
|
else:
|
|
if not os.path.exists(t_path):
|
|
os.makedirs(t_path)
|
|
cc.v('copy [%s]\n -> [%s]' % (s, t))
|
|
shutil.copy(s, t)
|
|
|
|
|
|
def update_file(s_path, t_path, f_name):
|
|
if isinstance(f_name, str):
|
|
f_from = f_name
|
|
f_to = f_name
|
|
elif isinstance(f_name, tuple):
|
|
f_from = f_name[0]
|
|
f_to = f_name[1]
|
|
else:
|
|
raise RuntimeError('utils.update_file() got invalid param.')
|
|
|
|
s = os.path.join(s_path, f_from)
|
|
t = os.path.join(t_path, f_to)
|
|
if not os.path.exists(s):
|
|
cc.w('try update file `%s` but not exists, skip.' % f_from)
|
|
return
|
|
|
|
# TODO: check file MD5 and update time.
|
|
|
|
if os.path.exists(t):
|
|
remove(t)
|
|
|
|
if not os.path.exists(t_path):
|
|
makedirs(t_path)
|
|
cc.v('update [%s]\n -> [%s]' % (s, t))
|
|
shutil.copy(os.path.join(s_path, f_from), t)
|
|
|
|
|
|
def ensure_file_exists(filename):
|
|
if not os.path.exists(filename):
|
|
raise RuntimeError('file not exists: {}'.format(filename))
|
|
if not os.path.isfile(filename):
|
|
raise RuntimeError('path exists but not a file: {}'.format(filename))
|
|
|
|
|
|
# def root_path():
|
|
# return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
|
|
|
|
|
def python_exec():
|
|
if not os.path.exists(sys.executable):
|
|
raise RuntimeError('Can not locate Python execute file.')
|
|
return sys.executable
|
|
|
|
|
|
def msbuild_path():
|
|
if cfg.toolchain.msbuild is not None:
|
|
return cfg.toolchain.msbuild
|
|
|
|
# 14.0 = VS2015
|
|
# 12.0 = VS2012
|
|
# 4.0 = VS2008
|
|
chk = ['14.0', '4.0', '12.0']
|
|
|
|
msp = None
|
|
for c in chk:
|
|
msp = winreg_read("SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}".format(c), 'MSBuildToolsPath')
|
|
if msp is not None:
|
|
break
|
|
|
|
if msp is None:
|
|
raise RuntimeError('Can not locate MSBuild.')
|
|
|
|
msb = os.path.join(msp[0], 'MSBuild.exe')
|
|
if not os.path.exists(msb):
|
|
raise RuntimeError('Can not locate MSBuild at {}'.format(msp))
|
|
|
|
cfg.toolchain.msbuild = msb
|
|
return msb
|
|
|
|
|
|
def nsis_path():
|
|
if cfg.toolchain.nsis is not None:
|
|
return cfg.toolchain.nsis
|
|
|
|
p = winreg_read_wow64_32(r'SOFTWARE\NSIS\Unicode', '')
|
|
if p is None:
|
|
raise RuntimeError('Can not locate unicode version of NSIS.')
|
|
|
|
p = os.path.join(p[0], 'makensis.exe')
|
|
if not os.path.exists(p):
|
|
raise RuntimeError('Can not locate NSIS at {}'.format(p))
|
|
|
|
cfg.toolchain.nsis = p
|
|
return p
|
|
|
|
|
|
def winreg_read(path, key):
|
|
try:
|
|
hkey = winreg.CreateKeyEx(winreg.HKEY_LOCAL_MACHINE, path, 0, winreg.KEY_READ)
|
|
value = winreg.QueryValueEx(hkey, key)
|
|
except OSError:
|
|
return None
|
|
|
|
return value
|
|
|
|
|
|
def winreg_read_wow64_32(path, key):
|
|
try:
|
|
hkey = winreg.CreateKeyEx(winreg.HKEY_LOCAL_MACHINE, path, 0, winreg.KEY_READ | winreg.KEY_WOW64_32KEY)
|
|
value = winreg.QueryValueEx(hkey, key)
|
|
except OSError:
|
|
return None
|
|
|
|
return value
|
|
|
|
|
|
def sys_exec(cmd, direct_output=False, output_codec=None):
|
|
cc.v(cmd)
|
|
# _os = platform.system().lower()
|
|
if output_codec is None:
|
|
if env.is_win:
|
|
output_codec = 'gb2312'
|
|
else:
|
|
output_codec = 'utf8'
|
|
|
|
p = None
|
|
if env.is_win:
|
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=True)
|
|
|
|
else:
|
|
p = subprocess.Popen(cmd, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=True)
|
|
|
|
output = ''
|
|
f = p.stdout
|
|
while True:
|
|
line = f.readline()
|
|
if 0 == len(line):
|
|
break
|
|
|
|
if direct_output:
|
|
cc.o((cc.CR_GRAY, line), end='')
|
|
|
|
output += line
|
|
|
|
ret = p.wait()
|
|
|
|
return (ret, output)
|
|
|
|
|
|
# def msvc_build(sln_file, proj_name, target, platform, force_rebuild):
|
|
# msbuild = msbuild_path()
|
|
#
|
|
# if force_rebuild:
|
|
# cmd = '"{}" "{}" "/target:clean" "/property:Configuration={};Platform={}"'.format(msbuild, sln_file, target, platform)
|
|
# ret, _ = sys_exec(cmd, direct_output=True)
|
|
# cc.v('ret:', ret)
|
|
#
|
|
# cmd = '"{}" "{}" "/target:{}" "/property:Configuration={};Platform={}"'.format(msbuild, sln_file, proj_name, target, platform)
|
|
# ret, _ = sys_exec(cmd, direct_output=True)
|
|
# if ret != 0:
|
|
# raise RuntimeError('build MSVC project `{}` failed.'.format(proj_name))
|
|
|
|
|
|
def nsis_build(nsi_file, _define=''):
|
|
nsis = nsis_path()
|
|
cmd = '"{}" /V2 {} /X"SetCompressor /SOLID /FINAL lzma" "{}"'.format(nsis, _define, nsi_file)
|
|
ret, _ = sys_exec(cmd, direct_output=True)
|
|
if ret != 0:
|
|
raise RuntimeError('make installer with nsis failed. [{}]'.format(nsi_file))
|
|
|
|
|
|
def cmake(work_path, target, force_rebuild, cmake_define=''):
|
|
# because cmake v2.8 shipped with Ubuntu 14.04LTS, but we need 3.5.
|
|
# I copy a v3.5 cmake from CLion.
|
|
print(cfg)
|
|
if 'cmake' not in cfg.toolchain:
|
|
raise RuntimeError('please set `cmake` path.')
|
|
|
|
print(cfg.toolchain.cmake)
|
|
if not os.path.exists(cfg.toolchain.cmake):
|
|
raise RuntimeError('`cmake` does not exists, please check your configuration and try again.')
|
|
|
|
CMAKE = cfg.toolchain.cmake
|
|
|
|
cc.n('make by cmake', target, sep=': ')
|
|
old_p = os.getcwd()
|
|
# new_p = os.path.dirname(wscript_file)
|
|
|
|
# work_path = os.path.join(root_path(), 'cmake-build')
|
|
if os.path.exists(work_path):
|
|
if force_rebuild:
|
|
remove(work_path)
|
|
if not os.path.exists(work_path):
|
|
makedirs(work_path)
|
|
|
|
os.chdir(work_path)
|
|
if target == 'debug':
|
|
target = 'Debug'
|
|
else:
|
|
target = 'Release'
|
|
cmd = '"{}" -DCMAKE_BUILD_TYPE={} {} ..;make'.format(CMAKE, target, cmake_define)
|
|
ret, _ = sys_exec(cmd, direct_output=True)
|
|
os.chdir(old_p)
|
|
if ret != 0:
|
|
raise RuntimeError('build with cmake failed, ret={}. [{}]'.format(ret, target))
|
|
|
|
|
|
def strip(filename):
|
|
cc.n('strip binary file', filename)
|
|
if not os.path.exists(filename):
|
|
return False
|
|
cmd = 'strip {}'.format(filename)
|
|
ret, _ = sys_exec(cmd, direct_output=True)
|
|
if ret != 0:
|
|
raise RuntimeError('failed to strip binary file [{}], ret={}.'.format(filename, ret))
|
|
return True
|
|
|
|
|
|
def make_zip(src_path, to_file):
|
|
cc.v('compress folder into .zip...')
|
|
n, _ = os.path.splitext(to_file)
|
|
# x = os.path.split(to_file)[1].split('.')
|
|
p = os.path.dirname(to_file)
|
|
shutil.make_archive(os.path.join(p, n), 'zip', src_path)
|
|
ensure_file_exists(to_file)
|
|
|
|
|
|
def make_targz(work_path, folder, to_file):
|
|
cc.v('compress folder into .tar.gz...')
|
|
old_p = os.getcwd()
|
|
|
|
os.chdir(work_path)
|
|
cmd = 'tar zcf "{}" "{}"'.format(to_file, folder)
|
|
ret, _ = sys_exec(cmd, direct_output=True)
|
|
ensure_file_exists(to_file)
|
|
os.chdir(old_p)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# test()
|
|
pass
|