jbsrc/lib/src/core/jb-resource.c (46793B) - 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 <string.h>
21 #include "jb-resource.h"
22 #include "jb-group.h"
23 #include "jb-variable.h"
24 #include "jb-util.h"
25 #include "jb-feature.h"
26 #include "jb-action.h"
27
28 #define INTLTOOL_MERGE_IN "jbsrc/tools/intltool-merge.in"
29 #define INTLTOOL_MERGE_OUT "build/jbsrc/tools/intltool-merge"
30 #define INTLTOOL_MERGE_CACHE "build/jbsrc/tools/intltool-merge-cache"
31
32 static gboolean
33 has_template (const char *filename)
34 {
35 char *template_input;
36 gboolean result;
37
38 if (jb_templates == NULL)
39 return FALSE;
40
41 template_input = g_strdup_printf("%s.in", filename);
42 result = jb_string_hash_set_contains(jb_templates, template_input);
43 g_free(template_input);
44
45 return result;
46 }
47
48 static char *
49 get_input_file (const char *filename)
50 {
51 if (has_template(filename))
52 return g_strdup_printf("build/%s", filename);
53 else
54 return g_strdup(filename);
55 }
56
57 static char *
58 get_output_file (const char *filename)
59 {
60 char *tmp;
61 char *result;
62
63 g_return_val_if_fail(filename != NULL, NULL);
64 g_return_val_if_fail(g_str_has_suffix(filename, ".in"), NULL);
65
66 tmp = jb_strip_extension(filename);
67
68 /*
69 * If the input file is already in build/, do not put the output
70 * file in build/build/.
71 */
72 if (g_str_has_prefix(tmp, "build/"))
73 result = g_strdup(tmp);
74 else
75 result = g_strdup_printf("build/%s", tmp);
76
77 g_free(tmp);
78
79 return result;
80 }
81
82 G_DEFINE_ABSTRACT_TYPE(JBResource, jb_resource, G_TYPE_OBJECT)
83
84 char *
85 jb_resource_to_string (JBResource *self)
86 {
87 JBResourceClass *class;
88
89 g_return_val_if_fail(JB_IS_RESOURCE(self), NULL);
90
91 class = JB_RESOURCE_GET_CLASS(self);
92
93 if (class->to_string != NULL)
94 return class->to_string(self);
95 else
96 {
97 g_error("to_string() not implemented for resource type %s", G_OBJECT_TYPE_NAME(self));
98 return NULL;
99 }
100 }
101
102 void
103 jb_resource_pre_build (JBResource *self)
104 {
105 JBResourceClass *class;
106
107 g_return_if_fail(JB_IS_RESOURCE(self));
108
109 class = JB_RESOURCE_GET_CLASS(self);
110
111 if (class->pre_build != NULL)
112 class->pre_build(self);
113 }
114
115 void
116 jb_resource_build (JBResource *self)
117 {
118 JBResourceClass *class;
119
120 g_return_if_fail(JB_IS_RESOURCE(self));
121
122 class = JB_RESOURCE_GET_CLASS(self);
123
124 if (class->build != NULL)
125 class->build(self);
126 }
127
128 void
129 jb_resource_install (JBResource *self)
130 {
131 JBResourceClass *class;
132
133 g_return_if_fail(JB_IS_RESOURCE(self));
134
135 class = JB_RESOURCE_GET_CLASS(self);
136
137 if (class->install != NULL)
138 class->install(self);
139 }
140
141 void
142 jb_resource_makedist (JBResource *self)
143 {
144 JBResourceClass *class;
145
146 g_return_if_fail(JB_IS_RESOURCE(self));
147
148 class = JB_RESOURCE_GET_CLASS(self);
149
150 if (class->makedist != NULL)
151 class->makedist(self);
152 }
153
154 void
155 jb_resource_clean (JBResource *self)
156 {
157 JBResourceClass *class;
158
159 g_return_if_fail(JB_IS_RESOURCE(self));
160
161 class = JB_RESOURCE_GET_CLASS(self);
162
163 if (class->clean != NULL)
164 class->clean(self);
165 }
166
167 void
168 jb_resource_distclean (JBResource *self)
169 {
170 JBResourceClass *class;
171
172 g_return_if_fail(JB_IS_RESOURCE(self));
173
174 class = JB_RESOURCE_GET_CLASS(self);
175
176 if (class->distclean != NULL)
177 class->distclean(self);
178 }
179
180 void
181 jb_resource_maintainerclean (JBResource *self)
182 {
183 JBResourceClass *class;
184
185 g_return_if_fail(JB_IS_RESOURCE(self));
186
187 class = JB_RESOURCE_GET_CLASS(self);
188
189 if (class->maintainerclean != NULL)
190 class->maintainerclean(self);
191 }
192
193 static void
194 resource_action_message (JBResource *self, const char *action)
195 {
196 char *repr;
197
198 g_return_if_fail(JB_IS_RESOURCE(self));
199 g_return_if_fail(action != NULL);
200
201 repr = jb_resource_to_string(self);
202 jb_message("%s %s", action, repr);
203 g_free(repr);
204 }
205
206 void
207 jb_resource_message_building (JBResource *self)
208 {
209 g_return_if_fail(JB_IS_RESOURCE(self));
210
211 resource_action_message(self, "building");
212 }
213
214 static void
215 jb_resource_init (JBResource *self)
216 {
217 }
218
219 static void
220 jb_resource_class_init (JBResourceClass *class)
221 {
222 }
223
224 G_DEFINE_ABSTRACT_TYPE(JBGroupResource, jb_group_resource, JB_TYPE_RESOURCE)
225
226 static void
227 jb_group_resource_init (JBGroupResource *self)
228 {
229 }
230
231 static void
232 jb_group_resource_class_init (JBGroupResourceClass *class)
233 {
234 }
235
236 G_DEFINE_ABSTRACT_TYPE(JBObjectResource, jb_object_resource, JB_TYPE_RESOURCE)
237
238 static void
239 jb_object_resource_init (JBObjectResource *self)
240 {
241 }
242
243 static void
244 jb_object_resource_class_init (JBObjectResourceClass *class)
245 {
246 }
247
248 static char *
249 object_resource_get_object_file (JBObjectResource *self)
250 {
251 JBObjectResourceClass *class;
252
253 g_return_val_if_fail(JB_IS_OBJECT_RESOURCE(self), NULL);
254
255 class = JB_OBJECT_RESOURCE_GET_CLASS(self);
256
257 if (class->get_object_file != NULL)
258 return class->get_object_file(self);
259 else
260 {
261 g_error("get_object_file() not implemented for object resource type %s", G_OBJECT_TYPE_NAME(self));
262 return NULL;
263 }
264 }
265
266 G_DEFINE_TYPE(JBTemplate, jb_template, JB_TYPE_GROUP_RESOURCE)
267
268 JBTemplate *
269 jb_template_new (const char *filename)
270 {
271 JBTemplate *self;
272
273 g_return_val_if_fail(filename != NULL, NULL);
274 g_return_val_if_fail(g_str_has_suffix(filename, ".in"), NULL);
275
276 self = g_object_new(JB_TYPE_TEMPLATE, NULL);
277 self->filename = g_strdup(filename);
278
279 return self;
280 }
281
282 static char *
283 template_to_string (JBResource *res)
284 {
285 JBTemplate *self = JB_TEMPLATE(res);
286
287 return g_strdup_printf("template %s", self->filename);
288 }
289
290 static void
291 template_get_files (JBTemplate *self, char **infile, char **outfile)
292 {
293 JBGroupResource *gres = JB_GROUP_RESOURCE(self);
294
295 if (infile != NULL)
296 *infile = g_strdup_printf("%s/%s", gres->group->srcdir, self->filename);
297 if (outfile != NULL)
298 {
299 char *tmp;
300
301 tmp = jb_strip_extension(self->filename);
302 *outfile = g_strdup_printf("%s/%s", gres->group->builddir, tmp);
303 g_free(tmp);
304 }
305 }
306
307 static void
308 template_build (JBResource *res)
309 {
310 JBTemplate *self = JB_TEMPLATE(res);
311 char *infile;
312 char *outfile;
313
314 template_get_files(self, &infile, &outfile);
315
316 if (! jb_is_uptodate(outfile, infile))
317 {
318 static GHashTable *variables = NULL;
319
320 jb_resource_message_building(res);
321
322 if (variables == NULL)
323 {
324 GSList *l;
325
326 variables = g_hash_table_new(g_str_hash, g_str_equal);
327
328 JB_LIST_FOREACH(l, jb_variables)
329 {
330 JBVariable *variable = l->data;
331
332 g_hash_table_insert(variables, variable->name, jb_variable_evaluate(variable));
333 }
334 }
335
336 jb_mkdir_of_file(outfile);
337
338 jb_subst(infile, outfile, variables);
339 }
340
341 g_free(infile);
342 g_free(outfile);
343 }
344
345 static void
346 template_makedist (JBResource *res)
347 {
348 JBTemplate *self = JB_TEMPLATE(res);
349 char *infile;
350
351 template_get_files(self, &infile, NULL);
352
353 jb_action_add_to_dist(infile);
354
355 g_free(infile);
356 }
357
358 static void
359 template_clean (JBResource *res)
360 {
361 JBTemplate *self = JB_TEMPLATE(res);
362 char *outfile;
363
364 template_get_files(self, NULL, &outfile);
365
366 jb_action_rm(outfile);
367
368 g_free(outfile);
369 }
370
371 static void
372 jb_template_init (JBTemplate *self)
373 {
374 }
375
376 static void
377 jb_template_class_init (JBTemplateClass *class)
378 {
379 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
380
381 rclass->to_string = template_to_string;
382 rclass->build = template_build;
383 rclass->makedist = template_makedist;
384 rclass->clean = template_clean;
385 }
386
387 G_DEFINE_TYPE(JBDataFile, jb_data_file, JB_TYPE_GROUP_RESOURCE)
388
389 JBDataFile *
390 jb_data_file_new (const char *filename)
391 {
392 JBDataFile *self;
393
394 g_return_val_if_fail(filename != NULL, NULL);
395
396 self = g_object_new(JB_TYPE_DATA_FILE, NULL);
397 self->filename = g_strdup(filename);
398
399 return self;
400 }
401
402 static char *
403 data_file_to_string (JBResource *res)
404 {
405 JBDataFile *self = JB_DATA_FILE(res);
406
407 return g_strdup_printf("data file %s", self->filename);
408 }
409
410 static void
411 data_file_install (JBResource *res)
412 {
413 JBDataFile *self = JB_DATA_FILE(res);
414 JBGroupResource *gres = JB_GROUP_RESOURCE(res);
415 char *srcfile;
416 char *real_srcfile;
417 char *dstfile;
418
419 srcfile = g_strdup_printf("%s/%s", gres->group->srcdir, self->filename);
420 real_srcfile = get_input_file(srcfile);
421 dstfile = g_path_get_basename(self->filename);
422
423 jb_install_options_install_data(self->install_options, real_srcfile, dstfile);
424
425 g_free(srcfile);
426 g_free(real_srcfile);
427 g_free(dstfile);
428 }
429
430 static void
431 data_file_makedist (JBResource *res)
432 {
433 JBDataFile *self = JB_DATA_FILE(res);
434 JBGroupResource *gres = JB_GROUP_RESOURCE(res);
435 char *file;
436
437 file = g_strdup_printf("%s/%s", gres->group->srcdir, self->filename);
438
439 if (! has_template(file))
440 jb_action_add_to_dist(file);
441
442 g_free(file);
443 }
444
445 static void
446 jb_data_file_init (JBDataFile *self)
447 {
448 self->install_options = jb_install_options_new();
449 }
450
451 static void
452 jb_data_file_class_init (JBDataFileClass *class)
453 {
454 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
455
456 rclass->to_string = data_file_to_string;
457 rclass->install = data_file_install;
458 rclass->makedist = data_file_makedist;
459 }
460
461 static GSList *
462 parse_depsfile (const char *depsfile)
463 {
464 char *contents;
465 char **lines;
466 GSList *deps = NULL;
467 int i;
468
469 contents = jb_read_file(depsfile, NULL);
470 if (contents == NULL)
471 return NULL; /* depsfile is optional */
472
473 lines = g_strsplit(contents, "\n", 0);
474 g_free(contents);
475
476 for (i = 0; lines[i] != NULL; i++)
477 {
478 char *p;
479 char **files;
480 int j;
481
482 p = strchr(lines[i], ':');
483 if (p != NULL)
484 p++;
485 else
486 p = lines[i];
487
488 files = g_strsplit(p, " ", 0);
489
490 for (j = 0; files[j] != NULL; j++)
491 {
492 char *work;
493 char *file;
494
495 work = g_strdup(files[j]);
496 file = g_strstrip(work);
497
498 if (*file != '\0' && *file != '\\')
499 deps = g_slist_prepend(deps, g_strdup(file));
500
501 g_free(work);
502 }
503
504 g_strfreev(files);
505 }
506
507 return deps;
508 }
509
510 static char *
511 object_file_get_depsfile (const char *ofile)
512 {
513 return g_strdup_printf("%s.deps", ofile);
514 }
515
516 static gboolean
517 object_file_is_uptodate (const char *ofile, const char *cfile)
518 {
519 char *depsfile;
520 GSList *deps;
521
522 if (! jb_variable_get_bool("cc-dependency-tracking"))
523 return FALSE;
524
525 if (! jb_is_uptodate(ofile, cfile))
526 return FALSE;
527
528 depsfile = object_file_get_depsfile(ofile);
529 deps = parse_depsfile(depsfile);
530 g_free(depsfile);
531
532 if (deps != NULL)
533 {
534 gboolean is_uptodate;
535
536 is_uptodate = jb_is_uptodate_list(ofile, deps);
537
538 jb_g_slist_free_deep(deps);
539
540 return is_uptodate;
541 }
542 else
543 return TRUE;
544 }
545
546 static void
547 object_file_build (JBObject *object, const char *ofile, const char *cfile)
548 {
549 JBGroupResource *gres = JB_GROUP_RESOURCE(object);
550 JBObjectClass *object_class;
551 char *depsfile;
552 char *depsflags = NULL;
553
554 object_class = JB_OBJECT_GET_CLASS(object);
555
556 depsfile = object_file_get_depsfile(ofile);
557
558 if (jb_variable_get_bool("cc-dependency-tracking"))
559 depsflags = jb_variable_expand(" -MT $ofile -MD -MP -MF $depsfile",
560 "ofile", ofile,
561 "depsfile", depsfile,
562 NULL);
563
564 jb_mkdir_of_file(ofile);
565
566 jb_action_exec("$cc -c -o $ofile"
567 " $package-cflags $group-cflags $object-cflags $stock-cflags $cflags"
568 " $package-cppflags $group-cppflags $object-cppflags $stock-cppflags $cppflags"
569 " $depsflags $cfile",
570 "package-cflags", jb_compile_options_get_cflags(jb_compile_options),
571 "group-cflags", jb_compile_options_get_cflags(gres->group->compile_options),
572 "object-cflags", jb_compile_options_get_cflags(object->compile_options),
573 "stock-cflags", object_class->stock_cflags,
574 "package-cppflags", jb_compile_options_get_cppflags(jb_compile_options),
575 "group-cppflags", jb_compile_options_get_cppflags(gres->group->compile_options),
576 "object-cppflags", jb_compile_options_get_cppflags(object->compile_options),
577 "stock-cppflags", object_class->stock_cppflags,
578 "depsflags", depsflags,
579 "ofile", ofile,
580 "cfile", cfile,
581 NULL);
582
583 g_free(depsfile);
584 g_free(depsflags);
585 }
586
587 static void
588 object_file_clean (const char *ofile)
589 {
590 char *depsfile;
591
592 depsfile = object_file_get_depsfile(ofile);
593
594 jb_action_rm(ofile);
595 jb_action_rm(depsfile);
596
597 g_free(depsfile);
598 }
599
600 G_DEFINE_TYPE(JBSource, jb_source, JB_TYPE_OBJECT_RESOURCE)
601
602 JBSource *
603 jb_source_new (const char *filename)
604 {
605 JBSource *self;
606
607 g_return_val_if_fail(filename != NULL, NULL);
608
609 self = g_object_new(JB_TYPE_SOURCE, NULL);
610 self->filename = g_strdup(filename);
611
612 return self;
613 }
614
615 static char *
616 source_to_string (JBResource *res)
617 {
618 JBSource *self = JB_SOURCE(res);
619 char *base_filename;
620 char *str;
621
622 base_filename = g_path_get_basename(self->filename);
623 str = g_strdup_printf("C source %s", base_filename);
624 g_free(base_filename);
625
626 return str;
627 }
628
629 static void
630 source_get_files (JBSource *self, char **ofile, char **cfile)
631 {
632 JBObjectResource *ores = JB_OBJECT_RESOURCE(self);
633 JBGroupResource *gres = JB_GROUP_RESOURCE(ores->object);
634 char *base_filename;
635 char *base_prefix;
636
637 base_filename = g_path_get_basename(self->filename);
638 base_prefix = jb_strip_extension(base_filename);
639
640 if (ofile != NULL)
641 *ofile = g_strdup_printf("%s/%s-%s.o",
642 gres->group->builddir,
643 ores->object->name,
644 base_prefix);
645 if (cfile != NULL)
646 *cfile = g_strdup_printf("%s/%s", gres->group->srcdir, self->filename);
647
648 g_free(base_filename);
649 g_free(base_prefix);
650 }
651
652 static void
653 source_build (JBResource *res)
654 {
655 JBObjectResource *ores = JB_OBJECT_RESOURCE(res);
656 JBSource *self = JB_SOURCE(res);
657 char *ofile;
658 char *cfile;
659
660 source_get_files(self, &ofile, &cfile);
661
662 if (! object_file_is_uptodate(ofile, cfile))
663 {
664 jb_resource_message_building(res);
665 object_file_build(ores->object, ofile, cfile);
666 }
667
668 g_free(ofile);
669 g_free(cfile);
670 }
671
672 static void
673 source_makedist (JBResource *res)
674 {
675 JBSource *self = JB_SOURCE(res);
676 char *cfile;
677
678 source_get_files(self, NULL, &cfile);
679
680 jb_action_add_to_dist(cfile);
681
682 g_free(cfile);
683 }
684
685 static void
686 source_clean (JBResource *res)
687 {
688 JBSource *self = JB_SOURCE(res);
689 char *ofile;
690
691 source_get_files(self, &ofile, NULL);
692
693 object_file_clean(ofile);
694
695 g_free(ofile);
696 }
697
698 static char *
699 source_get_object_file (JBObjectResource *res)
700 {
701 JBSource *self = JB_SOURCE(res);
702 char *ofile;
703
704 source_get_files(self, &ofile, NULL);
705
706 return ofile;
707 }
708
709 static void
710 jb_source_init (JBSource *self)
711 {
712 }
713
714 static void
715 jb_source_class_init (JBSourceClass *class)
716 {
717 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
718 JBObjectResourceClass *orclass = JB_OBJECT_RESOURCE_CLASS(class);
719
720 rclass->to_string = source_to_string;
721 rclass->build = source_build;
722 rclass->makedist = source_makedist;
723 rclass->clean = source_clean;
724
725 orclass->get_object_file = source_get_object_file;
726 }
727
728 G_DEFINE_TYPE(JBGobClass, jb_gob_class, JB_TYPE_OBJECT_RESOURCE)
729
730 JBGobClass *
731 jb_gob_class_new (const char *name)
732 {
733 JBGobClass *self;
734
735 g_return_val_if_fail(name != NULL, NULL);
736 g_return_val_if_fail(jb_feature_is_enabled(&jb_gob2_feature), NULL);
737
738 self = g_object_new(JB_TYPE_GOB_CLASS, NULL);
739 self->name = g_strdup(name);
740
741 return self;
742 }
743
744 static void
745 gob_class_get_gob_files (JBGobClass *self, char **gobfile, char **stamp)
746 {
747 JBGroupResource *gres = JB_GROUP_RESOURCE(JB_OBJECT_RESOURCE(self)->object);
748 char *prefix;
749
750 prefix = g_strdelimit(g_ascii_strdown(self->name, -1), ":", '-');
751 if (gobfile != NULL)
752 *gobfile = g_strdup_printf("%s/%s.gob", gres->group->srcdir, prefix);
753 if (stamp != NULL)
754 *stamp = g_strdup_printf("%s/%s.gob.stamp", gres->group->builddir, prefix);
755 g_free(prefix);
756 }
757
758 static void
759 gob_class_pre_build (JBResource *res)
760 {
761 JBGobClass *self = JB_GOB_CLASS(res);
762 char *gobfile;
763 char *stamp;
764
765 gob_class_get_gob_files(self, &gobfile, &stamp);
766
767 if (! jb_is_uptodate(stamp, gobfile))
768 {
769 JBObjectResource *ores = JB_OBJECT_RESOURCE(res);
770 JBGroupResource *gres = JB_GROUP_RESOURCE(ores->object);
771 const char *error;
772
773 error = jb_variable_get_string_or_null("gob2-error");
774 if (error != NULL)
775 jb_error("%s", error);
776
777 jb_message("building GOB class %s", self->name);
778
779 jb_mkdir(gres->group->builddir);
780
781 jb_action_exec("$gob2 $package-gob2flags $group-gob2flags $object-gob2flags $gobfile",
782 "package-gob2flags", jb_compile_options_get_gob2flags(jb_compile_options),
783 "group-gob2flags", jb_compile_options_get_gob2flags(gres->group->compile_options),
784 "object-gob2flags", jb_compile_options_get_gob2flags(ores->object->compile_options),
785 "gobfile", gobfile,
786 NULL);
787
788 jb_action_exec("touch $stamp",
789 "stamp", stamp,
790 NULL);
791 }
792
793 g_free(gobfile);
794 g_free(stamp);
795 }
796
797 static void
798 gob_class_get_c_files (JBGobClass *self,
799 char **ofile,
800 char **cfile,
801 char **hfile,
802 char **phfile)
803 {
804 JBObjectResource *ores = JB_OBJECT_RESOURCE(self);
805 JBGroupResource *gres = JB_GROUP_RESOURCE(ores->object);
806 char *prefix;
807
808 prefix = g_strdelimit(g_ascii_strdown(self->name, -1), ":", '-');
809
810 if (ofile != NULL)
811 *ofile = g_strdup_printf("%s/%s-%s.o",
812 gres->group->builddir,
813 ores->object->name,
814 prefix);
815 if (cfile != NULL)
816 *cfile = g_strdup_printf("%s/%s.c", gres->group->builddir, prefix);
817 if (hfile != NULL)
818 *hfile = g_strdup_printf("%s/%s.h", gres->group->builddir, prefix);
819 if (phfile != NULL)
820 *phfile = g_strdup_printf("%s/%s-private.h", gres->group->builddir, prefix);
821
822 g_free(prefix);
823 }
824
825 static void
826 gob_class_build (JBResource *res)
827 {
828 JBGobClass *self = JB_GOB_CLASS(res);
829 char *ofile;
830 char *cfile;
831
832 gob_class_get_c_files(self, &ofile, &cfile, NULL, NULL);
833
834 if (! object_file_is_uptodate(ofile, cfile))
835 {
836 JBObjectResource *ores = JB_OBJECT_RESOURCE(res);
837 char *class_name;
838
839 class_name = jb_strip_chars(self->name, ":");
840 jb_message("building class %s", class_name);
841 g_free(class_name);
842
843 object_file_build(ores->object, ofile, cfile);
844 }
845
846 g_free(ofile);
847 g_free(cfile);
848 }
849
850 static void
851 gob_class_makedist (JBResource *res)
852 {
853 JBGobClass *self = JB_GOB_CLASS(res);
854 char *gobfile;
855 char *stamp;
856 char *cfile;
857 char *hfile;
858 char *phfile;
859
860 gob_class_get_gob_files(self, &gobfile, &stamp);
861 gob_class_get_c_files(self, NULL, &cfile, &hfile, &phfile);
862
863 jb_action_add_to_dist(gobfile);
864 jb_action_add_to_dist(stamp);
865 jb_action_add_to_dist(cfile);
866 jb_action_add_to_dist(hfile);
867 jb_action_add_to_dist(phfile);
868
869 g_free(gobfile);
870 g_free(stamp);
871 g_free(cfile);
872 g_free(hfile);
873 g_free(phfile);
874 }
875
876 static void
877 gob_class_clean (JBResource *res)
878 {
879 JBGobClass *self = JB_GOB_CLASS(res);
880 char *ofile;
881
882 gob_class_get_c_files(self, &ofile, NULL, NULL, NULL);
883
884 object_file_clean(ofile);
885
886 g_free(ofile);
887 }
888
889 static void
890 gob_class_maintainerclean (JBResource *res)
891 {
892 JBGobClass *self = JB_GOB_CLASS(res);
893 char *stamp;
894 char *cfile;
895 char *hfile;
896 char *phfile;
897
898 gob_class_get_gob_files(self, NULL, &stamp);
899 gob_class_get_c_files(self, NULL, &cfile, &hfile, &phfile);
900
901 jb_action_rm(stamp);
902 jb_action_rm(cfile);
903 jb_action_rm(hfile);
904 jb_action_rm(phfile);
905
906 g_free(stamp);
907 g_free(cfile);
908 g_free(hfile);
909 g_free(phfile);
910 }
911
912 static char *
913 gob_class_get_object_file (JBObjectResource *res)
914 {
915 JBGobClass *self = JB_GOB_CLASS(res);
916 char *ofile;
917
918 gob_class_get_c_files(self, &ofile, NULL, NULL, NULL);
919
920 return ofile;
921 }
922
923 static void
924 jb_gob_class_init (JBGobClass *self)
925 {
926 }
927
928 static void
929 jb_gob_class_class_init (JBGobClassClass *class)
930 {
931 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
932 JBObjectResourceClass *orclass = JB_OBJECT_RESOURCE_CLASS(class);
933
934 rclass->pre_build = gob_class_pre_build;
935 rclass->build = gob_class_build;
936 rclass->makedist = gob_class_makedist;
937 rclass->clean = gob_class_clean;
938 rclass->maintainerclean = gob_class_maintainerclean;
939
940 orclass->get_object_file = gob_class_get_object_file;
941 }
942
943 G_DEFINE_TYPE(JBIntltoolFile, jb_intltool_file, JB_TYPE_GROUP_RESOURCE)
944
945 JBIntltoolFile *
946 jb_intltool_file_new (const char *type,
947 const char *filename,
948 const char *merge_flags)
949 {
950 JBIntltoolFile *self;
951
952 g_return_val_if_fail(type != NULL, NULL);
953 g_return_val_if_fail(filename != NULL, NULL);
954 g_return_val_if_fail(g_str_has_suffix(filename, ".in"), NULL);
955 g_return_val_if_fail(merge_flags != NULL, NULL);
956
957 self = g_object_new(JB_TYPE_INTLTOOL_FILE, NULL);
958 self->type = g_strdup(type);
959 self->filename = g_strdup(filename);
960 self->merge_flags = g_strdup(merge_flags);
961
962 return self;
963 }
964
965 static char *
966 intltool_file_to_string (JBResource *res)
967 {
968 JBIntltoolFile *self = JB_INTLTOOL_FILE(res);
969
970 return g_strdup_printf("%s %s", self->type, self->filename);
971 }
972
973 static void
974 intltool_file_get_files (JBIntltoolFile *self, char **infile, char **outfile)
975 {
976 JBGroupResource *gres = JB_GROUP_RESOURCE(self);
977 char *filename;
978
979 filename = g_strdup_printf("%s/%s", gres->group->srcdir, self->filename);
980
981 if (infile != NULL)
982 *infile = get_input_file(filename);
983 if (outfile != NULL)
984 *outfile = get_output_file(filename);
985
986 g_free(filename);
987 }
988
989 static void
990 intltool_file_build (JBResource *res)
991 {
992 JBIntltoolFile *self = JB_INTLTOOL_FILE(res);
993 char *infile;
994 char *outfile;
995 GSList *deps = NULL;
996
997 if (! jb_is_uptodate(INTLTOOL_MERGE_OUT, INTLTOOL_MERGE_IN))
998 {
999 GHashTable *variables;
1000
1001 jb_message("building intltool-merge");
1002
1003 jb_mkdir_of_file(INTLTOOL_MERGE_OUT);
1004
1005 variables = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
1006 g_hash_table_insert(variables, "INTLTOOL_PERL", jb_variable_expand("$perl", NULL));
1007 g_hash_table_insert(variables, "INTLTOOL_LIBDIR", jb_variable_expand("$perl", NULL));
1008
1009 jb_subst(INTLTOOL_MERGE_IN, INTLTOOL_MERGE_OUT, variables);
1010
1011 g_hash_table_destroy(variables);
1012
1013 jb_chmod(INTLTOOL_MERGE_OUT, 0755);
1014 }
1015
1016 intltool_file_get_files(self, &infile, &outfile);
1017
1018 deps = g_slist_append(deps, g_strdup(infile));
1019 deps = g_slist_append(deps, g_strdup(INTLTOOL_MERGE_OUT));
1020 deps = g_slist_concat(deps, jb_match_files("po/*.po"));
1021
1022 if (! jb_is_uptodate_list(outfile, deps))
1023 {
1024 jb_resource_message_building(res);
1025
1026 jb_mkdir_of_file(outfile);
1027 jb_mkdir_of_file(INTLTOOL_MERGE_CACHE);
1028
1029 jb_action_exec("LC_ALL=C " INTLTOOL_MERGE_OUT " $merge-flags -u -c " INTLTOOL_MERGE_CACHE " po $infile $outfile",
1030 "merge-flags", self->merge_flags,
1031 "infile", infile,
1032 "outfile", outfile,
1033 NULL);
1034 }
1035
1036 g_free(infile);
1037 g_free(outfile);
1038 jb_g_slist_free_deep(deps);
1039 }
1040
1041 static void
1042 intltool_file_install (JBResource *res)
1043 {
1044 JBIntltoolFile *self = JB_INTLTOOL_FILE(res);
1045 char *outfile;
1046
1047 intltool_file_get_files(self, NULL, &outfile);
1048
1049 jb_install_options_install_data(self->install_options, outfile, NULL);
1050
1051 g_free(outfile);
1052 }
1053
1054 static void
1055 intltool_file_makedist (JBResource *res)
1056 {
1057 JBIntltoolFile *self = JB_INTLTOOL_FILE(res);
1058 JBGroupResource *gres = JB_GROUP_RESOURCE(res);
1059 char *filename;
1060
1061 filename = g_strdup_printf("%s/%s", gres->group->srcdir, self->filename);
1062
1063 jb_action_add_to_dist(INTLTOOL_MERGE_IN);
1064
1065 if (! has_template(filename))
1066 jb_action_add_to_dist(filename);
1067
1068 g_free(filename);
1069 }
1070
1071 static void
1072 intltool_file_clean (JBResource *res)
1073 {
1074 JBIntltoolFile *self = JB_INTLTOOL_FILE(res);
1075 char *outfile;
1076
1077 intltool_file_get_files(self, NULL, &outfile);
1078
1079 jb_action_rm(INTLTOOL_MERGE_OUT);
1080 jb_action_rm(INTLTOOL_MERGE_CACHE);
1081 jb_action_rm(outfile);
1082
1083 g_free(outfile);
1084 }
1085
1086 static void
1087 intltool_file_maintainerclean (JBResource *res)
1088 {
1089 jb_action_rm(INTLTOOL_MERGE_IN);
1090 }
1091
1092 static void
1093 jb_intltool_file_init (JBIntltoolFile *self)
1094 {
1095 self->install_options = jb_install_options_new();
1096 }
1097
1098 static void
1099 jb_intltool_file_class_init (JBIntltoolFileClass *class)
1100 {
1101 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
1102
1103 rclass->to_string = intltool_file_to_string;
1104 rclass->build = intltool_file_build;
1105 rclass->install = intltool_file_install;
1106 rclass->makedist = intltool_file_makedist;
1107 rclass->clean = intltool_file_clean;
1108 rclass->maintainerclean = intltool_file_maintainerclean;
1109 }
1110
1111 G_DEFINE_TYPE(JBGConfSchemas, jb_gconf_schemas, JB_TYPE_INTLTOOL_FILE)
1112
1113 JBGConfSchemas *
1114 jb_gconf_schemas_new (const char *filename)
1115 {
1116 JBGConfSchemas *self;
1117 JBIntltoolFile *intltool_file;
1118
1119 self = g_object_new(JB_TYPE_GCONF_SCHEMAS, NULL);
1120
1121 intltool_file = JB_INTLTOOL_FILE(self);
1122
1123 intltool_file->type = g_strdup("GConf schemas");
1124 intltool_file->filename = g_strdup(filename);
1125 intltool_file->merge_flags = g_strdup("-s");
1126
1127 return self;
1128 }
1129
1130 static void
1131 gconf_schemas_install (JBResource *res)
1132 {
1133 JBIntltoolFile *intltool_file = JB_INTLTOOL_FILE(res);
1134
1135 JB_RESOURCE_CLASS(jb_gconf_schemas_parent_class)->install(res);
1136
1137 if (jb_variable_get_bool("install-gconf-schemas"))
1138 {
1139 char *outfile;
1140 char *filename;
1141
1142 intltool_file_get_files(intltool_file, NULL, &outfile);
1143
1144 filename = g_path_get_basename(outfile);
1145 jb_message("installing GConf schemas %s", filename);
1146 g_free(filename);
1147
1148 jb_action_exec("GCONF_CONFIG_SOURCE=$gconf-config-source $gconftool-2 --makefile-install-rule $outfile",
1149 "outfile", outfile,
1150 NULL);
1151
1152 g_free(outfile);
1153 }
1154 }
1155
1156 static void
1157 jb_gconf_schemas_init (JBGConfSchemas *self)
1158 {
1159 JBIntltoolFile *intltool_file = JB_INTLTOOL_FILE(self);
1160
1161 jb_install_options_set_installdir(intltool_file->install_options, "$gconf-schemas-dir");
1162 }
1163
1164 static void
1165 jb_gconf_schemas_class_init (JBGConfSchemasClass *class)
1166 {
1167 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
1168
1169 rclass->install = gconf_schemas_install;
1170 }
1171
1172 G_DEFINE_TYPE(JBGnomeHelp, jb_gnome_help, JB_TYPE_GROUP_RESOURCE)
1173
1174 JBGnomeHelp *
1175 jb_gnome_help_new (const char *lang, const char *entities)
1176 {
1177 JBGnomeHelp *self;
1178
1179 g_return_val_if_fail(lang != NULL, NULL);
1180 g_return_val_if_fail(jb_feature_is_enabled(&jb_gnome_help_feature), NULL);
1181
1182 self = g_object_new(JB_TYPE_GNOME_HELP, NULL);
1183 self->name = g_strdup(jb_variable_get_string("package"));
1184 self->lang = g_strdup(lang);
1185 self->entities = g_strsplit(entities != NULL ? entities : "", " ", 0);
1186
1187 return self;
1188 }
1189
1190 static char *
1191 gnome_help_to_string (JBResource *res)
1192 {
1193 JBGnomeHelp *self = JB_GNOME_HELP(res);
1194
1195 return g_strdup_printf("GNOME help %s [%s]", self->name, self->lang);
1196 }
1197
1198 static void
1199 gnome_help_get_files (JBGnomeHelp *self,
1200 char **inomf,
1201 char **outomf,
1202 char **helpdir,
1203 char **xmlfile,
1204 GSList **entities,
1205 GSList **figures)
1206 {
1207 JBGroupResource *gres = JB_GROUP_RESOURCE(self);
1208 char *_inomf;
1209
1210 _inomf = g_strdup_printf("%s/%s/%s-%s.omf.in",
1211 gres->group->srcdir,
1212 self->lang,
1213 self->name,
1214 self->lang);
1215
1216 if (inomf != NULL)
1217 *inomf = g_strdup(_inomf);
1218 if (outomf != NULL)
1219 *outomf = get_output_file(_inomf);
1220 if (helpdir != NULL)
1221 *helpdir = jb_variable_expand("$help-dir/$name/$lang",
1222 "name", self->name,
1223 "lang", self->lang,
1224 NULL);
1225 if (xmlfile != NULL)
1226 *xmlfile = g_strdup_printf("%s/%s/%s.xml",
1227 gres->group->srcdir,
1228 self->lang,
1229 self->name);
1230 if (entities != NULL)
1231 {
1232 int i;
1233 GSList *list = NULL;
1234
1235 for (i = 0; self->entities[i] != NULL; i++)
1236 list = g_slist_append(list, g_strdup_printf("%s/%s/%s",
1237 gres->group->srcdir,
1238 self->lang,
1239 self->entities[i]));
1240
1241 *entities = list;
1242 }
1243 if (figures != NULL)
1244 {
1245 char *pattern;
1246
1247 pattern = g_strdup_printf("%s/%s/figures/*.png",
1248 gres->group->srcdir,
1249 self->lang);
1250 *figures = jb_match_files(pattern);
1251 g_free(pattern);
1252 }
1253
1254 g_free(_inomf);
1255 }
1256
1257 static void
1258 gnome_help_build (JBResource *res)
1259 {
1260 JBGnomeHelp *self = JB_GNOME_HELP(res);
1261 char *inomf;
1262 char *outomf;
1263 char *helpdir;
1264
1265 gnome_help_get_files(self, &inomf, &outomf, &helpdir, NULL, NULL, NULL);
1266
1267 if (! jb_is_uptodate(outomf, inomf))
1268 {
1269 jb_resource_message_building(res);
1270
1271 jb_mkdir_of_file(outomf);
1272
1273 jb_action_exec("$scrollkeeper-preinstall \"$helpdir/$helpname.xml\" $inomf $outomf",
1274 "helpdir", helpdir,
1275 "helpname", self->name,
1276 "inomf", inomf,
1277 "outomf", outomf,
1278 NULL);
1279 }
1280
1281 g_free(inomf);
1282 g_free(outomf);
1283 g_free(helpdir);
1284 }
1285
1286 static void
1287 gnome_help_install (JBResource *res)
1288 {
1289 JBGnomeHelp *self = JB_GNOME_HELP(res);
1290 char *outomf;
1291 char *helpdir;
1292 char *omfdir;
1293 char *xmlfile;
1294 GSList *entities;
1295 GSList *figures;
1296 char *figdir;
1297
1298 gnome_help_get_files(self, NULL, &outomf, &helpdir, &xmlfile, &entities, &figures);
1299
1300 omfdir = g_strdup_printf("$omf-dir/%s", self->name);
1301
1302 figdir = g_strdup_printf("%s/figures", helpdir);
1303
1304 jb_action_install_data(xmlfile, helpdir);
1305
1306 jb_action_install_data_list(entities, helpdir);
1307
1308 jb_action_install_data_list(figures, figdir);
1309
1310 jb_action_install_data(outomf, omfdir);
1311
1312 jb_action_exec("-$scrollkeeper-update -p \"$destdir$scrollkeeper-dir\" -o \"$destdir$omfdir\"",
1313 "omfdir", omfdir,
1314 NULL);
1315
1316 g_free(outomf);
1317 g_free(helpdir);
1318 g_free(omfdir);
1319 g_free(xmlfile);
1320 jb_g_slist_free_deep(entities);
1321 jb_g_slist_free_deep(figures);
1322 g_free(figdir);
1323 }
1324
1325 static void
1326 gnome_help_makedist (JBResource *res)
1327 {
1328 JBGnomeHelp *self = JB_GNOME_HELP(res);
1329 char *inomf;
1330 char *xmlfile;
1331 GSList *entities;
1332 GSList *figures;
1333
1334 gnome_help_get_files(self, &inomf, NULL, NULL, &xmlfile, &entities, &figures);
1335
1336 jb_action_add_to_dist(inomf);
1337 jb_action_add_to_dist(xmlfile);
1338 jb_action_add_to_dist_list(entities);
1339 jb_action_add_to_dist_list(figures);
1340
1341 g_free(inomf);
1342 g_free(xmlfile);
1343 jb_g_slist_free_deep(entities);
1344 jb_g_slist_free_deep(figures);
1345 }
1346
1347 static void
1348 gnome_help_clean (JBResource *res)
1349 {
1350 JBGnomeHelp *self = JB_GNOME_HELP(res);
1351 char *outomf;
1352
1353 gnome_help_get_files(self, NULL, &outomf, NULL, NULL, NULL, NULL);
1354
1355 jb_action_rm(outomf);
1356
1357 g_free(outomf);
1358 }
1359
1360 static void
1361 jb_gnome_help_init (JBGnomeHelp *self)
1362 {
1363 }
1364
1365 static void
1366 jb_gnome_help_class_init (JBGnomeHelpClass *class)
1367 {
1368 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
1369
1370 rclass->to_string = gnome_help_to_string;
1371 rclass->build = gnome_help_build;
1372 rclass->install = gnome_help_install;
1373 rclass->makedist = gnome_help_makedist;
1374 rclass->clean = gnome_help_clean;
1375 }
1376
1377 G_DEFINE_TYPE(JBTranslations, jb_translations, JB_TYPE_GROUP_RESOURCE)
1378
1379 static void
1380 translations_get_files (JBTranslations *self, char **infile, char **outfile)
1381 {
1382 JBGroupResource *gres = JB_GROUP_RESOURCE(self);
1383
1384 if (infile != NULL)
1385 *infile = g_strdup_printf("%s/%s.po", gres->group->srcdir, self->lang);
1386 if (outfile != NULL)
1387 *outfile = g_strdup_printf("%s/%s.mo", gres->group->builddir, self->lang);
1388 }
1389
1390 JBTranslations *
1391 jb_translations_new (const char *lang)
1392 {
1393 JBTranslations *self;
1394
1395 g_return_val_if_fail(lang != NULL, NULL);
1396 g_return_val_if_fail(jb_feature_is_enabled(&jb_gettext_feature), NULL);
1397
1398 self = g_object_new(JB_TYPE_TRANSLATIONS, NULL);
1399 self->lang = g_strdup(lang);
1400
1401 return self;
1402 }
1403
1404 static char *
1405 translations_to_string (JBResource *res)
1406 {
1407 JBTranslations *self = JB_TRANSLATIONS(res);
1408
1409 return g_strdup_printf("%s translations", self->lang);
1410 }
1411
1412 static void
1413 translations_build (JBResource *res)
1414 {
1415 JBTranslations *self = JB_TRANSLATIONS(res);
1416 char *infile;
1417 char *outfile;
1418
1419 translations_get_files(self, &infile, &outfile);
1420
1421 if (! jb_is_uptodate(outfile, infile))
1422 {
1423 jb_resource_message_building(res);
1424
1425 jb_mkdir_of_file(outfile);
1426
1427 jb_action_exec("$msgfmt -o $outfile.tmp $infile && mv -f $outfile.tmp $outfile",
1428 "outfile", outfile,
1429 "infile", infile,
1430 NULL);
1431 }
1432
1433 g_free(infile);
1434 g_free(outfile);
1435 }
1436
1437 static void
1438 translations_install (JBResource *res)
1439 {
1440 JBTranslations *self = JB_TRANSLATIONS(res);
1441 char *outfile;
1442 char *installfile;
1443
1444 translations_get_files(self, NULL, &outfile);
1445
1446 installfile = g_strdup_printf("$prefix/share/locale/%s/LC_MESSAGES/$package.mo", self->lang);
1447
1448 jb_action_install_data_to_file(outfile, installfile);
1449
1450 g_free(outfile);
1451 g_free(installfile);
1452 }
1453
1454 static void
1455 translations_makedist (JBResource *res)
1456 {
1457 JBTranslations *self = JB_TRANSLATIONS(res);
1458 char *infile;
1459
1460 translations_get_files(self, &infile, NULL);
1461
1462 jb_action_add_to_dist(infile);
1463
1464 g_free(infile);
1465 }
1466
1467 static void
1468 translations_clean (JBResource *res)
1469 {
1470 JBTranslations *self = JB_TRANSLATIONS(res);
1471 char *outfile;
1472
1473 translations_get_files(self, NULL, &outfile);
1474
1475 jb_action_rm(outfile);
1476
1477 g_free(outfile);
1478 }
1479
1480 static void
1481 jb_translations_init (JBTranslations *self)
1482 {
1483 }
1484
1485 static void
1486 jb_translations_class_init (JBTranslationsClass *class)
1487 {
1488 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
1489
1490 rclass->to_string = translations_to_string;
1491 rclass->build = translations_build;
1492 rclass->install = translations_install;
1493 rclass->makedist = translations_makedist;
1494 rclass->clean = translations_clean;
1495 }
1496
1497 G_DEFINE_TYPE(JBRule, jb_rule, JB_TYPE_GROUP_RESOURCE)
1498
1499 JBRule *
1500 jb_rule_new (void)
1501 {
1502 return g_object_new(JB_TYPE_RULE, NULL);
1503 }
1504
1505 /*
1506 * This could be inferred by mapping input files to the resources that
1507 * produce them, but it would require a more complex JBResource
1508 * design. For now this is good enough.
1509 */
1510 void
1511 jb_rule_add_dependency (JBRule *self, JBGroupResource *res)
1512 {
1513 g_return_if_fail(JB_IS_RULE(self));
1514 g_return_if_fail(JB_IS_GROUP_RESOURCE(res));
1515
1516 self->dependencies = g_slist_append(self->dependencies, g_object_ref(res));
1517 }
1518
1519 void
1520 jb_rule_add_input_file (JBRule *self, const char *format, ...)
1521 {
1522 char *file;
1523
1524 g_return_if_fail(JB_IS_RULE(self));
1525 g_return_if_fail(format != NULL);
1526
1527 JB_STRDUP_VPRINTF(file, format);
1528 self->input_files = g_slist_append(self->input_files, file);
1529 }
1530
1531 void
1532 jb_rule_add_output_file (JBRule *self, const char *format, ...)
1533 {
1534 char *file;
1535
1536 g_return_if_fail(JB_IS_RULE(self));
1537 g_return_if_fail(format != NULL);
1538
1539 JB_STRDUP_VPRINTF(file, format);
1540 self->output_files = g_slist_append(self->output_files, file);
1541 }
1542
1543 void
1544 jb_rule_set_build_message (JBRule *self, const char *format, ...)
1545 {
1546 g_return_if_fail(JB_IS_RULE(self));
1547 g_return_if_fail(format != NULL);
1548
1549 g_free(self->build_message);
1550 JB_STRDUP_VPRINTF(self->build_message, format);
1551 }
1552
1553 void
1554 jb_rule_add_build_command (JBRule *self, const char *format, ...)
1555 {
1556 char *command;
1557
1558 g_return_if_fail(JB_IS_RULE(self));
1559 g_return_if_fail(format != NULL);
1560
1561 JB_STRDUP_VPRINTF(command, format);
1562 self->build_commands = g_slist_append(self->build_commands, command);
1563 }
1564
1565 void
1566 jb_rule_set_install_message (JBRule *self, const char *format, ...)
1567 {
1568 g_return_if_fail(JB_IS_RULE(self));
1569 g_return_if_fail(format != NULL);
1570
1571 g_free(self->install_message);
1572 JB_STRDUP_VPRINTF(self->install_message, format);
1573 }
1574
1575 void
1576 jb_rule_add_install_command (JBRule *self, const char *format, ...)
1577 {
1578 char *command;
1579
1580 g_return_if_fail(JB_IS_RULE(self));
1581 g_return_if_fail(format != NULL);
1582
1583 JB_STRDUP_VPRINTF(command, format);
1584 self->install_commands = g_slist_append(self->install_commands, command);
1585 }
1586
1587 static GSList *
1588 rule_expand_variables (JBRule *self, GSList *strings)
1589 {
1590 JBGroupResource *gres = JB_GROUP_RESOURCE(self);
1591 GSList *result = NULL;
1592 GSList *l;
1593
1594 JB_LIST_FOREACH(l, strings)
1595 {
1596 const char *str = l->data;
1597 char *expanded;
1598
1599 expanded = jb_variable_expand(str,
1600 "srcdir", gres->group->srcdir,
1601 "builddir", gres->group->builddir,
1602 NULL);
1603
1604 result = g_slist_append(result, expanded);
1605 }
1606
1607 return result;
1608 }
1609
1610 static void
1611 rule_perform (JBRule *self, const char *message, GSList *commands)
1612 {
1613 JBGroupResource *gres = JB_GROUP_RESOURCE(self);
1614 GSList *l;
1615
1616 if (commands == NULL)
1617 return;
1618
1619 jb_message("%s", message);
1620
1621 JB_LIST_FOREACH(l, commands)
1622 {
1623 const char *command = l->data;
1624
1625 jb_action_exec(command,
1626 "srcdir", gres->group->srcdir,
1627 "builddir", gres->group->builddir,
1628 NULL);
1629 }
1630 }
1631
1632 static void
1633 rule_build (JBResource *res)
1634 {
1635 JBRule *self = JB_RULE(res);
1636 GSList *l;
1637
1638 JB_LIST_FOREACH(l, self->dependencies)
1639 {
1640 JBResource *dep = l->data;
1641 jb_resource_build(dep);
1642 }
1643
1644 if (self->output_files != NULL)
1645 {
1646 GSList *input_files;
1647 GSList *output_files;
1648 gboolean is_uptodate;
1649
1650 input_files = rule_expand_variables(self, self->input_files);
1651 output_files = rule_expand_variables(self, self->output_files);
1652
1653 is_uptodate = jb_is_uptodate_list_list(output_files, input_files);
1654
1655 jb_g_slist_free_deep(input_files);
1656 jb_g_slist_free_deep(output_files);
1657
1658 if (is_uptodate)
1659 return;
1660 }
1661
1662 rule_perform(self, self->build_message, self->build_commands);
1663 }
1664
1665 static void
1666 rule_install (JBResource *res)
1667 {
1668 JBRule *self = JB_RULE(res);
1669
1670 rule_perform(self, self->install_message, self->install_commands);
1671 }
1672
1673 static void
1674 rule_clean (JBResource *res)
1675 {
1676 JBRule *self = JB_RULE(res);
1677 GSList *output_files;
1678
1679 output_files = rule_expand_variables(self, self->output_files);
1680
1681 jb_action_rm_list(output_files);
1682
1683 jb_g_slist_free_deep(output_files);
1684 }
1685
1686 static void
1687 jb_rule_init (JBRule *self)
1688 {
1689 }
1690
1691 static void
1692 jb_rule_class_init (JBRuleClass *class)
1693 {
1694 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
1695
1696 rclass->build = rule_build;
1697 rclass->install = rule_install;
1698 rclass->clean = rule_clean;
1699 }
1700
1701 G_DEFINE_ABSTRACT_TYPE(JBObject, jb_object, JB_TYPE_GROUP_RESOURCE)
1702
1703 static void
1704 object_construct (JBObject *self, const char *name)
1705 {
1706 self->name = g_strdup(name);
1707
1708 self->compile_options = jb_compile_options_new(name);
1709 self->install_options = jb_install_options_new();
1710 }
1711
1712 static char *
1713 object_to_string (JBResource *res)
1714 {
1715 JBObject *self = JB_OBJECT(res);
1716 JBObjectClass *class = JB_OBJECT_GET_CLASS(self);
1717
1718 return g_strdup_printf("%s %s", class->type, self->name);
1719 }
1720
1721 static char *
1722 object_get_output_file (JBObject *self)
1723 {
1724 JBObjectClass *class;
1725
1726 g_return_val_if_fail(JB_IS_OBJECT(self), NULL);
1727
1728 class = JB_OBJECT_GET_CLASS(self);
1729
1730 if (class->get_output_file != NULL)
1731 return class->get_output_file(self);
1732 else
1733 {
1734 g_error("get_output_file() not implemented for object type %s", G_OBJECT_TYPE_NAME(self));
1735 return NULL;
1736 }
1737 }
1738
1739 static GSList *
1740 object_get_object_files (JBObject *self)
1741 {
1742 GSList *list = NULL;
1743 GSList *l;
1744
1745 JB_LIST_FOREACH(l, self->resources)
1746 list = g_slist_append(list, object_resource_get_object_file(l->data));
1747
1748 return list;
1749 }
1750
1751 static GSList *
1752 object_get_headers (JBObject *self)
1753 {
1754 JBGroupResource *gres = JB_GROUP_RESOURCE(self);
1755 GSList *list = NULL;
1756 GSList *l;
1757
1758 JB_LIST_FOREACH(l, self->headers)
1759 {
1760 const char *header = l->data;
1761
1762 list = g_slist_append(list, g_strdup_printf("%s/%s",
1763 gres->group->srcdir,
1764 header));
1765 }
1766
1767 return list;
1768 }
1769
1770 static void
1771 object_pre_build (JBResource *res)
1772 {
1773 JBObject *self = JB_OBJECT(res);
1774 GSList *l;
1775
1776 JB_LIST_FOREACH(l, self->resources)
1777 jb_resource_pre_build(l->data);
1778 }
1779
1780 static void
1781 object_build (JBResource *res)
1782 {
1783 JBObject *self = JB_OBJECT(res);
1784 char *outfile;
1785 GSList *object_files_list;
1786 GSList *l;
1787
1788 JB_LIST_FOREACH(l, self->resources)
1789 jb_resource_build(l->data);
1790
1791 outfile = object_get_output_file(self);
1792 object_files_list = object_get_object_files(self);
1793
1794 if (! jb_is_uptodate_list(outfile, object_files_list))
1795 {
1796 JBGroupResource *gres = JB_GROUP_RESOURCE(self);
1797 JBObjectClass *object_class;
1798 char *object_files;
1799
1800 jb_resource_message_building(res);
1801
1802 object_class = JB_OBJECT_GET_CLASS(self);
1803
1804 object_files = jb_string_list_join(object_files_list, " ");
1805
1806 jb_mkdir(gres->group->builddir);
1807
1808 jb_action_exec("$cc -o $outfile"
1809 " $package-cflags $group-cflags $object-cflags $stock-cflags $cflags"
1810 " $package-ldflags $group-ldflags $object-ldflags $stock-ldflags $ldflags"
1811 " $object-files"
1812 " $package-libs $group-libs $object-libs $stock-libs $libs",
1813 "package-cflags", jb_compile_options_get_cflags(jb_compile_options),
1814 "group-cflags", jb_compile_options_get_cflags(gres->group->compile_options),
1815 "object-cflags", jb_compile_options_get_cflags(self->compile_options),
1816 "stock-cflags", object_class->stock_cflags,
1817 "package-ldflags", jb_compile_options_get_ldflags(jb_compile_options),
1818 "group-ldflags", jb_compile_options_get_ldflags(gres->group->compile_options),
1819 "object-ldflags", jb_compile_options_get_ldflags(self->compile_options),
1820 "stock-ldflags", object_class->stock_ldflags,
1821 "package-libs", jb_compile_options_get_libs(jb_compile_options),
1822 "group-libs", jb_compile_options_get_libs(gres->group->compile_options),
1823 "object-libs", jb_compile_options_get_libs(self->compile_options),
1824 "stock-libs", object_class->stock_libs,
1825 "outfile", outfile,
1826 "object-files", object_files,
1827 NULL);
1828
1829 g_free(object_files);
1830 }
1831
1832 g_free(outfile);
1833 jb_g_slist_free_deep(object_files_list);
1834 }
1835
1836 static void
1837 object_makedist (JBResource *res)
1838 {
1839 JBObject *self = JB_OBJECT(res);
1840 GSList *l;
1841 GSList *headers;
1842
1843 JB_LIST_FOREACH(l, self->resources)
1844 jb_resource_makedist(l->data);
1845
1846 headers = object_get_headers(self);
1847 jb_action_add_to_dist_list(headers);
1848 jb_g_slist_free_deep(headers);
1849 }
1850
1851 static void
1852 object_clean (JBResource *res)
1853 {
1854 JBObject *self = JB_OBJECT(res);
1855 GSList *l;
1856 char *outfile;
1857
1858 JB_LIST_FOREACH(l, self->resources)
1859 jb_resource_clean(l->data);
1860
1861 outfile = object_get_output_file(self);
1862
1863 jb_action_rm(outfile);
1864
1865 g_free(outfile);
1866 }
1867
1868 static void
1869 object_distclean (JBResource *res)
1870 {
1871 JBObject *self = JB_OBJECT(res);
1872 GSList *l;
1873
1874 JB_LIST_FOREACH(l, self->resources)
1875 jb_resource_distclean(l->data);
1876 }
1877
1878 static void
1879 object_maintainerclean (JBResource *res)
1880 {
1881 JBObject *self = JB_OBJECT(res);
1882 GSList *l;
1883
1884 JB_LIST_FOREACH(l, self->resources)
1885 jb_resource_maintainerclean(l->data);
1886 }
1887
1888 static void
1889 object_add_resource (JBObject *self, JBObjectResource *res)
1890 {
1891 g_return_if_fail(JB_IS_OBJECT(self));
1892 g_return_if_fail(JB_IS_OBJECT_RESOURCE(res));
1893 g_return_if_fail(res->object == NULL);
1894
1895 res->object = self;
1896
1897 self->resources = g_slist_append(self->resources, res);
1898 }
1899
1900 static void
1901 object_add_header (JBObject *self, const char *filename)
1902 {
1903 g_return_if_fail(JB_IS_OBJECT(self));
1904 g_return_if_fail(filename != NULL);
1905
1906 self->headers = g_slist_append(self->headers, g_strdup(filename));
1907 }
1908
1909 void
1910 jb_object_add_source (JBObject *self, const char *name)
1911 {
1912 g_return_if_fail(JB_IS_OBJECT(self));
1913 g_return_if_fail(name != NULL);
1914
1915 if (strchr(name, ':') != NULL)
1916 object_add_resource(self, JB_OBJECT_RESOURCE(jb_gob_class_new(name)));
1917 else if (strchr(name, '.') == NULL)
1918 {
1919 char *cfile;
1920 char *hfile;
1921
1922 cfile = g_strdup_printf("%s.c", name);
1923 hfile = g_strdup_printf("%s.h", name);
1924
1925 object_add_resource(self, JB_OBJECT_RESOURCE(jb_source_new(cfile)));
1926 object_add_header(self, hfile);
1927
1928 g_free(cfile);
1929 g_free(hfile);
1930 }
1931 else
1932 {
1933 if (g_str_has_suffix(name, ".c"))
1934 object_add_resource(self, JB_OBJECT_RESOURCE(jb_source_new(name)));
1935 else if (g_str_has_suffix(name, ".h"))
1936 object_add_header(self, name);
1937 else
1938 g_error("the extension of source file \"%s\" is not .c or .h", name);
1939 }
1940 }
1941
1942 void
1943 jb_object_add_sources (JBObject *self, const char *name, ...)
1944 {
1945 va_list args;
1946
1947 g_return_if_fail(JB_IS_OBJECT(self));
1948
1949 va_start(args, name);
1950
1951 while (name != NULL)
1952 {
1953 jb_object_add_source(self, name);
1954 name = va_arg(args, const char *);
1955 }
1956
1957 va_end(args);
1958 }
1959
1960 static void
1961 jb_object_init (JBObject *self)
1962 {
1963 }
1964
1965 static void
1966 jb_object_class_init (JBObjectClass *class)
1967 {
1968 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
1969
1970 rclass->to_string = object_to_string;
1971 rclass->pre_build = object_pre_build;
1972 rclass->build = object_build;
1973 rclass->makedist = object_makedist;
1974 rclass->clean = object_clean;
1975 rclass->distclean = object_distclean;
1976 rclass->maintainerclean = object_maintainerclean;
1977 }
1978
1979 G_DEFINE_TYPE(JBProgram, jb_program, JB_TYPE_OBJECT)
1980
1981 JBProgram *
1982 jb_program_new (const char *name)
1983 {
1984 JBProgram *self;
1985 JBObject *object;
1986
1987 g_return_val_if_fail(name != NULL, NULL);
1988
1989 self = g_object_new(JB_TYPE_PROGRAM, NULL);
1990 object = JB_OBJECT(self);
1991
1992 object_construct(object, name);
1993 jb_install_options_set_installdir(object->install_options, "$bindir");
1994
1995 return self;
1996 }
1997
1998 static void
1999 program_install (JBResource *res)
2000 {
2001 JBObject *object = JB_OBJECT(res);
2002 char *outfile;
2003
2004 outfile = object_get_output_file(object);
2005
2006 jb_install_options_install_program(object->install_options, outfile, NULL);
2007
2008 g_free(outfile);
2009 }
2010
2011 static char *
2012 program_get_output_file (JBObject *object)
2013 {
2014 JBGroupResource *gres = JB_GROUP_RESOURCE(object);
2015
2016 return g_strdup_printf("%s/%s", gres->group->builddir, object->name);
2017 }
2018
2019 static void
2020 jb_program_init (JBProgram *self)
2021 {
2022 }
2023
2024 static void
2025 jb_program_class_init (JBProgramClass *class)
2026 {
2027 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
2028 JBObjectClass *oclass = JB_OBJECT_CLASS(class);
2029
2030 rclass->install = program_install;
2031
2032 oclass->type = "program";
2033 oclass->get_output_file = program_get_output_file;
2034 }
2035
2036 G_DEFINE_TYPE(JBModule, jb_module, JB_TYPE_OBJECT)
2037
2038 JBModule *
2039 jb_module_new (const char *name)
2040 {
2041 JBModule *self;
2042 JBObject *object;
2043
2044 g_return_val_if_fail(name != NULL, NULL);
2045
2046 self = g_object_new(JB_TYPE_MODULE, NULL);
2047 object = JB_OBJECT(self);
2048
2049 object_construct(object, name);
2050 jb_install_options_set_installdir(object->install_options, "$pkglibdir");
2051
2052 return self;
2053 }
2054
2055 static void
2056 module_install (JBResource *res)
2057 {
2058 JBObject *object = JB_OBJECT(res);
2059 char *outfile;
2060
2061 outfile = object_get_output_file(object);
2062
2063 jb_install_options_install_library(object->install_options, outfile, NULL);
2064
2065 g_free(outfile);
2066 }
2067
2068 static char *
2069 module_get_output_file (JBObject *object)
2070 {
2071 JBGroupResource *gres = JB_GROUP_RESOURCE(object);
2072
2073 return g_strdup_printf("%s/%s.so", gres->group->builddir, object->name);
2074 }
2075
2076 static void
2077 jb_module_init (JBModule *self)
2078 {
2079 }
2080
2081 static void
2082 jb_module_class_init (JBModuleClass *class)
2083 {
2084 JBResourceClass *rclass = JB_RESOURCE_CLASS(class);
2085 JBObjectClass *oclass = JB_OBJECT_CLASS(class);
2086
2087 rclass->install = module_install;
2088
2089 oclass->type = "module";
2090 oclass->stock_cflags = "-fPIC";
2091 oclass->stock_cppflags = "-DPIC";
2092 oclass->stock_ldflags = "-shared";
2093 oclass->get_output_file = module_get_output_file;
2094 }