Skip to content

Replace platform-specific packaging scripts with CPack and add resource management helper#274

Closed
Copilot wants to merge 12 commits intomainfrom
copilot/replace-packaging-with-cpack
Closed

Replace platform-specific packaging scripts with CPack and add resource management helper#274
Copilot wants to merge 12 commits intomainfrom
copilot/replace-packaging-with-cpack

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Nov 21, 2025

The CMakeLists.txt had become cluttered with 80+ lines of platform-specific packaging code. Windows used InnoSetup with split CMake/ISS configuration, Linux generated bash scripts entirely in CMake, and adding files required modifications in multiple places.

Changes

CPack Configuration

  • Created CPack.cmake with unified packaging for all platforms
  • Windows: WiX MSI generator (NSIS fallback), includes code signing support
  • Linux: TGZ generator with preserved installer script, plus DEB/RPM support
  • macOS: No changes needed (resources already embedded via JUCE, DMG remains in CI)
  • Component-based installation filters out development files (lib/, include/)

Resource Management Function

  • Added set_target_resources() helper function to simplify resource handling
  • Single function call replaces platform-specific conditionals for adding resources
  • Supports three resource types: FILE, DIRECTORY, and PLUGIN
  • macOS: Copies resources to build directory and adds to bundle via juce_add_bundle_resources_directory()
  • Windows/Linux: Adds POST_BUILD commands to copy resources to target output directory
  • All platforms: Automatically generates corresponding install() commands for CPack
  • PLUGIN type: Automatically handles plugin targets and their .cat catalog files
  • Eliminates duplication between build-time copying and install rules

CMakeLists.txt

  • Replaced 80 lines of custom packaging with include(CPack.cmake)
  • Replaced 30+ lines of resource management with simple function calls
  • Removed platform-specific conditional blocks for package generation
  • Simplified translation script handling (no pre-copying needed)
  • Simplified plugin installation (single function call instead of manual commands)
  • Overall reduction of ~105 lines with improved maintainability

CI Workflow

  • Linux: cpack -G TGZ replaces custom bash script execution
  • Windows: cpack -C $config -G WIX replaces InnoSetup, output now .msi instead of .exe
  • Removed InnoSetup dependency, added WiX Toolset

Cleanup

  • Deleted BinaryData/Resource/windows-package.iss
  • Kept BinaryData/Resource/linux-install.sh (embedded in TGZ packages)

Usage

# Linux
cpack -G TGZ          # Self-contained archive with installer
cpack -G DEB          # Debian package
cpack -G RPM          # RPM package

# Windows
cpack -C Release -G WIX   # MSI installer
cpack -C Release -G NSIS  # NSIS installer (fallback)

Adding Resources

The new set_target_resources() function simplifies adding files to packages:

# Add files
set_target_resources(Partiels FILE "${SOURCE}/file.txt" DESTINATION Templates)

# Add directories
set_target_resources(Partiels DIRECTORY "${SOURCE}/Preset/" DESTINATION Preset)

# Add plugins (automatically handles plugin target and .cat file)
set_target_resources(Partiels PLUGIN partiels-vamp-plugins)

This single call handles bundle embedding (macOS), build directory copying (Windows/Linux), and CPack installation rules for all platforms.

Original prompt

This section details on the original issue you should resolve

<issue_title>Replace packaging and installation systems with CPack</issue_title>
<issue_description>Currently, Partiels uses

  • Windows: InnoSetup with a configuration file, and part of the configuration is managed in the CMakeLists.txt file
  • Linux: a bash installation script on Linux that is entirely generated in the CMakeLists.txt file
  • MacOS: a dmg that is generated on the CI (.github/workflows/ci.yml) which signs and notarises the Partiels.app application, generates the DMG, then signs and notarises the DMG

The CMakeLists.txt file has become cluttered, and embedding a new file with the application is complicated, must be done in multiple places, and is prone to errors. Furthermore, if dependency on InnoSetup on Windows could be avoided in favour of MSI, that would be preferable.

