1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2024-10-28 00:39:36 +01: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:
Andreas Traczyk 2023-04-13 14:55:39 -04:00
parent a56ee62dcf
commit 66e0e21482
7 changed files with 92 additions and 151 deletions

View file

@ -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)

View file

@ -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>

View file

@ -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()

View file

@ -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()

View file

@ -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()

View file

@ -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()

View file

@ -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)