Using CMake create a library, rpm package and source rpm package.
Creating rpm, tgz or deb package using cmake and cpack
When working with C/C++ libraries on RHEL-based systems like RedHat, Rocky Linux, and CentOS Stream, RPM packages are the go-to method. They simplify managing different versions, development files, and sources, making deployments a breeze with yum
or dnf
. RPM packages also ensure consistency across environments, which is crucial for stable production systems.
While the traditional approach involves rpmbuild
and manually writing spec files, there's a modern alternative that developers love: CMake paired with cpack. This combo not only speeds up the process but also adds versatility. By using the CPACK_GENERATOR
flag, you can package your library in various formats, such as ZIP, RPM, DEB, or TGZ, depending on your target OS. This flexibility means you’re not locked into a single format—perfect for cross-platform projects.
If you are maintaining libraries across different environments, this method saves a lot of time and reduces the potential for errors during packaging and deployment. It is a simple, yet powerful, way to streamline your library management.
For the Linux OS one can use RPM,DEB, TZ, TGZ based one OS distro.
For the Window OS once can select NSIS, ZIP
For MAC OS one can select PACKAGEMAKER, OSXX11 and etc.
Now, let’s walk through the steps to get this set up. I’ll be demonstrating on Rocky Linux 9 with CMake version 3.26.
Before we begin, make sure you have both CMake and rpmbuild
installed on your system. If not, you can easily install them using the following command.
sudo dnf install gcc-c++ rpm-build cmake
Let's write a simple add library in C++, it takes int, float, strings as input and return the result.
directory tree of this code -
.
├── build.sh
└── libadd
├── add.cpp
├── add.h
└── CMakeLists.txt
1 directory, 4 files
#!/bin/bash
#define build paths
source_path=$(pwd)/libadd
source_rpm_path=$(pwd)/source-rpm
binary_rpm_path=$(pwd)/binary-rpm
if [ "$1" == "clean" ]
then
rm -rf $source_rpm_path $binary_rpm_path
exit 0
fi
#create new build paths
rm -rf $source_rpm_path $binary_rpm_path
mkdir $source_rpm_path $binary_rpm_path
#build and pacakge binary rpm
cmake -B$binary_rpm_path -S$source_path -DGENERATE_SOURCE_RPM=ON
cd $binary_rpm_path
make
cpack
if [ $? == 0 ]; then
#build and package source rpm
cmake -B$source_rpm_path -S$source_path -DGENERATE_SOURCE_RPM=OFF
cd $source_rpm_path
cpack
fi
Using the build script, one should be able to generate the source as well as the binary rpm.
build script output
rohit@172:~/Blogging/libadd$ sh build.sh
-- The CXX compiler identification is GNU 11.4.1
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/rohit/Blogging/libadd/binary-rpm
[ 50%] Building CXX object CMakeFiles/add.dir/add.cpp.o
[100%] Linking CXX shared library libadd.so
[100%] Built target add
CPack: Create package using RPM
CPack: Install projects
CPack: - Run preinstall target for: libadd
CPack: - Install project: libadd []
CPack: Create package
libadd-1.0-1.x86_64
libadd-1.0-1.x86_64/usr
libadd-1.0-1.x86_64/usr/lib
libadd-1.0-1.x86_64/usr/lib/libadd.so.1.0
libadd-1.0-1.x86_64/usr/lib/libadd.so.1
libadd-1.0-1.x86_64/usr/lib/libadd.so
libadd-1.0-1.x86_64/usr/include
libadd-1.0-1.x86_64/usr/include/add.h
CPackRPM: Will use GENERATED spec file: /home/rohit/Blogging/libadd/binary-rpm/_CPack_Packages/Linux/RPM/SPECS/libadd.spec
CPack: - package: /home/rohit/Blogging/libadd/binary-rpm/libadd-1.0-1.src.rpm generated.
-- The CXX compiler identification is GNU 11.4.1
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/rohit/Blogging/libadd/source-rpm
CPack: Create package using RPM
CPack: Install projects
CPack: - Run preinstall target for: libadd
CPack: - Install project: libadd []
CPack: - Install component: lib
CPack: - Install component: devel
CPack: Create package
CPackRPM: Will use GENERATED spec file: /home/rohit/Blogging/libadd/source-rpm/_CPack_Packages/Linux/RPM/SPECS/libadd-devel.spec
CPackRPM: Will use GENERATED spec file: /home/rohit/Blogging/libadd/source-rpm/_CPack_Packages/Linux/RPM/SPECS/libadd-lib.spec
CPack: - package: /home/rohit/Blogging/libadd/source-rpm/libadd-1.0-1.x86_64-devel.rpm generated.
CPack: - package: /home/rohit/Blogging/libadd/source-rpm/libadd-1.0-1.x86_64-lib.rpm generated.
rohit@172:~/Blogging/libadd$