diff --git a/.gitea/workflows/build_and_test.yml b/.gitea/workflows/build_and_test.yml index 4ea46681c..69a7fc7be 100644 --- a/.gitea/workflows/build_and_test.yml +++ b/.gitea/workflows/build_and_test.yml @@ -151,8 +151,10 @@ jobs: python3 gitea_upload_file.py "$tgz" done + # One build packs the viewer installer and the rugnux .zip (CPackProjectConfig.cmake in + # CMakeLists.txt gives each generator its components). build-windows: - name: build:viewer:windows-x86_64:${{ matrix.variant }} + name: build:portable:windows-x86_64:${{ matrix.variant }} # Uploads to the release, so it waits for the job that creates it. needs: create-release runs-on: windows-11-cuda-qt @@ -192,22 +194,35 @@ jobs: run: | cd build\tests jfjoch_portable_test.exe "[portable]" - - name: Build installer (NSIS) + - name: Build installer (NSIS) and rugnux zip shell: cmd run: | for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VSPATH=%%i" call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat" cd build cpack - - name: Upload installer to release + - name: Verify the rugnux zip + shell: powershell + run: | + # rugnux.exe and, in the CUDA variant, the cuFFT DLL it needs - and no viewer. + $zip = Get-ChildItem -Path build -Filter 'rugnux-*-win64-*.zip' + if ($zip.Count -ne 1) { throw 'Expected one rugnux zip in build/' } + Add-Type -AssemblyName System.IO.Compression.FileSystem + $names = [System.IO.Compression.ZipFile]::OpenRead($zip[0].FullName).Entries | ForEach-Object { $_.FullName } + $names + if (-not ($names -match 'rugnux\.exe$')) { throw 'rugnux.exe missing from the zip' } + if ($names -match 'jfjoch_viewer') { throw 'the viewer is in the rugnux zip' } + if ('${{ matrix.use_cuda }}' -eq 'ON' -and -not ($names -match 'cufft64_.*\.dll$')) { throw 'cuFFT DLL missing from the CUDA zip' } + - name: Upload installer and rugnux zip to release if: github.event_name == 'workflow_dispatch' && (github.event.inputs.create_release == 'true' || github.event.inputs.create_release == true) shell: powershell env: TOKEN: ${{ secrets.PIP_REPOSITORY_API_TOKEN }} run: | - # NSIS installer named jfjoch-viewer--win64-{cuda|cpu}.exe (see CMakeLists.txt). - $files = Get-ChildItem -Path build -Filter 'jfjoch-viewer-*-win64-*.exe' - if ($files.Count -eq 0) { throw 'No Windows installer found in build/' } + # NSIS installer jfjoch-viewer--win64-{cuda|cpu}.exe and + # rugnux--win64-{cuda|cpu}.zip (see CMakeLists.txt). + $files = @(Get-ChildItem -Path build -Filter 'jfjoch-viewer-*-win64-*.exe') + @(Get-ChildItem -Path build -Filter 'rugnux-*-win64-*.zip') + if ($files.Count -ne 2) { throw 'Expected the installer and the rugnux zip in build/' } foreach ($file in $files) { python gitea_upload_file.py $file.FullName if ($LASTEXITCODE -ne 0) { throw "Upload failed for $($file.Name)" } @@ -412,64 +427,6 @@ jobs: python3 gitea_upload_file.py "$tgz" done - build-rugnux-windows: - name: build:rugnux:windows-x86_64:cuda - # Uploads to the release, so it waits for the job that creates it. - needs: create-release - runs-on: windows-11-cuda-qt - timeout-minutes: 120 - steps: - - uses: actions/checkout@v4 - # cmd, not bash: the Windows runner has no bash, and every cmake invocation needs the MSVC - # environment from vcvars64.bat first -- same shape as build-windows above. No Qt in - # CMAKE_PREFIX_PATH: JFJOCH_RUGNUX_ONLY is the portable subtree minus viewer/, and every - # library it needs is now fetched and built by the configure, so C:/deps is only a leftover. - - name: Configure rugnux build - shell: cmd - run: | - for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VSPATH=%%i" - call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat" - cmake -G Ninja -B build-rugnux -DJFJOCH_RUGNUX_ONLY=ON -DJFJOCH_USE_CUDA=ON -DCMAKE_BUILD_TYPE=Release ${{ env.MSVC_ARCH_CMAKE_FLAGS }} -DCMAKE_PREFIX_PATH="C:/deps" - - name: Build rugnux - shell: cmd - run: | - for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VSPATH=%%i" - call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat" - cmake --build build-rugnux - # The quick cross-platform checks (tests/PortableTest.cpp and the [portable] cases), before - # anything is packaged. CPU-only: the runner has no GPU. - - name: Build portable tests - shell: cmd - run: | - for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VSPATH=%%i" - call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat" - cmake --build build-rugnux --target jfjoch_portable_test - - name: Run portable tests - shell: cmd - run: | - cd build-rugnux\tests - jfjoch_portable_test.exe "[portable]" - - name: Build rugnux zip - shell: cmd - run: | - for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VSPATH=%%i" - call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat" - cd build-rugnux - cpack - - name: Upload rugnux zip to release - if: github.event_name == 'workflow_dispatch' && (github.event.inputs.create_release == 'true' || github.event.inputs.create_release == true) - shell: powershell - env: - TOKEN: ${{ secrets.PIP_REPOSITORY_API_TOKEN }} - run: | - # Zip named rugnux--win64-{cuda|cpu}.zip (see CMakeLists.txt). - $files = Get-ChildItem -Path build-rugnux -Filter 'rugnux-*-win64-*.zip' - if ($files.Count -eq 0) { throw 'No rugnux zip found in build-rugnux/' } - foreach ($file in $files) { - python gitea_upload_file.py $file.FullName - if ($LASTEXITCODE -ne 0) { throw "Upload failed for $($file.Name)" } - } - # ---- Jungfraujoch -------------------------------------------------------------------------------- unit-tests: name: Unit tests diff --git a/CMakeLists.txt b/CMakeLists.txt index c9a0f9884..1c35bc0c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,11 +61,12 @@ SET(JFJOCH_VIEWER_BUILD OFF CACHE BOOL "Compile Jungfraujoch viewer") # The portable products come out of two build modes; every artifact holds exactly one program: # # JFJOCH_VIEWER_ONLY jfjoch_viewer .tar.gz (Linux) / installer (Windows) / .dmg (macOS) -# and, on Linux and macOS, also rugnux and the XDS plugin, each a .tar.gz +# and also rugnux (.tar.gz; .zip on Windows) and, on Linux and macOS, +# the XDS plugin (.tar.gz) # JFJOCH_RUGNUX_ONLY rugnux .tar.gz (Linux, incl. cross-built aarch64) / .zip (Windows) # # The viewer build compiles everything rugnux needs anyway, so one build packs all three; the -# rugnux-only mode remains for where there is no Qt (the aarch64 cross build) and for Windows. +# rugnux-only mode remains for where there is no Qt (the aarch64 cross build). # # They used to be one package: the viewer tarball also carried rugnux and two CLI tools, which made # the download confusing (a GUI package containing a batch processor) and meant a rugnux user had to @@ -683,9 +684,8 @@ IF (WIN32 AND JFJOCH_CUDA_AVAILABLE AND JFJOCH_PORTABLE_ONLY AND NOT TARGET CUDA IF (NOT _cufft_dll) MESSAGE(FATAL_ERROR "cuFFT runtime DLL not found under ${CUDAToolkit_BIN_DIR}") ENDIF() - IF (JFJOCH_RUGNUX_ONLY) - INSTALL(FILES ${_cufft_dll} DESTINATION bin COMPONENT rugnux) - ELSE() + INSTALL(FILES ${_cufft_dll} DESTINATION bin COMPONENT rugnux) + IF (JFJOCH_VIEWER_ONLY) INSTALL(FILES ${_cufft_dll} DESTINATION bin COMPONENT viewer) ENDIF() ENDIF() @@ -701,7 +701,7 @@ SET(CPACK_PACKAGE_NAME "jfjoch") if (JFJOCH_RUGNUX_ONLY) set(CPACK_COMPONENTS_ALL rugnux) elseif (JFJOCH_VIEWER_ONLY AND WIN32) - set(CPACK_COMPONENTS_ALL viewer) + set(CPACK_COMPONENTS_ALL viewer rugnux) # there is no native XDS for Windows, so no plugin elseif (JFJOCH_VIEWER_ONLY) set(CPACK_COMPONENTS_ALL viewer rugnux xds_plugin) else() @@ -740,34 +740,41 @@ else() set(_jfjoch_tgz_variant "cpu") endif() set(CPACK_ARCHIVE_VIEWER_FILE_NAME "jfjoch_viewer-${JFJOCH_VERSION}-${_jfjoch_tgz_os}-${_jfjoch_tgz_variant}") -set(CPACK_ARCHIVE_RUGNUX_FILE_NAME "rugnux-${JFJOCH_VERSION}-${_jfjoch_tgz_os}-${CMAKE_SYSTEM_PROCESSOR}-${_jfjoch_tgz_variant}") +if (WIN32) + set(CPACK_ARCHIVE_RUGNUX_FILE_NAME "rugnux-${JFJOCH_VERSION}-win64-${_jfjoch_tgz_variant}") +else() + set(CPACK_ARCHIVE_RUGNUX_FILE_NAME "rugnux-${JFJOCH_VERSION}-${_jfjoch_tgz_os}-${CMAKE_SYSTEM_PROCESSOR}-${_jfjoch_tgz_variant}") +endif() set(CPACK_ARCHIVE_XDS_PLUGIN_FILE_NAME "jfjoch_xds_plugin-${JFJOCH_VERSION}-${_jfjoch_tgz_os}-${CMAKE_SYSTEM_PROCESSOR}") +# macOS and Windows pack the viewer as a .dmg / NSIS installer and the other programs of the same +# build (rugnux; on macOS also the XDS plugin) as archives, one each. CPack reads +# CPACK_PROJECT_CONFIG_FILE once per generator, which is where each generator gets its components. +file(WRITE ${CMAKE_BINARY_DIR}/CPackProjectConfig.cmake [=[ +if (CPACK_GENERATOR STREQUAL "TGZ" OR CPACK_GENERATOR STREQUAL "ZIP") + list(REMOVE_ITEM CPACK_COMPONENTS_ALL viewer) + set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) + set(CPACK_COMPONENTS_GROUPING IGNORE) +else() + set(CPACK_COMPONENTS_ALL viewer) +endif() +]=]) + # OS-aware packaging: DragNDrop (.dmg) on macOS, NSIS installer on Windows, DEB on Debian/Ubuntu, # RPM on RHEL/Rocky. macOS/Windows are checked first because the /etc/* probes below are Linux-only. if (APPLE AND NOT JFJOCH_RUGNUX_ONLY) # .dmg containing jfjoch_viewer.app (Qt runtime already deployed into the bundle). Named like the # Windows and Linux artifacts; CMAKE_SYSTEM_PROCESSOR is arm64 on Apple Silicon. - # rugnux and the XDS plugin come out of the same build as .tar.gz archives, one each. CPack - # reads CPACK_PROJECT_CONFIG_FILE once per generator, which is where each one gets its own - # components: the viewer alone in the .dmg, the two others in the archives. + # plus rugnux and the XDS plugin as .tar.gz, see CPackProjectConfig.cmake above set(CPACK_GENERATOR "DragNDrop;TGZ") + set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_BINARY_DIR}/CPackProjectConfig.cmake) set(CPACK_PACKAGE_FILE_NAME "jfjoch-viewer-${JFJOCH_VERSION}-macos-${CMAKE_SYSTEM_PROCESSOR}") set(CPACK_DMG_VOLUME_NAME "Jungfraujoch Viewer ${JFJOCH_VERSION}") - file(WRITE ${CMAKE_BINARY_DIR}/CPackProjectConfig.cmake [=[ -if (CPACK_GENERATOR STREQUAL "TGZ") - set(CPACK_COMPONENTS_ALL rugnux xds_plugin) - set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) - set(CPACK_COMPONENTS_GROUPING IGNORE) -else() - set(CPACK_COMPONENTS_ALL viewer) - set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) -endif() -]=]) - set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_BINARY_DIR}/CPackProjectConfig.cmake) elseif (WIN32 AND NOT JFJOCH_RUGNUX_ONLY) - # NSIS installer .exe (Qt runtime deployed next to the binary by windeployqt). - set(CPACK_GENERATOR "NSIS") + # NSIS installer .exe (Qt runtime deployed next to the binary by windeployqt), plus rugnux as + # a .zip, see CPackProjectConfig.cmake above. + set(CPACK_GENERATOR "NSIS;ZIP") + set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_BINARY_DIR}/CPackProjectConfig.cmake) # GPLv3 text shown as the click-through license page of the installer. set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") @@ -808,11 +815,7 @@ elseif (WIN32) set(CPACK_GENERATOR "ZIP") set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) - if (JFJOCH_CUDA_AVAILABLE) - set(CPACK_PACKAGE_FILE_NAME "rugnux-${JFJOCH_VERSION}-win64-cuda${CUDAToolkit_VERSION_MAJOR}") - else() - set(CPACK_PACKAGE_FILE_NAME "rugnux-${JFJOCH_VERSION}-win64-cpu") - endif() + set(CPACK_PACKAGE_FILE_NAME ${CPACK_ARCHIVE_RUGNUX_FILE_NAME}) elseif (JFJOCH_VIEWER_ONLY OR JFJOCH_RUGNUX_ONLY) # Linux portable products: self-contained .tar.gz archives (Qt is linked statically, so there is # nothing external to ship alongside a binary). Built on the oldest supported distro (RHEL 8) for diff --git a/docs/RELEASE_CONTENTS.md b/docs/RELEASE_CONTENTS.md index 46dc78211..215704274 100644 --- a/docs/RELEASE_CONTENTS.md +++ b/docs/RELEASE_CONTENTS.md @@ -19,7 +19,7 @@ result see [Deployment](DEPLOYMENT.md); for the package-repository URLs see | `jfjoch-viewer--macos-arm64.dmg` | Gitea release page | macOS disk image with `jfjoch_viewer.app` (Apple Silicon), the Qt runtime and the license notices inside the app | | `rugnux--linux-x86_64-cuda.tgz`, `...-linux-x86_64-cpu.tgz` | Gitea release page | Portable Linux [`rugnux`](RUGNUX.md), the offline analysis CLI, and the license notices. One executable | | `rugnux--linux-aarch64-cuda.tgz` | Gitea release page | The same, cross-built for 64-bit Arm — NVIDIA GH200 and DGX Spark | -| `rugnux--win64-cuda.zip` | Gitea release page | The same for Windows, plus the cuFFT DLL | +| `rugnux--win64-cuda.zip`, `...-win64-cpu.zip` | Gitea release page | The same for Windows, plus the cuFFT DLL in the CUDA variant | | `rugnux--macos-arm64-cpu.tgz` | Gitea release page | The same for macOS on Apple Silicon, CPU only | | `jfjoch-writer` `.rpm` / `.deb` | Gitea release page | The writer alone, for a file-writing machine without the rest of the stack | | `jfjoch_xds_plugin--linux-x86_64.tgz` | Gitea release page | XDS HDF5 read plugin (`lib/libjfjoch_xds_plugin.so.`, built on RHEL 8) and its license notices; see [Integration with MX software](SOFTWARE_INTEGRATION.md) |