diff --git a/build.sh b/build.sh
index b4c5c36..e5f225f 100755
--- a/build.sh
+++ b/build.sh
@@ -125,7 +125,7 @@ buildp_init_args() {
 	elif ! ex_pkg_process_restart_spec "${_bpia_rstatus}" \$ARG_RESTART \$ARG_RESTART_AT \$ARG_RESTART_RECURSIVE; then
 		_bpia_rc=1;
 		rtl_setrstatus "${_bpia_rstatus}" 'failed to process -r specification: ${'"${_bpia_rstatus}"'}.';
-	elif ! ex_pkg_load_groups \$_bpia_groups \$_bpia_groups_noauto \$GROUP_AUTO \$GROUP_TARGET; then
+	elif ! ex_pkg_load_groups \$_bpia_groups \$_bpia_groups_noauto; then
 		_bpia_rc=1;
 		rtl_setrstatus "${_bpia_rstatus}" 'failed to load build groups.';
 	else
diff --git a/etc/pkgtool.msgs.en b/etc/pkgtool.msgs.en
index eb9d25a..1fe000f 100644
--- a/etc/pkgtool.msgs.en
+++ b/etc/pkgtool.msgs.en
@@ -2,7 +2,7 @@
 # en_* locale messages file for pkgtool.sh
 #
 
-MSG_info_build_group="1;Build group: %s";
+MSG_info_build_group="2;Build group: %s (%s)";
 MSG_info_pkg_deps_fail="1;Warning: failed to unfold dependency-expanded package name list for \`%s'.";
 MSG_info_pkg_direct_deps="2;Direct dependencies of \`%s': %s";
 MSG_info_pkg_no_deps="1;Package \`%s' has no dependencies.";
diff --git a/groups/211.native_packages_cmdline.group b/groups/211.native_packages_cmdline.group
index fbfed1a..8979f5b 100644
--- a/groups/211.native_packages_cmdline.group
+++ b/groups/211.native_packages_cmdline.group
@@ -1,8 +1,8 @@
 #
 # Build group native_packages (cmdline)
 #
-GROUP_TARGET="native_packages";
-rtl_lconcat \$NATIVE_PACKAGES_PACKAGES "
+GROUP_TARGET_APPEND="native_packages";
+NATIVE_PACKAGES_CMDLINE_PACKAGES="
 bas bash bc busybox cabextract calcurse clipboard_utils coreutils cpio dash datamash dos2unix ed exif figlet
 findutils gawk gcal grep html_xml_utils jush lzop mawk mc mksh moe moon_buggy mpg123 mp3splt nano ninvaders
 openbsd_baseutils profanity pixz pv rc sash sbase screen sed sharutils sloccount tar tcsh
diff --git a/groups/221.native_packages_dev.group b/groups/221.native_packages_dev.group
index 44b37e6..89d28d5 100644
--- a/groups/221.native_packages_dev.group
+++ b/groups/221.native_packages_dev.group
@@ -1,8 +1,8 @@
 #
 # Build group native_packages (dev)
 #
-GROUP_TARGET="native_packages";
-rtl_lconcat \$NATIVE_PACKAGES_PACKAGES "
+GROUP_TARGET_APPEND="native_packages";
+NATIVE_PACKAGES_DEV_PACKAGES="
 bison cdecl chicken cparser cssc diffutils flex gdb gengetopt gnucobol indent lua lunix m4 make mandoc nasm
 patch patchutils perl posix_cc python2 python3 ruby sbsigntools tk";
 : ${PKG_BISON_DEPENDS:="readline libiconv"};
diff --git a/groups/231.native_packages_etc.group b/groups/231.native_packages_etc.group
index 1203f2f..50370e8 100644
--- a/groups/231.native_packages_etc.group
+++ b/groups/231.native_packages_etc.group
@@ -1,8 +1,8 @@
 #
 # Build group native_packages (etc)
 #
-GROUP_TARGET="native_packages";
-rtl_lconcat \$NATIVE_PACKAGES_PACKAGES "
+GROUP_TARGET_APPEND="native_packages";
+NATIVE_PACKAGES_ETC_PACKAGES="
 apr apr_util bdwgc bmake bochs bzip2 cherokee clzip cmake cron dante
 dosbox doomgeneric emacs enscript expat ffmpeg file gdbm geoip gettext_tiny ghostpdl
 giflib gnuchess graphicsmagick gzip hastyhex hexcurse hexer icoutils imagemagick infounzip infozip
diff --git a/groups/241.native_packages_inet.group b/groups/241.native_packages_inet.group
index c71813f..e46236b 100644
--- a/groups/241.native_packages_inet.group
+++ b/groups/241.native_packages_inet.group
@@ -1,8 +1,8 @@
 #
 # Build group native_packages (inet)
 #
-GROUP_TARGET="native_packages";
-rtl_lconcat \$NATIVE_PACKAGES_PACKAGES "
+GROUP_TARGET_APPEND="native_packages";
+NATIVE_PACKAGES_INET_PACKAGES="
 apk_tools bind ca_certificates curl cvs dropbear elinks fetchmail git gnupg gpgme
 gnutls httpd icecast inetutils irssi isync ldns lighttpd links lynx mailutils
 microsocks mutt nginx ngircd nullmailer openlitespeed opensmtpd openssh
diff --git a/groups/251.native_packages_lib.group b/groups/251.native_packages_lib.group
index 447720d..aeab281 100644
--- a/groups/251.native_packages_lib.group
+++ b/groups/251.native_packages_lib.group
@@ -1,8 +1,8 @@
 #
 # Build group native_packages (libs)
 #
-GROUP_TARGET="native_packages";
-rtl_lconcat \$NATIVE_PACKAGES_PACKAGES "
+GROUP_TARGET_APPEND="native_packages";
+NATIVE_PACKAGES_LIB_PACKAGES="
 aspell bearssl enchant fribidi glib hunspell ivykis jansson kvazaar lame libao libarchive libass libassuan libatomic_ops libdmtx libedit libeditline libelf libestr
 libevent libexif libfastjson libfetch libffi libfirm libflac libglob libgcrypt libgpg_error libiconv libidn2 libite
 libjpeg_turbo libksba libmad libmd libmspack libmp3splt libogg libpcap libpng libpsl
diff --git a/groups/261.native_packages_x11.group b/groups/261.native_packages_x11.group
index eb62afc..feefd73 100644
--- a/groups/261.native_packages_x11.group
+++ b/groups/261.native_packages_x11.group
@@ -1,8 +1,8 @@
 #
 # Build group native_packages (x11)
 #
-GROUP_TARGET="native_packages";
-rtl_lconcat \$NATIVE_PACKAGES_PACKAGES "
+GROUP_TARGET_APPEND="native_packages";
+NATIVE_PACKAGES_X11_PACKAGES="
 cairo fontconfig freetype freetype_pre gxemul harfbuzz imlib2
 libcaca libfontenc libICE libpthread_stubs libSM libX11 libXau
 libXaw libXdamage libXdmcp libXext libXfixes libXfont2 libXft libXi libxkbfile
diff --git a/pkgtool.sh b/pkgtool.sh
index 1fac303..c7c1133 100755
--- a/pkgtool.sh
+++ b/pkgtool.sh
@@ -210,12 +210,12 @@ pkgtoolp_init_getopts_fn() {
 # {{{ pkgtoolp_info($_rstatus, $_pkg_name)
 pkgtoolp_info() {
 	local	_ppi_rstatus="${1}" _ppi_pkg_name="${2}"				\
-		_ppi_fname="" _ppi_group_name="" _ppi_groups="" _ppi_groups_noauto=""	\
-		_ppi_patch_idx=0 _ppi_pkg_disabled="" _ppi_pkg_finished=""		\
-		_ppi_pkg_name_uc="" _ppi_pkg_names="" _ppi_rc=0;
+		_ppi_fname="" _ppi_group_fname="" _ppi_group_name="" _ppi_groups=""	\
+		_ppi_groups_noauto="" _ppi_patch_idx=0 _ppi_pkg_disabled=""		\
+		_ppi_pkg_finished="" _ppi_pkg_name_uc="" _ppi_pkg_names="" _ppi_rc=0;
 	rtl_toupper2 \$_ppi_pkg_name \$_ppi_pkg_name_uc;
 
-	if ! ex_pkg_load_groups \$_ppi_groups \$_ppi_groups_noauto \$GROUP_AUTO \$GROUP_TARGET; then
+	if ! ex_pkg_load_groups \$_ppi_groups \$_ppi_groups_noauto; then
 		_ppi_rc=1;
 		rtl_setrstatus "${_ppi_rstatus}" 'Error: failed to load build groups.';
 	elif ! ex_pkg_find_package \$_ppi_group_name "${_ppi_groups}" "${_ppi_pkg_name}"; then
@@ -229,9 +229,10 @@ pkgtoolp_info() {
 		_ppi_rc=1;
 		rtl_setrstatus "${_ppi_rstatus}" 'Error: failed to set package environment for \`'"${_ppi_pkg_name}'"'.';
 	else
+		rtl_get_var_unsafe \$_ppi_group_fname -u "PKG_${_ppi_pkg_name}_GROUP_FNAME";
 		rtl_get_var_unsafe \$_ppi_pkg_version -u "PKG_${_ppi_pkg_name}_VERSION";
 		rtl_log_env_vars "package_vars" "Package variables" $(rtl_get_vars_unsafe_fast "^PKG_${_ppi_pkg_name_uc}");
-		rtl_log_msgV "info_build_group" "${MSG_info_build_group}" "${_ppi_group_name}";
+		rtl_log_msgV "info_build_group" "${MSG_info_build_group}" "${_ppi_group_name}" "${_ppi_group_fname}";
 
 		if [ "${PKG_DISABLED:-0}" -eq 1 ]; then
 			rtl_log_msgV "info_pkg_disabled" "${MSG_info_pkg_disabled}" "${_ppi_pkg_name}";
@@ -291,7 +292,7 @@ pkgtoolp_mirror() {
 	rtl_subst \$_ppm_mirror_dname "~" "${HOME}";
 	rtl_subst \$_ppm_mirror_dname_git "~" "${HOME}";
 
-	if ! ex_pkg_load_groups \$_ppm_groups \$_ppm_groups_noauto \$GROUP_AUTO \$GROUP_TARGET; then
+	if ! ex_pkg_load_groups \$_ppm_groups \$_ppm_groups_noauto; then
 		_ppm_rc=1;
 		rtl_setrstatus "${_ppm_rstatus}" 'Error: failed to load build groups.';
 	elif [ "${_ppm_mirror_dname:+1}" = 1 ]\
@@ -501,7 +502,7 @@ pkgtoolp_rdepends() {
 		_ppr_pkg_name_rdepend="" _ppr_pkg_names="" _ppr_pkg_rdepends=""		\
 		_ppr_pkg_rdepends_direct="" _ppr_rc=0;
 
-	if ! ex_pkg_load_groups \$_ppr_groups \$_ppr_groups_noauto \$GROUP_AUTO \$GROUP_TARGET; then
+	if ! ex_pkg_load_groups \$_ppr_groups \$_ppr_groups_noauto; then
 		_ppr_rc=1;
 		rtl_setrstatus "${_ppr_rstatus}" 'Error: failed to load build groups.';
 	elif ! ex_pkg_find_package \$_ppr_group_name "${_ppr_groups}" "${_ppr_pkg_name}"; then
@@ -562,7 +563,7 @@ pkgtoolp_tarball() {
 		_ppt_hname="" _ppt_pkg_name_full="" _ppt_pkg_version="" _ppt_rc=0	\
 		_ppt_tarball_fname="";
 
-	if ! ex_pkg_load_groups \$_ppt_groups \$_ppt_groups_noauto \$GROUP_AUTO \$GROUP_TARGET; then
+	if ! ex_pkg_load_groups \$_ppt_groups \$_ppt_groups_noauto; then
 		_ppt_rc=1;
 		rtl_setrstatus "${_ppt_rstatus}" 'Error: failed to load build groups.';
 	elif ! ex_pkg_find_package \$_ppt_group_name "${_ppt_groups}" "${_ppt_pkg_name}"; then
diff --git a/subr.ex/ex_pkg.subr b/subr.ex/ex_pkg.subr
index 041faa4..4d1ae9b 100644
--- a/subr.ex/ex_pkg.subr
+++ b/subr.ex/ex_pkg.subr
@@ -210,42 +210,57 @@ ex_pkg_load_vars() {
 # ex_pkg_load_groups() - load all available build groups
 # @_rgroups:		reference to out variable of build groups
 # @_rgroups_noauoto:	optional reference to out variable of build groups not built automatically
-# @_rgroup_auto:	reference to in variable of flag controlling whether to build group automatically
-# @_rgroup_target:	reference to in variable of build group targets
 #
 # Returns:		zero (0) on success, non-zero (>0) on failure.
 #
 ex_pkg_load_groups() {
 	local	_eplg_rgroups="${1#\$}" _eplg_rgroups_noauto="${2#\$}"		\
-		_eplg_rgroup_auto="${3#\$}" _eplg_rgroup_target="${4#\$}"	\
 		_eplg_build_groups="" _eplg_build_groups_noauto=""		\
-		_eplg_fname="" _eplg_group="" _eplg_groups="";
+		_eplg_fname="" _eplg_group="" _eplg_group_target=""		\
+		_eplg_group_target_uc="" _eplg_group_target_appendfl=0		\
+		_eplg_groups="" _eplg_pkg_name="" _eplg_pkg_names="";
 
 	for _eplg_fname in $(find ./groups -name *.group | sort); do
 		rtl_fileop source_opt "${_eplg_fname}";
 
-		if eval [ \"\${${_eplg_rgroup_target}:+1}\" = 1 ]; then
-			eval _eplg_group=\"\${${_eplg_rgroup_target}}\";
-			eval unset ${_eplg_rgroup_target};
+		_eplg_group="${_eplg_fname##*/}";
+		_eplg_group="${_eplg_group%.group}";
+		_eplg_group="${_eplg_group#*.}";
+
+		if [ "${GROUP_TARGET_APPEND:+1}" = 1 ]; then
+			_eplg_group_target="${GROUP_TARGET_APPEND}";
+			_eplg_group_target_appendfl=1;
+			unset GROUP_TARGET_APPEND;
 		else
-			_eplg_group="${_eplg_fname##*/}";
-			_eplg_group="${_eplg_group%.group}";
-			_eplg_group="${_eplg_group#*.}";
+			_eplg_group_target="${_eplg_group}";
+			_eplg_group_target_appendfl=0;
 		fi;
 
-		if ! rtl_lmatch \$_eplg_groups "${_eplg_group}"; then
-			rtl_lconcat \$_eplg_groups "${_eplg_group}";
-			if eval [ \"\${${_eplg_rgroup_auto}:+1}\" = 1 ]; then
-				if eval [ \"\${${_eplg_rgroup_auto}:-0}\" -ne 0 ]; then
-					rtl_lconcat \$_eplg_build_groups "${_eplg_group}";
+		if ! rtl_lmatch \$_eplg_groups "${_eplg_group_target}"; then
+			rtl_lconcat \$_eplg_groups "${_eplg_group_target}";
+			if eval [ \"\${GROUP_AUTO:+1}\" = 1 ]; then
+				if eval [ \"\${GROUP_AUTO:-0}\" -ne 0 ]; then
+					rtl_lconcat \$_eplg_build_groups "${_eplg_group_target}";
 				else
-					rtl_lconcat \$_eplg_build_groups_noauto "${_eplg_group}";
+					rtl_lconcat \$_eplg_build_groups_noauto "${_eplg_group_target}";
 				fi;
-				eval unset ${_eplg_rgroup_auto};
+				unset GROUP_AUTO;
 			else
-				rtl_lconcat \$_eplg_build_groups "${_eplg_group}";
+				rtl_lconcat \$_eplg_build_groups "${_eplg_group_target}";
 			fi;
 		fi;
+
+		if rtl_get_var_unsafe \$_eplg_pkg_names -u "${_eplg_group}_PACKAGES"\
+		&& [ "${_eplg_pkg_names:+1}" = 1 ]; then
+			if [ "${_eplg_group_target_appendfl}" -eq 1 ]; then
+				rtl_toupper2 \$_eplg_group_target \$_eplg_group_target_uc;
+				rtl_lconcat "\$${_eplg_group_target_uc}_PACKAGES" "${_eplg_pkg_names}";
+			fi;
+
+			for _eplg_pkg_name in ${_eplg_pkg_names}; do
+				rtl_set_var_unsafe -u "PKG_${_eplg_pkg_name}_GROUP_FNAME" "${_eplg_fname}";
+			done;
+		fi;
 	done;
 
 	_eplg_build_groups="$(rtl_uniq "${_eplg_build_groups}")";
diff --git a/subr.rtl/rtl.subr b/subr.rtl/rtl.subr
index 50b7d18..1c51054 100644
--- a/subr.rtl/rtl.subr
+++ b/subr.rtl/rtl.subr
@@ -13,7 +13,6 @@ RTL_NL="
 
 rtl_date() { local _rdate="${1#\$}"; shift; eval ${_rdate}=\"\$\(command date \"+\${1:-\${DEFAULT_TIMESTAMP_FMT:-\"%Y/%m/%d %H:%M:%S\"}}\"\)\"; };
 rtl_set_IFS_nl() { IFS="${RTL_NL}"; };
-rtl_set_var_unsafe() { [ "${2:+1}" = 1 ] && eval ${1}=\"${2}\" || return 0; };
 rtl_test_cmd() { command -v "${1}" >/dev/null; };
 rtl_uniq() { if [ "${#}" -gt 0 ]; then printf "%s" "${*}" | sed 's/ /\n/g' | awk '!x[$0]++' | paste -s -d" "; fi; };
 rtl_uniq2() { eval set -- \${${1#\$}}; if [ "${#}" -gt 0 ]; then printf "%s" "${*}" | sed 's/ /\n/g' | awk '!x[$0]++' | paste -s -d" "; fi; };
diff --git a/subr.rtl/rtl_platform.subr b/subr.rtl/rtl_platform.subr
index 9bcf073..9fc7b01 100644
--- a/subr.rtl/rtl_platform.subr
+++ b/subr.rtl/rtl_platform.subr
@@ -227,4 +227,25 @@ rtl_set_var() {
 	return 0;
 };
 
+#
+# rtl_set_var_unsafe() - set value of variable
+# @[-u]:	optionally convert variable name to upper case
+# @_vname:	variable name
+# @_vval:	variable value
+#
+# Returns:	zero (0) on success, non-zero (>0) on failure
+# N.B.:		This function is *unsafe* and impossible to implement otherwise w/o filtering @_vname
+#		and implicitly allows for code execution and other undefined behaviour via @_vname.
+#		Do *not* pass untrusted input through @_vname.
+rtl_set_var_unsafe() {
+	local _rsvu_vname="" _rsvu_vval="";
+	if [ "x${1}" = "x-u" ]; then
+		shift; _rsvu_vname="${1}"; _rsvu_vval="${2}"; rtl_toupper \$_rsvu_vname;
+	else
+		_rsvu_vname="${1}"; _rsvu_vval="${2}";
+	fi;
+	eval ${_rsvu_vname}='${_rsvu_vval}';
+	return 0;
+};
+
 # vim:filetype=sh textwidth=0