Avoiding unnecessary rebuilds with Automake
Jean-Yves Lefort <[email protected]> Tue, 6 Dec 2005 12:47:25 +0100
| Newsgroups | gmane.comp.gnome.devtools.gob.general |
|---|---|
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format. [email protected] Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg="PGP-SHA1"; boundary="Signature=_Tue__6_Dec_2005_12_47_25_+0100_nihAuSVr4LVDHIZg" --Signature=_Tue__6_Dec_2005_12_47_25_+0100_nihAuSVr4LVDHIZg Content-Type: multipart/mixed; boundary="Multipart=_Tue__6_Dec_2005_12_47_25_+0100_xHZEwbVbhE1JYIuf" --Multipart=_Tue__6_Dec_2005_12_47_25_+0100_xHZEwbVbhE1JYIuf Content-Type: text/plain; charset=US-ASCII Content-Disposition: inline Content-Transfer-Encoding: quoted-printable The attached patch: - adds a --no-touch option, which prevents all files (not just the public header) from being touched unless they have changed - while here, checks if a file has changed without cmp(1) - removes the timestamp from .c comment headers It helps avoiding unnecessary rebuilds when GOB is used from Automake, thanks to the following trick (the manual page should be updated): foo_SOURCES =3D foo.gob foo.gob.stamp foo.c foo.h foo-private.h BUILT_SOURCES =3D foo.gob.stamp MAINTAINERCLEANFILES =3D foo.gob.stamp %.gob.stamp: %.gob @GOB2@ --no-touch $< @touch $@ --=20 Jean-Yves Lefort [email protected] http://lefort.be.eu.org/ --Multipart=_Tue__6_Dec_2005_12_47_25_+0100_xHZEwbVbhE1JYIuf Content-Type: text/plain; name="gob2-2.0.12-notouch.diff" Content-Disposition: attachment; filename="gob2-2.0.12-notouch.diff" Content-Transfer-Encoding: quoted-printable --- src/main.c.orig Tue Dec 6 11:08:37 2005 +++ src/main.c Tue Dec 6 12:30:23 2005 @@ -25,6 +25,7 @@ #include <glib.h> #include <time.h> #include <stdio.h> +#include <errno.h> #include <string.h> #include <unistd.h> #include <stdlib.h> @@ -54,6 +55,9 @@ =20 char *filebase; char *fullfilebase; +static char *outfilebase; +static char *outfilehbase; +static char *outfilephbase; static char *funcbase; static char *pfuncbase; static char *macrobase; @@ -99,6 +103,7 @@ FILE *outph =3D NULL; FILE *devnull =3D NULL; =20 +gboolean no_touch =3D FALSE; gboolean no_touch_headers =3D FALSE; gboolean for_cpp =3D FALSE; gboolean no_gnu =3D FALSE; @@ -3045,14 +3050,11 @@ { char *outfile, *outfileh, *outfileph; =20 - if ( ! for_cpp) - outfile =3D g_strconcat (fullfilebase, ".c", NULL); - else - outfile =3D g_strconcat (fullfilebase, ".cc", NULL); - if (no_touch_headers) - outfileh =3D g_strconcat (fullfilebase, ".h#gob#", NULL); - else - outfileh =3D g_strconcat (fullfilebase, ".h", NULL); + outfilebase =3D g_strconcat (fullfilebase, for_cpp ? ".cc" : ".c", NULL); + outfile =3D g_strconcat(outfilebase, no_touch ? "#gob#" : "", NULL); + + outfilehbase =3D g_strconcat (fullfilebase, ".h"); + outfileh =3D g_strconcat(outfilehbase, no_touch_headers ? "#gob#" : "", N= ULL); =20 if ((privates > 0 || protecteds > 0 || private_header =3D=3D PRIVATE_HEADER_ALWAYS) && @@ -3060,8 +3062,10 @@ char sep[2] =3D {0,0}; if (file_sep !=3D 0) sep[0] =3D file_sep; - outfileph =3D g_strconcat (fullfilebase, sep, "private.h", NULL); + outfilephbase =3D g_strconcat (fullfilebase, sep, "private.h", NULL); + outfileph =3D g_strconcat (outfilephbase, no_touch ? "#gob#" : "", NULL); } else { + outfilephbase =3D NULL; outfileph =3D NULL; } =20 @@ -3675,16 +3679,13 @@ static void print_file_comments(void) { - time_t curtime; - time(&curtime); out_printf(outh, "/* Generated by GOB (v%s)" " (do not edit directly) */\n\n", VERSION); if(outph) out_printf(outph, "/* Generated by GOB (v%s)" " (do not edit directly) */\n\n", VERSION); - out_printf(out, "/* Generated by GOB (v%s) on %s" - " (do not edit directly) */\n\n", - VERSION, ctime(&curtime)); + out_printf(out, "/* Generated by GOB (v%s)" + " (do not edit directly) */\n\n", VERSION); =20 out_printf(out, "/* End world hunger, donate to the World Food Programme,= http://www.wfp.org */\n\n"); } @@ -4075,6 +4076,9 @@ "\t--no-extern-c Never print extern \"C\" into the " "header\n" "\t--no-gnu Never use GNU extentions\n" + "\t--no-touch Don't touch output files unless they " + "really\n" + "\t changed (implies --no-touch-headers)\n" "\t--no-touch-headers Don't touch headers unless they " "really changed\n" "\t--always-private-header Always create a private header " @@ -4172,6 +4176,9 @@ exit_on_warn =3D FALSE; } else if(strcmp(argv[i], "--for-cpp")=3D=3D0) { for_cpp =3D TRUE; + } else if(strcmp(argv[i], "--no-touch")=3D=3D0) { + no_touch =3D TRUE; + no_touch_headers =3D TRUE; } else if(strcmp(argv[i], "--no-touch-headers")=3D=3D0) { no_touch_headers =3D TRUE; } else if(strcmp(argv[i], "--ondemand-private-header")=3D=3D0) { @@ -4283,35 +4290,79 @@ #endif } =20 -/* this is a somewhat ugly hack, but it appears to work */ static void -compare_and_move_header(void) +compare_and_move (const char *old_filename) { - char *hfnew =3D g_strconcat(fullfilebase, ".h#gob#", NULL); - char *hf =3D g_strconcat(fullfilebase, ".h", NULL); - struct stat s; - if(stat(hf, &s) =3D=3D 0) { - char *s; - s =3D g_strdup_printf("cmp '%s' '%s' > /dev/null", hf, hfnew); - if(system(s) =3D=3D 0) { - if(unlink(hfnew) !=3D 0) - error_printf(GOB_ERROR, 0, - "Can't remove new header file"); - g_free(hfnew); - g_free(hf); - g_free(s); - return; + char *new_filename =3D g_strconcat (old_filename, "#gob#", NULL); + FILE *old_f; + gboolean equal =3D FALSE; + + old_f =3D fopen (old_filename, "r"); + if (old_f) { + FILE *new_f; + gboolean error =3D FALSE; + + new_f =3D fopen (new_filename, "r"); + if (new_f) { + char new_buf[1024]; + char old_buf[1024]; + + while (TRUE) { + size_t new_n; + size_t old_n; + + new_n =3D fread (new_buf, 1, sizeof (new_buf), new_f); + if (ferror (new_f)) { + error =3D TRUE; + error_printf (GOB_ERROR, 0, + "Can't read %s: %s", + new_filename, + g_strerror (errno)); + break; + } + + old_n =3D fread (old_buf, 1, sizeof (old_buf), old_f); + if (ferror (old_f) + || feof (new_f) !=3D feof (old_f) + || new_n !=3D old_n + || memcmp (new_buf, old_buf, new_n) !=3D 0) + break; + + if (feof (new_f)) { + equal =3D TRUE; + break; + } + } + } else + error_printf (GOB_ERROR, 0, "Can't open %s: %s", + new_filename, g_strerror (errno)); + + fclose (old_f); + fclose (new_f); + + if (error) + goto end; + + if (! equal && unlink (old_filename) !=3D 0) { + error_printf (GOB_ERROR, 0, "Can't remove %s: %s", + old_filename, g_strerror (errno)); + goto end; } - g_free(s); - if(unlink(hf) !=3D 0) - error_printf(GOB_ERROR, 0, - "Can't remove old header file"); - } - if(rename(hfnew, hf) !=3D 0) - error_printf(GOB_ERROR, 0, - "Can't rename new header file"); - g_free(hfnew); - g_free(hf); + } + + if (equal) { + if (unlink (new_filename) !=3D 0) + error_printf (GOB_ERROR, 0, "Can't remove %s: %s", + new_filename, g_strerror (errno)); + } else { + if (rename (new_filename, old_filename) !=3D 0) + error_printf (GOB_ERROR, 0, "Can't rename %s to %s: %s", + new_filename, old_filename, + g_strerror (errno)); + } + + end: + g_free (new_filename); } =20 int @@ -4413,9 +4464,15 @@ fclose (outph); } =20 - if (no_touch_headers && - ! no_write) - compare_and_move_header (); + if (! no_write) { + if (no_touch) { + compare_and_move (outfilebase); + if (outfilephbase) + compare_and_move (outfilephbase); + } + if (no_touch_headers) + compare_and_move (outfilehbase); + } =09 return 0; } --Multipart=_Tue__6_Dec_2005_12_47_25_+0100_xHZEwbVbhE1JYIuf-- --Signature=_Tue__6_Dec_2005_12_47_25_+0100_nihAuSVr4LVDHIZg Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2 (FreeBSD) iD8DBQFDlXpOyzD7UaO4AGoRApGvAJ0Tlu9Kbz4+X0Fxi9QZk3k+EV5D+ACdHjIm RkyalGXspbLJ8B4sVcmLluA= =o8xS -----END PGP SIGNATURE----- --Signature=_Tue__6_Dec_2005_12_47_25_+0100_nihAuSVr4LVDHIZg-- [email protected] Content-Type: text/plain; charset=us-ascii; name="footer" Content-Transfer-Encoding: 8bit -- to unsubscribe: send mail to [email protected] with "unsubscribe gob-list" in the subject [email protected]