* plugins/build-basic-autotools/build-basic-autotools.c,
[anjuta-git-plugin.git] / plugins / build-basic-autotools / build-basic-autotools.c
blob12c58d46b1a19ef723d477b1e129fee1d06d98a9
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 <glib/gstdio.h>
25 #include <gio/gio.h>
26 #include <libanjuta/anjuta-shell.h>
27 #include <libanjuta/anjuta-launcher.h>
28 #include <libanjuta/anjuta-utils.h>
29 #include <libanjuta/anjuta-debug.h>
30 #include <libanjuta/anjuta-plugin-manager.h>
31 #include <libanjuta/interfaces/ianjuta-file.h>
32 #include <libanjuta/interfaces/ianjuta-file-manager.h>
33 #include <libanjuta/interfaces/ianjuta-project-manager.h>
34 #include <libanjuta/interfaces/ianjuta-file-loader.h>
35 #include <libanjuta/interfaces/ianjuta-buildable.h>
36 #include <libanjuta/interfaces/ianjuta-builder.h>
37 #include <libanjuta/interfaces/ianjuta-environment.h>
38 #include <libanjuta/interfaces/ianjuta-message-manager.h>
39 #include <libanjuta/interfaces/ianjuta-document-manager.h>
40 #include <libanjuta/interfaces/ianjuta-file-savable.h>
41 #include <libanjuta/interfaces/ianjuta-indicable.h>
42 #include <libanjuta/interfaces/ianjuta-preferences.h>
44 #include "build-basic-autotools.h"
45 #include "build-options.h"
46 #include "executer.h"
48 #include <sys/wait.h>
50 #define ICON_FILE "anjuta-build-basic-autotools-plugin-48.png"
51 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-build-basic-autotools-plugin.ui"
52 #define MAX_BUILD_PANES 3
53 #define PREF_INDICATORS_AUTOMATIC "indicators.automatic"
54 #define PREF_INSTALL_ROOT "build.install.root"
55 #define PREF_INSTALL_ROOT_COMMAND "build.install.root.command"
56 #define PREF_PARALLEL_MAKE "build.parallel.make"
57 #define PREF_PARALLEL_MAKE_JOB "build.parallel.make.job"
58 #define PREF_TRANSLATE_MESSAGE "build.translate.message"
59 #define PREF_CONTINUE_ON_ERROR "build.continue.error"
61 #define BUILD_PREFS_DIALOG "preferences_dialog_build"
62 #define BUILD_PREFS_ROOT "preferences_build_container"
63 #define INSTALL_ROOT_CHECK "preferences_toggle:bool:0:0:build.install.root"
64 #define INSTALL_ROOT_ENTRY "preferences_entry:text:sudo:0:build.install.root.command"
65 #define PARALLEL_MAKE_CHECK "preferences_toggle:bool:0:0:build.parallel.make"
66 #define PARALLEL_MAKE_SPIN "preferences_spin:int:1:0:build.parallel.make.job"
68 #define DEFAULT_COMMAND_COMPILE "make"
69 #define DEFAULT_COMMAND_BUILD "make"
70 #define DEFAULT_COMMAND_IS_BUILT "make -q"
71 #define DEFAULT_COMMAND_BUILD_TARBALL "make dist"
72 #define DEFAULT_COMMAND_INSTALL "make install"
73 #define DEFAULT_COMMAND_CONFIGURE "configure"
74 #define DEFAULT_COMMAND_GENERATE "autogen.sh"
75 #define DEFAULT_COMMAND_CLEAN "make clean"
76 #define DEFAULT_COMMAND_DISTCLEAN "make distclean"
77 #define DEFAULT_COMMAND_AUTORECONF "autoreconf -i --force"
79 #define CHOOSE_COMMAND(plugin,command) \
80 ((plugin->commands[(IANJUTA_BUILDABLE_COMMAND_##command)]) ? \
81 (plugin->commands[(IANJUTA_BUILDABLE_COMMAND_##command)]) \
82 : \
83 (DEFAULT_COMMAND_##command))
85 static gpointer parent_class;
87 typedef struct
89 gchar *pattern;
90 int options;
91 gchar *replace;
92 GRegex *regex;
93 } BuildPattern;
95 typedef struct
97 gchar *project_dir;
98 gchar *build_dir;
99 gchar **argv;
100 GtkWindow *parent;
101 } BuildLinkCommand;
103 typedef struct
105 gchar *pattern;
106 GRegex *regex;
107 GRegex *local_regex;
108 } MessagePattern;
110 typedef struct
112 gchar *filename;
113 gint line;
114 IAnjutaIndicableIndicator indicator;
115 } BuildIndicatorLocation;
117 /* Command processing */
118 typedef struct
120 AnjutaPlugin *plugin;
122 AnjutaLauncher *launcher;
123 gboolean used;
125 IAnjutaBuilderCallback callback;
126 gpointer user_data;
128 IAnjutaMessageView *message_view;
129 GHashTable *build_dir_stack;
131 /* Indicator locations */
132 GSList *locations;
134 /* Editors in which indicators have been updated */
135 GHashTable *indicators_updated_editors;
137 /* Environment */
138 IAnjutaEnvironment *environment;
139 } BuildContext;
141 /* Declarations */
142 static void update_project_ui (BasicAutotoolsPlugin *bb_plugin);
143 static gboolean directory_has_file (const gchar *dirname, const gchar *filename);
145 static GList *patterns_list = NULL;
147 /* The translations should match that of 'make' program. Both strings uses
148 * pearl regular expression
149 * 2 similar strings are used in order to parse the output of 2 different
150 * version of make if necessary. If you update one string, move the first
151 * string into the second slot and then replace the first string only. */
152 static MessagePattern patterns_make_entering[] = {{N_("make(\\[\\d+\\])?:\\s+Entering\\s+directory\\s+`(.+)'"), NULL, NULL},
153 {N_("make(\\[\\d+\\])?:\\s+Entering\\s+directory\\s+'(.+)'"), NULL, NULL},
154 {NULL, NULL, NULL}};
156 /* The translations should match that of 'make' program. Both strings uses
157 * pearl regular expression
158 * 2 similar strings are used in order to parse the output of 2 different
159 * version of make if necessary. If you update one string, move the first
160 * string into the second slot and then replace the first string only. */
161 static MessagePattern patterns_make_leaving[] = {{N_("make(\\[\\d+\\])?:\\s+Leaving\\s+directory\\s+`(.+)'"), NULL, NULL},
162 {N_("make(\\[\\d+\\])?:\\s+Leaving\\s+directory\\s+'(.+)'"), NULL, NULL},
163 {NULL, NULL, NULL}};
165 /* Helper functions
166 *---------------------------------------------------------------------------*/
168 static gchar*
169 build_shell_expand (const gchar *input)
171 GString* expand;
173 if (input == NULL) return NULL;
175 expand = g_string_sized_new (strlen (input));
177 for (; *input != '\0'; input++)
179 switch (*input)
181 case '$':
183 /* Variable expansion */
184 const gchar *end;
185 gint var_name_len;
187 end = input + 1;
188 while (isalnum (*end) || (*end == '_')) end++;
189 var_name_len = end - input - 1;
190 if (var_name_len > 0)
192 const gchar *value;
194 g_string_append_len (expand, input + 1, var_name_len);
195 value = g_getenv (expand->str + expand->len - var_name_len);
196 g_string_truncate (expand, expand->len - var_name_len);
197 g_string_append (expand, value);
198 input = end - 1;
199 continue;
201 break;
203 case '~':
205 /* User home directory expansion */
206 if (isspace(input[1]) || (input[1] == G_DIR_SEPARATOR) || (input[1] == '\0'))
208 g_string_append (expand, g_get_home_dir());
209 continue;
211 break;
213 default:
214 break;
216 g_string_append_c (expand, *input);
219 return g_string_free (expand, FALSE);
222 static gchar **
223 build_argv_command (const gchar *cmd_dir, const gchar *cmd, gchar **argv)
225 gchar **new_cmd;
226 gchar **split_cmd;
227 guint split_len;
229 split_cmd = g_strsplit (cmd, " ", 2);
230 split_len = g_strv_length (split_cmd);
232 if (argv == NULL)
234 new_cmd = split_cmd;
236 else
238 guint argv_len;
240 argv_len = g_strv_length (argv);
241 new_cmd = g_new (gchar *, split_len + argv_len + 1);
242 memcpy (new_cmd, split_cmd, split_len * sizeof (gchar *));
243 g_free (split_cmd);
244 memcpy (new_cmd + split_len, argv, (argv_len + 1) * sizeof (gchar *));
245 g_free (argv);
248 if (cmd_dir != NULL)
250 gchar *cmd = new_cmd[0];
252 new_cmd[0] = g_strconcat (cmd_dir, G_DIR_SEPARATOR_S, cmd, NULL);
253 g_free (cmd);
256 return new_cmd;
259 static gchar **
260 build_add_env_variable (gchar **envp, const gchar *name, const gchar *value)
262 gchar **var;
263 guint len = 0;
265 if (envp != NULL)
267 /* Look for an already existing variable */
268 for (var = envp; *var != NULL; var++)
270 if (strcmp (*var, name) == 0)
272 /* Just update variable */
273 if (value == NULL)
275 *var[strlen(name)] = '\0';
277 else
279 g_free (*var);
280 *var = g_strconcat (name, "=", value, NULL);
283 return envp;
286 len = var - envp;
289 /* Need to create a new variable */
290 var = g_new (gchar *, len + 2);
291 *var = g_strconcat (name, value == NULL ? NULL : "=", value, NULL);
292 if (envp != NULL)
294 memcpy (&var[1], envp, len * sizeof (gchar *));
295 g_free (envp);
297 var[len + 1] = NULL;
299 return var;
302 static gchar **
303 build_add_arg (gchar **argv, const gchar *argument)
305 gchar **new_argv;
306 guint len;
308 len = g_strv_length (argv);
310 /* Need to create a new variable */
311 new_argv = g_new (gchar *, len + 2);
312 new_argv[0] = argv[0];
313 new_argv[1] = g_strdup (argument);
314 memcpy (&new_argv[2], &argv[1], len * sizeof (gchar *));
315 g_free (argv);
317 return new_argv;
320 /* Allow installation as root (#321455) */
321 static void on_root_check_toggled(GtkWidget* toggle_button, GtkWidget* entry)
323 gtk_widget_set_sensitive(entry,
324 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
327 static gchar*
328 get_root_install_command(BasicAutotoolsPlugin *bplugin)
330 AnjutaPlugin* plugin = ANJUTA_PLUGIN(bplugin);
331 AnjutaPreferences* prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
332 if (anjuta_preferences_get_int (prefs , PREF_INSTALL_ROOT))
334 gchar* command = anjuta_preferences_get(prefs, PREF_INSTALL_ROOT_COMMAND);
335 if (command != NULL)
336 return command;
337 else
338 return g_strdup("");
340 else
341 return g_strdup("");
344 /* Indicator locations reported by the build */
346 static BuildIndicatorLocation*
347 build_indicator_location_new (const gchar *filename, gint line,
348 IAnjutaIndicableIndicator indicator)
350 BuildIndicatorLocation *loc = g_new0 (BuildIndicatorLocation, 1);
351 loc->filename = g_strdup (filename);
352 loc->line = line;
353 loc->indicator = indicator;
354 return loc;
357 static void
358 build_indicator_location_set (BuildIndicatorLocation *loc,
359 IAnjutaEditor *editor,
360 const gchar *editor_filename)
362 IAnjutaIterable *line_start, *line_end;
364 if (editor && editor_filename &&
365 IANJUTA_IS_INDICABLE (editor) &&
366 IANJUTA_IS_EDITOR (editor) &&
367 strcmp (editor_filename, loc->filename) == 0)
369 DEBUG_PRINT ("loc line: %d", loc->line);
371 line_start = ianjuta_editor_get_line_begin_position (editor,
372 loc->line, NULL);
374 line_end = ianjuta_editor_get_line_end_position (editor,
375 loc->line, NULL);
376 ianjuta_indicable_set (IANJUTA_INDICABLE (editor),
377 line_start, line_end, loc->indicator,
378 NULL);
380 g_object_unref (line_start);
381 g_object_unref (line_end);
385 static void
386 build_indicator_location_free (BuildIndicatorLocation *loc)
388 g_free (loc->filename);
389 g_free (loc);
392 /* Build context */
394 static void
395 build_context_stack_destroy (gpointer value)
397 GSList *slist = (GSList *)value;
398 if (slist)
400 g_slist_foreach (slist, (GFunc)g_free, NULL);
401 g_slist_free (slist);
405 static void
406 build_context_push_dir (BuildContext *context, const gchar *key,
407 const gchar *dir)
409 GSList *dir_stack;
411 if (context->build_dir_stack == NULL)
413 context->build_dir_stack =
414 g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
415 build_context_stack_destroy);
417 dir_stack = g_hash_table_lookup (context->build_dir_stack, key);
418 if (dir_stack)
419 g_hash_table_steal (context->build_dir_stack, key);
421 dir_stack = g_slist_prepend (dir_stack, g_strdup (dir));
422 g_hash_table_insert (context->build_dir_stack, (gpointer)key, dir_stack);
425 static void
426 build_context_pop_dir (BuildContext *context, const gchar *key,
427 const gchar *dir)
429 GSList *dir_stack;
430 gchar *top_dir;
432 if (context->build_dir_stack == NULL)
433 return;
434 dir_stack = g_hash_table_lookup (context->build_dir_stack, key);
435 if (dir_stack == NULL)
436 return;
438 g_hash_table_steal (context->build_dir_stack, key);
439 top_dir = dir_stack->data;
440 dir_stack = g_slist_remove (dir_stack, top_dir);
442 if (strcmp (top_dir, dir) != 0)
444 DEBUG_PRINT("Directory stack misaligned!!");
446 g_free (top_dir);
447 if (dir_stack)
448 g_hash_table_insert (context->build_dir_stack, (gpointer)key, dir_stack);
451 static const gchar *
452 build_context_get_dir (BuildContext *context, const gchar *key)
454 GSList *dir_stack;
456 if (context->build_dir_stack == NULL)
457 return NULL;
458 dir_stack = g_hash_table_lookup (context->build_dir_stack, key);
459 if (dir_stack == NULL)
460 return NULL;
462 return dir_stack->data;
465 static gboolean
466 build_context_destroy_command (BuildContext *context)
468 if (context->used) return FALSE;
469 if (context->callback)
471 GError *err;
473 /* Emit command-finished signal abort */
474 err = g_error_new_literal (ianjuta_builder_error_quark (),
475 IANJUTA_BUILDER_ABORTED,
476 _("Command aborted"));
477 context->callback (G_OBJECT (context->plugin), context, err, context->user_data);
478 g_error_free (err);
479 context->callback = NULL;
482 if (context->launcher)
484 g_object_unref (context->launcher);
485 context->launcher = NULL;
488 if (context->environment)
490 g_object_unref (context->environment);
491 context->environment = NULL;
494 /* Empty context, remove from pool */
495 if (context->message_view == NULL)
497 ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool =
498 g_list_remove (ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool,
499 context);
500 g_free (context);
502 return TRUE;
504 else
506 return FALSE;
510 static gboolean
511 build_context_destroy_view (BuildContext *context)
513 if (context->message_view)
515 gtk_widget_destroy (GTK_WIDGET (context->message_view));
516 context->message_view = NULL;
519 if (context->build_dir_stack)
521 g_hash_table_destroy (context->build_dir_stack);
522 context->build_dir_stack = NULL;
524 if (context->indicators_updated_editors)
526 g_hash_table_destroy (context->indicators_updated_editors);
527 context->indicators_updated_editors = NULL;
530 g_slist_foreach (context->locations, (GFunc) build_indicator_location_free,
531 NULL);
532 g_slist_free (context->locations);
533 context->locations = NULL;
535 /* Empty context, remove from pool */
536 if (context->launcher == NULL)
538 ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool =
539 g_list_remove (ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool,
540 context);
541 g_free (context);
543 return TRUE;
545 else
547 return FALSE;
551 static void
552 build_context_destroy (BuildContext *context)
554 if (build_context_destroy_command (context))
556 build_context_destroy_view (context);
560 static void
561 build_context_reset (BuildContext *context)
563 /* Reset context */
565 ianjuta_message_view_clear (context->message_view, NULL);
567 if (context->build_dir_stack)
568 g_hash_table_destroy (context->build_dir_stack);
569 context->build_dir_stack = NULL;
571 g_slist_foreach (context->locations,
572 (GFunc) build_indicator_location_free, NULL);
573 g_slist_free (context->locations);
574 context->locations = NULL;
577 static void
578 build_regex_load ()
580 FILE *fp;
582 if (patterns_list)
583 return;
585 fp = fopen (PACKAGE_DATA_DIR"/build/automake-c.filters", "r");
586 if (fp == NULL)
588 DEBUG_PRINT ("Failed to load filters: %s",
589 PACKAGE_DATA_DIR"/build/automake-c.filters");
590 return;
592 while (!feof (fp) && !ferror (fp))
594 char buffer[1024];
595 gchar **tokens;
596 BuildPattern *pattern;
598 fgets (buffer, 1024, fp);
599 if (ferror (fp))
600 break;
601 tokens = g_strsplit (buffer, "|||", 3);
603 if (!tokens[0] || !tokens[1])
605 DEBUG_PRINT ("Cannot parse regex: %s", buffer);
606 g_strfreev (tokens);
607 continue;
609 pattern = g_new0 (BuildPattern, 1);
610 pattern->pattern = g_strdup (tokens[0]);
611 pattern->replace = g_strdup (tokens[1]);
612 if (tokens[2])
613 pattern->options = atoi (tokens[2]);
614 g_strfreev (tokens);
616 patterns_list = g_list_prepend (patterns_list, pattern);
618 patterns_list = g_list_reverse (patterns_list);
621 static void
622 build_regex_init_message (MessagePattern *patterns)
624 g_return_if_fail (patterns != NULL);
626 if (patterns->regex != NULL)
627 return; /* Already done */
629 for (;patterns->pattern != NULL; patterns++)
631 /* Untranslated string */
632 patterns->regex = g_regex_new(
633 patterns->pattern,
636 NULL);
638 /* Translated string */
639 patterns->local_regex = g_regex_new(
640 _(patterns->pattern),
643 NULL);
647 static void
648 build_regex_init ()
650 GList *node;
651 GError *error = NULL;
653 build_regex_init_message (patterns_make_entering);
655 build_regex_init_message (patterns_make_leaving);
657 build_regex_load ();
658 if (!patterns_list)
659 return;
661 if (((BuildPattern*)(patterns_list->data))->regex)
662 return;
664 node = patterns_list;
665 while (node)
667 BuildPattern *pattern;
669 pattern = node->data;
670 pattern->regex =
671 g_regex_new(
672 pattern->pattern,
673 pattern->options,
675 &error); /* for error message */
676 if (error != NULL) {
677 DEBUG_PRINT ("GRegex compilation failed: pattern \"%s\": error %s",
678 pattern->pattern, error->message);
679 g_error_free (error);
681 node = g_list_next (node);
685 /* Regex processing */
686 static gchar*
687 build_get_summary (const gchar *details, BuildPattern* bp)
689 gboolean matched;
690 GMatchInfo *match_info;
691 const gchar *iter;
692 GString *ret;
693 gchar *final = NULL;
695 if (!bp || !bp->regex)
696 return NULL;
698 matched = g_regex_match(
699 bp->regex, /* result of g_regex_new() */
700 details, /* the subject string */
702 &match_info);
704 if (matched)
706 ret = g_string_new ("");
707 iter = bp->replace;
708 while (*iter != '\0')
710 if (*iter == '\\' && isdigit(*(iter + 1)))
712 char temp[2] = {0, 0};
713 gint start_pos, end_pos;
715 temp[0] = *(iter + 1);
716 int idx = atoi (temp);
718 g_match_info_fetch_pos (match_info, idx, &start_pos, &end_pos);
720 ret = g_string_append_len (ret, details + start_pos,
721 end_pos - start_pos);
722 iter += 2;
724 else
726 const gchar *start;
727 const gchar *end;
729 start = iter;
730 iter = g_utf8_next_char (iter);
731 end = iter;
733 ret = g_string_append_len (ret, start, end - start);
737 final = g_string_free (ret, FALSE);
738 if (strlen (final) <= 0) {
739 g_free (final);
740 final = NULL;
743 g_match_info_free (match_info);
745 return final;
748 static void
749 on_build_mesg_arrived (AnjutaLauncher *launcher,
750 AnjutaLauncherOutputType output_type,
751 const gchar * mesg, gpointer user_data)
753 BuildContext *context = (BuildContext*)user_data;
754 /* Message view could have been destroyed */
755 if (context->message_view)
756 ianjuta_message_view_buffer_append (context->message_view, mesg, NULL);
759 static gboolean
760 parse_error_line (const gchar * line, gchar ** filename, int *lineno)
762 gint i = 0;
763 gint j = 0;
764 gint k = 0;
765 gchar *dummy;
767 while (line[i++] != ':')
769 if (i >= strlen (line) || i >= 512 || line[i - 1] == ' ')
771 goto down;
774 if (isdigit (line[i]))
776 j = i;
777 while (isdigit (line[i++])) ;
778 dummy = g_strndup (&line[j], i - j - 1);
779 *lineno = atoi (dummy);
780 if (dummy)
781 g_free (dummy);
782 dummy = g_strndup (line, j - 1);
783 *filename = g_strdup (g_strstrip (dummy));
784 if (dummy)
785 g_free (dummy);
786 return TRUE;
789 down:
790 i = strlen (line) - 1;
791 while (isspace (line[i]) == FALSE)
793 i--;
794 if (i < 0)
796 *filename = NULL;
797 *lineno = 0;
798 return FALSE;
801 k = i++;
802 while (line[i++] != ':')
804 if (i >= strlen (line) || i >= 512 || line[i - 1] == ' ')
806 *filename = NULL;
807 *lineno = 0;
808 return FALSE;
811 if (isdigit (line[i]))
813 j = i;
814 while (isdigit (line[i++])) ;
815 dummy = g_strndup (&line[j], i - j - 1);
816 *lineno = atoi (dummy);
817 if (dummy)
818 g_free (dummy);
819 dummy = g_strndup (&line[k], j - k - 1);
820 *filename = g_strdup (g_strstrip (dummy));
821 if (dummy)
822 g_free (dummy);
823 return TRUE;
825 *lineno = 0;
826 *filename = NULL;
827 return FALSE;
830 static void
831 on_build_mesg_format (IAnjutaMessageView *view, const gchar *one_line,
832 BuildContext *context)
834 gchar *dummy_fn, *line;
835 gint dummy_int;
836 IAnjutaMessageViewType type;
837 GList *node;
838 gchar *summary = NULL;
839 gchar *freeptr = NULL;
840 BasicAutotoolsPlugin *p = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin);
841 gboolean matched;
842 GMatchInfo *match_info;
843 MessagePattern *pat;
845 g_return_if_fail (one_line != NULL);
847 /* Check if make enter a new directory */
848 matched = FALSE;
849 for (pat = patterns_make_entering; pat->pattern != NULL; pat++)
851 matched = g_regex_match(
852 pat->regex,
853 one_line,
855 &match_info);
856 if (matched) break;
857 g_match_info_free (match_info);
858 matched = g_regex_match(
859 pat->local_regex,
860 one_line,
862 &match_info);
863 if (matched) break;
864 g_match_info_free (match_info);
866 if (matched)
868 gchar *dir;
869 gchar *summary;
871 dir = g_match_info_fetch (match_info, 2);
872 dir = context->environment ? ianjuta_environment_get_real_directory(context->environment, dir, NULL)
873 : dir;
874 build_context_push_dir (context, "default", dir);
875 summary = g_strdup_printf(_("Entering: %s"), dir);
876 ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_NORMAL,
877 summary, one_line, NULL);
878 g_free (dir);
879 g_free(summary);
880 g_match_info_free (match_info);
883 /* Check if make leave a directory */
884 matched = FALSE;
885 for (pat = patterns_make_leaving; pat->pattern != NULL; pat++)
887 matched = g_regex_match(
888 pat->regex,
889 one_line,
891 &match_info);
892 if (matched) break;
893 g_match_info_free (match_info);
894 matched = g_regex_match(
895 pat->local_regex,
896 one_line,
898 &match_info);
899 if (matched) break;
900 g_match_info_free (match_info);
902 if (matched)
904 gchar *dir;
905 gchar *summary;
907 dir = g_match_info_fetch (match_info, 2);
908 dir = context->environment ? ianjuta_environment_get_real_directory(context->environment, dir, NULL)
909 : dir;
910 build_context_pop_dir (context, "default", dir);
911 summary = g_strdup_printf(_("Leaving: %s"), dir);
912 ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_NORMAL,
913 summary, one_line, NULL);
914 g_free (dir);
915 g_free(summary);
916 g_match_info_free (match_info);
919 /* Save freeptr so that we can free the copied string */
920 line = freeptr = g_strdup (one_line);
922 g_strchug(line); /* Remove leading whitespace */
923 if (g_str_has_prefix(line, "if ") == TRUE)
925 char *end;
926 line = line + 3;
928 /* Find the first occurence of ';' (ignoring nesting in quotations) */
929 end = strchr(line, ';');
930 if (end)
932 *end = '\0';
936 type = IANJUTA_MESSAGE_VIEW_TYPE_NORMAL;
937 if (parse_error_line(line, &dummy_fn, &dummy_int))
939 gchar *start_str, *end_str, *mid_str;
940 BuildIndicatorLocation *loc;
941 IAnjutaIndicableIndicator indicator;
943 if ((strstr (line, "warning:") != NULL) ||
944 (strstr (line, _("warning:")) != NULL))
946 type = IANJUTA_MESSAGE_VIEW_TYPE_WARNING;
947 indicator = IANJUTA_INDICABLE_WARNING;
949 else
951 type = IANJUTA_MESSAGE_VIEW_TYPE_ERROR;
952 indicator = IANJUTA_INDICABLE_CRITICAL;
955 mid_str = strstr (line, dummy_fn);
956 DEBUG_PRINT ("mid_str = %s, line = %s", mid_str, line);
957 start_str = g_strndup (line, mid_str - line);
958 end_str = line + strlen (start_str) + strlen (dummy_fn);
959 DEBUG_PRINT("dummy_fn: %s", dummy_fn);
960 if (g_path_is_absolute(dummy_fn))
962 mid_str = g_strdup(dummy_fn);
964 else
966 mid_str = g_build_filename (build_context_get_dir (context, "default"),
967 dummy_fn, NULL);
969 DEBUG_PRINT ("mid_str: %s", mid_str);
971 if (mid_str)
973 line = g_strconcat (start_str, mid_str, end_str, NULL);
975 /* We sucessfully build an absolute path of the file (mid_str),
976 * so we create an indicator location for it and save it.
977 * Additionally, check of current editor holds this file and if
978 * so, set the indicator.
980 DEBUG_PRINT ("dummy int: %d", dummy_int);
982 loc = build_indicator_location_new (mid_str, dummy_int,
983 indicator);
984 context->locations = g_slist_prepend (context->locations, loc);
986 /* If current editor file is same as indicator file, set indicator */
987 if (anjuta_preferences_get_int (anjuta_shell_get_preferences (context->plugin->shell, NULL), PREF_INDICATORS_AUTOMATIC))
989 build_indicator_location_set (loc, p->current_editor,
990 p->current_editor_filename);
993 else
995 line = g_strconcat (start_str, dummy_fn, end_str, NULL);
997 g_free (start_str);
998 g_free (mid_str);
999 g_free (dummy_fn);
1001 else if (strstr (line, ": ") != NULL)
1003 type = IANJUTA_MESSAGE_VIEW_TYPE_INFO;
1006 node = patterns_list;
1007 while (node)
1009 BuildPattern *pattern = node->data;
1010 summary = build_get_summary (line, pattern);
1011 if (summary)
1012 break;
1013 node = g_list_next (node);
1016 if (summary)
1018 ianjuta_message_view_append (view, type, summary, line, NULL);
1019 g_free (summary);
1021 else
1022 ianjuta_message_view_append (view, type, line, "", NULL);
1023 g_free(freeptr);
1026 static void
1027 on_build_mesg_parse (IAnjutaMessageView *view, const gchar *line,
1028 BuildContext *context)
1030 gchar *filename;
1031 gint lineno;
1032 if (parse_error_line (line, &filename, &lineno))
1034 IAnjutaDocumentManager *docman;
1035 GFile* file;
1037 /* Go to file and line number */
1038 docman = anjuta_shell_get_interface (context->plugin->shell,
1039 IAnjutaDocumentManager,
1040 NULL);
1042 /* Full path is detected from parse_error_line() */
1043 file = g_file_new_for_path(filename);
1044 ianjuta_document_manager_goto_file_line_mark(docman, file, lineno, TRUE, NULL);
1045 g_object_unref (file);
1049 static void
1050 on_build_terminated (AnjutaLauncher *launcher,
1051 gint child_pid, gint status, gulong time_taken,
1052 BuildContext *context)
1054 context->used = FALSE;
1055 if (context->callback != NULL)
1057 GError *err = NULL;
1058 IAnjutaBuilderCallback callback;
1060 if (WIFEXITED (status))
1062 if (WEXITSTATUS (status) != 0)
1064 err = g_error_new (ianjuta_builder_error_quark (),
1065 WEXITSTATUS (status),
1066 _("Command exited with status %d"), WEXITSTATUS (status));
1069 else if (WIFSIGNALED (status))
1071 switch (WTERMSIG (status))
1073 case SIGTERM:
1074 err = g_error_new (ianjuta_builder_error_quark (),
1075 IANJUTA_BUILDER_CANCELED,
1076 _("Command canceled by user"));
1077 break;
1078 case SIGKILL:
1079 err = g_error_new (ianjuta_builder_error_quark (),
1080 IANJUTA_BUILDER_ABORTED,
1081 _("Command aborted by user"));
1082 break;
1083 default:
1084 err = g_error_new (ianjuta_builder_error_quark (),
1085 IANJUTA_BUILDER_INTERRUPTED,
1086 _("Command terminated with signal %d"), WTERMSIG(status));
1087 break;
1090 else
1092 err = g_error_new_literal (ianjuta_builder_error_quark (),
1093 IANJUTA_BUILDER_TERMINATED,
1094 _("Command terminated for an unknown reason"));
1096 callback = context->callback;
1097 context->callback = NULL;
1098 callback (G_OBJECT (context->plugin), context, err, context->user_data);
1100 if (context->used)
1101 return; /* Another command is run */
1103 g_signal_handlers_disconnect_by_func (context->launcher,
1104 G_CALLBACK (on_build_terminated),
1105 context);
1107 /* Message view could have been destroyed before */
1108 if (context->message_view)
1110 gchar *buff1;
1112 buff1 = g_strdup_printf (_("Total time taken: %lu secs\n"),
1113 time_taken);
1114 if (status)
1116 ianjuta_message_view_buffer_append (context->message_view,
1117 _("Completed unsuccessful\n"), NULL);
1119 else
1121 ianjuta_message_view_buffer_append (context->message_view,
1122 _("Completed successful\n"), NULL);
1124 ianjuta_message_view_buffer_append (context->message_view, buff1, NULL);
1125 g_free (buff1);
1127 /* Goto the first error if it exists */
1128 /* if (anjuta_preferences_get_int (ANJUTA_PREFERENCES (app->preferences),
1129 "build.option.gotofirst"))
1130 an_message_manager_next(app->messages);
1133 update_project_ui (ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin));
1135 build_context_destroy_command (context);
1138 static void
1139 on_message_view_destroyed (BuildContext *context, GtkWidget *view)
1141 DEBUG_PRINT ("Destroying build context");
1142 context->message_view = NULL;
1144 build_context_destroy_view (context);
1147 static gboolean
1148 g_hashtable_foreach_true (gpointer key, gpointer value, gpointer user_data)
1150 return TRUE;
1153 static BuildContext*
1154 build_get_context_with_message(BasicAutotoolsPlugin *plugin, const gchar *dir)
1156 IAnjutaMessageManager *mesg_manager;
1157 gchar mname[128];
1158 gchar *subdir;
1159 BuildContext *context = NULL;
1160 static gint message_pane_count = 0;
1162 /* Initialise regex rules */
1163 build_regex_init();
1165 subdir = g_path_get_basename (dir);
1166 /* Translators: the first number is the number of the build attemp,
1167 the string is the directory where the build takes place */
1168 snprintf (mname, 128, _("Build %d: %s"), ++message_pane_count, subdir);
1169 g_free (subdir);
1171 /* If we already have MAX_BUILD_PANES build panes, find a free context */
1172 if (g_list_length (plugin->contexts_pool) >= MAX_BUILD_PANES)
1174 GList *node;
1175 node = plugin->contexts_pool;
1176 while (node)
1178 BuildContext *c;
1179 c = node->data;
1180 if (c->launcher == NULL)
1182 context = c;
1183 break;
1185 node = g_list_next (node);
1189 mesg_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
1190 IAnjutaMessageManager, NULL);
1191 if (context)
1193 build_context_reset (context);
1195 /* It will be re-inserted in right order */
1196 plugin->contexts_pool = g_list_remove (plugin->contexts_pool, context);
1197 ianjuta_message_manager_set_view_title (mesg_manager,
1198 context->message_view,
1199 mname, NULL);
1201 else
1203 /* If no free context found, create one */
1204 context = g_new0 (BuildContext, 1);
1205 context->plugin = ANJUTA_PLUGIN(plugin);
1206 context->indicators_updated_editors =
1207 g_hash_table_new (g_direct_hash, g_direct_equal);
1209 context->message_view =
1210 ianjuta_message_manager_add_view (mesg_manager, mname,
1211 ICON_FILE, NULL);
1212 g_signal_connect (G_OBJECT (context->message_view), "buffer_flushed",
1213 G_CALLBACK (on_build_mesg_format), context);
1214 g_signal_connect (G_OBJECT (context->message_view), "message_clicked",
1215 G_CALLBACK (on_build_mesg_parse), context);
1216 g_object_weak_ref (G_OBJECT (context->message_view),
1217 (GWeakNotify)on_message_view_destroyed, context);
1220 ianjuta_message_manager_set_current_view (mesg_manager,
1221 context->message_view, NULL);
1223 /* Reset indicators in editors */
1224 if (IANJUTA_IS_INDICABLE (plugin->current_editor))
1225 ianjuta_indicable_clear (IANJUTA_INDICABLE (plugin->current_editor),
1226 NULL);
1227 /* This is only since glib 2.12.
1228 g_hash_table_remove_all (context->indicators_updated_editors);
1230 g_hash_table_foreach_remove (context->indicators_updated_editors,
1231 g_hashtable_foreach_true, NULL);
1233 return context;
1236 static BuildContext*
1237 build_get_context (BasicAutotoolsPlugin *plugin, const gchar *dir,
1238 gboolean with_view)
1240 BuildContext *context = NULL;
1241 AnjutaPluginManager *plugin_manager;
1243 if (with_view)
1245 context = build_get_context_with_message (plugin, dir);
1247 else
1249 /* Context without a message view */
1250 context = g_new0 (BuildContext, 1);
1251 DEBUG_PRINT ("new context %p", context);
1252 context->plugin = ANJUTA_PLUGIN(plugin);
1255 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN (plugin)->shell, NULL);
1257 if (context->environment != NULL)
1259 g_object_unref (context->environment);
1261 if (anjuta_plugin_manager_is_active_plugin (plugin_manager, "IAnjutaEnvironment"))
1263 IAnjutaEnvironment *env = IANJUTA_ENVIRONMENT (anjuta_shell_get_object (ANJUTA_PLUGIN (plugin)->shell,
1264 "IAnjutaEnvironment", NULL));
1266 g_object_ref (env);
1267 context->environment = env;
1269 else
1271 context->environment = NULL;
1274 context->callback = NULL;
1275 context->launcher = anjuta_launcher_new ();
1276 g_signal_connect (G_OBJECT (context->launcher), "child-exited",
1277 G_CALLBACK (on_build_terminated), context);
1278 build_context_push_dir (context, "default", dir);
1279 dir = g_strconcat (dir, "/", NULL);
1280 g_chdir (dir);
1282 plugin->contexts_pool = g_list_append (plugin->contexts_pool, context);
1284 return context;
1287 /* Save all current anjuta files */
1288 static void
1289 save_all_files (AnjutaPlugin *plugin)
1291 IAnjutaDocumentManager *docman;
1292 IAnjutaFileSavable* save;
1294 docman = anjuta_shell_get_interface (plugin->shell, IAnjutaDocumentManager, NULL);
1295 /* No document manager, so no file to save */
1296 if (docman != NULL)
1298 save = IANJUTA_FILE_SAVABLE (docman);
1299 if (save) ianjuta_file_savable_save (save, NULL);
1303 static gboolean
1304 build_execute_command_in_context (BuildContext* context, const gchar *dir,
1305 gchar *argv[],
1306 gchar *envp[],
1307 IAnjutaBuilderCallback callback, gpointer user_data,
1308 GError **err)
1310 gchar *real_dir;
1312 g_return_val_if_fail (argv != NULL, FALSE);
1314 real_dir = g_strdup (dir);
1316 context->callback = callback;
1317 context->user_data = user_data;
1318 context->used = TRUE;
1320 /* Add current directory */
1321 envp = build_add_env_variable (envp, "PWD", dir);
1323 if (context->environment)
1325 if (!ianjuta_environment_override (context->environment, &real_dir, &argv, &envp, NULL))
1327 g_object_unref (context->environment);
1328 context->environment = NULL;
1332 if (context->message_view)
1334 gchar *command;
1336 command = g_strjoinv (" ", argv);
1337 ianjuta_message_view_buffer_append (context->message_view,
1338 "Building in directory: ", NULL);
1339 ianjuta_message_view_buffer_append (context->message_view, dir, NULL);
1340 ianjuta_message_view_buffer_append (context->message_view, "\n", NULL);
1341 ianjuta_message_view_buffer_append (context->message_view, command, NULL);
1342 ianjuta_message_view_buffer_append (context->message_view, "\n", NULL);
1343 g_free (command);
1345 anjuta_launcher_execute_v (context->launcher, argv, envp,
1346 on_build_mesg_arrived, context);
1348 else
1350 anjuta_launcher_execute_v (context->launcher, argv, envp,
1351 NULL, NULL);
1354 return TRUE;
1357 static gchar *
1358 target_from_source (BasicAutotoolsPlugin *plugin, const gchar *target)
1360 if ((plugin->project_root_dir == NULL) ||
1361 (plugin->project_build_dir == NULL) ||
1362 (strcmp (plugin->project_root_dir, plugin->project_build_dir) == 0) ||
1363 (strncmp (target, plugin->project_root_dir, strlen (plugin->project_root_dir)) != 0))
1365 return g_strdup (target);
1367 else
1369 return g_strconcat (plugin->project_build_dir, target + strlen (plugin->project_root_dir), NULL);
1373 static BuildContext*
1374 build_execute_command_full (BasicAutotoolsPlugin* bplugin, const gchar *dir,
1375 gchar *argv[],
1376 gboolean save_file, gboolean with_view, gchar *envp[],
1377 IAnjutaBuilderCallback callback, gpointer user_data,
1378 GError **err)
1380 AnjutaPlugin* plugin = ANJUTA_PLUGIN(bplugin);
1381 BuildContext *context;
1382 AnjutaPreferences* prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
1383 gboolean ok;
1384 gchar **arg;
1386 if (save_file)
1387 save_all_files (ANJUTA_PLUGIN (plugin));
1389 context = build_get_context (bplugin, dir, with_view);
1391 /* Send options to make */
1392 if (strcmp (argv[0], "make") == 0)
1394 if (!anjuta_preferences_get_int (prefs , PREF_TRANSLATE_MESSAGE))
1396 envp = build_add_env_variable (envp, "LANGUAGE", "C");
1398 if (anjuta_preferences_get_int (prefs , PREF_PARALLEL_MAKE))
1400 gchar *arg = g_strdup_printf ("-j%d", anjuta_preferences_get_int (prefs , PREF_PARALLEL_MAKE_JOB));
1401 argv = build_add_arg (argv, arg);
1402 g_free (arg);
1404 if (anjuta_preferences_get_int (prefs , PREF_CONTINUE_ON_ERROR))
1406 argv = build_add_arg (argv, "-k");
1410 /* Expand shell variable */
1411 for (arg = argv; *arg != NULL; arg++)
1413 gchar *old_arg;
1415 old_arg = *arg;
1416 *arg = build_shell_expand (old_arg);
1417 g_free (old_arg);
1420 ok = build_execute_command_in_context (context, dir, argv, envp, callback, user_data, NULL);
1421 g_strfreev (argv);
1423 if (ok)
1425 return context;
1427 else
1429 build_context_destroy (context);
1431 return NULL;
1436 static gboolean
1437 build_execute_command (BasicAutotoolsPlugin* bplugin, const gchar *dir,
1438 const gchar *command, gboolean save_file, GError **err)
1440 gchar **argv;
1441 gboolean ok;
1443 /* Store args and environment variables as string array */
1444 if (!g_shell_parse_argv (command, NULL, &argv, NULL))
1445 return FALSE;
1447 ok = build_execute_command_full (bplugin, dir, argv, save_file, TRUE, NULL, NULL, NULL, NULL) != NULL;
1449 return ok;
1452 static void
1453 build_cancel_command (BasicAutotoolsPlugin* bplugin, BuildContext *context,
1454 GError **err)
1456 GList *node;
1458 if (context == NULL) return;
1460 for (node = g_list_first (bplugin->contexts_pool); node != NULL; node = g_list_next (node))
1462 if (node->data == context)
1464 if (context->launcher != NULL)
1466 anjuta_launcher_signal (context->launcher, SIGTERM);
1467 return;
1472 /* Invalid handle passed */
1473 g_return_if_reached ();
1476 static gboolean
1477 build_compile_file_real (BasicAutotoolsPlugin *plugin, const gchar *file)
1479 gchar *target;
1480 gchar *target_basename;
1481 gchar *target_dirname;
1482 gchar *ext_ptr;
1483 gboolean ret;
1485 /* FIXME: This should be configuration somewhere, eg. preferences */
1486 static GHashTable *target_ext = NULL;
1487 if (!target_ext)
1489 target_ext = g_hash_table_new (g_str_hash, g_str_equal);
1490 g_hash_table_insert (target_ext, ".c", ".o");
1491 g_hash_table_insert (target_ext, ".cpp", ".o");
1492 g_hash_table_insert (target_ext, ".cxx", ".o");
1493 g_hash_table_insert (target_ext, ".c++", ".o");
1494 g_hash_table_insert (target_ext, ".cc", ".o");
1495 g_hash_table_insert (target_ext, ".in", "");
1496 g_hash_table_insert (target_ext, ".in.in", ".in");
1497 g_hash_table_insert (target_ext, ".la", ".la");
1498 g_hash_table_insert (target_ext, ".a", ".a");
1499 g_hash_table_insert (target_ext, ".so", ".so");
1500 g_hash_table_insert (target_ext, ".java", ".class");
1503 g_return_val_if_fail (file != NULL, FALSE);
1504 ret = FALSE;
1506 target = target_from_source (plugin, file);
1507 target_basename = g_path_get_basename (target);
1508 target_dirname = g_path_get_dirname (target);
1509 ext_ptr = strrchr (target_basename, '.');
1510 if (ext_ptr)
1512 const gchar *new_ext;
1513 new_ext = g_hash_table_lookup (target_ext, ext_ptr);
1514 if (new_ext)
1516 gchar *command;
1518 *ext_ptr = '\0';
1519 command = g_strconcat (CHOOSE_COMMAND (plugin, COMPILE), " ",
1520 target_basename, new_ext, NULL);
1521 build_execute_command (plugin, target_dirname, command, TRUE, NULL);
1522 g_free (command);
1523 ret = TRUE;
1525 } else {
1526 /* If file has no extension, take it as target itself */
1527 gchar *command;
1528 command = g_strconcat (CHOOSE_COMMAND(plugin, COMPILE), " ",
1529 target_basename, NULL);
1530 build_execute_command (plugin, target_dirname, command, TRUE, NULL);
1531 g_free (command);
1532 ret = TRUE;
1534 g_free (target_basename);
1535 g_free (target_dirname);
1536 g_free (target);
1537 if (ret == FALSE)
1539 /* FIXME: Prompt the user to create a Makefile with a wizard
1540 (if there is no Makefile in the directory) or to add a target
1541 rule in the above hash table, eg. editing the preferences, if
1542 there is target extension defined for that file extension.
1544 GtkWindow *window;
1545 window = GTK_WINDOW (ANJUTA_PLUGIN (plugin)->shell);
1546 anjuta_util_dialog_error (window, _("Can not compile \"%s\": No compile rule defined for this file type."), file);
1548 return ret;
1551 /* UI actions */
1552 static void
1553 build_build_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1555 build_execute_command (plugin, plugin->project_build_dir,
1556 CHOOSE_COMMAND (plugin, BUILD), TRUE, NULL);
1559 static void
1560 build_install_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1562 gchar* root = get_root_install_command(plugin);
1563 gchar* command = g_strdup_printf("%s %s", root,
1564 CHOOSE_COMMAND (plugin, INSTALL));
1565 g_free(root);
1566 build_execute_command (plugin, plugin->project_build_dir,
1567 command, TRUE, NULL);
1568 g_free(command);
1571 static void
1572 build_clean_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1574 build_execute_command (plugin, plugin->project_build_dir,
1575 CHOOSE_COMMAND (plugin, CLEAN), FALSE, NULL);
1578 static void
1579 build_remove_build_dir (GObject *sender,
1580 IAnjutaBuilderHandle context,
1581 GError *error,
1582 gpointer user_data)
1587 static void
1588 build_distclean_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1590 gchar **argv;
1592 if (!g_shell_parse_argv (CHOOSE_COMMAND (plugin, DISTCLEAN), NULL, &argv, NULL))
1593 return;
1595 build_execute_command_full (plugin, plugin->project_build_dir, argv, TRUE, TRUE, NULL, build_remove_build_dir, plugin, NULL);
1598 static void
1599 on_select_configuration (GtkRadioMenuItem *item, gpointer user_data)
1601 if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
1603 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (user_data);
1604 gchar *name;
1605 GValue *value;
1606 gchar *uri;
1608 name = g_object_get_data (G_OBJECT (item), "untranslated_name");
1610 build_configuration_list_select (plugin->configurations, name);
1612 value = g_new0 (GValue, 1);
1613 g_value_init (value, G_TYPE_STRING);
1615 uri = build_configuration_list_get_build_uri (plugin->configurations, build_configuration_list_get_selected (plugin->configurations));
1616 g_value_set_string (value, uri);
1617 g_free (uri);
1619 anjuta_shell_add_value (ANJUTA_PLUGIN (plugin)->shell, IANJUTA_BUILDER_ROOT_URI, value, NULL);
1623 static void
1624 build_update_configuration_menu (BasicAutotoolsPlugin *plugin)
1626 GtkWidget *submenu = NULL;
1627 BuildConfiguration *cfg;
1628 BuildConfiguration *selected;
1629 GSList *group = NULL;
1631 submenu = gtk_menu_new ();
1632 selected = build_configuration_list_get_selected (plugin->configurations);
1633 for (cfg = build_configuration_list_get_first (plugin->configurations); cfg != NULL; cfg = build_configuration_next (cfg))
1635 GtkWidget *item;
1637 item = gtk_radio_menu_item_new_with_mnemonic (group, build_configuration_get_translated_name (cfg));
1638 group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
1639 if (cfg == selected)
1641 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
1643 g_object_set_data_full (G_OBJECT (item), "untranslated_name", g_strdup (build_configuration_get_name (cfg)), g_free);
1644 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (on_select_configuration), plugin);
1645 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
1647 gtk_menu_item_set_submenu (GTK_MENU_ITEM (plugin->configuration_menu), submenu);
1648 gtk_widget_show_all (submenu);
1651 static void
1652 build_project_configured (GObject *sender,
1653 IAnjutaBuilderHandle context,
1654 GError *error,
1655 gpointer user_data)
1657 BasicAutotoolsPlugin *plugin = (BasicAutotoolsPlugin *)sender;
1658 GValue *value;
1659 gchar *uri;
1661 value = g_new0 (GValue, 1);
1662 g_value_init (value, G_TYPE_STRING);
1664 uri = build_configuration_list_get_build_uri (plugin->configurations, build_configuration_list_get_selected (plugin->configurations));
1665 g_value_set_string (value, uri);
1666 g_free (uri);
1668 anjuta_shell_add_value (ANJUTA_PLUGIN (plugin)->shell, IANJUTA_BUILDER_ROOT_URI, value, NULL);
1670 build_update_configuration_menu (plugin);
1673 static void
1674 build_configure_project_after_autogen (GObject *sender,
1675 IAnjutaBuilderHandle context,
1676 GError *error,
1677 gpointer user_data)
1679 BuildLinkCommand *link = (BuildLinkCommand *)user_data;
1680 BasicAutotoolsPlugin *plugin = (BasicAutotoolsPlugin *)sender;
1682 if (error == NULL)
1684 struct stat conf_stat, log_stat;
1685 gchar *filename;
1687 filename = g_build_filename (link->project_dir, "configure", NULL);
1688 if (stat (filename, &conf_stat) != 0)
1690 anjuta_util_dialog_error (link->parent, _("Can not configure project: Missing configure script in %s."), link->project_dir);
1692 else
1694 g_free (filename);
1695 filename = g_build_filename (link->build_dir, "config.log", NULL);
1696 if ((stat (filename, &log_stat) != 0) ||
1697 (log_stat.st_mtime < conf_stat.st_mtime))
1699 link->argv = build_argv_command (link->project_dir,
1700 CHOOSE_COMMAND (plugin, CONFIGURE),
1701 link->argv);
1702 build_execute_command_in_context ((BuildContext *)context, link->build_dir, link->argv,
1703 NULL, build_project_configured, NULL, NULL);
1706 g_free (filename);
1709 g_free (link->project_dir);
1710 g_free (link->build_dir);
1711 g_strfreev (link->argv);
1712 g_free (link);
1715 static void
1716 build_configure_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1718 GtkWindow *parent;
1719 gboolean run_autogen = FALSE;
1720 const gchar *project_root;
1721 GValue value = {0,};
1723 run_autogen = !directory_has_file (plugin->project_root_dir, "configure");
1725 anjuta_shell_get_value (ANJUTA_PLUGIN (plugin)->shell, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI, &value, NULL);
1726 project_root = g_value_get_string (&value);
1727 parent = GTK_WINDOW (ANJUTA_PLUGIN(plugin)->shell);
1728 if (build_dialog_configure (parent, project_root, plugin->configurations, &run_autogen))
1730 BuildConfiguration *config;
1731 gchar **argv;
1732 GFile *build_file;
1733 gchar *build_dir;
1734 gchar *uri;
1736 config = build_configuration_list_get_selected (plugin->configurations);
1737 uri = build_configuration_list_get_build_uri (plugin->configurations, config);
1738 build_file = g_file_new_for_uri (uri);
1739 g_free (uri);
1740 build_dir = g_file_get_path (build_file);
1741 g_object_unref (build_file);
1743 IAnjutaBuilderCallback callback = NULL;
1744 BuildLinkCommand* user_data = NULL;
1746 if (run_autogen)
1748 gboolean has_autogen = directory_has_file (plugin->project_root_dir,
1749 "autogen.sh");
1751 gchar **args = g_strdupv (build_configuration_get_args (config));
1752 argv = build_argv_command (plugin->project_root_dir,
1753 has_autogen ? CHOOSE_COMMAND (plugin, GENERATE) : CHOOSE_COMMAND (plugin, AUTORECONF),
1754 args);
1757 /* Plan to run configure afterward */
1758 user_data = g_new (BuildLinkCommand, 1);
1759 user_data->project_dir = g_strdup (plugin->project_root_dir);
1760 user_data->build_dir = g_strdup (build_dir);
1761 /* Remove command name from argument array */
1762 user_data->argv = g_strdupv (&argv[1]);
1763 user_data->parent = parent;
1765 callback = build_configure_project_after_autogen;
1767 else
1769 /* Run configure only */
1770 gchar **args = g_strdupv (build_configuration_get_args (config));
1772 argv = build_argv_command (plugin->project_root_dir,
1773 CHOOSE_COMMAND (plugin, CONFIGURE),
1774 args);
1775 callback = build_project_configured;
1777 build_execute_command_full (plugin, build_dir,
1778 argv, TRUE, TRUE, NULL,
1779 callback, user_data, NULL);
1780 g_free (build_dir);
1784 static void
1785 build_distribution_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1787 build_execute_command (plugin, plugin->project_build_dir,
1788 CHOOSE_COMMAND (plugin, BUILD_TARBALL),
1789 FALSE, NULL);
1792 static void
1793 build_build_module (GtkAction *action, BasicAutotoolsPlugin *plugin)
1795 gchar *dirname = g_dirname (plugin->current_editor_filename);
1796 gchar *target = target_from_source (plugin, dirname);
1798 build_execute_command (plugin, target,
1799 CHOOSE_COMMAND (plugin, BUILD),
1800 TRUE, NULL);
1801 g_free (target);
1802 g_free (dirname);
1805 static void
1806 build_install_module (GtkAction *action, BasicAutotoolsPlugin *plugin)
1808 gchar *dirname = g_dirname (plugin->current_editor_filename);
1809 gchar* root = get_root_install_command(plugin);
1810 gchar *target = target_from_source (plugin, dirname);
1811 gchar* command = g_strdup_printf ("%s %s", root,
1812 CHOOSE_COMMAND (plugin, INSTALL));
1813 g_free(root);
1814 build_execute_command (plugin, target, command, TRUE, NULL);
1815 g_free(command);
1816 g_free (target);
1817 g_free (dirname);
1820 static void
1821 build_clean_module (GtkAction *action, BasicAutotoolsPlugin *plugin)
1823 gchar *dirname = g_dirname (plugin->current_editor_filename);
1824 gchar *target = target_from_source (plugin, dirname);
1825 build_execute_command (plugin, target,
1826 CHOOSE_COMMAND (plugin, CLEAN),
1827 FALSE, NULL);
1828 g_free (target);
1829 g_free (dirname);
1832 static void
1833 build_compile_file (GtkAction *action, BasicAutotoolsPlugin *plugin)
1835 if (plugin->current_editor_filename)
1837 build_compile_file_real (plugin, plugin->current_editor_filename);
1841 /* File manager context menu */
1842 static void
1843 fm_compile (GtkAction *action, BasicAutotoolsPlugin *plugin)
1845 if (plugin->fm_current_filename)
1847 build_compile_file_real (plugin, plugin->fm_current_filename);
1851 static void
1852 fm_build (GtkAction *action, BasicAutotoolsPlugin *plugin)
1854 gchar *dir;
1855 gchar *target;
1857 g_return_if_fail (plugin->fm_current_filename != NULL);
1859 if (g_file_test (plugin->fm_current_filename, G_FILE_TEST_IS_DIR))
1860 dir = g_strdup (plugin->fm_current_filename);
1861 else
1862 dir = g_path_get_dirname (plugin->fm_current_filename);
1863 target = target_from_source (plugin, dir);
1864 build_execute_command (plugin, target,
1865 CHOOSE_COMMAND (plugin, BUILD),
1866 TRUE, NULL);
1867 g_free (target);
1868 g_free (dir);
1871 static void
1872 fm_install (GtkAction *action, BasicAutotoolsPlugin *plugin)
1874 gchar *dir;
1875 gchar* root;
1876 gchar* command;
1877 gchar *target;
1879 g_return_if_fail (plugin->fm_current_filename != NULL);
1882 if (g_file_test (plugin->fm_current_filename, G_FILE_TEST_IS_DIR))
1883 dir = g_strdup (plugin->fm_current_filename);
1884 else
1885 dir = g_path_get_dirname (plugin->fm_current_filename);
1886 root = get_root_install_command(plugin);
1887 command = g_strdup_printf ("%s %s", root,
1888 CHOOSE_COMMAND (plugin, INSTALL));
1889 g_free(root);
1890 target = target_from_source (plugin, dir);
1891 build_execute_command (plugin, dir, command, TRUE, NULL);
1892 g_free (target);
1895 static void
1896 fm_clean (GtkAction *action, BasicAutotoolsPlugin *plugin)
1898 gchar *dir;
1899 gchar *target;
1901 g_return_if_fail (plugin->fm_current_filename != NULL);
1903 if (g_file_test (plugin->fm_current_filename, G_FILE_TEST_IS_DIR))
1904 dir = g_strdup (plugin->fm_current_filename);
1905 else
1906 dir = g_path_get_dirname (plugin->fm_current_filename);
1908 target = target_from_source (plugin, dir);
1909 build_execute_command (plugin, target,
1910 CHOOSE_COMMAND (plugin, CLEAN),
1911 FALSE, NULL);
1912 g_free (target);
1915 /* Project manager context menu */
1916 static void
1917 pm_compile (GtkAction *action, BasicAutotoolsPlugin *plugin)
1919 if (plugin->pm_current_filename)
1921 build_compile_file_real (plugin, plugin->pm_current_filename);
1925 static void
1926 pm_build (GtkAction *action, BasicAutotoolsPlugin *plugin)
1928 gchar *dir;
1929 gchar *target;
1931 g_return_if_fail (plugin->pm_current_filename != NULL);
1933 if (g_file_test (plugin->pm_current_filename, G_FILE_TEST_IS_DIR))
1934 dir = g_strdup (plugin->pm_current_filename);
1935 else
1936 dir = g_path_get_dirname (plugin->pm_current_filename);
1937 target = target_from_source (plugin, dir);
1938 build_execute_command (plugin, target,
1939 CHOOSE_COMMAND (plugin, BUILD),
1940 TRUE, NULL);
1941 g_free (target);
1942 g_free (dir);
1945 static void
1946 pm_install (GtkAction *action, BasicAutotoolsPlugin *plugin)
1948 gchar *dir;
1949 gchar *target;
1950 gchar* root;
1951 gchar* command;
1953 g_return_if_fail (plugin->pm_current_filename != NULL);
1955 root = get_root_install_command(plugin);
1956 command = g_strdup_printf ("%s %s", root,
1957 CHOOSE_COMMAND (plugin, INSTALL));
1958 g_free(root);
1960 if (g_file_test (plugin->pm_current_filename, G_FILE_TEST_IS_DIR))
1961 dir = g_strdup (plugin->pm_current_filename);
1962 else
1963 dir = g_path_get_dirname (plugin->pm_current_filename);
1964 target = target_from_source (plugin, dir);
1965 build_execute_command (plugin, target, command, TRUE, NULL);
1966 g_free(command);
1967 g_free (target);
1968 g_free (dir);
1971 static void
1972 pm_clean (GtkAction *action, BasicAutotoolsPlugin *plugin)
1974 gchar *dir;
1975 gchar *target;
1977 g_return_if_fail (plugin->pm_current_filename != NULL);
1979 if (g_file_test (plugin->pm_current_filename, G_FILE_TEST_IS_DIR))
1980 dir = g_strdup (plugin->pm_current_filename);
1981 else
1982 dir = g_path_get_dirname (plugin->pm_current_filename);
1983 target = target_from_source (plugin, dir);
1984 build_execute_command (plugin, target,
1985 CHOOSE_COMMAND (plugin, CLEAN),
1986 FALSE, NULL);
1987 g_free (dir);
1988 g_free (target);
1991 static void
1992 mv_cancel (GtkAction *action, BasicAutotoolsPlugin *plugin)
1994 IAnjutaMessageManager *msgman;
1996 msgman = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
1997 IAnjutaMessageManager,
1998 NULL);
2000 if (msgman != NULL)
2002 IAnjutaMessageView *view;
2004 view = ianjuta_message_manager_get_current_view (msgman, NULL);
2005 if (view != NULL)
2007 GList *node;
2009 for (node = g_list_first (plugin->contexts_pool); node != NULL; node = g_list_next (node))
2011 BuildContext *context;
2013 context = (BuildContext *)node->data;
2014 if (context->message_view == view)
2016 if (context->launcher != NULL)
2018 anjuta_launcher_signal (context->launcher, SIGTERM);
2020 return;
2027 static GtkActionEntry build_actions[] =
2030 "ActionMenuBuild", NULL,
2031 N_("_Build"), NULL, NULL, NULL
2034 "ActionBuildBuildProject", NULL,
2035 N_("_Build Project"), "<shift>F11",
2036 N_("Build whole project"),
2037 G_CALLBACK (build_build_project)
2040 "ActionBuildInstallProject", NULL,
2041 N_("_Install Project"), NULL,
2042 N_("Install whole project"),
2043 G_CALLBACK (build_install_project)
2046 "ActionBuildCleanProject", NULL,
2047 N_("_Clean Project"), NULL,
2048 N_("Clean whole project"),
2049 G_CALLBACK (build_clean_project)
2052 "ActionBuildConfigure", NULL,
2053 N_("C_onfigure Project..."), NULL,
2054 N_("Configure project"),
2055 G_CALLBACK (build_configure_project)
2058 "ActionBuildDistribution", NULL,
2059 N_("Build _Tarball"), NULL,
2060 N_("Build project tarball distribution"),
2061 G_CALLBACK (build_distribution_project)
2064 "ActionBuildBuildModule", GTK_STOCK_EXECUTE,
2065 N_("_Build Module"), "F11",
2066 N_("Build module associated with current file"),
2067 G_CALLBACK (build_build_module)
2070 "ActionBuildInstallModule", NULL,
2071 N_("_Install Module"), NULL,
2072 N_("Install module associated with current file"),
2073 G_CALLBACK (build_install_module)
2076 "ActionBuildCleanModule", NULL,
2077 N_("_Clean Module"), NULL,
2078 N_("Clean module associated with current file"),
2079 G_CALLBACK (build_clean_module)
2082 "ActionBuildCompileFile", GTK_STOCK_CONVERT,
2083 N_("Co_mpile File"), "F9",
2084 N_("Compile current editor file"),
2085 G_CALLBACK (build_compile_file)
2088 "ActionBuildSelectConfiguration", NULL,
2089 N_("Select Configuration"), NULL,
2090 N_("Select current configuration"),
2091 NULL
2094 "ActionBuildRemoveConfiguration", NULL,
2095 N_("Remove Configuration"), NULL,
2096 N_("Clean project (distclean) and remove configuration directory if possible"),
2097 G_CALLBACK (build_distclean_project)
2101 static GtkActionEntry build_popup_actions[] =
2104 "ActionPopupBuild", NULL,
2105 N_("_Build"), NULL, NULL, NULL
2108 "ActionPopupBuildCompile", GTK_STOCK_CONVERT,
2109 N_("_Compile"), NULL,
2110 N_("Compile file"),
2111 G_CALLBACK (fm_compile)
2114 "ActionPopupBuildBuild", GTK_STOCK_EXECUTE,
2115 N_("_Build"), NULL,
2116 N_("Build module"),
2117 G_CALLBACK (fm_build)
2120 "ActionPopupBuildInstall", NULL,
2121 N_("_Install"), NULL,
2122 N_("Install module"),
2123 G_CALLBACK (fm_install)
2126 "ActionPopupBuildClean", NULL,
2127 N_("_Clean"), NULL,
2128 N_("Clean module"),
2129 G_CALLBACK (fm_clean)
2132 "ActionPopupPMBuild", NULL,
2133 N_("_Build"), NULL, NULL, NULL
2136 "ActionPopupPMBuildCompile", GTK_STOCK_CONVERT,
2137 N_("_Compile"), NULL,
2138 N_("Compile file"),
2139 G_CALLBACK (pm_compile)
2142 "ActionPopupPMBuildBuild", GTK_STOCK_EXECUTE,
2143 N_("_Build"), NULL,
2144 N_("Build module"),
2145 G_CALLBACK (pm_build)
2148 "ActionPopupPMBuildInstall", NULL,
2149 N_("_Install"), NULL,
2150 N_("Install module"),
2151 G_CALLBACK (pm_install)
2154 "ActionPopupPMBuildClean", NULL,
2155 N_("_Clean"), NULL,
2156 N_("Clean module"),
2157 G_CALLBACK (pm_clean)
2160 "ActionPopupMVBuildCancel", NULL,
2161 N_("_Cancel command"), NULL,
2162 N_("Cancel build command"),
2163 G_CALLBACK (mv_cancel)
2167 static gboolean
2168 directory_has_makefile (const gchar *dirname)
2170 gchar *makefile;
2171 gboolean makefile_exists;
2173 makefile_exists = TRUE;
2174 makefile = g_build_filename (dirname, "Makefile", NULL);
2175 if (!g_file_test (makefile, G_FILE_TEST_EXISTS))
2177 g_free (makefile);
2178 makefile = g_build_filename (dirname, "makefile", NULL);
2179 if (!g_file_test (makefile, G_FILE_TEST_EXISTS))
2181 g_free (makefile);
2182 makefile = g_build_filename (dirname, "MAKEFILE", NULL);
2183 if (!g_file_test (makefile, G_FILE_TEST_EXISTS))
2185 makefile_exists = FALSE;
2189 g_free (makefile);
2190 return makefile_exists;
2193 static gboolean
2194 directory_has_file (const gchar *dirname, const gchar *filename)
2196 gchar *filepath;
2197 gboolean exists;
2199 exists = TRUE;
2200 filepath = g_build_filename (dirname, filename, NULL);
2201 if (!g_file_test (filepath, G_FILE_TEST_EXISTS))
2202 exists = FALSE;
2204 g_free (filepath);
2205 return exists;
2208 static gchar*
2209 escape_label (const gchar *str)
2211 GString *ret;
2212 const gchar *iter;
2214 ret = g_string_new ("");
2215 iter = str;
2216 while (*iter != '\0')
2218 if (*iter == '_')
2220 ret = g_string_append (ret, "__");
2221 iter++;
2223 else
2225 const gchar *start;
2226 const gchar *end;
2228 start = iter;
2229 iter = g_utf8_next_char (iter);
2230 end = iter;
2232 ret = g_string_append_len (ret, start, end - start);
2235 return g_string_free (ret, FALSE);
2238 static void
2239 update_module_ui (BasicAutotoolsPlugin *bb_plugin)
2241 AnjutaUI *ui;
2242 GtkAction *action;
2243 gchar *filename= NULL;
2244 gchar *module = NULL;
2245 gchar *label;
2246 gboolean has_file = FALSE;
2247 gboolean has_makefile= FALSE;
2249 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (bb_plugin)->shell, NULL);
2251 DEBUG_PRINT ("Updating module UI");
2253 has_file = bb_plugin->current_editor_filename != NULL;
2254 if (has_file)
2256 gchar *dirname;
2257 gchar *build_dirname;
2259 dirname = g_dirname (bb_plugin->current_editor_filename);
2260 build_dirname = target_from_source (bb_plugin, dirname);
2262 module = escape_label (g_basename (dirname));
2263 filename = escape_label (g_basename (bb_plugin->current_editor_filename));
2264 has_makefile = directory_has_makefile (build_dirname);
2265 g_free (build_dirname);
2266 g_free (dirname);
2269 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2270 "ActionBuildBuildModule");
2271 label = g_strdup_printf (module ? _("_Build (%s)") : _("_Build"), module);
2272 g_object_set (G_OBJECT (action), "sensitive", has_makefile,
2273 "label", label, NULL);
2274 g_free (label);
2276 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2277 "ActionBuildInstallModule");
2278 label = g_strdup_printf (module ? _("_Install (%s)") : _("_Install"), module);
2279 g_object_set (G_OBJECT (action), "sensitive", has_makefile,
2280 "label", label, NULL);
2281 g_free (label);
2283 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2284 "ActionBuildCleanModule");
2285 label = g_strdup_printf (module ? _("_Clean (%s)") : _("_Clean"), module);
2286 g_object_set (G_OBJECT (action), "sensitive", has_makefile,
2287 "label", label, NULL);
2288 g_free (label);
2291 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2292 "ActionBuildCompileFile");
2293 label = g_strdup_printf (filename ? _("Co_mpile (%s)") : _("Co_mpile"), filename);
2294 g_object_set (G_OBJECT (action), "sensitive", has_file,
2295 "label", label, NULL);
2296 g_free (label);
2298 g_free (module);
2299 g_free (filename);
2302 static void
2303 update_project_ui (BasicAutotoolsPlugin *bb_plugin)
2305 AnjutaUI *ui;
2306 GtkAction *action;
2307 gboolean has_makefile;
2308 gboolean has_project;
2310 DEBUG_PRINT ("Updating project UI");
2312 has_project = bb_plugin->project_root_dir != NULL;
2313 has_makefile = has_project && directory_has_makefile (bb_plugin->project_build_dir);
2315 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (bb_plugin)->shell, NULL);
2316 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2317 "ActionBuildBuildProject");
2318 g_object_set (G_OBJECT (action), "sensitive", has_makefile, NULL);
2319 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2320 "ActionBuildInstallProject");
2321 g_object_set (G_OBJECT (action), "sensitive", has_makefile, NULL);
2322 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2323 "ActionBuildCleanProject");
2324 g_object_set (G_OBJECT (action), "sensitive", has_makefile, NULL);
2325 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2326 "ActionBuildDistribution");
2327 g_object_set (G_OBJECT (action), "sensitive", has_makefile, NULL);
2328 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2329 "ActionBuildConfigure");
2330 g_object_set (G_OBJECT (action), "sensitive", has_project, NULL);
2331 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2332 "ActionBuildSelectConfiguration");
2333 g_object_set (G_OBJECT (action), "sensitive", has_project, NULL);
2334 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2335 "ActionBuildRemoveConfiguration");
2336 g_object_set (G_OBJECT (action), "sensitive", has_makefile, NULL);
2338 update_module_ui (bb_plugin);
2341 static void
2342 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
2343 AnjutaSession *session, BasicAutotoolsPlugin *plugin)
2345 GList *configurations;
2346 BuildConfiguration *cfg;
2347 const gchar *name;
2349 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
2350 return;
2352 configurations = build_configuration_list_to_string_list (plugin->configurations);
2353 anjuta_session_set_string_list (session, "Build",
2354 "Configuration list",
2355 configurations);
2356 g_list_foreach (configurations, (GFunc)g_free, NULL);
2357 g_list_free (configurations);
2359 cfg = build_configuration_list_get_selected (plugin->configurations);
2360 if (cfg != NULL)
2362 name = build_configuration_get_name (cfg);
2363 anjuta_session_set_string (session, "Build", "Selected Configuration", name);
2367 static void
2368 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase,
2369 AnjutaSession *session, BasicAutotoolsPlugin *plugin)
2371 GList *configurations;
2372 gchar *selected;
2374 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
2375 return;
2377 configurations = anjuta_session_get_string_list (session, "Build",
2378 "Configuration list");
2380 build_configuration_list_from_string_list (plugin->configurations, configurations);
2381 g_list_foreach (configurations, (GFunc)g_free, NULL);
2382 g_list_free (configurations);
2384 selected = anjuta_session_get_string (session, "Build", "Selected Configuration");
2385 build_configuration_list_select (plugin->configurations, selected);
2386 g_free (selected);
2388 build_project_configured (G_OBJECT (plugin), NULL, NULL, NULL);
2391 static void
2392 value_added_fm_current_file (AnjutaPlugin *plugin, const char *name,
2393 const GValue *value, gpointer data)
2395 AnjutaUI *ui;
2396 GtkAction *action;
2397 GFile* file;
2398 GFileInfo* file_info;
2399 gchar* filename;
2400 gchar* dirname;
2401 gboolean makefile_exists, is_dir;
2403 file = g_value_get_object (value);
2404 filename = g_file_get_path (file);
2405 g_return_if_fail (filename != NULL);
2407 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2408 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2410 if (ba_plugin->fm_current_filename)
2411 g_free (ba_plugin->fm_current_filename);
2412 ba_plugin->fm_current_filename = filename;
2414 file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE,
2415 G_FILE_QUERY_INFO_NONE, NULL, NULL);
2416 is_dir = (g_file_info_get_file_type(file_info) == G_FILE_TYPE_DIRECTORY);
2417 if (is_dir)
2418 dirname = g_strdup (filename);
2419 else
2420 dirname = g_path_get_dirname (filename);
2421 makefile_exists = directory_has_makefile (dirname);
2422 g_free (dirname);
2424 if (!makefile_exists)
2425 return;
2427 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild", "ActionPopupBuild");
2428 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
2429 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
2430 "ActionPopupBuildCompile");
2431 if (is_dir)
2432 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
2433 else
2434 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
2437 static void
2438 value_removed_fm_current_file (AnjutaPlugin *plugin,
2439 const char *name, gpointer data)
2441 AnjutaUI *ui;
2442 GtkAction *action;
2443 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2445 if (ba_plugin->fm_current_filename)
2446 g_free (ba_plugin->fm_current_filename);
2447 ba_plugin->fm_current_filename = NULL;
2449 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2450 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild", "ActionPopupBuild");
2451 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
2454 static void
2455 value_added_pm_current_uri (AnjutaPlugin *plugin, const char *name,
2456 const GValue *value, gpointer data)
2458 AnjutaUI *ui;
2459 GtkAction *action;
2460 const gchar *uri;
2461 gchar *dirname, *filename;
2462 gboolean makefile_exists, is_dir;
2463 GFile* file;
2465 uri = g_value_get_string (value);
2466 file = g_file_new_for_uri (uri);
2467 filename = g_file_get_path (file);
2468 g_object_unref (file);
2469 g_return_if_fail (filename != NULL);
2472 if (g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE)
2473 return;
2476 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2477 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2479 if (ba_plugin->pm_current_filename)
2480 g_free (ba_plugin->pm_current_filename);
2481 ba_plugin->pm_current_filename = filename;
2483 is_dir = g_file_test (filename, G_FILE_TEST_IS_DIR);
2484 if (is_dir)
2485 dirname = g_strdup (filename);
2486 else
2487 dirname = g_path_get_dirname (filename);
2488 makefile_exists = directory_has_makefile (dirname);
2489 g_free (dirname);
2491 if (!makefile_exists)
2492 return;
2494 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild", "ActionPopupPMBuild");
2495 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
2496 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
2497 "ActionPopupPMBuildCompile");
2498 if (is_dir)
2499 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
2500 else
2501 g_object_set (G_OBJECT (action), "sensitive", TRUE, NULL);
2504 static void
2505 value_removed_pm_current_uri (AnjutaPlugin *plugin,
2506 const char *name, gpointer data)
2508 AnjutaUI *ui;
2509 GtkAction *action;
2510 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2512 if (ba_plugin->pm_current_filename)
2513 g_free (ba_plugin->pm_current_filename);
2514 ba_plugin->pm_current_filename = NULL;
2516 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2517 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild", "ActionPopupPMBuild");
2518 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
2521 static void
2522 value_added_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
2523 const GValue *value, gpointer user_data)
2525 BasicAutotoolsPlugin *bb_plugin;
2526 const gchar *root_uri;
2528 bb_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2530 g_free (bb_plugin->project_root_dir);
2531 bb_plugin->project_root_dir = NULL;
2533 root_uri = g_value_get_string (value);
2534 if (root_uri)
2536 GFile* file = g_file_new_for_uri (root_uri);
2537 bb_plugin->project_root_dir =
2538 g_file_get_path(file);
2539 g_object_unref (file);
2542 build_configuration_list_set_project_uri (bb_plugin->configurations, root_uri);
2544 /* Export project build uri */
2545 anjuta_shell_add_value (ANJUTA_PLUGIN(plugin)->shell,
2546 IANJUTA_BUILDER_ROOT_URI,
2547 value, NULL);
2549 update_project_ui (bb_plugin);
2552 static void
2553 value_removed_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
2554 gpointer user_data)
2556 BasicAutotoolsPlugin *bb_plugin;
2558 bb_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2560 g_free (bb_plugin->project_root_dir);
2561 g_free (bb_plugin->project_build_dir);
2562 g_free (bb_plugin->program_args);
2564 bb_plugin->run_in_terminal = TRUE;
2565 bb_plugin->program_args = NULL;
2566 bb_plugin->project_build_dir = NULL;
2567 bb_plugin->project_root_dir = NULL;
2569 build_configuration_list_set_project_uri (bb_plugin->configurations, NULL);
2571 /* Export project build uri */
2572 anjuta_shell_remove_value (ANJUTA_PLUGIN (plugin)->shell,
2573 IANJUTA_BUILDER_ROOT_URI, NULL);
2575 update_project_ui (bb_plugin);
2578 static void
2579 value_added_project_build_uri (AnjutaPlugin *plugin, const gchar *name,
2580 const GValue *value, gpointer user_data)
2582 BasicAutotoolsPlugin *bb_plugin;
2583 const gchar *build_uri;
2585 bb_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2587 g_free (bb_plugin->project_build_dir);
2588 bb_plugin->project_build_dir = NULL;
2590 build_uri = g_value_get_string (value);
2591 if (build_uri)
2593 GFile* file = g_file_new_for_uri (build_uri);
2594 bb_plugin->project_build_dir =
2595 g_file_get_path(file);
2596 g_object_unref (file);
2598 update_project_ui (bb_plugin);
2601 static gint
2602 on_update_indicators_idle (gpointer data)
2604 AnjutaPlugin *plugin = ANJUTA_PLUGIN (data);
2605 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (data);
2606 IAnjutaEditor *editor = ba_plugin->current_editor;
2608 /* If indicators are not yet updated in the editor, do it */
2609 if (ba_plugin->current_editor_filename &&
2610 IANJUTA_IS_INDICABLE (editor) &&
2611 anjuta_preferences_get_int (anjuta_shell_get_preferences (plugin->shell,
2612 NULL),
2613 PREF_INDICATORS_AUTOMATIC))
2615 GList *node;
2616 node = ba_plugin->contexts_pool;
2617 while (node)
2619 BuildContext *context = node->data;
2620 if (g_hash_table_lookup (context->indicators_updated_editors,
2621 editor) == NULL)
2623 GSList *loc_node;
2624 ianjuta_indicable_clear (IANJUTA_INDICABLE (editor), NULL);
2627 loc_node = context->locations;
2628 while (loc_node)
2630 build_indicator_location_set ((BuildIndicatorLocation*) loc_node->data,
2631 IANJUTA_EDITOR (editor), ba_plugin->current_editor_filename);
2632 loc_node = g_slist_next (loc_node);
2634 g_hash_table_insert (context->indicators_updated_editors,
2635 editor, editor);
2637 node = g_list_next (node);
2640 return FALSE;
2643 static void
2644 on_editor_destroy (IAnjutaEditor *editor, BasicAutotoolsPlugin *ba_plugin)
2646 g_hash_table_remove (ba_plugin->editors_created, editor);
2649 static void
2650 on_editor_changed (IAnjutaEditor *editor, IAnjutaIterable *position,
2651 gboolean added, gint length, gint lines, const gchar *text,
2652 BasicAutotoolsPlugin *ba_plugin)
2654 gint line;
2655 IAnjutaIterable *begin_pos, *end_pos;
2656 if (g_hash_table_lookup (ba_plugin->editors_created,
2657 editor) == NULL)
2658 return;
2659 line = ianjuta_editor_get_line_from_position (editor, position, NULL);
2660 begin_pos = ianjuta_editor_get_line_begin_position (editor, line, NULL);
2661 end_pos = ianjuta_editor_get_line_end_position (editor, line, NULL);
2662 if (IANJUTA_IS_INDICABLE (editor))
2664 DEBUG_PRINT ("Clearing indicator on line %d", line);
2665 ianjuta_indicable_set (IANJUTA_INDICABLE (editor), begin_pos,
2666 end_pos, IANJUTA_INDICABLE_NONE, NULL);
2668 DEBUG_PRINT ("Editor changed: line number = %d, added = %d,"
2669 " text length = %d, number of lines = %d",
2670 line, added, length, lines);
2671 g_object_unref (begin_pos);
2672 g_object_unref (end_pos);
2675 static void
2676 value_added_current_editor (AnjutaPlugin *plugin, const char *name,
2677 const GValue *value, gpointer data)
2679 AnjutaUI *ui;
2680 GFile* file;
2681 GObject *editor;
2683 editor = g_value_get_object (value);
2685 if (!IANJUTA_IS_EDITOR(editor))
2686 return;
2688 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2689 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2691 g_free (ba_plugin->current_editor_filename);
2692 ba_plugin->current_editor_filename = NULL;
2693 ba_plugin->current_editor = IANJUTA_EDITOR (editor);
2695 if (g_hash_table_lookup (ba_plugin->editors_created,
2696 ba_plugin->current_editor) == NULL)
2698 g_hash_table_insert (ba_plugin->editors_created,
2699 ba_plugin->current_editor,
2700 ba_plugin->current_editor);
2701 g_signal_connect (ba_plugin->current_editor, "destroy",
2702 G_CALLBACK (on_editor_destroy), plugin);
2703 g_signal_connect (ba_plugin->current_editor, "changed",
2704 G_CALLBACK (on_editor_changed), plugin);
2707 file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
2708 if (file)
2710 gchar *filename;
2712 filename = g_file_get_path(file);
2713 g_object_unref (file);
2714 g_return_if_fail (filename != NULL);
2715 ba_plugin->current_editor_filename = filename;
2716 update_module_ui (ba_plugin);
2718 g_idle_add (on_update_indicators_idle, plugin);
2721 static void
2722 value_removed_current_editor (AnjutaPlugin *plugin,
2723 const char *name, gpointer data)
2725 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2726 #if 0
2727 if (ba_plugin->indicators_updated_editors &&
2728 g_hash_table_lookup (ba_plugin->indicators_updated_editors,
2729 ba_plugin->current_editor))
2731 g_hash_table_remove (ba_plugin->indicators_updated_editors,
2732 ba_plugin->current_editor);
2734 #endif
2735 if (ba_plugin->current_editor_filename)
2736 g_free (ba_plugin->current_editor_filename);
2737 ba_plugin->current_editor_filename = NULL;
2738 ba_plugin->current_editor = NULL;
2740 update_module_ui (ba_plugin);
2743 static gboolean
2744 activate_plugin (AnjutaPlugin *plugin)
2746 AnjutaUI *ui;
2747 static gboolean initialized = FALSE;
2748 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2750 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2752 g_signal_connect (plugin->shell, "save-session",
2753 G_CALLBACK (on_session_save),
2754 plugin);
2755 g_signal_connect (plugin->shell, "load-session",
2756 G_CALLBACK (on_session_load),
2757 plugin);
2759 /* Add action group */
2760 ba_plugin->build_action_group =
2761 anjuta_ui_add_action_group_entries (ui,
2762 "ActionGroupBuild",
2763 _("Build commands"),
2764 build_actions,
2765 sizeof(build_actions)/sizeof(GtkActionEntry),
2766 GETTEXT_PACKAGE, TRUE, plugin);
2767 ba_plugin->build_popup_action_group =
2768 anjuta_ui_add_action_group_entries (ui,
2769 "ActionGroupPopupBuild",
2770 _("Build popup commands"),
2771 build_popup_actions,
2772 sizeof(build_popup_actions)/sizeof(GtkActionEntry),
2773 GETTEXT_PACKAGE, FALSE, plugin);
2774 /* Add UI */
2775 ba_plugin->build_merge_id = anjuta_ui_merge (ui, UI_FILE);
2777 ba_plugin->configuration_menu = gtk_ui_manager_get_widget (GTK_UI_MANAGER(ui),
2778 "/MenuMain/PlaceHolderBuildMenus/MenuBuild/SelectConfiguration");
2779 update_project_ui (ba_plugin);
2781 /* Add watches */
2782 ba_plugin->fm_watch_id =
2783 anjuta_plugin_add_watch (plugin, IANJUTA_FILE_MANAGER_SELECTED_FILE,
2784 value_added_fm_current_file,
2785 value_removed_fm_current_file, NULL);
2786 ba_plugin->pm_watch_id =
2787 anjuta_plugin_add_watch (plugin, IANJUTA_PROJECT_MANAGER_CURRENT_URI,
2788 value_added_pm_current_uri,
2789 value_removed_pm_current_uri, NULL);
2790 ba_plugin->project_root_watch_id =
2791 anjuta_plugin_add_watch (plugin, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
2792 value_added_project_root_uri,
2793 value_removed_project_root_uri, NULL);
2794 ba_plugin->project_build_watch_id =
2795 anjuta_plugin_add_watch (plugin, IANJUTA_BUILDER_ROOT_URI,
2796 value_added_project_build_uri,
2797 NULL, NULL);
2798 ba_plugin->editor_watch_id =
2799 anjuta_plugin_add_watch (plugin, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
2800 value_added_current_editor,
2801 value_removed_current_editor, NULL);
2803 initialized = TRUE;
2804 return TRUE;
2807 static gboolean
2808 deactivate_plugin (AnjutaPlugin *plugin)
2810 AnjutaUI *ui;
2811 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2813 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2815 g_signal_handlers_disconnect_by_func (plugin->shell,
2816 G_CALLBACK (on_session_save),
2817 plugin);
2818 g_signal_handlers_disconnect_by_func (plugin->shell,
2819 G_CALLBACK (on_session_load),
2820 plugin);
2822 /* Remove watches */
2823 anjuta_plugin_remove_watch (plugin, ba_plugin->fm_watch_id, TRUE);
2824 anjuta_plugin_remove_watch (plugin, ba_plugin->pm_watch_id, TRUE);
2825 anjuta_plugin_remove_watch (plugin, ba_plugin->project_root_watch_id, TRUE);
2826 anjuta_plugin_remove_watch (plugin, ba_plugin->project_build_watch_id, TRUE);
2827 anjuta_plugin_remove_watch (plugin, ba_plugin->editor_watch_id, TRUE);
2829 /* Remove UI */
2830 anjuta_ui_unmerge (ui, ba_plugin->build_merge_id);
2832 /* Remove action group */
2833 anjuta_ui_remove_action_group (ui, ba_plugin->build_action_group);
2834 anjuta_ui_remove_action_group (ui, ba_plugin->build_popup_action_group);
2835 return TRUE;
2838 static void
2839 dispose (GObject *obj)
2841 G_OBJECT_CLASS (parent_class)->dispose (obj);
2844 static void
2845 finalize (GObject *obj)
2847 gint i;
2848 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (obj);
2850 for (i = 0; i < IANJUTA_BUILDABLE_N_COMMANDS; i++)
2852 g_free (ba_plugin->commands[i]);
2853 ba_plugin->commands[i] = NULL;
2856 g_free (ba_plugin->fm_current_filename);
2857 g_free (ba_plugin->pm_current_filename);
2858 g_free (ba_plugin->project_root_dir);
2859 g_free (ba_plugin->project_build_dir);
2860 g_free (ba_plugin->current_editor_filename);
2861 g_free (ba_plugin->program_args);
2862 build_configuration_list_free (ba_plugin->configurations);
2864 ba_plugin->fm_current_filename = NULL;
2865 ba_plugin->pm_current_filename = NULL;
2866 ba_plugin->project_root_dir = NULL;
2867 ba_plugin->project_build_dir = NULL;
2868 ba_plugin->current_editor_filename = NULL;
2869 ba_plugin->program_args = NULL;
2870 ba_plugin->configurations = NULL;
2872 G_OBJECT_CLASS (parent_class)->finalize (obj);
2875 static void
2876 basic_autotools_plugin_instance_init (GObject *obj)
2878 gint i;
2879 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (obj);
2881 for (i = 0; i < IANJUTA_BUILDABLE_N_COMMANDS; i++)
2882 ba_plugin->commands[i] = NULL;
2884 ba_plugin->fm_current_filename = NULL;
2885 ba_plugin->pm_current_filename = NULL;
2886 ba_plugin->project_root_dir = NULL;
2887 ba_plugin->project_build_dir = NULL;
2888 ba_plugin->current_editor = NULL;
2889 ba_plugin->current_editor_filename = NULL;
2890 ba_plugin->contexts_pool = NULL;
2891 ba_plugin->configurations = build_configuration_list_new ();
2892 ba_plugin->program_args = NULL;
2893 ba_plugin->run_in_terminal = TRUE;
2894 ba_plugin->last_exec_uri = NULL;
2895 ba_plugin->editors_created = g_hash_table_new (g_direct_hash,
2896 g_direct_equal);
2899 static void
2900 basic_autotools_plugin_class_init (GObjectClass *klass)
2902 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
2904 parent_class = g_type_class_peek_parent (klass);
2906 plugin_class->activate = activate_plugin;
2907 plugin_class->deactivate = deactivate_plugin;
2908 klass->dispose = dispose;
2909 klass->finalize = finalize;
2912 #if 0
2913 static void
2914 ibuildable_compile (IAnjutaBuildable *manager, const gchar * filename,
2915 GError **err)
2917 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2918 build_compile_file_real (plugin, filename);
2920 #endif
2922 static void
2923 ibuildable_set_command (IAnjutaBuildable *manager,
2924 IAnjutaBuildableCommand command_id,
2925 const gchar *command_override, GError **err)
2927 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2928 if (plugin->commands[command_id])
2929 g_free (plugin->commands[command_id]);
2930 plugin->commands[command_id] = g_strdup (command_override);
2933 static void
2934 ibuildable_reset_commands (IAnjutaBuildable *manager, GError **err)
2936 gint i;
2937 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2939 for (i = 0; i < IANJUTA_BUILDABLE_N_COMMANDS; i++)
2941 g_free (ba_plugin->commands[i]);
2942 ba_plugin->commands[i] = NULL;
2946 static const gchar *
2947 ibuildable_get_command (IAnjutaBuildable *manager,
2948 IAnjutaBuildableCommand command_id,
2949 GError **err)
2951 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2952 return plugin->commands[command_id];
2955 static void
2956 ibuildable_build (IAnjutaBuildable *manager, const gchar *directory,
2957 GError **err)
2959 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2960 build_execute_command (plugin, directory,
2961 CHOOSE_COMMAND (plugin, BUILD),
2962 TRUE, NULL);
2965 static void
2966 ibuildable_clean (IAnjutaBuildable *manager, const gchar *directory,
2967 GError **err)
2969 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2970 build_execute_command (plugin, directory,
2971 CHOOSE_COMMAND (plugin, CLEAN),
2972 FALSE, NULL);
2975 static void
2976 ibuildable_install (IAnjutaBuildable *manager, const gchar *directory,
2977 GError **err)
2979 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2980 gchar* root = get_root_install_command(plugin);
2981 gchar* command = g_strdup_printf ("%s %s", root,
2982 CHOOSE_COMMAND (plugin, INSTALL));
2983 g_free(root);
2984 build_execute_command (plugin, directory, command, TRUE, NULL);
2985 g_free(command);
2988 static void
2989 ibuildable_configure (IAnjutaBuildable *manager, const gchar *directory,
2990 GError **err)
2992 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2993 build_execute_command (plugin, directory,
2994 CHOOSE_COMMAND (plugin, CONFIGURE),
2995 TRUE, NULL);
2998 static void
2999 ibuildable_generate (IAnjutaBuildable *manager, const gchar *directory,
3000 GError **err)
3002 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
3003 if (directory_has_file (plugin->project_root_dir, "autogen.sh"))
3005 build_execute_command (plugin, directory,
3006 CHOOSE_COMMAND (plugin, GENERATE),
3007 FALSE, NULL);
3009 else
3011 /* FIXME: get override command for this too */
3012 build_execute_command (plugin, directory,
3013 "autoreconf -i --force",
3014 FALSE, NULL);
3018 static void
3019 ibuildable_execute (IAnjutaBuildable *manager, const gchar *uri,
3020 GError **err)
3022 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
3023 if (uri && strlen (uri) > 0)
3024 execute_program (plugin, uri);
3025 else
3026 execute_program (plugin, NULL);
3029 static void
3030 ibuildable_iface_init (IAnjutaBuildableIface *iface)
3032 /* iface->compile = ibuildable_compile; */
3033 iface->set_command = ibuildable_set_command;
3034 iface->get_command = ibuildable_get_command;
3035 iface->reset_commands = ibuildable_reset_commands;
3036 iface->build = ibuildable_build;
3037 iface->clean = ibuildable_clean;
3038 iface->install = ibuildable_install;
3039 iface->configure = ibuildable_configure;
3040 iface->generate = ibuildable_generate;
3041 iface->execute = ibuildable_execute;
3044 static void
3045 ifile_open (IAnjutaFile *manager, GFile* file,
3046 GError **err)
3048 gchar* uri = g_file_get_uri (file);
3049 ianjuta_buildable_execute (IANJUTA_BUILDABLE (manager), uri, NULL);
3050 g_free(file);
3053 static GFile*
3054 ifile_get_file (IAnjutaFile *manager, GError **err)
3056 DEBUG_PRINT ("Unsupported operation");
3057 return NULL;
3060 static void
3061 ifile_iface_init (IAnjutaFileIface *iface)
3063 iface->open = ifile_open;
3064 iface->get_file = ifile_get_file;
3068 /* IAnjutaBuilder implementation
3069 *---------------------------------------------------------------------------*/
3071 static IAnjutaBuilderHandle
3072 ibuilder_is_built (IAnjutaBuilder *builder, const gchar *uri,
3073 IAnjutaBuilderCallback callback, gpointer user_data,
3074 GError **err)
3076 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
3077 BuildContext *context;
3078 gchar *filename;
3079 gchar *dirname;
3080 gchar **argv;
3081 gchar **args = g_new0 (gchar *, 2);
3082 GFile* file = g_file_new_for_uri (uri);
3084 filename = g_file_get_path (file);
3085 g_object_unref (file);
3086 if (filename == NULL) return NULL;
3087 args[0] = g_path_get_basename (filename);
3088 dirname = g_path_get_dirname (filename);
3089 g_free (filename);
3090 argv = build_argv_command (NULL, CHOOSE_COMMAND (plugin, IS_BUILT), args);
3092 context = build_execute_command_full (plugin, dirname, argv,
3093 TRUE, FALSE, NULL,
3094 callback, user_data, err);
3095 g_free (dirname);
3097 return (IAnjutaBuilderHandle)context;
3100 static IAnjutaBuilderHandle
3101 ibuilder_build (IAnjutaBuilder *builder, const gchar *uri,
3102 IAnjutaBuilderCallback callback, gpointer user_data,
3103 GError **err)
3105 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
3106 BuildContext *context;
3107 gchar *filename;
3108 gchar *dirname;
3109 gchar **argv;
3110 gchar **args = g_new0 (gchar *, 2);
3111 GFile* file = g_file_new_for_uri (uri);
3113 filename = g_file_get_path (file);
3114 g_object_unref (file);
3115 if (filename == NULL) return NULL;
3116 args[0] = g_path_get_basename (filename);
3117 dirname = g_path_get_dirname (filename);
3118 g_free (filename);
3119 argv = build_argv_command (NULL, CHOOSE_COMMAND (plugin, BUILD), args);
3121 context = build_execute_command_full (plugin, dirname, argv,
3122 TRUE, TRUE, NULL,
3123 callback, user_data, err);
3124 g_free (dirname);
3126 return (IAnjutaBuilderHandle)context;
3129 static void
3130 ibuilder_cancel (IAnjutaBuilder *builder, IAnjutaBuilderHandle handle, GError **err)
3132 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
3134 build_cancel_command (plugin, (BuildContext *)handle, err);
3137 static void
3138 ibuilder_iface_init (IAnjutaBuilderIface *iface)
3140 iface->is_built = ibuilder_is_built;
3141 iface->build = ibuilder_build;
3142 iface->cancel = ibuilder_cancel;
3145 /* IAnjutaPreferences implementation
3146 *---------------------------------------------------------------------------*/
3148 static GladeXML *gxml;
3150 static void
3151 ipreferences_merge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
3153 GtkWidget *root_check;
3154 GtkWidget *entry;
3156 /* Create the preferences page */
3157 gxml = glade_xml_new (GLADE_FILE, BUILD_PREFS_DIALOG, NULL);
3158 root_check = glade_xml_get_widget(gxml, INSTALL_ROOT_CHECK);
3159 entry = glade_xml_get_widget(gxml, INSTALL_ROOT_ENTRY);
3160 g_signal_connect(G_OBJECT(root_check), "toggled", G_CALLBACK(on_root_check_toggled), entry);
3161 on_root_check_toggled (root_check, entry);
3162 root_check = glade_xml_get_widget(gxml, PARALLEL_MAKE_CHECK);
3163 entry = glade_xml_get_widget(gxml, PARALLEL_MAKE_SPIN);
3164 g_signal_connect(G_OBJECT(root_check), "toggled", G_CALLBACK(on_root_check_toggled), entry);
3165 on_root_check_toggled (root_check, entry);
3167 anjuta_preferences_add_page (prefs, gxml, BUILD_PREFS_ROOT, _("Build Autotools"), ICON_FILE);
3170 static void
3171 ipreferences_unmerge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
3173 GtkWidget *root_check;
3174 GtkWidget *entry;
3176 root_check = glade_xml_get_widget(gxml, INSTALL_ROOT_CHECK);
3177 entry = glade_xml_get_widget(gxml, INSTALL_ROOT_ENTRY);
3178 g_signal_handlers_disconnect_by_func(G_OBJECT(root_check),
3179 G_CALLBACK(on_root_check_toggled), entry);
3180 root_check = glade_xml_get_widget(gxml, PARALLEL_MAKE_CHECK);
3181 entry = glade_xml_get_widget(gxml, PARALLEL_MAKE_SPIN);
3182 g_signal_handlers_disconnect_by_func(G_OBJECT(root_check),
3183 G_CALLBACK(on_root_check_toggled), entry);
3185 anjuta_preferences_remove_page(prefs, _("Build Autotools"));
3187 g_object_unref (gxml);
3190 static void
3191 ipreferences_iface_init(IAnjutaPreferencesIface* iface)
3193 iface->merge = ipreferences_merge;
3194 iface->unmerge = ipreferences_unmerge;
3197 ANJUTA_PLUGIN_BEGIN (BasicAutotoolsPlugin, basic_autotools_plugin);
3198 ANJUTA_PLUGIN_ADD_INTERFACE (ibuilder, IANJUTA_TYPE_BUILDER);
3199 ANJUTA_PLUGIN_ADD_INTERFACE (ibuildable, IANJUTA_TYPE_BUILDABLE);
3200 ANJUTA_PLUGIN_ADD_INTERFACE (ifile, IANJUTA_TYPE_FILE);
3201 ANJUTA_PLUGIN_ADD_INTERFACE (ipreferences, IANJUTA_TYPE_PREFERENCES);
3202 ANJUTA_PLUGIN_END;
3204 ANJUTA_SIMPLE_PLUGIN (BasicAutotoolsPlugin, basic_autotools_plugin);