CPack/Deb: Add ability to split out debug symbols into .ddeb package

This commit is contained in:
Andrew Fuller 2018-09-18 10:57:27 -07:00
parent 42fbff45e4
commit d8a3939aef
10 changed files with 746 additions and 423 deletions

View File

@ -518,6 +518,26 @@ List of CPack Deb generator specific variables:
This value is not interpreted. It is possible to pass an optional
revision number of the referenced source package as well.
Packaging of debug information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Dbgsym packages contain debug symbols for debugging packaged binaries.
Dbgsym packaging has its own set of variables:
.. variable:: CPACK_DEBIAN_DEBUGINFO_PACKAGE
CPACK_DEBIAN_<component>_DEBUGINFO_PACKAGE
Enable generation of dbgsym .ddeb package(s).
* Mandatory : NO
* Default : OFF
.. note::
Binaries must contain debug symbols before packaging so use either ``Debug``
or ``RelWithDebInfo`` for :variable:`CMAKE_BUILD_TYPE` variable value.
Building Debian packages on Windows
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -0,0 +1,6 @@
cpack-deb-dbgsym-ddeb
---------------------
* The :cpack_gen:`CPack Deb Generator` learned to split debug symbols into
a corresponding .ddeb package when ``CPACK_DEBIAN_DEBUGINFO_PACKAGE`` is
set.

View File

