From c3b47abcc88379253d8bd0ea09efe277ecbcc69f Mon Sep 17 00:00:00 2001 From: vulcandth Date: Sun, 8 Mar 2026 21:14:34 -0500 Subject: [PATCH] Use CPack for Windows packaging --- .github/scripts/install_deps.sh | 3 +- .../workflows/create-release-artifacts.yml | 11 ++----- .github/workflows/testing.yml | 15 ++------- CMakeLists.txt | 22 ++++++++++++- cmake/deps.cmake | 2 ++ src/CMakeLists.txt | 32 ++++++++++++++++++- 6 files changed, 62 insertions(+), 23 deletions(-) diff --git a/.github/scripts/install_deps.sh b/.github/scripts/install_deps.sh index 0452eaa2..21cadca0 100755 --- a/.github/scripts/install_deps.sh +++ b/.github/scripts/install_deps.sh @@ -21,7 +21,8 @@ case "${1%-*}" in pkg install -y bash bison cmake git png ;; windows) - choco install -y winflexbison3 + # GitHub Actions' hosted runners ship CMake 3.x, but versions prior to 4.0.0 ignore `CPACK_PACKAGE_FILE_NAME`. + choco install -y winflexbison3 cmake # The below expects the base name, not the Windows-specific name. bison() { win_bison "$@"; } # An alias doesn't work, so we use a function instead. ;; diff --git a/.github/workflows/create-release-artifacts.yml b/.github/workflows/create-release-artifacts.yml index 3e19345f..6f16badf 100644 --- a/.github/workflows/create-release-artifacts.yml +++ b/.github/workflows/create-release-artifacts.yml @@ -24,11 +24,6 @@ jobs: strategy: matrix: bits: [32, 64] - include: - - bits: 32 - arch: x86 - - bits: 64 - arch: x86_x64 fail-fast: false steps: - name: Checkout repo @@ -42,14 +37,14 @@ jobs: cmake -S . -B build --preset msvc${{ matrix.bits }} -DFETCHCONTENT_BASE_DIR="${{ env.DEPS_ROOT_DIR }}" cmake --build build --config Release - name: Package binaries + working-directory: build run: | - cmake --install build --config Release --prefix install_dir --verbose - Compress-Archive -LiteralPath @("install_dir/bin/rgbasm.exe", "install_dir/bin/rgblink.exe", "install_dir/bin/rgbfix.exe", "install_dir/bin/rgbgfx.exe", "install_dir/bin/z.dll", "install_dir/bin/libpng16.dll") "rgbds-win${{ matrix.bits }}.zip" + cpack -DCPACK_PACKAGE_FILE_NAME=rgbds-win${{ matrix.bits }} -G ZIP -C Release --verbose - name: Upload Windows binaries uses: actions/upload-artifact@v7 with: name: win${{ matrix.bits }} - path: rgbds-win${{ matrix.bits }}.zip + path: build/rgbds-win${{ matrix.bits }}.zip if-no-files-found: error macos: diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 26f905e1..e3e17f7d 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -155,11 +155,6 @@ jobs: matrix: bits: [32, 64] os: [windows-2022, windows-2025] - include: - - bits: 32 - arch: x86 - - bits: 64 - arch: x86_x64 fail-fast: false runs-on: ${{ matrix.os }} steps: @@ -175,21 +170,19 @@ jobs: key: dep-srcs-${{ hashFiles('cmake/deps.cmake') }} enableCrossOsArchive: true # Currently only used on Windows, but the contents are OS-agnostic. - name: Build Windows binaries - shell: bash run: | # ASan seems to be broken on Windows, so we disable it. cmake -S . -B build --preset develop-msvc${{ matrix.bits }} -DFETCHCONTENT_BASE_DIR="${{ env.DEPS_ROOT_DIR }}" -DSANITIZERS=OFF cmake --build build - name: Package binaries + working-directory: build shell: bash run: | - cmake --install build --config Debug --prefix install_dir --verbose - mkdir bins - cp -v install_dir/bin/{rgb*.exe,*.dll} bins + cpack -DCPACK_PACKAGE_FILE_NAME=rgbds-win${{ matrix.bits }} -G ZIP -C Debug --verbose - name: Upload Windows binaries uses: actions/upload-artifact@v7 with: name: rgbds-canary-w${{ matrix.bits }}-${{ matrix.os }} - path: bins + path: build/rgbds-win${{ matrix.bits }}.zip if-no-files-found: error - name: Compute test dependency cache params id: test-deps-cache-params @@ -218,8 +211,6 @@ jobs: - name: Run tests shell: bash run: | - cp bins/* . - cp bins/*.dll test/gfx test/run-tests.sh --os ${{ matrix.os }} windows-mingw-build: diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e1b8080..bb5c01e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,5 +176,25 @@ set(man7 "man/gbz80.7" "man/rgbds.7") foreach(SECTION "man1" "man5" "man7") - install(FILES ${${SECTION}} DESTINATION "${CMAKE_INSTALL_MANDIR}/${SECTION}") + install(FILES ${${SECTION}} DESTINATION "${CMAKE_INSTALL_MANDIR}/${SECTION}" COMPONENT man) endforeach() + +## Packaging. + +# We only specify here the package-agnostic options; +# the rest is rather convention from our side, and thus more appropriate for presets or CLI flags. +## CPACK_PACKAGE_NAME: copied from `project()` +set(CPACK_PACKAGE_VENDOR "GBDev") +set(CPACK_PACKAGE_VERSION "${CMAKE_PROJECT_VERSION}") # The individual components are defined implicitly. +set(CPACK_PACKAGE_DESCRIPTION "An assembly toolchain for the Nintendo Game Boy and Game Boy Color") # Same as our repo's description. +## CPACK_PACKAGE_DESCRIPTION_SUMMARY: copied from `project()` +set(CPACK_PACKAGE_HOMEPAGE_URL "https://rgbds.gbdev.io") +## CPACK_PACKAGE_FILE_NAME: should be provided at runtime (`cpack -P`) +set(CPACK_PACKAGE_CHECKSUM SHA256) +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") +set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") +set(CPACK_STRIP_FILES ON) # Only applies to binary packages, not sources. +set(CPACK_VERBATIM_VARIABLES ON) +set(CPACK_THREADS 0) # Use all available CPU cores. +set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) +include(CPack) diff --git a/cmake/deps.cmake b/cmake/deps.cmake index c1ea12f8..c03daa25 100644 --- a/cmake/deps.cmake +++ b/cmake/deps.cmake @@ -5,6 +5,7 @@ FetchContent_Declare(PNG URL https://download.sourceforge.net/libpng/libpng-1.6.56.tar.xz URL_HASH SHA256=f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 + EXCLUDE_FROM_ALL # We only install the runtime dependencies, and do so separately. FIND_PACKAGE_ARGS 1.5.4) set(PNG_TESTS OFF CACHE INTERNAL "") # We do not care for these two (and they can even cause compile errors!) @@ -15,6 +16,7 @@ set(PNG_STATIC OFF CACHE INTERNAL "") FetchContent_Declare(ZLIB URL https://www.zlib.net/zlib-1.3.2.tar.xz URL_HASH SHA256=d7a0654783a4da529d1bb793b7ad9c3318020af77667bcae35f95d0e42a792f3 + EXCLUDE_FROM_ALL # We only install the runtime dependencies, and do so separately. # libpng documents requiring "zlib 1.0.4 or later (1.2.13 or later recommended for performance and security reasons)". # We thus enforce 1.0.4, but note that the libpng source code mentions that "it may work with versions as old as zlib 0.95". FIND_PACKAGE_ARGS 1.0.4) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ad7a0fe4..635b3d2e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -102,9 +102,39 @@ add_executable(rgbgfx $ "verbosity.cpp" ) -install(TARGETS rgbasm rgblink rgbfix rgbgfx RUNTIME) +install(TARGETS rgbasm rgblink rgbfix rgbgfx RUNTIME COMPONENT binaries) # Tests expect the binaries to end up in-source; this is more acceptable than the entire artifact dir. set_target_properties(rgbasm rgblink rgbfix rgbgfx PROPERTIES # The generator expression (even if a no-op) stops muti-config generators using a of "per-configuration subdirectory". RUNTIME_OUTPUT_DIRECTORY $<1:${CMAKE_SOURCE_DIR}>) target_link_libraries(rgbgfx PRIVATE PNG::PNG) + +# On Windows, you don't link against DLLs directly, but against an import library for that DLL. +# This leads to, sometimes, the DLL being stored in a directory far away from the import library itself! +set(DLL_SEARCH_DIRS CACHE PATH "List of directories in which DLLs will be searched") +cmake_path(CONVERT "${DLL_SEARCH_DIRS}" TO_CMAKE_PATH_LIST search_dirs NORMALIZE) +# TODO: we've only tested this with MinGW, but it may not work with other uses of the variable. +# Anyone who knows how to handle this better, feel free to submit a patch! +if(DEFINED CMAKE_FIND_ROOT_PATH) + list(APPEND search_dirs "${CMAKE_FIND_ROOT_PATH}/bin") +endif() +# Escape the search paths in a form that makes them suitable for splatting into the CMake install script. +list(TRANSFORM search_dirs REPLACE "([\\$\"])" "\\\\1") # Neutralize escapes and variable refs... +list(TRANSFORM search_dirs REPLACE "^(.+)\$" "\"\\1\"") # ...and quote each argument. +list(JOIN search_dirs " " search_dirs_splat) +# This is a modified version of the install code generated by +# `install(TARGETS rgbgfx RUNTIME_DEPENDENCIES)`. +# Unfortunately, that `install(TARGETS)` is outright not supported when cross-compiling, +# and working around that has CMake fail to resolve the DLL locations with MinGW, +# due to not specifying any `DIRECTORIES` and the system search path being ineffective. +install(CODE "\ +file(GET_RUNTIME_DEPENDENCIES + RESOLVED_DEPENDENCIES_VAR rgbgfx_deps + EXECUTABLES \"$\" + DIRECTORIES ${search_dirs_splat} \"$\" \"$\" + PRE_EXCLUDE_REGEXES \"^kernel32\\\\.dll$\" \"^msvcrt.?.?\\\\.dll\" \"^api-ms-win-.*\\\\.dll$\") + foreach(rgbgfx_dep IN LISTS rgbgfx_deps) + file(INSTALL DESTINATION \"$/${CMAKE_INSTALL_BINDIR}\" TYPE SHARED_LIBRARY FILES \${rgbgfx_dep} + FOLLOW_SYMLINK_CHAIN) + endforeach()" + COMPONENT shared-libs EXCLUDE_FROM_ALL) # Most platforms install those separately.