[gnome-builder] cmake: add build target provider
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] cmake: add build target provider
- Date: Thu, 5 Aug 2021 22:15:01 +0000 (UTC)
commit f01e37048d8d99182aaf0607d1495ae31cba971a
Author: Günther Wagner <info gunibert de>
Date: Fri Aug 6 00:07:48 2021 +0200
cmake: add build target provider
This uses the preferred codemodel IDE integration which can be found
here: https://cmake.org/cmake/help/latest/guide/ide-integration/index.html
src/plugins/cmake/cmake-plugin.c | 4 +
.../cmake/gbp-cmake-build-stage-codemodel.c | 162 +++++++++++++++++
.../cmake/gbp-cmake-build-stage-codemodel.h | 33 ++++
.../cmake/gbp-cmake-build-target-provider.c | 194 +++++++++++++++++++++
.../cmake/gbp-cmake-build-target-provider.h | 33 ++++
src/plugins/cmake/gbp-cmake-pipeline-addin.c | 8 +
src/plugins/cmake/meson.build | 2 +
7 files changed, 436 insertions(+)
---
diff --git a/src/plugins/cmake/cmake-plugin.c b/src/plugins/cmake/cmake-plugin.c
index de605456c..a0505448e 100644
--- a/src/plugins/cmake/cmake-plugin.c
+++ b/src/plugins/cmake/cmake-plugin.c
@@ -27,6 +27,7 @@
#include "gbp-cmake-build-system-discovery.h"
#include "gbp-cmake-pipeline-addin.h"
#include "gbp-cmake-toolchain-provider.h"
+#include "gbp-cmake-build-target-provider.h"
_IDE_EXTERN void
_gbp_cmake_register_types (PeasObjectModule *module)
@@ -43,4 +44,7 @@ _gbp_cmake_register_types (PeasObjectModule *module)
peas_object_module_register_extension_type (module,
IDE_TYPE_TOOLCHAIN_PROVIDER,
GBP_TYPE_CMAKE_TOOLCHAIN_PROVIDER);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_BUILD_TARGET_PROVIDER,
+ GBP_TYPE_CMAKE_BUILD_TARGET_PROVIDER);
}
diff --git a/src/plugins/cmake/gbp-cmake-build-stage-codemodel.c
b/src/plugins/cmake/gbp-cmake-build-stage-codemodel.c
new file mode 100644
index 000000000..9568cde74
--- /dev/null
+++ b/src/plugins/cmake/gbp-cmake-build-stage-codemodel.c
@@ -0,0 +1,162 @@
+/* gbp-cmake-build-stage-codemodel.c
+ *
+ * Copyright 2021 Günther Wagner <info gunibert de>
+ *
+ * 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-cmake-build-stage-codemodel"
+
+#include <json-glib/json-glib.h>
+
+#include "gbp-cmake-build-stage-codemodel.h"
+
+struct _GbpCmakeBuildStageCodemodel
+{
+ IdePipelineStage parent_instance;
+};
+
+G_DEFINE_TYPE (GbpCmakeBuildStageCodemodel, gbp_cmake_build_stage_codemodel, IDE_TYPE_PIPELINE_STAGE)
+
+GbpCmakeBuildStageCodemodel *
+gbp_cmake_build_stage_codemodel_new (void)
+{
+ return g_object_new (GBP_TYPE_CMAKE_BUILD_STAGE_CODEMODEL, NULL);
+}
+
+static gchar *
+gbp_cmake_build_stage_codemodel_get_query_path (GbpCmakeBuildStageCodemodel *self,
+ IdePipeline *pipeline)
+{
+ g_return_val_if_fail (GBP_IS_CMAKE_BUILD_STAGE_CODEMODEL (self), NULL);
+ g_return_val_if_fail (IDE_IS_PIPELINE (pipeline), NULL);
+
+ return ide_pipeline_build_builddir_path (pipeline, ".cmake", "api", "v1", "query", "client-builder", NULL);
+}
+
+static JsonNode *
+gbp_cmake_build_stage_codemodel_create_query (GbpCmakeBuildStageCodemodel *self)
+{
+ g_autoptr(JsonBuilder) builder = NULL;
+
+ g_return_val_if_fail (GBP_IS_CMAKE_BUILD_STAGE_CODEMODEL (self), NULL);
+
+ builder = json_builder_new ();
+ json_builder_begin_object (builder);
+
+ json_builder_set_member_name (builder, "requests");
+ json_builder_begin_array (builder);
+
+ json_builder_begin_object (builder);
+
+ json_builder_set_member_name (builder, "kind");
+ json_builder_add_string_value (builder, "codemodel");
+
+ json_builder_set_member_name (builder, "version");
+ json_builder_add_int_value (builder, 2);
+
+ json_builder_end_object (builder);
+
+ json_builder_end_array (builder);
+
+ json_builder_end_object (builder);
+
+ return json_builder_get_root (builder);
+}
+
+static gboolean
+gbp_cmake_build_stage_codemodel_build (IdePipelineStage *stage,
+ IdePipeline *pipeline,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GbpCmakeBuildStageCodemodel *self = GBP_CMAKE_BUILD_STAGE_CODEMODEL (stage);
+ g_autoptr(JsonGenerator) generator = NULL;
+ g_autoptr(JsonNode) query = NULL;
+ g_autofree gchar *path = NULL;
+ g_autofree gchar *queryfile = NULL;
+ gboolean ret;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_CMAKE_BUILD_STAGE_CODEMODEL (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ ide_pipeline_stage_set_active (stage, TRUE);
+
+ path = gbp_cmake_build_stage_codemodel_get_query_path (self, pipeline);
+ ret = g_mkdir_with_parents (path, 0750);
+
+ if (ret != 0)
+ {
+ g_set_error_literal (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ g_strerror (errno));
+ IDE_RETURN (FALSE);
+ }
+
+ generator = json_generator_new ();
+ query = gbp_cmake_build_stage_codemodel_create_query (self);
+ json_generator_set_root (generator, query);
+ queryfile = g_build_filename (path, "query.json", NULL);
+ json_generator_to_file (generator, queryfile, NULL);
+
+ ide_pipeline_stage_set_active (stage, FALSE);
+
+ IDE_RETURN (TRUE);
+}
+
+static void
+gbp_cmake_build_stage_codemodel_query (IdePipelineStage *stage,
+ IdePipeline *pipeline,
+ GPtrArray *targets,
+ GCancellable *cancellable)
+{
+ GbpCmakeBuildStageCodemodel *self = GBP_CMAKE_BUILD_STAGE_CODEMODEL (stage);
+ g_autofree gchar *path = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_CMAKE_BUILD_STAGE_CODEMODEL (self));
+ g_assert (IDE_IS_PIPELINE (pipeline));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ path = gbp_cmake_build_stage_codemodel_get_query_path (self, pipeline);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ {
+ ide_pipeline_stage_set_completed (stage, FALSE);
+ IDE_EXIT;
+ }
+
+ ide_pipeline_stage_set_completed (stage, TRUE);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_cmake_build_stage_codemodel_class_init (GbpCmakeBuildStageCodemodelClass *klass)
+{
+ IdePipelineStageClass *stage_class = IDE_PIPELINE_STAGE_CLASS (klass);
+
+ stage_class->build = gbp_cmake_build_stage_codemodel_build;
+ stage_class->query = gbp_cmake_build_stage_codemodel_query;
+}
+
+static void
+gbp_cmake_build_stage_codemodel_init (GbpCmakeBuildStageCodemodel *self)
+{
+}
diff --git a/src/plugins/cmake/gbp-cmake-build-stage-codemodel.h
b/src/plugins/cmake/gbp-cmake-build-stage-codemodel.h
new file mode 100644
index 000000000..a00d91ea9
--- /dev/null
+++ b/src/plugins/cmake/gbp-cmake-build-stage-codemodel.h
@@ -0,0 +1,33 @@
+/* gbp-cmake-build-stage-codemodel.h
+ *
+ * Copyright 2021 Günther Wagner <info gunibert de>
+ *
+ * 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_CMAKE_BUILD_STAGE_CODEMODEL (gbp_cmake_build_stage_codemodel_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpCmakeBuildStageCodemodel, gbp_cmake_build_stage_codemodel, GBP,
CMAKE_BUILD_STAGE_CODEMODEL, IdePipelineStage)
+
+GbpCmakeBuildStageCodemodel *gbp_cmake_build_stage_codemodel_new (void);
+
+G_END_DECLS
diff --git a/src/plugins/cmake/gbp-cmake-build-target-provider.c
b/src/plugins/cmake/gbp-cmake-build-target-provider.c
new file mode 100644
index 000000000..030a6f76d
--- /dev/null
+++ b/src/plugins/cmake/gbp-cmake-build-target-provider.c
@@ -0,0 +1,194 @@
+/* gbp-cmake-build-target-provider.c
+ *
+ * Copyright 2021 Günther Wagner <info gunibert de>
+ *
+ * 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
+ */
+
+#include "gbp-cmake-build-target-provider.h"
+#include "gbp-cmake-build-target.h"
+#include <json-glib/json-glib.h>
+
+struct _GbpCmakeBuildTargetProvider
+{
+ IdeObject parent_instance;
+};
+
+static void build_target_provider_iface_init (IdeBuildTargetProviderInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GbpCmakeBuildTargetProvider, gbp_cmake_build_target_provider, IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_BUILD_TARGET_PROVIDER,
build_target_provider_iface_init))
+
+GbpCmakeBuildTargetProvider *
+gbp_cmake_build_target_provider_new (void)
+{
+ return g_object_new (GBP_TYPE_CMAKE_BUILD_TARGET_PROVIDER, NULL);
+}
+
+static void
+gbp_cmake_build_target_provider_class_init (GbpCmakeBuildTargetProviderClass *klass)
+{
+}
+
+static void
+gbp_cmake_build_target_provider_init (GbpCmakeBuildTargetProvider *self)
+{
+}
+
+static void
+gbp_cmake_build_target_provider_create_target (GbpCmakeBuildTargetProvider *self,
+ GPtrArray **ret,
+ IdeContext *context,
+ JsonObject *obj)
+{
+ g_autoptr(IdeBuildTarget) target = NULL;
+ g_autoptr(GFile) install_directory = NULL;
+ g_autofree gchar *install_dir = NULL;
+ g_autofree gchar *install_dir_abs = NULL;
+ g_autofree gchar *name = NULL;
+ JsonArray *artefacts;
+ JsonObject *path_object;
+ JsonObject *install;
+ JsonObject *prefix;
+ const gchar *artefacts_path;
+ const gchar *prefix_path;
+
+ g_return_if_fail (GBP_IS_CMAKE_BUILD_TARGET_PROVIDER (self));
+
+ artefacts = json_object_get_array_member (obj, "artifacts");
+ /* currently we support only one artefact executable */
+ path_object = json_array_get_object_element (artefacts, 0);
+ artefacts_path = json_object_get_string_member (path_object, "path");
+
+ install = json_object_get_object_member (obj, "install");
+ prefix = json_object_get_object_member (install, "prefix");
+ prefix_path = json_object_get_string_member (prefix, "path");
+
+ install_dir = g_path_get_dirname (artefacts_path);
+ install_dir_abs = g_build_path (G_DIR_SEPARATOR_S, prefix_path, install_dir, NULL);
+ install_directory = g_file_new_for_path (install_dir_abs);
+
+ name = g_path_get_basename (artefacts_path);
+ target = gbp_cmake_build_target_new (context, install_directory, name);
+
+ g_debug ("Found target %s with install directory %s", name, install_dir_abs);
+
+ g_ptr_array_add (*ret, g_steal_pointer (&target));
+}
+
+static void
+gbp_cmake_build_target_provider_get_targets_async (IdeBuildTargetProvider *provider,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpCmakeBuildTargetProvider *self = GBP_CMAKE_BUILD_TARGET_PROVIDER (provider);
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GPtrArray) ret = NULL;
+ g_autoptr(GFile) reply = NULL;
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+ g_autofree gchar *replydir = NULL;
+ IdeContext *context;
+ IdeBuildManager *build_manager;
+ IdePipeline *pipeline;
+ const gchar *builddir;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_CMAKE_BUILD_TARGET_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_cmake_build_target_provider_get_targets_async);
+ ide_task_set_priority (task, G_PRIORITY_LOW);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ build_manager = ide_build_manager_from_context (context);
+ pipeline = ide_build_manager_get_pipeline (build_manager);
+ builddir = ide_pipeline_get_builddir (pipeline);
+
+ replydir = g_build_path (G_DIR_SEPARATOR_S, builddir, ".cmake", "api", "v1", "reply", NULL);
+
+ if (!g_file_test (replydir, G_FILE_TEST_EXISTS))
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ "Response codemodel does not exists, ignoring");
+ IDE_EXIT;
+ }
+
+ ret = g_ptr_array_new_with_free_func (g_object_unref);
+ reply = g_file_new_for_path (replydir);
+ enumerator = g_file_enumerate_children (reply, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NONE,
cancellable, NULL);
+
+ while (TRUE)
+ {
+ g_autoptr(GFileInputStream) stream = NULL;
+ g_autoptr(JsonParser) parser = NULL;
+ GFile *file;
+ JsonNode *root;
+ JsonObject *jobject;
+
+ if (!g_file_enumerator_iterate (enumerator, NULL, &file, cancellable, NULL))
+ goto out;
+ if (!file)
+ break;
+
+ stream = g_file_read (file, cancellable, NULL);
+ parser = json_parser_new ();
+ json_parser_load_from_stream (parser, G_INPUT_STREAM (stream), cancellable, NULL);
+
+ root = json_parser_get_root (parser);
+ jobject = json_node_get_object (root);
+ if (json_object_has_member (jobject, "type") &&
+ ide_str_equal0 (json_object_get_string_member (jobject, "type"), "EXECUTABLE"))
+ {
+ gbp_cmake_build_target_provider_create_target (self, &ret, context, jobject);
+ }
+ }
+
+out:
+ IDE_PROBE;
+ ide_task_return_pointer (task, g_steal_pointer (&ret), g_ptr_array_unref);
+
+ IDE_EXIT;
+}
+
+static GPtrArray *
+gbp_cmake_build_target_provider_get_targets_finish (IdeBuildTargetProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ GPtrArray *ret;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_CMAKE_BUILD_TARGET_PROVIDER (provider));
+ g_assert (IDE_IS_TASK (result));
+ g_assert (ide_task_is_valid (IDE_TASK (result), provider));
+
+ ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ IDE_RETURN (IDE_PTR_ARRAY_STEAL_FULL (&ret));
+}
+
+static void
+build_target_provider_iface_init (IdeBuildTargetProviderInterface *iface)
+{
+ iface->get_targets_async = gbp_cmake_build_target_provider_get_targets_async;
+ iface->get_targets_finish = gbp_cmake_build_target_provider_get_targets_finish;
+}
diff --git a/src/plugins/cmake/gbp-cmake-build-target-provider.h
b/src/plugins/cmake/gbp-cmake-build-target-provider.h
new file mode 100644
index 000000000..5a7c954b8
--- /dev/null
+++ b/src/plugins/cmake/gbp-cmake-build-target-provider.h
@@ -0,0 +1,33 @@
+/* gbp-cmake-build-target-provider.h
+ *
+ * Copyright 2021 Günther Wagner <info gunibert de>
+ *
+ * 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_CMAKE_BUILD_TARGET_PROVIDER (gbp_cmake_build_target_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpCmakeBuildTargetProvider, gbp_cmake_build_target_provider, GBP,
CMAKE_BUILD_TARGET_PROVIDER, IdeObject)
+
+GbpCmakeBuildTargetProvider *gbp_cmake_build_target_provider_new (void);
+
+G_END_DECLS
diff --git a/src/plugins/cmake/gbp-cmake-pipeline-addin.c b/src/plugins/cmake/gbp-cmake-pipeline-addin.c
index 0a24049b6..6335fdb38 100644
--- a/src/plugins/cmake/gbp-cmake-pipeline-addin.c
+++ b/src/plugins/cmake/gbp-cmake-pipeline-addin.c
@@ -25,6 +25,7 @@
#include "gbp-cmake-build-system.h"
#include "gbp-cmake-build-stage-cross-file.h"
+#include "gbp-cmake-build-stage-codemodel.h"
#include "gbp-cmake-toolchain.h"
#include "gbp-cmake-pipeline-addin.h"
@@ -69,6 +70,7 @@ gbp_cmake_pipeline_addin_load (IdePipelineAddin *addin,
IdePipeline *pipeline)
{
GbpCMakePipelineAddin *self = (GbpCMakePipelineAddin *)addin;
+ g_autoptr(GbpCmakeBuildStageCodemodel) codemodel_stage = NULL;
g_autoptr(IdeSubprocessLauncher) configure_launcher = NULL;
g_autoptr(IdeSubprocessLauncher) build_launcher = NULL;
g_autoptr(IdeSubprocessLauncher) install_launcher = NULL;
@@ -163,6 +165,12 @@ gbp_cmake_pipeline_addin_load (IdePipelineAddin *addin,
ide_pipeline_addin_track (addin, id);
}
+ /* Setup ide integration stage for cmake */
+ codemodel_stage = gbp_cmake_build_stage_codemodel_new ();
+ ide_pipeline_stage_set_name (IDE_PIPELINE_STAGE (codemodel_stage), "Prepare Codemodel");
+ id = ide_pipeline_attach (pipeline, IDE_PIPELINE_PHASE_PREPARE, 1, IDE_PIPELINE_STAGE (codemodel_stage));
+ ide_pipeline_addin_track (addin, id);
+
/* Setup our configure stage. */
prefix_option = g_strdup_printf ("-DCMAKE_INSTALL_PREFIX=%s", prefix);
diff --git a/src/plugins/cmake/meson.build b/src/plugins/cmake/meson.build
index f97154023..31765f413 100644
--- a/src/plugins/cmake/meson.build
+++ b/src/plugins/cmake/meson.build
@@ -6,9 +6,11 @@ plugins_sources += files([
'gbp-cmake-build-system.c',
'gbp-cmake-build-system-discovery.c',
'gbp-cmake-build-target.c',
+ 'gbp-cmake-build-target-provider.c',
'gbp-cmake-pipeline-addin.c',
'gbp-cmake-toolchain.c',
'gbp-cmake-toolchain-provider.c',
+ 'gbp-cmake-build-stage-codemodel.c',
])
plugin_cmake_resources = gnome.compile_resources(
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]