The attached patch makes rpm create debuginfo subpackage for each subpackage that contains files with debug data.
This is pretty much a complete rewrite of the old SUSE patch, so this needs a review. As this is off by default it can't break anything. Cheers, Michael. -- Michael Schroeder m...@suse.de SUSE LINUX GmbH, GF Jeff Hawn, HRB 16746 AG Nuernberg main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);}
>From 86a3bb4918b6fefff5f8ded6c462015cf8217b55 Mon Sep 17 00:00:00 2001 From: Michael Schroeder <m...@suse.de> Date: Fri, 24 Mar 2017 15:35:23 +0100 Subject: [PATCH 2/2] Support debuginfo subpackages We do this by filtering the debuginfo files generated by find-debuginfo.sh with the files from the (sub)packages. --- build/files.c | 276 +++++++++++++++++++++++++++++++++++++++++++++- build/parseSpec.c | 2 +- build/rpmbuild_internal.h | 7 ++ macros.in | 3 + 4 files changed, 284 insertions(+), 4 deletions(-) diff --git a/build/files.c b/build/files.c index f58569e..d06a0f3 100644 --- a/build/files.c +++ b/build/files.c @@ -2659,24 +2659,285 @@ exit: return rc; } +static rpmTag copyTagsForDebug[] = { + /* see copyTagsDuringParse */ + RPMTAG_EPOCH, + RPMTAG_VERSION, + RPMTAG_RELEASE, + RPMTAG_LICENSE, + RPMTAG_PACKAGER, + RPMTAG_DISTRIBUTION, + RPMTAG_DISTURL, + RPMTAG_VENDOR, + RPMTAG_ICON, + RPMTAG_URL, + RPMTAG_VCS, + RPMTAG_CHANGELOGTIME, + RPMTAG_CHANGELOGNAME, + RPMTAG_CHANGELOGTEXT, + RPMTAG_PREFIXES, + RPMTAG_DISTTAG, + RPMTAG_BUGURL, + 0 +}; + +static rpmTag copyTagsForDebugMain[] = { + RPMTAG_ARCH, + RPMTAG_SUMMARY, + RPMTAG_DESCRIPTION, + RPMTAG_GROUP, + /* see addTargets */ + RPMTAG_OS, + RPMTAG_PLATFORM, + RPMTAG_OPTFLAGS, +}; + +/* this is a hack: patch the summary and the description to include + * the correct package name */ +static void patch_debug_package_string(Package dbg, rpmTag tag, Package pkg, Package mainpkg) +{ + const char *oldname, *newname, *old; + char *oldsubst = NULL, *newsubst = NULL, *p; + oldname = headerGetString(mainpkg->header, RPMTAG_NAME); + newname = headerGetString(pkg->header, RPMTAG_NAME); + rasprintf(&oldsubst, "package %s", oldname); + rasprintf(&newsubst, "package %s", newname); + old = headerGetString(dbg->header, tag); + p = old ? strstr(old, oldsubst) : NULL; + if (p) { + char *new = NULL; + rasprintf(&new, "%.*s%s%s", (int)(p - old), old, newsubst, p + strlen(oldsubst)); + headerDel(dbg->header, tag); + headerPutString(dbg->header, tag, new); + _free(new); + } + _free(oldsubst); + _free(newsubst); +} + +/* create a new debuginfo subpackage for package pkg from the + * main debuginfo package */ +static Package cloneDebuginfoPackage(rpmSpec spec, Package pkg, Package maindbg) +{ + const char *name = headerGetString(pkg->header, RPMTAG_NAME); + char *dbgname = NULL; + Package dbg; + + rasprintf(&dbgname, "%s-%s", name, "debuginfo"); + dbg = newPackage(dbgname, spec->pool, &spec->packages); + headerPutString(dbg->header, RPMTAG_NAME, dbgname); + headerCopyTags(pkg->header, dbg->header, copyTagsForDebug); + headerCopyTags(maindbg->header, dbg->header, copyTagsForDebugMain); + dbg->autoReq = maindbg->autoReq; + dbg->autoProv = maindbg->autoProv; + + /* patch summary and description strings */ + patch_debug_package_string(dbg, RPMTAG_SUMMARY, pkg, spec->packages); + patch_debug_package_string(dbg, RPMTAG_DESCRIPTION, pkg, spec->packages); + + /* Add self-provides (normally done by addTargets) */ + addPackageProvides(dbg); + dbg->ds = rpmdsThis(dbg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); + + _free(dbgname); + return dbg; +} + +/* collect the debug files for package pkg and put them into + * a (possibly new) debuginfo subpackage */ +static void filterDebuginfoPackage(rpmSpec spec, Package pkg, + Package maindbg, char *buildroot, char *uniquearch) +{ + rpmfi fi; + ARGV_t files = NULL; + Package dbg = NULL; + char *path = NULL; + size_t buildrootlen = strlen(buildroot); + + /* ignore noarch subpackages */ + if (rstreq(headerGetString(pkg->header, RPMTAG_ARCH), "noarch")) + return; + + if (!uniquearch) + uniquearch = ""; + + fi = rpmfilesIter(pkg->cpioList, RPMFI_ITER_FWD); + /* Check if the current package has files with debug info + and add them to the file list */ + fi = rpmfiInit(fi, 0); + while (rpmfiNext(fi) >= 0) { + const char *name = rpmfiFN(fi); + int namel = strlen(name); + + /* strip trailing .debug like in find-debuginfo.sh */ + namel = strlen(name); + if (namel > 6 && !strcmp(name + namel - 6, ".debug")) + namel -= 6; + + /* generate path */ + rasprintf(&path, "%s/usr/lib/debug%.*s%s.debug", buildroot, namel, name, uniquearch); + + /* If that file exists we have debug information for it */ + if (access(path, F_OK) == 0) { + /* Append the file list preamble */ + if (!files) { + argvAdd(&files, "%defattr(-,root,root)"); + argvAdd(&files, "%dir /usr/lib/debug"); + } + /* Add the files main debug-info file */ + argvAdd(&files, path + buildrootlen); + } + path = _free(path); + } + + if (files) { + /* we have collected some files. Now put them in a debuginfo + * package. If this is not the main package, clone the main + * debuginfo package */ + if (pkg == spec->packages) + maindbg->fileList = files; + else { + Package dbg = cloneDebuginfoPackage(spec, pkg, maindbg); + dbg->fileList = files; + } + } +} + +/* add the debug dwz files to package pkg. + * return 1 if something was added, 0 otherwise. */ +static int addDebugDwz(Package pkg, char *buildroot) +{ + int ret = 0; + char *path = NULL; + struct stat sbuf; + + rasprintf(&path, "%s/usr/lib/debug/.dwz", buildroot); + if (lstat(path, &sbuf) == 0 && S_ISDIR(sbuf.st_mode)) { + if (!pkg->fileList) { + argvAdd(&pkg->fileList, "%defattr(-,root,root)"); + argvAdd(&pkg->fileList, "%dir /usr/lib/debug"); + } + argvAdd(&pkg->fileList, "/usr/lib/debug/.dwz"); + ret = 1; + } + path = _free(path); + return ret; +} + +/* add the debug source files to package pkg. + * return 1 if something was added, 0 otherwise. */ +static int addDebugSrc(Package pkg, char *buildroot) +{ + int ret = 0; + char *path = NULL; + DIR *d; + struct dirent *de; + + /* not needed if we have an extra debugsource subpackage */ + if (rpmExpandNumeric("%{?_debugsource_packages}")) + return 0; + + rasprintf(&path, "%s/usr/src/debug", buildroot); + d = opendir(path); + path = _free(path); + if (d) { + while ((de = readdir(d)) != NULL) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + rasprintf(&path, "/usr/src/debug/%s", de->d_name); + if (!pkg->fileList) + argvAdd(&pkg->fileList, "%defattr(-,root,root)"); + argvAdd(&pkg->fileList, path); + path = _free(path); + ret = 1; + } + closedir(d); + } + return ret; +} + +/* find the main debuginfo package. We do this simply by + * searching for a package with the right name. */ +static Package findDebuginfoPackage(rpmSpec spec) +{ + Package pkg = NULL; + if (lookupPackage(spec, "debuginfo", PART_SUBNAME, &pkg)) + return NULL; + return pkg && pkg->fileList ? pkg : NULL; +} + +/* add a requires for package "to" into package "from". */ +static void addDebugRequires(Package from, Package to) +{ + const char *name; + char *evr, *isaprov; + name = headerGetString(to->header, RPMTAG_NAME); + evr = headerGetAsString(to->header, RPMTAG_EVR); + isaprov = rpmExpand(name, "%{?_isa}", NULL); + addReqProv(from, RPMTAG_REQUIRENAME, isaprov, evr, RPMSENSE_EQUAL, 0); + free(isaprov); + free(evr); +} + rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, int didInstall, int test) { Package pkg; rpmRC rc = RPMRC_OK; + char *buildroot; + char *uniquearch = NULL; + Package maindbg = NULL; /* the (existing) main debuginfo package */ + Package deplink = NULL; /* create requires to this package */ #if HAVE_LIBDW elf_version (EV_CURRENT); #endif check_fileList = newStringBuf(); genSourceRpmName(spec); + buildroot = rpmGenPath(spec->rootDir, spec->buildRoot, NULL); + if (rpmExpandNumeric("%{?_debuginfo_subpackages}")) { + maindbg = findDebuginfoPackage(spec); + if (maindbg) { + /* move debuginfo package to back */ + if (maindbg->next) { + Package *pp; + /* dequeue */ + for (pp = &spec->packages; *pp != maindbg; pp = &(*pp)->next) + ; + *pp = maindbg->next; + maindbg->next = 0; + /* enqueue at tail */ + for (; *pp; pp = &(*pp)->next) + ; + *pp = maindbg; + } + /* delete unsplit file list, we will re-add files back later */ + maindbg->fileFile = argvFree(maindbg->fileFile); + maindbg->fileList = argvFree(maindbg->fileList); + if (rpmExpandNumeric("%{?_unique_debug_names}")) + uniquearch = rpmExpand("-%{VERSION}-%{RELEASE}.%{_arch}", NULL); + } + } + for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) { char *nvr; const char *a; int header_color; int arch_color; + if (pkg == maindbg) { + /* if there is just one debuginfo package, we put our extra stuff + * in it. Otherwise we put it in the main debug package */ + Package extradbg = !maindbg->fileList && maindbg->next && !maindbg->next->next ? + maindbg->next : maindbg; + if (addDebugDwz(extradbg, buildroot)) + deplink = extradbg; + if (addDebugSrc(extradbg, buildroot)) + deplink = extradbg; + maindbg = NULL; /* all normal packages processed */ + } + if (pkg->fileList == NULL) continue; @@ -2685,9 +2946,16 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, nvr = headerGetAsString(pkg->header, RPMTAG_NVRA); rpmlog(RPMLOG_NOTICE, _("Processing files: %s\n"), nvr); free(nvr); - - if ((rc = processPackageFiles(spec, pkgFlags, pkg, didInstall, test)) != RPMRC_OK || - (rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK) + + if ((rc = processPackageFiles(spec, pkgFlags, pkg, didInstall, test)) != RPMRC_OK) + goto exit; + + if (maindbg) + filterDebuginfoPackage(spec, pkg, maindbg, buildroot, uniquearch); + else if (deplink && pkg != deplink) + addDebugRequires(pkg, deplink); + + if ((rc = rpmfcGenerateDepends(spec, pkg)) != RPMRC_OK) goto exit; a = headerGetString(pkg->header, RPMTAG_ARCH); @@ -2722,6 +2990,8 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, } exit: check_fileList = freeStringBuf(check_fileList); + _free(buildroot); + _free(uniquearch); return rc; } diff --git a/build/parseSpec.c b/build/parseSpec.c index 2928e85..d0c42a4 100644 --- a/build/parseSpec.c +++ b/build/parseSpec.c @@ -572,7 +572,7 @@ static void initSourceHeader(rpmSpec spec) } /* Add extra provides to package. */ -static void addPackageProvides(Package pkg) +void addPackageProvides(Package pkg) { const char *arch, *name; char *evr, *isaprov; diff --git a/build/rpmbuild_internal.h b/build/rpmbuild_internal.h index 948dc31..4f26324 100644 --- a/build/rpmbuild_internal.h +++ b/build/rpmbuild_internal.h @@ -452,6 +452,13 @@ rpmRC addReqProvPkg(void *cbdata, rpmTagVal tagN, int index); /** \ingroup rpmbuild + * Add self-provides to package. + * @param pkg package + */ +RPM_GNUC_INTERNAL +void addPackageProvides(Package pkg); + +/** \ingroup rpmbuild * Add rpmlib feature dependency. * @param pkg package * @param feature rpm feature name (i.e. "rpmlib(Foo)" for feature Foo) diff --git a/macros.in b/macros.in index b2cfceb..dcd4865 100644 --- a/macros.in +++ b/macros.in @@ -532,6 +532,9 @@ package or when debugging this package.\ # Whether rpm should put debug source files into an own subpackage #%_debugsource_packages 1 +# Whether rpm should create extra debuginfo packages for subpackage +#%_debuginfo_subpackages 1 + # # Use internal dependency generator rather than external helpers? %_use_internal_dependency_generator 1 -- 2.1.4
_______________________________________________ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint