commit 1890360633f9e2e2db7d890f1e3a57db32dcc949 from: Benjamin Stürz date: Fri Nov 15 23:19:16 2024 UTC make: implement -f option commit - 56b8970e016ef878addb3a2bb6b965bab0618dd4 commit + 1890360633f9e2e2db7d890f1e3a57db32dcc949 blob - 05ebc849f544e93f1441be88fcfd8d5e0b91cc4c blob + fb7db528948ded17772f6914fa42f8ba2ab912e9 --- make/TODO.md +++ make/TODO.md @@ -53,7 +53,6 @@ -S opposite of `-k` -h print a generated help page -s silent, do not write commands to stdout --f file read `file` instead of `MyMakefile` # "normal" `include file` @@ -202,4 +201,3 @@ Allow specifying additional `PATH` directories. ## Write a tutorial on how to correctly use this make ## Write a specification ## Create a freestanding version, written in Rust, so that other projects can use this make -# `.include xxx, DIR, Makefile` blob - fae3ab7b588ebd6ec2fca7724642b14d063bbc34 blob + a293f0d5de67124d87a88694466fe78320acc182 --- make/make.c +++ make/make.c @@ -607,6 +607,7 @@ char *s; sub = new (struct scope); sub->next = sc->dir->subdirs; sub->parent = sc; + sub->makefile = NULL; sc->dir->subdirs = sub; p = strtok (s, ","); @@ -624,6 +625,7 @@ char *s; if (p == NULL) { sub->type = SC_DIR; sub->dir = NULL; + sub->makefile = MAKEFILE; return 0; } @@ -631,12 +633,18 @@ char *s; if (strcmp (p, "DIR") == 0) { sub->type = SC_DIR; sub->dir = NULL; + sub->makefile = MAKEFILE; + + p = strtok (NULL, ","); + if (p == NULL) + return 0; + + sub->makefile = strdup (trim (p)); return 0; } else if (strcmp (p, "GNU") == 0) { sub->type = SC_GNU; sub->gnu = new (struct gnu); sub->gnu->prog = NULL; - sub->gnu->file = NULL; p = strtok (NULL, ","); if (p == NULL) @@ -646,7 +654,7 @@ char *s; p = strtok (NULL, ","); if (p == NULL) return 0; - sub->gnu->file = strdup (trim (p)); + sub->makefile = strdup (trim (p)); return 0; } else { @@ -856,7 +864,7 @@ struct path *dir; { char *path; - asprintf (&path, "%s/" MAKEFILE, path_to_str (dir)); + asprintf (&path, "%s/%s", path_to_str (dir), sc->makefile); parse (sc, dir, path); free (path); @@ -864,14 +872,15 @@ struct path *dir; } struct scope * -parse_recursive (dir) +parse_recursive (dir, makefile) struct path *dir; +char *makefile; { struct path *mfpath, *ppath; struct scope *sc, *parent; char *path, *name; - tmppath.name = MAKEFILE; + tmppath.name = makefile; mfpath = path_cat (dir, &tmppath); path = path_to_str (mfpath); if (access (path, F_OK) != 0) { @@ -880,7 +889,9 @@ struct path *dir; } ppath = path_cat (dir, &path_super); - parent = parse_recursive (ppath); + parent = parse_recursive (ppath, makefile); + if (parent == NULL) + parent = parse_recursive (ppath, MAKEFILE); free (ppath); name = path_basename (dir); @@ -908,6 +919,7 @@ struct path *dir; } parse: + sc->makefile = makefile; sc->parent = parent; path = strdup (path_to_str (mfpath)); parse (sc, dir, path); @@ -948,25 +960,25 @@ struct expand_ctx *ctx; return ec; } -rungnu (sc, prefix, gnu, rule, q) +rungnu (sc, prefix, rule, q) struct scope *sc; struct path *prefix; -struct gnu *gnu; char *rule; { size_t len = 0; char *cmd, *prog; int ec; - prog = gnu->prog != NULL ? gnu->prog : "make"; + /* TODO: use str_*() API */ + prog = sc->gnu->prog != NULL ? sc->gnu->prog : "make"; len += strlen (prog); if (q) len += 3; - if (gnu->file != NULL) - len += strlen (gnu->file) + 4; + if (sc->makefile != NULL) + len += strlen (sc->makefile) + 4; if (rule != NULL) len += strlen (rule) + 1; @@ -977,9 +989,9 @@ char *rule; if (q) strcat (cmd, " -q"); - if (gnu->file != NULL) { + if (sc->makefile != NULL) { strcat (cmd, " -f "); - strcat (cmd, gnu->file); + strcat (cmd, sc->makefile); } if (rule != NULL) { @@ -1224,12 +1236,12 @@ struct path *prefix; goto ret; case SC_GNU: /* first check if the target is already built */ - if (rungnu (sc, prefix, sc->gnu, name, 1) == 0) { + if (rungnu (sc, prefix, name, 1) == 0) { t.tv_sec = 0; goto ret; } - if (rungnu (sc, prefix, sc->gnu, name, 0) != 0) + if (rungnu (sc, prefix, name, 0) != 0) errx (1, "building foreign directory failed"); t = now (); @@ -1311,7 +1323,7 @@ struct scope *sc; char **s; if (verbose) - printf ("=== %s/%s\n", path_to_str (prefix), MAKEFILE); + printf ("=== %s/%s\n", path_to_str (prefix), sc->makefile); if (sc->type != SC_DIR || sc->dir == NULL) errx (1, "print_sc(): must be of type SC_DIR"); @@ -1350,14 +1362,17 @@ struct scope *sc; for (sub = sc->dir->subdirs; sub != NULL; sub = sub->next) { switch (sub->type) { case SC_DIR: - printf (".include %s, DIR\n", sub->name); + printf (".include %s, DIR", sub->name); + if (sc->makefile != NULL) + printf (", %s", sc->makefile); + printf ("\n"); break; case SC_GNU: printf (".include %s, GNU", sub->name); - if (sub->gnu->prog) + if (sub->gnu->prog != NULL) printf (", %s", sub->gnu->prog); - if (sub->gnu->file) - printf (", %s", sub->gnu->file); + if (sc->makefile != NULL) + printf (", %s", sc->makefile); printf ("\n"); break; } @@ -1382,7 +1397,7 @@ struct scope *sc; usage () { - fprintf (stderr, "usage: %s [-pv] [-C dir] [target...]\n", m_make.value); + fprintf (stderr, "usage: %s [-pv] [-C dir] [-f makefile] [target...]\n", m_make.value); return 1; } @@ -1392,13 +1407,13 @@ char **argv; struct scope *sc; struct path *path; struct macro *m; - char *s, *cd = NULL; + char *s, *cd = NULL, *makefile = MAKEFILE; int i, option, pr = 0, n = 0; m_dmake.value = m_make.value = argv[0]; str_reset (); - while ((option = getopt (argc, argv, "pvC:")) != -1) { + while ((option = getopt (argc, argv, "pvC:f:")) != -1) { switch (option) { case 'p': str_push_str (" -p"); @@ -1411,6 +1426,9 @@ char **argv; case 'C': cd = optarg; break; + case 'f': + makefile = optarg; + break; case '?': return usage (); default: @@ -1445,7 +1463,9 @@ char **argv; m_dmakeflags.value = m_makeflags.value = strdup (trim (str_get ())); path = parse_path ("."); - sc = parse_recursive (path); + sc = parse_recursive (path, makefile); + if (sc == NULL) + errx (1, "failed to find or parse makefile"); if (pr) { print_sc (path, sc, verbose); blob - 9d67b3a7fb336880d2b6daab65c7ce4e9d09bad8 blob + d2758945c7b2ec8dc2490fe94f889cd012978ab9 --- make/make.h +++ make/make.h @@ -21,6 +21,7 @@ struct scope { enum scope_type type; char *name; /* optional */ struct scope *parent; /* optional */ + char *makefile; /* required */ union { struct directory *dir; /* optional */ struct gnu *gnu; /* required */ @@ -37,7 +38,6 @@ struct directory { struct gnu { char *prog; /* optional (default: "make") */ - char *file; /* optional */ }; struct dep {