* plugins/cvs-plugin/Makefile.am,
[anjuta-git-plugin.git] / plugins / build-basic-autotools / build-basic-autotools.c
blob4a561ec20a4ca9e9d6b8a498bdf0a138fd815f1a
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 build-basic-autotools.c
4 Copyright (C) 2000 Naba Kumar
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <config.h>
22 #include <ctype.h>
24 #include <libgnomevfs/gnome-vfs-utils.h>
25 #include <libanjuta/anjuta-shell.h>
26 #include <libanjuta/anjuta-launcher.h>
27 #include <libanjuta/anjuta-utils.h>
28 #include <libanjuta/anjuta-debug.h>
29 #include <libanjuta/interfaces/ianjuta-file.h>
30 #include <libanjuta/interfaces/ianjuta-file-loader.h>
31 #include <libanjuta/interfaces/ianjuta-buildable.h>
32 #include <libanjuta/interfaces/ianjuta-builder.h>
33 #include <libanjuta/interfaces/ianjuta-message-manager.h>
34 #include <libanjuta/interfaces/ianjuta-document-manager.h>
35 #include <libanjuta/interfaces/ianjuta-file-savable.h>
36 #include <libanjuta/interfaces/ianjuta-indicable.h>
37 #include <libanjuta/interfaces/ianjuta-preferences.h>
39 #include "build-basic-autotools.h"
40 #include "build-options.h"
41 #include "executer.h"
43 #include <sys/wait.h>
45 #define ICON_FILE "anjuta-build-basic-autotools-plugin-48.png"
46 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-build-basic-autotools-plugin.ui"
47 #define MAX_BUILD_PANES 3
48 #define PREF_INDICATORS_AUTOMATIC "indicators.automatic"
49 #define PREF_INSTALL_ROOT "build.install.root"
50 #define PREF_INSTALL_ROOT_COMMAND "build.install.root.command"
51 #define PREF_USE_SB "build.use_scratchbox"
52 #define PREF_SB_PATH "build.scratchbox.path"
54 #define CHECK_BUTTON "preferences_toggle:bool:0:0:build.install.root"
55 #define ENTRY "preferences_entry:text:sudo:0:build.install.root.command"
56 #define SB_CHECK "preferences_toggle:bool:0:0:build.use_scratchbox"
57 #define SB_ENTRY "preferences_entry:text:/scratchbox:0:build.scratchbox.path"
59 #define DEFAULT_COMMAND_COMPILE "make"
60 #define DEFAULT_COMMAND_BUILD "make"
61 #define DEFAULT_COMMAND_IS_BUILT "make -q"
62 #define DEFAULT_COMMAND_BUILD_TARBALL "make dist"
63 #define DEFAULT_COMMAND_INSTALL "make install"
64 #define DEFAULT_COMMAND_CONFIGURE "./configure"
65 #define DEFAULT_COMMAND_GENERATE "./autogen.sh"
66 #define DEFAULT_COMMAND_CLEAN "make clean"
68 #define CHOOSE_COMMAND(plugin,command) \
69 ((plugin->commands[(IANJUTA_BUILDABLE_COMMAND_##command)]) ? \
70 (plugin->commands[(IANJUTA_BUILDABLE_COMMAND_##command)]) \
71 : \
72 (DEFAULT_COMMAND_##command))
74 static gpointer parent_class;
76 typedef struct
78 gchar *pattern;
79 int options;
80 gchar *replace;
81 GRegex *regex;
82 } BuildPattern;
84 typedef struct
86 gchar *filename;
87 gint line;
88 IAnjutaIndicableIndicator indicator;
89 } BuildIndicatorLocation;
91 /* Command processing */
92 typedef struct
94 AnjutaPlugin *plugin;
96 AnjutaLauncher *launcher;
97 gchar *command;
98 IAnjutaBuilderCallback callback;
99 gpointer user_data;
101 IAnjutaMessageView *message_view;
102 GHashTable *build_dir_stack;
104 /* Indicator locations */
105 GSList *locations;
107 /* Editors in which indicators have been updated */
108 GHashTable *indicators_updated_editors;
109 } BuildContext;
111 /* Declarations */
112 static void update_project_ui (BasicAutotoolsPlugin *bb_plugin);
113 static gboolean directory_has_file (const gchar *dirname, const gchar *filename);
115 static GList *patterns_list = NULL;
117 /* Allow installation as root (#321455) */
118 static void on_root_check_toggled(GtkWidget* toggle_button, GtkWidget* entry)
120 gtk_widget_set_sensitive(entry,
121 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
124 static void on_sb_check_toggled(GtkWidget* toggle_button, GtkWidget* entry)
126 gtk_widget_set_sensitive(entry,
127 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
130 static gchar*
131 get_root_install_command(BasicAutotoolsPlugin *bplugin)
133 AnjutaPlugin* plugin = ANJUTA_PLUGIN(bplugin);
134 AnjutaPreferences* prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
135 if (anjuta_preferences_get_int (prefs , PREF_INSTALL_ROOT))
137 gchar* command = anjuta_preferences_get(prefs, PREF_INSTALL_ROOT_COMMAND);
138 if (command != NULL)
139 return command;
140 else
141 return g_strdup("");
143 else
144 return g_strdup("");
147 /* Indicator locations reported by the build */
149 static BuildIndicatorLocation*
150 build_indicator_location_new (const gchar *filename, gint line,
151 IAnjutaIndicableIndicator indicator)
153 BuildIndicatorLocation *loc = g_new0 (BuildIndicatorLocation, 1);
154 loc->filename = g_strdup (filename);
155 loc->line = line;
156 loc->indicator = indicator;
157 return loc;
160 static void
161 build_indicator_location_set (BuildIndicatorLocation *loc,
162 IAnjutaEditor *editor,
163 const gchar *editor_filename)
165 IAnjutaIterable *line_start, *line_end;
167 if (editor && editor_filename &&
168 IANJUTA_IS_INDICABLE (editor) &&
169 IANJUTA_IS_EDITOR (editor) &&
170 strcmp (editor_filename, loc->filename) == 0)
172 DEBUG_PRINT ("loc line: %d", loc->line);
174 line_start = ianjuta_editor_get_line_begin_position (editor,
175 loc->line, NULL);
177 line_end = ianjuta_editor_get_line_end_position (editor,
178 loc->line, NULL);
179 ianjuta_indicable_set (IANJUTA_INDICABLE (editor),
180 line_start, line_end, loc->indicator,
181 NULL);
183 g_object_unref (line_start);
184 g_object_unref (line_end);
188 static void
189 build_indicator_location_free (BuildIndicatorLocation *loc)
191 g_free (loc->filename);
192 g_free (loc);
195 /* Build context */
197 static void
198 build_context_stack_destroy (gpointer value)
200 GSList *slist = (GSList *)value;
201 if (slist)
203 g_slist_foreach (slist, (GFunc)g_free, NULL);
204 g_slist_free (slist);
208 static void
209 build_context_push_dir (BuildContext *context, const gchar *key,
210 const gchar *dir)
212 GSList *dir_stack;
214 if (context->build_dir_stack == NULL)
216 context->build_dir_stack =
217 g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
218 build_context_stack_destroy);
220 dir_stack = g_hash_table_lookup (context->build_dir_stack, key);
221 if (dir_stack)
222 g_hash_table_steal (context->build_dir_stack, key);
224 dir_stack = g_slist_prepend (dir_stack, g_strdup (dir));
225 g_hash_table_insert (context->build_dir_stack, (gpointer)key, dir_stack);
228 static void
229 build_context_pop_dir (BuildContext *context, const gchar *key,
230 const gchar *dir)
232 GSList *dir_stack;
233 gchar *top_dir;
235 if (context->build_dir_stack == NULL)
236 return;
237 dir_stack = g_hash_table_lookup (context->build_dir_stack, key);
238 if (dir_stack == NULL)
239 return;
241 g_hash_table_steal (context->build_dir_stack, key);
242 top_dir = dir_stack->data;
243 dir_stack = g_slist_remove (dir_stack, top_dir);
245 if (strcmp (top_dir, dir) != 0)
247 DEBUG_PRINT("Directory stack misaligned!!");
249 g_free (top_dir);
250 if (dir_stack)
251 g_hash_table_insert (context->build_dir_stack, (gpointer)key, dir_stack);
254 static const gchar *
255 build_context_get_dir (BuildContext *context, const gchar *key)
257 GSList *dir_stack;
259 if (context->build_dir_stack == NULL)
260 return NULL;
261 dir_stack = g_hash_table_lookup (context->build_dir_stack, key);
262 if (dir_stack == NULL)
263 return NULL;
265 return dir_stack->data;
268 static gboolean
269 build_context_destroy_command (BuildContext *context)
271 if (context->callback)
273 GError *err;
275 /* Emit command-finished signal abort */
276 err = g_error_new_literal (ianjuta_builder_error_quark (),
277 IANJUTA_BUILDER_ABORTED,
278 _("Command aborted"));
279 context->callback (G_OBJECT (context->plugin), err, context->user_data);
280 g_error_free (err);
281 context->callback = NULL;
284 if (context->launcher)
286 g_object_unref (context->launcher);
287 context->launcher = NULL;
290 g_free (context->command);
291 context->command = NULL;
293 /* Empty context, remove from pool */
294 if (context->message_view == NULL)
296 ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool =
297 g_list_remove (ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool,
298 context);
299 g_free (context);
301 return TRUE;
303 else
305 return FALSE;
309 static gboolean
310 build_context_destroy_view (BuildContext *context)
312 if (context->message_view)
314 gtk_widget_destroy (GTK_WIDGET (context->message_view));
315 context->message_view = NULL;
318 if (context->build_dir_stack)
320 g_hash_table_destroy (context->build_dir_stack);
321 context->build_dir_stack = NULL;
323 if (context->indicators_updated_editors)
325 g_hash_table_destroy (context->indicators_updated_editors);
326 context->indicators_updated_editors = NULL;
329 g_slist_foreach (context->locations, (GFunc) build_indicator_location_free,
330 NULL);
331 g_slist_free (context->locations);
332 context->locations = NULL;
334 /* Empty context, remove from pool */
335 if (context->launcher == NULL)
337 ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool =
338 g_list_remove (ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool,
339 context);
340 g_free (context);
342 return TRUE;
344 else
346 return FALSE;
350 static void
351 build_context_destroy (BuildContext *context)
353 if (build_context_destroy_command (context))
355 build_context_destroy_view (context);
359 static void
360 build_context_reset (BuildContext *context)
362 /* Reset context */
363 g_free (context->command);
364 context->command = NULL;
366 ianjuta_message_view_clear (context->message_view, NULL);
368 if (context->build_dir_stack)
369 g_hash_table_destroy (context->build_dir_stack);
370 context->build_dir_stack = NULL;
372 g_slist_foreach (context->locations,
373 (GFunc) build_indicator_location_free, NULL);
374 g_slist_free (context->locations);
375 context->locations = NULL;
378 static void
379 build_regex_load ()
381 FILE *fp;
383 if (patterns_list)
384 return;
386 fp = fopen (PACKAGE_DATA_DIR"/build/automake-c.filters", "r");
387 if (fp == NULL)
389 DEBUG_PRINT ("Failed to load filters: %s",
390 PACKAGE_DATA_DIR"/build/automake-c.filters");
391 return;
393 while (!feof (fp) && !ferror (fp))
395 char buffer[1024];
396 gchar **tokens;
397 BuildPattern *pattern;
399 fgets (buffer, 1024, fp);
400 if (ferror (fp))
401 break;
402 tokens = g_strsplit (buffer, "|||", 3);
404 if (!tokens[0] || !tokens[1])
406 DEBUG_PRINT ("Cannot parse regex: %s", buffer);
407 g_strfreev (tokens);
408 continue;
410 pattern = g_new0 (BuildPattern, 1);
411 pattern->pattern = g_strdup (tokens[0]);
412 pattern->replace = g_strdup (tokens[1]);
413 if (tokens[2])
414 pattern->options = atoi (tokens[2]);
415 g_strfreev (tokens);
417 patterns_list = g_list_prepend (patterns_list, pattern);
419 patterns_list = g_list_reverse (patterns_list);
422 static void
423 build_regex_init ()
425 GList *node;
426 GError *error = NULL;
428 build_regex_load ();
429 if (!patterns_list)
430 return;
432 if (((BuildPattern*)(patterns_list->data))->regex)
433 return;
435 node = patterns_list;
436 while (node)
438 BuildPattern *pattern;
440 pattern = node->data;
441 pattern->regex =
442 g_regex_new(
443 pattern->pattern,
444 pattern->options,
446 &error); /* for error message */
447 if (error != NULL) {
448 DEBUG_PRINT ("GRegex compilation failed: pattern \"%s\": error %s",
449 pattern->pattern, error->message);
450 g_error_free (error);
452 node = g_list_next (node);
456 /* Regex processing */
457 static gchar*
458 build_get_summary (const gchar *details, BuildPattern* bp)
460 gboolean matched;
461 GMatchInfo *match_info;
462 const gchar *iter;
463 GString *ret;
464 gchar *final;
466 if (!bp || !bp->regex)
467 return NULL;
469 matched = g_regex_match(
470 bp->regex, /* result of g_regex_new() */
471 details, /* the subject string */
473 &match_info);
475 if (!matched)
476 return NULL;
478 ret = g_string_new ("");
479 iter = bp->replace;
480 while (*iter != '\0')
482 if (*iter == '\\' && isdigit(*(iter + 1)))
484 char temp[2] = {0, 0};
485 gint start_pos, end_pos;
487 temp[0] = *(iter + 1);
488 int idx = atoi (temp);
490 g_match_info_fetch_pos (match_info, idx, &start_pos, &end_pos);
492 ret = g_string_append_len (ret, details + start_pos,
493 end_pos - start_pos);
494 iter += 2;
496 else
498 const gchar *start;
499 const gchar *end;
501 start = iter;
502 iter = g_utf8_next_char (iter);
503 end = iter;
505 ret = g_string_append_len (ret, start, end - start);
508 g_match_info_free (match_info);
510 final = g_string_free (ret, FALSE);
511 if (strlen (final) <= 0) {
512 g_free (final);
513 final = NULL;
515 return final;
518 static void
519 on_build_mesg_arrived (AnjutaLauncher *launcher,
520 AnjutaLauncherOutputType output_type,
521 const gchar * mesg, gpointer user_data)
523 BuildContext *context = (BuildContext*)user_data;
524 /* Message view could have been destroyed */
525 if (context->message_view)
526 ianjuta_message_view_buffer_append (context->message_view, mesg, NULL);
529 static gboolean
530 parse_error_line (const gchar * line, gchar ** filename, int *lineno)
532 gint i = 0;
533 gint j = 0;
534 gint k = 0;
535 gchar *dummy;
537 while (line[i++] != ':')
539 if (i >= strlen (line) || i >= 512 || line[i - 1] == ' ')
541 goto down;
544 if (isdigit (line[i]))
546 j = i;
547 while (isdigit (line[i++])) ;
548 dummy = g_strndup (&line[j], i - j - 1);
549 *lineno = atoi (dummy);
550 if (dummy)
551 g_free (dummy);
552 dummy = g_strndup (line, j - 1);
553 *filename = g_strdup (g_strstrip (dummy));
554 if (dummy)
555 g_free (dummy);
556 return TRUE;
559 down:
560 i = strlen (line) - 1;
561 while (isspace (line[i]) == FALSE)
563 i--;
564 if (i < 0)
566 *filename = NULL;
567 *lineno = 0;
568 return FALSE;
571 k = i++;
572 while (line[i++] != ':')
574 if (i >= strlen (line) || i >= 512 || line[i - 1] == ' ')
576 *filename = NULL;
577 *lineno = 0;
578 return FALSE;
581 if (isdigit (line[i]))
583 j = i;
584 while (isdigit (line[i++])) ;
585 dummy = g_strndup (&line[j], i - j - 1);
586 *lineno = atoi (dummy);
587 if (dummy)
588 g_free (dummy);
589 dummy = g_strndup (&line[k], j - k - 1);
590 *filename = g_strdup (g_strstrip (dummy));
591 if (dummy)
592 g_free (dummy);
593 return TRUE;
595 *lineno = 0;
596 *filename = NULL;
597 return FALSE;
600 static gchar* get_real_directory(BuildContext* context, gchar* dir)
602 AnjutaPreferences* prefs = anjuta_shell_get_preferences (context->plugin->shell, NULL);
603 gchar* real_dir = dir;
604 if (anjuta_preferences_get_int (prefs, PREF_USE_SB))
606 gchar* username = getenv("USERNAME");
607 if (!username || strlen(username) == 0)
608 username = getenv("USER");
609 if (!username || strlen(username) == 0)
610 return real_dir;
612 const gchar* sb_dir = anjuta_preferences_get(prefs, PREF_SB_PATH);
613 real_dir = g_strdup_printf("%s/users/%s%s", sb_dir, username, dir);
614 g_free(dir);
615 DEBUG_PRINT("sb_dir = %s", real_dir);
617 return real_dir;
620 static void
621 on_build_mesg_format (IAnjutaMessageView *view, const gchar *one_line,
622 BuildContext *context)
624 gchar *dummy_fn, *line;
625 gint dummy_int;
626 IAnjutaMessageViewType type;
627 GList *node;
628 gchar* dir = g_new0(gchar, 2048);
629 gchar *summary = NULL;
630 gchar *freeptr = NULL;
631 BasicAutotoolsPlugin *p = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin);
633 g_return_if_fail (one_line != NULL);
635 /* The translations should match that of 'make' program */
636 if ((sscanf (one_line, _("make[%d]: Entering directory '%s'"), &dummy_int, dir) == 2) ||
637 (sscanf (one_line, _("make: Entering directory '%s'"), dir) == 1) ||
638 (sscanf (one_line, _("make[%d]: Entering directory `%s'"), &dummy_int, dir) == 2) ||
639 (sscanf (one_line, _("make: Entering directory `%s'"), dir) == 1) ||
640 (sscanf (one_line, "make[%d]: Entering directory '%s'", &dummy_int, dir) == 2) ||
641 (sscanf (one_line, "make: Entering directory '%s'", dir) == 1) ||
642 (sscanf (one_line, "make[%d]: Entering directory `%s'", &dummy_int, dir) == 2) ||
643 (sscanf (one_line, "make: Entering directory `%s'", dir) == 1))
645 gchar* summary;
646 /* FIXME: Hack to remove the last ' */
647 gchar *idx = strchr (dir, '\'');
648 if (idx != NULL)
650 *idx = '\0';
652 dir = get_real_directory(context, dir);
653 build_context_push_dir (context, "default", dir);
654 summary = g_strdup_printf(_("Entering: %s"), dir);
655 ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_INFO,
656 summary, one_line, NULL);
657 g_free(summary);
659 return;
661 /* Translation for the following should match that of 'make' program */
662 if ((sscanf (one_line, _("make[%d]: Leaving directory '%s'"), &dummy_int, dir) == 2) ||
663 (sscanf (one_line, _("make: Leaving directory '%s'"), dir) == 1) ||
664 (sscanf (one_line, _("make[%d]: Leaving directory `%s'"), &dummy_int, dir) == 2) ||
665 (sscanf (one_line, _("make: Leaving directory `%s'"), dir) == 1) ||
666 (sscanf (one_line, "make[%d]: Leaving directory '%s'", &dummy_int, dir) == 2) ||
667 (sscanf (one_line, "make: Leaving directory '%s'", dir) == 1) ||
668 (sscanf (one_line, "make[%d]: Leaving directory `%s'", &dummy_int, dir) == 2) ||
669 (sscanf (one_line, "make: Leaving directory `%s'", dir) == 1))
672 gchar* summary;
673 /* FIXME: Hack to remove the last ' */
674 gchar *idx = strchr (dir, '\'');
675 if (idx != NULL)
677 *idx = '\0';
679 dir = get_real_directory(context, dir);
680 build_context_pop_dir (context, "default", dir);
681 summary = g_strdup_printf(_("Leaving: %s"), dir);
682 ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_INFO,
683 summary, one_line, NULL);
684 g_free(summary);
685 return;
688 /* Save freeptr so that we can free the copied string */
689 line = freeptr = g_strdup (one_line);
691 g_strchug(line); /* Remove leading whitespace */
692 if (g_str_has_prefix(line, "if ") == TRUE)
694 char *end;
695 line = line + 3;
697 /* Find the first occurence of ';' (ignoring nesting in quotations) */
698 end = strchr(line, ';');
699 if (end)
701 *end = '\0';
705 type = IANJUTA_MESSAGE_VIEW_TYPE_NORMAL;
706 if (parse_error_line(line, &dummy_fn, &dummy_int))
708 gchar *start_str, *end_str, *mid_str;
709 BuildIndicatorLocation *loc;
710 IAnjutaIndicableIndicator indicator;
712 if ((strstr (line, "warning:") != NULL) ||
713 (strstr (line, _("warning:")) != NULL))
715 type = IANJUTA_MESSAGE_VIEW_TYPE_WARNING;
716 indicator = IANJUTA_INDICABLE_WARNING;
718 else
720 type = IANJUTA_MESSAGE_VIEW_TYPE_ERROR;
721 indicator = IANJUTA_INDICABLE_CRITICAL;
724 mid_str = strstr (line, dummy_fn);
725 DEBUG_PRINT ("mid_str = %s, line = %s", mid_str, line);
726 start_str = g_strndup (line, mid_str - line);
727 end_str = line + strlen (start_str) + strlen (dummy_fn);
728 DEBUG_PRINT("dummy_fn: %s", dummy_fn);
729 if (g_path_is_absolute(dummy_fn))
731 mid_str = g_strdup(dummy_fn);
733 else
735 mid_str = g_build_filename (build_context_get_dir (context, "default"),
736 dummy_fn, NULL);
738 DEBUG_PRINT ("mid_str: %s", mid_str);
740 if (mid_str)
742 line = g_strconcat (start_str, mid_str, end_str, NULL);
744 /* We sucessfully build an absolute path of the file (mid_str),
745 * so we create an indicator location for it and save it.
746 * Additionally, check of current editor holds this file and if
747 * so, set the indicator.
749 DEBUG_PRINT ("dummy int: %d", dummy_int);
751 loc = build_indicator_location_new (mid_str, dummy_int,
752 indicator);
753 context->locations = g_slist_prepend (context->locations, loc);
755 /* If current editor file is same as indicator file, set indicator */
756 if (anjuta_preferences_get_int (anjuta_shell_get_preferences (context->plugin->shell, NULL), PREF_INDICATORS_AUTOMATIC))
758 build_indicator_location_set (loc, p->current_editor,
759 p->current_editor_filename);
762 else
764 line = g_strconcat (start_str, dummy_fn, end_str, NULL);
766 g_free (start_str);
767 g_free (mid_str);
768 g_free (dummy_fn);
770 else if (strstr (line, ": ") != NULL)
772 type = IANJUTA_MESSAGE_VIEW_TYPE_INFO;
775 node = patterns_list;
776 while (node)
778 BuildPattern *pattern = node->data;
779 summary = build_get_summary (line, pattern);
780 if (summary)
781 break;
782 node = g_list_next (node);
785 if (summary)
787 ianjuta_message_view_append (view, type, summary, line, NULL);
788 g_free (summary);
790 else
791 ianjuta_message_view_append (view, type, line, "", NULL);
792 g_free(freeptr);
795 static void
796 on_build_mesg_parse (IAnjutaMessageView *view, const gchar *line,
797 BuildContext *context)
799 gchar *filename;
800 gint lineno;
801 if (parse_error_line (line, &filename, &lineno))
803 IAnjutaDocumentManager *docman;
804 gchar *uri;
806 /* Go to file and line number */
807 docman = anjuta_shell_get_interface (context->plugin->shell,
808 IAnjutaDocumentManager,
809 NULL);
811 /* Full path is detected from parse_error_line() */
812 uri = gnome_vfs_get_uri_from_local_path(filename);
813 g_free(filename);
814 if (uri)
816 ianjuta_document_manager_goto_uri_line_mark(docman, uri, lineno, TRUE, NULL);
817 g_free(uri);
822 static void
823 on_build_terminated (AnjutaLauncher *launcher,
824 gint child_pid, gint status, gulong time_taken,
825 BuildContext *context)
827 g_signal_handlers_disconnect_by_func (context->launcher,
828 G_CALLBACK (on_build_terminated),
829 context);
831 if (context->callback != NULL)
833 GError *err = NULL;
835 if (WIFEXITED (status))
837 if (WEXITSTATUS (status) != 0)
839 err = g_error_new (ianjuta_builder_error_quark (),
840 WEXITSTATUS (status),
841 _("Command exited with status %d"), WEXITSTATUS (status));
844 else if (WIFSIGNALED (status))
846 switch (WTERMSIG (status))
848 case SIGTERM:
849 err = g_error_new (ianjuta_builder_error_quark (),
850 IANJUTA_BUILDER_CANCELED,
851 _("Command canceled by user"));
852 break;
853 case SIGKILL:
854 err = g_error_new (ianjuta_builder_error_quark (),
855 IANJUTA_BUILDER_ABORTED,
856 _("Command aborted by user"));
857 break;
858 default:
859 err = g_error_new (ianjuta_builder_error_quark (),
860 IANJUTA_BUILDER_INTERRUPTED,
861 _("Command terminated with signal %d"), WTERMSIG(status));
862 break;
865 else
867 err = g_error_new_literal (ianjuta_builder_error_quark (),
868 IANJUTA_BUILDER_TERMINATED,
869 _("Command terminated for an unknown reason"));
872 context->callback (G_OBJECT (context->plugin), err, context->user_data);
873 context->callback = NULL;
876 /* Message view could have been destroyed before */
877 if (context->message_view)
879 gchar *buff1;
881 buff1 = g_strdup_printf (_("Total time taken: %lu secs\n"),
882 time_taken);
883 if (status)
885 ianjuta_message_view_buffer_append (context->message_view,
886 _("Completed unsuccessful\n"), NULL);
888 else
890 ianjuta_message_view_buffer_append (context->message_view,
891 _("Completed successful\n"), NULL);
893 ianjuta_message_view_buffer_append (context->message_view, buff1, NULL);
894 g_free (buff1);
896 /* Goto the first error if it exists */
897 /* if (anjuta_preferences_get_int (ANJUTA_PREFERENCES (app->preferences),
898 "build.option.gotofirst"))
899 an_message_manager_next(app->messages);
902 update_project_ui (ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin));
904 build_context_destroy_command (context);
907 static void
908 on_message_view_destroyed (BuildContext *context, GtkWidget *view)
910 DEBUG_PRINT ("Destroying build context");
911 context->message_view = NULL;
913 build_context_destroy_view (context);
916 static gboolean
917 g_hashtable_foreach_true (gpointer key, gpointer value, gpointer user_data)
919 return TRUE;
922 static BuildContext*
923 build_get_context_with_message(BasicAutotoolsPlugin *plugin, const gchar *dir)
925 IAnjutaMessageManager *mesg_manager;
926 gchar mname[128];
927 gchar *subdir;
928 BuildContext *context = NULL;
929 static gint message_pane_count = 0;
931 /* Initialise regex rules */
932 build_regex_init();
934 subdir = g_path_get_basename (dir);
935 /* Translators: the first number is the number of the build attemp,
936 the string is the directory where the build takes place */
937 snprintf (mname, 128, _("Build %d: %s"), ++message_pane_count, subdir);
938 g_free (subdir);
940 /* If we already have MAX_BUILD_PANES build panes, find a free context */
941 if (g_list_length (plugin->contexts_pool) >= MAX_BUILD_PANES)
943 GList *node;
944 node = plugin->contexts_pool;
945 while (node)
947 BuildContext *c;
948 c = node->data;
949 if (c->launcher == NULL)
951 context = c;
952 break;
954 node = g_list_next (node);
958 mesg_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
959 IAnjutaMessageManager, NULL);
960 if (context)
962 build_context_reset (context);
964 /* It will be re-inserted in right order */
965 plugin->contexts_pool = g_list_remove (plugin->contexts_pool, context);
966 ianjuta_message_manager_set_view_title (mesg_manager,
967 context->message_view,
968 mname, NULL);
970 else
972 /* If no free context found, create one */
973 context = g_new0 (BuildContext, 1);
974 context->plugin = ANJUTA_PLUGIN(plugin);
975 context->indicators_updated_editors =
976 g_hash_table_new (g_direct_hash, g_direct_equal);
978 context->message_view =
979 ianjuta_message_manager_add_view (mesg_manager, mname,
980 ICON_FILE, NULL);
981 g_signal_connect (G_OBJECT (context->message_view), "buffer_flushed",
982 G_CALLBACK (on_build_mesg_format), context);
983 g_signal_connect (G_OBJECT (context->message_view), "message_clicked",
984 G_CALLBACK (on_build_mesg_parse), context);
985 g_object_weak_ref (G_OBJECT (context->message_view),
986 (GWeakNotify)on_message_view_destroyed, context);
989 ianjuta_message_manager_set_current_view (mesg_manager,
990 context->message_view, NULL);
992 /* Reset indicators in editors */
993 if (IANJUTA_IS_INDICABLE (plugin->current_editor))
994 ianjuta_indicable_clear (IANJUTA_INDICABLE (plugin->current_editor),
995 NULL);
996 /* This is only since glib 2.12.
997 g_hash_table_remove_all (context->indicators_updated_editors);
999 g_hash_table_foreach_remove (context->indicators_updated_editors,
1000 g_hashtable_foreach_true, NULL);
1002 return context;
1005 static BuildContext*
1006 build_get_context (BasicAutotoolsPlugin *plugin, const gchar *dir,
1007 gboolean with_view, const gchar *command,
1008 IAnjutaBuilderCallback callback, gpointer user_data)
1010 BuildContext *context = NULL;
1012 if (with_view)
1014 context = build_get_context_with_message (plugin, dir);
1016 else
1018 /* Context without a message view */
1019 context = g_new0 (BuildContext, 1);
1020 DEBUG_PRINT ("new context %p", context);
1021 context->plugin = ANJUTA_PLUGIN(plugin);
1024 context->callback = callback;
1025 context->user_data = user_data;
1026 context->command = g_strdup (command);
1027 context->launcher = anjuta_launcher_new ();
1028 g_signal_connect (G_OBJECT (context->launcher), "child-exited",
1029 G_CALLBACK (on_build_terminated), context);
1030 build_context_push_dir (context, "default", dir);
1031 chdir (dir);
1033 plugin->contexts_pool = g_list_append (plugin->contexts_pool, context);
1035 return context;
1038 /* Save all current anjuta files */
1039 static void
1040 save_all_files (AnjutaPlugin *plugin)
1042 IAnjutaDocumentManager *docman;
1043 IAnjutaFileSavable* save;
1045 docman = anjuta_shell_get_interface (plugin->shell, IAnjutaDocumentManager, NULL);
1046 /* No document manager, so no file to save */
1047 if (docman != NULL)
1049 save = IANJUTA_FILE_SAVABLE (docman);
1050 if (save) ianjuta_file_savable_save (save, NULL);
1054 static void build_set_env (gpointer key, gpointer value, gpointer user_data)
1056 AnjutaLauncher* launcher = ANJUTA_LAUNCHER (user_data);
1057 const gchar* name = key;
1058 const gchar* env_value = value;
1059 anjuta_launcher_set_env (launcher, name, env_value);
1062 static BuildContext*
1063 build_execute_command_full (BasicAutotoolsPlugin* bplugin, const gchar *dir,
1064 const gchar *command,
1065 gboolean save_file, gboolean with_view, GHashTable* env,
1066 IAnjutaBuilderCallback callback, gpointer user_data,
1067 GError **err)
1069 AnjutaPlugin* plugin = ANJUTA_PLUGIN(bplugin);
1070 AnjutaPreferences* prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
1071 BuildContext *context;
1072 gchar* real_command;
1074 g_return_val_if_fail (command != NULL, NULL);
1076 if (save_file)
1077 save_all_files (ANJUTA_PLUGIN (plugin));
1079 context = build_get_context (bplugin, dir, with_view, command, callback, user_data);
1081 if (anjuta_preferences_get_int (prefs , PREF_USE_SB))
1083 const gchar* sb_path = anjuta_preferences_get(prefs, PREF_SB_PATH);
1084 /* we need to skip the /scratchbox/users part, maybe could be done more clever */
1085 const gchar* real_dir = strstr(dir, "/home");
1086 real_command = g_strdup_printf("%s/login -d %s \"%s\"", sb_path,
1087 real_dir, command);
1089 else
1091 real_command = g_strdup(command);
1094 if (env)
1096 g_hash_table_foreach (env, build_set_env, context->launcher);
1099 if (context->message_view)
1101 ianjuta_message_view_buffer_append (context->message_view,
1102 "Building in directory: ", NULL);
1103 ianjuta_message_view_buffer_append (context->message_view, dir, NULL);
1104 ianjuta_message_view_buffer_append (context->message_view, "\n", NULL);
1105 ianjuta_message_view_buffer_append (context->message_view, command, NULL);
1106 ianjuta_message_view_buffer_append (context->message_view, "\n", NULL);
1108 anjuta_launcher_execute (context->launcher, real_command,
1109 on_build_mesg_arrived, context);
1111 else
1113 anjuta_launcher_execute (context->launcher, real_command,
1114 NULL, NULL);
1116 g_free(real_command);
1118 return context;
1122 static gboolean
1123 build_execute_command (BasicAutotoolsPlugin* bplugin, const gchar *dir,
1124 const gchar *command, gboolean save_file, GError **err)
1126 return build_execute_command_full (bplugin, dir, command, save_file, TRUE, NULL, NULL, NULL, NULL) != NULL;
1129 static void
1130 build_cancel_command (BasicAutotoolsPlugin* bplugin, BuildContext *context,
1131 GError **err)
1133 GList *node;
1135 if (context == NULL) return;
1137 for (node = g_list_first (bplugin->contexts_pool); node != NULL; node = g_list_next (node))
1139 if (node->data == context)
1141 if (context->launcher != NULL)
1143 anjuta_launcher_signal (context->launcher, SIGTERM);
1144 return;
1149 /* Invalid handle passed */
1150 g_return_if_reached ();
1153 static gboolean
1154 build_compile_file_real (BasicAutotoolsPlugin *plugin, const gchar *file)
1156 gchar *file_basename;
1157 gchar *file_dirname;
1158 gchar *ext_ptr;
1159 gboolean ret;
1161 /* FIXME: This should be configuration somewhere, eg. preferences */
1162 static GHashTable *target_ext = NULL;
1163 if (!target_ext)
1165 target_ext = g_hash_table_new (g_str_hash, g_str_equal);
1166 g_hash_table_insert (target_ext, ".c", ".o");
1167 g_hash_table_insert (target_ext, ".cpp", ".o");
1168 g_hash_table_insert (target_ext, ".cxx", ".o");
1169 g_hash_table_insert (target_ext, ".c++", ".o");
1170 g_hash_table_insert (target_ext, ".cc", ".o");
1171 g_hash_table_insert (target_ext, ".in", "");
1172 g_hash_table_insert (target_ext, ".in.in", ".in");
1173 g_hash_table_insert (target_ext, ".la", ".la");
1174 g_hash_table_insert (target_ext, ".a", ".a");
1175 g_hash_table_insert (target_ext, ".so", ".so");
1176 g_hash_table_insert (target_ext, ".java", ".class");
1179 g_return_val_if_fail (file != NULL, FALSE);
1180 ret = FALSE;
1182 file_basename = g_path_get_basename (file);
1183 file_dirname = g_path_get_dirname (file);
1184 ext_ptr = strrchr (file_basename, '.');
1185 if (ext_ptr)
1187 const gchar *new_ext;
1188 new_ext = g_hash_table_lookup (target_ext, ext_ptr);
1189 if (new_ext)
1191 gchar *command;
1193 *ext_ptr = '\0';
1194 command = g_strconcat (CHOOSE_COMMAND (plugin, COMPILE), " ",
1195 file_basename, new_ext, NULL);
1196 build_execute_command (plugin, file_dirname, command, TRUE, NULL);
1197 g_free (command);
1198 ret = TRUE;
1200 } else {
1201 /* If file has no extension, take it as target itself */
1202 gchar *command;
1203 command = g_strconcat (CHOOSE_COMMAND(plugin, COMPILE), " ",
1204 file_basename, NULL);
1205 build_execute_command (plugin, file_dirname, command, TRUE, NULL);
1206 g_free (command);
1207 ret = TRUE;
1209 g_free (file_basename);
1210 g_free (file_dirname);
1211 if (ret == FALSE)
1213 /* FIXME: Prompt the user to create a Makefile with a wizard
1214 (if there is no Makefile in the directory) or to add a target
1215 rule in the above hash table, eg. editing the preferences, if
1216 there is target extension defined for that file extension.
1218 GtkWindow *window;
1219 window = GTK_WINDOW (ANJUTA_PLUGIN (plugin)->shell);
1220 anjuta_util_dialog_error (window, _("Can not compile \"%s\": No compile rule defined for this file type."), file);
1222 return ret;
1225 /* UI actions */
1226 static void
1227 build_build_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1229 build_execute_command (plugin, plugin->project_root_dir,
1230 CHOOSE_COMMAND (plugin, BUILD), TRUE, NULL);
1233 static void
1234 build_install_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1236 gchar* root = get_root_install_command(plugin);
1237 gchar* command = g_strdup_printf("%s %s", root,
1238 CHOOSE_COMMAND (plugin, INSTALL));
1239 g_free(root);
1240 build_execute_command (plugin, plugin->project_root_dir,
1241 command, TRUE, NULL);
1242 g_free(command);
1245 static void
1246 build_clean_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1248 build_execute_command (plugin, plugin->project_root_dir,
1249 CHOOSE_COMMAND (plugin, CLEAN), FALSE, NULL);
1252 static void
1253 build_configure_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1255 gint response;
1256 GtkWindow *parent;
1257 gchar *input = NULL;
1258 GHashTable* build_options = NULL;
1260 parent = GTK_WINDOW (ANJUTA_PLUGIN(plugin)->shell);
1261 /* Configure = ./configure script */
1262 response = build_dialog_configure (parent, _("Configure"),
1263 &build_options,
1264 plugin->configure_args,
1265 &input);
1266 if (response)
1268 gchar *cmd;
1269 if (input)
1271 cmd = g_strdup_printf ("%s %s", CHOOSE_COMMAND (plugin, CONFIGURE),
1272 input);
1273 g_free (plugin->configure_args);
1274 plugin->configure_args = input;
1276 else
1278 cmd = g_strdup (CHOOSE_COMMAND (plugin, CONFIGURE));
1280 build_execute_command_full (plugin, plugin->project_root_dir,
1281 cmd, TRUE, TRUE, build_options,
1282 NULL, NULL, NULL);
1283 g_free (cmd);
1284 g_hash_table_destroy (build_options);
1288 static void
1289 build_autogen_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1291 gint response;
1292 GtkWindow *parent;
1293 gchar *input = NULL;
1294 GHashTable* build_options = NULL;
1296 parent = GTK_WINDOW (ANJUTA_PLUGIN(plugin)->shell);
1297 response = build_dialog_configure (parent, _("Autogenerate"),
1298 &build_options,
1299 plugin->configure_args,
1300 &input);
1301 if (response)
1303 gboolean has_autogen = directory_has_file (plugin->project_root_dir,
1304 "autogen.sh");
1305 gchar *cmd;
1306 if (input)
1308 if (has_autogen)
1309 cmd = g_strdup_printf ("%s %s",
1310 CHOOSE_COMMAND (plugin, GENERATE),
1311 input);
1312 else /* FIXME: Get override command for this too */
1313 cmd = g_strconcat ("autoreconf -i --force ", input, NULL);
1314 g_free (plugin->configure_args);
1315 plugin->configure_args = input;
1317 else
1319 if (has_autogen)
1320 cmd = g_strdup (CHOOSE_COMMAND (plugin, GENERATE));
1321 else /* FIXME: Get override command for this too */
1322 cmd = g_strdup ("autoreconf -i --force");
1324 build_execute_command_full (plugin, plugin->project_root_dir,
1325 cmd, TRUE, TRUE, build_options,
1326 NULL, NULL, NULL);
1327 g_free (cmd);
1328 g_hash_table_destroy (build_options);
1332 static void
1333 build_distribution_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1335 build_execute_command (plugin, plugin->project_root_dir,
1336 CHOOSE_COMMAND (plugin, BUILD_TARBALL),
1337 FALSE, NULL);
1340 static void
1341 build_build_module (GtkAction *action, BasicAutotoolsPlugin *plugin)
1343 gchar *dirname = g_dirname (plugin->current_editor_filename);
1344 build_execute_command (plugin, dirname,
1345 CHOOSE_COMMAND (plugin, BUILD),
1346 TRUE, NULL);
1347 g_free (dirname);
1350 static void
1351 build_install_module (GtkAction *action, BasicAutotoolsPlugin *plugin)
1353 gchar *dirname = g_dirname (plugin->current_editor_filename);
1354 gchar* root = get_root_install_command(plugin);
1355 gchar* command = g_strdup_printf ("%s %s", root,
1356 CHOOSE_COMMAND (plugin, INSTALL));
1357 g_free(root);
1358 build_execute_command (plugin, dirname, command, TRUE, NULL);
1359 g_free(command);
1360 g_free (dirname);
1363 static void
1364 build_clean_module (GtkAction *action, BasicAutotoolsPlugin *plugin)
1366 gchar *dirname = g_dirname (plugin->current_editor_filename);
1367 build_execute_command (plugin, dirname,
1368 CHOOSE_COMMAND (plugin, CLEAN),
1369 FALSE, NULL);
1370 g_free (dirname);
1373 static void
1374 build_compile_file (GtkAction *action, BasicAutotoolsPlugin *plugin)
1376 if (plugin->current_editor_filename)
1378 build_compile_file_real (plugin, plugin->current_editor_filename);
1382 /* File manager context menu */
1383 static void
1384 fm_compile (GtkAction *action, BasicAutotoolsPlugin *plugin)
1386 if (plugin->fm_current_filename)
1388 build_compile_file_real (plugin, plugin->fm_current_filename);
1392 static void
1393 fm_build (GtkAction *action, BasicAutotoolsPlugin *plugin)
1395 gchar *dir;
1397 g_return_if_fail (plugin->fm_current_filename != NULL);
1399 if (g_file_test (plugin->fm_current_filename, G_FILE_TEST_IS_DIR))
1400 dir = g_strdup (plugin->fm_current_filename);
1401 else
1402 dir = g_path_get_dirname (plugin->fm_current_filename);
1403 build_execute_command (plugin, dir,
1404 CHOOSE_COMMAND (plugin, BUILD),
1405 TRUE, NULL);
1408 static void
1409 fm_install (GtkAction *action, BasicAutotoolsPlugin *plugin)
1411 gchar *dir;
1412 gchar* root;
1413 gchar* command;
1415 g_return_if_fail (plugin->fm_current_filename != NULL);
1418 if (g_file_test (plugin->fm_current_filename, G_FILE_TEST_IS_DIR))
1419 dir = g_strdup (plugin->fm_current_filename);
1420 else
1421 dir = g_path_get_dirname (plugin->fm_current_filename);
1422 root = get_root_install_command(plugin);
1423 command = g_strdup_printf ("%s %s", root,
1424 CHOOSE_COMMAND (plugin, INSTALL));
1425 g_free(root);
1426 build_execute_command (plugin, dir, command, TRUE, NULL);
1429 static void
1430 fm_clean (GtkAction *action, BasicAutotoolsPlugin *plugin)
1432 gchar *dir;
1434 g_return_if_fail (plugin->fm_current_filename != NULL);
1436 if (g_file_test (plugin->fm_current_filename, G_FILE_TEST_IS_DIR))
1437 dir = g_strdup (plugin->fm_current_filename);
1438 else
1439 dir = g_path_get_dirname (plugin->fm_current_filename);
1440 build_execute_command (plugin, dir,
1441 CHOOSE_COMMAND (plugin, CLEAN),
1442 FALSE, NULL);
1445 /* Project manager context menu */
1446 static void
1447 pm_compile (GtkAction *action, BasicAutotoolsPlugin *plugin)
1449 if (plugin->pm_current_filename)
1451 build_compile_file_real (plugin, plugin->pm_current_filename);
1455 static void
1456 pm_build (GtkAction *action, BasicAutotoolsPlugin *plugin)
1458 gchar *dir;
1460 g_return_if_fail (plugin->pm_current_filename != NULL);
1462 if (g_file_test (plugin->pm_current_filename, G_FILE_TEST_IS_DIR))
1463 dir = g_strdup (plugin->pm_current_filename);
1464 else
1465 dir = g_path_get_dirname (plugin->pm_current_filename);
1466 build_execute_command (plugin, dir,
1467 CHOOSE_COMMAND (plugin, BUILD),
1468 TRUE, NULL);
1471 static void
1472 pm_install (GtkAction *action, BasicAutotoolsPlugin *plugin)
1474 gchar *dir;
1475 gchar* root;
1476 gchar* command;
1478 g_return_if_fail (plugin->pm_current_filename != NULL);
1480 root = get_root_install_command(plugin);
1481 command = g_strdup_printf ("%s %s", root,
1482 CHOOSE_COMMAND (plugin, INSTALL));
1483 g_free(root);
1485 if (g_file_test (plugin->pm_current_filename, G_FILE_TEST_IS_DIR))
1486 dir = g_strdup (plugin->pm_current_filename);
1487 else
1488 dir = g_path_get_dirname (plugin->pm_current_filename);
1489 build_execute_command (plugin, dir, command, TRUE, NULL);
1490 g_free(command);
1493 static void
1494 pm_clean (GtkAction *action, BasicAutotoolsPlugin *plugin)
1496 gchar *dir;
1498 g_return_if_fail (plugin->pm_current_filename != NULL);
1500 if (g_file_test (plugin->pm_current_filename, G_FILE_TEST_IS_DIR))
1501 dir = g_strdup (plugin->pm_current_filename);
1502 else
1503 dir = g_path_get_dirname (plugin->pm_current_filename);
1504 build_execute_command (plugin, dir,
1505 CHOOSE_COMMAND (plugin, CLEAN),
1506 FALSE, NULL);
1509 static GtkActionEntry build_actions[] =
1512 "ActionMenuBuild", NULL,
1513 N_("_Build"), NULL, NULL, NULL
1516 "ActionBuildBuildProject", NULL,
1517 N_("_Build Project"), "<shift>F11",
1518 N_("Build whole project"),
1519 G_CALLBACK (build_build_project)
1522 "ActionBuildInstallProject", NULL,
1523 N_("_Install Project"), NULL,
1524 N_("Install whole project"),
1525 G_CALLBACK (build_install_project)
1528 "ActionBuildCleanProject", NULL,
1529 N_("_Clean Project"), NULL,
1530 N_("Clean whole project"),
1531 G_CALLBACK (build_clean_project)
1534 "ActionBuildConfigure", NULL,
1535 N_("Run C_onfigure..."), NULL,
1536 N_("Configure project"),
1537 G_CALLBACK (build_configure_project)
1540 "ActionBuildAutogen", NULL,
1541 N_("Run _Autogenerate..."), NULL,
1542 N_("Autogenerate project files"),
1543 G_CALLBACK (build_autogen_project)
1546 "ActionBuildDistribution", NULL,
1547 N_("Build _Tarball"), NULL,
1548 N_("Build project tarball distribution"),
1549 G_CALLBACK (build_distribution_project)
1552 "ActionBuildBuildModule", GTK_STOCK_EXECUTE,
1553 N_("_Build Module"), "F11",
1554 N_("Build module associated with current file"),
1555 G_CALLBACK (build_build_module)
1558 "ActionBuildInstallModule", NULL,
1559 N_("_Install Module"), NULL,
1560 N_("Install module associated with current file"),
1561 G_CALLBACK (build_install_module)
1564 "ActionBuildCleanModule", NULL,
1565 N_("_Clean Module"), NULL,
1566 N_("Clean module associated with current file"),
1567 G_CALLBACK (build_clean_module)
1570 "ActionBuildCompileFile", GTK_STOCK_CONVERT,
1571 N_("Co_mpile File"), "F9",
1572 N_("Compile current editor file"),
1573 G_CALLBACK (build_compile_file)
1577 static GtkActionEntry build_popup_actions[] =
1580 "ActionPopupBuild", NULL,
1581 N_("_Build"), NULL, NULL, NULL
1584 "ActionPopupBuildCompile", GTK_STOCK_CONVERT,
1585 N_("_Compile"), NULL,
1586 N_("Compile file"),
1587 G_CALLBACK (fm_compile)
1590 "ActionPopupBuildBuild", GTK_STOCK_EXECUTE,
1591 N_("_Build"), NULL,
1592 N_("Build module"),
1593 G_CALLBACK (fm_build)
1596 "ActionPopupBuildInstall", NULL,
1597 N_("_Install"), NULL,
1598 N_("Install module"),
1599 G_CALLBACK (fm_install)
1602 "ActionPopupBuildClean", NULL,
1603 N_("_Clean"), NULL,
1604 N_("Clean module"),
1605 G_CALLBACK (fm_clean)
1608 "ActionPopupPMBuild", NULL,
1609 N_("_Build"), NULL, NULL, NULL
1612 "ActionPopupPMBuildCompile", GTK_STOCK_CONVERT,
1613 N_("_Compile"), NULL,
1614 N_("Compile file"),
1615 G_CALLBACK (pm_compile)
1618 "ActionPopupPMBuildBuild", GTK_STOCK_EXECUTE,
1619 N_("_Build"), NULL,
1620 N_("Build module"),
1621 G_CALLBACK (pm_build)
1624 "ActionPopupPMBuildInstall", NULL,
1625 N_("_Install"), NULL,
1626 N_("Install module"),
1627 G_CALLBACK (pm_install)
1630 "ActionPopupPMBuildClean", NULL,
1631 N_("_Clean"), NULL,
1632 N_("Clean module"),
1633 G_CALLBACK (pm_clean)
1637 static gboolean
1638 directory_has_makefile (const gchar *dirname)
1640 gchar *makefile;
1641 gboolean makefile_exists;
1643 makefile_exists = TRUE;
1644 makefile = g_build_filename (dirname, "Makefile", NULL);
1645 if (!g_file_test (makefile, G_FILE_TEST_EXISTS))
1647 g_free (makefile);
1648 makefile = g_build_filename (dirname, "makefile", NULL);
1649 if (!g_file_test (makefile, G_FILE_TEST_EXISTS))
1651 g_free (makefile);
1652 makefile = g_build_filename (dirname, "MAKEFILE", NULL);
1653 if (!g_file_test (makefile, G_FILE_TEST_EXISTS))
1655 makefile_exists = FALSE;
1659 g_free (makefile);
1660 return makefile_exists;
1663 static gboolean
1664 directory_has_file (const gchar *dirname, const gchar *filename)
1666 gchar *filepath;
1667 gboolean exists;
1669 exists = TRUE;
1670 filepath = g_build_filename (dirname, filename, NULL);
1671 if (!g_file_test (filepath, G_FILE_TEST_EXISTS))
1672 exists = FALSE;
1674 g_free (filepath);
1675 return exists;
1678 static void
1679 update_project_ui (BasicAutotoolsPlugin *bb_plugin)
1681 AnjutaUI *ui;
1682 GtkAction *action;
1684 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (bb_plugin)->shell, NULL);
1686 DEBUG_PRINT ("Updateing project UI");
1688 if (!bb_plugin->project_root_dir)
1690 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1691 "ActionBuildBuildProject");
1692 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
1693 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1694 "ActionBuildInstallProject");
1695 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
1696 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1697 "ActionBuildCleanProject");
1698 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
1699 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1700 "ActionBuildDistribution");
1701 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
1702 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1703 "ActionBuildConfigure");
1704 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
1705 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1706 "ActionBuildAutogen");
1707 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
1708 return;
1710 if (directory_has_makefile (bb_plugin->project_root_dir))
1712 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1713 "ActionBuildBuildProject");
1714 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
1715 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1716 "ActionBuildInstallProject");
1717 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
1718 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1719 "ActionBuildCleanProject");
1720 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
1721 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1722 "ActionBuildDistribution");
1723 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
1725 if (directory_has_file (bb_plugin->project_root_dir, "configure"))
1727 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1728 "ActionBuildConfigure");
1729 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
1731 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1732 "ActionBuildAutogen");
1733 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
1736 static gchar*
1737 escape_label (const gchar *str)
1739 GString *ret;
1740 const gchar *iter;
1742 ret = g_string_new ("");
1743 iter = str;
1744 while (*iter != '\0')
1746 if (*iter == '_')
1748 ret = g_string_append (ret, "__");
1749 iter++;
1751 else
1753 const gchar *start;
1754 const gchar *end;
1756 start = iter;
1757 iter = g_utf8_next_char (iter);
1758 end = iter;
1760 ret = g_string_append_len (ret, start, end - start);
1763 return g_string_free (ret, FALSE);
1766 static void
1767 update_module_ui (BasicAutotoolsPlugin *bb_plugin)
1769 AnjutaUI *ui;
1770 GtkAction *action;
1771 gchar *dirname;
1772 gchar *module;
1773 gchar *filename;
1774 gchar *label;
1776 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (bb_plugin)->shell, NULL);
1778 DEBUG_PRINT ("Updateing module UI");
1780 if (!bb_plugin->current_editor_filename)
1782 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1783 "ActionBuildBuildModule");
1784 g_object_set (G_OBJECT (action), "sensitive", FALSE,
1785 "label", _("_Build"), NULL);
1786 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1787 "ActionBuildInstallModule");
1788 g_object_set (G_OBJECT (action), "sensitive", FALSE,
1789 "label", _("_Install"), NULL);
1790 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1791 "ActionBuildCleanModule");
1792 g_object_set (G_OBJECT (action), "sensitive", FALSE,
1793 "label", _("_Clean"), NULL);
1794 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1795 "ActionBuildCompileFile");
1796 g_object_set (G_OBJECT (action), "sensitive", FALSE,
1797 "label", _("Co_mpile"), NULL);
1798 return;
1801 dirname = g_dirname (bb_plugin->current_editor_filename);
1802 module = escape_label (g_basename (dirname));
1803 filename = escape_label (g_basename (bb_plugin->current_editor_filename));
1804 if (directory_has_makefile (dirname))
1806 label = g_strdup_printf (_("_Build (%s)"), module);
1807 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1808 "ActionBuildBuildModule");
1809 g_object_set (G_OBJECT (action), "sensitive", TRUE,
1810 /*"label", label, */NULL);
1811 g_free (label);
1813 label = g_strdup_printf (_("_Install (%s)"), module);
1814 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1815 "ActionBuildInstallModule");
1816 g_object_set (G_OBJECT (action), "sensitive", TRUE,
1817 /* "label", label, */NULL);
1818 g_free (label);
1820 label = g_strdup_printf (_("_Clean (%s)"), module);
1821 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1822 "ActionBuildCleanModule");
1823 g_object_set (G_OBJECT (action), "sensitive", TRUE,
1824 /* "label", label,*/ NULL);
1825 g_free (label);
1827 label = g_strdup_printf (_("Co_mpile (%s)"), filename);
1828 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1829 "ActionBuildCompileFile");
1830 g_object_set (G_OBJECT (action), "sensitive", TRUE,
1831 /* "label", label, */ NULL);
1832 g_free (label);
1833 g_free (module);
1834 g_free (filename);
1835 g_free (dirname);
1838 static void
1839 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
1840 AnjutaSession *session, BasicAutotoolsPlugin *plugin)
1842 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
1843 return;
1844 if (plugin->program_args)
1845 anjuta_session_set_string (session, "Execution",
1846 "Program arguments", plugin->program_args);
1847 anjuta_session_set_int (session, "Execution", "Run in terminal",
1848 plugin->run_in_terminal + 1);
1849 if (plugin->last_exec_uri)
1851 anjuta_session_set_string (session, "Execution",
1852 "Last selected uri", plugin->last_exec_uri);
1855 if (plugin->configure_args)
1856 anjuta_session_set_string (session, "Build",
1857 "Configure parameters",
1858 plugin->configure_args);
1861 static void
1862 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase,
1863 AnjutaSession *session, BasicAutotoolsPlugin *plugin)
1865 gchar *program_args, *configure_args, *last_uri;
1866 gint run_in_terminal;
1868 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
1869 return;
1871 program_args = anjuta_session_get_string (session, "Execution",
1872 "Program arguments");
1873 if (program_args)
1875 g_free (plugin->program_args);
1876 plugin->program_args = program_args;
1879 configure_args = anjuta_session_get_string (session, "Build",
1880 "Configure parameters");
1881 if (configure_args)
1883 g_free (plugin->configure_args);
1884 plugin->configure_args = configure_args;
1887 last_uri = anjuta_session_get_string (session, "Execution",
1888 "Last selected uri");
1890 if (last_uri)
1892 plugin->last_exec_uri = last_uri;
1895 /* The flag is store as 1 == FALSE, 2 == TRUE */
1896 run_in_terminal =
1897 anjuta_session_get_int (session, "Execution", "Run in terminal");
1898 run_in_terminal--;
1900 if (run_in_terminal >= 0)
1901 plugin->run_in_terminal = run_in_terminal;
1904 static void
1905 value_added_fm_current_uri (AnjutaPlugin *plugin, const char *name,
1906 const GValue *value, gpointer data)
1908 AnjutaUI *ui;
1909 GtkAction *action;
1910 const gchar *uri;
1911 gchar *dirname, *filename;
1912 gboolean makefile_exists, is_dir;
1914 uri = g_value_get_string (value);
1915 filename = gnome_vfs_get_local_path_from_uri (uri);
1916 g_return_if_fail (filename != NULL);
1918 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
1919 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1921 if (ba_plugin->fm_current_filename)
1922 g_free (ba_plugin->fm_current_filename);
1923 ba_plugin->fm_current_filename = filename;
1925 is_dir = g_file_test (filename, G_FILE_TEST_IS_DIR);
1926 if (is_dir)
1927 dirname = g_strdup (filename);
1928 else
1929 dirname = g_path_get_dirname (filename);
1930 makefile_exists = directory_has_makefile (dirname);
1931 g_free (dirname);
1933 if (!makefile_exists)
1934 return;
1936 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild", "ActionPopupBuild");
1937 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
1938 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1939 "ActionPopupBuildCompile");
1940 if (is_dir)
1941 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
1942 else
1943 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
1946 static void
1947 value_removed_fm_current_uri (AnjutaPlugin *plugin,
1948 const char *name, gpointer data)
1950 AnjutaUI *ui;
1951 GtkAction *action;
1952 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
1954 if (ba_plugin->fm_current_filename)
1955 g_free (ba_plugin->fm_current_filename);
1956 ba_plugin->fm_current_filename = NULL;
1958 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1959 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild", "ActionPopupBuild");
1960 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
1963 static void
1964 value_added_pm_current_uri (AnjutaPlugin *plugin, const char *name,
1965 const GValue *value, gpointer data)
1967 AnjutaUI *ui;
1968 GtkAction *action;
1969 const gchar *uri;
1970 gchar *dirname, *filename;
1971 gboolean makefile_exists, is_dir;
1973 uri = g_value_get_string (value);
1974 filename = gnome_vfs_get_local_path_from_uri (uri);
1975 g_return_if_fail (filename != NULL);
1978 if (g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE)
1979 return;
1982 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
1983 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1985 if (ba_plugin->pm_current_filename)
1986 g_free (ba_plugin->pm_current_filename);
1987 ba_plugin->pm_current_filename = filename;
1989 is_dir = g_file_test (filename, G_FILE_TEST_IS_DIR);
1990 if (is_dir)
1991 dirname = g_strdup (filename);
1992 else
1993 dirname = g_path_get_dirname (filename);
1994 makefile_exists = directory_has_makefile (dirname);
1995 g_free (dirname);
1997 if (!makefile_exists)
1998 return;
2000 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild", "ActionPopupPMBuild");
2001 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
2002 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
2003 "ActionPopupPMBuildCompile");
2004 if (is_dir)
2005 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
2006 else
2007 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
2010 static void
2011 value_removed_pm_current_uri (AnjutaPlugin *plugin,
2012 const char *name, gpointer data)
2014 AnjutaUI *ui;
2015 GtkAction *action;
2016 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2018 if (ba_plugin->pm_current_filename)
2019 g_free (ba_plugin->pm_current_filename);
2020 ba_plugin->pm_current_filename = NULL;
2022 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2023 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild", "ActionPopupPMBuild");
2024 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
2027 static void
2028 value_added_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
2029 const GValue *value, gpointer user_data)
2031 BasicAutotoolsPlugin *bb_plugin;
2032 const gchar *root_uri;
2034 bb_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2036 DEBUG_PRINT ("Project added");
2038 g_free (bb_plugin->project_root_dir);
2039 bb_plugin->project_root_dir = NULL;
2041 root_uri = g_value_get_string (value);
2042 if (root_uri)
2044 bb_plugin->project_root_dir =
2045 gnome_vfs_get_local_path_from_uri (root_uri);
2046 if (bb_plugin->project_root_dir)
2048 update_project_ui (bb_plugin);
2053 static void
2054 value_removed_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
2055 gpointer user_data)
2057 BasicAutotoolsPlugin *bb_plugin;
2059 bb_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2061 g_free (bb_plugin->project_root_dir);
2062 g_free (bb_plugin->program_args);
2063 g_free (bb_plugin->configure_args);
2065 bb_plugin->run_in_terminal = TRUE;
2066 bb_plugin->program_args = NULL;
2067 bb_plugin->configure_args = NULL;
2068 bb_plugin->project_root_dir = NULL;
2069 update_project_ui (bb_plugin);
2072 static gint
2073 on_update_indicators_idle (gpointer data)
2075 AnjutaPlugin *plugin = ANJUTA_PLUGIN (data);
2076 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (data);
2077 IAnjutaEditor *editor = ba_plugin->current_editor;
2079 /* If indicators are not yet updated in the editor, do it */
2080 if (ba_plugin->current_editor_filename &&
2081 IANJUTA_IS_INDICABLE (editor) &&
2082 anjuta_preferences_get_int (anjuta_shell_get_preferences (plugin->shell,
2083 NULL),
2084 PREF_INDICATORS_AUTOMATIC))
2086 GList *node;
2087 node = ba_plugin->contexts_pool;
2088 while (node)
2090 BuildContext *context = node->data;
2091 if (g_hash_table_lookup (context->indicators_updated_editors,
2092 editor) == NULL)
2094 GSList *loc_node;
2095 ianjuta_indicable_clear (IANJUTA_INDICABLE (editor), NULL);
2098 loc_node = context->locations;
2099 while (loc_node)
2101 build_indicator_location_set ((BuildIndicatorLocation*) loc_node->data,
2102 IANJUTA_EDITOR (editor), ba_plugin->current_editor_filename);
2103 loc_node = g_slist_next (loc_node);
2105 g_hash_table_insert (context->indicators_updated_editors,
2106 editor, editor);
2108 node = g_list_next (node);
2111 return FALSE;
2114 static void
2115 on_editor_destroy (IAnjutaEditor *editor, BasicAutotoolsPlugin *ba_plugin)
2117 g_hash_table_remove (ba_plugin->editors_created, editor);
2120 static void
2121 on_editor_changed (IAnjutaEditor *editor, IAnjutaIterable *position,
2122 gboolean added, gint length, gint lines, const gchar *text,
2123 BasicAutotoolsPlugin *ba_plugin)
2125 gint line;
2126 IAnjutaIterable *begin_pos, *end_pos;
2127 if (g_hash_table_lookup (ba_plugin->editors_created,
2128 editor) == NULL)
2129 return;
2130 line = ianjuta_editor_get_line_from_position (editor, position, NULL);
2131 begin_pos = ianjuta_editor_get_line_begin_position (editor, line, NULL);
2132 end_pos = ianjuta_editor_get_line_end_position (editor, line, NULL);
2133 if (IANJUTA_IS_INDICABLE (editor))
2135 DEBUG_PRINT ("Clearing indicator on line %d", line);
2136 ianjuta_indicable_set (IANJUTA_INDICABLE (editor), begin_pos,
2137 end_pos, IANJUTA_INDICABLE_NONE, NULL);
2139 DEBUG_PRINT ("Editor changed: line number = %d, added = %d,"
2140 " text length = %d, number of lines = %d",
2141 line, added, length, lines);
2142 g_object_unref (begin_pos);
2143 g_object_unref (end_pos);
2146 static void
2147 value_added_current_editor (AnjutaPlugin *plugin, const char *name,
2148 const GValue *value, gpointer data)
2150 AnjutaUI *ui;
2151 gchar *uri;
2152 GObject *editor;
2154 editor = g_value_get_object (value);
2156 if (!IANJUTA_IS_EDITOR(editor))
2157 return;
2159 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2160 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2162 g_free (ba_plugin->current_editor_filename);
2163 ba_plugin->current_editor_filename = NULL;
2164 ba_plugin->current_editor = IANJUTA_EDITOR (editor);
2166 if (g_hash_table_lookup (ba_plugin->editors_created,
2167 ba_plugin->current_editor) == NULL)
2169 g_hash_table_insert (ba_plugin->editors_created,
2170 ba_plugin->current_editor,
2171 ba_plugin->current_editor);
2172 g_signal_connect (ba_plugin->current_editor, "destroy",
2173 G_CALLBACK (on_editor_destroy), plugin);
2174 g_signal_connect (ba_plugin->current_editor, "changed",
2175 G_CALLBACK (on_editor_changed), plugin);
2178 uri = ianjuta_file_get_uri (IANJUTA_FILE (editor), NULL);
2179 if (uri)
2181 gchar *filename;
2183 filename = gnome_vfs_get_local_path_from_uri (uri);
2184 g_free (uri);
2185 g_return_if_fail (filename != NULL);
2186 ba_plugin->current_editor_filename = filename;
2187 update_module_ui (ba_plugin);
2189 g_idle_add (on_update_indicators_idle, plugin);
2192 static void
2193 value_removed_current_editor (AnjutaPlugin *plugin,
2194 const char *name, gpointer data)
2196 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2197 #if 0
2198 if (ba_plugin->indicators_updated_editors &&
2199 g_hash_table_lookup (ba_plugin->indicators_updated_editors,
2200 ba_plugin->current_editor))
2202 g_hash_table_remove (ba_plugin->indicators_updated_editors,
2203 ba_plugin->current_editor);
2205 #endif
2206 if (ba_plugin->current_editor_filename)
2207 g_free (ba_plugin->current_editor_filename);
2208 ba_plugin->current_editor_filename = NULL;
2209 ba_plugin->current_editor = NULL;
2211 update_module_ui (ba_plugin);
2214 static gboolean
2215 activate_plugin (AnjutaPlugin *plugin)
2217 AnjutaUI *ui;
2218 static gboolean initialized = FALSE;
2219 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2221 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2223 g_signal_connect (plugin->shell, "save-session",
2224 G_CALLBACK (on_session_save),
2225 plugin);
2226 g_signal_connect (plugin->shell, "load-session",
2227 G_CALLBACK (on_session_load),
2228 plugin);
2230 /* Add action group */
2231 ba_plugin->build_action_group =
2232 anjuta_ui_add_action_group_entries (ui,
2233 "ActionGroupBuild",
2234 _("Build commands"),
2235 build_actions,
2236 sizeof(build_actions)/sizeof(GtkActionEntry),
2237 GETTEXT_PACKAGE, TRUE, plugin);
2238 ba_plugin->build_popup_action_group =
2239 anjuta_ui_add_action_group_entries (ui,
2240 "ActionGroupPopupBuild",
2241 _("Build popup commands"),
2242 build_popup_actions,
2243 sizeof(build_popup_actions)/sizeof(GtkActionEntry),
2244 GETTEXT_PACKAGE, FALSE, plugin);
2245 /* Add UI */
2246 ba_plugin->build_merge_id = anjuta_ui_merge (ui, UI_FILE);
2248 update_project_ui (ba_plugin);
2249 update_module_ui (ba_plugin);
2251 /* Add watches */
2252 ba_plugin->fm_watch_id =
2253 anjuta_plugin_add_watch (plugin, "file_manager_current_uri",
2254 value_added_fm_current_uri,
2255 value_removed_fm_current_uri, NULL);
2256 ba_plugin->pm_watch_id =
2257 anjuta_plugin_add_watch (plugin, "project_manager_current_uri",
2258 value_added_pm_current_uri,
2259 value_removed_pm_current_uri, NULL);
2260 ba_plugin->project_watch_id =
2261 anjuta_plugin_add_watch (plugin, "project_root_uri",
2262 value_added_project_root_uri,
2263 value_removed_project_root_uri, NULL);
2264 ba_plugin->editor_watch_id =
2265 anjuta_plugin_add_watch (plugin, "document_manager_current_editor",
2266 value_added_current_editor,
2267 value_removed_current_editor, NULL);
2268 initialized = TRUE;
2269 return TRUE;
2272 static gboolean
2273 deactivate_plugin (AnjutaPlugin *plugin)
2275 AnjutaUI *ui;
2276 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2278 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2280 g_signal_handlers_disconnect_by_func (plugin->shell,
2281 G_CALLBACK (on_session_save),
2282 plugin);
2283 g_signal_handlers_disconnect_by_func (plugin->shell,
2284 G_CALLBACK (on_session_load),
2285 plugin);
2287 /* Remove watches */
2288 anjuta_plugin_remove_watch (plugin, ba_plugin->fm_watch_id, TRUE);
2289 anjuta_plugin_remove_watch (plugin, ba_plugin->pm_watch_id, TRUE);
2290 anjuta_plugin_remove_watch (plugin, ba_plugin->project_watch_id, TRUE);
2291 anjuta_plugin_remove_watch (plugin, ba_plugin->editor_watch_id, TRUE);
2293 /* Remove UI */
2294 anjuta_ui_unmerge (ui, ba_plugin->build_merge_id);
2296 /* Remove action group */
2297 anjuta_ui_remove_action_group (ui, ba_plugin->build_action_group);
2298 anjuta_ui_remove_action_group (ui, ba_plugin->build_popup_action_group);
2299 return TRUE;
2302 static void
2303 dispose (GObject *obj)
2305 G_OBJECT_CLASS (parent_class)->dispose (obj);
2308 static void
2309 finalize (GObject *obj)
2311 gint i;
2312 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (obj);
2314 for (i = 0; i < IANJUTA_BUILDABLE_N_COMMANDS; i++)
2316 g_free (ba_plugin->commands[i]);
2317 ba_plugin->commands[i] = NULL;
2320 g_free (ba_plugin->fm_current_filename);
2321 g_free (ba_plugin->pm_current_filename);
2322 g_free (ba_plugin->project_root_dir);
2323 g_free (ba_plugin->current_editor_filename);
2324 g_free (ba_plugin->program_args);
2325 g_free (ba_plugin->configure_args);
2327 ba_plugin->fm_current_filename = NULL;
2328 ba_plugin->pm_current_filename = NULL;
2329 ba_plugin->project_root_dir = NULL;
2330 ba_plugin->current_editor_filename = NULL;
2331 ba_plugin->program_args = NULL;
2332 ba_plugin->configure_args = NULL;
2334 G_OBJECT_CLASS (parent_class)->finalize (obj);
2337 static void
2338 basic_autotools_plugin_instance_init (GObject *obj)
2340 gint i;
2341 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (obj);
2343 for (i = 0; i < IANJUTA_BUILDABLE_N_COMMANDS; i++)
2344 ba_plugin->commands[i] = NULL;
2346 ba_plugin->fm_current_filename = NULL;
2347 ba_plugin->pm_current_filename = NULL;
2348 ba_plugin->project_root_dir = NULL;
2349 ba_plugin->current_editor = NULL;
2350 ba_plugin->current_editor_filename = NULL;
2351 ba_plugin->contexts_pool = NULL;
2352 ba_plugin->configure_args = NULL;
2353 ba_plugin->program_args = NULL;
2354 ba_plugin->run_in_terminal = TRUE;
2355 ba_plugin->last_exec_uri = NULL;
2356 ba_plugin->editors_created = g_hash_table_new (g_direct_hash,
2357 g_direct_equal);
2360 static void
2361 basic_autotools_plugin_class_init (GObjectClass *klass)
2363 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
2365 parent_class = g_type_class_peek_parent (klass);
2367 plugin_class->activate = activate_plugin;
2368 plugin_class->deactivate = deactivate_plugin;
2369 klass->dispose = dispose;
2370 klass->finalize = finalize;
2373 #if 0
2374 static void
2375 ibuildable_compile (IAnjutaBuildable *manager, const gchar * filename,
2376 GError **err)
2378 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2379 build_compile_file_real (plugin, filename);
2381 #endif
2383 static void
2384 ibuildable_set_command (IAnjutaBuildable *manager,
2385 IAnjutaBuildableCommand command_id,
2386 const gchar *command_override, GError **err)
2388 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2389 if (plugin->commands[command_id])
2390 g_free (plugin->commands[command_id]);
2391 plugin->commands[command_id] = g_strdup (command_override);
2394 static void
2395 ibuildable_reset_commands (IAnjutaBuildable *manager, GError **err)
2397 gint i;
2398 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2400 for (i = 0; i < IANJUTA_BUILDABLE_N_COMMANDS; i++)
2402 g_free (ba_plugin->commands[i]);
2403 ba_plugin->commands[i] = NULL;
2407 static const gchar *
2408 ibuildable_get_command (IAnjutaBuildable *manager,
2409 IAnjutaBuildableCommand command_id,
2410 GError **err)
2412 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2413 return plugin->commands[command_id];
2416 static void
2417 ibuildable_build (IAnjutaBuildable *manager, const gchar *directory,
2418 GError **err)
2420 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2421 build_execute_command (plugin, directory,
2422 CHOOSE_COMMAND (plugin, BUILD),
2423 TRUE, NULL);
2426 static void
2427 ibuildable_clean (IAnjutaBuildable *manager, const gchar *directory,
2428 GError **err)
2430 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2431 build_execute_command (plugin, directory,
2432 CHOOSE_COMMAND (plugin, CLEAN),
2433 FALSE, NULL);
2436 static void
2437 ibuildable_install (IAnjutaBuildable *manager, const gchar *directory,
2438 GError **err)
2440 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2441 gchar* root = get_root_install_command(plugin);
2442 gchar* command = g_strdup_printf ("%s %s", root,
2443 CHOOSE_COMMAND (plugin, INSTALL));
2444 g_free(root);
2445 build_execute_command (plugin, directory, command, TRUE, NULL);
2446 g_free(command);
2449 static void
2450 ibuildable_configure (IAnjutaBuildable *manager, const gchar *directory,
2451 GError **err)
2453 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2454 build_execute_command (plugin, directory,
2455 CHOOSE_COMMAND (plugin, CONFIGURE),
2456 TRUE, NULL);
2459 static void
2460 ibuildable_generate (IAnjutaBuildable *manager, const gchar *directory,
2461 GError **err)
2463 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2464 if (directory_has_file (plugin->project_root_dir, "autogen.sh"))
2466 build_execute_command (plugin, directory,
2467 CHOOSE_COMMAND (plugin, GENERATE),
2468 FALSE, NULL);
2470 else
2472 /* FIXME: get override command for this too */
2473 build_execute_command (plugin, directory,
2474 "autoreconf -i --force",
2475 FALSE, NULL);
2479 static void
2480 ibuildable_execute (IAnjutaBuildable *manager, const gchar *uri,
2481 GError **err)
2483 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2484 if (uri && strlen (uri) > 0)
2485 execute_program (plugin, uri);
2486 else
2487 execute_program (plugin, NULL);
2490 static void
2491 ibuildable_iface_init (IAnjutaBuildableIface *iface)
2493 /* iface->compile = ibuildable_compile; */
2494 iface->set_command = ibuildable_set_command;
2495 iface->get_command = ibuildable_get_command;
2496 iface->reset_commands = ibuildable_reset_commands;
2497 iface->build = ibuildable_build;
2498 iface->clean = ibuildable_clean;
2499 iface->install = ibuildable_install;
2500 iface->configure = ibuildable_configure;
2501 iface->generate = ibuildable_generate;
2502 iface->execute = ibuildable_execute;
2505 static void
2506 ifile_open (IAnjutaFile *manager, const gchar *uri,
2507 GError **err)
2509 ianjuta_buildable_execute (IANJUTA_BUILDABLE (manager), uri, NULL);
2512 static gchar*
2513 ifile_get_uri (IAnjutaFile *manager, GError **err)
2515 DEBUG_PRINT ("Unsupported operation");
2516 return NULL;
2519 static void
2520 ifile_iface_init (IAnjutaFileIface *iface)
2522 iface->open = ifile_open;
2523 iface->get_uri = ifile_get_uri;
2527 /* IAnjutaBuilder implementation
2528 *---------------------------------------------------------------------------*/
2530 static IAnjutaBuilderHandle
2531 ibuilder_is_built (IAnjutaBuilder *builder, const gchar *uri,
2532 IAnjutaBuilderCallback callback, gpointer user_data,
2533 GError **err)
2535 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
2536 BuildContext *context;
2537 gchar *filename;
2538 gchar *target;
2539 gchar *dirname;
2540 gchar *cmd;
2542 filename = gnome_vfs_get_local_path_from_uri (uri);
2543 if (filename == NULL) return NULL;
2544 target = g_path_get_basename (filename);
2545 dirname = g_path_get_dirname (filename);
2546 g_free (filename);
2547 cmd = g_strconcat (CHOOSE_COMMAND (plugin, IS_BUILT), " ", target, NULL);
2548 g_free (target);
2550 context = build_execute_command_full (plugin, dirname, cmd,
2551 TRUE, FALSE, NULL,
2552 callback, user_data, err);
2553 g_free (cmd);
2554 g_free (dirname);
2556 return (IAnjutaBuilderHandle)context;
2559 static IAnjutaBuilderHandle
2560 ibuilder_build (IAnjutaBuilder *builder, const gchar *uri,
2561 IAnjutaBuilderCallback callback, gpointer user_data,
2562 GError **err)
2564 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
2565 BuildContext *context;
2566 gchar *filename;
2567 gchar *target;
2568 gchar *dirname;
2569 gchar *cmd;
2571 filename = gnome_vfs_get_local_path_from_uri (uri);
2572 if (filename == NULL) return NULL;
2573 target = g_path_get_basename (filename);
2574 dirname = g_path_get_dirname (filename);
2575 g_free (filename);
2576 cmd = g_strconcat (CHOOSE_COMMAND (plugin, BUILD), " ", target, NULL);
2577 g_free (target);
2579 context = build_execute_command_full (plugin, dirname, cmd,
2580 TRUE, TRUE, NULL,
2581 callback, user_data, err);
2583 g_free (cmd);
2584 g_free (dirname);
2586 return (IAnjutaBuilderHandle)context;
2589 static void
2590 ibuilder_cancel (IAnjutaBuilder *builder, IAnjutaBuilderHandle handle, GError **err)
2592 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
2594 build_cancel_command (plugin, (BuildContext *)handle, err);
2597 static void
2598 ibuilder_iface_init (IAnjutaBuilderIface *iface)
2600 iface->is_built = ibuilder_is_built;
2601 iface->build = ibuilder_build;
2602 iface->cancel = ibuilder_cancel;
2605 /* IAnjutaPreferences implementation
2606 *---------------------------------------------------------------------------*/
2608 static GladeXML *gxml;
2610 static void
2611 ipreferences_merge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
2613 GtkWidget *root_check;
2614 GtkWidget *sb_check;
2615 GtkWidget *entry;
2616 GtkWidget *sb_entry;
2618 /* Create the preferences page */
2619 gxml = glade_xml_new (GLADE_FILE, "preferences_dialog_build", NULL);
2620 root_check = glade_xml_get_widget(gxml, CHECK_BUTTON);
2621 sb_check = glade_xml_get_widget(gxml, SB_CHECK);
2622 entry = glade_xml_get_widget(gxml, ENTRY);
2623 sb_entry = glade_xml_get_widget(gxml, SB_ENTRY);
2625 g_signal_connect(G_OBJECT(root_check), "toggled", G_CALLBACK(on_root_check_toggled), entry);
2626 g_signal_connect(G_OBJECT(sb_check), "toggled", G_CALLBACK(on_sb_check_toggled), sb_entry);
2629 anjuta_preferences_add_page (prefs, gxml, "Build", _("Build Autotools"), ICON_FILE);
2632 static void
2633 ipreferences_unmerge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
2635 GtkWidget *root_check;
2636 GtkWidget *sb_check;
2637 GtkWidget *entry;
2638 GtkWidget *sb_entry;
2640 root_check = glade_xml_get_widget(gxml, CHECK_BUTTON);
2641 sb_check = glade_xml_get_widget(gxml, SB_CHECK);
2642 entry = glade_xml_get_widget(gxml, ENTRY);
2643 sb_entry = glade_xml_get_widget(gxml, SB_ENTRY);
2644 g_signal_handlers_disconnect_by_func(G_OBJECT(root_check),
2645 G_CALLBACK(on_root_check_toggled), entry);
2646 g_signal_handlers_disconnect_by_func(G_OBJECT(root_check),
2647 G_CALLBACK(on_sb_check_toggled), sb_entry);
2649 anjuta_preferences_remove_page(prefs, _("Build Autotools"));
2651 g_object_unref (gxml);
2654 static void
2655 ipreferences_iface_init(IAnjutaPreferencesIface* iface)
2657 iface->merge = ipreferences_merge;
2658 iface->unmerge = ipreferences_unmerge;
2661 ANJUTA_PLUGIN_BEGIN (BasicAutotoolsPlugin, basic_autotools_plugin);
2662 ANJUTA_PLUGIN_ADD_INTERFACE (ibuilder, IANJUTA_TYPE_BUILDER);
2663 ANJUTA_PLUGIN_ADD_INTERFACE (ibuildable, IANJUTA_TYPE_BUILDABLE);
2664 ANJUTA_PLUGIN_ADD_INTERFACE (ifile, IANJUTA_TYPE_FILE);
2665 ANJUTA_PLUGIN_ADD_INTERFACE (ipreferences, IANJUTA_TYPE_PREFERENCES);
2666 ANJUTA_PLUGIN_END;
2668 ANJUTA_SIMPLE_PLUGIN (BasicAutotoolsPlugin, basic_autotools_plugin);