tech-toolchain archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: make: dealing with targets with multiple outputs
David Holland <dholland-tech%netbsd.org@localhost> wrote:
> I don't think that's the right way to do it; it should be done by
> tracking where recipes are shared (and not parameterized). I don't
> have time or energy to go look at the internals right now to think
> about how best to arrange that.
The big concern I have with your proposal (assuming I understand it
correctly) is the risk of surprising lots of people with new magic
behavior. bmake is used by lots of projects so we can never hope to
pre-fix all makefiles that a behavior change may impact.
Adding explicit syntax ensures that cannot happen.
I spent a few minutes implementing it - for compat mode it is trivial
[I used .COLLATERAL as the magic target]
--------------------8<--------------------
all: a b c
a b c:
@echo making $@
@echo A > a; echo B > b; echo C > c
# always build b if any of a b c are out-of-date
.COLLATERAL: b a c
--------------------8<--------------------
In compat mode will always build b
even if you say 'make a'
If a or c are missing for some bizzare reason, b will be made
This is basically the behavior that was requested.
And of course a make binary that does not grok the special target will
do nothing unusual.
For jobs mode if we find 'b' has already been examined and found up to
date when a or c are out-of-date, we basically just reschedule it.
If b's node is still in REQUESTED state we just ensure it will be
considered out-of-date.
I'm pretty sure there are some corner cases to address...
but the diff is pretty minimal
diff -r 6f103b9234c3 bmake/compat.c
--- a/bmake/compat.c Sun Dec 30 09:28:02 2018 -0800
+++ b/bmake/compat.c Tue Jun 18 22:53:23 2019 -0700
@@ -581,6 +581,19 @@
exit(1);
}
+ if (gn->proxygn) {
+ int rc;
+
+ /*
+ * This is what needs to be made
+ */
+ gn->proxygn->made = UNMADE;
+ gn->proxygn->flags |= FORCE;
+ rc = Compat_Make(gn->proxygn, pgn);
+ gn->made = gn->proxygn->made;
+ return (rc);
+ }
+
/*
* We need to be re-made. We also have to make sure we've got a $?
* variable. To be nice, we also define the $> variable using
diff -r 6f103b9234c3 bmake/make.c
--- a/bmake/make.c Sun Dec 30 09:28:02 2018 -0800
+++ b/bmake/make.c Tue Jun 18 22:53:23 2019 -0700
@@ -1121,6 +1121,20 @@
if (queryFlag) {
return (TRUE);
}
+ if (gn->proxygn) {
+ /*
+ * This is what needs to be made
+ */
+ gn->proxygn->flags |= FORCE; /* make sure! */
+
+ if (gn->proxygn->made == UPTODATE) {
+ gn->proxygn->made = REQUESTED;
+ Lst_InsertBefore(toBeMade, Lst_First(toBeMade),
+ gn->proxygn);
+ }
+ gn->made = UPTODATE; /* yes we lie */
+ continue;
+ }
Make_DoAllVar(gn);
Job_Make(gn);
have_token = 0;
diff -r 6f103b9234c3 bmake/make.h
--- a/bmake/make.h Sun Dec 30 09:28:02 2018 -0800
+++ b/bmake/make.h Tue Jun 18 22:53:23 2019 -0700
@@ -221,6 +221,7 @@
time_t mtime; /* Its modification time */
struct GNode *cmgn; /* The youngest child */
+ struct GNode *proxygn; /* Node to build if we are out-of-date */
Lst iParents; /* Links to parents for which this is an
* implied source, if any */
diff -r 6f103b9234c3 bmake/parse.c
--- a/bmake/parse.c Sun Dec 30 09:28:02 2018 -0800
+++ b/bmake/parse.c Tue Jun 18 22:53:23 2019 -0700
@@ -187,6 +187,7 @@
*/
typedef enum {
Begin, /* .BEGIN */
+ Collateral, /* .COLLATERAL */
Default, /* .DEFAULT */
DeleteOnError, /* .DELETE_ON_ERROR */
End, /* .END */
@@ -305,6 +306,7 @@
int op; /* Operator when used as a source */
} parseKeywords[] = {
{ ".BEGIN", Begin, 0 },
+{ ".COLLATERAL", Collateral, 0 },
{ ".DEFAULT", Default, 0 },
{ ".DELETE_ON_ERROR", DeleteOnError, 0 },
{ ".END", End, 0 },
@@ -361,7 +363,7 @@
static int ParseFindKeyword(const char *);
static int ParseLinkSrc(void *, void *);
static int ParseDoOp(void *, void *);
-static void ParseDoSrc(int, const char *);
+static void ParseDoSrc(int, const char *, GNode *);
static int ParseFindMain(void *, void *);
static int ParseAddDir(void *, void *);
static int ParseClearPath(void *, void *);
@@ -996,7 +998,7 @@
*---------------------------------------------------------------------
*/
static void
-ParseDoSrc(int tOp, const char *src)
+ParseDoSrc(int tOp, const char *src, GNode *proxygn)
{
GNode *gn = NULL;
static int wait_number = 0;
@@ -1088,6 +1090,7 @@
/* Find/create the 'src' node and attach to all targets */
gn = Targ_FindNode(src, TARG_CREATE);
+ gn->proxygn = proxygn;
if (doing_depend)
ParseMark(gn);
if (tOp) {
@@ -1212,6 +1215,7 @@
{
char *cp; /* our current position */
GNode *gn = NULL; /* a general purpose temporary node */
+ GNode *proxygn = NULL;
int op; /* the operator on the line */
char savec; /* a place to save a character */
Lst paths; /* List of search paths to alter when parsing
@@ -1738,7 +1742,7 @@
while (!Lst_IsEmpty (sources)) {
gn = (GNode *)Lst_DeQueue(sources);
- ParseDoSrc(tOp, gn->name);
+ ParseDoSrc(tOp, gn->name, proxygn);
}
Lst_Destroy(sources, NULL);
cp = line;
@@ -1748,7 +1752,11 @@
cp += 1;
}
- ParseDoSrc(tOp, line);
+ if (specType == Collateral && proxygn == NULL) {
+ /* first src is the one the rest should use */
+ proxygn = Targ_FindNode(line, TARG_CREATE);
+ } else
+ ParseDoSrc(tOp, line, proxygn);
}
while (*cp && isspace ((unsigned char)*cp)) {
cp++;
Home |
Main Index |
Thread Index |
Old Index