A CMake function based on CPack would be ideal. It could initially generate the installers for Windows and Linux, and embed the necessary folders and files in the app bundle on macOS (notarization and DMG can remain on the CI). If possible, a second version managing DMG will be considered at a later date.

</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 6 commits November 21, 2025 11:00
Co-authored-by: pierreguillot <1409918+pierreguillot@users.noreply.github.com>
Co-authored-by: pierreguillot <1409918+pierreguillot@users.noreply.github.com>
Co-authored-by: pierreguillot <1409918+pierreguillot@users.noreply.github.com>
Co-authored-by: pierreguillot <1409918+pierreguillot@users.noreply.github.com>
Co-authored-by: pierreguillot <1409918+pierreguillot@users.noreply.github.com>
Co-authored-by: pierreguillot <1409918+pierreguillot@users.noreply.github.com>
Copilot AI changed the title [WIP] Replace packaging and installation systems with CPack Replace platform-specific packaging scripts with CPack Nov 21, 2025
Copilot AI requested a review from pierreguillot November 21, 2025 11:10
@pierreguillot
Copy link
Copy Markdown
Contributor

@copilot Can you add a function that simplifies the systems that add resources to the bundle or build directory (lines 258 to 279 of CMakeLists.txt)? There could be a function set_target_resources, that would add the resource files to the target bundle and/or copy them to the target directory, and call the corresponding install() command to add them to the package.

Copilot AI and others added 2 commits November 21, 2025 11:35
Co-authored-by: pierreguillot <1409918+pierreguillot@users.noreply.github.com>
Co-authored-by: pierreguillot <1409918+pierreguillot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 21, 2025

@copilot Can you add a function that simplifies the systems that add resources to the bundle or build directory (lines 258 to 279 of CMakeLists.txt)? There could be a function set_target_resources, ...

Added set_target_resources() function in commit f41924c.

The function handles:

  • macOS: Copies resources to build dir and adds to bundle via juce_add_bundle_resources_directory()
  • Windows/Linux: Adds POST_BUILD commands to copy to output directory
  • All platforms: Automatically adds install() commands for CPack

Usage example:

set_target_resources(Partiels FILE "${SOURCE}/file.txt" DESTINATION Templates)
set_target_resources(Partiels DIRECTORY "${SOURCE}/Preset/" DESTINATION Preset)

This reduced CMakeLists.txt by ~15 lines and eliminates duplication between build and install rules.

Copilot AI changed the title Replace platform-specific packaging scripts with CPack Replace platform-specific packaging scripts with CPack and add resource management helper Nov 21, 2025
@pierreguillot
Copy link
Copy Markdown
Contributor

@copilot

The code can still be simplified with:

if(WIN32)
    set_target_resources(Partiels FILE ${PARTIELS_BINARYDATA_DIRECTORY}/Resource/generate-translation-file.ps1 DESTINATION Scripts)
else()
    set_target_resources(Partiels FILE ${PARTIELS_BINARYDATA_DIRECTORY}/Resource/generate-translation-file.sh DESTINATION Scripts)
endif()

and set_target_resources() could also manage the plugin type.

Co-authored-by: pierreguillot <1409918+pierreguillot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 21, 2025

@copilot

The code can still be simplified with:
...

Implemented in commit 458939e.

Changes:

  1. Translation scripts now use set_target_resources() directly (no pre-copying needed)
  2. Added PLUGIN resource type that handles plugin targets and their .cat files automatically

Example:

# Translation script (platform-specific)
if(WIN32)
    set_target_resources(Partiels FILE ${BINARY_DIR}/script.ps1 DESTINATION Scripts)
else()
    set_target_resources(Partiels FILE ${BINARY_DIR}/script.sh DESTINATION Scripts)
endif()

# Plugin
set_target_resources(Partiels PLUGIN partiels-vamp-plugins)

