[gnome-builder] pipeline: add IdeBuildStage:check-stdout



commit 230954077d461df81e502e9d0eeb768e406f36b7
Author: Christian Hergert <chergert redhat com>
Date:   Fri Mar 24 21:48:29 2017 -0700

    pipeline: add IdeBuildStage:check-stdout
    
    This property is used to notify the pipeline that it needs to look at
    stdout to extract errors using the error regexes. Typical build systems
    such as make, will pass stderr on to the caller. However, others like
    Ninja coalesce everything into a single stream, complicating the matter.
    
    This means we burn extra overhead parsing stdout, but in practice, the
    output we get from ninja is small enough that it should be roughly
    equivalent.

 libide/buildsystem/ide-build-pipeline.c |   32 ++++++++++++++++--
 libide/buildsystem/ide-build-stage.c    |   54 +++++++++++++++++++++++++++++++
 libide/buildsystem/ide-build-stage.h    |    3 ++
 3 files changed, 86 insertions(+), 3 deletions(-)
---
diff --git a/libide/buildsystem/ide-build-pipeline.c b/libide/buildsystem/ide-build-pipeline.c
index 763e331..e109323 100644
--- a/libide/buildsystem/ide-build-pipeline.c
+++ b/libide/buildsystem/ide-build-pipeline.c
@@ -201,6 +201,13 @@ struct _IdeBuildPipeline
    * If we are in the middle of a clean operation.
    */
   guint in_clean : 1;
+
+  /*
+   * Precalculation if we need to look for errors on stdout. We can't rely
+   * on @current_stage for this, becase log entries might come in
+   * asynchronously and after the processes/stage has completed.
+   */
+  guint errors_on_stdout : 1;
 };
 
 typedef enum
