From dfa410001df6224a53eeacd40cfe226600c009e0 Mon Sep 17 00:00:00 2001 From: felix Date: Sat, 20 Oct 2018 13:54:03 +0200 Subject: [PATCH] allow multiple targets in "chicken-do" invocations To handle selective deletion of files generated by egg-builds, we need a way to make targets are re-built when one of several generated files are missing or superseded by dpendency files. This patch generalizes chicken-do(1) to allow multiple targets. --- chicken-do.c | 90 +++++++++++++++++++++++++++++++++++++++----------------- chicken-do.mdoc | 24 ++++++++------- egg-compile.scm | 91 ++++++++++++++++++++++++++++++++++----------------------- 3 files changed, 133 insertions(+), 72 deletions(-) diff --git a/chicken-do.c b/chicken-do.c index c58acd7e..2923ca8c 100644 --- a/chicken-do.c +++ b/chicken-do.c @@ -39,22 +39,33 @@ #include #include -static char *target; +#define MAX_TARGETS 256 +#define MAX_DEPENDS 1024 + +static char *targets[ MAX_TARGETS ]; +static char *depends[ MAX_DEPENDS ]; +static struct stat tstats[ MAX_TARGETS ]; +static char **cmd; +static int opts = 1; +static int quiet = 0; static void usage(int code) { - fputs("usage: chicken-do [-q] [-h] TARGET COMMAND ... : DEPENDENCIES ...\n", stderr); + fputs("usage: chicken-do [-q] [-h] [--] TARGET ... : DEPENDENCY ... : COMMAND ...\n", stderr); exit(code); } static void cleanup() { + char **t; + + for(t = targets; *t != NULL; ++t) #ifdef WIN32 - DeleteFile(target); + DeleteFile(*t); #else - unlink(target); + unlink(*t); #endif } @@ -132,48 +143,75 @@ static int execute(char **argv) int main(int argc, char *argv[]) { - int i, count, a = 0; - char **args = (char **)malloc(sizeof(char *) * argc); - struct stat st, sd; - int quiet = 0, opts = 1; + int i, a = 0; + struct stat *st, sd; + char **t = targets; + char **d = depends; if(argc < 3) usage(1); - target = argv[ 1 ]; + for(i = 1; i < argc; ++i) { + if(!strcmp(argv[ i ], ":")) { + *t = NULL; + break; + } - for(i = 2; i < argc; ++i) { if(opts && *argv[ i ] == '-') { switch(argv[ i ][ 1 ]) { case 'q': quiet = 1; break; case 'h': usage(0); + case '-': opts = 0; break; default: usage(1); } } - else if(!strcmp(argv[ i ], ":")) break; - else { - args[ a++ ] = argv[ i ]; - opts = 0; + else if(t >= targets + MAX_TARGETS) { + fprintf(stderr, "too many targets\n"); + exit(1); } + else *(t++) = argv[ i ]; } if(i == argc) usage(1); - args[ a ] = NULL; + while(++i < argc) { + if(!strcmp(argv[ i ], ":")) { + *d = NULL; + break; + } - if(stat(target, &st) == -1) { - if(errno == ENOENT) goto build; + if(d >= depends + MAX_DEPENDS) { + fprintf(stderr, "too many dependencies\n"); + exit(1); + } - fprintf(stderr, "%s: %s\n", target, strerror(errno)); - exit(1); + *(d++) = argv[ i ]; + } + + if(i == argc) usage(1); + + cmd = argv + i + 1; + st = tstats; + + for(t = targets; *t != NULL; ++t) { + if(stat(*t, st++) == -1) { + if(errno == ENOENT) goto build; + + fprintf(stderr, "%s: %s\n", *t, strerror(errno)); + exit(1); + } } - for(++i; i < argc; ++i) { - if(stat(argv[ i ], &sd) == -1) { - fprintf(stderr, "%s: %s\n", argv[ i ], strerror(errno)); + for(d = depends; *d != NULL; ++d) { + if(stat(*d, &sd) == -1) { + fprintf(stderr, "%s: %s\n", *d, strerror(errno)); exit(1); } - if(sd.st_mtime > st.st_mtime) goto build; + st = tstats; + + for(t = targets; *t != NULL; ++t) { + if(sd.st_mtime > (st++)->st_mtime) goto build; + } } return 0; @@ -182,14 +220,14 @@ build: if(!quiet) { fputs(" ", stdout); - for(i = 0; i < a; ++i) - printf(" %s", args[ i ]); + for(t = cmd; *t != NULL; ++t) + printf(" %s", *t); putchar('\n'); fflush(stdout); } - int s = execute(args); + int s = execute(cmd); if(s != 0) cleanup(); diff --git a/chicken-do.mdoc b/chicken-do.mdoc index 6b6e4d2d..20cf1697 100644 --- a/chicken-do.mdoc +++ b/chicken-do.mdoc @@ -35,33 +35,37 @@ not newer than the target .Nm .Op Fl q .Op Fl h -.Ar TARGET -.Ar COMMAND ... +.Op Fl - +.Ar TARGET ... .Cm : .Ar DEPENDENCY ... +.Cm : +.Ar COMMAND ... .Sh DESCRIPTION -If the file -.Em TARGET -does not exist, or if any of the files in +If the files +.Em TARGET ... +do not exist, or if any of the files in .Em DEPENDENCY ... -are newer than -.Em TARGET , -then execute the shell commands in +are newer than one of the target files, then execute the shell commands in .Em COMMAND ... . .Pp -The program accepts following arguments: +The program accepts the following options: .Bl -tag -width Ds .It Fl h Show usage and exit. .It Fl q Quiet operation - do not print shell commands when they are executed. +.It Fl - +Treat all following tokens as target filenames, even if they begin with a +.It - +character. .El .Sh EXIT STATUS .Ex -std .Sh EXAMPLES Build a C program from sources: .Pp -.Dl $ chicken-do prg gcc prg.c -o prg \& : prg.c inc.h +.Dl $ chicken-do prg : prg.c inc.h : gcc prg.c -o prg .Sh SEE ALSO .Xr chicken 1 , .Xr chicken-status 1 , diff --git a/egg-compile.scm b/egg-compile.scm index 9c1b9f82..0a095fb8 100644 --- a/egg-compile.scm +++ b/egg-compile.scm @@ -473,29 +473,37 @@ default-csc) platform)) (sname (prefix srcdir name)) + (tfile (qs* (prefix srcdir (conc types-file ".types")) + platform)) + (ifile (qs* (prefix srcdir (conc inline-file ".inline")) + platform)) (opts (append (if (null? options) default-static-compilation-options options) (if (and types-file (not predefined-types)) - (list "-emit-types-file" - (qs* (prefix srcdir (conc types-file ".types")) - platform)) + (list "-emit-types-file" tfile) '()) (if inline-file - (list "-emit-inline-file" - (qs* (prefix srcdir (conc inline-file ".inline")) - platform)) + (list "-emit-inline-file" ifile) '()))) (out (qs* (target-file (conc sname ".static" (object-extension platform)) mode) platform)) + (targets (append (list out) + (maybe types-file tfile) + (maybe inline-file ifile))) (src (qs* (or source (conc name ".scm")) platform))) (when custom (prepare-custom-command cmd platform)) - (print "\n" (qs* default-builder platform #t) " " out " " cmd + (print "\n" (qs* default-builder platform #t) " " + (joins targets) " : " + src " " (qs* eggfile platform) " " + (if custom cmd "") " " + (filelist srcdir source-dependencies platform) + " : " cmd (if keep-generated-files " -k" "") " -setup-mode -static -I " srcdir " -emit-link-file " @@ -504,10 +512,7 @@ " -D compiling-extension -c -unit " name " -D compiling-static-extension" " -C -I" srcdir (arglist opts platform) - " " src " -o " out " : " - src " " (qs* eggfile platform) " " - (if custom cmd "") " " - (filelist srcdir source-dependencies platform)) + " " src " -o " out) (print-end-command platform))) (define ((compile-dynamic-extension name #!key mode mode @@ -520,33 +525,39 @@ default-csc) platform)) (sname (prefix srcdir name)) + (tfile (qs* (prefix srcdir (conc types-file ".types")) + platform)) + (ifile (qs* (prefix srcdir (conc inline-file ".inline")) + platform)) (opts (append (if (null? options) default-dynamic-compilation-options options) (if (and types-file (not predefined-types)) - (list "-emit-types-file" - (qs* (prefix srcdir (conc types-file ".types")) - platform)) + (list "-emit-types-file" tfile) '()) (if inline-file - (list "-emit-inline-file" - (qs* (prefix srcdir (conc inline-file ".inline")) - platform)) + (list "-emit-inline-file" ifile) '()))) (out (qs* (target-file (conc sname ".so") mode) platform)) + (targets (append (list out) + (maybe inline-file ifile) + (maybe types-file tfile))) (src (qs* (or source (conc name ".scm")) platform))) (when custom (prepare-custom-command cmd platform)) - (print "\n" (qs* default-builder platform #t) " " out " " cmd + (print "\n" (qs* default-builder platform #t) " " + (joins targets) " : " + src " " (qs* eggfile platform) " " + (if custom cmd "") " " + (filelist srcdir source-dependencies platform) + " : " cmd (if keep-generated-files " -k" "") (if (eq? mode 'host) " -host" "") " -D compiling-extension -J -s" " -setup-mode -I " srcdir " -C -I" srcdir (arglist opts platform) (arglist link-options platform) - " " src " -o " out " : " src " " (qs* eggfile platform) " " - (if custom cmd "") " " - (filelist srcdir source-dependencies platform)) + " " src " -o " out) (print-end-command platform))) (define ((compile-import-library name #!key mode @@ -561,13 +572,14 @@ (out (qs* (target-file (conc sname ".import.so") mode) platform)) (src (qs* (conc name ".import.scm") platform))) - (print "\n" (qs* default-builder platform #t) " " out " " cmd + (print "\n" (qs* default-builder platform #t) " " out " : " + src (filelist srcdir source-dependencies platform) + " : " cmd (if keep-generated-files " -k" "") " -setup-mode -s" (if (eq? mode 'host) " -host" "") " -I " srcdir " -C -I" srcdir (arglist opts platform) - (arglist link-options platform) " " src " -o " out " : " - src (filelist srcdir source-dependencies platform)) + (arglist link-options platform) " " src " -o " out) (print-end-command platform))) (define ((compile-dynamic-program name #!key source mode @@ -589,15 +601,16 @@ (src (qs* (or source (conc name ".scm")) platform))) (when custom (prepare-custom-command cmd platform)) - (print "\n" (qs* default-builder platform #t) " " out " " cmd + (print "\n" (qs* default-builder platform #t) " " out " : " + src " " (qs* eggfile platform) " " + (if custom cmd "") " " + (filelist srcdir source-dependencies platform) + " : " cmd (if keep-generated-files " -k" "") " -setup-mode" (if (eq? mode 'host) " -host" "") " -I " srcdir " -C -I" srcdir (arglist opts platform) - (arglist link-options platform) " " src " -o " out " : " - src " " (qs* eggfile platform) " " - (if custom cmd "") " " - (filelist srcdir source-dependencies platform)) + (arglist link-options platform) " " src " -o " out) (print-end-command platform))) (define ((compile-static-program name #!key source @@ -619,15 +632,16 @@ (src (qs* (or source (conc name ".scm")) platform))) (when custom (prepare-custom-command cmd platform)) - (print "\n" (qs* default-builder platform #t) " " out " " cmd + (print "\n" (qs* default-builder platform #t) " " out " : " + src " " (qs* eggfile platform) " " + (if custom cmd "") " " + (filelist srcdir source-dependencies platform) + " : " cmd (if keep-generated-files " -k" "") (if (eq? mode 'host) " -host" "") " -static -setup-mode -I " srcdir " -C -I" srcdir (arglist opts platform) - (arglist link-options platform) " " src " -o " out " : " - src " " (qs* eggfile platform) " " - (if custom cmd "") " " - (filelist srcdir source-dependencies platform)) + (arglist link-options platform) " " src " -o " out) (print-end-command platform))) (define ((compile-generated-file name #!key source custom @@ -637,9 +651,10 @@ (out (qs* (or source name) platform))) (prepare-custom-command cmd platform) (print "\n" (qs* default-builder platform #t) - " " out " " cmd " : " cmd " " + " " out " : " cmd " " (qs* eggfile platform) " " - (filelist srcdir source-dependencies platform)) + (filelist srcdir source-dependencies platform) + " : " cmd) (print-end-command platform))) @@ -979,3 +994,7 @@ EOF (p1 (substring fname 0 plen))) (assert (string=? prefix p1) "wrong prefix") (substring fname (add1 plen)))) + +(define (joins strs) (string-intersperse strs " ")) + +(define (maybe f x) (if f (list x) '())) -- 2.16.2