CPack archive file empty

I have been trying to use CPack on my project (which builds vst plugins) and having a hard time making it work. So I created a smaller project to ask for help.

The idea is that there are 2 components: a vst2 and a vst3 which are both the exact same file but need to go in different folder with different names (note that it is actually the same way for my audio plugins).

Here is the small project CMakeLists.txt

cmake_minimum_required(VERSION 3.17)
project(cpack_test)

set(CMAKE_CXX_STANDARD 17)

add_executable(cpack_test main.cpp)

set(DEST_DIR "/Volumes/Vault/tmp/cpack-test")

install(FILES "$<TARGET_FILE:cpack_test>"
    COMPONENT "vst2"
    DESTINATION "${DEST_DIR}/vst2"
    CONFIGURATIONS Debug
    RENAME "cpack_test_Debug_vst2"
    )

install(FILES "$<TARGET_FILE:cpack_test>"
    COMPONENT "vst3"
    DESTINATION "${DEST_DIR}/vst3"
    CONFIGURATIONS Debug
    RENAME "cpack_test_Debug_vst3"
    )


set(CPACK_PACKAGE_NAME                "CPackTestArchive")
set(CPACK_PACKAGE_VENDOR              "TBD: CPACK_PACKAGE_VENDOR")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "TBD: CPACK_PACKAGE_DESCRIPTION_SUMMARY")
set(CPACK_PACKAGE_VERSION_MAJOR       "1")
set(CPACK_PACKAGE_VERSION_MINOR       "0")
set(CPACK_PACKAGE_VERSION_PATCH       "0")
set(CPACK_GENERATOR ZIP)
set(CPACK_VERBATIM_VARIABLES TRUE)
set(CPACK_ARCHIVE_COMPONENT_INSTALL TRUE)
set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)

include(CPack)

cpack_add_component(vst3
    DISPLAY_NAME "TBD: cpack_add_component/vst3/DISPLAY_NAME"
    DESCRIPTION  "TBD: cpack_add_component/vst3/DESCRIPTION"
    )

cpack_add_component(vst2
    DISPLAY_NAME "TBD: cpack_add_component/vst2/DISPLAY_NAME"
    DESCRIPTION  "TBD: cpack_add_component/vst2/DESCRIPTION"
    )

add_custom_target("archive"
    COMMAND ${CMAKE_COMMAND} -E echo "Creating archive ${CMAKE_CPACK_COMMAND}"
    COMMAND "${CMAKE_CPACK_COMMAND}" --verbose -G ZIP -C $<CONFIG>
    DEPENDS cpack_test
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" # CPackConfig.cmake is created there
    )

When I run the archive target I get the following output:

[100%] Built target cpack_test
Creating archive /Applications/CLion.app/Contents/bin/cmake/mac/bin/cpack
CPack: Enable Verbose
CPack Verbose: Read CPack config file: 
CPack Verbose: Read CPack configuration file: /Volumes/Vault/tmp/misc-projects/cpack-test/cmake-build-debug/CPackConfig.cmake
CPack Verbose: Specified generator: ZIP
CPack Verbose: Use generator: cmCPackArchiveGenerator
CPack Verbose: For project: CPackTestArchive
CPack: Create package using ZIP
CPack Verbose: Read description file: /Applications/CLion.app/Contents/bin/cmake/mac/share/cmake-3.17/Templates/CPack.GenericDescription.txt
CPack Verbose: [ZIP] requested component grouping = ALL_COMPONENTS_IN_ONE
CPack Verbose: [ZIP] requested component grouping = ALL_COMPONENTS_IN_ONE
CPack Verbose: Remove toplevel directory: /Volumes/Vault/tmp/misc-projects/cpack-test/cmake-build-debug/_CPack_Packages/Darwin/ZIP
CPack: Install projects
CPack: - Run preinstall target for: cpack_test
CPack: - Install project: cpack_test [Debug]
CPack: -   Install component: vst2
CPack Verbose: Install configuration: "Debug"
CPack Verbose: Up-to-date: /Volumes/Vault/tmp/cpack-test/vst2/cpack_test_Debug_vst2
CPack: -   Install component: vst3
CPack Verbose: Install configuration: "Debug"
CPack Verbose: Up-to-date: /Volumes/Vault/tmp/cpack-test/vst3/cpack_test_Debug_vst3
CPack: Create package
CPack Verbose: Package files to: /Volumes/Vault/tmp/misc-projects/cpack-test/cmake-build-debug/_CPack_Packages/Darwin/ZIP/CPackTestArchive-1.0.0-Darwin.zip
CPack Verbose: Packaging all groups in one package...(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE is set)
CPack Verbose:    - packaging component: vst2
CPack Verbose:    - packaging component: vst3
CPack Verbose: Copying final package(s) [1]:
CPack: - package: /Volumes/Vault/tmp/misc-projects/cpack-test/cmake-build-debug/CPackTestArchive-1.0.0-Darwin.zip generated.
Built target archive

