DEV Community

loading...

Packaging with CMake CPack and NSIS on Windows

David Velho
Primarily a C++ person. Also a full stack developer along with app-dev with flutter. DevOps is cool too
Updated on ・3 min read

Assuming you have your base project(ABC) setup with CMake, let's get started.

Download and Install NSIS from here. We'll need this to use CPack with NSIS.

Let's add an icon to our built application by creating a file called abc.rc which is a resource file used by MSVCC to apply icons, among other stuff.

IDI_ICON1               ICON        DISCARDABLE            "abc.ico"
Enter fullscreen mode Exit fullscreen mode

Add this definition to our add_executable command

add_executable(abc 
${ABC_SOURCE_DIR}/assets/abc.rc
${SOURCES} 
# other stuff
)
Enter fullscreen mode Exit fullscreen mode

Next we need to define our install targets that CPack will pick up on

install(TARGETS abc 
         #other stuff
         DESTINATION bin
    )
Enter fullscreen mode Exit fullscreen mode

Here, bin is any folder you want to put your built application in. In this case, running the installer will install abc.exe into C:\Program Files(x86)\abc\bin\abc.exe .

Normally, you would set the install target's DESTINATION to ${CMAKE_INSTALL_PREFIX}. However, CPack will give you an error :

ABSOLUTE path INSTALL DESTINATION forbidden (by caller):

After what seemed like an eternity of google searching, I came across a solution

You are trying to install some files using an ABSOLUTE path DESTINATION.
99.999% of the time this is an error on the Windows platform.

Normally you should be installing files to a RELATIVE path DESTINATION.

Cpack Config

Additional stuff that you can configure

    include(InstallRequiredSystemLibraries)
    set(CPACK_PACKAGE_INSTALL_DIRECTORY "
    set(CPACK_GENERATOR "NSIS")
    set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
    set(CPACK_PACKAGE_VERSION "${ABC_VERSION_MAJOR}.${ABC_VERSION_MINOR}")
    set(CPACK_PACKAGE_VERSION_PATCH "0")
    set(CPACK_PACKAGE_VENDOR "David Velho")
    set (CPACK_NSIS_MODIFY_PATH "ON")
    set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY ${PROJECT_NAME})
    set(CPACK_SOURCE_GENERATOR "TGZ")
    set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
    set(CPACK_SOURCE_IGNORE_FILES ${CPACK_IGNORE_FILES})
Enter fullscreen mode Exit fullscreen mode

Some additional fields

    set(CPACK_NSIS_INSTALLED_ICON_NAME "${ABC_SOURCE_DIR}/assets/abc.ico")
    set(CPACK_NSIS_HELP_LINK ${APP_URL})
    set(CPACK_NSIS_URL_INFO_ABOUT ${APP_URL})
    set(CPACK_NSIS_CONTACT ${APP_EMAIL})
 set(CPACK_NSIS_CREATE_ICONS_EXTRA
    "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\abc.lnk' '$INSTDIR\\\\bin\\\\abc.exe' "
    )
Enter fullscreen mode Exit fullscreen mode

Let's give the generated installer an icon

set(CPACK_NSIS_MUI_ICON "${ABC_SOURCE_DIR}/assets/abc.ico")
Enter fullscreen mode Exit fullscreen mode

And last, the NSIS installer script that CMake will read from and substitute the values into

set(CMAKE_MODULE_PATH  ${PROJECT_SOURCE_DIR}/assets/nsis ${CMAKE_MODULE_PATH})
Enter fullscreen mode Exit fullscreen mode

Where assets/nsis has a file called NSIS.definitions.nsh.in which is a script file needed by NSIS. CMake will read this file and substitute the values in so that NSIS can read it

NSIS.definitions.nsh.in :

!define VERSION "@APP_VERSION@"
!define APP_VERSION "@APP_VERSION@"
!define APP_NAME "@APP_NAME@"
!define EXE_NAME "@EXE_NAME@"
!define README_FILE "README"
!define LICENSE_FILE "@PROJECT_SOURCE_DIR@resourcestextLICENSE"
!define MUI_ICON "@PROJECT_SOURCE_DIR@resourcesgraphics@APP_LOW_NAME@.ico"
!define MUI_UNICON "@PROJECT_SOURCE_DIR@resourcesgraphics@APP_LOW_NAME@.ico"
!define MUI_WELCOMEFINISHPAGE_BITMAP "@PROJECT_SOURCE_DIR@resourcesgraphics@APP_LOW_NAME@-banner.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "@PROJECT_SOURCE_DIR@resourcesgraphics@APP_LOW_NAME@-banner.bmp"
!define PATCH  "0"
Enter fullscreen mode Exit fullscreen mode

Let's include CPack and some NSIS config files

    include(CPack)
    configure_file(
    ${PROJECT_SOURCE_DIR}/assets/nsis/NSIS.definitions.nsh.in
    ${CMAKE_CURRENT_BINARY_DIR}/assets/nsis/NSIS.definitions.nsh
    )
Enter fullscreen mode Exit fullscreen mode

Assuming you've added CMake to PATH during installation, you should have cpack in path. You can (while in the build directory) build the installer with

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
MSBuild.exe abc.sln
cpack -C Release
Enter fullscreen mode Exit fullscreen mode

Additional Resources

Discussion (0)