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 }