builder: Add support for separating out debuginfo

tingping/wmclass
Alexander Larsson 2016-01-08 18:01:35 +01:00
parent 62b4ffaa72
commit 98a7d731ad
10 changed files with 286 additions and 81 deletions

View File

@ -372,6 +372,73 @@ builder_cache_commit (BuilderCache *self,
return res;
}
gboolean
builder_cache_get_outstanding_changes (BuilderCache *self,
GPtrArray **added_out,
GPtrArray **modified_out,
GPtrArray **removed_out,
GError **error)
{
g_autoptr(GPtrArray) added = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(GPtrArray) modified = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_diff_item_unref);
g_autoptr(GPtrArray) removed = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(GPtrArray) added_paths = g_ptr_array_new_with_free_func (g_free);
g_autoptr(GPtrArray) modified_paths = g_ptr_array_new_with_free_func (g_free);
g_autoptr(GPtrArray) removed_paths = g_ptr_array_new_with_free_func (g_free);
g_autoptr(GFile) last_root = NULL;
g_autoptr(GVariant) variant = NULL;
int i;
if (!ostree_repo_read_commit (self->repo, self->last_parent, &last_root, NULL, NULL, error))
return FALSE;
if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_COMMIT, self->last_parent,
&variant, NULL))
return FALSE;
if (!ostree_diff_dirs (OSTREE_DIFF_FLAGS_IGNORE_XATTRS,
last_root,
self->app_dir,
modified,
removed,
added,
NULL, error))
return FALSE;
for (i = 0; i < added->len; i++)
{
GFile *added_file = g_ptr_array_index (added, i);
char *path = g_file_get_relative_path (self->app_dir, added_file);
g_ptr_array_add (added_paths, path);
}
for (i = 0; i < modified->len; i++)
{
OstreeDiffItem *modified_item = g_ptr_array_index (modified, i);
char *path = g_file_get_relative_path (self->app_dir, modified_item->target);
g_ptr_array_add (modified_paths, path);
}
for (i = 0; i < removed->len; i++)
{
GFile *removed_file = g_ptr_array_index (removed, i);
char *path = g_file_get_relative_path (self->app_dir, removed_file);
g_ptr_array_add (removed_paths, path);
}
if (added_out)
*added_out = g_steal_pointer (&added_paths);
if (modified_out)
*modified_out = g_steal_pointer (&modified_paths);
if (removed_out)
*removed_out = g_steal_pointer (&removed_paths);
return TRUE;
}
GPtrArray *
builder_cache_get_changes (BuilderCache *self,
GError **error)

View File

