Igor Gnatenko 082d5d
From bc5c404e7415108f15a8cd5e8514a74b43a7755a Mon Sep 17 00:00:00 2001
Igor Gnatenko 082d5d
From: Michael Schroeder <mls@suse.de>
Igor Gnatenko 082d5d
Date: Fri, 24 Mar 2017 15:35:23 +0100
Igor Gnatenko 082d5d
Subject: [PATCH 37/49] Support debuginfo subpackages
Igor Gnatenko 082d5d
Igor Gnatenko 082d5d
We do this by filtering the debuginfo files generated by find-debuginfo.sh
Igor Gnatenko 082d5d
with the files from the (sub)packages.
Igor Gnatenko 082d5d
Igor Gnatenko 082d5d
This commit is heavily based on a patch by Richard Biener.
Igor Gnatenko 082d5d
Igor Gnatenko 082d5d
(cherry picked from commit 980749fdce055254ca92ee7e2595b16750b699a2)
Igor Gnatenko 082d5d
Igor Gnatenko 082d5d
Conflicts:
Igor Gnatenko 082d5d
	build/files.c
Igor Gnatenko 082d5d
---
Igor Gnatenko 082d5d
 build/files.c             | 285 ++++++++++++++++++++++++++++++++++++++++++++--
Igor Gnatenko 082d5d
 build/parsePreamble.c     |  10 +-
Igor Gnatenko 082d5d
 build/parseSpec.c         |   2 +-
Igor Gnatenko 082d5d
 build/rpmbuild_internal.h |  17 +++
Igor Gnatenko 082d5d
 macros.in                 |   3 +
Igor Gnatenko 082d5d
 5 files changed, 304 insertions(+), 13 deletions(-)
Igor Gnatenko 082d5d
Igor Gnatenko 082d5d
diff --git a/build/files.c b/build/files.c
Igor Gnatenko 082d5d
index 2f02587f0..779a2a102 100644
Igor Gnatenko 082d5d
--- a/build/files.c
Igor Gnatenko 082d5d
+++ b/build/files.c
Igor Gnatenko 082d5d
@@ -40,6 +40,16 @@
Igor Gnatenko 082d5d
 #define	SKIPWHITE(_x)	{while(*(_x) && (risspace(*_x) || *(_x) == ',')) (_x)++;}
Igor Gnatenko 082d5d
 #define	SKIPNONWHITE(_x){while(*(_x) &&!(risspace(*_x) || *(_x) == ',')) (_x)++;}
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
+/* the following defines must be in sync with the equally hardcoded paths from
Igor Gnatenko 082d5d
+ * scripts/find-debuginfo.sh
Igor Gnatenko 082d5d
+ */
Igor Gnatenko 082d5d
+#define BUILD_ID_DIR		"/usr/lib/.build-id"
Igor Gnatenko 082d5d
+#define DEBUG_SRC_DIR		"/usr/src/debug"
Igor Gnatenko 082d5d
+#define DEBUG_LIB_DIR		"/usr/lib/debug"
Igor Gnatenko 082d5d
+#define DEBUG_LIB_PREFIX	"/usr/lib/debug/"
Igor Gnatenko 082d5d
+#define DEBUG_ID_DIR		"/usr/lib/debug/.build-id"
Igor Gnatenko 082d5d
+#define DEBUG_DWZ_DIR 		"/usr/lib/debug/.dwz"
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
 /**
Igor Gnatenko 082d5d
  */
