From 301e903e529847e1e3ad1e06b18b5e8953d56921 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Tue, 10 Dec 2024 16:10:55 +0200 Subject: [PATCH] Build windows Arm64 binaries IB-6662, IB-8805 Signed-off-by: Raul Metsma --- .github/workflows/build.yml | 33 ++++++------- client/Application.cpp | 4 +- client/CMakeLists.txt | 30 ++++++------ client/TSLDownload.cpp | 79 -------------------------------- client/download_tsl.py | 72 +++++++++++++++++++++++++++++ client/translations/en.ts | 11 +++++ client/translations/et.ts | 11 +++++ client/translations/ru.ts | 11 +++++ common | 2 +- prepare_osx_build_environment.sh | 8 ++-- qdigidoc4.wxs | 14 +++--- vcpkg.json | 13 +++++- 12 files changed, 160 insertions(+), 128 deletions(-) delete mode 100644 client/TSLDownload.cpp create mode 100644 client/download_tsl.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 54545187b..e46a83b58 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,13 +42,14 @@ jobs: key: vcpkg-macOS-${{ hashFiles('prepare_osx_build_environment.sh') }} - name: Build libraries run: | - mkdir -p ${LIBS_PATH}/Qt-6.10.1-OpenSSL + mkdir -p ${LIBS_PATH}/Qt-6.10.2-OpenSSL ./prepare_osx_build_environment.sh -p ${LIBS_PATH} - name: Install Qt uses: jurplel/install-qt-action@v4 with: - version: 6.10.1 + version: 6.10.2 arch: clang_64 + cache: true - name: Build run: | cmake "-GNinja" -B build -S . -DCMAKE_BUILD_TYPE=RelWithDebInfo \ @@ -140,10 +141,11 @@ jobs: path: build/qdigidoc4*.rpm windows: name: Build on Windows - runs-on: windows-2025 + runs-on: ${{ matrix.platform == 'arm64' && 'windows-11-arm' || 'windows-2025' }} strategy: matrix: vcver: [143] + platform: [x64, arm64] env: VER_SUFFIX: .VS${{ matrix.vcver }} steps: @@ -153,7 +155,7 @@ jobs: with: workflow: build.yml branch: master - name: msi_${{ matrix.vcver }}_x64 + name: msi_${{ matrix.vcver }}_${{ matrix.platform }} path: ./ repo: open-eid/libdigidocpp - name: Install artifact @@ -164,39 +166,34 @@ jobs: uses: actions/cache@v5 with: path: ${{ github.workspace }}/vcpkg_cache - key: vcpkg-${{ matrix.vcver }}-${{ hashFiles('vcpkg.json') }} - - name: Prepare vcpkg - uses: lukka/run-vcpkg@v11 - with: - vcpkgJsonGlob: ./vcpkg.json - runVcpkgInstall: true - env: - VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg_cache,readwrite - VCPKG_INSTALLED_DIR: ${{ github.workspace }}/build/vcpkg_installed + key: vcpkg-${{ matrix.vcver }}-${{ matrix.platform }}-${{ hashFiles('vcpkg.json') }} - name: Install Qt uses: jurplel/install-qt-action@v4 with: - version: 6.10.1 - arch: win64_msvc2022_64 + version: 6.10.2 + arch: ${{ matrix.platform == 'arm64' && 'win64_msvc2022_arm64' || 'win64_msvc2022_64' }} + cache: true - name: Setup dev env uses: ilammy/msvc-dev-cmd@v1 with: - arch: x64 + arch: ${{ matrix.platform }} - name: Install WiX run: | dotnet tool install -g wix --version 6.0.2 wix extension -g add WixToolset.UI.wixext/6.0.2 - name: Build + env: + VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg_cache,readwrite run: | cmake "-GNinja" -B build -S . -DCMAKE_BUILD_TYPE=RelWithDebInfo ` - -DCMAKE_TOOLCHAIN_FILE=${{ env.RUNVCPKG_VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake + -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake cmake --build build --target msi cmake --build build --target msishellext cmake --build build --target appx - name: Archive artifacts uses: actions/upload-artifact@v6 with: - name: msi_${{ matrix.vcver }}_x64 + name: msi_${{ matrix.vcver }}_${{ matrix.platform }} path: | build/*.msi build/*.appx diff --git a/client/Application.cpp b/client/Application.cpp index 11d5e443c..553f2dd74 100644 --- a/client/Application.cpp +++ b/client/Application.cpp @@ -294,7 +294,7 @@ class Application::Private std::unique_ptr bar; QSigner *signer {}; - QTranslator appTranslator, commonTranslator, qtTranslator; + QTranslator appTranslator, qtTranslator; QString lang; QTimer lastWindowTimer; volatile bool ready = false; @@ -418,7 +418,6 @@ Application::Application( int &argc, char **argv ) }); installTranslator( &d->appTranslator ); - installTranslator( &d->commonTranslator ); installTranslator( &d->qtTranslator ); loadTranslation(Settings::LANGUAGE); @@ -671,7 +670,6 @@ void Application::loadTranslation( const QString &lang ) else QLocale::setDefault(QLocale(QLocale::Estonian, QLocale::Estonia)); void(d->appTranslator.load(QLatin1String(":/translations/%1.qm").arg(lang))); - void(d->commonTranslator.load(QLatin1String(":/translations/common_%1.qm").arg(lang))); void(d->qtTranslator.load(QLatin1String(":/translations/qtbase_%1.qm").arg(lang))); if( d->closeAction ) d->closeAction->setText( tr("Close Window") ); if( d->newClientAction ) d->newClientAction->setText( tr("New Window") ); diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 22cf438cd..2f4722a77 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -1,5 +1,3 @@ -get_target_property(qtCore_install_prefix Qt6::qmake IMPORTED_LOCATION) -get_filename_component(qtCore_install_prefix ${qtCore_install_prefix} DIRECTORY) get_filename_component(TSL_FILENAME ${TSL_URL} NAME_WLE) set(TSL_LIST ${TSL_FILENAME} ${TSL_INCLUDE}) list(TRANSFORM TSL_LIST APPEND .xml) @@ -9,14 +7,11 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${TSL_FILENAME}.xml) else() set(TSL_DIR ${CMAKE_CURRENT_BINARY_DIR}) list(TRANSFORM TSL_LIST PREPEND ${TSL_DIR}/) - add_executable(TSLDownload TSLDownload.cpp) - target_link_libraries(TSLDownload Qt6::Network) - set_target_properties(TSLDownload PROPERTIES AUTOMOC OFF) + find_package(Python REQUIRED) add_custom_command( OUTPUT ${TSL_LIST} - DEPENDS TSLDownload - COMMAND $ ${CMAKE_CURRENT_BINARY_DIR} ${TSL_URL} ${TSL_INCLUDE} - WORKING_DIRECTORY ${qtCore_install_prefix} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/download_tsl.py + COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/download_tsl.py ${CMAKE_CURRENT_BINARY_DIR} ${TSL_URL} ${TSL_INCLUDE} ) endif() @@ -92,9 +87,6 @@ qt_add_translations(${PROJECT_NAME} TS_FILES translations/en.ts translations/et.ts translations/ru.ts - ../common/translations/common_en.ts - ../common/translations/common_et.ts - ../common/translations/common_ru.ts ../common/translations/qtbase_et.ts ../common/translations/qtbase_ru.ts RESOURCE_PREFIX /translations @@ -242,10 +234,11 @@ elseif(WIN32) ${CMAKE_SOURCE_DIR}/common/WelcomeDlg.wxs ${CMAKE_SOURCE_DIR}/common/WixUI_Minimal.wxs ) + get_filename_component(QT_BASE_DIR "${Qt6_DIR}/../../.." ABSOLUTE) add_custom_target(msi DEPENDS ${PROJECT_NAME} COMMAND ${WIX_CMD} -o "${MSI_FILE}.msi" #Build MSI with QT - COMMAND ${WIX_CMD} -d qt_path=${qtCore_install_prefix} -o "${MSI_FILE}.qt.msi" + COMMAND ${WIX_CMD} -d qt_path=${QT_BASE_DIR}/bin -o "${MSI_FILE}.qt.msi" WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) if(SIGNCERT) @@ -262,11 +255,16 @@ elseif(WIN32) endif() set(PLATFORM $ENV{PLATFORM}) configure_file(${CMAKE_SOURCE_DIR}/AppxManifest.xml.cmake ${CMAKE_BINARY_DIR}/AppxManifest.xml) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(OPENSSL_SUFFIX "-x64") - else() + if(PLATFORM STREQUAL "x86") set(OPENSSL_SUFFIX "") + else() + set(OPENSSL_SUFFIX "-${PLATFORM}") endif() + set(QT_PATHS ${QT_BASE_DIR}/bin/qtpaths.exe) + if(EXISTS ${QT_BASE_DIR}/bin/host-qtpaths.bat) + set(QT_PATHS ${QT_BASE_DIR}/bin/host-qtpaths.bat) + endif() + add_custom_target(appx DEPENDS ${PROJECT_NAME} COMMAND ${CMAKE_COMMAND} -E remove ${MSI_FILE}.appx COMMAND ${CMAKE_COMMAND} -E remove_directory appx @@ -284,7 +282,7 @@ elseif(WIN32) COMMAND ${CMAKE_COMMAND} -E copy ${LIBS_PATH}/digidocpp.conf appx COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Assets appx/Assets COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBS_PATH}/schema appx/schema - COMMAND Qt::windeployqt --no-translations --no-compiler-runtime --no-patchqt --force-openssl + COMMAND Qt::windeployqt --no-translations --no-compiler-runtime --no-patchqt --force-openssl --qtpaths ${QT_PATHS} --skip-plugin-types generic,networkinformation,iconengines --exclude-plugins qjpeg,qico,qgif,qcertonlybackend,qschannelbackend appx COMMAND ${CMAKE_COMMAND} -E copy ${LIBS_PATH}/digidoc-tool.exe appx COMMAND makeappx.exe pack -d appx -p ${MSI_FILE}.appx diff --git a/client/TSLDownload.cpp b/client/TSLDownload.cpp deleted file mode 100644 index cc966a19d..000000000 --- a/client/TSLDownload.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * QDigiDoc4 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -int main(int argc, char *argv[]) -{ - QCoreApplication a(argc, argv); - QStringList territories = QCoreApplication::arguments(); - territories.removeFirst(); - QString path = territories.takeFirst(); - QString url = territories.takeFirst(); - - QNetworkAccessManager m; - QObject::connect(&m, &QNetworkAccessManager::sslErrors, &m, [](QNetworkReply *r, const QList &errors){ - r->ignoreSslErrors(errors); - }); - - QNetworkReply *r = m.get(QNetworkRequest(QUrl(url))); - QObject::connect(r, &QNetworkReply::finished, r, [&] { - QFile f(path + "/" + r->request().url().fileName()); - if(f.open(QFile::ReadWrite)) - f.write(r->readAll()); - - f.seek(0); - QXmlStreamReader xml( &f ); - QString url, territory; - while(xml.readNext() != QXmlStreamReader::Invalid) - { - if(!xml.isStartElement()) - continue; - if(xml.name() == QLatin1String("TSLLocation")) - url = xml.readElementText(); - else if( xml.name() == QLatin1String("SchemeTerritory")) - territory = xml.readElementText(); - else if(xml.name() == QLatin1String("MimeType") && - xml.readElementText() == QLatin1String("application/vnd.etsi.tsl+xml") && - territories.contains(territory)) - { - QNetworkReply *rt = m.get(QNetworkRequest(QUrl(url))); - QEventLoop e; - QObject::connect(rt, &QNetworkReply::finished, rt, [&](){ - QFile t(QStringLiteral("%1/%2.xml").arg(path, territory)); - if(t.open(QFile::WriteOnly)) - t.write(rt->readAll()); - e.quit(); - }); - e.exec(); - url.clear(); - territory.clear(); - } - } - - QCoreApplication::quit(); - }); - return QCoreApplication::exec(); -} diff --git a/client/download_tsl.py b/client/download_tsl.py new file mode 100644 index 000000000..0967fcb3e --- /dev/null +++ b/client/download_tsl.py @@ -0,0 +1,72 @@ +import sys +import shutil +import os +import xml.etree.ElementTree as ET +import urllib.request +import urllib.error +import urllib.parse +import time + +def download_tsl_file(url, output_path, filename): + output_file = os.path.join(output_path, filename) + print(f"Downloading TSL list from: {url}") + retries = 3 + for attempt in range(retries): + try: + with urllib.request.urlopen(url, timeout=60) as response, open(output_file, 'wb') as f: + shutil.copyfileobj(response, f) + print(f"Saved to: {output_file}") + return output_file + except (urllib.error.HTTPError, urllib.error.URLError) as e: + print(f"Attempt {attempt + 1}/{retries} failed: {e}") + if attempt + 1 < retries: + sleep_time = 10 * (attempt + 1) + print(f"Retrying in {sleep_time} seconds...") + time.sleep(sleep_time) + else: + print("All retry attempts failed.") + sys.exit(1) + except IOError as e: + print(f"Error saving TSL list {output_file}: {e}") + sys.exit(1) + +def download_tsl_files(output_path, list_url, territories): + master_list_filename = os.path.basename(urllib.parse.urlparse(list_url).path) + if not master_list_filename: + master_list_filename = "eu-lotl.xml" # Fallback filename + file = download_tsl_file(list_url, output_path, master_list_filename) + try: + root = ET.parse(file) + ns = {'tsl': "http://uri.etsi.org/02231/v2#"} + for pointer in root.findall('.//tsl:OtherTSLPointer', ns): + territory = pointer.find('.//tsl:SchemeTerritory', ns) + if territory is None or territory.text not in territories: + continue + + mime = pointer.find('.//tslx:MimeType', {'tslx': 'http://uri.etsi.org/02231/v2/additionaltypes#'}) + if mime is None or mime.text != 'application/vnd.etsi.tsl+xml': + continue + + location = pointer.find('.//tsl:TSLLocation', ns) + if location is not None: + download_tsl_file(location.text, output_path, f"{territory.text}.xml") + + except ET.ParseError as e: + print(f"Error parsing XML: {e}") + sys.exit(1) + +if __name__ == "__main__": + if len(sys.argv) < 4: + print("Usage: python download_tsl.py [territory2] ...") + sys.exit(1) + + output_path = sys.argv[1] + url = sys.argv[2] + territories_to_download = sys.argv[3:] + + if not os.path.isdir(output_path): + print(f"Error: Output path '{output_path}' is not a directory.") + sys.exit(1) + + download_tsl_files(output_path, url, territories_to_download) + print("TSL download process finished.") diff --git a/client/translations/en.ts b/client/translations/en.ts index 378db7eda..2f50459c4 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -459,6 +459,17 @@ Cannot connect to certificate status service! + + Configuration + + The configuration file located on the server cannot be validated. + The configuration file located on the server cannot be validated. + + + Your computer's configuration file is later than the server has. + Your computer's configuration file is later than the server has. + + ContainerPage diff --git a/client/translations/et.ts b/client/translations/et.ts index b192fa010..10d7d5548 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -459,6 +459,17 @@ Kehtivuskinnitusteenus ei ole kättesaadav! + + Configuration + + The configuration file located on the server cannot be validated. + Serveris olev konfiguratsioonifail ei valideeru. + + + Your computer's configuration file is later than the server has. + Sinu arvutis on uuem konfiguratsioonifail kui serveris. + + ContainerPage diff --git a/client/translations/ru.ts b/client/translations/ru.ts index 4354e1acf..cfe3bdede 100644 --- a/client/translations/ru.ts +++ b/client/translations/ru.ts @@ -459,6 +459,17 @@ Услуга подтверждения действительности не доступна! + + Configuration + + The configuration file located on the server cannot be validated. + Находящийся на сервере конфигурационный файл не валидируется. + + + Your computer's configuration file is later than the server has. + Находящийся на Вашем компьютере конфигурационный файл новее файла на сервере. + + ContainerPage diff --git a/common b/common index b81713523..38737af0b 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit b81713523221e73e1ce4d463a2cf5e460c74cb18 +Subproject commit 38737af0b4079474c54146c2a7bf3845c35a7f5b diff --git a/prepare_osx_build_environment.sh b/prepare_osx_build_environment.sh index c8134c5c4..b869639e4 100755 --- a/prepare_osx_build_environment.sh +++ b/prepare_osx_build_environment.sh @@ -4,9 +4,9 @@ set -e ######### Versions of libraries/frameworks to be compiled -QT_VER="6.10.1" -OPENSSL_VER="3.5.4" -OPENLDAP_VER="2.6.10" +QT_VER="6.10.2" +OPENSSL_VER="3.5.5" +OPENLDAP_VER="2.6.12" REBUILD=false BUILD_PATH=~/cmake_builds : ${MACOSX_DEPLOYMENT_TARGET:="13.0"} @@ -110,7 +110,7 @@ if [[ "$REBUILD" = true || ! -d ${QT_PATH} ]] ; then pushd ${PACKAGE} if [[ "${PACKAGE}" == *"qtbase"* ]] ; then ./configure -prefix ${QT_PATH} -opensource -sbom -appstore-compliant -confirm-license -openssl-linked \ - -no-securetransport -nomake tests -nomake examples -no-dbus -no-libjpeg -no-libpng -no-gif -- \ + -no-securetransport -nomake tests -nomake examples -no-dbus -no-libjpeg -no-gif -- \ -DOPENSSL_ROOT_DIR=${OPENSSL_PATH} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" else ${QT_PATH}/bin/qt-configure-module . diff --git a/qdigidoc4.wxs b/qdigidoc4.wxs index dff65dd29..b002f491f 100644 --- a/qdigidoc4.wxs +++ b/qdigidoc4.wxs @@ -1,7 +1,7 @@ - - - + + + @@ -18,7 +18,7 @@ - @@ -38,7 +38,7 @@ - + + + - + diff --git a/vcpkg.json b/vcpkg.json index 31a791405..ba81ebe9d 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,5 +1,16 @@ { "name": "qdigidoc4", "dependencies": ["openssl", "flatbuffers", "zlib"], - "builtin-baseline": "bc38a15b0bee8bc48a49ea267cc32fbb49aedfc4" + "builtin-baseline": "bc38a15b0bee8bc48a49ea267cc32fbb49aedfc4", + "vcpkg-configuration": { + "registries": [ + { + "kind": "git", + "repository": "https://github.com/open-eid/vcpkg-ports", + "reference": "vcpkg-registry", + "baseline": "316f4d642f489b7d23d97891ed73431e7394d749", + "packages": ["openssl"] + } + ] + } }