[gnome-ostree] build: Split debuginfo



commit baaeef3242d74dcf46245f2516662dcdfc9ea678
Author: Colin Walters <walters verbum org>
Date:   Wed Mar 27 09:30:01 2013 -0400

    build: Split debuginfo
    
    This is similar to the Debian/debhelper code, except it hard-requires
    objects to contain Build ID.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=695816

 src/js/procutil.js         |   30 +++++++++++---
 src/js/tasks/task-build.js |   92 ++++++++++++++++++++++++++++++++++++--------
 2 files changed, 100 insertions(+), 22 deletions(-)
---
diff --git a/src/js/procutil.js b/src/js/procutil.js
index 3c30ab3..12a7519 100644
--- a/src/js/procutil.js
+++ b/src/js/procutil.js
@@ -72,7 +72,9 @@ function runSync(argv, cancellable, params) {
     _wait_sync_check_internal(proc, cancellable);
 }
 
-function _runSyncGetOutputInternal(argv, cancellable, params, splitLines) {
+function _runSyncGetOutputInternal(argv, cancellable, params, subParams) {
+    subParams = Params.parse(subParams, { splitLines: false,
+                                         grep: null });
     let [context, pparams] = _newContext(argv, params);
     context.set_stdout_disposition(GSystem.SubprocessStreamDisposition.PIPE);
     context.set_stderr_disposition(GSystem.SubprocessStreamDisposition.INHERIT);
@@ -83,8 +85,19 @@ function _runSyncGetOutputInternal(argv, cancellable, params, splitLines) {
     let input = proc.get_stdout_pipe();
     let dataIn = Gio.DataInputStream.new(input);
 
-    let result;
-    if (splitLines) {
+    let result = null;
+    if (subParams.grep) {
+       let grep = subParams.grep;
+       while (true) {
+           let [line, len] = dataIn.read_line_utf8(cancellable);
+           if (line == null)
+               break;
+           result = grep.exec(line);
+           if (result != null) {
+               break;
+           }
+       }
+    } else if (subParams.splitLines) {
        result = StreamUtil.dataInputStreamReadLines(dataIn, cancellable);
     } else {
        result = '';
@@ -95,20 +108,21 @@ function _runSyncGetOutputInternal(argv, cancellable, params, splitLines) {
            result += (line + '\n');
        }
     }
+    dataIn.close(cancellable);
     _wait_sync_check_internal(proc, cancellable);
     return result;
 }
 
 function runSyncGetOutputLines(args, cancellable, params) {
-    return _runSyncGetOutputInternal(args, cancellable, params, true);
+    return _runSyncGetOutputInternal(args, cancellable, params, { splitLines: true });
 }
 
 function runSyncGetOutputUTF8(args, cancellable, params) {
-    return _runSyncGetOutputInternal(args, cancellable, params, false);
+    return _runSyncGetOutputInternal(args, cancellable, params);
 }
 
 function runSyncGetOutputUTF8Stripped(args, cancellable, params) {
-    return _runSyncGetOutputInternal(args, cancellable, params, false).replace(/[ \n]+$/, '');
+    return _runSyncGetOutputInternal(args, cancellable, params).replace(/[ \n]+$/, '');
 }
 
 function runSyncGetOutputUTF8StrippedOrNull(args, cancellable, params) {
@@ -124,6 +138,10 @@ function runSyncGetOutputUTF8StrippedOrNull(args, cancellable, params) {
     }
 }
 
+function runSyncGetOutputGrep(args, pattern, cancellable, params) {
+    return _runSyncGetOutputInternal(args, cancellable, params, { grep: pattern });
+}
+
 function getExitStatusAndString(ecode) {
     try {
        GLib.spawn_check_exit_status(ecode);
diff --git a/src/js/tasks/task-build.js b/src/js/tasks/task-build.js
index 8740798..a7b6a11 100644
--- a/src/js/tasks/task-build.js
+++ b/src/js/tasks/task-build.js
@@ -299,14 +299,6 @@ const TaskBuild = new Lang.Class({
 
        GSystem.file_ensure_directory(destFile.get_parent(), true, cancellable);
        
-       if (srcInfo.get_file_type() != Gio.FileType.SYMBOLIC_LINK) {
-           let minimalMode = 436; // u+rw,g+rw,o+r
-           if (srcInfo.get_file_type() == Gio.FileType.DIRECTORY)
-               minimalMode |= 64; // u+x
-           let mode = srcInfo.get_attribute_uint32('unix::mode');
-           GSystem.file_chmod(srcFile, mode | minimalMode, cancellable);
-       }
-
        if (srcInfo.get_file_type() == Gio.FileType.DIRECTORY) {
            GSystem.file_ensure_directory(destFile, true, cancellable);
            let e = srcFile.enumerate_children('standard::*,unix::mode', 
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, cancellable);
@@ -327,6 +319,50 @@ const TaskBuild = new Lang.Class({
        let srcInfo = srcFile.query_info('standard::*,unix::mode', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, 
cancellable);
        this._installAndUnlinkRecurse(buildResultDir, srcFile, srcInfo, finalResultDir, cancellable);
     },
+
+    _processBuildResultSplitDebuginfo: function(buildResultDir, debugPath, path, cancellable) {
+       let name = path.get_basename();
+       // Only process files ending in .so.* or executables
+       let soRegex = /\.so\./;
+       if (!soRegex.exec(name)) {
+           let finfo = path.query_info('unix::mode', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
+                                       cancellable);
+           let mode = finfo.get_attribute_uint32('unix::mode');
+           if (!(mode & 73))
+               return;
+       }
+       let elfSharedRe = /ELF.*shared/;
+       let elfExecRe = /ELF.*executable/;
+       let ftype = ProcUtil.runSyncGetOutputUTF8StrippedOrNull(['file', path.get_path()], cancellable);
+       if (ftype == null)
+           return;
+
+       let isShared = elfSharedRe.test(ftype);
+       let isExec = elfExecRe.test(ftype);
+
+       if (!(isShared || isExec))
+           return;
+
+       let buildIdPattern = /\s+Build ID: ([0-9a-f]+)/;
+       let match = ProcUtil.runSyncGetOutputGrep(['eu-readelf', '-n', path.get_path()], buildIdPattern, 
cancellable);
+       if (match == null) {
+           print("WARNING: no build-id for ELF object " + path.get_path());
+           return;
+       } 
+       let buildId = match[1];
+       print("ELF object " + path.get_path() + " buildid=" + buildId);
+       let dbgName = buildId[0] + buildId[1] + '/' + buildId.substr(2) + '.debug';
+       let objdebugPath = debugPath.resolve_relative_path('usr/lib/debug/.build-id/' + dbgName);
+       GSystem.file_ensure_directory(objdebugPath.get_parent(), true, cancellable);
+       ProcUtil.runSync(['objcopy', '--only-keep-debug', path.get_path(), objdebugPath.get_path()], 
cancellable);
+
+       let stripArgs = ['strip', '--remove-section=.comment', '--remove-section=.note']; 
+       if (isShared) {
+           stripArgs.push('--strip-unneeded');
+       }
+       stripArgs.push(path.get_path());
+       ProcUtil.runSync(stripArgs, cancellable);
+    },
     
     _processBuildResults: function(component, buildResultDir, finalResultDir, cancellable) {
        let runtimePath = finalResultDir.get_child('runtime');
@@ -335,8 +371,23 @@ const TaskBuild = new Lang.Class({
        GSystem.file_ensure_directory(develPath, true, cancellable);
        let docPath = finalResultDir.get_child('doc');
        GSystem.file_ensure_directory(docPath, true, cancellable);
+       let debugPath = finalResultDir.get_child('debug');
+       GSystem.file_ensure_directory(debugPath, true, cancellable);
+
+       // Change file modes first; some components install files that
+       // are read-only even by the user, which we don't want.
+       FileUtil.walkDir(buildResultDir, {}, Lang.bind(this, function(path, cancellable) {
+           let info = path.query_info("standard::type,unix::mode", Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, 
cancellable);
+           if (info.get_file_type() != Gio.FileType.SYMBOLIC_LINK) {
+               let minimalMode = 436; // u+rw,g+rw,o+r
+               if (info.get_file_type() == Gio.FileType.DIRECTORY)
+                   minimalMode |= 64; // u+x
+               let mode = info.get_attribute_uint32('unix::mode');
+               GSystem.file_chmod(path, mode | minimalMode, cancellable);
+           }
+       }), cancellable);
 
-       // First, remove /var from the install - components are required to
+       // Remove /var from the install - components are required to
        // auto-create these directories on demand.
        let varPath = buildResultDir.get_child('var');
        GSystem.shutil_rm_rf(varPath, cancellable);
@@ -374,6 +425,11 @@ const TaskBuild = new Lang.Class({
                             }), cancellable);
        }
 
+       FileUtil.walkDir(buildResultDir, { fileType: Gio.FileType.REGULAR },
+                        Lang.bind(this, function(filePath, cancellable) {
+                            this._processBuildResultSplitDebuginfo(buildResultDir, debugPath, filePath, 
cancellable);
+                        }), cancellable);
+
        for (let i = 0; i < DEVEL_DIRS.length; i++) {
            let path = DEVEL_DIRS[i];
            let oneDevelDir = buildResultDir.resolve_relative_path(path);
@@ -924,7 +980,7 @@ const TaskBuild = new Lang.Class({
        }
 
         let targetsList = [];
-       let componentTypes = ['runtime', 'devel'];
+       let componentTypes = ['runtime', 'runtime-debug', 'devel', 'devel-debug'];
         for (let i = 0; i < componentTypes.length; i++) {
            let targetComponentType = componentTypes[i];
             for (let i = 0; i < architectures.length; i++) {
@@ -933,20 +989,20 @@ const TaskBuild = new Lang.Class({
                 targetsList.push(target);
                 target['name'] = 'buildmaster/' + architecture + '-' + targetComponentType;
 
-                let runtimeRef = baseName + '/' + architecture + '-runtime';
+                let baseRuntimeRef = baseName + '/' + architecture + '-runtime';
                 let buildrootRef = baseName + '/' + architecture + '-devel';
                let baseRef;
                 if (targetComponentType == 'runtime') {
-                    baseRef = runtimeRef;
+                    baseRef = baseRuntimeRef;
                 } else {
                     baseRef = buildrootRef;
                }
                 target['base'] = {'name': baseRef,
-                                  'runtime': runtimeRef,
+                                  'runtime': baseRuntimeRef,
                                   'devel': buildrootRef};
 
                let targetComponents;
-                if (targetComponentType == 'runtime') {
+                if (targetComponentType.indexOf('runtime-') == 0) {
                     targetComponents = runtimeComponents;
                 } else {
                     targetComponents = develComponents;
@@ -966,8 +1022,12 @@ const TaskBuild = new Lang.Class({
                     let componentRef = {'name': binaryName};
                     if (targetComponentType == 'runtime') {
                         componentRef['trees'] = ['/runtime'];
-                    } else {
+                    } else if (targetComponentType == 'runtime-debug') {
+                        componentRef['trees'] = ['/runtime', '/debug'];
+                    } else if (targetComponentType == 'devel') {
                         componentRef['trees'] = ['/runtime', '/devel', '/doc']
+                   } else if (targetComponentType == 'devel-debug') {
+                        componentRef['trees'] = ['/runtime', '/devel', '/doc', '/debug'];
                    }
                     contents.push(componentRef);
                }
@@ -1001,7 +1061,7 @@ const TaskBuild = new Lang.Class({
 
        // Now loop over the other targets per architecture, reusing
        // the initramfs cached from -devel generation.
-       let nonDevelTargets = ['runtime'];
+       let nonDevelTargets = ['runtime', 'runtime-debug', 'devel-debug'];
        for (let i = 0; i < nonDevelTargets.length; i++) {
            let target = nonDevelTargets[i];
             for (let j = 0; j < architectures.length; j++) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]