diff --git a/readme.txt b/readme.txt index 6bf7d1c..826ffda 100644 --- a/readme.txt +++ b/readme.txt @@ -63,6 +63,10 @@ Release notes: Compiler: access predicates consisting of a single multi-query no longer crash the compiler when negated. + Compiler: a new --override-serial option makes builds reproducible + by overriding the release date and serial number fields. This is + not recommended, but occasionally necessary. + Compiler: --word-seps option can change which characters are considered word separators (by default . , ; ( ) " * ) diff --git a/src/backend.c b/src/backend.c index 3d4d824..3e94f9e 100644 --- a/src/backend.c +++ b/src/backend.c @@ -82,6 +82,7 @@ void usage(char *prgname) { fprintf(stderr, "--strip -s Strip internal object names.\n"); fprintf(stderr, "--warn-not-topic Always warn about objects not used as topics.\n"); fprintf(stderr, "--no-warn-not-topic Never warn about objects not used as topics.\n"); + fprintf(stderr, "--override-serial Override serial number for reproducible builds.\n"); fprintf(stderr, "\n"); fprintf(stderr, "Only for z5, z8, or zblorb format:\n"); fprintf(stderr, "\n"); @@ -98,8 +99,10 @@ void usage(char *prgname) { extern int topic_warning_level; // Defined in frontend.c extern int zmachine_optimize_alphabet; // Defined in backend_z.c extern int zmachine_preserve_zscii; // Defined in backend_z.c +static int serial_overridden; int main(int argc, char **argv) { + struct option longopts[] = { {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, @@ -119,6 +122,7 @@ int main(int argc, char **argv) { {"warn-not-topic", 0, &topic_warning_level, 1}, {"no-warn-not-topic", 0, &topic_warning_level, 2}, {"optimize-alphabet", 0, &zmachine_optimize_alphabet, 1}, + {"override-serial", 1, &serial_overridden, 2}, {0, 0, 0, 0} }; @@ -128,6 +132,7 @@ int main(int argc, char **argv) { char *coverfname = 0; char *coveralt = 0; char *resdir = 0; + char *override_serial_with = 0; uint8_t *wordseps = 0; int auxsize = 500, heapsize = 1000, ltssize = 500; int strip = 0; @@ -146,6 +151,10 @@ int main(int argc, char **argv) { opt = getopt_long(argc, argv, "?hVvo:t:r:c:a:W:H:A:L:s", longopts, 0); switch(opt) { case 0: + if(serial_overridden == 2) { // Long-only option with arg + override_serial_with = strdup(optarg); + serial_overridden = 1; + } break; // Added DMS so long-only options are possible case '?': case 'h': @@ -329,9 +338,26 @@ int main(int argc, char **argv) { } else if(need_meta) { report(LVL_WARN, 0, "No release number declared."); } - - get_timestamp(compiletime_buf, reldate_buf); - + + if(serial_overridden) { + if(strlen(override_serial_with) != 10) { + report(LVL_ERR, 0, "Argument of --override-serial must be exactly 10 characters in the format YYYY-MM-DD"); + exit(1); + } + strcpy(reldate_buf, override_serial_with); + compiletime_buf[0] = reldate_buf[2]; // yyYy-mm-dd + compiletime_buf[1] = reldate_buf[3]; // yyyY-mm-dd + compiletime_buf[2] = reldate_buf[5]; // yyyy-Mm-dd + compiletime_buf[3] = reldate_buf[6]; // yyyy-mM-dd + compiletime_buf[4] = reldate_buf[8]; // yyyy-mm-Dd + compiletime_buf[5] = reldate_buf[9]; // yyyy-mm-dD + compiletime_buf[6] = 0; + report(LVL_WARN, 0, "Release date has been set to \"%s\" and serial number has been set to \"%s\". This is not recommended, and should only be used when necessary for reproducible builds.", reldate_buf, compiletime_buf); + free(override_serial_with); + } else { + get_timestamp(compiletime_buf, reldate_buf); + } + prg->meta_serial = arena_strdup(&prg->arena, compiletime_buf); prg->meta_reldate = arena_strdup(&prg->arena, reldate_buf); diff --git a/test/simple/warnings/Makefile b/test/simple/warnings/Makefile index 52ed952..3b75979 100644 --- a/test/simple/warnings/Makefile +++ b/test/simple/warnings/Makefile @@ -41,6 +41,9 @@ stdlib.dglib: $(BASEPATH)/stdlib.dg origin: $(origin) +serial.out: $(BASEPATH)/src/dialogc serial.dg stdlib.dglib + $(BASEPATH)/src/dialogc serial.dg stdlib.dglib -t z5 -o serial.z5 --override-serial 0123456789 >serial.out 2>&1 || : + # This one is non-deterministic so we need to sed the results afterward ifid.out: $(BASEPATH)/src/dialogc ifid.dg stdlib.dglib $(BASEPATH)/src/dialogc $*.dg stdlib.dglib -t z5 -o ifid.z5 >ifid.out 2>&1 || : diff --git a/test/simple/warnings/serial.dg b/test/simple/warnings/serial.dg new file mode 100644 index 0000000..47c2c17 --- /dev/null +++ b/test/simple/warnings/serial.dg @@ -0,0 +1,6 @@ +#player +(current player *) +(* is #in #room) + +#room +(room *) diff --git a/test/simple/warnings/serial.gold b/test/simple/warnings/serial.gold new file mode 100644 index 0000000..f407134 --- /dev/null +++ b/test/simple/warnings/serial.gold @@ -0,0 +1 @@ +Warning: Release date has been set to "0123456789" and serial number has been set to "235689". This is not recommended, and should only be used when necessary for reproducible builds.