This reduced CMakeLists.txt by another 10+ lines and eliminated all manual plugin copying/installation code.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR successfully modernizes the packaging system by replacing 80+ lines of platform-specific CMake code with a unified CPack-based solution. The changes eliminate InnoSetup dependency on Windows in favor of WiX MSI generation, consolidate Linux packaging with proper TGZ/DEB/RPM support, and introduce a reusable set_target_resources() helper function that dramatically simplifies resource management across all platforms.

Key improvements:

  • Unified packaging configuration in CPack.cmake eliminates duplicate code and reduces maintenance burden
  • New set_target_resources() function provides single-point resource management for files, directories, and plugins
  • CI workflow updated to use cpack commands instead of custom scripts

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
CPack.cmake New unified packaging configuration supporting WiX/NSIS (Windows), TGZ/DEB/RPM (Linux), and DMG (macOS) with set_target_resources() helper function
CMakeLists.txt Simplified from ~105 lines to ~17 lines by replacing custom packaging logic with include(CPack.cmake) and function calls
BinaryData/Resource/windows-package.iss Removed InnoSetup configuration file (replaced by WiX/NSIS CPack generators)
.gitignore Added build_test directory exclusion
.github/workflows/ci.yml Updated CI to use cpack commands, replaced InnoSetup with WiX toolset, changed artifact from .exe to .msi

Comment thread CPack.cmake Outdated
Comment thread CPack.cmake
Comment on lines +110 to +116
install(DIRECTORY "${source_path}" DESTINATION ${dest_dir} COMPONENT Runtime)
endif()
elseif(UNIX AND NOT APPLE)
if(resource_type STREQUAL "FILE")
install(FILES "${source_path}" DESTINATION opt/Partiels/${dest_dir} COMPONENT Runtime)
elseif(resource_type STREQUAL "DIRECTORY")
install(DIRECTORY "${source_path}" DESTINATION opt/Partiels/${dest_dir} COMPONENT Runtime)
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The install(DIRECTORY ...) command behavior is inconsistent with expectations. When source_path has a trailing slash (e.g., "${PARTIELS_BINARYDATA_DIRECTORY}/Preset/"), CMake copies the contents of the directory, not the directory itself. Without a trailing slash, it copies the directory. This means:

  • Line 240 in CMakeLists.txt: DIRECTORY "${PARTIELS_BINARYDATA_DIRECTORY}/Preset/" will install contents directly to opt/Partiels/Preset/ (correct)
  • Line 241: DIRECTORY "${PARTIELS_BINARYDATA_DIRECTORY}/Translations/" will install contents directly to opt/Partiels/Translations/ (correct)

However, this creates ambiguity. Consider documenting this behavior or normalizing the paths to ensure consistent behavior. The same issue exists for Windows on line 110.

Suggested change
install(DIRECTORY "${source_path}" DESTINATION ${dest_dir} COMPONENT Runtime)
endif()
elseif(UNIX AND NOT APPLE)
if(resource_type STREQUAL "FILE")
install(FILES "${source_path}" DESTINATION opt/Partiels/${dest_dir} COMPONENT Runtime)
elseif(resource_type STREQUAL "DIRECTORY")
install(DIRECTORY "${source_path}" DESTINATION opt/Partiels/${dest_dir} COMPONENT Runtime)
# Normalize source_path to remove trailing slash for consistent install behavior
string(REGEX REPLACE "/$" "" normalized_source_path "${source_path}")
install(DIRECTORY "${normalized_source_path}" DESTINATION ${dest_dir} COMPONENT Runtime)
endif()
elseif(UNIX AND NOT APPLE)
if(resource_type STREQUAL "FILE")
install(FILES "${source_path}" DESTINATION opt/Partiels/${dest_dir} COMPONENT Runtime)
elseif(resource_type STREQUAL "DIRECTORY")
# Normalize source_path to remove trailing slash for consistent install behavior
string(REGEX REPLACE "/$" "" normalized_source_path "${source_path}")
install(DIRECTORY "${normalized_source_path}" DESTINATION opt/Partiels/${dest_dir} COMPONENT Runtime)

