I am trying to create a binary software package using CPack utility. I am using TGZ
CPack generator to generate tar.gz
file which should contain both the executable and a static library, but when I run sudo make package
the resulting tar.gz
file only contains the static library. Can somebody explain how to include both the executable and also it's dependencies(static library in this case)?
main.cpp
#include <iostream>
#include "math_lib/lib.h"
int main(int, char**){
std::cout << "Hello, from cpack_demo!\n";
std::cout << add(2, 3) << std::endl;
std::cout << subtract(2, 3) << std::endl;
std::cout << multiply(2, 3) << std::endl;
std::cout << divide(2, 3) << std::endl;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10.0)
project(cpack_demo VERSION 0.1.0 LANGUAGES C CXX)
add_subdirectory(math_lib)
add_executable(cpack_demo main.cpp)
target_link_libraries(cpack_demo math_lib)
install(TARGETS cpack_demo RUNTIME DESTINATION /usr/local/bin)
# Set CPack configuration
set(CPACK_GENERATOR "TGZ")
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_DESCRIPTION "Cpack demo")
include(CPack)
math_lib/lib.h
int add(const int a, const int b);
int subtract(const int a, const int b);
int multiply(const int a, const int b);
int divide(const int a, const int b);
math_lib/lib.cpp
int add(const int a, const int b) {
return a + b;
}
int subtract(const int a, const int b) {
return a - b;
}
int multiply(const int a, const int b) {
return a * b;
}
int divide(const int a, const int b) {
return a / b;
}
math_lib/CMakeLists.txt
cmake_minimum_required(VERSION 3.10.0)
project(math_lib VERSION 0.1.0 LANGUAGES C CXX)
add_library(math_lib lib.h lib.cpp)
install(TARGETS math_lib RUNTIME DESTINATION /usr/local/lib)
Commands
mkdir build
cd build
cmake ..
make
sudo make package
Output
tar -tvf cpack_demo-0.1.0-Linux.tar.gz
drwxr-xr-x root/root 0 2025-02-21 05:21 cpack_demo-0.1.0-Linux/lib/
-rw-r--r-- root/root 4110 2025-02-21 05:21 cpack_demo-0.1.0-Linux/lib/libmath_lib.a
Your problem is using absolute paths in DESTINATION parameter for install()
commands. While CMake allows that, it breaks many usages of your project. And packaging is among them. (This is covered in the documentation).
When create a package, CPack firstly installs a project into the intermediate staging directory, and then packages everything from that directory.
For install into the staging directory, all relative DESTINATION in install()
commands are interpreted relative to that directory. But absolute DESTINATION paths are not transformed. As a result, those files are not collected in the staging directory, and the created package doesn't include them.
Actually, needing to use sudo
with make package
is a strong signal that something goes wrong: a regular packaging never requires administrative permissions.
Just use relative DESTINATION paths in your project:
install(TARGETS cpack_demo RUNTIME DESTINATION bin)
install(TARGETS math_lib ARCHIVE DESTINATION lib)
Since CMake 3.14 you may omit those paths, because they are default:
# By default, CMake installs shared libraries into bin/ and static ones into lib/
install(TARGETS cpack_demo)
install(TARGETS math_lib)