Packaging with CPack in NebulaGraph Database
Tags: compilation, cpack, packaging, cmake
Published: 2020-06-30 01:44:28

---
title: Packaging with CPack in NebulaGraph Database
published: true
date: 2020-05-24 08:47:10 UTC
tags: compilation,cpack,packaging,cmake
canonical_url: https://nebula-graph.io/posts/packaging-with-cpack-in-nebula-graph/
---

![](https://cdn-images-1.medium.com/max/1024/1*3evEtC0CLyjpb2DSGk3nbw.png)<figcaption>Packaging with CPack in NebulaGraph</figcaption>

[CPack](https://gitlab.kitware.com/cmake/community/-/wikis/doc/cpack/Packaging-With-CPack) is a powerful, easy to use, cross-platform software packaging tool distributed with CMake since version 2.4.2. It helps create binary package and source code package. The following figure shows where CPack locates in the whole CMake tool chain.

![](https://cdn-images-1.medium.com/max/1024/0*fBiAZDMM4hPB6bxu.png)

CPack supports the following types of package formats:

- 7Z (7-Zip file format)
- DEB (Debian packages)
- External (CPack External packages)
- IFW (Qt Installer Framework)
- NSIS (Null Soft Installer)
- NSIS64 (Null Soft Installer (64-bit))
- NuGet (NuGet packages)
- RPM (RPM packages)
- STGZ (Self extracting Tar GZip compression
- TBZ2 (Tar GZip compression)
- TXZ (Tar XZ compression)
- TZ (Tar Compress compression)
- ZIP (ZIP file format)

### Why Packaging Tools

The one-click installation package facilitates the deployment and usage of your software in production so that you can concentrate on your work rather than the software itself.

CPack can be used by specifying a CPackConfig.cmake file without CMake or as a module of CMake. As a built-in tool for CMake, CPack supports to generate the binary installer in multiple formats and is easy to use. You can just configure it in the CMakeLists.txt file.

### How to Install CPack

CPack is installed along with CMake or you can install it separately via yum or apt-get.

### A Packaging Example

### Basic Configuration

The rpm files are very similar to deb files and their differences lie mainly in configurations. Here we use rpm packages as an example. CPack packages rpm with the CPack RPM generator. All the configurations used are prefixed with CPACK\_RPM. The **rpm-build** tool is used to build the package, so make sure it has already been installed. You can install **rpm-build** via sudo yum install -y rpm-build. In our example, we're using CMake 3.14.5.

The following is the structure of our sample project:

```
example 
  |-- CMakeLists.txt // Main CMakeLists.txt file of the project 
  |-- Readme.txt 
  |-- License.txt 
  |-- src 
  | |-- CMakeLists.txt 
  | |-- MainA.cpp // Source code of the executable file Aprogram 
  | |\_\_ MainB.cpp // Source code of the executable file Bprogram 
  | 
  |-- etc 
  | |-- CMakeLists.txt 
  | |-- A.conf // Configuration file of the executable file Aprogram
  | |\_\_ B.conf // Configuration file of the executable file Bprogram 
  | 
  |\_\_ scripts 
     |-- preinst // Script to be executed before installation 
     |-- postinst // Script to be executed after installation 
     |-- prerm // Script to be executed before uninstallation 
     |\_\_ postrm // Script to be executed after uninstallation
```

Add the following configurations to the example/CMakeLists.txt file.

```
# Set Package Name 
set(CPACK\_PACKAGE\_NAME "example") 
# Enable Customized Installation Directory With ON 
set(CPACK\_SET\_DESTDIR ON) 
# Set Installation Directory 
set(CPACK\_INSTALL\_PREFIX "/home/vesoft/install") 
# Set The Version Information of The Installation Package
set(CPACK\_PACKAGE\_VERSION "1.0.0") 
# Set The Group Name 
set(CPACK\_RPM\_PACKAGE\_GROUP "vesoft") 
# Set The Vendor Name 
set(CPACK\_PACKAGE\_VENDOR "vesoft") 
# Set The License Information 
set(CPACK\_RPM\_PACKAGE\_LICENSE "Apache 2.0 + Common Clause 1.0") include(CPack)
```

When the cmake command is run, two new files will be generated in the current directory: **CPackConfig.cmake** and **CPackSourceConfig.cmake**. When compilation is completed, run cpack -G RPM to pack the files into an rpm package. You will find a new directory **\_CPack\_Packages** and a file with .rpm extension **example-1.0.0-Linux.rpm** is generated in the current directory. The installation package file is named **example-1.0.0-Linux.rpm** , which is the target package.

If you want to check detailed outputs when packing, add --verbose behind the cpack -G RPM command. CPack generates the \_CPack\_Packages/Linux/RPM/SPECS/example.spec file which is used to build the rpm based on the customer configuration.

The installation package **example-1.0.0-Linux.rpm** generated by the above configuration contains the following files:

![](https://cdn-images-1.medium.com/max/462/0*XZX1G9OpAFgVf530.png)

Note: if there is a conflict during the installation like this file /home from install of example-1.0.0-1.x86\_64 conflicts with file from package filesystem-3.2-25.el7.x86\_64, add the following configurations to exclude /home and /home/vesoft in the generated rpm file.

```
set(CPACK\_RPM\_EXCLUDE\_FROM\_AUTO\_FILELIST\_ADDITION "/home") 
list(APPEND CPACK\_RPM\_EXCLUDE\_FROM\_AUTO\_FILELIST\_ADDITION "/home/vesoft")
```

### Adding Behaviors

You can embed a pre/post (un)installation script in the spec file:

- preinst: Pre install script
- postinst: Post install script
- prerm: Pre uninstall script
- postrm: Post uninstall script

Add the following configurations in the above CMakeLists.txt file:

```
# Set the script preinst to be executed before installation
set(CPACK\_RPM\_PRE\_INSTALL\_SCRIPT\_FILE ${CMAKE\_CURRENT\_SOURCE\_DIR}/scripts/preinst) 
# Set the script prerm to be executated before uninstallation set(CPACK\_RPM\_PRE\_UNINSTALL\_SCRIPT\_FILE ${CMAKE\_CURRENT\_SOURCE\_DIR}/scripts/prerm) 
# Set the script postinst to be executed after installation set(CPACK\_RPM\_POST\_INSTALL\_SCRIPT\_FILE ${CMAKE\_CURRENT\_SOURCE\_DIR}/scripts/postinst) 
# Set the script postrm to be executed after uninstallation set(CPACK\_RPM\_POST\_UNINSTALL\_SCRIPT\_FILE ${CMAKE\_CURRENT\_SOURCE\_DIR}/scripts/postrm)
```

Note: The above four scripts require execute permissions for all users and user groups. You can change the file permissions under the script directory with chmod 755 scripts/\* after creating the scripts.

Call the sudo rpm -ivh example-1.0.0-Linux.rpm and you'll see the following outputs:

![](https://cdn-images-1.medium.com/max/1024/0*HNcgAnERIxwWbjO7.png)

Run the sudo rpm -e example-1.0.0 and you'll see the following outputs:

![](https://cdn-images-1.medium.com/max/798/0*8WJaUSIGFf1RNbnK.png)

The green and red words in the pictures are the printouts of the pre/post (un)installation scrip, which indicates they are executed as expected or not.

### Generating Multiple Packages With CPackComponent

The above configuration packs all the files to a single installation package. However, often a project contains multiple services which will be deployed on different machines. In this case, you don’t want to pack all of them into one package because this will make the package too large in size. At this time, you need the CPack components.

We will introduce to you the three CPack component functions in the following section: **cpack\_add\_component** , **cpack\_add\_component\_group** and  **install**.

Add a definition for the **install** function:

![](https://cdn-images-1.medium.com/max/1024/0*d0DXse5tern82bZJ.png)

Add a definition for the **cpack\_add\_component** function:

![](https://cdn-images-1.medium.com/max/1024/0*uhoWYl3oPdIV59vy.png)

Add a definition for the **cpack\_add\_component\_group** function:

![](https://cdn-images-1.medium.com/max/1024/0*oqL0J8tdyMoAgHir.png)

Assume we are packing program A and its configuration file A.conf into an rpm package, program B and its configuration file B.conf into another rpm package, we need to replace the include(CPack) of the above example/CMakeLists.txt with the following configurations:

```
# Set one rpm package per group 
set(CPACK\_COMPONENTS\_GROUPING ONE\_PER\_GROUP) 
# Enable COMPONENT 
set(CPACK\_RPM\_COMPONENT\_INSTALL ON) 

include(CPack) 

# Add a component named AComponent 
cpack\_add\_component(AComponent DISPLAY\_NAME "A program" DESCRIPTION "The program for test" GROUP Aprogram) 
# Add a component named BComponent 
cpack\_add\_component(BComponent DISPLAY\_NAME "B program" DESCRIPTION "The program for test" GROUP Bprogram) 
# Add a group named Aprogram, this will make part of the rpm package name 
cpack\_add\_component\_group(Aprogram) 
# Add a group named Bprogram 
cpack\_add\_component\_group(Bprogram)
```

Then modify src/CMakeLists.txt, as show below, the config the COMPONENT option of installation rules of program A and B to AComponent and BComponent

![](https://cdn-images-1.medium.com/max/382/0*XhEnrnzsTvD8vuPQ.png)

So as the etc/CMakeLists.txt

![](https://cdn-images-1.medium.com/max/502/0*lKdfL9VIVtF4B0w4.png)

After that, re-run cmake command to generate a new makefile. Then call cpack -G RPM. Two files will be generated under the current directory, i.e. **example-1.0.0-Linux-Aprogram.rpm** and **example-1.0.0-Linux-Bprogram.rpm** , each of which contains the following files:

![](https://cdn-images-1.medium.com/max/572/0*uupTQ9seHxKXghh5.png)

### More Common Parameters

```
# Set CPACK\_SET\_DESTDIR to OFF 
set(CPACK\_SET\_DESTDIR OFF) 
# Enable the CPACK\_RPM\_PACKAGE\_RELOCATABLE 
set(CPACK\_RPM\_PACKAGE\_RELOCATABLE ON) 
# Set the default reset directory 
set(CPACK\_PACKAGING\_INSTALL\_PREFIX "/home/vesoft/install")
```

The relocatable RPM can be installed using:

```
sudo rpm -ivh example-1.0.0-Linux-Aprogram.rpm --prefix=/home/test/install
```

You can use **CPACK\_RPM\_SPEC\_MORE\_DEFINE** option to add any %define lines to the generated spec file.

### More About CPack

There are many parameters for CPack. And parameters in different versions may vary. Please refer to the [CPack Site](https://cmake.org/cmake/help/latest/module/CPack.html) for details or use CPack --help for more information.

### Applying CPack in NebulaGraph Database

We use CPack to pack rpm and deb packages for **Nebula Graph**. Click [here](https://github.com/vesoft-inc/nebula/releases) to get packages of each release version.

![](https://cdn-images-1.medium.com/max/1024/0*W6BT5eAv55iuVr6B.png)

### You might also like:

1. [Automating Your Project Processes with Github Actions](https://nebula-graph.io/en/posts/github-action-automating-project-process/)
2. [Practice Jepsen Test Framework in NebulaGraph](https://nebula-graph.io/en/posts/practice-jepsen-test-framework-in-nebula-graph/)
3. [Integrating Codecov Test Coverage With NebulaGraph](https://nebula-graph.io/en/posts/integrate-codecov-test-coverage-with-nebula-graph/)

> _Hi, I’m Laura, an engineer at NebulaGraph. Hope my post is of help to you. Please let me know if you have any ideas about this. Thanks~_

> _Like what we do ? Star us on GitHub._ [_https://github.com/vesoft-inc/nebula_](https://github.com/vesoft-inc/nebula)

_Originally published at_ [_https://nebula-graph.io_](https://nebula-graph.io/posts/packaging-with-cpack-in-nebula-graph/) _on May 19, 2020._

* * *