@ -46,6 +46,11 @@ void builder_cache_ensure_checkout (BuilderCache *self);
gboolean builder_cache_commit (BuilderCache *self,
const char *body,
GError **error);
gboolean builder_cache_get_outstanding_changes (BuilderCache *self,
GPtrArray **added_out,
GPtrArray **modified_out,
GPtrArray **removed_out,
GError **error);
GPtrArray *builder_cache_get_changes (BuilderCache *self,
GError **error);
gboolean builder_gc (BuilderCache *self,

View File

@ -51,7 +51,6 @@ struct BuilderManifest {
char *desktop_file_name_prefix;
char *desktop_file_name_suffix;
gboolean writable_sdk;
gboolean strip;
char *command;
BuilderOptions *build_options;
GList *modules;
@ -78,7 +77,6 @@ enum {
PROP_MODULES,
PROP_CLEANUP,
PROP_CLEANUP_COMMANDS,
PROP_STRIP,
PROP_WRITABLE_SDK,
PROP_FINISH_ARGS,
PROP_RENAME_DESKTOP_FILE,
@ -167,10 +165,6 @@ builder_manifest_get_property (GObject *object,
g_value_set_boxed (value, self->finish_args);
break;
case PROP_STRIP:
g_value_set_boolean (value, self->strip);
break;
case PROP_WRITABLE_SDK:
g_value_set_boolean (value, self->writable_sdk);
break;
@ -269,10 +263,6 @@ builder_manifest_set_property (GObject *object,
g_strfreev (tmp);
break;
case PROP_STRIP:
self->strip = g_value_get_boolean (value);
break;
case PROP_WRITABLE_SDK:
self->writable_sdk = g_value_get_boolean (value);
break;
@ -391,13 +381,6 @@ builder_manifest_class_init (BuilderManifestClass *klass)
"",
G_TYPE_STRV,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_STRIP,
g_param_spec_boolean ("strip",
"",
"",
TRUE,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_WRITABLE_SDK,
g_param_spec_boolean ("writable-sdk",
@ -445,7 +428,6 @@ builder_manifest_class_init (BuilderManifestClass *klass)
static void
builder_manifest_init (BuilderManifest *self)
{
self->strip = TRUE;
}
static JsonNode *
@ -652,7 +634,6 @@ builder_manifest_checksum_for_cleanup (BuilderManifest *self,
builder_cache_checksum_boolean (cache, self->copy_icon);
builder_cache_checksum_str (cache, self->desktop_file_name_prefix);
builder_cache_checksum_str (cache, self->desktop_file_name_suffix);
builder_cache_checksum_boolean (cache, self->strip);
builder_cache_checksum_boolean (cache, self->writable_sdk);
for (l = self->modules; l != NULL; l = l->next)
@ -715,7 +696,7 @@ builder_manifest_build (BuilderManifest *self,
{
g_autofree char *body =
g_strdup_printf ("Built %s\n", builder_module_get_name (m));
if (!builder_module_build (m, keep_build_dir, context, error))
if (!builder_module_build (m, keep_build_dir, cache, context, error))
return FALSE;
if (!builder_cache_commit (cache, body, error))
return FALSE;
@ -865,42 +846,6 @@ foreach_file (BuilderManifest *self,
error);
}
static gboolean
strip_file_cb (BuilderManifest *self,
int source_parent_fd,
const char *source_name,
const char *full_dir,
const char *rel_dir,
struct stat *stbuf,
gboolean *found,
int depth,
GError **error)
{
if (S_ISREG (stbuf->st_mode))
{
g_autofree char *path = g_strconcat (full_dir, "/", source_name, NULL);
gboolean is_shared, is_stripped;
if (is_elf_file (path, &is_shared, &is_stripped) && !is_stripped)
{
g_autofree char *rel_path = g_strconcat (rel_dir, "/", source_name, NULL);
g_print ("stripping: %s\n", rel_path);
if (is_shared)
{
if (!strip (error, "--remove-section=.comment", "--remove-section=.note", "--strip-unneeded", path, NULL))
return FALSE;
}
else
{
if (!strip (error, "--remove-section=.comment", "--remove-section=.note", path, NULL))
return FALSE;
}
}
}
return TRUE;
}
static gboolean
rename_icon_cb (BuilderManifest *self,
int source_parent_fd,
@ -1005,12 +950,6 @@ builder_manifest_cleanup (BuilderManifest *self,
}
}
if (self->strip)
{
if (!foreach_file (self, strip_file_cb, NULL, app_root, error))
return FALSE;
}
if (self->rename_desktop_file != NULL)
{
g_autoptr(GFile) applications_dir = g_file_resolve_relative_path (app_root, "share/applications");

View File

@ -31,6 +31,7 @@
#include "libglnx/libglnx.h"
#include "libgsystem.h"
#include "xdg-app-utils.h"
#include "builder-utils.h"
#include "builder-module.h"
@ -600,9 +601,102 @@ build (GFile *app_dir,
return TRUE;
}
static gboolean
builder_module_handle_debuginfo (BuilderModule *self,
GFile *app_dir,
BuilderCache *cache,
BuilderContext *context,
GError **error)
{
g_autofree char *app_dir_path = g_file_get_path (app_dir);
int i;
g_autoptr(GPtrArray) added = NULL;
g_autoptr(GPtrArray) modified = NULL;
g_autoptr(GPtrArray) added_or_modified = g_ptr_array_new ();
if (!builder_cache_get_outstanding_changes (cache, &added, &modified, NULL, error))
return FALSE;
for (i = 0; i < added->len; i++)
g_ptr_array_add (added_or_modified, g_ptr_array_index (added, i));
for (i = 0; i < modified->len; i++)
g_ptr_array_add (added_or_modified, g_ptr_array_index (modified, i));
g_ptr_array_sort (added_or_modified, xdg_app_strcmp0_ptr);
for (i = 0; i < added_or_modified->len; i++)
{
const char *rel_path = (char *)g_ptr_array_index (added_or_modified, i);
g_autoptr(GFile) file = g_file_resolve_relative_path (app_dir, rel_path);
g_autofree char *path = g_file_get_path (file);
g_autofree char *debug_path = NULL;
g_autofree char *real_debug_path = NULL;
gboolean is_shared, is_stripped;
if (is_elf_file (path, &is_shared, &is_stripped))
{
if (builder_options_get_strip (self->build_options, context))
{
g_print ("stripping: %s\n", rel_path);
if (is_shared)
{
if (!strip (error, "--remove-section=.comment", "--remove-section=.note", "--strip-unneeded", path, NULL))
return FALSE;
}
else
{
if (!strip (error, "--remove-section=.comment", "--remove-section=.note", path, NULL))
return FALSE;
}
}
else if (!builder_options_get_no_debuginfo (self->build_options, context))
{
g_autofree char *rel_path_dir = g_path_get_dirname (rel_path);
g_autofree char *filename = g_path_get_basename (rel_path);
g_autofree char *filename_debug = g_strconcat (filename, ".debug", NULL);
g_autofree char *debug_dir = NULL;
g_autofree char *real_debug_dir = NULL;
if (g_str_has_prefix (rel_path_dir, "files/"))
{
debug_dir = g_build_filename (app_dir_path, "files/lib/debug", rel_path_dir + strlen("files/"), NULL);
real_debug_dir = g_build_filename ("/app/lib/debug", rel_path_dir + strlen("files/"), NULL);
}
else if (g_str_has_prefix (rel_path_dir, "usr/"))
{
debug_dir = g_build_filename (app_dir_path, "usr/lib/debug", rel_path_dir + strlen("usr/"), NULL);
real_debug_dir = g_build_filename ("/usr/lib/debug", rel_path_dir + strlen("usr/"), NULL);
}
if (debug_dir)
{
if (g_mkdir_with_parents (debug_dir, 0755) != 0)
{
glnx_set_error_from_errno (error);
return FALSE;
}
debug_path = g_build_filename (debug_dir, filename_debug, NULL);
real_debug_path = g_build_filename (real_debug_dir, filename_debug, NULL);
g_print ("stripping %s to %s\n", path, debug_path);
eu_strip (error, "--remove-comment", "--reloc-debug-sections",
"-f", debug_path,
"-F", real_debug_path,
path, NULL);
}
}
}
}
return TRUE;
}
gboolean
builder_module_build (BuilderModule *self,
gboolean keep_build_dir,
BuilderCache *cache,
BuilderContext *context,
GError **error)
{
@ -807,6 +901,8 @@ builder_module_build (BuilderModule *self,
make_l = g_strdup_printf ("-l%d", 2*builder_context_get_n_cpu (context));
}
/* Build and install */
if (!build (app_dir, source_dir, build_dir, build_args, env, error,
"make", make_j?make_j:skip_arg, make_l?make_l:skip_arg, strv_arg, self->make_args, NULL))
return FALSE;
@ -815,6 +911,8 @@ builder_module_build (BuilderModule *self,
"make", "install", strv_arg, self->make_install_args, NULL))
return FALSE;
/* Post installation scripts */
if (self->post_install)
{
for (i = 0; self->post_install[i] != NULL; i++)
@ -825,6 +923,11 @@ builder_module_build (BuilderModule *self,
}
}
if (!builder_module_handle_debuginfo (self, app_dir, cache, context, error))
return FALSE;
/* Clean up build dir */
if (keep_build_dir)
{
g_autofree char *buildname_link = g_strdup_printf ("build-%s", self->name);

View File

@ -55,6 +55,7 @@ gboolean builder_module_extract_sources (BuilderModule *self,
GError **error);
gboolean builder_module_build (BuilderModule *self,
gboolean keep_build_dir,
BuilderCache *cache,
BuilderContext *context,
GError **error);
gboolean builder_module_update (BuilderModule *self,

View File

@ -35,6 +35,8 @@
struct BuilderOptions {
GObject parent;
gboolean strip;
gboolean no_debuginfo;
char *cflags;
char *cxxflags;
char *prefix;
@ -58,6 +60,8 @@ enum {
PROP_CXXFLAGS,
PROP_PREFIX,
PROP_ENV,
PROP_STRIP,
PROP_NO_DEBUGINFO,
PROP_ARCH,
PROP_BUILD_ARGS,
LAST_PROP
@ -112,6 +116,14 @@ builder_options_get_property (GObject *object,
g_value_set_boxed (value, self->build_args);
break;
case PROP_STRIP:
g_value_set_boolean (value, self->strip);
break;
case PROP_NO_DEBUGINFO:
g_value_set_boolean (value, self->no_debuginfo);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@ -161,6 +173,14 @@ builder_options_set_property (GObject *object,
g_strfreev (tmp);
break;
case PROP_STRIP:
self->strip = g_value_get_boolean (value);
break;
case PROP_NO_DEBUGINFO:
self->no_debuginfo = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@ -217,6 +237,20 @@ builder_options_class_init (BuilderOptionsClass *klass)
"",
G_TYPE_STRV,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_STRIP,
g_param_spec_boolean ("strip",
"",
"",
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_STRIP,
g_param_spec_boolean ("no-debuginfo",
"",
"",
FALSE,
G_PARAM_READWRITE));
}
static void
@ -474,6 +508,38 @@ builder_options_get_prefix (BuilderOptions *self, BuilderContext *context)
return "/app";
}
gboolean
builder_options_get_strip (BuilderOptions *self, BuilderContext *context)
{
g_autoptr(GList) options = get_all_options (self, context);
GList *l;
for (l = options; l != NULL; l = l->next)
{
BuilderOptions *o = l->data;
if (o->strip)
return TRUE;
}
return FALSE;
}
gboolean
builder_options_get_no_debuginfo (BuilderOptions *self, BuilderContext *context)
{
g_autoptr(GList) options = get_all_options (self, context);
GList *l;
for (l = options; l != NULL; l = l->next)
{
BuilderOptions *o = l->data;
if (o->no_debuginfo)
return TRUE;
}
return FALSE;
}
char **
builder_options_get_env (BuilderOptions *self, BuilderContext *context)
{
@ -552,6 +618,8 @@ builder_options_checksum (BuilderOptions *self,
builder_cache_checksum_str (cache, self->prefix);
builder_cache_checksum_strv (cache, self->env);
builder_cache_checksum_strv (cache, self->build_args);
builder_cache_checksum_boolean (cache, self->strip);
builder_cache_checksum_boolean (cache, self->no_debuginfo);
arch_options = g_hash_table_lookup (self->arch, builder_context_get_arch (context));
if (arch_options)

View File

@ -38,19 +38,23 @@ typedef struct BuilderOptions BuilderOptions;
GType builder_options_get_type (void);
const char *builder_options_get_cflags (BuilderOptions *self,
BuilderContext *context);
const char *builder_options_get_cxxflags (BuilderOptions *self,
BuilderContext *context);
const char *builder_options_get_prefix (BuilderOptions *self,
BuilderContext *context);
char ** builder_options_get_env (BuilderOptions *self,
BuilderContext *context);
char ** builder_options_get_build_args (BuilderOptions *self,
BuilderContext *context);
void builder_options_checksum (BuilderOptions *self,
BuilderCache *cache,
BuilderContext *context);
const char *builder_options_get_cflags (BuilderOptions *self,
BuilderContext *context);
const char *builder_options_get_cxxflags (BuilderOptions *self,
BuilderContext *context);
const char *builder_options_get_prefix (BuilderOptions *self,
BuilderContext *context);
char ** builder_options_get_env (BuilderOptions *self,
BuilderContext *context);
char ** builder_options_get_build_args (BuilderOptions *self,
BuilderContext *context);
void builder_options_checksum (BuilderOptions *self,
BuilderCache *cache,
BuilderContext *context);
gboolean builder_options_get_no_debuginfo (BuilderOptions *self,
BuilderContext *context);
gboolean builder_options_get_strip (BuilderOptions *self,
BuilderContext *context);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(BuilderOptions, g_object_unref)

View File

@ -133,6 +133,20 @@ strip (GError **error,
return res;
}
gboolean
eu_strip (GError **error,
...)
{
gboolean res;
va_list ap;
va_start (ap, error);
res = xdg_app_spawn (NULL, NULL, error, "eu-strip", ap);
va_end (ap);
return res;
}
static gboolean elf_has_symtab (Elf *elf)
{
Elf_Scn *scn;

View File

@ -33,8 +33,8 @@ char *builder_uri_to_filename (const char *uri);
const char *path_prefix_match (const char *pattern,
const char *string);
gboolean strip (GError **error,
...);
gboolean strip (GError **error, ...);
gboolean eu_strip (GError **error, ...);
gboolean is_elf_file (const char *path,
gboolean *is_shared,

View File

@ -149,10 +149,6 @@
<term><option>finish-args</option></term>
<listitem><para>An array of arguments passed to the <command>xdg-app build-finish</command> command</para></listitem>
</varlistentry>
<varlistentry>
<term><option>strip</option></term>
<listitem><para>If this is true (the default) then all ELF files will be stripped during the cleanup phase.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>rename-desktop-file</option></term>
<listitem><para>Any desktop file with this name will be renamed to a name based on app-id during the cleanup phase.</para></listitem>
@ -202,6 +198,14 @@
<term><option>env</option></term>
<listitem><para>This is a dictionary defining environment variables to be set during the build.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>strip</option></term>
<listitem><para>If this is true (the default is false) then all ELF files will be stripped after install.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>no-debuginfo</option></term>
<listitem><para>If this is true (the default is false) and strip is not set then all ELF files will have their debug info extracted to a separate file.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>arch</option></term>
<listitem><para>This is a dictionary defining for each arch a separate build options object that override the main one</para></listitem>