Search code examples
c++cmakerpmbuild

How to use cmake pack redhat-style rpm, which is major and "-devel"?


I have tried to use cmake to pack redhat style rpms. Classical RedHat-style rpms are consist of 2 rpm, one is package-version.rpm and another is package-devel-version.rpm. But I failed.

For example, the project foo, which contains

- bin/demo 
- lib/libfoo.so.1.2.3
- lib/libfoo.so.1 
- lib/libfoo.so
- include/foo.h

I want foo-1.2.3.rpm to contain bin/demo, lib/libfoo.so.1, lib/libfoo.so.1.2.3 and foo-devel-1.2.3.rpm to contain lib/libfoo.so, include/foo.h.

But now, I can only get foo-1.2.3-major.rpm (bin/demo, lib/libfoo.so, lib/libfoo.so.1, lib/libfoo.so.1.2.3) and foo-1.2.3-devel.rpm (include/foo.h).

# CMakeLists.txt 

project (foo)

include (GNUInstallDirs)

set(CPACK_PACKAGE_VERSION_MAJOR 1)
set(CPACK_PACKAGE_VERSION_MINOR 2)
set(CPACK_PACKAGE_VERSION_PATCH 3)
set(CPACK_PACKAGE_RELEASE 1)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The CMake Demo Project")
set(CPACK_GENERATOR RPM)
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_COMPONENTS_ALL major devel)

include (CPackComponent)
include (CPack)
cpack_add_component(major DISPLAY_NAME Major)
cpack_add_component(devel DISPLAY_NAME Development)

add_executable (demo demo.cxx)

add_library (foo SHARED foo.cxx foo.h)
set_target_properties(foo PROPERTIES VERSION 1.2.3 SOVERSION 1)

install (TARGETS demo foo
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    COMPONENT major
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    COMPONENT major
    )
install (FILES foo.h
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
    COMPONENT devel
    )

Thanks to @Tsyvarev, I have made some progress. Add line set(CPACK_RPM_MAIN_COMPONENT major) before include(CPack), I get follwing result. The rpm name foo-1.2.3.rpm is correct now.

]$ rpm -ql --qf "%{name}-%{version}\n" -p foo-1.2.3-devel.rpm
foo-devel-1.2.3
/usr/include/foo.h

]$ rpm -ql --qf "%{name}-%{version}\n" -p foo-1.2.3.rpm
foo-1.2.3
/usr/bin/demo
/usr/lib64/libfoo.so
/usr/lib64/libfoo.so.1
/usr/lib64/libfoo.so.1.2.3

But the filename of foo-1.2.3-devel.rpm is still incorrect, and the files inside rpm are still wrong.


Solution

  • Finally, I finished my CMakeLists.txt

    # CMakeLists.txt 
    cmake_minimum_required (VERSION 3.12)
    
    set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "build type")
    
    project (foo VERSION 1.2.3 HOMEPAGE_URL "http://null")
    
    include (GNUInstallDirs)
    
    set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The CMake Demo Project")
    set(CPACK_COMPONENTS_ALL major devel)
    set(CPACK_GENERATOR RPM)
    set(CPACK_RPM_PACKAGE_RELEASE 10)
    set(CPACK_RPM_PACKAGE_RELEASE_DIST  ON)
    set(CPACK_RPM_COMPONENT_INSTALL ON)
    set(CPACK_RPM_MAIN_COMPONENT major) # Which set the major package name to foo instead of foo-major
    set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") # Which makes the rpm name from foo-1.2.3-devel to foo-devel-1.2.3
    set(CPACK_RPM_DEBUGINFO_PACKAGE ON)
    set(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE ON)
    
    # you must include it here after set(CPACK...) and befor cpack_add_... 
    include (CPack) 
    
    cpack_add_component(major DESCRIPTION "Something for demo")
    cpack_add_component(devel DESCRIPTION "For Development")
    
    add_executable (demo demo.cxx)
    
    add_library (foo SHARED foo.cxx foo.h)
    set_target_properties(foo PROPERTIES VERSION 1.2.3 SOVERSION 1)
    
    set(PUBLIC_HEADERS foo.h)
    
    install (TARGETS demo foo
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        COMPONENT major
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT major
        NAMELINK_COMPONENT devel # Which separate libfoo.so into foo-devel rpm, but it requires cmake-3.12, RHEL-8 takes 3.11.
        )
    install (FILES ${PUBLIC_HEADERS}
        DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
        COMPONENT devel
        )
    install (FILES README.md
        DESTINATION ${CMAKE_INSTALL_DOCDIR}-${PROJECT_VERSION}
        COMPONENT devel
        )
    

    A workaround for RHEL-8 with cmake-3.11:

    # install libfoo.so.1.2.3 and libfoo.so.1
    install (TARGETS foo
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT major
        NAMELINK_SKIP
        )
    # install libfoo.so
    install (TARGETS foo
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT devel
        NAMELINK_ONLY
        )
    
    

    Thanks to all