@ -64,6 +64,8 @@ function(cpack_deb_prepare_package_vars)
endif()
set(WDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_DEB_PACKAGE_COMPONENT_PART_PATH}")
set(DBGSYMDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_DEB_PACKAGE_COMPONENT_PART_PATH}-dbgsym")
file(REMOVE_RECURSE "${DBGSYMDIR}")
# per component automatic discover: some of the component might not have
# binaries.
@ -80,7 +82,10 @@ function(cpack_deb_prepare_package_vars)
endif()
endif()
if(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OR CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS)
cpack_deb_variable_fallback("CPACK_DEBIAN_DEBUGINFO_PACKAGE"
"CPACK_DEBIAN_${_local_component_name}_DEBUGINFO_PACKAGE"
"CPACK_DEBIAN_DEBUGINFO_PACKAGE")
if(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OR CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS OR CPACK_DEBIAN_DEBUGINFO_PACKAGE)
# Generating binary list - Get type of all install files
file(GLOB_RECURSE FILE_PATHS_ LIST_DIRECTORIES false RELATIVE "${WDIR}" "${WDIR}/*")
@ -114,6 +119,81 @@ function(cpack_deb_prepare_package_vars)
string(REGEX MATCH "(^.*):" _FILE_NAME "${_FILE}")
list(APPEND CPACK_DEB_SHARED_OBJECT_FILES "${CMAKE_MATCH_1}")
endif()
if(_FILE MATCHES "ELF.*not stripped")
string(REGEX MATCH "(^.*):" _FILE_NAME "${_FILE}")
list(APPEND CPACK_DEB_UNSTRIPPED_FILES "${CMAKE_MATCH_1}")
endif()
endforeach()
endif()
find_program(READELF_EXECUTABLE NAMES readelf)
if(CPACK_DEBIAN_DEBUGINFO_PACKAGE AND CPACK_DEB_UNSTRIPPED_FILES)
find_program(OBJCOPY_EXECUTABLE NAMES objcopy)
if(NOT OBJCOPY_EXECUTABLE)
message(FATAL_ERROR "debuginfo packages require the objcopy tool")
endif()
if(NOT READELF_EXECUTABLE)
message(FATAL_ERROR "debuginfo packages require the readelf tool")
endif()
file(RELATIVE_PATH _DBGSYM_ROOT "${CPACK_TEMPORARY_DIRECTORY}" "${DBGSYMDIR}")
foreach(_FILE IN LISTS CPACK_DEB_UNSTRIPPED_FILES)
# Get the file's Build ID
execute_process(COMMAND env LC_ALL=C ${READELF_EXECUTABLE} -n "${_FILE}"
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE READELF_OUTPUT
RESULT_VARIABLE READELF_RESULT
ERROR_VARIABLE READELF_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE )
if(NOT READELF_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: readelf: '${READELF_ERROR}';\n"
"executed command: '${READELF_EXECUTABLE} -n ${_FILE}'")
endif()
if(READELF_OUTPUT MATCHES "Build ID: ([0-9a-zA-Z][0-9a-zA-Z])([0-9a-zA-Z]*)")
set(_BUILD_ID_START ${CMAKE_MATCH_1})
set(_BUILD_ID_REMAINING ${CMAKE_MATCH_2})
list(APPEND BUILD_IDS ${_BUILD_ID_START}${_BUILD_ID_REMAINING})
else()
message(FATAL_ERROR "Unable to determine Build ID for ${_FILE}")
endif()
# Split out the debug symbols from the binaries
set(_FILE_DBGSYM ${_DBGSYM_ROOT}/usr/lib/debug/.build-id/${_BUILD_ID_START}/${_BUILD_ID_REMAINING}.debug)
get_filename_component(_OUT_DIR "${_FILE_DBGSYM}" DIRECTORY)
file(MAKE_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}/${_OUT_DIR}")
execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --only-keep-debug "${_FILE}" "${_FILE_DBGSYM}"
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE OBJCOPY_OUTPUT
RESULT_VARIABLE OBJCOPY_RESULT
ERROR_VARIABLE OBJCOPY_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE )
if(NOT OBJCOPY_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
"executed command: '${OBJCOPY_EXECUTABLE} --only-keep-debug ${_FILE} ${_FILE_DBGSYM}'")
endif()
execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --strip-unneeded ${_FILE}
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE OBJCOPY_OUTPUT
RESULT_VARIABLE OBJCOPY_RESULT
ERROR_VARIABLE OBJCOPY_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE )
if(NOT OBJCOPY_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
"executed command: '${OBJCOPY_EXECUTABLE} --strip-debug ${_FILE}'")
endif()
execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}
WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
OUTPUT_VARIABLE OBJCOPY_OUTPUT
RESULT_VARIABLE OBJCOPY_RESULT
ERROR_VARIABLE OBJCOPY_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE )
if(NOT OBJCOPY_RESULT EQUAL 0)
message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
"executed command: '${OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}'")
endif()
endforeach()
endif()
@ -450,8 +530,6 @@ function(cpack_deb_prepare_package_vars)
set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY "=")
endif()
find_program(READELF_EXECUTABLE NAMES readelf)
if(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS)
if(READELF_EXECUTABLE)
foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES)
@ -507,18 +585,24 @@ function(cpack_deb_prepare_package_vars)
# <foo>_<VersionNumber>-<DebianRevisionNumber>_<DebianArchitecture>.deb
set(CPACK_OUTPUT_FILE_NAME
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
set(CPACK_DBGSYM_OUTPUT_FILE_NAME
"${CPACK_DEBIAN_PACKAGE_NAME}-dbgsym_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.ddeb")
else()
if(NOT CPACK_DEBIAN_FILE_NAME MATCHES ".*\\.(deb|ipk)")
message(FATAL_ERROR "'${CPACK_DEBIAN_FILE_NAME}' is not a valid DEB package file name as it must end with '.deb' or '.ipk'!")
endif()
set(CPACK_OUTPUT_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}")
string(REGEX REPLACE "\.deb$" "-dbgsym.ddeb" CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}")
endif()
set(CPACK_TEMPORARY_PACKAGE_FILE_NAME "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_OUTPUT_FILE_NAME}")
get_filename_component(BINARY_DIR "${CPACK_OUTPUT_FILE_PATH}" DIRECTORY)
set(CPACK_OUTPUT_FILE_PATH "${BINARY_DIR}/${CPACK_OUTPUT_FILE_NAME}")
endif() # else() back compatibility - don't change the name
else()
# back compatibility - don't change the name
string(REGEX REPLACE "\.deb$" "-dbgsym.ddeb" CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}")
endif()
# Print out some debug information if we were asked for that
if(CPACK_DEBIAN_PACKAGE_DEBUG)
@ -579,6 +663,14 @@ function(cpack_deb_prepare_package_vars)
set(GEN_CPACK_DEBIAN_GENERATE_POSTINST "${CPACK_DEBIAN_GENERATE_POSTINST}" PARENT_SCOPE)
set(GEN_CPACK_DEBIAN_GENERATE_POSTRM "${CPACK_DEBIAN_GENERATE_POSTRM}" PARENT_SCOPE)
set(GEN_WDIR "${WDIR}" PARENT_SCOPE)
set(GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE "${CPACK_DEBIAN_DEBUGINFO_PACKAGE}" PARENT_SCOPE)
if(BUILD_IDS)
set(GEN_DBGSYMDIR "${DBGSYMDIR}" PARENT_SCOPE)
set(GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_DBGSYM_OUTPUT_FILE_NAME}" PARENT_SCOPE)
string(REPLACE ";" " " BUILD_IDS "${BUILD_IDS}")
set(GEN_BUILD_IDS "${BUILD_IDS}" PARENT_SCOPE)
endif()
endfunction()
cpack_deb_prepare_package_vars()

File diff suppressed because it is too large Load Diff

View File

@ -65,6 +65,8 @@ protected:
private:
int createDeb();
int createDbgsymDDeb();
std::vector<std::string> packageFiles;
};

View File

