[gnome-builder/wip/tintou/toolchain] gcc: provide cross-architecture toolchains from the system
- From: Corentin Noël <corentinnoel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/tintou/toolchain] gcc: provide cross-architecture toolchains from the system
- Date: Wed, 2 May 2018 12:45:09 +0000 (UTC)
commit eeccc7848696c5b9c11faa9c85d36893bb441319
Author: Corentin Noël <corentin noel collabora co uk>
Date: Wed May 2 13:43:16 2018 +0100
gcc: provide cross-architecture toolchains from the system
src/plugins/gcc/gbp-gcc-plugin.c | 2 +
src/plugins/gcc/gbp-gcc-toolchain-provider.c | 378 +++++++++++++++++++++++++++
src/plugins/gcc/gbp-gcc-toolchain-provider.h | 30 +++
src/plugins/gcc/meson.build | 2 +
4 files changed, 412 insertions(+)
---
diff --git a/src/plugins/gcc/gbp-gcc-plugin.c b/src/plugins/gcc/gbp-gcc-plugin.c
index 7e4331a68..feea11c18 100644
--- a/src/plugins/gcc/gbp-gcc-plugin.c
+++ b/src/plugins/gcc/gbp-gcc-plugin.c
@@ -20,9 +20,11 @@
#include <libpeas/peas.h>
#include "gbp-gcc-pipeline-addin.h"
+#include "gbp-gcc-toolchain-provider.h"
void
gbp_gcc_register_types (PeasObjectModule *module)
{
peas_object_module_register_extension_type (module, IDE_TYPE_BUILD_PIPELINE_ADDIN,
GBP_TYPE_GCC_PIPELINE_ADDIN);
+ peas_object_module_register_extension_type (module, IDE_TYPE_TOOLCHAIN_PROVIDER,
GBP_TYPE_GCC_TOOLCHAIN_PROVIDER);
}
diff --git a/src/plugins/gcc/gbp-gcc-toolchain-provider.c b/src/plugins/gcc/gbp-gcc-toolchain-provider.c
new file mode 100644
index 000000000..9c67d8a3c
--- /dev/null
+++ b/src/plugins/gcc/gbp-gcc-toolchain-provider.c
@@ -0,0 +1,378 @@
+/* gbp-gcc-toolchain-provider.c
+ *
+ * Copyright 2018 Corentin Noël <corentin noel collabora com>
+ * Copyright 2018 Collabora Ltd.
+ *
+ * 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/>.
+ */
+
+#define G_LOG_DOMAIN "gbp-gcc-toolchain-provider"
+
+#include <glib/gi18n.h>
+
+#include "gbp-gcc-toolchain-provider.h"
+
+struct _GbpGccToolchainProvider
+{
+ IdeObject parent_instance;
+ GPtrArray *toolchains;
+};
+
+typedef struct
+{
+ GList *folders;
+ GPtrArray *found_files;
+ IdeTask *task;
+} FileSearching;
+
+static FileSearching *
+gbp_gcc_toolchain_provider_file_searching_new (void)
+{
+ FileSearching *file_searching;
+
+ file_searching = g_slice_new0 (FileSearching);
+ file_searching->task = NULL;
+ file_searching->folders = NULL;
+ file_searching->found_files = g_ptr_array_new ();
+ IDE_PTR_ARRAY_SET_FREE_FUNC (file_searching->found_files, g_object_unref);
+
+ return file_searching;
+}
+
+static void
+gbp_gcc_toolchain_provider_file_searching_free (FileSearching *file_searching)
+{
+ if (file_searching->task)
+ g_object_unref (file_searching->task);
+
+ if (file_searching->found_files)
+ g_ptr_array_unref (file_searching->found_files);
+
+ if (file_searching->folders)
+ g_list_free_full (file_searching->folders, g_object_unref);
+
+ g_slice_free (FileSearching, file_searching);
+}
+
+static gchar *
+_create_tool_path (const gchar *parent_name,
+ const gchar *arch,
+ const gchar *toolname)
+{
+ g_autofree gchar *tool_name = g_strdup_printf ("%s%s", arch, toolname);
+ g_autofree gchar *tool_path = g_build_filename (parent_name, tool_name, NULL);
+ if (!g_file_test (tool_path, G_FILE_TEST_EXISTS))
+ return NULL;
+
+ return g_steal_pointer (&tool_path);
+}
+
+static IdeToolchain *
+gbp_gcc_toolchain_provider_get_toolchain_from_file (GbpGccToolchainProvider *self,
+ GFile *file,
+ const gchar *arch)
+{
+ g_autoptr(IdeTriplet) triplet = ide_triplet_new (arch);
+ g_autoptr(IdeSimpleToolchain) toolchain = NULL;
+ g_autoptr(GFile) parent = NULL;
+ g_autofree gchar *parent_path = NULL;
+ g_autofree gchar *gcc_path = NULL;
+ g_autofree gchar *toolchain_id = NULL;
+ g_autofree gchar *display_name = NULL;
+ g_autofree gchar *sdk_cplusplus_path = NULL;
+ g_autofree gchar *sdk_ar_path = NULL;
+ g_autofree gchar *sdk_ld_path = NULL;
+ g_autofree gchar *sdk_strip_path = NULL;
+ g_autofree gchar *sdk_pkg_config_path = NULL;
+ IdeContext *context;
+
+ gcc_path = g_file_get_path (file);
+ toolchain_id = g_strdup_printf ("gcc:%s", gcc_path);
+ display_name = g_strdup_printf (_("GCC %s cross-compiler"), arch);
+ context = ide_object_get_context (IDE_OBJECT (self));
+ toolchain = ide_simple_toolchain_new (context, toolchain_id, display_name);
+ ide_toolchain_set_host_triplet (IDE_TOOLCHAIN (toolchain), triplet);
+ ide_simple_toolchain_set_tool_for_language (toolchain, IDE_TOOLCHAIN_LANGUAGE_C, IDE_TOOLCHAIN_TOOL_CC,
gcc_path);
+
+ parent = g_file_get_parent (file);
+ parent_path = g_file_get_path (parent);
+
+ sdk_cplusplus_path = _create_tool_path (parent_path, arch, "-g++");
+ sdk_ar_path = _create_tool_path (parent_path, arch, "-ar");
+ sdk_ld_path = _create_tool_path (parent_path, arch, "-ld");
+ sdk_strip_path = _create_tool_path (parent_path, arch, "-strip");
+ sdk_pkg_config_path = _create_tool_path (parent_path, arch, "-pkg-config");
+
+ if (sdk_cplusplus_path != NULL)
+ ide_simple_toolchain_set_tool_for_language (toolchain, IDE_TOOLCHAIN_LANGUAGE_CPLUSPLUS,
IDE_TOOLCHAIN_TOOL_CC, sdk_cplusplus_path);
+
+ if (sdk_ar_path != NULL)
+ ide_simple_toolchain_set_tool_for_language (toolchain, IDE_TOOLCHAIN_LANGUAGE_ANY,
IDE_TOOLCHAIN_TOOL_AR, sdk_ar_path);
+
+ if (sdk_ld_path != NULL)
+ ide_simple_toolchain_set_tool_for_language (toolchain, IDE_TOOLCHAIN_LANGUAGE_ANY,
IDE_TOOLCHAIN_TOOL_LD, sdk_ld_path);
+
+ if (sdk_strip_path != NULL)
+ ide_simple_toolchain_set_tool_for_language (toolchain, IDE_TOOLCHAIN_LANGUAGE_ANY,
IDE_TOOLCHAIN_TOOL_STRIP, sdk_strip_path);
+
+ if (sdk_pkg_config_path != NULL)
+ ide_simple_toolchain_set_tool_for_language (toolchain, IDE_TOOLCHAIN_LANGUAGE_ANY,
IDE_TOOLCHAIN_TOOL_PKG_CONFIG, sdk_pkg_config_path);
+
+ return IDE_TOOLCHAIN (g_steal_pointer (&toolchain));
+}
+
+static void
+gbp_gcc_toolchain_provider_load_worker (IdeTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GbpGccToolchainProvider *self = source_object;
+ g_autoptr(GPtrArray) toolchains = NULL;
+ GPtrArray *files = task_data;
+
+ g_assert (IDE_IS_TASK (task));
+ g_assert (GBP_IS_GCC_TOOLCHAIN_PROVIDER (self));
+ g_assert (files != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ toolchains = g_ptr_array_new_with_free_func (g_object_unref);
+
+ for (guint i = 0; i < files->len; i++)
+ {
+ GFile *file = g_ptr_array_index (files, i);
+ g_autofree gchar *basename = NULL;
+ glong basename_length = 0;
+
+ basename = g_file_get_basename (file);
+ basename_length = g_utf8_strlen (basename, -1);
+ if (basename_length > sizeof ("-gcc"))
+ {
+ g_autofree gchar *arch = NULL;
+ arch = g_utf8_substring (basename, 0, g_utf8_strlen (basename, -1) - sizeof("-gcc") +1 );
+ /* MinGW is out of the scope of this provider */
+ if (g_strrstr (arch, "-") != NULL && g_strrstr (arch, "mingw32") == NULL)
+ {
+ g_autoptr(IdeTriplet) system_triplet = ide_triplet_new_from_system ();
+ /* The default toolchain already covers the system triplet */
+ if (g_strcmp0 (ide_triplet_get_full_name (system_triplet), arch) != 0)
+ {
+ IdeToolchain *toolchain = NULL;
+
+ toolchain = gbp_gcc_toolchain_provider_get_toolchain_from_file (self, file, arch);
+ g_ptr_array_add (toolchains, toolchain);
+ }
+ }
+ }
+ }
+
+ ide_task_return_pointer (task,
+ g_steal_pointer (&toolchains),
+ (GDestroyNotify)g_ptr_array_unref);
+}
+
+void
+gbp_gcc_toolchain_provider_search_finish (FileSearching *file_searching,
+ GError *error)
+{
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GPtrArray) ret = NULL;
+
+ task = g_steal_pointer (&file_searching->task);
+ ret = g_steal_pointer (&file_searching->found_files);
+ gbp_gcc_toolchain_provider_file_searching_free (file_searching);
+
+ if (error != NULL)
+ {
+ ide_task_return_error (task, error);
+ return;
+ }
+
+ ide_task_set_task_data (task, g_steal_pointer (&ret), (GDestroyNotify)g_ptr_array_unref);
+ ide_task_run_in_thread (task, gbp_gcc_toolchain_provider_load_worker);
+}
+
+static void
+add_all_files (GFile *array,
+ GPtrArray *dest_array)
+{
+ g_assert (G_IS_FILE (array));
+ g_assert (dest_array != NULL);
+ g_ptr_array_add (dest_array, g_object_ref (array));
+}
+
+void
+gbp_gcc_toolchain_provider_search_iterate (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GFile *file = (GFile *)object;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) ret = NULL;
+ FileSearching *file_searching = user_data;
+
+ g_assert (G_IS_FILE (file));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (file_searching != NULL);
+ g_assert (IDE_IS_TASK (file_searching->task));
+
+ ret = ide_g_file_find_finish (file, result, &error);
+ IDE_PTR_ARRAY_SET_FREE_FUNC (ret, g_object_unref);
+
+ if (ret == NULL)
+ {
+ gbp_gcc_toolchain_provider_search_finish (file_searching, g_steal_pointer (&error));
+ return;
+ }
+
+ g_ptr_array_foreach (ret, (GFunc)add_all_files, file_searching->found_files);
+ file_searching->folders = g_list_remove (file_searching->folders, file);
+ if (file_searching->folders != NULL)
+ {
+ ide_g_file_find_async (file_searching->folders->data,
+ "*-gcc",
+ ide_task_get_cancellable (file_searching->task),
+ gbp_gcc_toolchain_provider_search_iterate,
+ file_searching);
+ }
+ else
+ gbp_gcc_toolchain_provider_search_finish (file_searching, NULL);
+}
+
+void
+gbp_gcc_toolchain_provider_search_init (GbpGccToolchainProvider *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GList *folders = NULL;
+ g_autoptr (IdeTask) task = NULL;
+ g_auto(GStrv) environ = NULL;
+ g_auto(GStrv) paths = NULL;
+ const gchar *path_env;
+ FileSearching *file_searching;
+
+ g_assert (GBP_IS_GCC_TOOLCHAIN_PROVIDER (self));
+
+ environ = g_get_environ ();
+ path_env = g_environ_getenv (environ, "PATH");
+ paths = g_strsplit (path_env, ":", -1);
+ for (int i = 0; paths[i] != NULL; i++)
+ folders = g_list_append (folders, g_file_new_for_path (paths[i]));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_gcc_toolchain_provider_search_init);
+ ide_task_set_priority (task, G_PRIORITY_LOW);
+
+ file_searching = gbp_gcc_toolchain_provider_file_searching_new ();
+ file_searching->task = g_steal_pointer (&task);
+ file_searching->folders = folders;
+
+ /* GCC */
+ ide_g_file_find_async (g_list_first (folders)->data,
+ "*-gcc",
+ cancellable,
+ gbp_gcc_toolchain_provider_search_iterate,
+ file_searching);
+}
+
+static void
+gbp_gcc_toolchain_provider_load_async (IdeToolchainProvider *provider,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpGccToolchainProvider *self = (GbpGccToolchainProvider *)provider;
+ g_autoptr(IdeTask) task = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_GCC_TOOLCHAIN_PROVIDER (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ gbp_gcc_toolchain_provider_search_init (self, cancellable, callback, user_data);
+
+ IDE_EXIT;
+}
+
+static gboolean
+gbp_gcc_toolchain_provider_load_finish (IdeToolchainProvider *provider,
+ GAsyncResult *result,
+ GError **error)
+{
+ GbpGccToolchainProvider *self = (GbpGccToolchainProvider *)provider;
+ g_autoptr(GPtrArray) toolchains = NULL;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_GCC_TOOLCHAIN_PROVIDER (self));
+ g_assert (IDE_IS_TASK (result));
+ g_assert (ide_task_is_valid (IDE_TASK (result), provider));
+
+ toolchains = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ if (toolchains == NULL)
+ return FALSE;
+
+ g_clear_pointer (&self->toolchains, g_ptr_array_unref);
+ self->toolchains = g_ptr_array_ref (toolchains);
+
+ for (guint i = 0; i < toolchains->len; i++)
+ {
+ IdeToolchain *toolchain = g_ptr_array_index (toolchains, i);
+
+ g_assert (IDE_IS_TOOLCHAIN (toolchain));
+
+ ide_toolchain_provider_emit_added (provider, toolchain);
+ }
+
+ return TRUE;
+}
+
+void
+gbp_gcc_toolchain_provider_unload (IdeToolchainProvider *provider,
+ IdeToolchainManager *manager)
+{
+ GbpGccToolchainProvider *self = (GbpGccToolchainProvider *)provider;
+
+ g_assert (GBP_IS_GCC_TOOLCHAIN_PROVIDER (self));
+ g_assert (IDE_IS_TOOLCHAIN_MANAGER (manager));
+
+ g_clear_pointer (&self->toolchains, g_ptr_array_unref);
+}
+
+static void
+toolchain_provider_iface_init (IdeToolchainProviderInterface *iface)
+{
+ iface->load_async = gbp_gcc_toolchain_provider_load_async;
+ iface->load_finish = gbp_gcc_toolchain_provider_load_finish;
+ iface->unload = gbp_gcc_toolchain_provider_unload;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GbpGccToolchainProvider,
+ gbp_gcc_toolchain_provider,
+ IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_TOOLCHAIN_PROVIDER,
+ toolchain_provider_iface_init))
+
+static void
+gbp_gcc_toolchain_provider_class_init (GbpGccToolchainProviderClass *klass)
+{
+}
+
+static void
+gbp_gcc_toolchain_provider_init (GbpGccToolchainProvider *self)
+{
+
+}
diff --git a/src/plugins/gcc/gbp-gcc-toolchain-provider.h b/src/plugins/gcc/gbp-gcc-toolchain-provider.h
new file mode 100644
index 000000000..f6e725549
--- /dev/null
+++ b/src/plugins/gcc/gbp-gcc-toolchain-provider.h
@@ -0,0 +1,30 @@
+/* gbp-gcc-toolchain-provider.h
+ *
+ * Copyright 2018 Corentin Noël <corentin noel collabora com>
+ * Copyright 2018 Collabora Ltd.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GCC_TOOLCHAIN_PROVIDER (gbp_gcc_toolchain_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGccToolchainProvider, gbp_gcc_toolchain_provider, GBP, GCC_TOOLCHAIN_PROVIDER,
IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/gcc/meson.build b/src/plugins/gcc/meson.build
index 648dc41ba..4127bde80 100644
--- a/src/plugins/gcc/meson.build
+++ b/src/plugins/gcc/meson.build
@@ -10,6 +10,8 @@ gcc_sources = [
'gbp-gcc-pipeline-addin.c',
'gbp-gcc-pipeline-addin.h',
'gbp-gcc-plugin.c',
+ 'gbp-gcc-toolchain-provider.c',
+ 'gbp-gcc-toolchain-provider.h',
]
gnome_builder_plugins_sources += files(gcc_sources)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]