305 lines
11 KiB
Python
305 lines
11 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
import os
|
||
|
import subprocess
|
||
|
import sys
|
||
|
import shutil
|
||
|
import zipfile
|
||
|
from contextlib import contextmanager
|
||
|
import click
|
||
|
|
||
|
|
||
|
def get_platform():
|
||
|
""" a name for the platform """
|
||
|
if sys.platform.startswith('win'):
|
||
|
return 'win'
|
||
|
elif sys.platform == 'darwin':
|
||
|
return 'osx'
|
||
|
elif sys.platform.startswith('linux'):
|
||
|
return 'linux'
|
||
|
raise Exception('Unsupported platform ' + sys.platform)
|
||
|
|
||
|
|
||
|
SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
|
||
|
# we use Buildkite which sets this env variable by default
|
||
|
IS_BUILD_MACHINE = os.environ.get('CI', '') == 'true'
|
||
|
PLATFORM = get_platform()
|
||
|
INSTALL_ROOT = os.path.join(SCRIPT_PATH, 'builds', 'install')
|
||
|
|
||
|
|
||
|
def get_signtool():
|
||
|
""" get path to code signing tool """
|
||
|
if PLATFORM == 'win':
|
||
|
sdk_dir = 'c:\\Program Files (x86)\\Windows Kits\\10' # os.environ['WindowsSdkDir']
|
||
|
return os.path.join(sdk_dir, 'bin', 'x86', 'signtool.exe')
|
||
|
elif PLATFORM == 'osx':
|
||
|
return '/usr/bin/codesign'
|
||
|
|
||
|
|
||
|
@contextmanager
|
||
|
def cd(new_dir):
|
||
|
""" Temporarily change current directory """
|
||
|
if new_dir:
|
||
|
old_dir = os.getcwd()
|
||
|
os.chdir(new_dir)
|
||
|
yield
|
||
|
if new_dir:
|
||
|
os.chdir(old_dir)
|
||
|
|
||
|
|
||
|
def mkdir_p(path):
|
||
|
""" mkdir -p """
|
||
|
if not os.path.isdir(path):
|
||
|
click.secho('Making ' + path, fg='yellow')
|
||
|
os.makedirs(path)
|
||
|
|
||
|
|
||
|
@click.group(invoke_without_command=True)
|
||
|
@click.pass_context
|
||
|
@click.option('--clean', is_flag=True)
|
||
|
def cli(ctx, clean):
|
||
|
""" click wrapper for command line stuff """
|
||
|
if ctx.invoked_subcommand is None:
|
||
|
ctx.invoke(libs, clean=clean)
|
||
|
if IS_BUILD_MACHINE:
|
||
|
ctx.invoke(sign)
|
||
|
ctx.invoke(archive)
|
||
|
|
||
|
|
||
|
@cli.command()
|
||
|
@click.pass_context
|
||
|
def unity(ctx):
|
||
|
""" build just dynamic libs for use in unity project """
|
||
|
ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True)
|
||
|
BUILDS = []
|
||
|
|
||
|
click.echo('--- Copying libs and header into unity example')
|
||
|
UNITY_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'button-clicker', 'Assets', 'Plugins')
|
||
|
|
||
|
if sys.platform.startswith('win'):
|
||
|
LIBRARY_NAME = 'discord-rpc.dll'
|
||
|
BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release')
|
||
|
UNITY_64_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86_64')
|
||
|
BUILDS.append({BUILD_64_BASE_PATH: UNITY_64_DLL_PATH})
|
||
|
|
||
|
BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release')
|
||
|
UNITY_32_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86')
|
||
|
BUILDS.append({BUILD_32_BASE_PATH: UNITY_32_DLL_PATH})
|
||
|
|
||
|
elif sys.platform == 'darwin':
|
||
|
LIBRARY_NAME = 'discord-rpc.bundle'
|
||
|
BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src')
|
||
|
UNITY_DLL_PATH = UNITY_PROJECT_PATH
|
||
|
os.rename(
|
||
|
os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.dylib'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.bundle'))
|
||
|
|
||
|
BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH})
|
||
|
|
||
|
elif sys.platform.startswith('linux'):
|
||
|
LIBRARY_NAME = 'discord-rpc.so'
|
||
|
BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src')
|
||
|
UNITY_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86')
|
||
|
os.rename(os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.so'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.so'))
|
||
|
|
||
|
BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH})
|
||
|
|
||
|
else:
|
||
|
raise Exception('Unsupported platform ' + sys.platform)
|
||
|
|
||
|
for build in BUILDS:
|
||
|
for i in build:
|
||
|
mkdir_p(build[i])
|
||
|
shutil.copy(os.path.join(i, LIBRARY_NAME), build[i])
|
||
|
|
||
|
|
||
|
@cli.command()
|
||
|
@click.pass_context
|
||
|
def unreal(ctx):
|
||
|
""" build libs and copy them into the unreal project """
|
||
|
ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True)
|
||
|
BUILDS = []
|
||
|
|
||
|
click.echo('--- Copying libs and header into unreal example')
|
||
|
UNREAL_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'unrealstatus', 'Plugins', 'discordrpc')
|
||
|
UNREAL_INCLUDE_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Include')
|
||
|
mkdir_p(UNREAL_INCLUDE_PATH)
|
||
|
shutil.copy(os.path.join(SCRIPT_PATH, 'include', 'discord_rpc.h'), UNREAL_INCLUDE_PATH)
|
||
|
|
||
|
if sys.platform.startswith('win'):
|
||
|
LIBRARY_NAME = 'discord-rpc.lib'
|
||
|
BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release')
|
||
|
UNREAL_64_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win64')
|
||
|
BUILDS.append({BUILD_64_BASE_PATH: UNREAL_64_DLL_PATH})
|
||
|
|
||
|
BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release')
|
||
|
UNREAL_32_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win32')
|
||
|
BUILDS.append({BUILD_32_BASE_PATH: UNREAL_32_DLL_PATH})
|
||
|
|
||
|
elif sys.platform == 'darwin':
|
||
|
LIBRARY_NAME = 'libdiscord-rpc.dylib'
|
||
|
BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src')
|
||
|
UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Mac')
|
||
|
|
||
|
BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH})
|
||
|
|
||
|
elif sys.platform.startswith('linux'):
|
||
|
LIBRARY_NAME = 'libdiscord-rpc.so'
|
||
|
BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src')
|
||
|
UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Linux')
|
||
|
|
||
|
BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH})
|
||
|
|
||
|
else:
|
||
|
raise Exception('Unsupported platform ' + sys.platform)
|
||
|
|
||
|
for build in BUILDS:
|
||
|
for i in build:
|
||
|
mkdir_p(build[i])
|
||
|
shutil.copy(os.path.join(i, LIBRARY_NAME), build[i])
|
||
|
|
||
|
|
||
|
def build_lib(build_name, generator, options, just_release):
|
||
|
""" Create a dir under builds, run build and install in it """
|
||
|
build_path = os.path.join(SCRIPT_PATH, 'builds', build_name)
|
||
|
install_path = os.path.join(INSTALL_ROOT, build_name)
|
||
|
mkdir_p(build_path)
|
||
|
mkdir_p(install_path)
|
||
|
with cd(build_path):
|
||
|
initial_cmake = ['cmake', SCRIPT_PATH, '-DCMAKE_INSTALL_PREFIX=%s' % os.path.join('..', 'install', build_name)]
|
||
|
if generator:
|
||
|
initial_cmake.extend(['-G', generator])
|
||
|
for key in options:
|
||
|
val = options[key]
|
||
|
if type(val) is bool:
|
||
|
val = 'ON' if val else 'OFF'
|
||
|
initial_cmake.append('-D%s=%s' % (key, val))
|
||
|
click.echo('--- Building ' + build_name)
|
||
|
subprocess.check_call(initial_cmake)
|
||
|
if not just_release:
|
||
|
subprocess.check_call(['cmake', '--build', '.', '--config', 'Debug'])
|
||
|
subprocess.check_call(['cmake', '--build', '.', '--config', 'Release', '--target', 'install'])
|
||
|
|
||
|
|
||
|
@cli.command()
|
||
|
def archive():
|
||
|
""" create zip of install dir """
|
||
|
click.echo('--- Archiving')
|
||
|
archive_file_path = os.path.join(SCRIPT_PATH, 'builds', 'discord-rpc-%s.zip' % get_platform())
|
||
|
archive_file = zipfile.ZipFile(archive_file_path, 'w', zipfile.ZIP_DEFLATED)
|
||
|
archive_src_base_path = INSTALL_ROOT
|
||
|
archive_dst_base_path = 'discord-rpc'
|
||
|
with cd(archive_src_base_path):
|
||
|
for path, _, filenames in os.walk('.'):
|
||
|
for fname in filenames:
|
||
|
fpath = os.path.join(path, fname)
|
||
|
dst_path = os.path.normpath(os.path.join(archive_dst_base_path, fpath))
|
||
|
click.echo('Adding ' + dst_path)
|
||
|
archive_file.write(fpath, dst_path)
|
||
|
|
||
|
|
||
|
@cli.command()
|
||
|
def sign():
|
||
|
""" Do code signing within install directory using our cert """
|
||
|
tool = get_signtool()
|
||
|
signable_extensions = set()
|
||
|
if PLATFORM == 'win':
|
||
|
signable_extensions.add('.dll')
|
||
|
sign_command_base = [
|
||
|
tool,
|
||
|
'sign',
|
||
|
'/n',
|
||
|
'Discord Inc.',
|
||
|
'/a',
|
||
|
'/tr',
|
||
|
'http://timestamp.digicert.com/rfc3161',
|
||
|
'/as',
|
||
|
'/td',
|
||
|
'sha256',
|
||
|
'/fd',
|
||
|
'sha256',
|
||
|
]
|
||
|
elif PLATFORM == 'osx':
|
||
|
signable_extensions.add('.dylib')
|
||
|
sign_command_base = [
|
||
|
tool,
|
||
|
'--keychain',
|
||
|
os.path.expanduser('~/Library/Keychains/login.keychain'),
|
||
|
'-vvvv',
|
||
|
'--deep',
|
||
|
'--force',
|
||
|
'--sign',
|
||
|
'Developer ID Application: Hammer & Chisel Inc. (53Q6R32WPB)',
|
||
|
]
|
||
|
else:
|
||
|
click.secho('Not signing things on this platform yet', fg='red')
|
||
|
return
|
||
|
|
||
|
click.echo('--- Signing')
|
||
|
for path, _, filenames in os.walk(INSTALL_ROOT):
|
||
|
for fname in filenames:
|
||
|
ext = os.path.splitext(fname)[1]
|
||
|
if ext not in signable_extensions:
|
||
|
continue
|
||
|
fpath = os.path.join(path, fname)
|
||
|
click.echo('Sign ' + fpath)
|
||
|
sign_command = sign_command_base + [fpath]
|
||
|
subprocess.check_call(sign_command)
|
||
|
|
||
|
|
||
|
@cli.command()
|
||
|
@click.option('--clean', is_flag=True)
|
||
|
@click.option('--static', is_flag=True)
|
||
|
@click.option('--shared', is_flag=True)
|
||
|
@click.option('--skip_formatter', is_flag=True)
|
||
|
@click.option('--just_release', is_flag=True)
|
||
|
def libs(clean, static, shared, skip_formatter, just_release):
|
||
|
""" Do all the builds for this platform """
|
||
|
if clean:
|
||
|
shutil.rmtree('builds', ignore_errors=True)
|
||
|
|
||
|
mkdir_p('builds')
|
||
|
|
||
|
if not (static or shared):
|
||
|
static = True
|
||
|
shared = True
|
||
|
|
||
|
static_options = {}
|
||
|
dynamic_options = {
|
||
|
'BUILD_SHARED_LIBS': True,
|
||
|
'USE_STATIC_CRT': True,
|
||
|
}
|
||
|
|
||
|
if skip_formatter or IS_BUILD_MACHINE:
|
||
|
static_options['CLANG_FORMAT_SUFFIX'] = 'none'
|
||
|
dynamic_options['CLANG_FORMAT_SUFFIX'] = 'none'
|
||
|
|
||
|
if IS_BUILD_MACHINE:
|
||
|
just_release = True
|
||
|
static_options['WARNINGS_AS_ERRORS'] = True
|
||
|
dynamic_options['WARNINGS_AS_ERRORS'] = True
|
||
|
|
||
|
if PLATFORM == 'win':
|
||
|
generator32 = 'Visual Studio 14 2015'
|
||
|
generator64 = 'Visual Studio 14 2015 Win64'
|
||
|
if static:
|
||
|
build_lib('win32-static', generator32, static_options, just_release)
|
||
|
build_lib('win64-static', generator64, static_options, just_release)
|
||
|
if shared:
|
||
|
build_lib('win32-dynamic', generator32, dynamic_options, just_release)
|
||
|
build_lib('win64-dynamic', generator64, dynamic_options, just_release)
|
||
|
elif PLATFORM == 'osx':
|
||
|
if static:
|
||
|
build_lib('osx-static', None, static_options, just_release)
|
||
|
if shared:
|
||
|
build_lib('osx-dynamic', None, dynamic_options, just_release)
|
||
|
elif PLATFORM == 'linux':
|
||
|
if static:
|
||
|
build_lib('linux-static', None, static_options, just_release)
|
||
|
if shared:
|
||
|
build_lib('linux-dynamic', None, dynamic_options, just_release)
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
os.chdir(SCRIPT_PATH)
|
||
|
sys.exit(cli())
|