[gnome-builder] plugins/meson: port to GTK 4
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] plugins/meson: port to GTK 4
- Date: Tue, 12 Jul 2022 06:39:17 +0000 (UTC)
commit 4693f7dc83715c7bb021f5cdc51c8def220d02d5
Author: Christian Hergert <chergert redhat com>
Date: Mon Jul 11 23:06:30 2022 -0700
plugins/meson: port to GTK 4
- Remove libdazzle usage
- Remove unnecessary Since: docs
- Implement introspection support
- Use run commands to access introspection
- Use pipeline addin to register introspection stage
- Cleanup meson discovery
- Remove test provider
src/plugins/meson/gbp-meson-build-system.c | 101 ++-
src/plugins/meson/gbp-meson-build-system.h | 8 +-
.../meson/gbp-meson-build-target-provider.c | 14 +-
src/plugins/meson/gbp-meson-introspection.c | 682 +++++++++++++++++++++
src/plugins/meson/gbp-meson-introspection.h | 40 ++
src/plugins/meson/gbp-meson-pipeline-addin.c | 347 +++++------
src/plugins/meson/gbp-meson-pipeline-addin.h | 4 +
src/plugins/meson/gbp-meson-run-command-provider.c | 171 ++++++
...provider.h => gbp-meson-run-command-provider.h} | 8 +-
src/plugins/meson/gbp-meson-test-provider.c | 655 --------------------
src/plugins/meson/gbp-meson-test.c | 198 ------
src/plugins/meson/gbp-meson-test.h | 36 --
.../gbp-meson-toolchain-edition-preferences-row.c | 2 -
src/plugins/meson/gbp-meson-toolchain.c | 2 -
src/plugins/meson/meson-plugin.c | 25 +-
src/plugins/meson/meson.build | 17 +-
src/plugins/meson/meson.plugin | 5 +-
17 files changed, 1206 insertions(+), 1109 deletions(-)
---
diff --git a/src/plugins/meson/gbp-meson-build-system.c b/src/plugins/meson/gbp-meson-build-system.c
index ee7dfd18e..df26e691b 100644
--- a/src/plugins/meson/gbp-meson-build-system.c
+++ b/src/plugins/meson/gbp-meson-build-system.c
@@ -20,8 +20,11 @@
#define G_LOG_DOMAIN "gbp-meson-build-system"
+#include "config.h"
+
#include <glib/gi18n.h>
#include <json-glib/json-glib.h>
+#include <string.h>
#include "gbp-meson-build-system.h"
#include "gbp-meson-build-target.h"
@@ -29,20 +32,20 @@
struct _GbpMesonBuildSystem
{
- IdeObject parent_instance;
- GFile *project_file;
- IdeCompileCommands *compile_commands;
- GFileMonitor *monitor;
- gchar *project_version;
- gchar **languages;
+ IdeObject parent_instance;
+ GFile *project_file;
+ IdeCompileCommands *compile_commands;
+ GFileMonitor *monitor;
+ char *project_version;
+ char **languages;
};
static void async_initable_iface_init (GAsyncInitableIface *iface);
static void build_system_iface_init (IdeBuildSystemInterface *iface);
G_DEFINE_FINAL_TYPE_WITH_CODE (GbpMesonBuildSystem, gbp_meson_build_system, IDE_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
- G_IMPLEMENT_INTERFACE (IDE_TYPE_BUILD_SYSTEM, build_system_iface_init))
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_BUILD_SYSTEM, build_system_iface_init))
enum {
PROP_0,
@@ -983,3 +986,85 @@ gbp_meson_build_system_get_languages (GbpMesonBuildSystem *self)
return (const gchar * const *)self->languages;
}
+
+char *
+gbp_meson_build_system_get_project_dir (GbpMesonBuildSystem *self)
+{
+ g_autoptr(GFile) workdir = NULL;
+ g_autofree char *base = NULL;
+ IdeContext *context;
+
+ g_return_val_if_fail (GBP_IS_MESON_BUILD_SYSTEM (self), NULL);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ workdir = ide_context_ref_workdir (context);
+
+ if (self->project_file == NULL)
+ return g_strdup (g_file_peek_path (workdir));
+
+ base = g_file_get_basename (self->project_file);
+
+ if (strcasecmp (base, "meson.build") == 0)
+ {
+ g_autoptr(GFile) parent = g_file_get_parent (self->project_file);
+ return g_file_get_path (parent);
+ }
+
+ return g_file_get_path (self->project_file);
+}
+
+char *
+gbp_meson_build_system_locate_meson (GbpMesonBuildSystem *self,
+ IdePipeline *pipeline)
+{
+ IdeConfig *config;
+
+ g_return_val_if_fail (!self || GBP_IS_MESON_BUILD_SYSTEM (self), NULL);
+ g_return_val_if_fail (!pipeline || IDE_IS_PIPELINE (pipeline), NULL);
+
+ if ((config = ide_pipeline_get_config (pipeline)))
+ {
+ const char *envvar = ide_config_getenv (config, "MESON");
+
+ if (envvar != NULL)
+ return g_strdup (envvar);
+ }
+
+ return g_strdup ("meson");
+}
+
+char *
+gbp_meson_build_system_locate_ninja (GbpMesonBuildSystem *self,
+ IdePipeline *pipeline)
+{
+ IdeConfig *config = NULL;
+
+ g_return_val_if_fail (!self || GBP_IS_MESON_BUILD_SYSTEM (self), NULL);
+ g_return_val_if_fail (!pipeline || IDE_IS_PIPELINE (pipeline), NULL);
+
+ if (pipeline != NULL && config == NULL)
+ config = ide_pipeline_get_config (pipeline);
+
+ /* First check NINJA=path override in IdeConfig */
+ if (config != NULL)
+ {
+ const char *envvar = ide_config_getenv (config, "NINJA");
+
+ if (envvar != NULL)
+ return g_strdup (envvar);
+ }
+
+ if (pipeline != NULL)
+ {
+ static const char *known_aliases[] = { "ninja", "ninja-build" };
+
+ for (guint i = 0; i < G_N_ELEMENTS (known_aliases); i++)
+ {
+ if (ide_pipeline_contains_program_in_path (pipeline, known_aliases[i], NULL))
+ return g_strdup (known_aliases[i]);
+ }
+ }
+
+ /* Fallback to "ninja" and hope for the best */
+ return g_strdup ("ninja");
+}
diff --git a/src/plugins/meson/gbp-meson-build-system.h b/src/plugins/meson/gbp-meson-build-system.h
index 5cb726ff3..bd0f57ece 100644
--- a/src/plugins/meson/gbp-meson-build-system.h
+++ b/src/plugins/meson/gbp-meson-build-system.h
@@ -27,6 +27,12 @@ G_BEGIN_DECLS
#define GBP_TYPE_MESON_BUILD_SYSTEM (gbp_meson_build_system_get_type())
G_DECLARE_FINAL_TYPE (GbpMesonBuildSystem, gbp_meson_build_system, GBP, MESON_BUILD_SYSTEM, IdeObject)
-const gchar * const * gbp_meson_build_system_get_languages (GbpMesonBuildSystem *self);
+
+const gchar * const *gbp_meson_build_system_get_languages (GbpMesonBuildSystem *self);
+char *gbp_meson_build_system_get_project_dir (GbpMesonBuildSystem *self);
+char *gbp_meson_build_system_locate_meson (GbpMesonBuildSystem *self,
+ IdePipeline *pipeline);
+char *gbp_meson_build_system_locate_ninja (GbpMesonBuildSystem *self,
+ IdePipeline *pipeline);
G_END_DECLS
diff --git a/src/plugins/meson/gbp-meson-build-target-provider.c
b/src/plugins/meson/gbp-meson-build-target-provider.c
index a78e050b3..f81c626da 100644
--- a/src/plugins/meson/gbp-meson-build-target-provider.c
+++ b/src/plugins/meson/gbp-meson-build-target-provider.c
@@ -55,7 +55,7 @@ create_launcher (IdeContext *context,
return NULL;
}
- if ((ret = ide_runtime_create_launcher (runtime, error)))
+ if ((ret = ide_pipeline_create_launcher (pipeline, error)))
{
ide_subprocess_launcher_set_flags (ret, G_SUBPROCESS_FLAGS_STDOUT_PIPE |
G_SUBPROCESS_FLAGS_STDERR_SILENCE);
ide_subprocess_launcher_set_cwd (ret, ide_pipeline_get_builddir (pipeline));
@@ -314,19 +314,17 @@ gbp_meson_build_target_provider_communicate_cb (GObject *object,
return;
}
- launcher = create_launcher (context, &error);
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_manager = ide_build_manager_from_context (context);
+ pipeline = ide_build_manager_get_pipeline (build_manager);
+ cancellable = ide_task_get_cancellable (task);
- if (launcher == NULL)
+ if (!(launcher = ide_pipeline_create_launcher (pipeline, &error)))
{
ide_task_return_error (task, g_steal_pointer (&error));
return;
}
- context = ide_object_get_context (IDE_OBJECT (self));
- build_manager = ide_build_manager_from_context (context);
- pipeline = ide_build_manager_get_pipeline (build_manager);
- cancellable = ide_task_get_cancellable (task);
-
ide_subprocess_launcher_push_argv (launcher, "meson");
ide_subprocess_launcher_push_argv (launcher, "introspect");
ide_subprocess_launcher_push_argv (launcher, "--installed");
diff --git a/src/plugins/meson/gbp-meson-introspection.c b/src/plugins/meson/gbp-meson-introspection.c
new file mode 100644
index 000000000..59038844d
--- /dev/null
+++ b/src/plugins/meson/gbp-meson-introspection.c
@@ -0,0 +1,682 @@
+/* gbp-meson-introspection.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-meson-introspection"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <json-glib/json-glib.h>
+
+#include <libide-core.h>
+#include <libide-foundry.h>
+#include <libide-threading.h>
+
+#include "gbp-meson-build-system.h"
+#include "gbp-meson-introspection.h"
+
+struct _GbpMesonIntrospection
+{
+ IdePipelineStage parent_instance;
+
+ IdePipeline *pipeline;
+
+ char *etag;
+
+ GListStore *run_commands;
+
+ char *descriptive_name;
+ char *subproject_dir;
+ char *version;
+
+ guint loaded : 1;
+ guint has_built_once : 1;
+};
+
+G_DEFINE_FINAL_TYPE (GbpMesonIntrospection, gbp_meson_introspection, IDE_TYPE_PIPELINE_STAGE)
+
+static gboolean
+get_string_member (JsonObject *object,
+ const char *member,
+ char **location)
+{
+ JsonNode *node;
+
+ g_assert (object != NULL);
+ g_assert (member != NULL);
+ g_assert (location != NULL);
+
+ g_clear_pointer (location, g_free);
+
+ if (json_object_has_member (object, member) &&
+ (node = json_object_get_member (object, member)) &&
+ JSON_NODE_HOLDS_VALUE (node))
+ {
+ *location = g_strdup (json_node_get_string (node));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+get_strv_member (JsonObject *object,
+ const char *member,
+ char ***location)
+{
+ JsonNode *node;
+ JsonArray *ar;
+
+ g_assert (object != NULL);
+ g_assert (member != NULL);
+ g_assert (location != NULL);
+
+ g_clear_pointer (location, g_strfreev);
+
+ if (json_object_has_member (object, member) &&
+ (node = json_object_get_member (object, member)) &&
+ JSON_NODE_HOLDS_ARRAY (node) &&
+ (ar = json_node_get_array (node)))
+ {
+ GPtrArray *strv = g_ptr_array_new ();
+ guint n_items = json_array_get_length (ar);
+
+ for (guint i = 0; i < n_items; i++)
+ {
+ JsonNode *ele = json_array_get_element (ar, i);
+ const char *str;
+
+ if (JSON_NODE_HOLDS_VALUE (ele) &&
+ (str = json_node_get_string (ele)))
+ g_ptr_array_add (strv, g_strdup (str));
+ }
+
+ g_ptr_array_add (strv, NULL);
+
+ *location = (char **)(gpointer)g_ptr_array_free (strv, FALSE);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+get_environ_member (JsonObject *object,
+ const char *member,
+ char ***location)
+{
+ JsonNode *node;
+ JsonObject *envobj;
+
+ g_assert (object != NULL);
+ g_assert (member != NULL);
+ g_assert (location != NULL);
+ g_assert (*location == NULL);
+
+ if (json_object_has_member (object, member) &&
+ (node = json_object_get_member (object, member)) &&
+ JSON_NODE_HOLDS_OBJECT (node) &&
+ (envobj = json_node_get_object (node)))
+ {
+ JsonObjectIter iter;
+ const char *key;
+ JsonNode *value_node;
+
+ json_object_iter_init (&iter, envobj);
+ while (json_object_iter_next (&iter, &key, &value_node))
+ {
+ const char *value;
+
+ if (!JSON_NODE_HOLDS_VALUE (value_node) ||
+ !(value = json_node_get_string (value_node)))
+ continue;
+
+ *location = g_environ_setenv (*location, key, value, TRUE);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gbp_meson_introspection_load_buildoptions (GbpMesonIntrospection *self,
+ JsonArray *buildoptions)
+{
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (buildoptions != NULL);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_introspection_load_projectinfo (GbpMesonIntrospection *self,
+ JsonObject *projectinfo)
+{
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (projectinfo != NULL);
+
+ get_string_member (projectinfo, "version", &self->version);
+ get_string_member (projectinfo, "descriptive_name", &self->descriptive_name);
+ get_string_member (projectinfo, "subproject_dir", &self->subproject_dir);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_introspection_load_test (GbpMesonIntrospection *self,
+ JsonObject *test)
+{
+ g_autoptr(IdeRunCommand) run_command = NULL;
+ g_auto(GStrv) cmd = NULL;
+ g_auto(GStrv) env = NULL;
+ g_auto(GStrv) suite = NULL;
+ g_autofree char *name = NULL;
+ g_autofree char *workdir = NULL;
+ g_autofree char *id = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (test != NULL);
+
+ get_strv_member (test, "cmd", &cmd);
+ get_strv_member (test, "suite", &suite);
+ get_environ_member (test, "env", &env);
+ get_string_member (test, "name", &name);
+ get_string_member (test, "workdir", &workdir);
+
+ id = g_strdup_printf ("meson:%s", name);
+
+ run_command = ide_run_command_new ();
+ ide_run_command_set_id (run_command, id);
+ ide_run_command_set_kind (run_command, IDE_RUN_COMMAND_KIND_TEST);
+ ide_run_command_set_display_name (run_command, name);
+ ide_run_command_set_environ (run_command, (const char * const *)env);
+ ide_run_command_set_argv (run_command, (const char * const *)cmd);
+ ide_run_command_set_cwd (run_command, workdir);
+
+ g_list_store_append (self->run_commands, run_command);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_introspection_load_tests (GbpMesonIntrospection *self,
+ JsonArray *tests)
+{
+ guint n_items;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (tests != NULL);
+
+ n_items = json_array_get_length (tests);
+
+ for (guint i = 0; i < n_items; i++)
+ {
+ JsonNode *node = json_array_get_element (tests, i);
+ JsonObject *obj;
+
+ if (node != NULL &&
+ JSON_NODE_HOLDS_OBJECT (node) &&
+ (obj = json_node_get_object (node)))
+ gbp_meson_introspection_load_test (self, obj);
+ }
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_introspection_load_benchmarks (GbpMesonIntrospection *self,
+ JsonArray *benchmarks)
+{
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (benchmarks != NULL);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_introspection_load_targets (GbpMesonIntrospection *self,
+ JsonArray *targets)
+{
+ guint length;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (targets != NULL);
+
+ length = json_array_get_length (targets);
+
+ for (guint i = 0; i < length; i++)
+ {
+ JsonNode *node = json_array_get_element (targets, i);
+ g_autofree char *id = NULL;
+ g_autofree char *name = NULL;
+ g_autofree char *type = NULL;
+ JsonObject *obj;
+
+ if (!JSON_NODE_HOLDS_OBJECT (node) || !(obj = json_node_get_object (node)))
+ continue;
+
+ get_string_member (obj, "id", &id);
+ get_string_member (obj, "name", &name);
+ get_string_member (obj, "type", &type);
+
+ if (ide_str_equal0 (type, "executable"))
+ {
+ g_auto(GStrv) filename = NULL;
+
+ get_strv_member (obj, "filename", &filename);
+
+ if (filename != NULL && filename[0] != NULL)
+ {
+ g_autoptr(IdeRunCommand) run_command = ide_run_command_new ();
+
+ ide_run_command_set_kind (run_command, IDE_RUN_COMMAND_KIND_UTILITY);
+ ide_run_command_set_id (run_command, id);
+ ide_run_command_set_display_name (run_command, name);
+ ide_run_command_set_argv (run_command, IDE_STRV_INIT (filename[0]));
+
+ g_list_store_append (self->run_commands, run_command);
+ }
+ }
+ }
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_introspection_load_installed (GbpMesonIntrospection *self,
+ JsonObject *installed)
+{
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (installed != NULL);
+
+ IDE_EXIT;
+}
+
+static char *
+get_current_etag (IdePipeline *pipeline)
+{
+ g_autofree char *build_dot_ninja = NULL;
+ g_autoptr(GFileInfo) info = NULL;
+ g_autoptr(GFile) file = NULL;
+
+ g_assert (IDE_IS_PIPELINE (pipeline));
+
+ build_dot_ninja = ide_pipeline_build_builddir_path (pipeline, "build.ninja", NULL);
+ file = g_file_new_for_path (build_dot_ninja);
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_ETAG_VALUE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+
+ if (info == NULL)
+ return NULL;
+
+ return g_strdup (g_file_info_get_etag (info));
+}
+
+static void
+gbp_meson_introspection_query (IdePipelineStage *stage,
+ IdePipeline *pipeline,
+ GPtrArray *targets,
+ GCancellable *cancellable)
+{
+ GbpMesonIntrospection *self = (GbpMesonIntrospection *)stage;
+ g_autofree char *etag = NULL;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ etag = get_current_etag (pipeline);
+
+ ide_pipeline_stage_set_completed (stage,
+ ide_str_equal0 (etag, self->etag));
+}
+
+static void
+gbp_meson_introspection_load_json (GbpMesonIntrospection *self,
+ JsonObject *root)
+{
+ JsonNode *member;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (root != NULL);
+
+ if (json_object_has_member (root, "buildoptions") &&
+ (member = json_object_get_member (root, "buildoptions")) &&
+ JSON_NODE_HOLDS_ARRAY (member))
+ gbp_meson_introspection_load_buildoptions (self, json_node_get_array (member));
+
+ if (json_object_has_member (root, "projectinfo") &&
+ (member = json_object_get_member (root, "projectinfo")) &&
+ JSON_NODE_HOLDS_OBJECT (member))
+ gbp_meson_introspection_load_projectinfo (self, json_node_get_object (member));
+
+ if (json_object_has_member (root, "tests") &&
+ (member = json_object_get_member (root, "tests")) &&
+ JSON_NODE_HOLDS_ARRAY (member))
+ gbp_meson_introspection_load_tests (self, json_node_get_array (member));
+
+ if (json_object_has_member (root, "benchmarks") &&
+ (member = json_object_get_member (root, "benchmarks")) &&
+ JSON_NODE_HOLDS_ARRAY (member))
+ gbp_meson_introspection_load_benchmarks (self, json_node_get_array (member));
+
+ if (json_object_has_member (root, "installed") &&
+ (member = json_object_get_member (root, "installed")) &&
+ JSON_NODE_HOLDS_OBJECT (member))
+ gbp_meson_introspection_load_installed (self, json_node_get_object (member));
+
+ if (json_object_has_member (root, "targets") &&
+ (member = json_object_get_member (root, "targets")) &&
+ JSON_NODE_HOLDS_ARRAY (member))
+ gbp_meson_introspection_load_targets (self, json_node_get_array (member));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_introspection_load_stream_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ JsonParser *parser = (JsonParser *)object;
+ GbpMesonIntrospection *self;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ const char *etag;
+ JsonObject *obj;
+ JsonNode *root;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (JSON_IS_PARSER (parser));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!json_parser_load_from_stream_finish (parser, result, &error))
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ IDE_EXIT;
+ }
+
+ self = ide_task_get_source_object (task);
+ etag = ide_task_get_task_data (task);
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (etag != NULL);
+
+ /* Clear all of our previously loaded state */
+ ide_set_string (&self->etag, etag);
+ g_list_store_remove_all (self->run_commands);
+
+ if ((root = json_parser_get_root (parser)) &&
+ JSON_NODE_HOLDS_OBJECT (root) &&
+ (obj = json_node_get_object (root)))
+ gbp_meson_introspection_load_json (self, obj);
+
+ ide_task_return_boolean (task, TRUE);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_introspection_build_async (IdePipelineStage *stage,
+ IdePipeline *pipeline,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpMesonIntrospection *self = (GbpMesonIntrospection *)stage;
+ g_autoptr(IdeRunContext) run_context = NULL;
+ g_autoptr(IdeSubprocess) subprocess = NULL;
+ g_autoptr(JsonParser) parser = NULL;
+ g_autoptr(GIOStream) io_stream = NULL;
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autofree char *meson = NULL;
+ IdeBuildSystem *build_system;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ self->has_built_once = TRUE;
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_meson_introspection_build_async);
+ ide_task_set_task_data (task, get_current_etag (pipeline), g_free);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_system = ide_build_system_from_context (context);
+ meson = gbp_meson_build_system_locate_meson (GBP_MESON_BUILD_SYSTEM (build_system), pipeline);
+
+ g_assert (IDE_IS_CONTEXT (context));
+ g_assert (GBP_IS_MESON_BUILD_SYSTEM (build_system));
+ g_assert (meson != NULL);
+
+ run_context = ide_run_context_new ();
+ ide_pipeline_prepare_run_context (pipeline, run_context);
+ ide_run_context_append_args (run_context, IDE_STRV_INIT (meson, "introspect", "--all",
"--force-object-output"));
+
+ /* Create a stream to communicate with the subprocess and then spawn it */
+ if (!(io_stream = ide_run_context_create_stdio_stream (run_context, &error)) ||
+ !(subprocess = ide_run_context_spawn (run_context, &error)))
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ IDE_EXIT;
+ }
+
+ /* Keep stream alive for duration of operation */
+ g_object_set_data_full (G_OBJECT (task),
+ "IO_STREAM",
+ g_object_ref (io_stream),
+ g_object_unref);
+
+ /* Start parsing our input stream */
+ parser = json_parser_new ();
+ json_parser_load_from_stream_async (parser,
+ g_io_stream_get_input_stream (io_stream),
+ cancellable,
+ gbp_meson_introspection_load_stream_cb,
+ g_steal_pointer (&task));
+
+ /* Make sure something watches the child */
+ ide_subprocess_wait_async (subprocess, NULL, NULL, NULL);
+
+ IDE_EXIT;
+}
+
+static gboolean
+gbp_meson_introspection_build_finish (IdePipelineStage *stage,
+ GAsyncResult *result,
+ GError **error)
+{
+ gboolean ret;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (stage));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_boolean (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static void
+gbp_meson_introspection_dispose (GObject *object)
+{
+ GbpMesonIntrospection *self = (GbpMesonIntrospection *)object;
+
+ g_clear_object (&self->run_commands);
+
+ g_clear_pointer (&self->descriptive_name, g_free);
+ g_clear_pointer (&self->subproject_dir, g_free);
+ g_clear_pointer (&self->version, g_free);
+ g_clear_pointer (&self->etag, g_free);
+
+ g_clear_weak_pointer (&self->pipeline);
+
+ G_OBJECT_CLASS (gbp_meson_introspection_parent_class)->dispose (object);
+}
+
+static void
+gbp_meson_introspection_class_init (GbpMesonIntrospectionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ IdePipelineStageClass *pipeline_stage_class = IDE_PIPELINE_STAGE_CLASS (klass);
+
+ object_class->dispose = gbp_meson_introspection_dispose;
+
+ pipeline_stage_class->query = gbp_meson_introspection_query;
+ pipeline_stage_class->build_async = gbp_meson_introspection_build_async;
+ pipeline_stage_class->build_finish = gbp_meson_introspection_build_finish;
+}
+
+static void
+gbp_meson_introspection_init (GbpMesonIntrospection *self)
+{
+ self->run_commands = g_list_store_new (IDE_TYPE_RUN_COMMAND);
+
+ ide_pipeline_stage_set_name (IDE_PIPELINE_STAGE (self),
+ _("Load Meson Introspection"));
+}
+
+GbpMesonIntrospection *
+gbp_meson_introspection_new (IdePipeline *pipeline)
+{
+ GbpMesonIntrospection *self;
+
+ g_return_val_if_fail (IDE_IS_PIPELINE (pipeline), NULL);
+
+ self = g_object_new (GBP_TYPE_MESON_INTROSPECTION, NULL);
+ g_set_weak_pointer (&self->pipeline, pipeline);
+
+ return self;
+}
+
+static void
+gbp_meson_introspection_list_run_commands_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = user_data;
+ GbpMesonIntrospection *self;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_PIPELINE (object) || IDE_IS_PIPELINE_STAGE (object));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ self = ide_task_get_source_object (task);
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+
+ ide_task_return_pointer (task, g_object_ref (self->run_commands), g_object_unref);
+
+ IDE_EXIT;
+}
+
+void
+gbp_meson_introspection_list_run_commands_async (GbpMesonIntrospection *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_MAIN_THREAD ());
+ g_return_if_fail (GBP_IS_MESON_INTROSPECTION (self));
+ g_return_if_fail (IDE_IS_PIPELINE (self->pipeline));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_meson_introspection_list_run_commands_async);
+
+ if (!self->has_built_once)
+ {
+ g_autofree char *build_dot_ninja = ide_pipeline_build_builddir_path (self->pipeline, "build.ninja",
NULL);
+
+ /* If there is a build.ninja then assume we can skip running through
+ * the pipeline and just introspection immediately.
+ */
+ if (g_file_test (build_dot_ninja, G_FILE_TEST_EXISTS))
+ ide_pipeline_stage_build_async (IDE_PIPELINE_STAGE (self),
+ self->pipeline,
+ cancellable,
+ gbp_meson_introspection_list_run_commands_cb,
+ g_steal_pointer (&task));
+ else
+ ide_pipeline_build_async (self->pipeline,
+ IDE_PIPELINE_PHASE_CONFIGURE,
+ cancellable,
+ gbp_meson_introspection_list_run_commands_cb,
+ g_steal_pointer (&task));
+
+ IDE_EXIT;
+ }
+
+ ide_task_return_pointer (task, g_object_ref (self->run_commands), g_object_unref);
+
+ IDE_EXIT;
+}
+
+GListModel *
+gbp_meson_introspection_list_run_commands_finish (GbpMesonIntrospection *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GListModel *ret;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (self));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
diff --git a/src/plugins/meson/gbp-meson-introspection.h b/src/plugins/meson/gbp-meson-introspection.h
new file mode 100644
index 000000000..ed83a4c2e
--- /dev/null
+++ b/src/plugins/meson/gbp-meson-introspection.h
@@ -0,0 +1,40 @@
+/* gbp-meson-introspection.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_MESON_INTROSPECTION (gbp_meson_introspection_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpMesonIntrospection, gbp_meson_introspection, GBP, MESON_INTROSPECTION,
IdePipelineStage)
+
+GbpMesonIntrospection *gbp_meson_introspection_new (IdePipeline *pipeline);
+void gbp_meson_introspection_list_run_commands_async (GbpMesonIntrospection *self,
+ GCancellable *cancelalble,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GListModel *gbp_meson_introspection_list_run_commands_finish (GbpMesonIntrospection *self,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/src/plugins/meson/gbp-meson-pipeline-addin.c b/src/plugins/meson/gbp-meson-pipeline-addin.c
index b7f3f15fa..df1594f2e 100644
--- a/src/plugins/meson/gbp-meson-pipeline-addin.c
+++ b/src/plugins/meson/gbp-meson-pipeline-addin.c
@@ -29,11 +29,13 @@
#include "gbp-meson-build-stage-cross-file.h"
#include "gbp-meson-build-system.h"
#include "gbp-meson-build-target.h"
+#include "gbp-meson-introspection.h"
#include "gbp-meson-pipeline-addin.h"
struct _GbpMesonPipelineAddin
{
- IdeObject parent_instance;
+ IdeObject parent_instance;
+ GbpMesonIntrospection *introspection;
};
static const gchar *ninja_names[] = { "ninja", "ninja-build", NULL };
@@ -77,12 +79,11 @@ on_build_stage_query (IdePipelineStage *stage,
if (GBP_IS_MESON_BUILD_TARGET (target))
{
- const gchar *filename;
+ const char *builddir = ide_pipeline_get_builddir (pipeline);
+ const char *filename = gbp_meson_build_target_get_filename (GBP_MESON_BUILD_TARGET (target));
- filename = gbp_meson_build_target_get_filename (GBP_MESON_BUILD_TARGET (target));
-
- if (filename != NULL)
- ide_subprocess_launcher_push_argv (launcher, filename);
+ if (filename != NULL && g_str_has_prefix (filename, builddir))
+ ide_subprocess_launcher_push_argv (launcher, g_path_skip_root (filename + strlen
(builddir)));
}
}
}
@@ -102,214 +103,186 @@ on_install_stage_query (IdePipelineStage *stage,
ide_pipeline_stage_set_completed (stage, FALSE);
}
-static void
-gbp_meson_pipeline_addin_load (IdePipelineAddin *addin,
- IdePipeline *pipeline)
+G_GNUC_NULL_TERMINATED
+static IdeRunContext *
+create_run_context (GbpMesonPipelineAddin *self,
+ IdePipeline *pipeline,
+ const char *argv,
+ ...)
+{
+ IdeRunContext *run_context;
+ va_list args;
+
+ g_assert (GBP_IS_MESON_PIPELINE_ADDIN (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+
+ run_context = ide_run_context_new ();
+ ide_pipeline_prepare_run_context (pipeline, run_context);
+
+ va_start (args, argv);
+ while (argv != NULL)
+ {
+ ide_run_context_append_argv (run_context, argv);
+ argv = va_arg (args, const char *);
+ }
+ va_end (args);
+
+ return run_context;
+}
+
+static IdePipelineStage *
+attach_run_context (GbpMesonPipelineAddin *self,
+ IdePipeline *pipeline,
+ IdeRunContext *build_context,
+ IdeRunContext *clean_context,
+ const char *title,
+ IdePipelinePhase phase)
{
- GbpMesonPipelineAddin *self = (GbpMesonPipelineAddin *)addin;
- g_autoptr(IdeSubprocessLauncher) config_launcher = NULL;
g_autoptr(IdeSubprocessLauncher) build_launcher = NULL;
g_autoptr(IdeSubprocessLauncher) clean_launcher = NULL;
- g_autoptr(IdeSubprocessLauncher) install_launcher = NULL;
- g_autoptr(IdePipelineStage) build_stage = NULL;
- g_autoptr(IdePipelineStage) config_stage = NULL;
- g_autoptr(IdePipelineStage) install_stage = NULL;
+ g_autoptr(IdePipelineStage) stage = NULL;
g_autoptr(GError) error = NULL;
- g_autofree gchar *build_ninja = NULL;
- g_autofree gchar *crossbuild_file = NULL;
- g_autofree gchar *meson_build = NULL;
- g_autofree gchar *alt_meson_build = NULL;
- IdeBuildSystem *build_system;
- IdeConfig *config;
IdeContext *context;
- IdeRuntime *runtime;
- IdeToolchain *toolchain;
- IdeWorkbench *workbench;
- IdeProjectInfo *project_info;
- g_autoptr(GFile) project_dir = NULL;
- g_autoptr(GFile) alt_meson_build_file = NULL;
- const gchar *config_opts;
- const gchar *ninja = NULL;
- const gchar *prefix;
- const gchar *srcdir;
- const gchar *meson;
- GFile *project_file;
guint id;
- gint parallel;
-
- IDE_ENTRY;
g_assert (GBP_IS_MESON_PIPELINE_ADDIN (self));
g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (!build_context || IDE_IS_RUN_CONTEXT (build_context));
+ g_assert (!clean_context || IDE_IS_RUN_CONTEXT (clean_context));
- context = ide_object_get_context (IDE_OBJECT (self));
-
- build_system = ide_build_system_from_context (context);
- if (!GBP_IS_MESON_BUILD_SYSTEM (build_system))
- IDE_GOTO (failure);
-
- config = ide_pipeline_get_config (pipeline);
- runtime = ide_pipeline_get_runtime (pipeline);
- toolchain = ide_pipeline_get_toolchain (pipeline);
- srcdir = ide_pipeline_get_srcdir (pipeline);
- workbench = ide_workbench_from_context (context);
- project_info = ide_workbench_get_project_info (workbench);
- project_file = ide_project_info_get_file (project_info);
+ context = ide_object_get_context (IDE_OBJECT (pipeline));
+ stage = ide_pipeline_stage_launcher_new (context, NULL);
- if (project_file != NULL)
+ if (build_context != NULL)
{
- GFileType file_type = g_file_query_file_type (project_file, 0, NULL);
-
- if (file_type == G_FILE_TYPE_DIRECTORY)
- project_dir = g_object_ref (project_file);
- else
- project_dir = g_file_get_parent (project_file);
-
- alt_meson_build_file = g_file_get_child (project_dir, "meson.build");
- alt_meson_build = g_file_get_path (alt_meson_build_file);
+ if (!(build_launcher = ide_run_context_end (build_context, &error)))
+ {
+ g_critical ("Failed to create launcher from run context: %s",
+ error->message);
+ return NULL;
+ }
}
- g_assert (IDE_IS_CONFIG (config));
- g_assert (IDE_IS_RUNTIME (runtime));
- g_assert (srcdir != NULL);
-
- /* If the srcdir does not contain the meson.build, perhaps the project's
- * "Project File" directory does (and that could be in a sub-directory).
- */
- meson_build = g_build_filename (srcdir, "meson.build", NULL);
- if (!g_file_test (meson_build, G_FILE_TEST_EXISTS) &&
- alt_meson_build != NULL &&
- project_dir != NULL &&
- g_file_test (alt_meson_build, G_FILE_TEST_EXISTS))
- srcdir = g_file_get_path (project_dir);
-
- if (NULL == (meson = ide_config_getenv (config, "MESON")))
- meson = "meson";
-
- /* Warn about not finding Meson, but continue setting up */
- if (!ide_runtime_contains_program_in_path (runtime, meson, NULL))
- ide_context_warning (context,
- _("A Meson-based project is loaded but meson could not be found."));
-
- /* Requires NULL check so we can use g_strv_contains() elsewhere */
- for (guint i = 0; ninja_names[i]; i++)
+ if (clean_context != NULL)
{
- if (ide_runtime_contains_program_in_path (runtime, ninja_names[i], NULL))
+ if (!(clean_launcher = ide_run_context_end (clean_context, &error)))
{
- ninja = ninja_names[i];
- break;
+ g_critical ("Failed to create launcher from run context: %s",
+ error->message);
+ return NULL;
}
}
- if (ninja == NULL)
- ninja = ide_config_getenv (config, "NINJA");
+ g_object_set (stage,
+ "launcher", build_launcher,
+ "clean-launcher", clean_launcher,
+ "name", title,
+ NULL);
- /* Warn about not finding ninja, but continue setting up */
- if (ninja == NULL)
- {
- ide_context_warning (context,
- _("A Meson-based project is loaded but Ninja could not be found."));
- ninja = "ninja";
- }
+ id = ide_pipeline_attach (pipeline, phase, 0, stage);
+ ide_pipeline_addin_track (IDE_PIPELINE_ADDIN (self), id);
- /* Create all our launchers up front */
- if (NULL == (config_launcher = ide_pipeline_create_launcher (pipeline, &error)) ||
- NULL == (build_launcher = ide_pipeline_create_launcher (pipeline, &error)) ||
- NULL == (clean_launcher = ide_pipeline_create_launcher (pipeline, &error)) ||
- NULL == (install_launcher = ide_pipeline_create_launcher (pipeline, &error)))
- IDE_GOTO (failure);
+ /* We return a borrowed instance */
+ return stage;
+}
- prefix = ide_config_get_prefix (config);
+static void
+gbp_meson_pipeline_addin_load (IdePipelineAddin *addin,
+ IdePipeline *pipeline)
+{
+ GbpMesonPipelineAddin *self = (GbpMesonPipelineAddin *)addin;
+ g_autoptr(IdeRunContext) build_context = NULL;
+ g_autoptr(IdeRunContext) clean_context = NULL;
+ g_autoptr(IdeRunContext) config_context = NULL;
+ g_autoptr(IdeRunContext) install_context = NULL;
+ IdePipelineStage *stage;
+ g_autofree char *build_dot_ninja = NULL;
+ g_autofree char *crossbuild_file = NULL;
+ g_autofree char *meson = NULL;
+ g_autofree char *ninja = NULL;
+ IdeBuildSystem *build_system;
+ IdeToolchain *toolchain;
+ IdeContext *context;
+ const char *config_opts;
+ const char *prefix;
+ const char *srcdir;
+ IdeConfig *config;
+ guint id;
+ int parallel;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_MESON_PIPELINE_ADDIN (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+
+ config = ide_pipeline_get_config (pipeline);
+ context = ide_object_get_context (IDE_OBJECT (pipeline));
+ build_system = ide_build_system_from_context (context);
+
+ if (!GBP_IS_MESON_BUILD_SYSTEM (build_system))
+ IDE_EXIT;
+
+ srcdir = ide_pipeline_get_srcdir (pipeline);
config_opts = ide_config_get_config_opts (config);
+ prefix = ide_config_get_prefix (config);
+ build_dot_ninja = ide_pipeline_build_builddir_path (pipeline, "build.ninja", NULL);
parallel = ide_config_get_parallelism (config);
+ toolchain = ide_pipeline_get_toolchain (pipeline);
+
+ /* Discover program locations for meson/ninja */
+ meson = gbp_meson_build_system_locate_meson (GBP_MESON_BUILD_SYSTEM (build_system), pipeline);
+ ninja = gbp_meson_build_system_locate_ninja (GBP_MESON_BUILD_SYSTEM (build_system), pipeline);
/* Create the toolchain file if required */
if (GBP_IS_MESON_TOOLCHAIN (toolchain))
- crossbuild_file = g_strdup (gbp_meson_toolchain_get_file_path (GBP_MESON_TOOLCHAIN (toolchain)));
+ {
+ crossbuild_file = g_strdup (gbp_meson_toolchain_get_file_path (GBP_MESON_TOOLCHAIN (toolchain)));
+ }
else if (g_strcmp0 (ide_toolchain_get_id (toolchain), "default") != 0)
{
- GbpMesonBuildStageCrossFile *cross_file_stage;
- cross_file_stage = gbp_meson_build_stage_cross_file_new (toolchain);
- crossbuild_file = gbp_meson_build_stage_cross_file_get_path (cross_file_stage, pipeline);
-
+ g_autoptr(GbpMesonBuildStageCrossFile) cross_file_stage = gbp_meson_build_stage_cross_file_new
(toolchain);
id = ide_pipeline_attach (pipeline, IDE_PIPELINE_PHASE_PREPARE, 0, IDE_PIPELINE_STAGE
(cross_file_stage));
+ crossbuild_file = gbp_meson_build_stage_cross_file_get_path (cross_file_stage, pipeline);
ide_pipeline_addin_track (addin, id);
}
- /* Setup our meson configure stage. */
-
- ide_subprocess_launcher_push_argv (config_launcher, meson);
- ide_subprocess_launcher_push_argv (config_launcher, srcdir);
- ide_subprocess_launcher_push_argv (config_launcher, ".");
- ide_subprocess_launcher_push_argv (config_launcher, "--prefix");
- ide_subprocess_launcher_push_argv (config_launcher, prefix);
+ /* Setup our configure stage */
+ config_context = create_run_context (self, pipeline, meson, srcdir, ".", "--prefix", prefix, NULL);
if (crossbuild_file != NULL)
- {
- ide_subprocess_launcher_push_argv (config_launcher, "--cross-file");
- ide_subprocess_launcher_push_argv (config_launcher, crossbuild_file);
- }
-
+ ide_run_context_append_formatted (config_context, "--cross-file=%s", crossbuild_file);
if (!ide_str_empty0 (config_opts))
- {
- g_auto(GStrv) argv = NULL;
- gint argc;
-
- if (!g_shell_parse_argv (config_opts, &argc, &argv, &error))
- IDE_GOTO (failure);
-
- ide_subprocess_launcher_push_args (config_launcher, (const gchar * const *)argv);
- }
-
- config_stage = ide_pipeline_stage_launcher_new (context, config_launcher);
- ide_pipeline_stage_set_name (config_stage, _("Configuring project"));
- build_ninja = ide_pipeline_build_builddir_path (pipeline, "build.ninja", NULL);
- if (g_file_test (build_ninja, G_FILE_TEST_IS_REGULAR))
- ide_pipeline_stage_set_completed (config_stage, TRUE);
-
- id = ide_pipeline_attach (pipeline, IDE_PIPELINE_PHASE_CONFIGURE, 0, config_stage);
- ide_pipeline_addin_track (addin, id);
-
- /*
- * Register the build launcher which will perform the incremental
- * build of the project when the IDE_PIPELINE_PHASE_BUILD phase is
- * requested of the pipeline.
- */
- ide_subprocess_launcher_push_argv (build_launcher, ninja);
- ide_subprocess_launcher_push_argv (clean_launcher, ninja);
-
+ ide_run_context_append_args_parsed (config_context, config_opts, NULL);
+ stage = attach_run_context (self, pipeline, config_context, NULL,
+ _("Configure project"), IDE_PIPELINE_PHASE_CONFIGURE);
+ if (g_file_test (build_dot_ninja, G_FILE_TEST_EXISTS))
+ ide_pipeline_stage_set_completed (stage, TRUE);
+
+ /* Setup our Build/Clean stage */
+ clean_context = create_run_context (self, pipeline, ninja, "clean", NULL);
+ build_context = create_run_context (self, pipeline, ninja, NULL);
if (parallel > 0)
- {
- g_autofree gchar *j = g_strdup_printf ("-j%u", parallel);
-
- ide_subprocess_launcher_push_argv (build_launcher, j);
- ide_subprocess_launcher_push_argv (clean_launcher, j);
- }
-
- ide_subprocess_launcher_push_argv (clean_launcher, "clean");
-
- build_stage = ide_pipeline_stage_launcher_new (context, build_launcher);
- ide_pipeline_stage_launcher_set_clean_launcher (IDE_PIPELINE_STAGE_LAUNCHER (build_stage), clean_launcher);
- ide_pipeline_stage_set_check_stdout (build_stage, TRUE);
- ide_pipeline_stage_set_name (build_stage, _("Building project"));
- g_signal_connect (build_stage, "query", G_CALLBACK (on_build_stage_query), NULL);
-
- id = ide_pipeline_attach (pipeline, IDE_PIPELINE_PHASE_BUILD, 0, build_stage);
- ide_pipeline_addin_track (addin, id);
-
- /* Setup our install stage */
- ide_subprocess_launcher_push_argv (install_launcher, ninja);
- ide_subprocess_launcher_push_argv (install_launcher, "install");
- install_stage = ide_pipeline_stage_launcher_new (context, install_launcher);
- ide_pipeline_stage_set_name (install_stage, _("Installing project"));
- g_signal_connect (install_stage, "query", G_CALLBACK (on_install_stage_query), NULL);
- id = ide_pipeline_attach (pipeline, IDE_PIPELINE_PHASE_INSTALL, 0, install_stage);
+ ide_run_context_append_formatted (build_context, "-j%u", parallel);
+ stage = attach_run_context (self, pipeline, build_context, clean_context,
+ _("Build project"), IDE_PIPELINE_PHASE_BUILD);
+ ide_pipeline_stage_set_check_stdout (stage, TRUE);
+ g_signal_connect (stage, "query", G_CALLBACK (on_build_stage_query), NULL);
+
+ /* Setup our Install stage */
+ install_context = create_run_context (self, pipeline, ninja, "install", NULL);
+ stage = attach_run_context (self, pipeline, install_context, NULL,
+ _("Install project"), IDE_PIPELINE_PHASE_INSTALL);
+ g_signal_connect (stage, "query", G_CALLBACK (on_install_stage_query), NULL);
+
+ /* Setup our introspection stage */
+ self->introspection = gbp_meson_introspection_new (pipeline);
+ id = ide_pipeline_attach (pipeline,
+ IDE_PIPELINE_PHASE_CONFIGURE | IDE_PIPELINE_PHASE_AFTER,
+ 0,
+ IDE_PIPELINE_STAGE (self->introspection));
ide_pipeline_addin_track (addin, id);
IDE_EXIT;
-
-failure:
- if (error != NULL)
- g_warning ("Failed to setup meson build pipeline: %s", error->message);
}
static void
@@ -319,15 +292,35 @@ pipeline_addin_iface_init (IdePipelineAddinInterface *iface)
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GbpMesonPipelineAddin, gbp_meson_pipeline_addin, IDE_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (IDE_TYPE_PIPELINE_ADDIN,
- pipeline_addin_iface_init))
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_PIPELINE_ADDIN, pipeline_addin_iface_init))
+
+static void
+gbp_meson_pipeline_addin_dispose (GObject *object)
+{
+ GbpMesonPipelineAddin *self = (GbpMesonPipelineAddin *)object;
+
+ g_clear_object (&self->introspection);
+
+ G_OBJECT_CLASS (gbp_meson_pipeline_addin_parent_class)->dispose (object);
+}
static void
gbp_meson_pipeline_addin_class_init (GbpMesonPipelineAddinClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gbp_meson_pipeline_addin_dispose;
}
static void
gbp_meson_pipeline_addin_init (GbpMesonPipelineAddin *self)
{
}
+
+GbpMesonIntrospection *
+gbp_meson_pipeline_addin_get_introspection (GbpMesonPipelineAddin *self)
+{
+ g_return_val_if_fail (GBP_IS_MESON_PIPELINE_ADDIN (self), NULL);
+
+ return self->introspection;
+}
diff --git a/src/plugins/meson/gbp-meson-pipeline-addin.h b/src/plugins/meson/gbp-meson-pipeline-addin.h
index f2b24093e..cefda157d 100644
--- a/src/plugins/meson/gbp-meson-pipeline-addin.h
+++ b/src/plugins/meson/gbp-meson-pipeline-addin.h
@@ -22,10 +22,14 @@
#include <libide-foundry.h>
+#include "gbp-meson-introspection.h"
+
G_BEGIN_DECLS
#define GBP_TYPE_MESON_PIPELINE_ADDIN (gbp_meson_pipeline_addin_get_type())
G_DECLARE_FINAL_TYPE (GbpMesonPipelineAddin, gbp_meson_pipeline_addin, GBP, MESON_PIPELINE_ADDIN, IdeObject)
+GbpMesonIntrospection *gbp_meson_pipeline_addin_get_introspection (GbpMesonPipelineAddin *self);
+
G_END_DECLS
diff --git a/src/plugins/meson/gbp-meson-run-command-provider.c
b/src/plugins/meson/gbp-meson-run-command-provider.c
new file mode 100644
index 000000000..d166bcef2
--- /dev/null
+++ b/src/plugins/meson/gbp-meson-run-command-provider.c
@@ -0,0 +1,171 @@
+/* gbp-meson-run-command-provider.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-meson-run-command-provider"
+
+#include <libide-threading.h>
+
+#include "gbp-meson-build-system.h"
+#include "gbp-meson-introspection.h"
+#include "gbp-meson-pipeline-addin.h"
+#include "gbp-meson-run-command-provider.h"
+
+struct _GbpMesonRunCommandProvider
+{
+ IdeObject parent_instance;
+};
+
+static void
+gbp_meson_run_command_provider_list_run_commands_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GbpMesonIntrospection *introspection = (GbpMesonIntrospection *)object;
+ g_autoptr(GListModel) run_commands = NULL;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_MESON_INTROSPECTION (introspection));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!(run_commands = gbp_meson_introspection_list_run_commands_finish (introspection, result, &error)))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else
+ ide_task_return_pointer (task, g_steal_pointer (&run_commands), g_object_unref);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_run_command_provider_list_commands_async (IdeRunCommandProvider *provider,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpMesonRunCommandProvider *self = (GbpMesonRunCommandProvider *)provider;
+ g_autoptr(GListModel) run_commands = NULL;
+ GbpMesonIntrospection *introspection;
+ g_autoptr(IdeTask) task = NULL;
+ IdePipelineAddin *addin;
+ IdeBuildManager *build_manager;
+ IdeBuildSystem *build_system;
+ IdePipeline *pipeline;
+ IdeContext *context;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_RUN_COMMAND_PROVIDER (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_meson_run_command_provider_list_commands_async);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_system = ide_build_system_from_context (context);
+ build_manager = ide_build_manager_from_context (context);
+ pipeline = ide_build_manager_get_pipeline (build_manager);
+
+ if (!GBP_IS_MESON_BUILD_SYSTEM (build_system) ||
+ pipeline == NULL ||
+ !(addin = ide_pipeline_addin_find_by_module_name (pipeline, "meson")) ||
+ !(introspection = gbp_meson_pipeline_addin_get_introspection (GBP_MESON_PIPELINE_ADDIN (addin))))
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "Cannot list run commands without a meson-based pipeline");
+ IDE_EXIT;
+ }
+
+ g_assert (GBP_IS_MESON_INTROSPECTION (introspection));
+
+ gbp_meson_introspection_list_run_commands_async (introspection,
+ cancellable,
+ gbp_meson_run_command_provider_list_run_commands_cb,
+ g_steal_pointer (&task));
+
+ IDE_EXIT;
+}
+
+static GListModel *
+gbp_meson_run_command_provider_list_commands_finish (IdeRunCommandProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ GListModel *ret;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_RUN_COMMAND_PROVIDER (provider));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static void
+run_command_provider_iface (IdeRunCommandProviderInterface *iface)
+{
+ iface->list_commands_async = gbp_meson_run_command_provider_list_commands_async;
+ iface->list_commands_finish = gbp_meson_run_command_provider_list_commands_finish;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpMesonRunCommandProvider, gbp_meson_run_command_provider, IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_RUN_COMMAND_PROVIDER,
run_command_provider_iface))
+
+static void
+gbp_meson_run_command_provider_parent_set (IdeObject *object,
+ IdeObject *parent)
+{
+ GbpMesonRunCommandProvider *self = (GbpMesonRunCommandProvider *)object;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_MESON_RUN_COMMAND_PROVIDER (self));
+ g_assert (!parent || IDE_IS_OBJECT (parent));
+
+ if (parent == NULL)
+ IDE_EXIT;
+
+ ide_run_command_provider_invalidates_at_phase (IDE_RUN_COMMAND_PROVIDER (self),
+ IDE_PIPELINE_PHASE_CONFIGURE);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_meson_run_command_provider_class_init (GbpMesonRunCommandProviderClass *klass)
+{
+ IdeObjectClass *ide_object_class = IDE_OBJECT_CLASS (klass);
+
+ ide_object_class->parent_set = gbp_meson_run_command_provider_parent_set;
+}
+
+static void
+gbp_meson_run_command_provider_init (GbpMesonRunCommandProvider *self)
+{
+}
diff --git a/src/plugins/meson/gbp-meson-test-provider.h b/src/plugins/meson/gbp-meson-run-command-provider.h
similarity index 71%
rename from src/plugins/meson/gbp-meson-test-provider.h
rename to src/plugins/meson/gbp-meson-run-command-provider.h
index 2ed6efd51..2b2bff778 100644
--- a/src/plugins/meson/gbp-meson-test-provider.h
+++ b/src/plugins/meson/gbp-meson-run-command-provider.h
@@ -1,6 +1,6 @@
-/* gbp-meson-test-provider.h
+/* gbp-meson-run-command-provider.h
*
- * Copyright 2017-2019 Christian Hergert <chergert redhat com>
+ * Copyright 2022 Christian Hergert <chergert redhat com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,8 +24,8 @@
G_BEGIN_DECLS
-#define GBP_TYPE_MESON_TEST_PROVIDER (gbp_meson_test_provider_get_type())
+#define GBP_TYPE_MESON_RUN_COMMAND_PROVIDER (gbp_meson_run_command_provider_get_type())
-G_DECLARE_FINAL_TYPE (GbpMesonTestProvider, gbp_meson_test_provider, GBP, MESON_TEST_PROVIDER,
IdeTestProvider)
+G_DECLARE_FINAL_TYPE (GbpMesonRunCommandProvider, gbp_meson_run_command_provider, GBP,
MESON_RUN_COMMAND_PROVIDER, IdeObject)
G_END_DECLS
diff --git a/src/plugins/meson/gbp-meson-toolchain-edition-preferences-row.c
b/src/plugins/meson/gbp-meson-toolchain-edition-preferences-row.c
index e93e67fda..b1ff91388 100644
--- a/src/plugins/meson/gbp-meson-toolchain-edition-preferences-row.c
+++ b/src/plugins/meson/gbp-meson-toolchain-edition-preferences-row.c
@@ -367,8 +367,6 @@ gbp_meson_toolchain_edition_preferences_row_finalize (GObject *object)
* @self: a #GbpMesonToolchainEditionPreferencesRow
*
* Requests the configuration popover the be shown over the widget.
- *
- * Since: 3.32
*/
void
gbp_meson_toolchain_edition_preferences_row_show_popup (GbpMesonToolchainEditionPreferencesRow *self)
diff --git a/src/plugins/meson/gbp-meson-toolchain.c b/src/plugins/meson/gbp-meson-toolchain.c
index 9a52fe280..0720fea7f 100644
--- a/src/plugins/meson/gbp-meson-toolchain.c
+++ b/src/plugins/meson/gbp-meson-toolchain.c
@@ -119,8 +119,6 @@ gbp_meson_toolchain_load (GbpMesonToolchain *self,
* Gets the path to the Meson cross-file
*
* Returns: (transfer none): the path to the Meson cross-file.
- *
- * Since: 3.32
*/
const gchar *
gbp_meson_toolchain_get_file_path (GbpMesonToolchain *self)
diff --git a/src/plugins/meson/meson-plugin.c b/src/plugins/meson/meson-plugin.c
index 9724ec5e3..166a5c04a 100644
--- a/src/plugins/meson/meson-plugin.c
+++ b/src/plugins/meson/meson-plugin.c
@@ -18,7 +18,12 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
+#define G_LOG_DOMAIN "meson-plugin"
+
+#include "config.h"
+
#include <libpeas/peas.h>
+
#include <libide-foundry.h>
#include <libide-gui.h>
@@ -27,9 +32,12 @@
#include "gbp-meson-build-target-provider.h"
#include "gbp-meson-config-view-addin.h"
#include "gbp-meson-pipeline-addin.h"
-#include "gbp-meson-test-provider.h"
+#include "gbp-meson-run-command-provider.h"
#include "gbp-meson-toolchain-provider.h"
+
+#if 0
#include "gbp-meson-toolchain-edition-preferences-addin.h"
+#endif
_IDE_EXTERN void
_gbp_meson_register_types (PeasObjectModule *module)
@@ -37,11 +45,6 @@ _gbp_meson_register_types (PeasObjectModule *module)
/* For in-tree builds of meson projects */
ide_g_file_add_ignored_pattern ("_build");
-#if 0
- peas_object_module_register_extension_type (module,
- IDE_TYPE_CONFIG_VIEW_ADDIN,
- GBP_TYPE_MESON_CONFIG_VIEW_ADDIN);
-#endif
peas_object_module_register_extension_type (module,
IDE_TYPE_PIPELINE_ADDIN,
GBP_TYPE_MESON_PIPELINE_ADDIN);
@@ -55,12 +58,18 @@ _gbp_meson_register_types (PeasObjectModule *module)
IDE_TYPE_BUILD_TARGET_PROVIDER,
GBP_TYPE_MESON_BUILD_TARGET_PROVIDER);
peas_object_module_register_extension_type (module,
- IDE_TYPE_TEST_PROVIDER,
- GBP_TYPE_MESON_TEST_PROVIDER);
+ IDE_TYPE_RUN_COMMAND_PROVIDER,
+ GBP_TYPE_MESON_RUN_COMMAND_PROVIDER);
peas_object_module_register_extension_type (module,
IDE_TYPE_TOOLCHAIN_PROVIDER,
GBP_TYPE_MESON_TOOLCHAIN_PROVIDER);
+
+#if 0
peas_object_module_register_extension_type (module,
IDE_TYPE_PREFERENCES_ADDIN,
GBP_TYPE_MESON_TOOLCHAIN_EDITION_PREFERENCES_ADDIN);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_CONFIG_VIEW_ADDIN,
+ GBP_TYPE_MESON_CONFIG_VIEW_ADDIN);
+#endif
}
diff --git a/src/plugins/meson/meson.build b/src/plugins/meson/meson.build
index 38923ed21..b3df6d1fe 100644
--- a/src/plugins/meson/meson.build
+++ b/src/plugins/meson/meson.build
@@ -6,17 +6,18 @@ plugins_sources += files([
'gbp-meson-build-system.c',
'gbp-meson-build-target-provider.c',
'gbp-meson-build-target.c',
- 'gbp-meson-config-view-addin.c',
+ 'gbp-meson-introspection.c',
'gbp-meson-pipeline-addin.c',
- 'gbp-meson-test-provider.c',
- 'gbp-meson-test.c',
- 'gbp-meson-tool-row.c',
- 'gbp-meson-toolchain-edition-preferences-addin.c',
- 'gbp-meson-toolchain-edition-preferences-row.c',
+ 'gbp-meson-run-command-provider.c',
'gbp-meson-toolchain-provider.c',
'gbp-meson-toolchain.c',
'gbp-meson-utils.c',
'meson-plugin.c',
+
+ # 'gbp-meson-config-view-addin.c',
+ # 'gbp-meson-toolchain-edition-preferences-addin.c',
+ # 'gbp-meson-toolchain-edition-preferences-row.c',
+ # 'gbp-meson-tool-row.c',
])
plugin_meson_resources = gnome.compile_resources(
@@ -27,14 +28,14 @@ plugin_meson_resources = gnome.compile_resources(
plugins_sources += plugin_meson_resources
-test_sources = files([
+test_meson_sources = files([
'test-meson-build-system.c',
'gbp-meson-build-system.c',
'gbp-meson-toolchain.c',
'gbp-meson-utils.c',
])
-test_meson = executable('test-meson', test_sources,
+test_meson = executable('test-meson', test_meson_sources,
c_args: test_cflags,
dependencies: [ libide_foundry_dep, libide_terminal_dep ],
)
diff --git a/src/plugins/meson/meson.plugin b/src/plugins/meson/meson.plugin
index 8d9ab2349..963141de8 100644
--- a/src/plugins/meson/meson.plugin
+++ b/src/plugins/meson/meson.plugin
@@ -4,8 +4,9 @@ Builtin=true
Copyright=Copyright © 2016 Patrick Griffis
Description=Provides integration with the Meson build system
Embedded=_gbp_meson_register_types
-Hidden=true
Module=meson
Name=Meson
-X-Project-File-Filter-Name=Meson Project (meson.build)
+X-Category=buildsystems
+X-Project-File-Filter-Name=Meson (meson.build)
X-Project-File-Filter-Pattern=meson.build
+X-Preferences-Kind=application;project;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]