[gnome-builder] libide: use makecache to extract build flags from autotools



commit 03e0835d025bfab3a0f353f63d0358fd782421b9
Author: Christian Hergert <christian hergert me>
Date:   Sun Mar 1 18:01:37 2015 -0800

    libide: use makecache to extract build flags from autotools
    
    This implements the IdeBuildSystem::get_build_flags_async() and
    IdeBuildSystem::get_build_flags_finish() virtual functions using the
    makecache module.
    
    TODO:
    
    We should invalidate the makecache when we discover a makefile has been
    changed (or configure.ac/dependency).

 libide/autotools/ide-autotools-build-system.c |  350 +++++++++++++++++++++++--
 1 files changed, 331 insertions(+), 19 deletions(-)
---
diff --git a/libide/autotools/ide-autotools-build-system.c b/libide/autotools/ide-autotools-build-system.c
index 3784fe6..e636c45 100644
--- a/libide/autotools/ide-autotools-build-system.c
+++ b/libide/autotools/ide-autotools-build-system.c
@@ -20,14 +20,20 @@
 #include <gio/gio.h>
 
 #include "ide-autotools-build-system.h"
+#include "ide-autotools-builder.h"
 #include "ide-context.h"
 #include "ide-device.h"
-
-#include "autotools/ide-autotools-builder.h"
+#include "ide-device-manager.h"
+#include "ide-file.h"
+#include "ide-makecache.h"
 
 typedef struct
 {
-  gchar *tarball_name;
+  IdeMakecache *makecache;
+  gchar        *tarball_name;
+  GPtrArray    *makecache_tasks;
+
+  guint         makecache_in_progress : 1;
 } IdeAutotoolsBuildSystemPrivate;
 
 static void async_initable_iface_init (GAsyncInitableIface *iface);
@@ -195,6 +201,322 @@ ide_autotools_build_system_discover_file_finish (IdeAutotoolsBuildSystem  *syste
 }
 
 static void