But the archive generated (CPackTestArchive-1.0.0-Darwin.zip ) is completely empty. I have been following the details in Chapter 27 of Professional CMake (7th edition) but cannot figure out what I am doing wrong. It also seems to suggest that cpack is installing in a staging directory but from the output it looks like it is installing in the actual destination folder, not a staging one and I am wondering if that is the issue.

Thanks for the help
Yan

This is your issue. This is due to the fact you use absolute path as installation destination:

set(DEST_DIR "/Volumes/Vault/tmp/cpack-test")

install(FILES "$<TARGET_FILE:cpack_test>"
        COMPONENT "vst2"
        DESTINATION "${DEST_DIR}/vst2"
        CONFIGURATIONS Debug
        RENAME "cpack_test_Debug_vst2"
        )

You can try to set https://cmake.org/cmake/help/v3.18/variable/CPACK_SET_DESTDIR.html to 1,
which will make the CPack archive generator uses the destdir mechanism for installing in the staging area (some generator like RPM or DEB does that by default but archive generator does not).
My advice: unless you have good reason to chose absolute destination you’d better use a relative destination path. This way you will stay away from subtle trouble when packaging and I bet you’ll get what you want in the archive.

Have a look at: https://cmake.org/cmake/help/v3.18/variable/CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION.html
too.

I tried to make the installation not absolute like so (and using CMAKE_INSTALL_PREFIX):

set(CMAKE_INSTALL_PREFIX "/Volumes/Vault/tmp/cpack-test")

install(FILES "$<TARGET_FILE:cpack_test>"
    COMPONENT "vst2"
    DESTINATION "vst2"
    CONFIGURATIONS Debug
    RENAME "cpack_test_Debug_vst2"
    )

install(FILES "$<TARGET_FILE:cpack_test>"
    COMPONENT "vst3"
    DESTINATION "vst3"
    CONFIGURATIONS Debug
    RENAME "cpack_test_Debug_vst3"
    )

And indeed it does work as you suggested! Thank you.

Is there any CPack generator that would allow the installation to be user specific? In the case of vst plugins, they must end up in ${HOME)/Library/Audio-Plugins/VST3 (resp. ${HOME)/Library/Audio-Plugins/VST for VST2) on macOS and this is clearly a path that cannot be hardcoded.

Thanks
Yan

If the installation destination is user specific then this will probably be the installer that will make it possible to chose the appropriate location.
May be (I’m not using those), IFW (https://cmake.org/cmake/help/v3.18/cpack_gen/ifw.html) or NSIS (https://cmake.org/cmake/help/v3.18/cpack_gen/nsis.html) can do that?

Have a look at generator specific variables: CPACK_IFW_TARGET_DIRECTORY
and CPACK_NSIS_INSTALL_ROOT.

May be some of them can accommodate with a “user-directory”.

Ok I will take a look at IFW and will report back if I can make it work. Thanks!

Another way people often enable relocatable CMake project builds (not even getting into CPack) is by simply not setting CMAKE_INSTALL_PREFIX at all — that will cause CMake to use /usr/local/ by default (on POSIX), but also allows it to be overridden at build time from the command line. Configuring package builds with something like:

cmake -B build -S . -DCMAKE_INSTALL_PREFIX="$HOME/.local"

Is pretty familiar territory for anyone building CMake projects from source. CMAKE_INSTALL_PREFIX should generally be treated as a builder-defined, rather than vendor-defined, path.

Going back to packaged builds, though…

Why not? $HOME/Library/Audio-Plugins/VST3 can be hardcoded as long as you keep the variable unexpanded until install time.

Specifically, on macOS, if you’re using e.g. the Bundle generator, then it supports defining a CPACK_BUNDLE_STARTUP_COMMAND script to be packaged with the Bundle, and that script could absolutely include a line like cp myplugin.vst ~/Library/Audio-Plugins/VST3/ to execute when the user first extracts the package locally. (That would be in line with the macOS ecosystem’s preferred “no-install install” ethos, in fact.)

This is true but this require building from source. If you want to go the CPack way you can produce relocatable package too for the CPack generator supporting it, e.g. RPM or DEB do.
In this case you still have to decide what will be the default prefix of the package, which is given by https://cmake.org/cmake/help/latest/variable/CPACK_PACKAGING_INSTALL_PREFIX.html
(and not CMAKE_INSTALL_PREFIX).

I am not sure what you mean when you say to keep the variable unexpanded until install time. The issue is that my framework allows to install the plugin locally after being build (and this uses the install functionality from CMake) and also to create an archive (zip file) using CPack which piggies back onto install to install into a staging area. If my path is absolute then it works for install but it fails with CPack. By changing to relative then it works in both cases. The default /usr/local makes no sense for this project but I am letting the user override it anyway (if for example they want to install for everybody /Library/... vs for the user ~/Library/...)

At this stage I only want to provide ZIP archive because it needs to work both on macOS and Windows but any user of my framework can override the “Archive” functionality and use CMake/CPack the way they want to generate bundles or whatever they want.