@@ -425,7 +432,7 @@ create_diagnostic (IdeBuildPipeline *self,
       if (g_str_has_prefix (basedir, self->errfmt_top_dir))
         {
           basedir += strlen (self->errfmt_top_dir);
-          if (*basedir == '/')
+          if (*basedir == G_DIR_SEPARATOR)
             basedir++;
         }
 
@@ -466,8 +473,8 @@ ide_build_pipeline_log_observer (IdeBuildLogStream  stream,
                                  gpointer           user_data)
 {
   IdeBuildPipeline *self = user_data;
-  const gchar *enterdir;
   g_autofree gchar *filtered_message = NULL;
+  const gchar *enterdir;
 
   g_assert (stream == IDE_BUILD_LOG_STDOUT || stream == IDE_BUILD_LOG_STDERR);
   g_assert (IDE_IS_BUILD_PIPELINE (self));
@@ -519,7 +526,13 @@ ide_build_pipeline_log_observer (IdeBuildLogStream  stream,
           return;
         }
     }
-  else if (stream == IDE_BUILD_LOG_STDERR)
+
+  /*
+   * Unfortunately, some build engines such as Ninja refuse to pass errors on
+   * stderr like the tooling they abstract. So we must parse stdout in addition
+   * to stderr to extract errors.
+   */
+  if (stream == IDE_BUILD_LOG_STDERR || self->errors_on_stdout)
     {
       for (guint i = 0; i < self->errfmts->len; i++)
         {
@@ -664,6 +677,19 @@ ide_build_pipeline_real_started (IdeBuildPipeline *self)
 
   g_assert (IDE_IS_BUILD_PIPELINE (self));
 
+  self->errors_on_stdout = FALSE;
+
+  for (guint i = 0; i < self->pipeline->len; i++)
+    {
+      PipelineEntry *entry = &g_array_index (self->pipeline, PipelineEntry, i);
+
+      if (ide_build_stage_get_check_stdout (entry->stage))
+        {
+          self->errors_on_stdout = TRUE;
+          break;
+        }
+    }
+
   IDE_EXIT;
 }
 
diff --git a/libide/buildsystem/ide-build-stage.c b/libide/buildsystem/ide-build-stage.c
index b91ab2e..e0742be 100644
--- a/libide/buildsystem/ide-build-stage.c
+++ b/libide/buildsystem/ide-build-stage.c
@@ -37,12 +37,14 @@ typedef struct
   guint                completed : 1;
   guint                disabled : 1;
   guint                transient : 1;
+  guint                check_stdout : 1;
 } IdeBuildStagePrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (IdeBuildStage, ide_build_stage, IDE_TYPE_OBJECT)
 
 enum {
   PROP_0,
+  PROP_CHECK_STDOUT,
   PROP_COMPLETED,
   PROP_DISABLED,
   PROP_NAME,
@@ -265,6 +267,10 @@ ide_build_stage_get_property (GObject    *object,
 
   switch (prop_id)
     {
+    case PROP_CHECK_STDOUT:
+      g_value_set_boolean (value, ide_build_stage_get_check_stdout (self));
+      break;
+
     case PROP_COMPLETED:
       g_value_set_boolean (value, ide_build_stage_get_completed (self));
       break;
@@ -296,6 +302,10 @@ ide_build_stage_set_property (GObject      *object,
 
   switch (prop_id)
     {
+    case PROP_CHECK_STDOUT:
+      ide_build_stage_set_check_stdout (self, g_value_get_boolean (value));
+      break;
+
     case PROP_COMPLETED:
       ide_build_stage_set_completed (self, g_value_get_boolean (value));
       break;
@@ -334,6 +344,23 @@ ide_build_stage_class_init (IdeBuildStageClass *klass)
   klass->chain = ide_build_stage_real_chain;
 
   /**
+   * IdeBuildStage:check-stdout:
+   *
+   * Most build systems will preserve stderr for the processes they call, such
+   * as gcc, clang, and others. However, if your build system redirects all
+   * output to stdout, you may need to set this property to %TRUE to ensure
+   * that Builder will extract errors from stdout.
+   *
+   * One such example is Ninja.
+   */
+  properties [PROP_CHECK_STDOUT] =
+    g_param_spec_boolean ("check-stdout",
+                         "Check STDOUT",
+                         "If STDOUT should be checked for errors using error regexes",
+                         FALSE,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  /**
    * IdeBuildStage:completed:
    *
    * The "completed" property is set to %TRUE after the pipeline has
@@ -999,3 +1026,30 @@ ide_build_stage_set_disabled (IdeBuildStage *self,
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DISABLED]);
     }
 }
+
+gboolean
+ide_build_stage_get_check_stdout (IdeBuildStage *self)
+{
+  IdeBuildStagePrivate *priv = ide_build_stage_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_BUILD_STAGE (self), FALSE);
+
+  return priv->check_stdout;
+}
+
+void
+ide_build_stage_set_check_stdout (IdeBuildStage *self,
+                                  gboolean       check_stdout)
+{
+  IdeBuildStagePrivate *priv = ide_build_stage_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_BUILD_STAGE (self));
+
+  check_stdout = !!check_stdout;
+
+  if (check_stdout != priv->check_stdout)
+    {
+      priv->check_stdout = check_stdout;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CHECK_STDOUT]);
+    }
+}
diff --git a/libide/buildsystem/ide-build-stage.h b/libide/buildsystem/ide-build-stage.h
index 832dc61..57e6b6a 100644
--- a/libide/buildsystem/ide-build-stage.h
+++ b/libide/buildsystem/ide-build-stage.h
@@ -192,6 +192,9 @@ void           ide_build_stage_set_completed    (IdeBuildStage        *self,
 gboolean       ide_build_stage_get_disabled     (IdeBuildStage        *self);
 void           ide_build_stage_set_disabled     (IdeBuildStage        *self,
                                                  gboolean              disabled);
+gboolean       ide_build_stage_get_check_stdout (IdeBuildStage        *self);
+void           ide_build_stage_set_check_stdout (IdeBuildStage        *self,
+                                                 gboolean              check_stdout);
 gboolean       ide_build_stage_get_transient    (IdeBuildStage        *self);
 void           ide_build_stage_set_transient    (IdeBuildStage        *self,
                                                  gboolean              transient);


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