From e9cde187ccf15e328b153d359fccd450c9bb7c01 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 Signed-off-by: Raul Metsma --- .github/workflows/build.yml | 29 ++++++-------- client/Application.cpp | 4 +- client/CMakeLists.txt | 24 +++++------ client/TSLDownload.cpp | 79 ------------------------------------- client/download_tsl.py | 63 +++++++++++++++++++++++++++++ client/translations/en.ts | 11 ++++++ client/translations/et.ts | 11 ++++++ client/translations/ru.ts | 11 ++++++ common | 2 +- qdigidoc4.wxs | 12 +++--- 10 files changed, 127 insertions(+), 119 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 b897ec295..c03b4de5f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,6 +49,7 @@ jobs: with: version: 6.10.1 arch: clang_64 + cache: true - name: Build run: | cmake "-GNinja" -B build -S . -DCMAKE_BUILD_TYPE=RelWithDebInfo \ @@ -70,7 +71,7 @@ jobs: container: ubuntu:${{ matrix.container }} strategy: matrix: - container: ['22.04', '24.04', '25.04', '25.10'] + container: ['22.04', '24.04', '25.10'] arch: ['amd64', 'arm64'] env: DEBIAN_FRONTEND: noninteractive @@ -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@v4 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 + 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@v5 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 2aa6ca3c8..844c9e674 100644 --- a/client/Application.cpp +++ b/client/Application.cpp @@ -292,7 +292,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; @@ -411,7 +411,6 @@ Application::Application( int &argc, char **argv ) }); installTranslator( &d->appTranslator ); - installTranslator( &d->commonTranslator ); installTranslator( &d->qtTranslator ); loadTranslation(Settings::LANGUAGE); @@ -665,7 +664,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 25addf337..06dcc0ede 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() @@ -96,12 +91,10 @@ 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 + LUPDATE_OPTIONS -locations none ) qt_add_resources(${PROJECT_NAME} tsl BASE ${TSL_DIR} PREFIX /TSL FILES ${TSL_LIST}) @@ -241,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) @@ -261,10 +255,10 @@ 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() add_custom_target(appx DEPENDS ${PROJECT_NAME} COMMAND ${CMAKE_COMMAND} -E remove ${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..b89f9f36b --- /dev/null +++ b/client/download_tsl.py @@ -0,0 +1,63 @@ +import sys +import shutil +import os +import xml.etree.ElementTree as ET +import urllib.request +import urllib.error +import urllib.parse + +def download_tsl_file(url, output_path, filename): + output_file = os.path.join(output_path, filename) + print(f"Downloading TSL list from: {url}") + try: + with urllib.request.urlopen(url) 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"Error downloading TSL list: {e}") + 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 7a49523c8..553969c6c 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -443,6 +443,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 597314778..477e82b8f 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -443,6 +443,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 280c7ef25..e3e9ebfd6 100644 --- a/client/translations/ru.ts +++ b/client/translations/ru.ts @@ -443,6 +443,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..1c7d527b5 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit b81713523221e73e1ce4d463a2cf5e460c74cb18 +Subproject commit 1c7d527b5af584b5db4f29dbfc53b3463acb9c4d diff --git a/qdigidoc4.wxs b/qdigidoc4.wxs index dff65dd29..eae58dcc8 100644 --- a/qdigidoc4.wxs +++ b/qdigidoc4.wxs @@ -1,7 +1,7 @@ - - - + + + @@ -18,7 +18,7 @@ - @@ -92,9 +92,11 @@ + + - +