+ide_autotools_build_system__bootstrap_cb (GObject      *object,
+                                          GAsyncResult *result,
+                                          gpointer      user_data)
+{
+  IdeAutotoolsBuilder *builder = (IdeAutotoolsBuilder *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(GFile) build_directory = NULL;
+  g_autoptr(GFile) makefile = NULL;
+  GError *error = NULL;
+
+  g_assert (IDE_IS_AUTOTOOLS_BUILDER (builder));
+  g_assert (G_IS_TASK (task));
+
+  if (!ide_autotools_builder_bootstrap_finish (builder, result, &error))
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  build_directory = ide_autotools_builder_get_build_directory (builder);
+  makefile = g_file_get_child (build_directory, "Makefile");
+
+  g_task_return_pointer (task, g_object_ref (makefile), g_object_unref);
+}
+
+static void
+ide_autotools_build_system_get_local_makefile_async (IdeAutotoolsBuildSystem *self,
+                                                     GCancellable            *cancellable,
+                                                     GAsyncReadyCallback      callback,
+                                                     gpointer                 user_data)
+{
+  IdeContext *context;
+  IdeDeviceManager *device_manager;
+  IdeDevice *device;
+  g_autoptr(GTask) task = NULL;
+  g_autoptr(IdeBuilder) builder = NULL;
+  g_autoptr(GKeyFile) config = NULL;
+  g_autoptr(GFile) build_directory = NULL;
+  g_autoptr(GFile) makefile = NULL;
+  GError *error = NULL;
+
+  g_return_if_fail (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (self));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  device_manager = ide_context_get_device_manager (context);
+  device = ide_device_manager_get_device (device_manager, "local");
+  config = g_key_file_new ();
+  builder = ide_autotools_build_system_get_builder (IDE_BUILD_SYSTEM (self), config, device, &error);
+
+  if (!builder)
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  /*
+   * If we haven't yet bootstrapped the project, let's go ahead and do that now.
+   */
+  if (ide_autotools_builder_get_needs_bootstrap (IDE_AUTOTOOLS_BUILDER (builder)))
+    {
+      ide_autotools_builder_bootstrap_async (IDE_AUTOTOOLS_BUILDER (builder),
+                                             cancellable,
+                                             ide_autotools_build_system__bootstrap_cb,
+                                             g_object_ref (task));
+      return;
+    }
+
+  build_directory = ide_autotools_builder_get_build_directory (IDE_AUTOTOOLS_BUILDER (builder));
+  makefile = g_file_get_child (build_directory, "Makefile");
+
+  g_task_return_pointer (task, g_object_ref (makefile), g_object_unref);
+}
+
+static GFile *
+ide_autotools_build_system_get_local_makefile_finish (IdeAutotoolsBuildSystem  *self,
+                                                      GAsyncResult             *result,
+                                                      GError                  **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_return_val_if_fail (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (self), NULL);
+
+  return g_task_propagate_pointer (task, error);
+}
+
+static void
+ide_autotools_build_system__makecache_new_cb (GObject      *object,
+                                              GAsyncResult *result,
+                                              gpointer      user_data)
+{
+  IdeAutotoolsBuildSystemPrivate *priv;
+  IdeAutotoolsBuildSystem *self;
+  g_autoptr(IdeMakecache) makecache = NULL;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(GPtrArray) tasks = NULL;
+  GError *error = NULL;
+
+  g_assert (G_IS_TASK (task));
+
+  makecache = ide_makecache_new_for_makefile_finish (result, &error);
+
+  if (!makecache)
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  /*
+   * Complete all of the pending tasks in flight.
+   */
+
+  self = g_task_get_source_object (task);
+  priv = ide_autotools_build_system_get_instance_private (self);
+
+  tasks = priv->makecache_tasks;
+  priv->makecache_tasks = g_ptr_array_new ();
+  priv->makecache_in_progress = FALSE;
+
+  g_task_return_pointer (task, g_object_ref (makecache), g_object_unref);
+
+  while (tasks->len)
+    {
+      GTask *other_task;
+      gsize i = tasks->len - 1;
+
+      other_task = g_ptr_array_index (tasks, i);
+      g_task_return_pointer (other_task, g_object_ref (makecache), g_object_unref);
+      g_ptr_array_remove_index (tasks, i);
+      g_object_unref (other_task);
+    }
+}
+
+static void
+ide_autotools_build_system__local_makefile_cb (GObject      *object,
+                                               GAsyncResult *result,
+                                               gpointer      user_data)
+{
+  IdeAutotoolsBuildSystem *self = (IdeAutotoolsBuildSystem *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(GFile) makefile = NULL;
+  IdeContext *context;
+  GError *error = NULL;
+
+  g_assert (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (self));
+  g_assert (G_IS_TASK (task));
+
+  makefile = ide_autotools_build_system_get_local_makefile_finish (self, result, &error);
+
+  if (!makefile)
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  ide_makecache_new_for_makefile_async (context,
+                                        makefile,
+                                        g_task_get_cancellable (task),
+                                        ide_autotools_build_system__makecache_new_cb,
+                                        g_object_ref (task));
+}
+
+static void
+ide_autotools_build_system_get_makecache_async (IdeAutotoolsBuildSystem *self,
+                                                GCancellable            *cancellable,
+                                                GAsyncReadyCallback      callback,
+                                                gpointer                 user_data)
+{
+  IdeAutotoolsBuildSystemPrivate *priv = ide_autotools_build_system_get_instance_private (self);
+  g_autoptr(GTask) task = NULL;
+
+  g_return_if_fail (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (self));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  /*
+   * If we already have the makecache loaded, we can just return that.
+   */
+  if (priv->makecache)
+    {
+      g_task_return_pointer (task, g_object_ref (priv->makecache), g_object_unref);
+      return;
+    }
+
+  /*
+   * If we have a makecache operation in progress, we need to queue the task to be completed
+   * when that operation completes.
+   */
+  if (priv->makecache_in_progress)
+    {
+      g_ptr_array_add (priv->makecache_tasks, g_object_ref (task));
+      return;
+    }
+
+  /*
+   * Nothing else is creating the makecache, so let's go ahead and create it now.
+   */
+  priv->makecache_in_progress = TRUE;
+  ide_autotools_build_system_get_local_makefile_async (self,
+                                                       cancellable,
+                                                       ide_autotools_build_system__local_makefile_cb,
+                                                       g_object_ref (task));
+}
+
+static IdeMakecache *
+ide_autotools_build_system_get_makecache_finish (IdeAutotoolsBuildSystem  *self,
+                                                 GAsyncResult             *result,
+                                                 GError                  **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_return_val_if_fail (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (self), NULL);
+  g_return_val_if_fail (G_IS_TASK (task), NULL);
+
+  return g_task_propagate_pointer (task, error);
+}
+
+static void
+ide_autotools_build_system__get_file_flags_cb (GObject      *object,
+                                               GAsyncResult *result,
+                                               gpointer      user_data)
+{
+  IdeMakecache *makecache = (IdeMakecache *)object;
+  g_autoptr(GTask) task = user_data;
+  gchar **flags;
+  GError *error = NULL;
+
+  g_assert (IDE_IS_MAKECACHE (makecache));
+  g_assert (G_IS_TASK (task));
+
+  flags = ide_makecache_get_file_flags_finish (makecache, result, &error);
+
+  if (!flags)
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  g_task_return_pointer (task, flags, (GDestroyNotify)g_strfreev);
+}
+
+static void
+ide_autotools_build_system__makecache_cb (GObject      *object,
+                                          GAsyncResult *result,
+                                          gpointer      user_data)
+{
+  IdeAutotoolsBuildSystem *self = (IdeAutotoolsBuildSystem *)object;
+  g_autoptr(IdeMakecache) makecache = NULL;
+  g_autoptr(GTask) task = user_data;
+  GError *error = NULL;
+  GFile *file;
+
+  g_assert (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (self));
+  g_assert (G_IS_TASK (task));
+
+  makecache = ide_autotools_build_system_get_makecache_finish (self, result, &error);
+
+  if (!makecache)
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  file = g_task_get_task_data (task);
+  g_assert (G_IS_FILE (file));
+
+  ide_makecache_get_file_flags_async (makecache,
+                                      file,
+                                      g_task_get_cancellable (task),
+                                      ide_autotools_build_system__get_file_flags_cb,
+                                      g_object_ref (task));
+}
+
+static void
+ide_autotools_build_system_get_build_flags_async (IdeBuildSystem      *build_system,
+                                                  IdeFile             *file,
+                                                  GCancellable        *cancellable,
+                                                  GAsyncReadyCallback  callback,
+                                                  gpointer             user_data)
+{
+  IdeAutotoolsBuildSystem *self = (IdeAutotoolsBuildSystem *)build_system;
+  g_autoptr(GTask) task = NULL;
+  GFile *gfile;
+
+  g_assert (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (self));
+  g_assert (IDE_IS_FILE (file));
+
+  gfile = ide_file_get_file (file);
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_task_data (task, g_object_ref (gfile), g_object_unref);
+
+  ide_autotools_build_system_get_makecache_async (self,
+                                                  cancellable,
+                                                  ide_autotools_build_system__makecache_cb,
+                                                  g_object_ref (task));
+}
+
+static gchar **
+ide_autotools_build_system_get_build_flags_finish (IdeBuildSystem  *build_system,
+                                                   GAsyncResult    *result,
+                                                   GError         **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_assert (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (build_system));
+  g_assert (G_IS_TASK (task));
+
+  return g_task_propagate_pointer (task, error);
+}
+
+static void
 ide_autotools_build_system_finalize (GObject *object)
 {
   IdeAutotoolsBuildSystemPrivate *priv;
@@ -203,6 +525,7 @@ ide_autotools_build_system_finalize (GObject *object)
   priv = ide_autotools_build_system_get_instance_private (system);
 
   g_clear_pointer (&priv->tarball_name, g_free);
+  g_clear_pointer (&priv->makecache_tasks, g_ptr_array_unref);
 
   G_OBJECT_CLASS (ide_autotools_build_system_parent_class)->finalize (object);
 }
@@ -228,21 +551,6 @@ ide_autotools_build_system_get_property (GObject    *object,
 }
 
 static void
-ide_autotools_build_system_set_property (GObject      *object,
-                                         guint         prop_id,
-                                         const GValue *value,
-                                         GParamSpec   *pspec)
-{
-  //IdeAutotoolsBuildSystem *self = IDE_AUTOTOOLS_BUILD_SYSTEM (object);
-
-  switch (prop_id)
-    {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-    }
-}
-
-static void
 ide_autotools_build_system_class_init (IdeAutotoolsBuildSystemClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -250,9 +558,10 @@ ide_autotools_build_system_class_init (IdeAutotoolsBuildSystemClass *klass)
 
   object_class->finalize = ide_autotools_build_system_finalize;
   object_class->get_property = ide_autotools_build_system_get_property;
-  object_class->set_property = ide_autotools_build_system_set_property;
 
   build_system_class->get_builder = ide_autotools_build_system_get_builder;
+  build_system_class->get_build_flags_async = ide_autotools_build_system_get_build_flags_async;
+  build_system_class->get_build_flags_finish = ide_autotools_build_system_get_build_flags_finish;
 
   gParamSpecs [PROP_TARBALL_NAME] =
     g_param_spec_string ("tarball-name",
@@ -267,6 +576,9 @@ ide_autotools_build_system_class_init (IdeAutotoolsBuildSystemClass *klass)
 static void
 ide_autotools_build_system_init (IdeAutotoolsBuildSystem *self)
 {
+  IdeAutotoolsBuildSystemPrivate *priv = ide_autotools_build_system_get_instance_private (self);
+
+  priv->makecache_tasks = g_ptr_array_new ();
 }
 
 static void


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