diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9a96827cc60adef32218cc1c1411b83740f26583..6a5ecca0da8d0f534a10d935d07f878a02fa37ec 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -51,7 +51,7 @@ variables: - .\.venv\Scripts\Activate.ps1 - pip install --upgrade llbase autobuild certifi script: - - autobuild configure -c Release -- -DUSE_LTO=ON -DDISABLE_FATAL_WARNINGS=ON -DREVISION_FROM_VCS=FALSE + - autobuild configure -c Release -- -DUSE_LTO=ON -DDISABLE_FATAL_WARNINGS=ON -DREVISION_FROM_VCS=FALSE -DENABLE_DELTA_GEN=ON - autobuild build -c Release --no-configure - autobuild graph -c Release --graph-file alchemy-windows${AUTOBUILD_ADDRSIZE}-dependencies.svg build-vc-64/autobuild-package.xml - $AlchemyPdbPath = Resolve-Path build-vc-*/newview/Release/alchemy-bin.pdb @@ -71,7 +71,7 @@ variables: - build-vc-*/newview/Release/alchemy-bin.exe - build-vc-*/newview/Release/alchemy-bin.pdb - build-vc-*/newview/Release/alchemy-bin.src.zip - - build-vc-*/newview/Release/Alchemy_*_Setup.exe + - build-vc-*/newview/Deploy/* - alchemy-*-dependencies.svg .mac_build: @@ -396,7 +396,7 @@ build:release:windows64: - Pop-Location - Push-Location ./build-vc-64/ - - Push-Location ./newview/Release/ + - Push-Location ./newview/Deploy/ - $WinFileName = Get-ChildItem -Path . -Name -Include Alchemy_*_Setup.exe - $WinFileHash = (Get-FileHash .\$WinFileName -a sha256).Hash - $WinPackageUrl = "${UploadDestURL}/${WinFileName}" diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 1686547cc79c63761c5ba930af75fb1fd1db40b7..73edcfacc476a3814a05e929e06b3331eed9bef6 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -282,6 +282,8 @@ set(USESYSTEMLIBS OFF CACHE BOOL "Use libraries from your system rather than Lin set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.") +set(VIEWER_UPDATE_SERVICE "https://update.alchemyviewer.org" CACHE STRING "Update service URL") + source_group("CMake Rules" FILES CMakeLists.txt) endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8a1f230133864e7807434c0e88ff82f589a5dc88..a640c7ceead7d073bd44fd78890209acff4cc81e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2084,6 +2084,12 @@ if (WINDOWS) ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py ) + if (ENABLE_DELTA_GEN) + set(DELTA_GEN_SETTING "--gendelta=ON") + else () + set(DELTA_GEN_SETTING "") + endif () + add_custom_command( OUTPUT ${VIEWER_BUILD_DEST_DIR}/touched.bat COMMAND ${Python3_EXECUTABLE} @@ -2105,6 +2111,8 @@ if (WINDOWS) --source=${CMAKE_CURRENT_SOURCE_DIR} --touch=${VIEWER_BUILD_DEST_DIR}/touched.bat --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt + --updateurl=${VIEWER_UPDATE_SERVICE} + ${DELTA_GEN_SETTING} DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py diff --git a/indra/newview/alsquirrelupdater.cpp b/indra/newview/alsquirrelupdater.cpp index 73afe03fc746f78f17cd307c8a1ed8446443c6ad..c958d7c768b8cb694eb1af450c8771349f5cb276 100644 --- a/indra/newview/alsquirrelupdater.cpp +++ b/indra/newview/alsquirrelupdater.cpp @@ -27,6 +27,8 @@ #include "alsquirrelupdater.h" +#include "llviewerbuildconfig.h" + #include "llappviewer.h" #include "llnotificationsutil.h" #include "llversioninfo.h" @@ -39,6 +41,14 @@ #include "llwin32headerslean.h" #include "llstartup.h" +#if LL_WINDOWS +#define UPDATER_PLATFORM "windows" +#define UPDATER_ARCH "x64" +#elif LL_DARWIN +#define UPDATER_PLATFORM "macos" +#define UPDATER_ARCH "universal" +#endif + static std::string win32_errorcode_to_string(LONG errorMessageID) { if (errorMessageID == 0) @@ -121,7 +131,7 @@ struct ALRegWriter void ALUpdateUtils::updateSlurlRegistryKeys(const std::string& protocol, const std::string& name, const std::string& executable_path) { // SecondLife slurls - std::wstring reg_path = ll_convert_string_to_wide(llformat("Software\\Classes\\%s", protocol.c_str())); + std::wstring reg_path = ll_convert_string_to_wide(fmt::format("Software\\Classes\\{}", protocol)); if (auto regpath = ALRegWriter(HKEY_CURRENT_USER, reg_path)) { regpath.setValue(name); @@ -143,7 +153,7 @@ void ALUpdateUtils::updateSlurlRegistryKeys(const std::string& protocol, const s if (auto command = open.createSubKey(TEXT("command"))) { - std::string open_cmd_string = llformat("\"%s\" -url \"%s\"", executable_path.c_str(), "%1"); + std::string open_cmd_string = fmt::format("\"{}\" -url \"%1\"", executable_path); command.setValue(open_cmd_string, REG_EXPAND_SZ); } } @@ -154,8 +164,6 @@ void ALUpdateUtils::updateSlurlRegistryKeys(const std::string& protocol, const s // static bool ALUpdateUtils::handleCommandLineParse(LLControlGroupCLP& clp) { - if(!ALUpdateHandler::isSupported()) return true; - bool is_install = clp.hasOption("squirrel-install"); bool is_update = clp.hasOption("squirrel-updated"); bool is_uninstall = clp.hasOption("squirrel-uninstall"); @@ -232,9 +240,9 @@ bool ALUpdateUtils::handleCommandLineParse(LLControlGroupCLP& clp) } LLAppViewer::instance()->removeDumpDir(); LLAppViewer::instance()->removeMarkerFiles(); - return false; + return true; } - return true; + return false; } ALUpdateHandler::ALUpdateHandler() @@ -250,8 +258,7 @@ ALUpdateHandler::ALUpdateHandler() { std::string channel = LLVersionInfo::instance().getChannel(); channel.erase(std::remove_if(channel.begin(), channel.end(), isspace), channel.end()); - - mUpdateURL = llformat("http://update.alchemyviewer.net/windows%s/channel/%s/", std::to_string(ADDRESS_SIZE).c_str(), channel.c_str()); + mUpdateURL = fmt::format("{}/{}/{}/{}/", VIEWER_UPDATE_SERVICE, UPDATER_PLATFORM, UPDATER_ARCH, channel); } LL_INFOS() << "Update service url: " << mUpdateURL << LL_ENDL; @@ -468,8 +475,8 @@ void ALUpdateHandler::updateCheckFinished(const LLSD& data) else if (update_preference == 2) { LLSD args; - args["VIEWER_VER"] = llformat("%s %s", LLVersionInfo::instance().getChannel().c_str(), LLVersionInfo::instance().getShortVersion().c_str()); - args["VIEWER_UPDATES"] = llformat("%s", new_ver.version().c_str()); + args["VIEWER_VER"] = fmt::format("{} {}", LLVersionInfo::instance().getChannel(), LLVersionInfo::instance().getShortVersion()); + args["VIEWER_UPDATES"] = fmt::format("{}", new_ver.version()); LLSD payload; payload["user_update_action"] = LLSD(E_DOWNLOAD_INSTALL); LLNotificationsUtil::add("UpdateDownloadRequest", args, payload, boost::bind(&ALUpdateHandler::onUpdateNotification, this, _1, _2)); @@ -507,7 +514,7 @@ void ALUpdateHandler::updateDownloadFinished(const LLSD& data) } } LLSD args; - args["VIEWER_VER"] = llformat("%s %s", LLVersionInfo::instance().getChannel().c_str(), new_ver.version().c_str()); + args["VIEWER_VER"] = fmt::format("{} {}", LLVersionInfo::instance().getChannel(), new_ver.version()); args["VIEWER_UPDATES"] = releases; LLSD payload; payload["user_update_action"] = LLSD(E_DOWNLOADED); @@ -524,8 +531,8 @@ void ALUpdateHandler::updateInstallFinished(const LLSD& data) ALVersionInfo new_ver; if (mSavedUpdateInfo.has("futureVersion")) new_ver.parse(mSavedUpdateInfo["futureVersion"].asString()); LLSD args; - args["VIEWER_VER"] = llformat("%s %s", LLVersionInfo::instance().getChannel().c_str(), LLVersionInfo::instance().getShortVersion().c_str()); - args["VIEWER_UPDATES"] = llformat("%s", new_ver.version().c_str()); + args["VIEWER_VER"] = fmt::format("{} {}", LLVersionInfo::instance().getChannel(), LLVersionInfo::instance().getShortVersion()); + args["VIEWER_UPDATES"] = fmt::format("{}", new_ver.version()); LLSD payload; payload["user_update_action"] = LLSD(E_INSTALLED_RESTART); LLNotificationsUtil::add((LLStartUp::getStartupState() < STATE_STARTED ? "UpdateInstalledRestart" : "UpdateInstalledRestartToast"), args, payload, boost::bind(&ALUpdateHandler::onUpdateNotification, this, _1, _2)); diff --git a/indra/newview/installers/windows/placeholder.gif b/indra/newview/installers/windows/placeholder.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe374f1c6176cf7f82bd49741a2b6fb7721ac12d Binary files /dev/null and b/indra/newview/installers/windows/placeholder.gif differ diff --git a/indra/newview/installers/windows/viewer.nuspec b/indra/newview/installers/windows/viewer.nuspec index af8fb411ab8028f558f3da4cd2e3a23192ff099d..6325fd4a38deb6f9731d75cab66caccba0657b92 100644 --- a/indra/newview/installers/windows/viewer.nuspec +++ b/indra/newview/installers/windows/viewer.nuspec @@ -5,12 +5,12 @@ <version>${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}</version> <authors>Alchemy Development Group</authors> <owners>Alchemy Development Group</owners> - <title>${VIEWER_CHANNEL}</title> + <title>${VIEWER_CHANNEL}</title> <description>${VIEWER_CHANNEL}</description> <copyright>Copyright (C) 2013-2023 Alchemy Development Group</copyright> <projectUrl>https://www.alchemyviewer.org</projectUrl> </metadata> <files> - <file src="Release\**\*.*" target="lib\net45\" exclude="Release\**\*.pdb;Release\**\*.vshost.*;Release\**\*.nsi;Release\**\*.bat;Release\**\*_Setup.exe;Release\**\*-bin.exe"/> + <file src="Release\**\*.*" target="lib\net45\" exclude="Release\**\*.pdb;Release\**\*.vshost.*;Release\**\*.nsi;Release\**\*.bat;Release\**\*_Setup.exe;Release\**\*-bin.exe;Release\**\*.exp;Release\**\*.lib"/> </files> </package> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6f5fe3352cea4d73d7d9f9435e486a435890d9e5..3aa83d8c981d0179875b66028bf04d15bc7db006 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2560,7 +2560,7 @@ bool LLAppViewer::initConfiguration() } #if LL_WINDOWS - if (ALUpdateHandler::isSupported() && !ALUpdateUtils::handleCommandLineParse(clp)) + if (ALUpdateUtils::handleCommandLineParse(clp)) { return false; } diff --git a/indra/newview/llviewerbuildconfig.h.in b/indra/newview/llviewerbuildconfig.h.in index a408ccd56a508c8f3dcb7e3f4602a521caeeaefe..4e975df04b02a68b54fc18cd1252760f3f7099ed 100644 --- a/indra/newview/llviewerbuildconfig.h.in +++ b/indra/newview/llviewerbuildconfig.h.in @@ -42,6 +42,9 @@ #define LL_VIEWER_VERSION_MINOR @VIEWER_VERSION_MINOR@ #define LL_VIEWER_VERSION_PATCH @VIEWER_VERSION_PATCH@ +// Updater URL +#define VIEWER_UPDATE_SERVICE "@VIEWER_UPDATE_SERVICE@" + // Sentry #define SENTRY_DSN "@SENTRY_DSN@" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index d7b4f56e2b061b4f5db025541fca7952585c80bf..139b93d1c6220a06d20976fda2c24936f8c7960d 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -617,22 +617,46 @@ def package_finish(self): '-Properties', 'NoWarn=NU5128', os.path.join(self.args['build'], 'viewer.nuspec')]) + #Build installer and update delta squirrel_exe = os.path.join(self.args['build'], os.pardir, 'packages', 'squirrel', 'Squirrel.exe') + + # Download previous build for delta generation + temp_installdir = os.path.join(self.args['build'], 'Installer') + if 'gendelta' in self.args and 'updateurl' in self.args: + if (self.address_size == 64): + updater_arch = 'x64' + else: + updater_arch = 'x86' + + self.run_command( + [squirrel_exe, + 'http-down', + '--releaseDir', temp_installdir, + '--url', '{}/windows/{}/{}/'.format(self.args['updateurl'], updater_arch, self.app_name_oneword())]) + + # Build installer files + temp_nupkg = os.path.join(self.args['build'], '{}.{}.nupkg'.format(self.app_name_oneword(), '.'.join(self.args['version']))) self.run_command( [squirrel_exe, 'releasify', - '--releaseDir', os.path.join(self.args['build'], 'Releases'), + '--releaseDir', temp_installdir, '--framework', 'vcredist143-x64', '--icon', os.path.join(self.args['source'], 'installers', 'windows', 'install_icon.ico'), - '--splashImage', os.path.join(self.args['source'], 'installers', 'windows', 'splash.gif'), - '--package', os.path.join(self.args['build'], '{}.{}.nupkg'.format(self.app_name_oneword(), '.'.join(self.args['version'])))]) + '--splashImage', os.path.join(self.args['source'], 'installers', 'windows', 'placeholder.gif'), + '--package', temp_nupkg]) + # Copy to final installer destination installer_file = self.installer_base_name() + '_Setup.exe' + with self.prefix(src=temp_installdir, dst=os.path.join(self.args['build'], 'Deploy')): # everything goes in Contents + self.path(src=self.app_name_oneword() + 'Setup.exe', dst=installer_file) + self.path('{}-{}-*.nupkg'.format(self.app_name_oneword(), '.'.join(self.args['version']))) + self.path('RELEASES') - os.rename(os.path.join('Releases', self.app_name_oneword() + 'Setup.exe'), os.path.join('Release', installer_file)) + # Clean up temporary files + os.remove(temp_nupkg) + shutil.rmtree(temp_installdir, True) - self.sign(installer_file) - self.created_path(self.dst_path_of(installer_file)) + self.created_path(os.path.join(self.args['build'], 'Deploy', installer_file)) self.package_file = installer_file def sign(self, exe):