Igor Gnatenko 082d5d
 enum specfFlags_e {
Igor Gnatenko 082d5d
@@ -1702,9 +1712,8 @@ static int generateBuildIDs(FileList fl)
Igor Gnatenko 082d5d
 	if (lstat(flp->diskPath, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) {
Igor Gnatenko 082d5d
 	    /* We determine whether this is a main or
Igor Gnatenko 082d5d
 	       debug ELF based on path.  */
Igor Gnatenko 082d5d
-	    #define DEBUGPATH "/usr/lib/debug/"
Igor Gnatenko 082d5d
 	    int isDbg = strncmp (flp->cpioPath,
Igor Gnatenko 082d5d
-				 DEBUGPATH, strlen (DEBUGPATH)) == 0;
Igor Gnatenko 082d5d
+				 DEBUG_LIB_PREFIX, strlen (DEBUG_LIB_PREFIX)) == 0;
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
 	    /* For the main package files mimic what find-debuginfo.sh does.
Igor Gnatenko 082d5d
 	       Only check build-ids for executable files. Debug files are
Igor Gnatenko 082d5d
@@ -1797,8 +1806,6 @@ static int generateBuildIDs(FileList fl)
Igor Gnatenko 082d5d
 	if (rc == 0) {
Igor Gnatenko 082d5d
 	    char *attrstr;
Igor Gnatenko 082d5d
 	    /* Add .build-id directories to hold the subdirs/symlinks.  */
Igor Gnatenko 082d5d
-            #define BUILD_ID_DIR "/usr/lib/.build-id"
Igor Gnatenko 082d5d
-            #define DEBUG_ID_DIR "/usr/lib/debug/.build-id"
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
 	    mainiddir = rpmGetPath(fl->buildRoot, BUILD_ID_DIR, NULL);
Igor Gnatenko 082d5d
 	    debugiddir = rpmGetPath(fl->buildRoot, DEBUG_ID_DIR, NULL);
Igor Gnatenko 082d5d
@@ -1864,8 +1871,8 @@ static int generateBuildIDs(FileList fl)
Igor Gnatenko 082d5d
 	    /* Don't add anything more when an error occured. But do
Igor Gnatenko 082d5d
 	       cleanup.  */
Igor Gnatenko 082d5d
 	    if (rc == 0) {
Igor Gnatenko 082d5d
-		int isDbg = strncmp (paths[i], DEBUGPATH,
Igor Gnatenko 082d5d
-				     strlen (DEBUGPATH)) == 0;
Igor Gnatenko 082d5d
+		int isDbg = strncmp (paths[i], DEBUG_LIB_PREFIX,
Igor Gnatenko 082d5d
+				     strlen (DEBUG_LIB_PREFIX)) == 0;
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
 		char *buildidsubdir;
Igor Gnatenko 082d5d
 		char subdir[4];
Igor Gnatenko 082d5d
@@ -1967,7 +1974,7 @@ static int generateBuildIDs(FileList fl)
Igor Gnatenko 082d5d
 			       which don't end in ".debug". */
Igor Gnatenko 082d5d
 			    int pathlen = strlen(paths[i]);
Igor Gnatenko 082d5d
 			    int debuglen = strlen(".debug");
Igor Gnatenko 082d5d
-			    int prefixlen = strlen("/usr/lib/debug");
Igor Gnatenko 082d5d
+			    int prefixlen = strlen(DEBUG_LIB_DIR);
Igor Gnatenko 082d5d
 			    int vralen = vra == NULL ? 0 : strlen(vra);
Igor Gnatenko 082d5d
 			    if (pathlen > prefixlen + debuglen + vralen
Igor Gnatenko 082d5d
 				&& strcmp ((paths[i] + pathlen - debuglen),
Igor Gnatenko 082d5d
@@ -2621,24 +2628,273 @@ exit:
Igor Gnatenko 082d5d
     return rc;
Igor Gnatenko 082d5d
 }
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
+static rpmTag copyTagsFromMainDebug[] = {
Igor Gnatenko 082d5d
+    RPMTAG_ARCH,
Igor Gnatenko 082d5d
+    RPMTAG_SUMMARY,
Igor Gnatenko 082d5d
+    RPMTAG_DESCRIPTION,
Igor Gnatenko 082d5d
+    RPMTAG_GROUP,
Igor Gnatenko 082d5d
+    /* see addTargets */
Igor Gnatenko 082d5d
+    RPMTAG_OS,
Igor Gnatenko 082d5d
+    RPMTAG_PLATFORM,
Igor Gnatenko 082d5d
+    RPMTAG_OPTFLAGS,
Igor Gnatenko 082d5d
+};
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/* this is a hack: patch the summary and the description to include
Igor Gnatenko 082d5d
+ * the correct package name */
Igor Gnatenko 082d5d
+static void patchDebugPackageString(Package dbg, rpmTag tag, Package pkg, Package mainpkg)
Igor Gnatenko 082d5d
+{
Igor Gnatenko 082d5d
+    const char *oldname, *newname, *old;
Igor Gnatenko 082d5d
+    char *oldsubst = NULL, *newsubst = NULL, *p;
Igor Gnatenko 082d5d
+    oldname = headerGetString(mainpkg->header, RPMTAG_NAME);
Igor Gnatenko 082d5d
+    newname = headerGetString(pkg->header, RPMTAG_NAME);
Igor Gnatenko 082d5d
+    rasprintf(&oldsubst, "package %s", oldname);
Igor Gnatenko 082d5d
+    rasprintf(&newsubst, "package %s", newname);
Igor Gnatenko 082d5d
+    old = headerGetString(dbg->header, tag);
Igor Gnatenko 082d5d
+    p = old ? strstr(old, oldsubst) : NULL;
Igor Gnatenko 082d5d
+    if (p) {
Igor Gnatenko 082d5d
+	char *new = NULL;
Igor Gnatenko 082d5d
+	rasprintf(&new, "%.*s%s%s", (int)(p - old), old, newsubst, p + strlen(oldsubst));
Igor Gnatenko 082d5d
+	headerDel(dbg->header, tag);
Igor Gnatenko 082d5d
+	headerPutString(dbg->header, tag, new);
Igor Gnatenko 082d5d
+	_free(new);
Igor Gnatenko 082d5d
+    }
Igor Gnatenko 082d5d
+    _free(oldsubst);
Igor Gnatenko 082d5d
+    _free(newsubst);
Igor Gnatenko 082d5d
+}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/* create a new debuginfo subpackage for package pkg from the
Igor Gnatenko 082d5d
+ * main debuginfo package */
Igor Gnatenko 082d5d
+static Package cloneDebuginfoPackage(rpmSpec spec, Package pkg, Package maindbg)
Igor Gnatenko 082d5d
+{
Igor Gnatenko 082d5d
+    const char *name = headerGetString(pkg->header, RPMTAG_NAME);
Igor Gnatenko 082d5d
+    char *dbgname = NULL;
Igor Gnatenko 082d5d
+    Package dbg;
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    rasprintf(&dbgname, "%s-%s", name, "debuginfo");
Igor Gnatenko 082d5d
+    dbg = newPackage(dbgname, spec->pool, &spec->packages);
Igor Gnatenko 082d5d
+    headerPutString(dbg->header, RPMTAG_NAME, dbgname);
Igor Gnatenko 082d5d
+    copyInheritedTags(dbg->header, pkg->header);
Igor Gnatenko 082d5d
+    headerDel(dbg->header, RPMTAG_GROUP);
Igor Gnatenko 082d5d
+    headerCopyTags(maindbg->header, dbg->header, copyTagsFromMainDebug);
Igor Gnatenko 082d5d
+    dbg->autoReq = maindbg->autoReq;
Igor Gnatenko 082d5d
+    dbg->autoProv = maindbg->autoProv;
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    /* patch summary and description strings */
Igor Gnatenko 082d5d
+    patchDebugPackageString(dbg, RPMTAG_SUMMARY, pkg, spec->packages);
Igor Gnatenko 082d5d
+    patchDebugPackageString(dbg, RPMTAG_DESCRIPTION, pkg, spec->packages);
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    /* Add self-provides (normally done by addTargets) */
Igor Gnatenko 082d5d
+    addPackageProvides(dbg);
Igor Gnatenko 082d5d
+    dbg->ds = rpmdsThis(dbg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL);
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    _free(dbgname);
Igor Gnatenko 082d5d
+    return dbg;
Igor Gnatenko 082d5d
+}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/* add a directory to the file list */
Igor Gnatenko 082d5d
+static void argvAddDir(ARGV_t *filesp, const char *dir)
Igor Gnatenko 082d5d
+{
Igor Gnatenko 082d5d
+    char *line = NULL;
Igor Gnatenko 082d5d
+    rasprintf(&line, "%%dir %s", dir);
Igor Gnatenko 082d5d
+    argvAdd(filesp, line);
Igor Gnatenko 082d5d
+    _free(line);
Igor Gnatenko 082d5d
+}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/* collect the debug files for package pkg and put them into
Igor Gnatenko 082d5d
+ * a (possibly new) debuginfo subpackage */
Igor Gnatenko 082d5d
+static void filterDebuginfoPackage(rpmSpec spec, Package pkg,
Igor Gnatenko 082d5d
+		Package maindbg, char *buildroot, char *uniquearch)
Igor Gnatenko 082d5d
+{
Igor Gnatenko 082d5d
+    rpmfi fi;
Igor Gnatenko 082d5d
+    ARGV_t files = NULL;
Igor Gnatenko 082d5d
+    Package dbg = NULL;
Igor Gnatenko 082d5d
+    char *path = NULL;
Igor Gnatenko 082d5d
+    size_t buildrootlen = strlen(buildroot);
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    /* ignore noarch subpackages */
Igor Gnatenko 082d5d
+    if (rstreq(headerGetString(pkg->header, RPMTAG_ARCH), "noarch"))
Igor Gnatenko 082d5d
+	return;
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    if (!uniquearch)
Igor Gnatenko 082d5d
+	uniquearch = "";
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    fi = rpmfilesIter(pkg->cpioList, RPMFI_ITER_FWD);
Igor Gnatenko 082d5d
+    /* Check if the current package has files with debug info
Igor Gnatenko 082d5d
+       and add them to the file list */
Igor Gnatenko 082d5d
+    fi = rpmfiInit(fi, 0);
Igor Gnatenko 082d5d
+    while (rpmfiNext(fi) >= 0) {
Igor Gnatenko 082d5d
+	const char *name = rpmfiFN(fi);
Igor Gnatenko 082d5d
+	int namel = strlen(name);
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+	/* strip trailing .debug like in find-debuginfo.sh */
Igor Gnatenko 082d5d
+	namel = strlen(name);
Igor Gnatenko 082d5d
+	if (namel > 6 && !strcmp(name + namel - 6, ".debug"))
Igor Gnatenko 082d5d
+	    namel -= 6;
Igor Gnatenko 082d5d
+	
Igor Gnatenko 082d5d
+	/* generate path */
Igor Gnatenko 082d5d
+	rasprintf(&path, "%s%s%.*s%s.debug", buildroot, DEBUG_LIB_DIR, namel, name, uniquearch);
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+	/* If that file exists we have debug information for it */
Igor Gnatenko 082d5d
+	if (access(path, F_OK) == 0) {
Igor Gnatenko 082d5d
+	    /* Append the file list preamble */
Igor Gnatenko 082d5d
+	    if (!files) {
Igor Gnatenko 082d5d
+		argvAdd(&files, "%defattr(-,root,root)");
Igor Gnatenko 082d5d
+		argvAddDir(&files, DEBUG_LIB_DIR);
Igor Gnatenko 082d5d
+	    }
Igor Gnatenko 082d5d
+	    /* Add the files main debug-info file */
Igor Gnatenko 082d5d
+	    argvAdd(&files, path + buildrootlen);
Igor Gnatenko 082d5d
+	}
Igor Gnatenko 082d5d
+	path = _free(path);
Igor Gnatenko 082d5d
+    }
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    if (files) {
Igor Gnatenko 082d5d
+	/* we have collected some files. Now put them in a debuginfo
Igor Gnatenko 082d5d
+         * package. If this is not the main package, clone the main
Igor Gnatenko 082d5d
+         * debuginfo package */
Igor Gnatenko 082d5d
+	if (pkg == spec->packages)
Igor Gnatenko 082d5d
+	    maindbg->fileList = files;
Igor Gnatenko 082d5d
+	else {
Igor Gnatenko 082d5d
+	    Package dbg = cloneDebuginfoPackage(spec, pkg, maindbg);
Igor Gnatenko 082d5d
+	    dbg->fileList = files;
Igor Gnatenko 082d5d
+	}
Igor Gnatenko 082d5d
+    }
Igor Gnatenko 082d5d
+}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/* add the debug dwz files to package pkg.
Igor Gnatenko 082d5d
+ * return 1 if something was added, 0 otherwise. */
Igor Gnatenko 082d5d
+static int addDebugDwz(Package pkg, char *buildroot)
Igor Gnatenko 082d5d
+{
Igor Gnatenko 082d5d
+    int ret = 0;
Igor Gnatenko 082d5d
+    char *path = NULL;
Igor Gnatenko 082d5d
+    struct stat sbuf;
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    rasprintf(&path, "%s%s", buildroot, DEBUG_DWZ_DIR);
Igor Gnatenko 082d5d
+    if (lstat(path, &sbuf) == 0 && S_ISDIR(sbuf.st_mode)) {
Igor Gnatenko 082d5d
+	if (!pkg->fileList) {
Igor Gnatenko 082d5d
+	    argvAdd(&pkg->fileList, "%defattr(-,root,root)");
Igor Gnatenko 082d5d
+	    argvAddDir(&pkg->fileList, DEBUG_LIB_DIR);
Igor Gnatenko 082d5d
+	}
Igor Gnatenko 082d5d
+	argvAdd(&pkg->fileList, DEBUG_DWZ_DIR);
Igor Gnatenko 082d5d
+	ret = 1;
Igor Gnatenko 082d5d
+    }
Igor Gnatenko 082d5d
+    path = _free(path);
Igor Gnatenko 082d5d
+    return ret;
Igor Gnatenko 082d5d
+}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/* add the debug source files to package pkg.
Igor Gnatenko 082d5d
+ * return 1 if something was added, 0 otherwise. */
Igor Gnatenko 082d5d
+static int addDebugSrc(Package pkg, char *buildroot)
Igor Gnatenko 082d5d
+{
Igor Gnatenko 082d5d
+    int ret = 0;
Igor Gnatenko 082d5d
+    char *path = NULL;
Igor Gnatenko 082d5d
+    DIR *d;
Igor Gnatenko 082d5d
+    struct dirent *de;
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    /* not needed if we have an extra debugsource subpackage */
Igor Gnatenko 082d5d
+    if (rpmExpandNumeric("%{?_debugsource_packages}"))
Igor Gnatenko 082d5d
+	return 0;
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+    rasprintf(&path, "%s%s", buildroot, DEBUG_SRC_DIR);
Igor Gnatenko 082d5d
+    d = opendir(path);
Igor Gnatenko 082d5d
+    path = _free(path);
Igor Gnatenko 082d5d
+    if (d) {
Igor Gnatenko 082d5d
+	while ((de = readdir(d)) != NULL) {
Igor Gnatenko 082d5d
+	    if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
Igor Gnatenko 082d5d
+		continue;
Igor Gnatenko 082d5d
+	    rasprintf(&path, "%s/%s", DEBUG_SRC_DIR, de->d_name);
Igor Gnatenko 082d5d
+	    if (!pkg->fileList)
Igor Gnatenko 082d5d
+		argvAdd(&pkg->fileList, "%defattr(-,root,root)");
Igor Gnatenko 082d5d
+	    argvAdd(&pkg->fileList, path);
Igor Gnatenko 082d5d
+	    path = _free(path);
Igor Gnatenko 082d5d
+	    ret = 1;
Igor Gnatenko 082d5d
+	}
Igor Gnatenko 082d5d
+	closedir(d);
Igor Gnatenko 082d5d
+    }
Igor Gnatenko 082d5d
+    return ret;
Igor Gnatenko 082d5d
+}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/* find the main debuginfo package. We do this simply by
Igor Gnatenko 082d5d
+ * searching for a package with the right name. */
Igor Gnatenko 082d5d
+static Package findDebuginfoPackage(rpmSpec spec)
Igor Gnatenko 082d5d
+{
Igor Gnatenko 082d5d
+    Package pkg = NULL;
Igor Gnatenko 082d5d
+    if (lookupPackage(spec, "debuginfo", PART_SUBNAME, &pkg))
Igor Gnatenko 082d5d
+	return NULL;
Igor Gnatenko 082d5d
+    return pkg && pkg->fileList ? pkg : NULL;
Igor Gnatenko 082d5d
+}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/* add a requires for package "to" into package "from". */
Igor Gnatenko 082d5d
+static void addPackageRequires(Package from, Package to)
Igor Gnatenko 082d5d
+{
Igor Gnatenko 082d5d
+    const char *name;
Igor Gnatenko 082d5d
+    char *evr, *isaprov;
Igor Gnatenko 082d5d
+    name = headerGetString(to->header, RPMTAG_NAME);
Igor Gnatenko 082d5d
+    evr = headerGetAsString(to->header, RPMTAG_EVR);
Igor Gnatenko 082d5d
+    isaprov = rpmExpand(name, "%{?_isa}", NULL);
Igor Gnatenko 082d5d
+    addReqProv(from, RPMTAG_REQUIRENAME, isaprov, evr, RPMSENSE_EQUAL, 0);
Igor Gnatenko 082d5d
+    free(isaprov);
Igor Gnatenko 082d5d
+    free(evr);
Igor Gnatenko 082d5d
+}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
 rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
Igor Gnatenko 082d5d
 			int installSpecialDoc, int test)
Igor Gnatenko 082d5d
 {
Igor Gnatenko 082d5d
     Package pkg;
Igor Gnatenko 082d5d
     rpmRC rc = RPMRC_OK;
Igor Gnatenko 082d5d
+    char *buildroot;
Igor Gnatenko 082d5d
+    char *uniquearch = NULL;
Igor Gnatenko 082d5d
+    Package maindbg = NULL;		/* the (existing) main debuginfo package */
Igor Gnatenko 082d5d
+    Package deplink = NULL;		/* create requires to this package */
Igor Gnatenko 082d5d
     
Igor Gnatenko 082d5d
 #if HAVE_LIBDW
Igor Gnatenko 082d5d
     elf_version (EV_CURRENT);
Igor Gnatenko 082d5d
 #endif
Igor Gnatenko 082d5d
     check_fileList = newStringBuf();
Igor Gnatenko 082d5d
     genSourceRpmName(spec);
Igor Gnatenko 082d5d
+    buildroot = rpmGenPath(spec->rootDir, spec->buildRoot, NULL);
Igor Gnatenko 082d5d
     
Igor Gnatenko 082d5d
+    if (rpmExpandNumeric("%{?_debuginfo_subpackages}")) {
Igor Gnatenko 082d5d
+	maindbg = findDebuginfoPackage(spec);
Igor Gnatenko 082d5d
+	if (maindbg) {
Igor Gnatenko 082d5d
+	    /* move debuginfo package to back */
Igor Gnatenko 082d5d
+	    if (maindbg->next) {
Igor Gnatenko 082d5d
+		Package *pp;
Igor Gnatenko 082d5d
+		/* dequeue */
Igor Gnatenko 082d5d
+		for (pp = &spec->packages; *pp != maindbg; pp = &(*pp)->next)
Igor Gnatenko 082d5d
+		    ;
Igor Gnatenko 082d5d
+		*pp = maindbg->next;
Igor Gnatenko 082d5d
+		maindbg->next = 0;
Igor Gnatenko 082d5d
+		/* enqueue at tail */
Igor Gnatenko 082d5d
+		for (; *pp; pp = &(*pp)->next)
Igor Gnatenko 082d5d
+		    ;
Igor Gnatenko 082d5d
+		*pp = maindbg;
Igor Gnatenko 082d5d
+	    }
Igor Gnatenko 082d5d
+	    /* delete unsplit file list, we will re-add files back later */
Igor Gnatenko 082d5d
+	    maindbg->fileFile = argvFree(maindbg->fileFile);
Igor Gnatenko 082d5d
+	    maindbg->fileList = argvFree(maindbg->fileList);
Igor Gnatenko 082d5d
+	    if (rpmExpandNumeric("%{?_unique_debug_names}"))
Igor Gnatenko 082d5d
+		uniquearch = rpmExpand("-%{VERSION}-%{RELEASE}.%{_arch}", NULL);
Igor Gnatenko 082d5d
+	}
Igor Gnatenko 082d5d
+    }
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
     for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
Igor Gnatenko 082d5d
 	char *nvr;
Igor Gnatenko 082d5d
 	const char *a;
Igor Gnatenko 082d5d
 	int header_color;
Igor Gnatenko 082d5d
 	int arch_color;
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
+	if (pkg == maindbg) {
Igor Gnatenko 082d5d
+	    /* if there is just one debuginfo package, we put our extra stuff
Igor Gnatenko 082d5d
+	     * in it. Otherwise we put it in the main debug package */
Igor Gnatenko 082d5d
+	    Package extradbg = !maindbg->fileList && maindbg->next && !maindbg->next->next ?
Igor Gnatenko 082d5d
+		 maindbg->next : maindbg;
Igor Gnatenko 082d5d
+	    if (addDebugDwz(extradbg, buildroot))
Igor Gnatenko 082d5d
+		deplink = extradbg;
Igor Gnatenko 082d5d
+	    if (addDebugSrc(extradbg, buildroot))
Igor Gnatenko 082d5d
+		deplink = extradbg;
Igor Gnatenko 082d5d
+	    maindbg = NULL;	/* all normal packages processed */
Igor Gnatenko 082d5d
+	}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
 	if (pkg->fileList == NULL)
Igor Gnatenko 082d5d
 	    continue;
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
@@ -2647,9 +2903,16 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
Igor Gnatenko 082d5d
 	nvr = headerGetAsString(pkg->header, RPMTAG_NVRA);
Igor Gnatenko 082d5d
 	rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), nvr);
Igor Gnatenko 082d5d
 	free(nvr);
Igor Gnatenko 082d5d
-		   
Igor Gnatenko 082d5d
-	if ((rc = processPackageFiles(spec, pkgFlags, pkg, installSpecialDoc, test)) != RPMRC_OK ||
Igor Gnatenko 082d5d
-	    (rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK)
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+	if ((rc = processPackageFiles(spec, pkgFlags, pkg, installSpecialDoc, test)) != RPMRC_OK)
Igor Gnatenko 082d5d
+	    goto exit;
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+	if (maindbg)
Igor Gnatenko 082d5d
+	    filterDebuginfoPackage(spec, pkg, maindbg, buildroot, uniquearch);
Igor Gnatenko 082d5d
+	else if (deplink && pkg != deplink)
Igor Gnatenko 082d5d
+	    addPackageRequires(pkg, deplink);
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+        if ((rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK)
Igor Gnatenko 082d5d
 	    goto exit;
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
 	a = headerGetString(pkg->header, RPMTAG_ARCH);
Igor Gnatenko 082d5d
@@ -2684,6 +2947,8 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
Igor Gnatenko 082d5d
     }
Igor Gnatenko 082d5d
 exit:
Igor Gnatenko 082d5d
     check_fileList = freeStringBuf(check_fileList);
Igor Gnatenko 082d5d
+    _free(buildroot);
Igor Gnatenko 082d5d
+    _free(uniquearch);
Igor Gnatenko 082d5d
     
Igor Gnatenko 082d5d
     return rc;
Igor Gnatenko 082d5d
 }
Igor Gnatenko 082d5d
diff --git a/build/parsePreamble.c b/build/parsePreamble.c
Igor Gnatenko 082d5d
index 6be440369..3bb833cff 100644
Igor Gnatenko 082d5d
--- a/build/parsePreamble.c
Igor Gnatenko 082d5d
+++ b/build/parsePreamble.c
Igor Gnatenko 082d5d
@@ -544,6 +544,13 @@ static void fillOutMainPackage(Header h)
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
 /**
Igor Gnatenko 082d5d
  */
Igor Gnatenko 082d5d
+void copyInheritedTags(Header h, Header fromh)
Igor Gnatenko 082d5d
+{
Igor Gnatenko 082d5d
+    headerCopyTags(fromh, h, (rpmTagVal *)copyTagsDuringParse);
Igor Gnatenko 082d5d
+}
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/**
Igor Gnatenko 082d5d
+ */
Igor Gnatenko 082d5d
 static rpmRC readIcon(Header h, const char * file)
Igor Gnatenko 082d5d
 {
Igor Gnatenko 082d5d
     char *fn = NULL;
Igor Gnatenko 082d5d
@@ -1171,8 +1178,7 @@ int parsePreamble(rpmSpec spec, int initialPackage)
Igor Gnatenko 082d5d
     }
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
     if (pkg != spec->packages) {
Igor Gnatenko 082d5d
-	headerCopyTags(spec->packages->header, pkg->header,
Igor Gnatenko 082d5d
-			(rpmTagVal *)copyTagsDuringParse);
Igor Gnatenko 082d5d
+	copyInheritedTags(pkg->header, spec->packages->header);
Igor Gnatenko 082d5d
     }
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
     if (checkForRequired(pkg->header, NVR)) {
Igor Gnatenko 082d5d
diff --git a/build/parseSpec.c b/build/parseSpec.c
Igor Gnatenko 082d5d
index 9fff0e2c8..582060770 100644
Igor Gnatenko 082d5d
--- a/build/parseSpec.c
Igor Gnatenko 082d5d
+++ b/build/parseSpec.c
Igor Gnatenko 082d5d
@@ -564,7 +564,7 @@ static void initSourceHeader(rpmSpec spec)
Igor Gnatenko 082d5d
 }
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
 /* Add extra provides to package.  */
Igor Gnatenko 082d5d
-static void addPackageProvides(Package pkg)
Igor Gnatenko 082d5d
+void addPackageProvides(Package pkg)
Igor Gnatenko 082d5d
 {
Igor Gnatenko 082d5d
     const char *arch, *name;
Igor Gnatenko 082d5d
     char *evr, *isaprov;
Igor Gnatenko 082d5d
diff --git a/build/rpmbuild_internal.h b/build/rpmbuild_internal.h
Igor Gnatenko 082d5d
index 7dd577f26..7ec05b9c9 100644
Igor Gnatenko 082d5d
--- a/build/rpmbuild_internal.h
Igor Gnatenko 082d5d
+++ b/build/rpmbuild_internal.h
Igor Gnatenko 082d5d
@@ -442,6 +442,13 @@ int addReqProv(Package pkg, rpmTagVal tagN,
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
 /** \ingroup rpmbuild
Igor Gnatenko 082d5d
+ * Add self-provides to package.
Igor Gnatenko 082d5d
+ * @param pkg		package
Igor Gnatenko 082d5d
+ */
Igor Gnatenko 082d5d
+RPM_GNUC_INTERNAL
Igor Gnatenko 082d5d
+void addPackageProvides(Package pkg);
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/** \ingroup rpmbuild
Igor Gnatenko 082d5d
  * Add rpmlib feature dependency.
Igor Gnatenko 082d5d
  * @param pkg		package
Igor Gnatenko 082d5d
  * @param feature	rpm feature name (i.e. "rpmlib(Foo)" for feature Foo)
Igor Gnatenko 082d5d
@@ -453,6 +460,16 @@ int rpmlibNeedsFeature(Package pkg, const char * feature, const char * featureEV
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
 RPM_GNUC_INTERNAL
Igor Gnatenko 082d5d
 rpmRC checkForEncoding(Header h, int addtag);
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
+/** \ingroup rpmbuild
Igor Gnatenko 082d5d
+ * Copy tags inherited by subpackages from the source header to the target header
Igor Gnatenko 082d5d
+ * @param h		target header
Igor Gnatenko 082d5d
+ * @param fromh		source header
Igor Gnatenko 082d5d
+ */
Igor Gnatenko 082d5d
+RPM_GNUC_INTERNAL
Igor Gnatenko 082d5d
+void copyInheritedTags(Header h, Header fromh);
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
 #ifdef __cplusplus
Igor Gnatenko 082d5d
 }
Igor Gnatenko 082d5d
 #endif
Igor Gnatenko 082d5d
diff --git a/macros.in b/macros.in
Igor Gnatenko 082d5d
index d104ad5a7..0c055a7fd 100644
Igor Gnatenko 082d5d
--- a/macros.in
Igor Gnatenko 082d5d
+++ b/macros.in
Igor Gnatenko 082d5d
@@ -539,6 +539,9 @@ package or when debugging this package.\
Igor Gnatenko 082d5d
 # Whether rpm should put debug source files into its own subpackage
Igor Gnatenko 082d5d
 #%_debugsource_packages	1
Igor Gnatenko 082d5d
 
Igor Gnatenko 082d5d
+# Whether rpm should create extra debuginfo packages for each subpackage
Igor Gnatenko 082d5d
+#%_debuginfo_subpackages 1
Igor Gnatenko 082d5d
+
Igor Gnatenko 082d5d
 #
Igor Gnatenko 082d5d
 # Use internal dependency generator rather than external helpers?
Igor Gnatenko 082d5d
 %_use_internal_dependency_generator	1
Igor Gnatenko 082d5d
-- 
Igor Gnatenko 082d5d
2.13.2
Igor Gnatenko 082d5d