jbsrc/lib/src/core/jb-feature.c (9504B) - raw
1 /*
2 * JB, the Jean-Yves Lefort's Build System
3 * Copyright (C) 2008 Jean-Yves Lefort <jylefort@brutele.be>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include "jb-util.h"
23 #include "jb-variable.h"
24 #include "jb-tests.h"
25 #include "jb-feature.h"
26
27 typedef struct
28 {
29 int major;
30 int minor;
31 int micro;
32 } Version;
33
34 static const JBFeature **_features = NULL;
35 static int _num_features = 0;
36
37 gboolean jb_intltool_use_xml = TRUE;
38
39 void
40 jb_feature_set_list (const JBFeature **features, int num_features)
41 {
42 g_return_if_fail(features != NULL);
43
44 _features = features;
45 _num_features = num_features;
46 }
47
48 gboolean
49 jb_feature_is_enabled (JBFeature *feature)
50 {
51 int i;
52
53 g_return_val_if_fail(feature != NULL, FALSE);
54
55 for (i = 0; i < _num_features; i++)
56 if (_features[i] == feature)
57 return TRUE;
58
59 return FALSE;
60 }
61
62 void
63 jb_feature_init (void)
64 {
65 int i;
66
67 for (i = 0; i < _num_features; i++)
68 {
69 const JBFeature *feature = _features[i];
70
71 if (feature->init)
72 feature->init();
73 }
74 }
75
76 void
77 jb_feature_configure (void)
78 {
79 int i;
80
81 for (i = 0; i < _num_features; i++)
82 {
83 const JBFeature *feature = _features[i];
84
85 if (feature->configure)
86 feature->configure();
87 }
88 }
89
90 static void
91 pkg_config_init (void)
92 {
93 /* NO_REPORT since it is only used in configure */
94 jb_register_program("pkg-config", JB_VARIABLE_NO_REPORT);
95 }
96
97 static void
98 gettext_init (void)
99 {
100 jb_register_program("msgfmt", 0);
101 }
102
103 static void
104 gettext_configure (void)
105 {
106 static const char *functions = "ngettext dgettext bind_textdomain_codeset";
107
108 if (jb_check_functions(functions, NULL))
109 jb_variable_set_package_flags("gettext", NULL, "-DENABLE_NLS", NULL, NULL);
110 else if (jb_check_functions(functions, "intl"))
111 jb_variable_set_package_flags("gettext", NULL, "-DENABLE_NLS", NULL, "-lintl");
112 else
113 jb_error("gettext found neither in libc nor in libintl");
114
115 jb_require_program("msgfmt");
116 }
117
118 static void
119 intltool_init (void)
120 {
121 jb_register_program("perl", 0);
122 }
123
124 static void
125 intltool_configure (void)
126 {
127 jb_require_program("perl");
128
129 if (jb_intltool_use_xml)
130 {
131 gboolean result;
132
133 jb_message_checking("for XML::Parser");
134 result = jb_exec_expand(NULL, NULL, "$perl -e 'require XML::Parser'", NULL);
135 jb_message_result_bool(result);
136
137 if (! result)
138 jb_error("intltool requires the XML::Parser Perl module");
139 }
140 }
141
142 static void
143 gconf_init (void)
144 {
145 jb_register_program("gconftool-2", 0);
146
147 jb_variable_add_string("gconf-config-source",
148 "GConf configuration source address",
149 jb_variable_group_installation_options,
150 0,
151 "autodetect");
152 jb_variable_add_string("gconf-schemas-dir",
153 "GConf schemas installation directory",
154 jb_variable_group_installation_options,
155 0,
156 "$sysconfdir/gconf/schemas");
157 jb_variable_add_bool("install-gconf-schemas",
158 "install GConf schemas",
159 jb_variable_group_installation_options,
160 0,
161 TRUE);
162 }
163
164 static void
165 gconf_configure (void)
166 {
167 JBVariable *variable;
168
169 jb_require_program("gconftool-2");
170
171 if (! strcmp(jb_variable_get_string("gconf-config-source"), "autodetect"))
172 {
173 char *config_source;
174
175 if (! jb_exec_expand(&config_source, NULL, "$gconftool-2 --get-default-source", NULL))
176 jb_error("unable to detect the GConf configuration source address");
177
178 jb_variable_set_string("gconf-config-source", config_source);
179 g_free(config_source);
180 }
181
182 /* fix the default schemas dir on Ubuntu */
183 variable = jb_variable_get_variable_or_error("gconf-schemas-dir");
184 if (! variable->user_set)
185 {
186 static const char *ubuntu_dir = "$datadir/gconf/schemas";
187 char *expanded;
188
189 expanded = jb_variable_expand(ubuntu_dir, NULL);
190
191 if (g_file_test(expanded, G_FILE_TEST_IS_DIR))
192 jb_variable_set_string("gconf-schemas-dir", ubuntu_dir);
193
194 g_free(expanded);
195 }
196 }
197
198 static void
199 gnome_help_init (void)
200 {
201 /* NO_REPORT since it is only used in configure */
202 jb_register_program("scrollkeeper-config", JB_VARIABLE_NO_REPORT);
203 jb_register_program("scrollkeeper-preinstall", 0);
204 jb_register_program("scrollkeeper-update", 0);
205
206 jb_variable_add_string("help-dir",
207 "GNOME help directory",
208 jb_variable_group_installation_options,
209 0,
210 "$datadir/gnome/help");
211 jb_variable_add_string("omf-dir",
212 "OMF directory",
213 jb_variable_group_installation_options,
214 0,
215 "autodetect");
216 jb_variable_add_string("scrollkeeper-dir",
217 "ScrollKeeper database directory",
218 jb_variable_group_installation_options,
219 0,
220 "autodetect");
221 }
222
223 static void
224 gnome_help_check_dir (const char *name,
225 const char *description,
226 const char *scrollkeeper_config_arg)
227 {
228 const char *dir;
229 char *result;
230
231 dir = jb_variable_get_string(name);
232 if (strcmp(dir, "autodetect"))
233 return;
234
235 jb_require_program("scrollkeeper-config");
236
237 jb_message_checking("for the %s", description);
238
239 if (jb_exec_expand(&result, NULL, "$scrollkeeper-config $arg",
240 "arg", scrollkeeper_config_arg,
241 NULL))
242 {
243 jb_message_result_string(result);
244 jb_variable_set_string(name, result);
245 }
246 else
247 {
248 jb_message_result_string("not found");
249 jb_error("unable to autodetect the %s", description);
250 }
251
252 g_free(result);
253 }
254
255 static void
256 gnome_help_configure (void)
257 {
258 jb_require_program("scrollkeeper-preinstall");
259 jb_require_program("scrollkeeper-update");
260
261 gnome_help_check_dir("omf-dir",
262 "OMF directory",
263 "--omfdir");
264 gnome_help_check_dir("scrollkeeper-dir",
265 "ScrollKeeper database directory",
266 "--pkglocalstatedir");
267 }
268
269 static gboolean
270 parse_version (const char *version_string, Version *version)
271 {
272 int _major;
273 int _minor;
274 int _micro;
275
276 switch (sscanf(version_string, "%d.%d.%d", &_major, &_minor, &_micro))
277 {
278 case 1:
279 version->major = _major;
280 version->minor = 0;
281 version->micro = 0;
282 return TRUE;
283
284 case 2:
285 version->major = _major;
286 version->minor = _minor;
287 version->micro = 0;
288 return TRUE;
289
290 case 3:
291 version->major = _major;
292 version->minor = _minor;
293 version->micro = _micro;
294 return TRUE;
295
296 default:
297 return FALSE;
298 }
299 }
300
301 static int
302 version_to_int (Version *version)
303 {
304 return (version->major << 16) + (version->minor << 8) + version->micro;
305 }
306
307 static void
308 gob2_init (void)
309 {
310 jb_register_program("gob2", 0);
311 jb_variable_set_string("gob2-minversion", "2.0");
312 }
313
314 static gboolean
315 parse_gob2_version_output (char *str,
316 char **version_string,
317 Version *version)
318 {
319 char *space;
320 char *_version_string;
321
322 space = strrchr(str, ' ');
323 if (space == NULL)
324 return FALSE;
325
326 _version_string = space + 1;
327 if (parse_version(_version_string, version))
328 {
329 *version_string = _version_string;
330 return TRUE;
331 }
332
333 return FALSE;
334 }
335
336 static char *
337 get_gob2_not_found_error (const char *minversion)
338 {
339 return g_strdup_printf("One or more .gob source files were modified but gob2 was not found. Please install gob2 >= %s and run configure again.",
340 minversion);
341 }
342
343 static void
344 gob2_configure (void)
345 {
346 const char *minversion_string;
347 Version minversion;
348 char *error = NULL;
349
350 minversion_string = jb_variable_get_string("gob2-minversion");
351 if (! parse_version(minversion_string, &minversion))
352 g_error("invalid gob2-minversion \"%s\"", minversion_string);
353
354 if (jb_check_program("gob2"))
355 {
356 char *output;
357 gboolean result = FALSE;
358
359 jb_message_checking("for gob2 >= %s", minversion_string);
360
361 if (jb_exec_expand(NULL, &output, "$gob2 --version", NULL))
362 {
363 char *version_string;
364 Version version;
365
366 if (parse_gob2_version_output(output, &version_string, &version))
367 {
368 if (version_to_int(&version) >= version_to_int(&minversion))
369 result = TRUE;
370 else
371 error = g_strdup_printf("One or more .gob source files were modified but the version of gob2 (%s) is too old. Please install gob2 >= %s and run configure again.",
372 version_string,
373 minversion_string);
374 }
375 else
376 error = get_gob2_not_found_error(minversion_string);
377 }
378 else
379 error = get_gob2_not_found_error(minversion_string);
380
381 g_free(output);
382
383 jb_message_result_bool(result);
384 }
385 else
386 error = get_gob2_not_found_error(minversion_string);
387
388 jb_variable_set_string("gob2-error", error);
389 g_free(error);
390 }
391
392 JBFeature jb_pkg_config_feature = {
393 pkg_config_init,
394 NULL
395 };
396
397 JBFeature jb_gettext_feature = {
398 gettext_init,
399 gettext_configure
400 };
401
402 JBFeature jb_intltool_feature = {
403 intltool_init,
404 intltool_configure
405 };
406
407 JBFeature jb_gconf_feature = {
408 gconf_init,
409 gconf_configure
410 };
411
412 JBFeature jb_gnome_help_feature = {
413 gnome_help_init,
414 gnome_help_configure
415 };
416
417 JBFeature jb_gob2_feature = {
418 gob2_init,
419 gob2_configure
420 };