Copilot uses AI. Check for mistakes.
Comment thread CPack.cmake
Comment on lines +167 to +168
set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/icon_square.png")
set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/icon_square.png")
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NSIS requires icons in .ico format, not .png. The CPACK_NSIS_MUI_ICON and CPACK_NSIS_MUI_UNIICON settings with PNG files will cause errors. Convert icon_square.png to .ico format or use an existing .ico file.

Suggested change
set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/icon_square.png")
set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/icon_square.png")
set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/icon_square.ico")
set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/icon_square.ico")

Copilot uses AI. Check for mistakes.
Comment thread CPack.cmake
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_BINARY_DIR}/Install.txt")

# Only install runtime components, skip development files
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment "Only install runtime components, skip development files" is helpful, but it's unclear what development files are being filtered. Consider expanding the comment to clarify what this achieves:

# Only install runtime components, skip development files (lib/, include/, CMake config files)
# The fourth parameter filters by component name; "/" means install at the project root
Suggested change
# Only install runtime components, skip development files
# Only install runtime components in the package; skip development files such as libraries (lib/), headers (include/), and CMake config files.

Copilot uses AI. Check for mistakes.
Comment thread CPack.cmake
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/ChangeLog.txt" DESTINATION . COMPONENT Runtime)

# Code signing support (if enabled)
if(PARTIELS_NOTARIZE AND PARTIELS_CODESIGN_WINDOWS_KEYFILE)
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable PARTIELS_NOTARIZE is used in the condition but is never defined in the codebase. This will always evaluate to false, effectively disabling Windows code signing. Consider either:

  1. Adding set(PARTIELS_NOTARIZE OFF CACHE BOOL "Enable code signing/notarization") in CMakeLists.txt, or
  2. Simplifying the condition to just check if(PARTIELS_CODESIGN_WINDOWS_KEYFILE) if notarization support is not needed yet.
Suggested change
if(PARTIELS_NOTARIZE AND PARTIELS_CODESIGN_WINDOWS_KEYFILE)
if(PARTIELS_CODESIGN_WINDOWS_KEYFILE)

Copilot uses AI. Check for mistakes.
Comment thread CPack.cmake
Comment on lines +28 to +46
function(set_target_resources target resource_type source_path)
# Parse optional DESTINATION argument
set(options "")
set(oneValueArgs DESTINATION)
set(multiValueArgs "")
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

# Determine destination directory
if(ARG_DESTINATION)
set(dest_dir "${ARG_DESTINATION}")
else()
if(resource_type STREQUAL "PLUGIN")
set(dest_dir "PlugIns")
else()
get_filename_component(dest_dir "${source_path}" NAME)
# Remove trailing slash if present
string(REGEX REPLACE "/$" "" dest_dir "${dest_dir}")
endif()
endif()
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function lacks input validation. Consider adding checks for:

  • Valid resource_type values (FILE, DIRECTORY, PLUGIN)
  • Existence of source_path (for FILE and DIRECTORY types)
  • Valid target name (for PLUGIN type)

Example:

if(NOT resource_type MATCHES "^(FILE|DIRECTORY|PLUGIN)$")
    message(FATAL_ERROR "Invalid resource_type: ${resource_type}")
endif()
if(resource_type STREQUAL "FILE" AND NOT EXISTS "${source_path}")
    message(FATAL_ERROR "File not found: ${source_path}")
endif()

Copilot uses AI. Check for mistakes.
Comment thread CPack.cmake
if(NOT resource_type STREQUAL "PLUGIN")
if(WIN32)
if(resource_type STREQUAL "FILE")
get_filename_component(file_name "${source_path}" NAME)
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The FILE installation on Windows doesn't preserve the directory structure correctly. The code gets file_name from the source path but then installs to ${dest_dir}, meaning a file will be installed as ${dest_dir}/${file_name}. However, the destination should just be the parent directory. Consider:

install(FILES "${source_path}" DESTINATION ${dest_dir} COMPONENT Runtime)

This is correct as written (CMake's install(FILES ...) automatically extracts the filename), but the unused file_name variable on line 107 is misleading and should be removed.

Suggested change
get_filename_component(file_name "${source_path}" NAME)

Copilot uses AI. Check for mistakes.
Comment thread CMakeLists.txt
file(APPEND ${PARTIELS_PACKAGE_SCRIPT} "\"${SIGNTOOL_EXE_NAT}\" verify /pa \"${PARTIELS_PACKAGE_OUTEXE_NAT}\"\n")
endif()
# Add resource files
set_target_resources(Partiels FILE "${PARTIELS_BINARYDATA_DIRECTORY}/Resource/FactoryTemplate.ptldoc" DESTINATION Templates)
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The trailing slash in "${PARTIELS_BINARYDATA_DIRECTORY}/Preset/" is significant for CMake's install(DIRECTORY ...) command - it causes the contents of Preset to be installed to the destination, rather than the Preset directory itself. While this appears intentional, consider being consistent with line 241 (Translations also has trailing slash). For clarity, you might want to add a comment explaining this behavior or remove the trailing slashes and adjust the DESTINATION accordingly.

Suggested change
set_target_resources(Partiels FILE "${PARTIELS_BINARYDATA_DIRECTORY}/Resource/FactoryTemplate.ptldoc" DESTINATION Templates)
set_target_resources(Partiels FILE "${PARTIELS_BINARYDATA_DIRECTORY}/Resource/FactoryTemplate.ptldoc" DESTINATION Templates)
# Note: The trailing slash in the DIRECTORY argument is significant for CMake's install(DIRECTORY ...) semantics.
# It causes the *contents* of the directory to be installed to the destination, rather than the directory itself.

Copilot uses AI. Check for mistakes.
Comment thread CPack.cmake
# WiX specific settings
set(CPACK_WIX_UPGRADE_GUID "2BE88D38-04D3-44AE-B6F6-2D78BD410D58")
set(CPACK_WIX_PRODUCT_GUID "*") # Generate new GUID for each version
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/icon_square.png")
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WiX requires icons to be in .ico format, not .png. The CPACK_WIX_PRODUCT_ICON setting with a PNG file will be ignored or cause errors. You need to either:

  1. Convert icon_square.png to icon_square.ico, or
  2. Create a separate .ico file for Windows packaging.
Suggested change
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/icon_square.png")
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/icon_square.ico")

Copilot uses AI. Check for mistakes.
Comment thread CPack.cmake
Comment on lines +151 to +152
set(CPACK_WIX_UI_BANNER "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/Ircam-logo-noir-RS.bmp")
set(CPACK_WIX_UI_DIALOG "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/Ircam-logo-noir-RS.bmp")
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WiX requires UI banners and dialogs to be in BMP format with specific dimensions (493x58 pixels for banner, 493x312 pixels for dialog). The BMP files should be 8-bit or 24-bit. Using the same file for both may not meet the dimension requirements. Consider verifying that Ircam-logo-noir-RS.bmp has appropriate dimensions or creating separate banner and dialog images.

Suggested change
set(CPACK_WIX_UI_BANNER "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/Ircam-logo-noir-RS.bmp")
set(CPACK_WIX_UI_DIALOG "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/Ircam-logo-noir-RS.bmp")
set(CPACK_WIX_UI_BANNER "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/banner_493x58.bmp")
set(CPACK_WIX_UI_DIALOG "${CMAKE_CURRENT_SOURCE_DIR}/BinaryData/Resource/dialog_493x312.bmp")

Copilot uses AI. Check for mistakes.
@pierreguillot
Copy link
Copy Markdown
Contributor

Obsolete

@pierreguillot pierreguillot deleted the copilot/replace-packaging-with-cpack branch April 7, 2026 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace packaging and installation systems with CPack

3 participants