Patchwork [13/22] package.bbclass: Rewrite split_and_strip_files

login
register
mail settings
Submitter Richard Purdie
Date Feb. 3, 2013, 11:55 p.m.
Message ID <11d3a4a06b141fc8b085baddb2195879fa7b8a03.1359935562.git.richard.purdie@linuxfoundation.org>
Download mbox | patch
Permalink /patch/43893/
State New
Headers show

Comments

Richard Purdie - Feb. 3, 2013, 11:55 p.m.
The split_and_strip_files funciton was hard to follow and its usage of prefixes
to strings was unusual. This rewrites it to use a list of hardlinks, symlinks and
elffiles where each list is iterated over at the correct point.

This means we can avoid creating dandling symlinks for example so we can simply
delete the cleanup code for this.

The isfile() check is also removed which gives a significant improvement in speed.
Its uneeded since os.walk will have already checked things in files are files.

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
---
 meta/classes/package.bbclass |  205 ++++++++++++++++++++----------------------
 1 file changed, 97 insertions(+), 108 deletions(-)
Enrico Scholz - Feb. 9, 2013, 11:41 a.m.
Richard Purdie <richard.purdie-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org> writes:

> -                   os.path.isfile(file):
> ...
> +                try:
> +                    s = os.stat(file)
> +                except OSError, (err, strerror):
> +                    if err != errno.ENOENT:
> +                        raise

Causes a regression (resp. triggers the previously hidden bug catched by
the os.path.isfile() check):

ERROR: Error executing a python function in .../org.openembedded.core/meta/recipes-core/systemd/systemd-serialgetty.bb:
OSError: [Errno 13] Permission denied: '.../systemd-serialgetty/1.0-r3/package/etc/systemd/system/getty.target.wants/serial-getty@ttySA0.service'



Enrico
Enrico Scholz - Feb. 10, 2013, 1:50 p.m.
Enrico Scholz
<enrico.scholz-wttK6gPy29v+Hn7q9Vec/7NAH6kLmebB@public.gmane.org>
writes:

> Causes a regression (resp. triggers the previously hidden bug catched by
> the os.path.isfile() check):
>
> ERROR: Error executing a python function in .../org.openembedded.core/meta/recipes-core/systemd/systemd-serialgetty.bb:
> OSError: [Errno 13] Permission denied: '.../systemd-serialgetty/1.0-r3/package/etc/systemd/system/getty.target.wants/serial-getty-OjP1UEOGd4Fo45MUmRTO9Q@public.gmane.org'

I posted a patchset "lib: implemented oe.path.realpath()" which should
solve this issue.


Enrico

Patch

diff --git a/meta/classes/package.bbclass b/meta/classes/package.bbclass
index bee6548..7e45655 100644
--- a/meta/classes/package.bbclass
+++ b/meta/classes/package.bbclass
@@ -722,8 +722,9 @@  python split_and_strip_files () {
     #
     # First lets figure out all of the files we may have to process ... do this only once!
     #
-    file_list = {}
-    file_links = {}
+    elffiles = {}
+    symlinks = {}
+    hardlinks = {}
     kernmods = []
     if (d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT', True) != '1') and \
             (d.getVar('INHIBIT_PACKAGE_STRIP', True) != '1'):
@@ -734,119 +735,108 @@  python split_and_strip_files () {
                     kernmods.append(file)
                     continue
 
-                # Only process files (and symlinks)... Skip files that are obviously debug files
-                if not (debugappend != "" and file.endswith(debugappend)) and \
-                   not (debugdir != "" and debugdir in os.path.dirname(file[len(dvar):])) and \
-                   os.path.isfile(file):
-                    try:
-                        s = os.stat(file)
-                    except OSError, (err, strerror):
-                        if err != errno.ENOENT:
-                            raise
-                        # Skip broken symlinks
+                # Skip debug files
+                if debugappend and file.endswith(debugappend):
+                    continue
+                if debugdir and debugdir in os.path.dirname(file[len(dvar):]):
+                    continue
+
+                try:
+                    s = os.stat(file)
+                except OSError, (err, strerror):
+                    if err != errno.ENOENT:
+                        raise
+                    # Skip broken symlinks
+                    continue
+                # Check its an excutable
+                if (s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) or (s[stat.ST_MODE] & stat.S_IXOTH):
+                    # If it's a symlink, and points to an ELF file, we capture the readlink target
+                    if os.path.islink(file):
+                        target = os.readlink(file)
+                        if not os.path.isabs(target):
+                            ltarget = os.path.join(os.path.dirname(file), target)
+                        else:
+                            ltarget = target
+
+                        if isELF(ltarget):
+                            #bb.note("Sym: %s (%d)" % (ltarget, isELF(ltarget)))
+                            symlinks[file] = target
                         continue
-                    # Is the item excutable?  Then we need to process it.
-                    if (s[stat.ST_MODE] & stat.S_IXUSR) or \
-                       (s[stat.ST_MODE] & stat.S_IXGRP) or \
-                       (s[stat.ST_MODE] & stat.S_IXOTH):
-                        # If it's a symlink, and points to an ELF file, we capture the readlink target
-                        if os.path.islink(file):
-                            target = os.readlink(file)
-                            if not os.path.isabs(target):
-                                ltarget = os.path.join(os.path.dirname(file), target)
-                            else:
-                                ltarget = target
-
-                            if isELF(ltarget):
-                                #bb.note("Sym: %s (%d)" % (ltarget, isELF(ltarget)))
-                                file_list[file] = "sym: " + target
+                    # It's a file (or hardlink), not a link
+                    # ...but is it ELF, and is it already stripped?
+                    elf_file = isELF(file)
+                    if elf_file & 1:
+                        if elf_file & 2:
+                            bb.warn("File '%s' from %s was already stripped, this will prevent future debugging!" % (src, pn))
                             continue
-                        # It's a file (or hardlink), not a link
-                        # ...but is it ELF, and is it already stripped?
-                        elf_file = isELF(file)
-                        if elf_file & 1:
-                            # Check if it's a hard link to something else
-                            if s.st_nlink > 1:
-                                file_reference = "%d_%d" % (s.st_dev, s.st_ino)
-                                # Hard link to something else
-                                file_list[file] = "hard: " + file_reference
-                                continue
-
-                            file_list[file] = "ELF: %d" % elf_file
-
+                        # Check if it's a hard link to something else
+                        if s.st_nlink > 1:
+                            file_reference = "%d_%d" % (s.st_dev, s.st_ino)
+                            # Hard link to something else
+                            hardlinks[file] = file_reference
+                            continue
+                        elffiles[file] = elf_file
 
     #
     # First lets process debug splitting
     #
     if (d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT', True) != '1'):
-        for file in file_list:
+        hardlinkmap = {}
+        # For hardlinks, process only one of the files
+        for file in hardlinks:
+            file_reference = hardlinks[file]
+            if file_reference not in hardlinkmap:
+                # If this is a new file, add it as a reference, and
+                # update it's type, so we can fall through and split
+                elffiles[file] = isELF(file)
+                hardlinkmap[file_reference] = file
+
+        for file in elffiles:
             src = file[len(dvar):]
             dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
             fpath = dvar + dest
-            # Preserve symlinks in debug area...
-            if file_list[file].startswith("sym: "):
-                ltarget = file_list[file][5:]
-                lpath = os.path.dirname(ltarget)
-                lbase = os.path.basename(ltarget)
-                ftarget = ""
-                if lpath and lpath != ".":
-                    ftarget += lpath + debugdir + "/"
-                ftarget += lbase + debugappend
-                if lpath.startswith(".."):
-                    ftarget = os.path.join("..", ftarget)
-                bb.mkdirhier(os.path.dirname(fpath))
-                #bb.note("Symlink %s -> %s" % (fpath, ftarget))
-                os.symlink(ftarget, fpath)
-                continue
 
-            # Preserve hard links in debug area...
-            file_reference = ""
-            if file_list[file].startswith("hard: "):
-                file_reference = file_list[file][6:]
-                if file_reference not in file_links:
-                    # If this is a new file, add it as a reference, and
-                    # update it's type, so we can fall through and split
-                    file_list[file] = "ELF: %d" % (isELF(file))
-                else:
-                    target = file_links[file_reference][len(dvar):]
-                    ftarget = dvar + debuglibdir + os.path.dirname(target) + debugdir + "/" + os.path.basename(target) + debugappend
-                    bb.mkdirhier(os.path.dirname(fpath))
-                    #bb.note("Link %s -> %s" % (fpath, ftarget))
-                    os.link(ftarget, fpath)
-                    continue
-
-            # It's ELF...
-            if file_list[file].startswith("ELF: "):
-                elf_file = int(file_list[file][5:])
-                if elf_file & 2:
-                    bb.warn("File '%s' from %s was already stripped, this will prevent future debugging!" % (src, pn))
-                    continue
+            # Split the file...
+            bb.utils.mkdirhier(os.path.dirname(fpath))
+            #bb.note("Split %s -> %s" % (file, fpath))
+            # Only store off the hard link reference if we successfully split!
+            splitdebuginfo(file, fpath, debugsrcdir, d)
+
+        # Hardlink our debug symbols to the other hardlink copies
+        for file in hardlinks:
+            if file not in elffiles:
+                file_reference = hardlinks[file]
+                target = hardlinkmap[file_reference][len(dvar):]
+                ftarget = dvar + debuglibdir + os.path.dirname(target) + debugdir + "/" + os.path.basename(target) + debugappend
+                bb.utils.mkdirhier(os.path.dirname(fpath))
+                #bb.note("Link %s -> %s" % (fpath, ftarget))
+                os.link(ftarget, fpath)
+
+        # Create symlinks for all cases we were able to split symbols
+        for file in symlinks:
+            src = file[len(dvar):]
+            dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
+            fpath = dvar + dest
+            # Skip it if the target doesn't exist
+            try:
+                s = os.stat(fpath)
+            except OSError, (err, strerror):
+                if err != errno.ENOENT:
+                    raise
+                continue
 
-                # Split the file...
-                bb.mkdirhier(os.path.dirname(fpath))
-                #bb.note("Split %s -> %s" % (file, fpath))
-                # Only store off the hard link reference if we successfully split!
-                if splitdebuginfo(file, fpath, debugsrcdir, d) == 0 and file_reference != "":
-                    file_links[file_reference] = file
-
-        # The above may have generated dangling symlinks, remove them!
-        # Dangling symlinks are a result of something NOT being split, such as a stripped binary.
-        # This should be a rare occurance, but we want to clean up anyway.
-        for file in file_list:
-            if file_list[file].startswith("sym: "):
-                src = file[len(dvar):]
-                dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
-                fpath = dvar + dest
-                try:
-                    s = os.stat(fpath)
-                except OSError, (err, strerror):
-                    if err != errno.ENOENT:
-                        raise
-                    #bb.note("Remove dangling link %s -> %s" % (fpath, os.readlink(fpath)))
-                    os.unlink(fpath)
-                    # This could leave an empty debug directory laying around
-                    # take care of the obvious case...
-                    subprocess.call("rmdir %s 2>/dev/null" % os.path.dirname(fpath), shell=True)
+            ltarget = symlinks[file]
+            lpath = os.path.dirname(ltarget)
+            lbase = os.path.basename(ltarget)
+            ftarget = ""
+            if lpath and lpath != ".":
+                ftarget += lpath + debugdir + "/"
+            ftarget += lbase + debugappend
+            if lpath.startswith(".."):
+                ftarget = os.path.join("..", ftarget)
+            bb.utils.mkdirhier(os.path.dirname(fpath))
+            #bb.note("Symlink %s -> %s" % (fpath, ftarget))
+            os.symlink(ftarget, fpath)
 
         # Process the debugsrcdir if requested...
         # This copies and places the referenced sources for later debugging...
@@ -861,11 +851,10 @@  python split_and_strip_files () {
     if (d.getVar('INHIBIT_PACKAGE_STRIP', True) != '1'):
         strip = d.getVar("STRIP", True)
         sfiles = []
-        for file in file_list:
-            if file_list[file].startswith("ELF: "):
-                elf_file = int(file_list[file][5:])
-                #bb.note("Strip %s" % file)
-                sfiles.append((file, elf_file, strip))
+        for file in elffiles:
+            elf_file = int(elffiles[file])
+            #bb.note("Strip %s" % file)
+            sfiles.append((file, elf_file, strip))
         for f in kernmods:
             sfiles.append((f, 16, strip))