Search code examples
makefilecmakepackagecpack

How to get CMake/CPack to generate multiple packages for different OSs and different architectures within each OS?


Say I have the following basic CMakeLists.txt file.

target_include_directories( addnum
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/include"
)

add_executable(addnumapp src/main.cpp)
target_link_libraries(addnumapp addnum)

SET(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "g++ (>= 7), libffi-dev, libncurses5-dev, libsqlite3-dev, mcpp, zlib1g-dev")

SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Some person")
INCLUDE(CPack)

To create a "deb" package, I create a build directory and run the following command to build my project:

cmake -S . -B ./build

I then run the cpack command from within the build directory and a ".deb" package is generated. This is great to generate a single ".deb" package; however, I would like to generate multiple packages using cmake and cpack and I'm unsure what the best way to go about this is.

For example, how do I generate ".deb" packages for all the supported Debian architectures?

enter image description here

From my research, I'm aware of the following command, which allows you to specify an architecture:

set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE, "i386")

However, this only works if you're generating a single Debian package through the method I've outlined above. How does one generate multiple Debian packages for all the different architectures?

My second question is about generating multiple packages for different Operating Systems. For example, the above CMakeLists.txt file just generates a Debian package; however, I would also like to generate packages for MacOS and Windows.

From my research, I'm aware that the following edits to my CMakeLists.txt file should theoretically be the minimal changes required for me to generate a ".dmg" package for MacOS in addition to the Debian package I also want generated.

...
SET(CPACK_GENERATOR "DEB;DragNDrop") # modification here
set(CPACK_DEBIAN_PACKAGE_DEPENDS "g++ (>= 7), libffi-dev, libncurses5-dev, libsqlite3-dev, mcpp, zlib1g-dev")
SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)

SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Some person") #required
INCLUDE(CPack)
INCLUDE(CPackDMG) # addition here

However, when I run cmake -S . -B ./build on this modified CMakeLists.txt file (from an Ubuntu OS), I get the following error:

CMake Error at CMakeLists.txt:28 (INCLUDE): INCLUDE could not find requested file:

CPackDMG

-- Configuring incomplete, errors occurred!

Is this error because I'm trying to generate a MacOS "dmg" package from Ubuntu or is it because I'm missing some cpack dependency?

Further, is this the best way to generate different packages for different platforms?

To summarise, my two questions are (1) how to generate multiple packages for different architectures and (2) how to generate multiple packages for different platforms? (Please bear in mind that I'm very new to C++, CMake and CPack.)


Solution

  • (1) how to generate multiple packages for different architectures

    Just use different build environments (hardware, docker containers, virtual machines, ...) or use cross-compilation and toolchain files.

    (2) how to generate multiple packages for different platforms?

    CPackDMG is an internal CPack module. You don't need to include it. Your CMakeLists.txt should use only CPack and set desired variables before. Set CPACK_GENERATOR to the list of package types you want and the generator-specific variables. However, some generators use external tools -- e.g., to build RPM package your environment requires working rmbuild tool... meaning that it'll be hard to build RPM package within a Debian distro %) In other words, you most likely fail to build DMG when building your package in Linux/Windows :)