git: 2c24a73ff2ca - main - Features/debuginfo.mk: Automatically generate a subpackage with debugging info.

From: Gleb Popov <arrowd_at_FreeBSD.org>
Date: Sat, 03 Feb 2024 06:32:25 UTC
The branch main has been updated by arrowd:

URL: https://cgit.FreeBSD.org/ports/commit/?id=2c24a73ff2ca33449a1edd860c645c43c8ed7d57

commit 2c24a73ff2ca33449a1edd860c645c43c8ed7d57
Author:     Gleb Popov <arrowd@FreeBSD.org>
AuthorDate: 2024-01-12 15:46:09 +0000
Commit:     Gleb Popov <arrowd@FreeBSD.org>
CommitDate: 2024-02-03 06:31:13 +0000

    Features/debuginfo.mk: Automatically generate a subpackage with debugging info.
    
    Differential Revision: https://reviews.freebsd.org/D43515
    
    Tested by:      flo
    Approved by:    portmgr, emaste
---
 Mk/Features/debuginfo.mk       | 34 ++++++++++++++++++++++++++++++++++
 Mk/Scripts/generate-symbols.sh | 17 ++++++++++++-----
 Mk/Scripts/qa.sh               |  2 ++
 Mk/Uses/cmake.mk               |  4 +++-
 Mk/Uses/meson.mk               |  2 ++
 Mk/bsd.port.mk                 |  6 +++---
 6 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/Mk/Features/debuginfo.mk b/Mk/Features/debuginfo.mk
new file mode 100644
index 000000000000..e64e59c68653
--- /dev/null
+++ b/Mk/Features/debuginfo.mk
@@ -0,0 +1,34 @@
+# DEBUGINFO Support
+#
+# Add WITH_DEBUGINFO=yes into make.conf:
+# - If set, the port will be compiled in the release mode but with debugging
+#   info generated. The debugging info is then extracted from binaries and put
+#   into a separate subpackage called debuginfo.
+# - If used in conjunction with WITH_DEBUG the port will be compiled in the
+#   debug mode.
+
+.if !defined(_DEBUGINFO_MK_INCLUDED)
+_DEBUGINFO_MK_INCLUDED=		yes
+DEBUGINFO_Include_MAINTAINER=	portmgr@FreeBSD.org
+
+# We need to do everything that Features/debug.mk does, but without setting
+# WITH_DEBUG to prevent build systems from building in the complete debug mode.
+# instead let them detect WITH_DEBUGINFO and build what meson calls "debugoptimized"
+# and CMake calls "RelWithDebInfo".
+.  if !defined(WITH_DEBUG)
+.    include "debug.mk"
+.  endif
+
+SUBPACKAGES+=		debuginfo
+DESCR.debuginfo=	${WRKDIR}/descr.debuginfo
+DEBUGINFO_EXTRACT_ENV=	PREFIX=${PREFIX} LOCALBASE=${LOCALBASE} STAGEDIR=${STAGEDIR} \
+			TMPPLIST=${TMPPLIST} PREPEND_SUBPACKAGE_PREFIX=yes
+
+_FEATURES_stage=	751:debuginfo-extract
+
+debuginfo-extract:
+	@${ECHO_CMD} "Debugging symbols for the ${PKGNAME} package" > ${DESCR.debuginfo}
+	@${ECHO_CMD} "====> Extracting debugging symbols from binaries"
+	@${SETENV} ${DEBUGINFO_EXTRACT_ENV} ${SH} ${SCRIPTSDIR}/generate-symbols.sh
+
+.endif
diff --git a/Mk/Scripts/generate-symbols.sh b/Mk/Scripts/generate-symbols.sh
index 680ffde814ac..1dfb869768d3 100644
--- a/Mk/Scripts/generate-symbols.sh
+++ b/Mk/Scripts/generate-symbols.sh
@@ -6,7 +6,6 @@
 # For example:
 # /var/qmail/bin/qmaild -> /usr/local/lib/debug/var/qmail/bin/qmaild.debug
 # /usr/local/bin/ssh    -> /usr/local/lib/debug/usr/local/bin/ssh.debug
-LIB_DIR_PREFIX="${LOCALBASE}/lib/debug"
 
 set -o pipefail
 
@@ -14,7 +13,15 @@ msg() {
         echo "====> $*"
 }
 
-msg "Finding symbols"
+
+if [ -z "${PREFIX}" -o -z "${LOCALBASE}" -o -z "${STAGEDIR}" -o -z "${TMPPLIST}" ]; then
+	echo "PREFIX, LOCALBASE, STAGEDIR and TMPPLIST are required in environment." >&2
+	exit 1
+fi
+
+if [ ! -z "${PREPEND_SUBPACKAGE_PREFIX}" ]; then
+	subpkg_prefix="@@debuginfo@@"
+fi
 
 # Find all ELF files
 ELF_FILES=$(mktemp -t elf_files)
@@ -25,7 +32,7 @@ find ${STAGEDIR} -type f ! -name '*.a' \
     > ${ELF_FILES}
 
 # Create all of the /usr/local/lib/* dirs
-lib_dir="${STAGEDIR}${LIB_DIR_PREFIX}"
+lib_dir="${STAGEDIR}${LOCALBASE}/lib/debug"
 sed -e "s,^${STAGEDIR}/,${lib_dir}/," -e 's,/[^/]*$,,' \
     ${ELF_FILES} | sort -u | xargs mkdir -p
 
@@ -40,8 +47,8 @@ while read -r staged_elf_file; do
 	# Strip and add a reference to f.debug for finding the symbols.
 	objcopy --strip-debug --strip-unneeded \
 	    --add-gnu-debuglink="${debug_file_name}" "${staged_elf_file}"
-	msg "Saved symbols for ${staged_elf_file}"
-	echo "${debug_file_name#${STAGEDIR}}" >&3
+	msg "Saved symbols for ${staged_elf_file#${STAGEDIR}}"
+	echo "${subpkg_prefix}${debug_file_name#${STAGEDIR}}" >&3
 done < ${ELF_FILES} 3>> ${TMPPLIST}
 
 # Need @dir entries if PREFIX != LOCALBASE
diff --git a/Mk/Scripts/qa.sh b/Mk/Scripts/qa.sh
index c4b68b67d2c8..4ba045601ebb 100644
--- a/Mk/Scripts/qa.sh
+++ b/Mk/Scripts/qa.sh
@@ -736,6 +736,8 @@ sonames() {
 		[ -z "${f}" ] && continue
 		# Ignore symlinks
 		[ -f "${f}" -a ! -L "${f}" ] || continue
+		# Ignore .debug files
+		[ "${f}" == "${f%.debug}" ] || continue
 		if ! readelf -d ${f} | grep SONAME > /dev/null; then
 			warn "${f} doesn't have a SONAME."
 			warn "pkg(8) will not register it as being provided by the port."
diff --git a/Mk/Uses/cmake.mk b/Mk/Uses/cmake.mk
index 57575ac913a2..f4150b0e5adf 100644
--- a/Mk/Uses/cmake.mk
+++ b/Mk/Uses/cmake.mk
@@ -70,13 +70,15 @@ RUN_DEPENDS+=		${CMAKE_BIN}:devel/cmake-core
 
 .    if defined(WITH_DEBUG)
 CMAKE_BUILD_TYPE?=	Debug
+.    elif defined(WITH_DEBUGINFO)
+CMAKE_BUILD_TYPE?=	RelWithDebInfo
 .    else
 CMAKE_BUILD_TYPE?=	Release
 .    endif #defined(WITH_DEBUG)
 
 PLIST_SUB+=		CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:tl}"
 
-.    if defined(STRIP) && ${STRIP} != "" && !defined(WITH_DEBUG)
+.    if defined(STRIP) && ${STRIP} != "" && !defined(WITH_DEBUG) && !defined(WITH_DEBUGINFO)
 INSTALL_TARGET?=	install/strip
 .    endif
 
diff --git a/Mk/Uses/meson.mk b/Mk/Uses/meson.mk
index 4237bf2c4793..571e8a990be0 100644
--- a/Mk/Uses/meson.mk
+++ b/Mk/Uses/meson.mk
@@ -53,6 +53,8 @@ INSTALL_TARGET=		install
 # should we have strip separate from WITH_DEBUG?
 .  if defined(WITH_DEBUG)
 CONFIGURE_ARGS+=	--buildtype debug
+.  elif defined(WITH_DEBUGINFO)
+CONFIGURE_ARGS+=	--buildtype debugoptimized
 .  else
 CONFIGURE_ARGS+=	--buildtype release \
 			--optimization plain \
diff --git a/Mk/bsd.port.mk b/Mk/bsd.port.mk
index 0f0aa8c2c392..617844d979f0 100644
--- a/Mk/bsd.port.mk
+++ b/Mk/bsd.port.mk
@@ -1013,7 +1013,7 @@ LC_ALL=		C
 # These need to be absolute since we don't know how deep in the ports
 # tree we are and thus can't go relative.  They can, of course, be overridden
 # by individual Makefiles or local system make configuration.
-_LIST_OF_WITH_FEATURES=	bind_now debug lto pie relro sanitize ssp
+_LIST_OF_WITH_FEATURES=	bind_now debug debuginfo lto pie relro sanitize ssp
 _DEFAULT_WITH_FEATURES=	ssp
 PORTSDIR?=		/usr/ports
 LOCALBASE?=		/usr/local
@@ -2650,7 +2650,7 @@ _SUBPACKAGE_HELPERS_FILE=	DESCR PKGINSTALL PKGDEINSTALL PKGMESSAGE \
 ${v}.${sp}?=	${$v}.${sp}
 .        endfor
 _PKGMESSAGES.${sp}=		${PKGMESSAGE}.${sp}
-.        if !exists(${DESCR.${sp}})
+.        if !exists(${DESCR.${sp}}) && ${sp} != debuginfo
 DESCR.${sp}=	${DESCR}
 DEV_WARNING+=	"DESCR.${sp} needs to point to an existing file."
 .        endif
@@ -5471,7 +5471,7 @@ _STAGE_SEQ=		050:stage-message 100:stage-dir 150:run-depends \
 				900:add-plist-info 910:add-plist-docs 920:add-plist-examples \
 				930:add-plist-data 940:add-plist-post ${POST_PLIST:C/^/990:/} \
 				${_OPTIONS_install} ${_USES_install} \
-				${_OPTIONS_stage} ${_USES_stage}
+				${_OPTIONS_stage} ${_USES_stage} ${_FEATURES_stage}
 .    if defined(DEVELOPER)
 _STAGE_SEQ+=	995:stage-qa
 .    else