mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-04-21 21:52:03 +02:00
packaging: windows: optionally skip windeployqt
This is a big time saver in the context of CI testing where we only need to supply some env vars instead. It would also be nice to also have the env vars filled out for CMake-generated project runtime configs to prevent unnecessary deployment for development builds, but that's not done in this commit. Change-Id: I338827cb87c9fc71c9a6b4b3076b22aa7cf7cfa3
This commit is contained in:
parent
a56ee62dcf
commit
66e0e21482
7 changed files with 92 additions and 151 deletions
|
@ -556,47 +556,6 @@ if(MSVC)
|
|||
target_sources(${PROJECT_NAME} PRIVATE ${QM_FILES})
|
||||
endif()
|
||||
|
||||
# POST_BUILD steps
|
||||
|
||||
# check time stamp
|
||||
set(TIME_STAMP_FILE ".deploy.stamp")
|
||||
add_custom_command(
|
||||
TARGET ${PROJECT_NAME}
|
||||
POST_BUILD
|
||||
WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
|
||||
COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE}
|
||||
-P ${EXTRAS_DIR}/build/cmake/time_stamp_check.cmake)
|
||||
|
||||
# copy runtime files and run windeployqt on target and deploy Qt libs
|
||||
add_custom_command(
|
||||
TARGET ${PROJECT_NAME}
|
||||
POST_BUILD
|
||||
WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
|
||||
COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE}
|
||||
-DCOPY_TO_PATH=$<TARGET_FILE_DIR:${PROJECT_NAME}>
|
||||
-DDRING_PATH=${DAEMON_DIR}
|
||||
-DPROJECT_ROOT_DIR=${PROJECT_SOURCE_DIR}
|
||||
-DPACKAGING_DIR=${PACKAGING_DIR}
|
||||
-P ${EXTRAS_DIR}/build/cmake/windows_daemon_deploy.cmake)
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${PROJECT_NAME}
|
||||
POST_BUILD
|
||||
WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
|
||||
COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE}
|
||||
-DWIN_DEPLOY_QT_PATH=${CMAKE_PREFIX_PATH}/bin
|
||||
-DQML_SRC_DIR=${APP_SRC_DIR}
|
||||
-DEXE_NAME=$<TARGET_FILE:${PROJECT_NAME}>
|
||||
-P ${EXTRAS_DIR}/build/cmake/windows_qt_deploy.cmake)
|
||||
|
||||
# create time stamp
|
||||
add_custom_command(
|
||||
TARGET ${PROJECT_NAME}
|
||||
POST_BUILD
|
||||
WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
|
||||
COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE}
|
||||
-P ${EXTRAS_DIR}/build/cmake/time_stamp_create.cmake)
|
||||
|
||||
# executable name
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "Jami")
|
||||
elseif (NOT APPLE)
|
||||
|
|
|
@ -12,33 +12,12 @@ xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">
|
|||
</xsl:template>
|
||||
|
||||
<xsl:key name="service-search" match="wix:Component[contains(wix:File/@Source, 'Jami.exe')]" use="@Id" />
|
||||
<xsl:key name="vc-service-search" match="wix:Component[contains(wix:File/@Source, 'redist') and contains(wix:File/@Source, 'vc')]" use="@Id" />
|
||||
<xsl:key name="pdb-search" match="wix:Component[contains(wix:File/@Source, '.pdb')]" use="@Id" />
|
||||
<xsl:key name="lib-search" match="wix:Component[contains(wix:File/@Source, 'Jami.lib')]" use="@Id" />
|
||||
<xsl:key name="exp-search" match="wix:Component[contains(wix:File/@Source, 'Jami.exp')]" use="@Id" />
|
||||
<xsl:key name="qmake-search" match="wix:Component[contains(wix:File/@Source, 'qmake')]" use="@Id" />
|
||||
<xsl:key name="obj-search" match="wix:Component[contains(wix:File/@Source, '.obj')]" use="@Id" />
|
||||
<xsl:key name="tlog-search" match="wix:Component[contains(wix:File/@Source, '.tlog')]" use="@Id" />
|
||||
<xsl:key name="log-search" match="wix:Component[contains(wix:File/@Source, '.log')]" use="@Id" />
|
||||
|
||||
<xsl:template match="wix:Component[key('service-search', @Id)]" />
|
||||
<xsl:template match="wix:Component[key('vc-service-search', @Id)]" />
|
||||
<xsl:template match="wix:Component[key('pdb-search', @Id)]" />
|
||||
<xsl:template match="wix:Component[key('lib-search', @Id)]" />
|
||||
<xsl:template match="wix:Component[key('exp-search', @Id)]" />
|
||||
<xsl:template match="wix:Component[key('qmake-search', @Id)]" />
|
||||
<xsl:template match="wix:Component[key('obj-search', @Id)]" />
|
||||
<xsl:template match="wix:Component[key('tlog-search', @Id)]" />
|
||||
<xsl:template match="wix:Component[key('log-search', @Id)]" />
|
||||
|
||||
<xsl:template match="wix:ComponentRef[key('service-search', @Id)]" />
|
||||
<xsl:template match="wix:ComponentRef[key('vc-service-search', @Id)]" />
|
||||
<xsl:template match="wix:ComponentRef[key('pdb-search', @Id)]" />
|
||||
<xsl:template match="wix:ComponentRef[key('lib-search', @Id)]" />
|
||||
<xsl:template match="wix:ComponentRef[key('exp-search', @Id)]" />
|
||||
<xsl:template match="wix:ComponentRef[key('qmake-search', @Id)]" />
|
||||
<xsl:template match="wix:ComponentRef[key('obj-search', @Id)]" />
|
||||
<xsl:template match="wix:ComponentRef[key('tlog-search', @Id)]" />
|
||||
<xsl:template match="wix:ComponentRef[key('log-search', @Id)]" />
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -1,13 +0,0 @@
|
|||
execute_process(COMMAND git rev-parse HEAD
|
||||
OUTPUT_VARIABLE VERSION_PATCH)
|
||||
|
||||
# remove leading and trailing spaces
|
||||
string(STRIP "${VERSION_PATCH}" VERSION_PATCH)
|
||||
|
||||
message("Checking time stamp ...")
|
||||
if(EXISTS ${TIME_STAMP_FILE})
|
||||
file (STRINGS ${TIME_STAMP_FILE} VERSION_IN_FILE)
|
||||
if(NOT "${VERSION_IN_FILE}" STREQUAL "${VERSION_PATCH}")
|
||||
file (REMOVE "${TIME_STAMP_FILE}")
|
||||
endif()
|
||||
endif()
|
|
@ -1,8 +0,0 @@
|
|||
execute_process(COMMAND git rev-parse HEAD
|
||||
OUTPUT_VARIABLE VERSION_PATCH)
|
||||
if (EXISTS ${TIME_STAMP_FILE})
|
||||
message("Keep the old time stamp")
|
||||
else()
|
||||
message("Creating time stamp ...")
|
||||
file(WRITE ${TIME_STAMP_FILE} "${VERSION_PATCH}")
|
||||
endif()
|
|
@ -1,21 +0,0 @@
|
|||
if (EXISTS ${TIME_STAMP_FILE})
|
||||
message("No need for daemon deployment")
|
||||
else()
|
||||
message("Daemon deploying ...")
|
||||
file(COPY "${DRING_PATH}/contrib/build/openssl/libcrypto-1_1-x64.dll"
|
||||
"${DRING_PATH}/contrib/build/openssl/libssl-1_1-x64.dll"
|
||||
"${PACKAGING_DIR}/wix/qt.conf"
|
||||
"${PROJECT_ROOT_DIR}/resources/images/jami.ico"
|
||||
"${PACKAGING_DIR}/wix/License.rtf"
|
||||
DESTINATION ${COPY_TO_PATH})
|
||||
# Cannot copy symbolic link using file COPY, create insread.
|
||||
file(GLOB_RECURSE RingTones "${DRING_PATH}/ringtones/*.ul"
|
||||
"${DRING_PATH}/ringtones/*.ogg"
|
||||
"${DRING_PATH}/ringtones/*.wav"
|
||||
"${DRING_PATH}/ringtones/*.opus")
|
||||
list(REMOVE_ITEM RingTones "${DRING_PATH}/ringtones/default.opus")
|
||||
file(COPY ${RingTones}
|
||||
DESTINATION ${COPY_TO_PATH}/ringtones)
|
||||
file(CREATE_LINK "${COPY_TO_PATH}/ringtones/01_AfroNigeria.opus"
|
||||
"${COPY_TO_PATH}/ringtones/default.opus")
|
||||
endif()
|
|
@ -1,14 +0,0 @@
|
|||
if (EXISTS ${TIME_STAMP_FILE})
|
||||
message("No need for Qt deployment in dir " ${QML_SRC_DIR})
|
||||
else()
|
||||
message("Qt deploying in dir " ${QML_SRC_DIR})
|
||||
execute_process(COMMAND "${WIN_DEPLOY_QT_PATH}/windeployqt.exe"
|
||||
--verbose 1
|
||||
--qmldir ${QML_SRC_DIR}
|
||||
--release ${EXE_NAME})
|
||||
if (DEFINED OFF_SCREEN_PLUGIN_REQUESTED)
|
||||
# for not showing window when testing
|
||||
file(COPY "${OFF_SCREEN_PLUGIN_PATH}/qoffscreen.dll"
|
||||
DESTINATION ${COPY_TO_PATH})
|
||||
endif()
|
||||
endif()
|
|
@ -41,6 +41,8 @@ import subprocess
|
|||
import platform
|
||||
import argparse
|
||||
import multiprocessing
|
||||
import shutil
|
||||
import time
|
||||
|
||||
|
||||
# Visual Studio helpers
|
||||
|
@ -93,43 +95,26 @@ def execute_cmd(cmd, with_shell=False, env_vars=None, cmd_dir=repo_root_dir):
|
|||
return proc.returncode
|
||||
|
||||
|
||||
def get_latest_vs_version():
|
||||
"""Find the latest visual c++ compiler tools version."""
|
||||
def get_vs_prop(prop):
|
||||
"""Get a visual studio property."""
|
||||
args = [
|
||||
"-latest",
|
||||
"-products *",
|
||||
"-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
||||
"-property installationVersion",
|
||||
"-property " + prop,
|
||||
]
|
||||
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 find_latest_vs_dir():
|
||||
"""Find the latest visual c++ compiler tools path."""
|
||||
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
|
||||
return None
|
||||
|
||||
|
||||
def find_ms_build():
|
||||
"""Find the latest msbuild executable."""
|
||||
filename = "MSBuild.exe"
|
||||
vs_path = find_latest_vs_dir()
|
||||
vs_path = get_vs_prop("installationPath")
|
||||
if vs_path is None:
|
||||
return
|
||||
for root, _, files in os.walk(os.path.join(vs_path, "MSBuild")):
|
||||
|
@ -169,7 +154,7 @@ def get_vs_env(arch="x64", _platform="", version=""):
|
|||
|
||||
def get_vs_env_cmd(arch="x64", _platform="", version=""):
|
||||
"""Get the vcvarsall.bat command."""
|
||||
vs_path = find_latest_vs_dir()
|
||||
vs_path = get_vs_prop("installationPath")
|
||||
if vs_path is None:
|
||||
return
|
||||
vc_env_init = [os.path.join(
|
||||
|
@ -286,6 +271,7 @@ def build(config_str, qt_dir, tests):
|
|||
cmake_options = [
|
||||
"-DWITH_DAEMON_SUBMODULE=ON",
|
||||
"-DCMAKE_PREFIX_PATH=" + qt_dir,
|
||||
"-DCMAKE_MSVCIDE_RUN_PATH=" + qt_dir + "\\bin",
|
||||
"-DCMAKE_INSTALL_PREFIX=" + daemon_bin_dir,
|
||||
"-DLIBJAMI_INCLUDE_DIR=" + daemon_dir + "\\src\\jami",
|
||||
"-DCMAKE_SYSTEM_VERSION=" + WIN_SDK_VERSION,
|
||||
|
@ -307,11 +293,73 @@ def build(config_str, qt_dir, tests):
|
|||
sys.exit(1)
|
||||
|
||||
|
||||
def deploy_runtimes(qt_dir):
|
||||
"""Deploy the dependencies to the runtime directory."""
|
||||
print("Deploying runtime dependencies")
|
||||
|
||||
runtime_dir = os.path.join(repo_root_dir, "x64", "Release")
|
||||
stamp_file = os.path.join(runtime_dir, ".deploy.stamp")
|
||||
if os.path.exists(stamp_file):
|
||||
return
|
||||
|
||||
daemon_dir = os.path.join(repo_root_dir, "daemon")
|
||||
ringtone_dir = os.path.join(daemon_dir, "ringtones")
|
||||
packaging_dir = os.path.join(repo_root_dir, "extras", "packaging")
|
||||
|
||||
def install_file(src, rel_path):
|
||||
shutil.copy(os.path.join(rel_path, src), runtime_dir)
|
||||
|
||||
print("Copying libjami dependencies")
|
||||
install_file("contrib/build/openssl/libcrypto-1_1-x64.dll", daemon_dir)
|
||||
install_file("contrib/build/openssl/libssl-1_1-x64.dll", daemon_dir)
|
||||
# Ringtone files (ul,ogg,wav,opus files in the daemon ringtone dir).
|
||||
|
||||
print("Copying ringtones")
|
||||
ringtone_dir = os.path.join(daemon_dir, "ringtones")
|
||||
ringtone_files = [f for f in os.listdir(ringtone_dir) if f.endswith(
|
||||
(".ul", ".ogg", ".wav", ".opus"))]
|
||||
ringtone_files = [os.path.join(ringtone_dir, f) for f in ringtone_files]
|
||||
default_ringtone = os.path.join(ringtone_dir, "default.opus")
|
||||
ringtone_files.remove(default_ringtone)
|
||||
ringtone_dir_out = os.path.join(runtime_dir, "ringtones")
|
||||
if os.path.exists(ringtone_dir_out):
|
||||
shutil.rmtree(ringtone_dir_out)
|
||||
os.makedirs(ringtone_dir_out, exist_ok=True)
|
||||
for ringtone in ringtone_files:
|
||||
shutil.copy(ringtone, os.path.join(runtime_dir, "ringtones"))
|
||||
# Create a hard link to the default ringtone (Windows).
|
||||
os.link(os.path.join(runtime_dir, "ringtones", "01_AfroNigeria.opus"),
|
||||
os.path.join(runtime_dir, "ringtones", "default.opus"))
|
||||
|
||||
print("Copying misc. client configuration files")
|
||||
install_file("wix/qt.conf", packaging_dir)
|
||||
install_file("wix/License.rtf", packaging_dir)
|
||||
install_file("resources/images/jami.ico", repo_root_dir)
|
||||
|
||||
# windeployqt
|
||||
print("Running windeployqt (this may take a while)...")
|
||||
win_deploy_qt = os.path.join(qt_dir, "bin", "windeployqt.exe")
|
||||
qml_src_dir = os.path.join(repo_root_dir, "src", "app")
|
||||
os.environ["VCINSTALLDIR"] = os.path.join(
|
||||
get_vs_prop("installationPath"), "VC")
|
||||
executable = os.path.join(runtime_dir, "Jami.exe")
|
||||
execute_cmd([win_deploy_qt, "--verbose", "1", "--no-compiler-runtime",
|
||||
"--qmldir", qml_src_dir, "--release", executable],
|
||||
False, cmd_dir=runtime_dir)
|
||||
|
||||
with open(stamp_file, "w", encoding="utf-8") as file:
|
||||
# Write the current time to the file.
|
||||
file.write(str(time.time()))
|
||||
|
||||
|
||||
def run_tests(config_str, qt_dir):
|
||||
"""Run tests."""
|
||||
print("Running client tests")
|
||||
|
||||
os.environ["PATH"] += os.pathsep + os.path.join(qt_dir, 'bin')
|
||||
daemon_dir = os.path.join(repo_root_dir, "daemon")
|
||||
os.environ["PATH"] += os.pathsep + \
|
||||
os.path.join(daemon_dir, "contrib", "build", "openssl")
|
||||
os.environ["QT_QPA_PLATFORM"] = "offscreen"
|
||||
os.environ["QT_QUICK_BACKEND"] = "software"
|
||||
os.environ['QT_QPA_FONTDIR'] = os.path.join(
|
||||
|
@ -319,6 +367,9 @@ def run_tests(config_str, qt_dir):
|
|||
os.environ['QT_PLUGIN_PATH'] = os.path.join(qt_dir, 'plugins')
|
||||
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.join(
|
||||
qt_dir, 'plugins', 'platforms')
|
||||
os.environ['QTWEBENGINEPROCESS_PATH'] = os.path.join(
|
||||
qt_dir, 'bin', 'QtWebEngineProcess.exe')
|
||||
os.environ["QML2_IMPORT_PATH"] = os.path.join(qt_dir, "qml")
|
||||
|
||||
tests_dir = os.path.join(build_dir, "tests")
|
||||
if execute_cmd(["ctest", "-V", "-C", config_str],
|
||||
|
@ -357,7 +408,7 @@ def generate_zip(version):
|
|||
app_output_dir = os.path.join(repo_root_dir, 'x64', 'Release')
|
||||
app_files = os.path.join(app_output_dir, '*')
|
||||
|
||||
# TODO: exclude Jami.PDB, .deploy.stamp, and vc_redist.x64.exe
|
||||
# TODO: exclude Jami.PDB, .deploy.stamp
|
||||
|
||||
artifacts_dir = os.path.join(build_dir, 'artifacts')
|
||||
if not os.path.exists(artifacts_dir):
|
||||
|
@ -404,7 +455,13 @@ def parse_args():
|
|||
parser.add_argument(
|
||||
"-i", "--init", action="store_true", help="Initialize submodules")
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
'-sd',
|
||||
'--skip-deploy',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Force skip deployment of runtime files needed for packaging')
|
||||
parser.add_argument(
|
||||
"-sb",
|
||||
"--skip-build",
|
||||
action="store_true",
|
||||
default=False,
|
||||
|
@ -426,7 +483,7 @@ def main():
|
|||
print("These scripts will only run on a 64-bit system for now.")
|
||||
sys.exit(1)
|
||||
if sys.platform == "win32":
|
||||
vs_version = get_latest_vs_version()
|
||||
vs_version = get_vs_prop("installationVersion").split(".")[0]
|
||||
if vs_version is None or int(vs_version) < 15:
|
||||
print("Visual Studio 2017 or later is required.")
|
||||
sys.exit(1)
|
||||
|
@ -454,19 +511,21 @@ def main():
|
|||
sys.exit(0)
|
||||
|
||||
config_str = ('Release', 'Beta')[parsed_args.beta]
|
||||
skip_build = parsed_args.skip_build
|
||||
|
||||
def do_build(do_tests):
|
||||
if not parsed_args.skip_build:
|
||||
build(config_str, parsed_args.qt, do_tests)
|
||||
if not parsed_args.skip_deploy:
|
||||
deploy_runtimes(parsed_args.qt)
|
||||
|
||||
if parsed_args.subcommand == "pack":
|
||||
if not skip_build:
|
||||
build(config_str, parsed_args.qt, False)
|
||||
elif parsed_args.msi:
|
||||
do_build(False)
|
||||
if parsed_args.msi:
|
||||
generate_msi(get_version())
|
||||
elif parsed_args.zip:
|
||||
generate_zip(get_version())
|
||||
else:
|
||||
if not skip_build:
|
||||
build(config_str, parsed_args.qt,
|
||||
parsed_args.tests)
|
||||
do_build(parsed_args.tests)
|
||||
if parsed_args.tests:
|
||||
run_tests(config_str, parsed_args.qt)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue