mirror of
https://git.yoctoproject.org/poky
synced 2026-06-02 01:19:52 +00:00
package.bbclass: Refactor split and strip function
Refactor the function to eliminate additional interations/walks of the filesystem.. Elimiate multiple runs of the external 'file' command as well. Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
This commit is contained in:
committed by
Richard Purdie
parent
16102e1890
commit
40ea19d6e1
+146
-100
@@ -184,7 +184,7 @@ def splitfile(file, debugfile, debugsrcdir, d):
|
|||||||
|
|
||||||
# We ignore kernel modules, we don't generate debug info files.
|
# We ignore kernel modules, we don't generate debug info files.
|
||||||
if file.find("/lib/modules/") != -1 and file.endswith(".ko"):
|
if file.find("/lib/modules/") != -1 and file.endswith(".ko"):
|
||||||
return 0
|
return 1
|
||||||
|
|
||||||
newmode = None
|
newmode = None
|
||||||
if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
|
if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
|
||||||
@@ -239,9 +239,14 @@ def splitfile2(debugsrcdir, d):
|
|||||||
#bb.note("rmdir -p %s" % dir)
|
#bb.note("rmdir -p %s" % dir)
|
||||||
os.system("rmdir -p %s 2>/dev/null" % dir)
|
os.system("rmdir -p %s 2>/dev/null" % dir)
|
||||||
|
|
||||||
def runstrip(file, d):
|
def runstrip(file, elftype, d):
|
||||||
# Function to strip a single file, called from split_and_strip_files below
|
# Function to strip a single file, called from split_and_strip_files below
|
||||||
# A working 'file' (one which works on the target architecture)
|
# A working 'file' (one which works on the target architecture)
|
||||||
|
#
|
||||||
|
# The elftype is a bit pattern (explained in split_and_strip_files) to tell
|
||||||
|
# us what type of file we're processing...
|
||||||
|
# 4 - executable
|
||||||
|
# 8 - shared library
|
||||||
|
|
||||||
import commands, stat
|
import commands, stat
|
||||||
|
|
||||||
@@ -258,16 +263,12 @@ def runstrip(file, d):
|
|||||||
newmode = origmode | stat.S_IWRITE | stat.S_IREAD
|
newmode = origmode | stat.S_IWRITE | stat.S_IREAD
|
||||||
os.chmod(file, newmode)
|
os.chmod(file, newmode)
|
||||||
|
|
||||||
ret, result = commands.getstatusoutput("%sfile '%s'" % (pathprefix, file))
|
|
||||||
|
|
||||||
if ret:
|
|
||||||
bb.error("runstrip: 'file %s' failed" % file)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
extraflags = ""
|
extraflags = ""
|
||||||
if ".so" in file and "shared" in result:
|
# .so and shared library
|
||||||
|
if ".so" in file and elftype & 8:
|
||||||
extraflags = "--remove-section=.comment --remove-section=.note --strip-unneeded"
|
extraflags = "--remove-section=.comment --remove-section=.note --strip-unneeded"
|
||||||
elif "shared" in result or "executable" in result:
|
# shared or executable:
|
||||||
|
elif elftype & 8 or elftype & 4:
|
||||||
extraflags = "--remove-section=.comment --remove-section=.note"
|
extraflags = "--remove-section=.comment --remove-section=.note"
|
||||||
|
|
||||||
stripcmd = "'%s' %s '%s'" % (strip, extraflags, file)
|
stripcmd = "'%s' %s '%s'" % (strip, extraflags, file)
|
||||||
@@ -410,109 +411,158 @@ python split_and_strip_files () {
|
|||||||
|
|
||||||
os.chdir(dvar)
|
os.chdir(dvar)
|
||||||
|
|
||||||
def isexec(path):
|
# Return type (bits):
|
||||||
try:
|
# 0 - not elf
|
||||||
s = os.stat(path)
|
# 1 - ELF
|
||||||
except (os.error, AttributeError):
|
# 2 - stripped
|
||||||
return 0
|
# 4 - executable
|
||||||
return ((s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) or (s[stat.ST_MODE] & stat.S_IXOTH))
|
# 8 - shared library
|
||||||
|
|
||||||
# Return 0 - not elf, 1 - ELF & not stripped, 2 - ELF & stripped
|
|
||||||
def isELF(path):
|
def isELF(path):
|
||||||
|
type = 0
|
||||||
pathprefix = "export PATH=%s; " % bb.data.getVar('PATH', d, True)
|
pathprefix = "export PATH=%s; " % bb.data.getVar('PATH', d, True)
|
||||||
ret, result = commands.getstatusoutput("%sfile '%s'" % (pathprefix, path))
|
ret, result = commands.getstatusoutput("%sfile '%s'" % (pathprefix, path))
|
||||||
|
|
||||||
if ret:
|
if ret:
|
||||||
bb.error("split_and_strip_files: 'file %s' failed" % path)
|
bb.error("split_and_strip_files: 'file %s' failed" % path)
|
||||||
return 0
|
return type
|
||||||
|
|
||||||
# Not stripped
|
# Not stripped
|
||||||
if "ELF" in result and "not stripped" in result:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# Stripped
|
|
||||||
if "ELF" in result:
|
if "ELF" in result:
|
||||||
return 2
|
type |= 1
|
||||||
|
if "not stripped" not in result:
|
||||||
|
type |= 2
|
||||||
|
if "executable" in result:
|
||||||
|
type |= 4
|
||||||
|
if "shared" in result:
|
||||||
|
type |= 8
|
||||||
|
return type
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# First lets process debug splitting
|
# First lets figure out all of the files we may have to process ... do this only once!
|
||||||
#
|
#
|
||||||
if (bb.data.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT', d, True) != '1'):
|
file_list = {}
|
||||||
file_links = {}
|
file_links = {}
|
||||||
|
if (bb.data.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT', d, True) != '1') and \
|
||||||
|
(bb.data.getVar('INHIBIT_PACKAGE_STRIP', d, True) != '1'):
|
||||||
for root, dirs, files in os.walk(dvar):
|
for root, dirs, files in os.walk(dvar):
|
||||||
for f in files:
|
for f in files:
|
||||||
file = os.path.join(root, f)
|
file = os.path.join(root, f)
|
||||||
# Skip debug files, it must be executable, and must be a file (or link)
|
# 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 isexec(file) and os.path.isfile(file):
|
if not (debugappend != "" and file.endswith(debugappend)) and \
|
||||||
src = file[len(dvar):]
|
not (debugdir != "" and debugdir in os.path.dirname(file[len(dvar):])) and \
|
||||||
dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
|
os.path.isfile(file):
|
||||||
fpath = dvar + dest
|
|
||||||
# Preserve symlinks in debug area...
|
|
||||||
if os.path.islink(file):
|
|
||||||
target = os.readlink(file)
|
|
||||||
if not os.path.isabs(target):
|
|
||||||
target = os.path.join(os.path.dirname(file), target)
|
|
||||||
if isELF(target):
|
|
||||||
ltarget = os.readlink(file)
|
|
||||||
lpath = os.path.dirname(ltarget)
|
|
||||||
lbase = os.path.basename(ltarget)
|
|
||||||
ftarget = ""
|
|
||||||
if lpath and lpath != ".":
|
|
||||||
ftarget += lpath + debugdir + "/"
|
|
||||||
ftarget += lbase + debugappend
|
|
||||||
bb.mkdirhier(os.path.dirname(fpath))
|
|
||||||
#bb.note("Symlink %s -> %s" % (fpath, ftarget))
|
|
||||||
os.symlink(ftarget, fpath)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# If the file is elf we need to check it for hard links
|
|
||||||
elf_file = isELF(file)
|
|
||||||
if elf_file:
|
|
||||||
# Preserve hard links in debug area...
|
|
||||||
s = os.stat(file)
|
|
||||||
if s.st_nlink > 1:
|
|
||||||
file_reference = "%d_%d" % (s.st_dev, s.st_ino)
|
|
||||||
if file_reference not in file_links:
|
|
||||||
# If this is new, and already stripped we avoid recording it
|
|
||||||
# as we'll be unable to set the hard link later, because it
|
|
||||||
# won't be split/stripped...
|
|
||||||
if elf_file != 2:
|
|
||||||
file_links[file_reference] = fpath
|
|
||||||
else:
|
|
||||||
bb.mkdirhier(os.path.dirname(fpath))
|
|
||||||
#bb.note("Link %s -> %s" % (fpath, file_links[file_reference]))
|
|
||||||
os.link(file_links[file_reference], fpath)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if elf_file == 2:
|
|
||||||
bb.warn("File '%s' was already stripped, this will prevent future debugging!" % (src))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Split and Strip
|
|
||||||
bb.mkdirhier(os.path.dirname(fpath))
|
|
||||||
#bb.note("Split %s -> %s" % (file, fpath))
|
|
||||||
splitfile(file, fpath, debugsrcdir, d)
|
|
||||||
|
|
||||||
# Process the debugsrcdir if requested...
|
|
||||||
splitfile2(debugsrcdir, d)
|
|
||||||
|
|
||||||
# The above may have generated dangling symlinks
|
|
||||||
for root, dirs, files in os.walk(dvar):
|
|
||||||
for f in files:
|
|
||||||
file = os.path.join(root, f)
|
|
||||||
# We ONLY strip dangling links if they're debug generated!
|
|
||||||
if (debugappend != "" and file.endswith(debugappend)) or (debugdir != "" and debugdir in os.path.dirname(file[len(dvar):])):
|
|
||||||
try:
|
try:
|
||||||
s = os.stat(file)
|
s = os.stat(file)
|
||||||
except OSError, (err, strerror):
|
except OSError, (err, strerror):
|
||||||
if err != errno.ENOENT:
|
if err != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
#bb.note("Remove dangling link %s" % file)
|
# Skip broken symlinks
|
||||||
os.unlink(file)
|
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
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# First lets process debug splitting
|
||||||
|
#
|
||||||
|
if (bb.data.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT', d, True) != '1'):
|
||||||
|
for file in file_list:
|
||||||
|
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
|
||||||
|
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' was already stripped, this will prevent future debugging!" % (src))
|
||||||
|
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 splitfile(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...
|
||||||
|
os.system("rmdir %s 2>/dev/null" % os.path.dirname(fpath))
|
||||||
|
|
||||||
|
# Process the debugsrcdir if requested...
|
||||||
|
# This copies and places the referenced sources for later debugging...
|
||||||
|
splitfile2(debugsrcdir, d)
|
||||||
#
|
#
|
||||||
# End of debug splitting
|
# End of debug splitting
|
||||||
#
|
#
|
||||||
@@ -521,15 +571,11 @@ python split_and_strip_files () {
|
|||||||
# Now lets go back over things and strip them
|
# Now lets go back over things and strip them
|
||||||
#
|
#
|
||||||
if (bb.data.getVar('INHIBIT_PACKAGE_STRIP', d, True) != '1'):
|
if (bb.data.getVar('INHIBIT_PACKAGE_STRIP', d, True) != '1'):
|
||||||
for root, dirs, files in os.walk(dvar):
|
for file in file_list:
|
||||||
for f in files:
|
if file_list[file].startswith("ELF: "):
|
||||||
file = os.path.join(root, f)
|
elf_file = int(file_list[file][5:])
|
||||||
# if not a debugfile, is executable, is a file, and not a symlink
|
#bb.note("Strip %s" % file)
|
||||||
if not (debugappend != "" and file.endswith(debugappend)) and not (debugdir != "" and debugdir in os.path.dirname(file[len(dvar):])) and isexec(file) and os.path.isfile(file) and not os.path.islink(file):
|
runstrip(file, elf_file, d)
|
||||||
elf_file = isELF(file)
|
|
||||||
if elf_file and elf_file != 2:
|
|
||||||
#bb.note("Strip %s" % file)
|
|
||||||
runstrip(file, d)
|
|
||||||
#
|
#
|
||||||
# End of strip
|
# End of strip
|
||||||
#
|
#
|
||||||
|
|||||||
Reference in New Issue
Block a user