Add separatedebug feature

When separatedebug is set in FEATURES, produce the debug symbols in a separate
tarball.
The resulting tarball is stored in PKGDIR with the extension .debug.tbz2.

BUG=chromium:432294
TEST=`FEATURES=separatedebug emerge-gizmo metrics` works.
/build/gizmo/packages/chromeos-base/metrics-0.0.1-r365.debug.tbz2 is created.
TEST=`emerge-gizmo metrics` works.
TEST=trybot run on daisy, link, gizmo, chromiumos-sdk, duck, lumpy-incremental.

Change-Id: I280cb9682fba1c6cd27f7b4825c1b331dc4729be
Reviewed-on: https://chromium-review.googlesource.com/229173
Reviewed-by: Zac Medico <zmedico@gmail.com>
Tested-by: Zac Medico <zmedico@gmail.com>
Reviewed-by: Bertrand Simonnet <bsimonnet@chromium.org>
Commit-Queue: Bertrand Simonnet <bsimonnet@chromium.org>
diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
index 961738f..b0d8b18 100755
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
@@ -1215,6 +1215,17 @@
 	[ -z "${PORTAGE_BINPKG_TMPFILE}" ] && \
 		die "PORTAGE_BINPKG_TMPFILE is unset"
 	mkdir -p "${PORTAGE_BINPKG_TMPFILE%/*}" || die "mkdir failed"
+
+	if has separatedebug ${FEATURES} && [[ -d "${PROOT%/}${EPREFIX}/usr/lib/debug" ]]; then
+		[[ -z "${PORTAGE_DEBUGSYMBOLS_TMPFILE}" ]] && \
+			die "PORTAGE_DEBUGSYMBOLS_TMPFILE is unset"
+		mkdir -p "${PORTAGE_DEBUGSYMBOLS_TMPFILE%/*}" || die "mkdir failed"
+		tar $tar_options -cf - $PORTAGE_BINPKG_TAR_OPTS \
+			-C "${PROOT}" ".${EPREFIX}/usr/lib/debug/" | \
+		$PORTAGE_BZIP2_COMMAND -c > "$PORTAGE_DEBUGSYMBOLS_TMPFILE"
+		tar_options+=" --anchored --exclude=.${EPREFIX}/usr/lib/debug"
+	fi
+
 	tar $tar_options -cf - $PORTAGE_BINPKG_TAR_OPTS -C "${PROOT}" . | \
 		$PORTAGE_BZIP2_COMMAND -c > "$PORTAGE_BINPKG_TMPFILE"
 	assert "failed to pack binary package: '$PORTAGE_BINPKG_TMPFILE'"
diff --git a/man/make.conf.5 b/man/make.conf.5
index 84e894b..9050ee7 100644
--- a/man/make.conf.5
+++ b/man/make.conf.5
@@ -506,6 +506,11 @@
 .B sandbox
 Enable sandbox\-ing when running \fBemerge\fR(1) and \fBebuild\fR(1).
 .TP
+.B separatedebug
+When splitdebug is enabled, produces a separate tarball containing the debug
+symbols in \fBPKGDIR\fR.
+The debug symbols tarball has the name ${CATEGORY}/${PF}.debug.tbz2.
+.TP
 .B sesandbox
 Enable SELinux sandbox\-ing.  Do not toggle this \fBFEATURE\fR yourself.
 .TP
diff --git a/pym/_emerge/EbuildBinpkg.py b/pym/_emerge/EbuildBinpkg.py
index 34a6aef..902639c 100644
--- a/pym/_emerge/EbuildBinpkg.py
+++ b/pym/_emerge/EbuildBinpkg.py
@@ -3,14 +3,14 @@
 
 from _emerge.CompositeTask import CompositeTask
 from _emerge.EbuildPhase import EbuildPhase
-from portage import os
+from portage import os, xpak
 
 class EbuildBinpkg(CompositeTask):
 	"""
 	This assumes that src_install() has successfully completed.
 	"""
 	__slots__ = ('pkg', 'settings') + \
-		('_binpkg_tmpfile',)
+		('_binpkg_tmpfile', '_symbols_tmpfile')
 
 	def _start(self):
 		pkg = self.pkg
@@ -24,6 +24,12 @@
 		self._binpkg_tmpfile = binpkg_tmpfile
 		self.settings["PORTAGE_BINPKG_TMPFILE"] = self._binpkg_tmpfile
 
+		if 'separatedebug' in self.settings.features:
+			self._symbols_tmpfile = os.path.join(bintree.pkgdir, pkg.cpv \
+										+ '.debug.tbz2')
+			self.settings["PORTAGE_DEBUGSYMBOLS_TMPFILE"] = \
+					self._symbols_tmpfile
+
 		package_phase = EbuildPhase(background=self.background,
 			phase='package', scheduler=self.scheduler,
 			settings=self.settings)
@@ -33,15 +39,25 @@
 	def _package_phase_exit(self, package_phase):
 
 		self.settings.pop("PORTAGE_BINPKG_TMPFILE", None)
+		self.settings.pop("PORTAGE_DEBUGSYMBOLS_TMPFILE", None)
 		if self._default_exit(package_phase) != os.EX_OK:
 			try:
 				os.unlink(self._binpkg_tmpfile)
 			except OSError:
 				pass
+			try:
+				os.unlink(self._symbols_tmpfile)
+			except OSError:
+				pass
 			self.wait()
 			return
 
 		pkg = self.pkg
+		if self._symbols_tmpfile and os.path.isfile(self._symbols_tmpfile):
+			xpak_data = xpak.xpak_mem({ "CATEGORY": pkg.category,
+							  "PF": pkg.pf + "-debug",
+							  "SLOT": pkg._metadata['SLOT'] })
+			xpak.tbz2(self._symbols_tmpfile).recompose_mem(xpak_data)
 		bintree = pkg.root_config.trees["bintree"]
 		bintree.inject(pkg.cpv, filename=self._binpkg_tmpfile)
 
diff --git a/pym/portage/const.py b/pym/portage/const.py
index f2e69e0..fa7bd66 100644
--- a/pym/portage/const.py
+++ b/pym/portage/const.py
@@ -173,6 +173,7 @@
 	"python-trace",
 	"sandbox",
 	"selinux",
+	"separatedebug",
 	"sesandbox",
 	"sfperms",
 	"sign",
diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py
index 8803491..55754d9 100644
--- a/pym/portage/package/ebuild/_config/special_env_vars.py
+++ b/pym/portage/package/ebuild/_config/special_env_vars.py
@@ -52,7 +52,7 @@
 	"PORTAGE_ACTUAL_DISTDIR", "PORTAGE_ARCHLIST", "PORTAGE_BASHRC_FILES",
 	"PORTAGE_BASHRC", "PM_EBUILD_HOOK_DIR",
 	"PORTAGE_BINPKG_FILE", "PORTAGE_BINPKG_TAR_OPTS",
-	"PORTAGE_BINPKG_TMPFILE",
+	"PORTAGE_BINPKG_TMPFILE", "PORTAGE_DEBUGSYMBOLS_TMPFILE",
 	"PORTAGE_BIN_PATH",
 	"PORTAGE_BUILDDIR", "PORTAGE_BUILD_GROUP", "PORTAGE_BUILD_USER",
 	"PORTAGE_BUNZIP2_COMMAND", "PORTAGE_BZIP2_COMMAND",