Commit dea27861 authored by Christian Hergert's avatar Christian Hergert
Browse files

build-system: move build helpers to IdeBuilder

Instead of having get_build_flags_async() and get_build_targets_async()
as part of the IdeBuildSystem, we've moved it to IdeBuilder. This allows
the build system to have an active configuration which is necessary for
many build systems to get accurate information.
parent 91c63c00
......@@ -42,6 +42,7 @@ libide_1_0_la_public_headers = \
buildsystem/ide-configuration.h \
buildsystem/ide-environment-variable.h \
buildsystem/ide-environment.h \
buildsystem/ide-simple-builder.h \
devices/ide-device-manager.h \
devices/ide-device-provider.h \
devices/ide-device.h \
......@@ -216,6 +217,7 @@ libide_1_0_la_public_sources = \
buildsystem/ide-configuration.c \
buildsystem/ide-environment-variable.c \
buildsystem/ide-environment.c \
buildsystem/ide-simple-builder.c \
devices/ide-device-manager.c \
devices/ide-device-provider.c \
devices/ide-device.c \
......
......@@ -18,23 +18,14 @@
#define G_LOG_DOMAIN "ide-build-system"
#include <glib/gi18n.h>
#include "ide-context.h"
#include "ide-object.h"
#include "buildsystem/ide-build-system.h"
#include "buildsystem/ide-builder.h"
#include "buildsystem/ide-configuration.h"
#include "devices/ide-device.h"
#include "devices/ide-device-manager.h"
#include "buildsystem/ide-configuration-manager.h"
#include "files/ide-file.h"
#include "runtimes/ide-runtime.h"
#include "runtimes/ide-runtime-manager.h"
typedef struct
{
GFile *project_file;
} IdeBuildSystemPrivate;
G_DEFINE_INTERFACE (IdeBuildSystem, ide_build_system, IDE_TYPE_OBJECT)
......@@ -42,10 +33,10 @@ enum {
PROP_0,
PROP_CONTEXT,
PROP_PROJECT_FILE,
LAST_PROP
N_PROPS
};
static GParamSpec *properties [LAST_PROP];
static GParamSpec *properties [N_PROPS];
gint
ide_build_system_get_priority (IdeBuildSystem *self)
......@@ -62,55 +53,6 @@ ide_build_system_get_priority (IdeBuildSystem *self)
return 0;
}
/**
* ide_build_system_get_build_flags_async:
*
* Asynchronously requests the build flags for a file. For autotools and C based projects, this
* would be similar to the $CFLAGS variable and is suitable for generating warnings and errors
* with clang.
*/
void
ide_build_system_get_build_flags_async (IdeBuildSystem *self,
IdeFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
g_return_if_fail (IDE_IS_BUILD_SYSTEM (self));
g_return_if_fail (IDE_IS_FILE (file));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
if (IDE_BUILD_SYSTEM_GET_IFACE (self)->get_build_flags_async)
return IDE_BUILD_SYSTEM_GET_IFACE (self)->get_build_flags_async (self, file, cancellable,
callback, user_data);
task = g_task_new (self, cancellable, callback, user_data);
g_task_return_pointer (task, NULL, NULL);
}
/**
* ide_build_system_get_build_flags_finish:
*
* Completes an asynchronous request to get the build flags for a file.
*
* Returns: (array zero-terminated=1) (transfer full): An array of strings
* containing the build flags, or %NULL upon failure and @error is set.
*/
gchar **
ide_build_system_get_build_flags_finish (IdeBuildSystem *self,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (IDE_IS_BUILD_SYSTEM (self), NULL);
if (IDE_BUILD_SYSTEM_GET_IFACE (self)->get_build_flags_finish)
return IDE_BUILD_SYSTEM_GET_IFACE (self)->get_build_flags_finish (self, result, error);
return g_new0 (gchar*, 1);
}
static IdeBuilder *
ide_build_system_real_get_builder (IdeBuildSystem *self,
IdeConfiguration *configuration,
......@@ -122,49 +64,16 @@ ide_build_system_real_get_builder (IdeBuildSystem *self,
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
_("%s() is not supported on %s build system."),
G_STRFUNC, g_type_name (G_TYPE_FROM_INSTANCE (self)));
"%s() is not supported on %s build system.",
G_STRFUNC, G_OBJECT_TYPE_NAME (self));
return NULL;
}
static void
ide_build_system_real_get_build_targets_async (IdeBuildSystem *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
g_assert (IDE_IS_BUILD_SYSTEM (self));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ide_build_system_real_get_build_targets_async);
g_task_return_pointer (task, g_ptr_array_new (), (GDestroyNotify)g_ptr_array_unref);
}
static GPtrArray *
ide_build_system_real_get_build_targets_finish (IdeBuildSystem *self,
GAsyncResult *result,
GError **error)
{
GTask *task = (GTask *)result;
g_assert (IDE_IS_BUILD_SYSTEM (self));
g_assert (G_IS_TASK (task));
g_assert (g_task_is_valid (task, self));
g_assert (g_task_get_source_tag (task) == ide_build_system_real_get_build_targets_async);
return g_task_propagate_pointer (task, error);
}
static void
ide_build_system_default_init (IdeBuildSystemInterface *iface)
{
iface->get_builder = ide_build_system_real_get_builder;
iface->get_build_targets_async = ide_build_system_real_get_build_targets_async;
iface->get_build_targets_finish = ide_build_system_real_get_build_targets_finish;
properties [PROP_PROJECT_FILE] =
g_param_spec_object ("project-file",
......@@ -269,10 +178,127 @@ ide_build_system_get_builder (IdeBuildSystem *system,
IdeConfiguration *configuration,
GError **error)
{
IdeBuilder *ret;
g_return_val_if_fail (IDE_IS_BUILD_SYSTEM (system), NULL);
g_return_val_if_fail (IDE_IS_CONFIGURATION (configuration), NULL);
return IDE_BUILD_SYSTEM_GET_IFACE (system)->get_builder (system, configuration, error);
ret = IDE_BUILD_SYSTEM_GET_IFACE (system)->get_builder (system, configuration, error);
if (ret != NULL)
{
IdeContext *context;
context = ide_object_get_context (IDE_OBJECT (system));
ide_context_hold_for_object (context, ret);
}
return ret;
}
static IdeBuilder *
get_default_builder (IdeBuildSystem *self,
GError **error)
{
IdeConfigurationManager *config_manager;
IdeConfiguration *config;
IdeContext *context;
g_assert (IDE_IS_BUILD_SYSTEM (self));
context = ide_object_get_context (IDE_OBJECT (self));
g_assert (IDE_IS_CONTEXT (context));
config_manager = ide_context_get_configuration_manager (context);
g_assert (IDE_IS_CONFIGURATION_MANAGER (config_manager));
config = ide_configuration_manager_get_current (config_manager);
g_assert (IDE_IS_CONFIGURATION (config));
return ide_build_system_get_builder (IDE_BUILD_SYSTEM (self), config, error);
}
static void
ide_build_system_get_build_flags_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
IdeBuilder *builder = (IdeBuilder *)object;
g_autoptr(GTask) task = user_data;
g_autoptr(GError) error = NULL;
g_auto(GStrv) flags = NULL;
g_assert (IDE_IS_BUILDER (builder));
if (NULL == (flags = ide_builder_get_build_flags_finish (builder, result, &error)))
g_task_return_error (task, g_steal_pointer (&error));
else
g_task_return_pointer (task, g_steal_pointer (&flags), (GDestroyNotify)g_strfreev);
}
void
ide_build_system_get_build_flags_async (IdeBuildSystem *self,
IdeFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
g_autoptr(IdeBuilder) builder = NULL;
g_autoptr(GError) error = NULL;
g_return_if_fail (IDE_IS_BUILD_SYSTEM (self));
g_return_if_fail (IDE_IS_FILE (file));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ide_build_system_get_build_flags_async);
if (NULL == (builder = get_default_builder (self, &error)))
{
g_task_return_error (task, g_steal_pointer (&error));
return;
}
ide_builder_get_build_flags_async (builder,
file,
cancellable,
ide_build_system_get_build_flags_cb,
g_steal_pointer (&task));
}
/**
* ide_build_system_get_build_flags_finish:
*
* Returns: (transfer full):
*/
gchar **
ide_build_system_get_build_flags_finish (IdeBuildSystem *self,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (IDE_IS_BUILD_SYSTEM (self), NULL);
g_return_val_if_fail (G_IS_TASK (result), NULL);
return g_task_propagate_pointer (G_TASK (result), error);
}
static void
ide_build_system_get_build_targets_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
IdeBuilder *builder = (IdeBuilder *)object;
g_autoptr(GTask) task = user_data;
g_autoptr(GPtrArray) targets = NULL;
g_autoptr(GError) error = NULL;
g_assert (IDE_IS_BUILDER (builder));
if (NULL == (targets = ide_builder_get_build_targets_finish (builder, result, &error)))
g_task_return_error (task, g_steal_pointer (&error));
else
g_task_return_pointer (task, g_steal_pointer (&targets), (GDestroyNotify)g_ptr_array_unref);
}
void
......@@ -281,17 +307,33 @@ ide_build_system_get_build_targets_async (IdeBuildSystem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
g_autoptr(IdeBuilder) builder = NULL;
g_autoptr(GError) error = NULL;
g_return_if_fail (IDE_IS_BUILD_SYSTEM (self));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
IDE_BUILD_SYSTEM_GET_IFACE (self)->get_build_targets_async (self, cancellable, callback, user_data);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ide_build_system_get_build_targets_async);
if (NULL == (builder = get_default_builder (self, &error)))
{
g_task_return_error (task, g_steal_pointer (&error));
return;
}
ide_builder_get_build_targets_async (builder,
cancellable,
ide_build_system_get_build_targets_cb,
g_steal_pointer (&task));
}
/**
* ide_build_system_get_build_targets_finish:
*
* Returns: (transfer container) (element-type Ide.BuildTarget): An array of build targets
* or %NULL upon failure and @error is set.
* Returns: (transfer container) (element-type Ide.BuildTarget): An array
* of #IdeBuildTarget or %NULL and @error is set.
*/
GPtrArray *
ide_build_system_get_build_targets_finish (IdeBuildSystem *self,
......@@ -299,7 +341,7 @@ ide_build_system_get_build_targets_finish (IdeBuildSystem *self,
GError **error)
{
g_return_val_if_fail (IDE_IS_BUILD_SYSTEM (self), NULL);
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
g_return_val_if_fail (G_IS_TASK (result), NULL);
return IDE_BUILD_SYSTEM_GET_IFACE (self)->get_build_targets_finish (self, result, error);
return g_task_propagate_pointer (G_TASK (result), error);
}
......@@ -33,36 +33,13 @@ struct _IdeBuildSystemInterface
{
GTypeInterface parent_iface;
gint (*get_priority) (IdeBuildSystem *system);
IdeBuilder *(*get_builder) (IdeBuildSystem *system,
IdeConfiguration *configuration,
GError **error);
void (*get_build_flags_async) (IdeBuildSystem *self,
IdeFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gchar **(*get_build_flags_finish) (IdeBuildSystem *self,
GAsyncResult *result,
GError **error);
void (*get_build_targets_async) (IdeBuildSystem *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GPtrArray *(*get_build_targets_finish) (IdeBuildSystem *self,
GAsyncResult *result,
GError **error);
gint (*get_priority) (IdeBuildSystem *system);
IdeBuilder *(*get_builder) (IdeBuildSystem *system,
IdeConfiguration *configuration,
GError **error);
};
gint ide_build_system_get_priority (IdeBuildSystem *self);
void ide_build_system_get_build_flags_async (IdeBuildSystem *self,
IdeFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gchar **ide_build_system_get_build_flags_finish (IdeBuildSystem *self,
GAsyncResult *result,
GError **error);
void ide_build_system_new_async (IdeContext *context,
GFile *project_file,
GCancellable *cancellable,
......@@ -73,6 +50,20 @@ IdeBuildSystem *ide_build_system_new_finish (GAsyncResult
IdeBuilder *ide_build_system_get_builder (IdeBuildSystem *system,
IdeConfiguration *configuration,
GError **error);
/*
* The following is convenience API for the legacy design to allow
* querying using the current IdeConfiguration.
*/
void ide_build_system_get_build_flags_async (IdeBuildSystem *self,
IdeFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gchar **ide_build_system_get_build_flags_finish (IdeBuildSystem *self,
GAsyncResult *result,
GError **error);
void ide_build_system_get_build_targets_async (IdeBuildSystem *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
......
......@@ -16,11 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "ide-builder"
#include <glib/gi18n.h>
#include "ide-build-result.h"
#include "ide-builder.h"
#include "ide-configuration.h"
#include "ide-context.h"
#include "ide-debug.h"
#include "buildsystem/ide-build-result.h"
#include "buildsystem/ide-builder.h"
#include "buildsystem/ide-configuration.h"
typedef struct
{
......@@ -63,9 +68,18 @@ ide_builder_set_configuration (IdeBuilder *self,
g_assert (IDE_IS_BUILDER (self));
g_assert (!configuration || IDE_IS_CONFIGURATION (configuration));
if (g_set_object (&priv->configuration, configuration))
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CONFIGURATION]);
g_assert (priv->configuration == NULL);
/* Make a copy of the configuration so that we do not need to worry
* about the user modifying the configuration while our bulid is
* active (and may be running in another thread).
*
* When the dirty bit is cleared from a successful build, the
* configuration will propagate that to the original build
* configuration.
*/
priv->configuration = ide_configuration_snapshot (configuration);
}
static void
......@@ -83,6 +97,8 @@ ide_builder_real_build_async (IdeBuilder *self,
g_assert (!result || *result == NULL);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ide_builder_real_build_async);
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
......@@ -101,6 +117,80 @@ ide_builder_real_build_finish (IdeBuilder *self,
return g_task_propagate_pointer (G_TASK (result), error);
}
static void
ide_builder_real_get_build_targets_async (IdeBuilder *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_task_report_new_error (self,
callback,
user_data,
ide_builder_real_get_build_targets_async,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"build targets not supported for %s",
G_OBJECT_TYPE_NAME (self));
}
static GPtrArray *
ide_builder_real_get_build_targets_finish (IdeBuilder *self,
GAsyncResult *result,
GError **error)
{
return g_task_propagate_pointer (G_TASK (result), error);
}
static void
ide_builder_real_get_build_flags_async (IdeBuilder *self,
IdeFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_task_report_new_error (self,
callback,
user_data,
ide_builder_real_get_build_flags_async,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"build flags not supported for %s",
G_OBJECT_TYPE_NAME (self));
}
static gchar **
ide_builder_real_get_build_flags_finish (IdeBuilder *self,
GAsyncResult *result,
GError **error)
{
return g_task_propagate_pointer (G_TASK (result), error);
}
static void
ide_builder_real_install_async (IdeBuilder *self,
IdeBuildResult **build_result,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_task_report_new_error (self,
callback,
user_data,
ide_builder_real_install_async,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"install not supported for %s",
G_OBJECT_TYPE_NAME (self));
}
static IdeBuildResult *
ide_builder_real_install_finish (IdeBuilder *self,
GAsyncResult *result,
GError **error)
{
return g_task_propagate_pointer (G_TASK (result), error);
}
/**
* ide_builder_build_async:
* @self: An #IdeBuilder
......@@ -117,12 +207,12 @@ ide_builder_real_build_finish (IdeBuilder *self,
* See ide_builder_build_finish() to complete the request.
*/
void
ide_builder_build_async (IdeBuilder *builder,
IdeBuilderBuildFlags flags,
IdeBuildResult **result,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
ide_builder_build_async (IdeBuilder *builder,
IdeBuilderBuildFlags flags,
IdeBuildResult **result,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_return_if_fail (IDE_IS_BUILDER (builder));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
......@@ -195,6 +285,19 @@ ide_builder_set_property (GObject *object,
}
}
static void
ide_builder_constructed (GObject *object)
{
G_OBJECT_CLASS (ide_builder_parent_class)->constructed (object);
#ifdef IDE_ENABLE_TRACE
{
IdeContext *context = ide_object_get_context (IDE_OBJECT (object));
g_assert (IDE_IS_CONTEXT (context));
}
#endif
}
static void
ide_builder_finalize (GObject *object)
{
......@@ -211,12 +314,19 @@ ide_builder_class_init (IdeBuilderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = ide_builder_constructed;
object_class->finalize = ide_builder_finalize;
object_class->get_property = ide_builder_get_property;
object_class->set_property = ide_builder_set_property;
klass->build_async = ide_builder_real_build_async;
klass->build_finish = ide_builder_real_build_finish;
klass->install_async = ide_builder_real_install_async;
klass->install_finish = ide_builder_real_install_finish;
klass->get_build_flags_async = ide_builder_real_get_build_flags_async;
klass->get_build_flags_finish = ide_builder_real_get_build_flags_finish;
klass->get_build_targets_async = ide_builder_real_get_build_targets_async;
klass->get_build_targets_finish = ide_builder_real_get_build_targets_finish;
properties [PROP_CONFIGURATION] =
g_param_spec_object ("configuration",
......@@ -284,3 +394,72 @@ ide_builder_install_finish (IdeBuilder *self,
return ret;
}
void
ide_builder_get_build_targets_async (IdeBuilder *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_return_if_fail (IDE_IS_BUILDER (self));
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
IDE_BUILDER_GET_CLASS (self)->get_build_targets_async (self, cancellable, callback, user_data);
}
/**
* ide_builder_get_build_targets_finish:
* @self: An #IdeBuilder
* @result: A #GAsyncResult provided to the async callback
* @error: A location for a #GError or %NULL
*
* Completes an async operation to ide_builder_get_build_targets_async().
*
* Returns: (transfer container) (element-type Ide.BuildTarget): A #GPtrArray of the
* build targets or %NULL upon failure and @error is set.
*/
GPtrArray *
ide_builder_get_build_targets_finish (IdeBuilder *self,