1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-04-21 21:52:03 +02:00
jami-client-qt/extras/scripts/build-windows.py
Aline Gondim Santos 956b7f7da5 windows: add support for system theme
Use registry
"HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion
/Themes/Personalize/AppsUseLightTheme"
to check if system theme is supported and if it is dark or
light.

Removes "EnableDarkTheme" in favor of "AppTheme".

Requires Windows SDK version 10.0.18362.0 to build with
system theme support.

Note: This does not watch for changes in system theme in
runtime as the support for it requires Windows Runtime
version 10.0.10240.0.

GitLab: #723

Change-Id: Ice8f7936a90535f47dc1870d4f18215e062684ba
2022-12-06 09:07:15 -05:00

344 lines
10 KiB
Python

#!/usr/bin/env python3
import tempfile
import re
import sys
import os
import subprocess
import platform
import argparse
import multiprocessing
import fileinput
from enum import Enum
qt_version_default = '6.2.3'
vs_where_path = os.path.join(
os.environ['ProgramFiles(x86)'], 'Microsoft Visual Studio', 'Installer', 'vswhere.exe'
)
host_is_64bit = (False, True)[platform.machine().endswith('64')]
this_dir = os.path.dirname(os.path.realpath(__file__))
repo_root_dir = os.path.dirname(os.path.dirname(this_dir))
build_dir = os.path.join(repo_root_dir, 'build')
temp_path = os.environ['TEMP']
openssl_include_dir = 'C:\\Qt\\Tools\\OpenSSL\\Win_x64\\include\\openssl'
qt_path = os.path.join('c:', os.sep, 'Qt')
qt_kit_path = 'msvc2019_64'
qt_root_path = os.getenv('QT_ROOT_DIRECTORY', qt_path)
# project path
installer_project = os.path.join(
repo_root_dir, 'JamiInstaller', 'JamiInstaller.wixproj')
unit_test_project = os.path.join(build_dir, 'tests', 'unittests.vcxproj')
qml_test_project = os.path.join(build_dir, 'tests', 'qml_tests.vcxproj')
# test executable command
qml_test_exe = os.path.join(repo_root_dir, 'x64', 'test', 'qml_tests.exe -input ') + \
os.path.join(repo_root_dir, 'tests', 'qml')
unit_test_exe = os.path.join(repo_root_dir, 'x64', 'test', 'unittests.exe')
def execute_cmd(cmd, with_shell=False, env_vars=None, cmd_dir=repo_root_dir):
p = subprocess.Popen(cmd,
shell=with_shell,
stdout=sys.stdout,
env=env_vars,
cwd=cmd_dir)
_, _ = p.communicate()
return p.returncode
def getLatestVSVersion():
args = [
'-latest',
'-products *',
'-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
'-property installationVersion'
]
cmd = [vs_where_path] + args
output = subprocess.check_output(' '.join(cmd)).decode('utf-8')
if output:
return output.splitlines()[0].split('.')[0]
else:
return
def findVSLatestDir():
args = [
'-latest',
'-products *',
'-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
'-property installationPath'
]
cmd = [vs_where_path] + args
output = subprocess.check_output(
' '.join(cmd)).decode('utf-8', errors='ignore')
if output:
return output.splitlines()[0]
else:
return
def findMSBuild():
filename = 'MSBuild.exe'
for root, _, files in os.walk(findVSLatestDir() + r'\\MSBuild'):
if filename in files:
return os.path.join(root, filename)
def getMSBuildArgs(arch, config_str, configuration_type=''):
msbuild_args = [
'/nologo',
'/verbosity:minimal',
'/maxcpucount:' + str(multiprocessing.cpu_count()),
'/p:Platform=' + arch,
'/p:Configuration=' + config_str,
'/p:useenv=true']
if (configuration_type != ''):
msbuild_args.append('/p:ConfigurationType=' + configuration_type)
return msbuild_args
def getVSEnv(arch='x64', platform='', version=''):
env_cmd = 'set path=%path:"=% && ' + \
getVSEnvCmd(arch, platform, version) + ' && set'
p = subprocess.Popen(env_cmd,
shell=True,
stdout=subprocess.PIPE)
stdout, _ = p.communicate()
out = stdout.decode('utf-8', errors='ignore').split("\r\n")[5:-1]
return dict(s.split('=', 1) for s in out)
def getVSEnvCmd(arch='x64', platform='', version=''):
vcEnvInit = [findVSLatestDir() + r'\VC\Auxiliary\Build\"vcvarsall.bat']
if platform != '':
args = [arch, platform, version]
else:
args = [arch, version]
if args:
vcEnvInit.extend(args)
vcEnvInit = 'call \"' + ' '.join(vcEnvInit)
return vcEnvInit
def replace_necessary_vs_prop(project_path, toolset, sdk_version):
# force toolset
replace_vs_prop(project_path,
'PlatformToolset',
toolset)
# force unicode
replace_vs_prop(project_path,
'CharacterSet',
'Unicode')
# force sdk_version
replace_vs_prop(project_path,
'WindowsTargetPlatformVersion',
sdk_version)
def build_project(msbuild, msbuild_args, proj, env_vars):
args = []
args.extend(msbuild_args)
args.append(proj)
cmd = [msbuild]
cmd.extend(args)
if (execute_cmd(cmd, True, env_vars)):
print("Build failed when building ", proj)
sys.exit(1)
def replace_vs_prop(filename, prop, val):
p = re.compile(r'(?s)<' + prop + r'\s?.*?>(.*?)<\/' + prop + r'>')
val = r'<' + prop + r'>' + val + r'</' + prop + r'>'
with fileinput.FileInput(filename, inplace=True) as file:
for line in file:
print(re.sub(p, val, line), end='')
def init_submodules():
print('Initializing submodules...')
if (execute_cmd(['git', 'submodule', 'update', '--init'], False)):
print('Submodule initialization error.')
else:
if (execute_cmd(['git', 'submodule', 'update', '--recursive'], False)):
print('Submodule recursive checkout error.')
else:
print('Submodule recursive checkout finished.')
def build_deps():
print('Patching and building qrencode')
apply_cmd = [
'git',
'apply',
'--reject',
'--ignore-whitespace',
'--whitespace=fix'
]
qrencode_dir = os.path.join(repo_root_dir, '3rdparty', 'qrencode-win32')
patch_file = os.path.join(repo_root_dir, 'qrencode-win32.patch')
apply_cmd.append(patch_file)
print(apply_cmd)
if(execute_cmd(apply_cmd, False, None, qrencode_dir)):
print("Couldn't patch qrencode-win32.")
vs_env_vars = {}
vs_env_vars.update(getVSEnv())
msbuild = findMSBuild()
if not os.path.isfile(msbuild):
raise IOError('msbuild.exe not found. path=' + msbuild)
msbuild_args = getMSBuildArgs('x64', 'Release-Lib')
proj_path = os.path.join(qrencode_dir, 'qrencode-win32',
'vc8', 'qrcodelib', 'qrcodelib.vcxproj')
build_project(msbuild, msbuild_args, proj_path, vs_env_vars)
def build(config_str, qtver, tests=False):
print("Building with Qt " + qtver)
vs_env_vars = {}
vs_env_vars.update(getVSEnv())
qt_dir = os.path.join(qt_root_path, qtver, qt_kit_path)
daemon_dir = os.path.dirname(repo_root_dir) + '\\daemon'
daemon_bin_dir = daemon_dir + '\\build\\x64\\ReleaseLib_win32\\bin'
# We need to update the minimum SDK version to be able to
# build with system theme support
cmake_options = [
'-DCMAKE_PREFIX_PATH=' + qt_dir,
'-DCMAKE_INSTALL_PREFIX=' + daemon_bin_dir,
'-DLIBJAMI_INCLUDE_DIR=' + daemon_dir + '\\src\\jami',
'-DCMAKE_SYSTEM_VERSION=10.0.18362.0'
]
if tests:
cmake_options.append('-DENABLE_TESTS=true')
if not os.path.exists(build_dir):
os.makedirs(build_dir)
cmd = ['cmake', '..']
if (config_str == 'Beta'):
cmake_options.append('-DBETA=1')
print('Generating…')
cmd.extend(cmake_options)
if(execute_cmd(cmd, False, vs_env_vars, build_dir)):
print("Cmake generate error")
sys.exit(1)
print('Building…')
cmd = [
'cmake', '--build', '.',
'--config', 'Release',
'--', '-m'
]
if(execute_cmd(cmd, False, vs_env_vars, build_dir)):
print("Cmake build error")
sys.exit(1)
def run_tests(mute_jamid, output_to_files):
print('Running client tests')
test_exe_command_list = [qml_test_exe, unit_test_exe]
if mute_jamid:
test_exe_command_list[0] += ' -mutejamid'
test_exe_command_list[1] += ' -mutejamid'
if output_to_files:
test_exe_command_list[0] += ' -o ' + \
os.path.join(repo_root_dir, 'x64', 'test', 'qml_tests.txt')
test_exe_command_list[1] += ' > ' + \
os.path.join(repo_root_dir, 'x64', 'test', 'unittests.txt')
test_result_code = 0
# make sure that the tests are rendered offscreen
os.environ["QT_QPA_PLATFORM"] = 'offscreen'
os.environ["QT_QUICK_BACKEND"] = 'software'
for test_exe_command in test_exe_command_list:
if (execute_cmd(test_exe_command, True)):
test_result_code = 1
sys.exit(test_result_code)
def generate_msi_installer(config_str):
print('Generating application installer...')
vs_env_vars = {}
vs_env_vars.update(getVSEnv())
msbuild = findMSBuild()
if not os.path.isfile(msbuild):
raise IOError('msbuild.exe not found. path=' + msbuild)
msbuild_args = getMSBuildArgs('x64', config_str)
build_project(msbuild, msbuild_args, installer_project, vs_env_vars)
def parse_args():
ap = argparse.ArgumentParser(description="Client qt build tool")
subparser = ap.add_subparsers(dest="subparser_name")
ap.add_argument(
'-t', '--runtests', action='store_true',
help='Build and run tests')
ap.add_argument(
'-b', '--beta', action='store_true',
help='Build Qt Client in Beta Config')
ap.add_argument(
'-q', '--qtver', default=qt_version_default,
help='Sets the version of Qmake')
ap.add_argument(
'-m', '--mute', action='store_true', default=False,
help='Mute jamid logs')
subparser.add_parser('init')
subparser.add_parser('pack')
run_test = subparser.add_parser('runtests')
run_test.add_argument(
'-l', '--logtests', action='store_true', default=False,
help='Output tests log to files')
parsed_args = ap.parse_args()
return parsed_args
def main():
if not host_is_64bit:
print('These scripts will only run on a 64-bit Windows system for now!')
sys.exit(1)
if int(getLatestVSVersion()) < 15:
print('These scripts require at least Visual Studio v15 2017!')
sys.exit(1)
parsed_args = parse_args()
if parsed_args.subparser_name == 'init':
init_submodules()
build_deps()
elif parsed_args.subparser_name == 'pack':
config = ('Release', 'Beta')[parsed_args.beta]
generate_msi_installer(config)
sys.exit(1)
else:
config = ('Release', 'Beta')[parsed_args.beta]
build(config, parsed_args.qtver, parsed_args.runtests)
if parsed_args.runtests:
run_tests(parsed_args.mutejamid, parsed_args.outputtofiles)
if __name__ == '__main__':
main()