@ -1,4 +1,4 @@
set(ALL_FILES_GLOB "*.deb")
set(ALL_FILES_GLOB "*.deb" "*.ddeb")
function(getPackageContent FILE RESULT_VAR)
execute_process(COMMAND ${CMAKE_COMMAND} -E env TZ=Etc/UTC ${DPKG_EXECUTABLE} -c "${FILE}"

View File

@ -6,7 +6,7 @@ include("${RunCMake_SOURCE_DIR}/CPackTestHelpers.cmake")
# run_cpack_test args: TEST_NAME "GENERATORS" RUN_CMAKE_BUILD_STEP "PACKAGING_TYPES"
run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM" false "MONOLITHIC;COMPONENT")
run_cpack_test(CUSTOM_NAMES "RPM;DEB;TGZ" true "COMPONENT")
run_cpack_test(DEBUGINFO "RPM" true "COMPONENT")
run_cpack_test(DEBUGINFO "RPM;DEB" true "COMPONENT")
run_cpack_test_subtests(DEFAULT_PERMISSIONS "CMAKE_var_set;CPACK_var_set;both_set;invalid_CMAKE_var;invalid_CPACK_var" "RPM;DEB" false "MONOLITHIC;COMPONENT")
run_cpack_test(DEPENDENCIES "RPM;DEB" true "COMPONENT")
run_cpack_test(DIST "RPM" false "MONOLITHIC")

View File

@ -92,7 +92,7 @@ if(NOT EXPECTED_FILES_COUNT EQUAL 0)
# check that there were no extra files generated
foreach(all_files_glob_ IN LISTS ALL_FILES_GLOB)
file(GLOB foundAll_ RELATIVE "${bin_dir}" "${all_files_glob_}")
list(APPEND allFoundFiles_ "${foundAll_}")
list(APPEND allFoundFiles_ ${foundAll_})
endforeach()
list(LENGTH foundFiles_ foundFilesCount_)

View File

@ -3,16 +3,39 @@ set(whitespaces_ "[\t\n\r ]*")
set(EXPECTED_FILES_COUNT "5")
set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
set(EXPECTED_FILE_1_NAME "Debuginfo")
if(GENERATOR_TYPE STREQUAL "RPM")
set(NAME "Debuginfo")
set(DEBUG_SUFFIX "debuginfo")
set(PKG "rpm")
set(DEBUG_PKG "rpm")
elseif(GENERATOR_TYPE STREQUAL "DEB")
set(NAME "debuginfo")
set(DEBUG_SUFFIX "dbgsym")
set(PKG "deb")
set(DEBUG_PKG "ddeb")
endif()
set(EXPECTED_FILE_1_NAME "${NAME}")
set(EXPECTED_FILE_1_COMPONENT "applications")
set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.rpm")
set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.${PKG}")
set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.rpm")
set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.${PKG}")
set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so")
set(EXPECTED_FILE_4_NAME "Debuginfo")
set(EXPECTED_FILE_4_COMPONENT "applications-debuginfo")
set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*\.debug.*")
set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm")
set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*")
set(EXPECTED_FILE_4 "${NAME}-applications-${DEBUG_SUFFIX}*.${DEBUG_PKG}")
if(GENERATOR_TYPE STREQUAL "RPM")
set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*\.debug.*")
elseif(GENERATOR_TYPE STREQUAL "DEB")
set(EXPECTED_FILE_CONTENT_4 ".*/usr/lib/debug/.build-id/.*\.debug.*")
endif()
if(GENERATOR_TYPE STREQUAL "RPM")
set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm")
set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*")
elseif(GENERATOR_TYPE STREQUAL "DEB")
set(EXPECTED_FILE_5 "TestDinfo-pkg-libs-dbgsym.ddeb")
set(EXPECTED_FILE_CONTENT_5 ".*/usr/lib/debug/.build-id/.*\.debug.*")
endif()

View File

@ -29,12 +29,16 @@ install(TARGETS test_lib DESTINATION bas COMPONENT libs)
set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT")
set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON)
set(CPACK_DEBIAN_APPLICATIONS_FILE_NAME "DEB-DEFAULT")
set(CPACK_DEBIAN_APPLICATIONS_DEBUGINFO_PACKAGE ON)
# test that components with debuginfo enabled still honor
# CPACK_PACKAGE_FILE_NAME setting
set(CPACK_RPM_PACKAGE_NAME "Debuginfo")
set(CPACK_PACKAGE_FILE_NAME "TestDinfo-pkg")
set(CPACK_RPM_LIBS_DEBUGINFO_PACKAGE ON)
set(CPACK_DEBIAN_PACKAGE_NAME "Debuginfo")
set(CPACK_DEBIAN_LIBS_DEBUGINFO_PACKAGE ON)
# test debuginfo package rename
set(CPACK_RPM_DEBUGINFO_FILE_NAME