Files
build_tools/scripts/package_desktop.py
2022-07-06 18:03:21 +03:00

333 lines
11 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from package_utils import *
from package_branding import *
def make():
if system == 'windows':
make_windows()
elif system == 'darwin':
make_macos()
elif system == 'linux':
if 'packages' in targets:
set_cwd(build_dir)
log("Clean")
cmd("make", ["clean"])
log("Build packages")
cmd("make", ["packages"])
else:
exit(1)
return
#
# Windows
#
def make_windows():
global package_version, sign, machine, arch, xp, iscc_args, source_dir, \
innosetup_file, innosetup_update_file, advinst_file, portable_zip_file
set_cwd(get_abspath(git_dir, build_dir))
if 'clean' in targets:
log("\n=== Clean\n")
delete_dir(get_path("data/vcredist"))
delete_dir("DesktopEditors-cache")
delete_files("*.exe")
delete_files("*.msi")
delete_files("*.aic")
delete_files("*.tmp")
delete_files("*.zip")
delete_files(get_path("update/*.exe"))
delete_files(get_path("update/*.xml"))
delete_files(get_path("update/*.html"))
package_version = version + '.' + build
sign = 'sign' in targets
for target in targets:
if not (target.startswith('innosetup') or target.startswith('advinst') or
target.startswith('portable')):
continue
machine = get_platform(target)['machine']
arch = get_platform(target)['arch']
xp = get_platform(target)['xp']
suffix = arch + ("_xp" if xp else "")
source_prefix = "win_" + machine + ("_xp" if xp else "")
source_dir = get_path("%s/%s/%s/%s" % (out_dir, source_prefix, company_name_l, product_name_s))
if target.startswith('innosetup'):
for year in vcredist_list:
download_vcredist(year)
innosetup_file = "%s_%s_%s.exe" % (package_name, package_version, suffix)
make_innosetup()
if 'winsparkle-update' in targets:
innosetup_update_file = get_path("update/editors_update_%s.exe" % suffix)
make_innosetup_update()
if 'winsparkle-files' in targets:
make_winsparkle_files()
if target.startswith('advinst'):
advinst_file = "%s_%s_%s.msi" % (package_name, package_version, suffix)
make_advinst()
if target.startswith('portable'):
portable_zip_file = "%s_%s_%s.zip" % (package_name, package_version, suffix)
make_win_portable()
return
def download_vcredist(year):
log("\n=== Download vcredist " + year + "\n")
vcredist = get_path("data/vcredist/vcredist_%s_%s.exe" % (year, arch))
log("--- " + vcredist)
if is_file(vcredist):
log("! file exist, skip")
return
create_dir(get_dirname(vcredist))
download_file(vcredist_links[year][machine], vcredist)
return
def make_innosetup():
log("\n=== Build innosetup project\n")
global iscc_args
iscc_args = [
"/Qp",
"/DsAppVersion=" + package_version,
"/DDEPLOY_PATH=" + source_dir,
"/D_ARCH=" + machine
]
if onlyoffice:
iscc_args.append("/D_ONLYOFFICE=1")
else:
iscc_args.append("/DsBrandingFolder=" + get_abspath(git_dir, branding_dir))
if xp:
iscc_args.append("/D_WIN_XP=1")
if sign:
iscc_args.append("/DENABLE_SIGNING=1")
iscc_args.append("/Sbyparam=signtool.exe sign /v /n $q" + cert_name + "$q /t " + tsa_server + " $f")
log("--- " + innosetup_file)
if is_file(innosetup_file):
log("! file exist, skip")
return
cmd("iscc", iscc_args + ["common.iss"])
return
def make_innosetup_update():
log("\n=== Build innosetup update project\n")
log("--- " + innosetup_update_file)
if is_file(innosetup_update_file):
log("! file exist, skip")
return
cmd("iscc", iscc_args + ["/DTARGET_NAME=" + innosetup_file, "update_common.iss"])
return
def make_winsparkle_files():
log("\n=== Build winsparkle files\n")
awk_branding = "update/branding.awk"
if not onlyoffice:
build_branding_dir = get_abspath(git_dir, branding_dir, "win-linux/package/windows")
else:
build_branding_dir = get_path(".")
awk_args = [
"-v", "Version=" + version,
"-v", "Build=" + build,
"-v", "Timestamp=" + timestamp,
"-i", get_path(build_branding_dir, awk_branding)
]
appcast = get_path("update/appcast.xml")
log("--- " + appcast)
if is_file(appcast):
log("! file exist, skip")
else:
command = "env LANG=en_US.UTF-8 awk " + \
' '.join(awk_args) + " -f update/appcast.xml.awk"
appcast_result = proc_open(command)
if appcast_result['stderr'] != "":
log("! error: " + appcast_result['stderr'])
write_file(appcast, appcast_result['stdout'])
appcast_prod = get_path("update/appcast-prod.xml")
log("--- " + appcast_prod)
if is_file(appcast_prod):
log("! file exist, skip")
else:
command = "env LANG=en_US.UTF-8 awk -v Prod=1 " + \
' '.join(awk_args) + " -f update/appcast.xml.awk"
appcast_result = proc_open(command)
if appcast_result['stderr'] != "":
log("! error: " + appcast_result['stderr'])
write_file(appcast_prod, appcast_result['stdout'])
changes_dir = get_path(build_branding_dir, "update/changes", version)
for lang, base in update_changes_list.items():
changes = get_path("update/" + base + ".html")
if lang == 'en': encoding = 'en_US.UTF-8'
elif lang == 'ru': encoding = 'ru_RU.UTF-8'
log("--- " + changes)
if is_file(changes):
log("! file exist, skip")
else:
command = "env LANG=" + encoding + " awk " + ' '.join(awk_args) + \
" -f update\\changes.html.awk " + changes_dir + "\\" + lang + ".html"
changes_result = proc_open(command)
if changes_result['stderr'] != "":
log("! error: " + changes_result['stderr'])
write_file(changes, changes_result['stdout'])
return
def make_advinst():
log("\n=== Build advanced installer project\n")
log("--- " + advinst_file)
if is_file(advinst_file):
log("! file exist, skip")
return
aic_content = [";aic"]
if not onlyoffice:
copy_dir_content(
get_abspath(git_dir, branding_dir, "win-linux/package/windows/data"),
"data", ".bmp")
copy_dir_content(
get_abspath(git_dir, branding_dir, "win-linux/package/windows/data"),
"data", ".png")
aic_content += [
"SetProperty ProductName=\"%s\"" % product_name_full,
"SetProperty Manufacturer=\"%s\"" % publisher_name.replace('"', '""'),
"SetProperty ARPURLINFOABOUT=\"%s\"" % info_about_url,
"SetProperty ARPURLUPDATEINFO=\"%s\"" % update_info_url,
"SetProperty ARPHELPLINK=\"%s\"" % help_url,
"SetProperty ARPHELPTELEPHONE=\"%s\"" % help_phone,
"SetProperty ARPCONTACT=\"%s\"" % publisher_address,
"DelLanguage 1029 -buildname DefaultBuild",
"DelLanguage 1031 -buildname DefaultBuild",
"DelLanguage 1041 -buildname DefaultBuild",
"DelLanguage 1046 -buildname DefaultBuild",
"DelLanguage 2070 -buildname DefaultBuild",
"DelLanguage 1060 -buildname DefaultBuild",
"DelLanguage 1036 -buildname DefaultBuild",
"DelLanguage 3082 -buildname DefaultBuild",
"DelLanguage 1033 -buildname DefaultBuild"
]
if not sign: aic_content.append("ResetSig")
if machine == '32': aic_content.append("SetPackageType x86")
aic_content += [
"AddOsLc -buildname DefaultBuild -arch " + arch,
"NewSync APPDIR " + source_dir + " -existingfiles delete",
"UpdateFile APPDIR\\DesktopEditors.exe " + get_path(source_dir, "DesktopEditors.exe"),
"SetVersion " + package_version,
"SetPackageName " + advinst_file + " -buildname DefaultBuild",
"Rebuild -buildslist DefaultBuild"
]
write_file("DesktopEditors.aic", "\r\n".join(aic_content), 'utf-8-sig')
cmd("AdvancedInstaller.com",
["/execute", "DesktopEditors.aip", "DesktopEditors.aic", "-nofail"])
return
def make_win_portable():
log("\n=== Build portable\n")
log("--- " + portable_zip_file)
if is_file(portable_zip_file):
log("! file exist, skip")
return
cmd("7z", ["a", "-y", portable_zip_file, get_path(source_dir, "*")])
return
#
# macOS
#
def make_macos():
global suffix, lane, scheme
set_cwd(git_dir + "/" + branding_build_dir)
for target in targets:
if not target.startswith('diskimage'):
continue
if target.startswith('diskimage'):
if (target == 'diskimage-x86_64'): suffix = 'x86_64'
elif (target == 'diskimage-x86_64-v8'): suffix = 'v8'
elif (target == 'diskimage-arm64'): suffix = 'arm'
else: exit(1)
lane = "release_" + suffix
scheme = package_name + '-' + suffix
make_diskimage(target)
if ('sparkle-updates' in targets):
make_sparkle_updates()
return
def make_diskimage(target):
log("\n=== Build package " + scheme + "\n")
log("--- build/" + package_name + ".app")
cmd("bundler", ["exec", "fastlane", lane, "skip_git_bump:true"])
return
def make_sparkle_updates():
log("\n=== Build sparkle updates\n")
app_version = proc_open("/usr/libexec/PlistBuddy \
-c 'print :CFBundleShortVersionString' \
build/" + package_name + ".app/Contents/Info.plist")['stdout']
zip_filename = scheme + '-' + app_version
macos_zip = "build/" + zip_filename + ".zip"
updates_storage_dir = "%s/%s/_updates" % (get_env('ARCHIVES_DIR'), scheme)
create_dir(updates_dir)
copy_dir_content(updates_storage_dir, updates_dir, ".zip")
copy_dir_content(updates_storage_dir, updates_dir, ".html")
copy_file(macos_zip, updates_dir)
for lang, base in update_changes_list.items():
notes_src = "%s/%s/%s.html" % (changes_dir, app_version, base)
notes_dst = "%s/%s.html" % (updates_dir, zip_filename)
if lang == 'en':
encoding = 'en_US.UTF-8'
cur_date = sh_output("env LC_ALL=" + encoding + " date -u \"+%B %e, %Y\"", verbose=True)
elif lang == 'ru':
encoding = 'ru_RU.UTF-8'
cur_date = sh_output("env LC_ALL=" + encoding + " date -u \"+%e %B %Y\"", verbose=True)
if is_file(notes_src):
copy_file(notes_src, notes_dst)
replace_in_file(notes_dst,
r"(<span class=\"releasedate\">).+(</span>)",
"\\1 - " + cur_date + "\\2")
# else:
# write_file(notes_dst, "placeholder\n")
cmd(git_dir + "/" + build_dir + "/Vendor/Sparkle/bin/generate_appcast", [updates_dir])
log("\n=== Edit Sparkle appcast links\n")
appcast_url = sparkle_base_url + "/" + suffix
appcast = "%s/%s.xml" % (updates_dir, package_name.lower())
for lang, base in update_changes_list.items():
if base == "ReleaseNotes":
replace_in_file(appcast,
r"(<sparkle:releaseNotesLink>)(?:.+" + package_name + \
"-(?:x86|x86_64|v8|arm)-([0-9.]+)\..+)(</sparkle:releaseNotesLink>)",
"\\1" + appcast_url + "/updates/changes/\\2/" + base + ".html\\3")
else:
replace_in_file(appcast,
r"(<sparkle:releaseNotesLink xml:lang=\"" + lang + "\">)(?:" + package_name + \
"-(?:x86|x86_64|v8|arm)-([0-9.]+)\..+)(</sparkle:releaseNotesLink>)",
"\\1" + appcast_url + "/updates/changes/\\2/" + base + ".html\\3")
replace_in_file(appcast,
r"(url=\")(?:.+/)(" + package_name + ".+\")",
"\\1" + appcast_url + "/updates/\\2")
log("\n=== Delete unnecessary files\n")
for file in os.listdir(updates_dir):
if (-1 == file.find(app_version)) and (file.endswith(".zip") or
file.endswith(".html")):
delete_file(updates_dir + '/' + file)
return