/* ide-config.c * * Copyright 2016-2019 Christian Hergert * * 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 . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "ide-config" #include "config.h" #include #include "ide-config-manager.h" #include "ide-config-private.h" #include "ide-config.h" #include "ide-foundry-enums.h" #include "ide-foundry-compat.h" #include "ide-runtime-manager.h" #include "ide-runtime.h" #include "ide-toolchain-manager.h" #include "ide-toolchain.h" typedef struct { gchar *app_id; gchar **build_commands; gchar *config_opts; gchar *display_name; gchar *id; gchar **post_install_commands; gchar *prefix; gchar *run_opts; gchar *runtime_id; gchar *toolchain_id; gchar *prepend_path; gchar *append_path; GHashTable *pipeline_args; GFile *build_commands_dir; IdeEnvironment *environment; IdeEnvironment *runtime_environment; GHashTable *internal; gint parallelism; guint sequence; guint block_changed; guint dirty : 1; guint debug : 1; guint has_attached : 1; guint prefix_set : 1; /* * This is used to determine if we can make progress building * with this configuration. When runtimes are added/removed, the * IdeConfig:ready property will be notified. */ guint runtime_ready : 1; IdeBuildLocality locality : 3; } IdeConfigPrivate; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (IdeConfig, ide_config, IDE_TYPE_OBJECT) enum { PROP_0, PROP_PREPEND_PATH, PROP_APPEND_PATH, PROP_APP_ID, PROP_BUILD_COMMANDS, PROP_BUILD_COMMANDS_DIR, PROP_CONFIG_OPTS, PROP_DEBUG, PROP_DIRTY, PROP_DISPLAY_NAME, PROP_ENVIRON, PROP_ID, PROP_LOCALITY, PROP_PARALLELISM, PROP_POST_INSTALL_COMMANDS, PROP_PREFIX, PROP_PREFIX_SET, PROP_READY, PROP_RUNTIME, PROP_RUNTIME_ID, PROP_TOOLCHAIN_ID, PROP_TOOLCHAIN, PROP_RUN_OPTS, N_PROPS }; enum { CHANGED, N_SIGNALS }; static GParamSpec *properties [N_PROPS]; static guint signals [N_SIGNALS]; static void _value_free (gpointer data) { GValue *value = data; if (value != NULL) { g_value_unset (value); g_slice_free (GValue, value); } } static GValue * _value_new (GType type) { GValue *value; value = g_slice_new0 (GValue); g_value_init (value, type); return value; } static void ide_config_block_changed (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_assert (IDE_IS_CONFIG (self)); priv->block_changed++; } static void ide_config_unblock_changed (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_assert (IDE_IS_CONFIG (self)); priv->block_changed--; } static void ide_config_emit_changed (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_assert (IDE_IS_CONFIG (self)); if (priv->block_changed == 0) g_signal_emit (self, signals [CHANGED], 0); } static IdeRuntime * ide_config_real_get_runtime (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); if (priv->runtime_id != NULL) { g_autoptr(IdeContext) context = NULL; g_autoptr(IdeRuntimeManager) runtime_manager = NULL; /* We might be in a thread, ref objects */ context = ide_object_ref_context (IDE_OBJECT (self)); runtime_manager = ide_object_get_child_typed (IDE_OBJECT (context), IDE_TYPE_RUNTIME_MANAGER); return ide_runtime_manager_get_runtime (runtime_manager, priv->runtime_id); } return NULL; } static void ide_config_set_id (IdeConfig *self, const gchar *id) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (id != NULL); if (g_strcmp0 (id, priv->id) != 0) { g_free (priv->id); priv->id = g_strdup (id); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ID]); } } static void ide_config_runtime_manager_items_changed (IdeConfig *self, guint position, guint added, guint removed, IdeRuntimeManager *runtime_manager) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); IdeRuntime *runtime; gboolean runtime_ready; g_assert (IDE_IS_CONFIG (self)); if (ide_object_in_destruction (IDE_OBJECT (self))) return; g_assert (IDE_IS_RUNTIME_MANAGER (runtime_manager)); runtime = ide_runtime_manager_get_runtime (runtime_manager, priv->runtime_id); runtime_ready = !!runtime; if (!priv->runtime_ready && runtime_ready) ide_runtime_prepare_configuration (runtime, self); if (runtime_ready != priv->runtime_ready) { priv->runtime_ready = runtime_ready; g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_READY]); } } static void ide_config_environment_changed (IdeConfig *self, IdeEnvironment *environment) { IDE_ENTRY; g_assert (IDE_IS_CONFIG (self)); g_assert (IDE_IS_ENVIRONMENT (environment)); if (ide_object_in_destruction (IDE_OBJECT (self))) return; ide_config_set_dirty (self, TRUE); ide_config_emit_changed (self); IDE_EXIT; } static void ide_config_runtime_environment_changed (IdeConfig *self, IdeEnvironment *environment) { IDE_ENTRY; g_assert (IDE_IS_CONFIG (self)); g_assert (IDE_IS_ENVIRONMENT (environment)); if (ide_object_in_destruction (IDE_OBJECT (self))) return; ide_config_set_dirty (self, TRUE); ide_config_emit_changed (self); IDE_EXIT; } static void ide_config_real_set_runtime (IdeConfig *self, IdeRuntime *runtime) { const gchar *runtime_id = "host"; g_assert (IDE_IS_CONFIG (self)); g_assert (!runtime || IDE_IS_RUNTIME (runtime)); if (runtime != NULL) runtime_id = ide_runtime_get_id (runtime); ide_config_set_runtime_id (self, runtime_id); } static gchar * ide_config_repr (IdeObject *object) { IdeConfig *self = (IdeConfig *)object; IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_assert (IDE_IS_MAIN_THREAD ()); g_assert (IDE_IS_CONFIG (self)); return g_strdup_printf ("%s id=\"%s\" name=\"%s\" runtime=\"%s\"", G_OBJECT_TYPE_NAME (self), priv->id, priv->display_name, priv->runtime_id); } static void ide_config_finalize (GObject *object) { IdeConfig *self = (IdeConfig *)object; IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_clear_object (&priv->build_commands_dir); g_clear_object (&priv->environment); g_clear_object (&priv->runtime_environment); g_clear_pointer (&priv->build_commands, g_strfreev); g_clear_pointer (&priv->internal, g_hash_table_unref); g_clear_pointer (&priv->pipeline_args, g_hash_table_unref); g_clear_pointer (&priv->config_opts, g_free); g_clear_pointer (&priv->display_name, g_free); g_clear_pointer (&priv->id, g_free); g_clear_pointer (&priv->post_install_commands, g_strfreev); g_clear_pointer (&priv->prefix, g_free); g_clear_pointer (&priv->run_opts, g_free); g_clear_pointer (&priv->runtime_id, g_free); g_clear_pointer (&priv->app_id, g_free); g_clear_pointer (&priv->toolchain_id, g_free); g_clear_pointer (&priv->prepend_path, g_free); g_clear_pointer (&priv->append_path, g_free); G_OBJECT_CLASS (ide_config_parent_class)->finalize (object); } static void ide_config_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { IdeConfig *self = IDE_CONFIG (object); switch (prop_id) { case PROP_CONFIG_OPTS: g_value_set_string (value, ide_config_get_config_opts (self)); break; case PROP_BUILD_COMMANDS: g_value_set_boxed (value, ide_config_get_build_commands (self)); break; case PROP_BUILD_COMMANDS_DIR: g_value_set_object (value, ide_config_get_build_commands_dir (self)); break; case PROP_DEBUG: g_value_set_boolean (value, ide_config_get_debug (self)); break; case PROP_DIRTY: g_value_set_boolean (value, ide_config_get_dirty (self)); break; case PROP_DISPLAY_NAME: g_value_set_string (value, ide_config_get_display_name (self)); break; case PROP_ENVIRON: g_value_set_boxed (value, ide_config_get_environ (self)); break; case PROP_ID: g_value_set_string (value, ide_config_get_id (self)); break; case PROP_PARALLELISM: g_value_set_int (value, ide_config_get_parallelism (self)); break; case PROP_READY: g_value_set_boolean (value, ide_config_get_ready (self)); break; case PROP_POST_INSTALL_COMMANDS: g_value_set_boxed (value, ide_config_get_post_install_commands (self)); break; case PROP_PREFIX: g_value_set_string (value, ide_config_get_prefix (self)); break; case PROP_RUNTIME: g_value_set_object (value, ide_config_get_runtime (self)); break; case PROP_RUNTIME_ID: g_value_set_string (value, ide_config_get_runtime_id (self)); break; case PROP_TOOLCHAIN: g_value_take_object (value, ide_config_get_toolchain (self)); break; case PROP_TOOLCHAIN_ID: g_value_set_string (value, ide_config_get_toolchain_id (self)); break; case PROP_RUN_OPTS: g_value_set_string (value, ide_config_get_run_opts (self)); break; case PROP_APP_ID: g_value_set_string (value, ide_config_get_app_id (self)); break; case PROP_PREPEND_PATH: g_value_set_string (value, ide_config_get_prepend_path (self)); break; case PROP_APPEND_PATH: g_value_set_string (value, ide_config_get_append_path (self)); break; case PROP_LOCALITY: g_value_set_flags (value, ide_config_get_locality (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void ide_config_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { IdeConfig *self = IDE_CONFIG (object); switch (prop_id) { case PROP_CONFIG_OPTS: ide_config_set_config_opts (self, g_value_get_string (value)); break; case PROP_BUILD_COMMANDS: ide_config_set_build_commands (self, g_value_get_boxed (value)); break; case PROP_BUILD_COMMANDS_DIR: ide_config_set_build_commands_dir (self, g_value_get_object (value)); break; case PROP_DEBUG: ide_config_set_debug (self, g_value_get_boolean (value)); break; case PROP_DIRTY: ide_config_set_dirty (self, g_value_get_boolean (value)); break; case PROP_DISPLAY_NAME: ide_config_set_display_name (self, g_value_get_string (value)); break; case PROP_ID: ide_config_set_id (self, g_value_get_string (value)); break; case PROP_POST_INSTALL_COMMANDS: ide_config_set_post_install_commands (self, g_value_get_boxed (value)); break; case PROP_PREFIX: ide_config_set_prefix (self, g_value_get_string (value)); break; case PROP_PARALLELISM: ide_config_set_parallelism (self, g_value_get_int (value)); break; case PROP_RUNTIME: ide_config_set_runtime (self, g_value_get_object (value)); break; case PROP_RUNTIME_ID: ide_config_set_runtime_id (self, g_value_get_string (value)); break; case PROP_TOOLCHAIN: ide_config_set_toolchain (self, g_value_get_object (value)); break; case PROP_TOOLCHAIN_ID: ide_config_set_toolchain_id (self, g_value_get_string (value)); break; case PROP_RUN_OPTS: ide_config_set_run_opts (self, g_value_get_string (value)); break; case PROP_APP_ID: ide_config_set_app_id (self, g_value_get_string (value)); break; case PROP_PREPEND_PATH: ide_config_set_prepend_path (self, g_value_get_string (value)); break; case PROP_APPEND_PATH: ide_config_set_append_path (self, g_value_get_string (value)); break; case PROP_LOCALITY: ide_config_set_locality (self, g_value_get_flags (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void ide_config_class_init (IdeConfigClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); IdeObjectClass *i_object_class = IDE_OBJECT_CLASS (klass); object_class->finalize = ide_config_finalize; object_class->get_property = ide_config_get_property; object_class->set_property = ide_config_set_property; i_object_class->repr = ide_config_repr; klass->get_runtime = ide_config_real_get_runtime; klass->set_runtime = ide_config_real_set_runtime; properties [PROP_PREPEND_PATH] = g_param_spec_string ("prepend-path", "Prepend Path", "Prepend to PATH environment variable", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties [PROP_APPEND_PATH] = g_param_spec_string ("append-path", "Append Path", "Append to PATH environment variable", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties [PROP_BUILD_COMMANDS] = g_param_spec_boxed ("build-commands", "Build commands", "Build commands", G_TYPE_STRV, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_BUILD_COMMANDS_DIR] = g_param_spec_object ("build-commands-dir", "Build commands Dir", "Directory to run build commands from", G_TYPE_FILE, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_CONFIG_OPTS] = g_param_spec_string ("config-opts", "Config Options", "Parameters to bootstrap the project", NULL, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_DEBUG] = g_param_spec_boolean ("debug", "Debug", "Debug", TRUE, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_DIRTY] = g_param_spec_boolean ("dirty", "Dirty", "If the configuration has been changed.", FALSE, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_DISPLAY_NAME] = g_param_spec_string ("display-name", "Display Name", "Display Name", NULL, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_ENVIRON] = g_param_spec_boxed ("environ", "Environ", "Environ", G_TYPE_STRV, (G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_ID] = g_param_spec_string ("id", "Id", "Id", NULL, (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); properties [PROP_PARALLELISM] = g_param_spec_int ("parallelism", "Parallelism", "Parallelism", -1, G_MAXINT, -1, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_POST_INSTALL_COMMANDS] = g_param_spec_boxed ("post-install-commands", "Post install commands", "Post install commands", G_TYPE_STRV, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_PREFIX] = g_param_spec_string ("prefix", "Prefix", "Prefix", NULL, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_PREFIX_SET] = g_param_spec_boolean ("prefix-set", "Prefix Set", "If Prefix is Set or not (meaning default)", FALSE, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_READY] = g_param_spec_boolean ("ready", "Ready", "If the configuration can be used for building", FALSE, (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); properties [PROP_RUN_OPTS] = g_param_spec_string ("run-opts", "Run Options", "The options for running the target application", NULL, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_RUNTIME] = g_param_spec_object ("runtime", "Runtime", "Runtime", IDE_TYPE_RUNTIME, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_RUNTIME_ID] = g_param_spec_string ("runtime-id", "Runtime Id", "The identifier of the runtime", "host", (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_TOOLCHAIN] = g_param_spec_object ("toolchain", "Toolchain", "Toolchain", IDE_TYPE_TOOLCHAIN, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_TOOLCHAIN_ID] = g_param_spec_string ("toolchain-id", "Toolchain Id", "The identifier of the toolchain", "default", (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_APP_ID] = g_param_spec_string ("app-id", "App ID", "The application ID (such as org.gnome.Builder)", NULL, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); properties [PROP_LOCALITY] = g_param_spec_flags ("locality", "Locality", "Where the build may occur", IDE_TYPE_BUILD_LOCALITY, IDE_BUILD_LOCALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, properties); signals [CHANGED] = g_signal_new ("changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); } static void ide_config_init (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_autoptr(IdeEnvironment) env = ide_environment_new (); g_autoptr(IdeEnvironment) rt_env = ide_environment_new (); priv->runtime_id = g_strdup ("host"); priv->toolchain_id = g_strdup ("default"); priv->debug = TRUE; priv->parallelism = -1; priv->locality = IDE_BUILD_LOCALITY_DEFAULT; priv->internal = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _value_free); priv->pipeline_args = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_strfreev); ide_config_set_environment (self, env); ide_config_set_runtime_environment (self, rt_env); } /** * ide_config_get_app_id: * @self: An #IdeConfig * * Gets the application ID for the configuration. * * Returns: (transfer none) (nullable): A string. * * Since: 3.32 */ const gchar * ide_config_get_app_id (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->app_id; } void ide_config_set_app_id (IdeConfig *self, const gchar *app_id) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (priv->app_id != app_id) { g_free (priv->app_id); priv->app_id = g_strdup (app_id); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_APP_ID]); } } const gchar * ide_config_get_runtime_id (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->runtime_id; } void ide_config_set_runtime_id (IdeConfig *self, const gchar *runtime_id) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (runtime_id == NULL) runtime_id = "host"; if (g_strcmp0 (runtime_id, priv->runtime_id) != 0) { priv->runtime_ready = FALSE; g_free (priv->runtime_id); priv->runtime_id = g_strdup (runtime_id); ide_config_set_dirty (self, TRUE); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_RUNTIME_ID]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_RUNTIME]); if (priv->has_attached) { IdeRuntimeManager *runtime_manager; IdeContext *context; g_assert (IDE_IS_MAIN_THREAD ()); context = ide_object_get_context (IDE_OBJECT (self)); runtime_manager = ide_runtime_manager_from_context (context); ide_config_runtime_manager_items_changed (self, 0, 0, 0, runtime_manager); ide_config_emit_changed (self); } } } /** * ide_config_get_toolchain_id: * @self: An #IdeConfig * * Gets the toolchain id for the configuration. * * Returns: (transfer none) (nullable): The id of an #IdeToolchain or %NULL * * Since: 3.32 */ const gchar * ide_config_get_toolchain_id (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->toolchain_id; } /** * ide_config_set_toolchain_id: * @self: An #IdeConfig * @toolchain_id: The id of an #IdeToolchain * * Sets the toolchain id for the configuration. * * Since: 3.32 */ void ide_config_set_toolchain_id (IdeConfig *self, const gchar *toolchain_id) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (toolchain_id == NULL) toolchain_id = "default"; if (g_strcmp0 (toolchain_id, priv->toolchain_id) != 0) { g_free (priv->toolchain_id); priv->toolchain_id = g_strdup (toolchain_id); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TOOLCHAIN_ID]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TOOLCHAIN]); ide_config_set_dirty (self, TRUE); ide_config_emit_changed (self); } } /** * ide_config_get_runtime: * @self: An #IdeConfig * * Gets the runtime for the configuration. * * Returns: (transfer none) (nullable): An #IdeRuntime * * Since: 3.32 */ IdeRuntime * ide_config_get_runtime (IdeConfig *self) { g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return IDE_CONFIG_GET_CLASS (self)->get_runtime (self); } void ide_config_set_runtime (IdeConfig *self, IdeRuntime *runtime) { g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (!runtime || IDE_IS_RUNTIME (runtime)); IDE_CONFIG_GET_CLASS (self)->set_runtime (self, runtime); } /** * ide_config_get_toolchain: * @self: An #IdeConfig * * Gets the toolchain for the configuration. * * Returns: (transfer full) (nullable): An #IdeToolchain * * Since: 3.32 */ IdeToolchain * ide_config_get_toolchain (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); if (priv->toolchain_id != NULL) { IdeContext *context = ide_object_get_context (IDE_OBJECT (self)); IdeToolchainManager *toolchain_manager = ide_toolchain_manager_from_context (context); g_autoptr (IdeToolchain) toolchain = ide_toolchain_manager_get_toolchain (toolchain_manager, priv->toolchain_id); if (toolchain != NULL) return g_steal_pointer (&toolchain); } return NULL; } /** * ide_config_set_toolchain: * @self: An #IdeConfig * @toolchain: (nullable): An #IdeToolchain or %NULL to use the default one * * Sets the toolchain for the configuration. * * Since: 3.32 */ void ide_config_set_toolchain (IdeConfig *self, IdeToolchain *toolchain) { const gchar *toolchain_id = "default"; g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (!toolchain || IDE_IS_TOOLCHAIN (toolchain)); if (toolchain != NULL) toolchain_id = ide_toolchain_get_id (toolchain); ide_config_set_toolchain_id (self, toolchain_id); } /** * ide_config_get_environ: * @self: An #IdeConfig * * Gets the environment to use when spawning processes. * * Returns: (transfer full): An array of key=value environment variables. * * Since: 3.32 */ gchar ** ide_config_get_environ (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return ide_environment_get_environ (priv->environment); } const gchar * ide_config_getenv (IdeConfig *self, const gchar *key) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); g_return_val_if_fail (key != NULL, NULL); return ide_environment_getenv (priv->environment, key); } void ide_config_setenv (IdeConfig *self, const gchar *key, const gchar *value) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (key != NULL); ide_environment_setenv (priv->environment, key, value); } const gchar * ide_config_get_id (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->id; } const gchar * ide_config_get_prefix (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->prefix; } void ide_config_set_prefix (IdeConfig *self, const gchar *prefix) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (g_strcmp0 (prefix, priv->prefix) != 0) { g_free (priv->prefix); priv->prefix = g_strdup (prefix); priv->prefix_set = TRUE; g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PREFIX]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PREFIX_SET]); ide_config_set_dirty (self, TRUE); } } gint ide_config_get_parallelism (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), -1); if (priv->parallelism == -1) { g_autoptr(GSettings) settings = g_settings_new ("org.gnome.builder.build"); return g_settings_get_int (settings, "parallel"); } return priv->parallelism; } void ide_config_set_parallelism (IdeConfig *self, gint parallelism) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (parallelism >= -1); if (parallelism != priv->parallelism) { priv->parallelism = parallelism; g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PARALLELISM]); } } gboolean ide_config_get_debug (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), FALSE); return priv->debug; } void ide_config_set_debug (IdeConfig *self, gboolean debug) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); debug = !!debug; if (debug != priv->debug) { priv->debug = debug; g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEBUG]); ide_config_set_dirty (self, TRUE); } } const gchar * ide_config_get_display_name (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->display_name; } void ide_config_set_display_name (IdeConfig *self, const gchar *display_name) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (g_strcmp0 (display_name, priv->display_name) != 0) { g_free (priv->display_name); priv->display_name = g_strdup (display_name); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DISPLAY_NAME]); ide_config_emit_changed (self); } } gboolean ide_config_get_dirty (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), FALSE); return priv->dirty; } void ide_config_set_dirty (IdeConfig *self, gboolean dirty) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); IDE_ENTRY; g_return_if_fail (IDE_IS_CONFIG (self)); if (priv->block_changed) IDE_EXIT; dirty = !!dirty; if (dirty != priv->dirty) { priv->dirty = dirty; g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DIRTY]); } if (dirty) { /* * Emit the changed signal so that the configuration manager * can queue a writeback of the configuration. If we are * clearing the dirty bit, then we don't need to do this. */ priv->sequence++; IDE_TRACE_MSG ("configuration set dirty with sequence %u", priv->sequence); ide_config_emit_changed (self); } IDE_EXIT; } /** * ide_config_get_environment: * * Returns: (transfer none): An #IdeEnvironment. * * Since: 3.32 */ IdeEnvironment * ide_config_get_environment (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->environment; } void ide_config_set_environment (IdeConfig *self, IdeEnvironment *environment) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (!environment || IDE_IS_ENVIRONMENT (environment)); if (priv->environment != environment) { if (priv->environment != NULL) { g_signal_handlers_disconnect_by_func (priv->environment, G_CALLBACK (ide_config_environment_changed), self); g_clear_object (&priv->environment); } if (environment != NULL) { priv->environment = g_object_ref (environment); g_signal_connect_object (priv->environment, "changed", G_CALLBACK (ide_config_environment_changed), self, G_CONNECT_SWAPPED); } g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ENVIRON]); } } /** * ide_config_get_runtime_environment: * * Returns: (transfer none): An #IdeEnvironment. * * Since: 3.40 */ IdeEnvironment * ide_config_get_runtime_environment (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->runtime_environment; } void ide_config_set_runtime_environment (IdeConfig *self, IdeEnvironment *environment) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (!environment || IDE_IS_ENVIRONMENT (environment)); if (priv->runtime_environment != environment) { if (priv->runtime_environment != NULL) { g_signal_handlers_disconnect_by_func (priv->runtime_environment, G_CALLBACK (ide_config_runtime_environment_changed), self); g_clear_object (&priv->runtime_environment); } if (environment != NULL) { priv->runtime_environment = g_object_ref (environment); g_signal_connect_object (priv->runtime_environment, "changed", G_CALLBACK (ide_config_runtime_environment_changed), self, G_CONNECT_SWAPPED); } } } const gchar * ide_config_get_config_opts (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->config_opts; } void ide_config_set_config_opts (IdeConfig *self, const gchar *config_opts) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (g_strcmp0 (config_opts, priv->config_opts) != 0) { g_free (priv->config_opts); priv->config_opts = g_strdup (config_opts); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CONFIG_OPTS]); ide_config_set_dirty (self, TRUE); } } const gchar * const * ide_config_get_build_commands (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return (const gchar * const *)priv->build_commands; } void ide_config_set_build_commands (IdeConfig *self, const gchar * const *build_commands) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (priv->build_commands != (gchar **)build_commands) { g_strfreev (priv->build_commands); priv->build_commands = g_strdupv ((gchar **)build_commands); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_BUILD_COMMANDS]); } } const gchar * const * ide_config_get_post_install_commands (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return (const gchar * const *)priv->post_install_commands; } void ide_config_set_post_install_commands (IdeConfig *self, const gchar * const *post_install_commands) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (priv->post_install_commands != (gchar **)post_install_commands) { g_strfreev (priv->post_install_commands); priv->post_install_commands = g_strdupv ((gchar **)post_install_commands); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_POST_INSTALL_COMMANDS]); } } /** * ide_config_get_sequence: * @self: An #IdeConfig * * This returns a sequence number for the configuration. This is useful * for build systems that want to clear the "dirty" bit on the configuration * so that they need not bootstrap a second time. This should be done by * checking the sequence number before executing the bootstrap, and only * cleared if the sequence number matches after performing the bootstrap. * This indicates no changes have been made to the configuration in the * mean time. * * Returns: A monotonic sequence number. * * Since: 3.32 */ guint ide_config_get_sequence (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), 0); return priv->sequence; } static GValue * ide_config_reset_internal_value (IdeConfig *self, const gchar *key, GType type) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); GValue *v; g_assert (IDE_IS_CONFIG (self)); g_assert (key != NULL); g_assert (type != G_TYPE_INVALID); v = g_hash_table_lookup (priv->internal, key); if (v == NULL) { v = _value_new (type); g_hash_table_insert (priv->internal, g_strdup (key), v); } else { g_value_unset (v); g_value_init (v, type); } return v; } const gchar * ide_config_get_internal_string (IdeConfig *self, const gchar *key) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); const GValue *v; g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); g_return_val_if_fail (key != NULL, NULL); v = g_hash_table_lookup (priv->internal, key); if (v != NULL && G_VALUE_HOLDS_STRING (v)) return g_value_get_string (v); return NULL; } void ide_config_set_internal_string (IdeConfig *self, const gchar *key, const gchar *value) { GValue *v; g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (key != NULL); v = ide_config_reset_internal_value (self, key, G_TYPE_STRING); g_value_set_string (v, value); } const gchar * const * ide_config_get_internal_strv (IdeConfig *self, const gchar *key) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); const GValue *v; g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); g_return_val_if_fail (key != NULL, NULL); v = g_hash_table_lookup (priv->internal, key); if (v != NULL && G_VALUE_HOLDS (v, G_TYPE_STRV)) return g_value_get_boxed (v); return NULL; } void ide_config_set_internal_strv (IdeConfig *self, const gchar *key, const gchar * const *value) { GValue *v; g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (key != NULL); v = ide_config_reset_internal_value (self, key, G_TYPE_STRV); g_value_set_boxed (v, value); } gboolean ide_config_get_internal_boolean (IdeConfig *self, const gchar *key) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); const GValue *v; g_return_val_if_fail (IDE_IS_CONFIG (self), FALSE); g_return_val_if_fail (key != NULL, FALSE); v = g_hash_table_lookup (priv->internal, key); if (v != NULL && G_VALUE_HOLDS_BOOLEAN (v)) return g_value_get_boolean (v); return FALSE; } void ide_config_set_internal_boolean (IdeConfig *self, const gchar *key, gboolean value) { GValue *v; g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (key != NULL); v = ide_config_reset_internal_value (self, key, G_TYPE_BOOLEAN); g_value_set_boolean (v, value); } gint ide_config_get_internal_int (IdeConfig *self, const gchar *key) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); const GValue *v; g_return_val_if_fail (IDE_IS_CONFIG (self), -1); g_return_val_if_fail (key != NULL, -1); v = g_hash_table_lookup (priv->internal, key); if (v != NULL && G_VALUE_HOLDS_INT (v)) return g_value_get_int (v); return 0; } void ide_config_set_internal_int (IdeConfig *self, const gchar *key, gint value) { GValue *v; g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (key != NULL); v = ide_config_reset_internal_value (self, key, G_TYPE_INT); g_value_set_int (v, value); } gint64 ide_config_get_internal_int64 (IdeConfig *self, const gchar *key) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); const GValue *v; g_return_val_if_fail (IDE_IS_CONFIG (self), -1); g_return_val_if_fail (key != NULL, -1); v = g_hash_table_lookup (priv->internal, key); if (v != NULL && G_VALUE_HOLDS_INT64 (v)) return g_value_get_int64 (v); return 0; } void ide_config_set_internal_int64 (IdeConfig *self, const gchar *key, gint64 value) { GValue *v; g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (key != NULL); v = ide_config_reset_internal_value (self, key, G_TYPE_INT64); g_value_set_int64 (v, value); } /** * ide_config_get_internal_object: * @self: An #IdeConfig * @key: The key to get * * Gets the value associated with @key if it is a #GObject. * * Returns: (nullable) (transfer none) (type GObject.Object): a #GObject or %NULL. * * Since: 3.32 */ gpointer ide_config_get_internal_object (IdeConfig *self, const gchar *key) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); const GValue *v; g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); g_return_val_if_fail (key != NULL, NULL); v = g_hash_table_lookup (priv->internal, key); if (v != NULL && G_VALUE_HOLDS_OBJECT (v)) return g_value_get_object (v); return NULL; } /** * ide_config_set_internal_object: * @self: an #IdeConfig * @key: the key to set * @instance: (type GObject.Object) (nullable): a #GObject or %NULL * * Sets the value for @key to @instance. * * Since: 3.32 */ void ide_config_set_internal_object (IdeConfig *self, const gchar *key, gpointer instance) { GValue *v; GType type; g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (key != NULL); if (instance != NULL) type = G_OBJECT_TYPE (instance); else type = G_TYPE_OBJECT; v = ide_config_reset_internal_value (self, key, type); g_value_set_object (v, instance); } /** * ide_config_get_ready: * @self: An #IdeConfig * * Determines if the configuration is ready for use. * * Returns: %TRUE if the configuration is ready for use. * * Since: 3.32 */ gboolean ide_config_get_ready (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), FALSE); return priv->runtime_ready; } gboolean ide_config_supports_runtime (IdeConfig *self, IdeRuntime *runtime) { gboolean ret = TRUE; IDE_ENTRY; g_return_val_if_fail (IDE_IS_CONFIG (self), FALSE); g_return_val_if_fail (IDE_IS_RUNTIME (runtime), FALSE); if (IDE_CONFIG_GET_CLASS (self)->supports_runtime) ret = IDE_CONFIG_GET_CLASS (self)->supports_runtime (self, runtime); IDE_RETURN (ret); } /** * ide_config_get_run_opts: * @self: a #IdeConfig * * Gets the command line options to use when running the target application. * The result should be parsed with g_shell_parse_argv() to convert the run * options to an array suitable for use in argv. * * Returns: (transfer none) (nullable): A string containing the run options * or %NULL if none have been set. * * Since: 3.32 */ const gchar * ide_config_get_run_opts (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->run_opts; } /** * ide_config_set_run_opts: * @self: a #IdeConfig * @run_opts: (nullable): the run options for the target application * * Sets the run options to use when running the target application. * See ide_config_get_run_opts() for more information. * * Since: 3.32 */ void ide_config_set_run_opts (IdeConfig *self, const gchar *run_opts) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (g_strcmp0 (run_opts, priv->run_opts) != 0) { g_free (priv->run_opts); priv->run_opts = g_strdup (run_opts); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_RUN_OPTS]); ide_config_set_dirty (self, TRUE); } } const gchar * ide_config_get_prepend_path (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->prepend_path; } void ide_config_set_prepend_path (IdeConfig *self, const gchar *prepend_path) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (g_strcmp0 (priv->prepend_path, prepend_path) != 0) { g_free (priv->prepend_path); priv->prepend_path = g_strdup (prepend_path); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PREPEND_PATH]); } } const gchar * ide_config_get_append_path (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->append_path; } void ide_config_set_append_path (IdeConfig *self, const gchar *append_path) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); if (g_strcmp0 (priv->append_path, append_path) != 0) { g_free (priv->append_path); priv->append_path = g_strdup (append_path); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_APPEND_PATH]); } } void ide_config_apply_path (IdeConfig *self, IdeSubprocessLauncher *launcher) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (IDE_IS_SUBPROCESS_LAUNCHER (launcher)); if (priv->prepend_path != NULL) ide_subprocess_launcher_prepend_path (launcher, priv->prepend_path); if (priv->append_path != NULL) ide_subprocess_launcher_append_path (launcher, priv->append_path); } IdeBuildLocality ide_config_get_locality (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), 0); return priv->locality; } void ide_config_set_locality (IdeConfig *self, IdeBuildLocality locality) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (locality > 0); g_return_if_fail (locality <= IDE_BUILD_LOCALITY_DEFAULT); if (priv->locality != locality) { priv->locality = locality; g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LOCALITY]); } } /** * ide_config_get_build_commands_dir: * @self: a #IdeConfig * * Returns: (transfer none) (nullable): a #GFile or %NULL * * Since: 3.32 */ GFile * ide_config_get_build_commands_dir (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); return priv->build_commands_dir; } void ide_config_set_build_commands_dir (IdeConfig *self, GFile *build_commands_dir) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (!build_commands_dir || G_IS_FILE (build_commands_dir)); if (g_set_object (&priv->build_commands_dir, build_commands_dir)) g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_BUILD_COMMANDS_DIR]); } void _ide_config_attach (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); IdeRuntimeManager *runtime_manager; IdeContext *context; g_return_if_fail (IDE_IS_MAIN_THREAD ()); g_return_if_fail (IDE_IS_CONFIG (self)); g_return_if_fail (priv->has_attached == FALSE); priv->has_attached = TRUE; /* * We don't start monitoring changed events until we've gotten back * to the main loop (in case of threaded loaders) which happens from * the point where the configuration is added to the config manager. */ if (!(context = ide_object_get_context (IDE_OBJECT (self)))) { g_critical ("Attempt to register configuration without a context"); return; } runtime_manager = ide_runtime_manager_from_context (context); g_signal_connect_object (runtime_manager, "items-changed", G_CALLBACK (ide_config_runtime_manager_items_changed), self, G_CONNECT_SWAPPED); /* Update the runtime and potentially set prefix, but do not emit changed */ ide_config_block_changed (self); ide_config_runtime_manager_items_changed (self, 0, 0, 0, runtime_manager); ide_config_unblock_changed (self); } gboolean ide_config_get_prefix_set (IdeConfig *self) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_val_if_fail (IDE_IS_CONFIG (self), FALSE); return priv->prefix_set; } void ide_config_set_prefix_set (IdeConfig *self, gboolean prefix_set) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); prefix_set = !!prefix_set; if (prefix_set != priv->prefix_set) { priv->prefix_set = prefix_set; g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PREFIX_SET]); } } /** * ide_config_get_extensions: * @self: a #IdeConfig * * Gets the known SDK extensions that will be used when building the project. * Implementing this in your configuration backend allows plugins to know if * additional binaries will be available to the build system. * * Returns: (not nullable) (transfer full) (element-type Ide.Runtime): an array * of #IdeRuntime for the runtime extensions for the configuration. * * Since: 3.34 */ GPtrArray * ide_config_get_extensions (IdeConfig *self) { GPtrArray *ret = NULL; g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); if (IDE_CONFIG_GET_CLASS (self)->get_extensions) ret = IDE_CONFIG_GET_CLASS (self)->get_extensions (self); if (ret == NULL) ret = g_ptr_array_new (); return g_steal_pointer (&ret); } const gchar * const * ide_config_get_args_for_phase (IdeConfig *self, IdePipelinePhase phase) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); const gchar * const *args; g_return_val_if_fail (IDE_IS_CONFIG (self), NULL); args = g_hash_table_lookup (priv->pipeline_args, GINT_TO_POINTER (phase)); return args; } void ide_config_set_args_for_phase (IdeConfig *self, IdePipelinePhase phase, const gchar * const *args) { IdeConfigPrivate *priv = ide_config_get_instance_private (self); g_return_if_fail (IDE_IS_CONFIG (self)); g_hash_table_insert (priv->pipeline_args, GINT_TO_POINTER (phase), g_strdupv ((gchar **)args)); }