NetBSD/usr.bin/make/compat.c

755 lines
20 KiB
C
Raw Normal View History

PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
/* $NetBSD: compat.c,v 1.95 2014/08/23 15:05:40 christos Exp $ */
1993-03-21 12:45:37 +03:00
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
1993-03-21 12:45:37 +03:00
* Copyright (c) 1988, 1989 by Adam de Boor
* Copyright (c) 1989 by Berkeley Softworks
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
static char rcsid[] = "$NetBSD: compat.c,v 1.95 2014/08/23 15:05:40 christos Exp $";
#else
1997-07-02 01:17:00 +04:00
#include <sys/cdefs.h>
1993-03-21 12:45:37 +03:00
#ifndef lint
#if 0
static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
#else
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
__RCSID("$NetBSD: compat.c,v 1.95 2014/08/23 15:05:40 christos Exp $");
#endif
1993-03-21 12:45:37 +03:00
#endif /* not lint */
#endif
1993-03-21 12:45:37 +03:00
/*-
* compat.c --
* The routines in this file implement the full-compatibility
* mode of PMake. Most of the special functionality of PMake
* is available in this mode. Things not supported:
* - different shells.
* - friendly variable substitution.
*
* Interface:
* Compat_Run Initialize things for this module and recreate
* thems as need creatin'
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
1993-03-21 12:45:37 +03:00
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
1993-03-21 12:45:37 +03:00
#include "make.h"
#include "hash.h"
#include "dir.h"
#include "job.h"
#include "pathnames.h"
1993-03-21 12:45:37 +03:00
/*
* The following array is used to make a fast determination of which
* characters are interpreted specially by the shell. If a command
* contains any of these characters, it is executed by the shell, not
* directly by us.
*/
static char meta[256];
static GNode *curTarg = NULL;
1993-03-21 12:45:37 +03:00
static GNode *ENDNode;
static void CompatInterrupt(int);
1993-03-21 12:45:37 +03:00
static void
Compat_Init(void)
{
const char *cp;
Shell_Init(); /* setup default shell */
for (cp = "~#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++) {
meta[(unsigned char) *cp] = 1;
}
/*
* The null character serves as a sentinel in the string.
*/
meta[0] = 1;
}
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* CompatInterrupt --
* Interrupt the creation of the current target and remove it if
* it ain't precious.
*
* Results:
* None.
*
* Side Effects:
* The target is removed and the process exits. If .INTERRUPT exists,
* its commands are run first WITH INTERRUPTS IGNORED..
*
*-----------------------------------------------------------------------
*/
static void
CompatInterrupt(int signo)
1993-03-21 12:45:37 +03:00
{
GNode *gn;
if ((curTarg != NULL) && !Targ_Precious (curTarg)) {
char *p1;
char *file = Var_Value(TARGET, curTarg, &p1);
1993-03-21 12:45:37 +03:00
if (!noExecute && eunlink(file) != -1) {
2002-03-21 04:24:43 +03:00
Error("*** %s removed", file);
1993-03-21 12:45:37 +03:00
}
if (p1)
free(p1);
1993-03-21 12:45:37 +03:00
/*
* Run .INTERRUPT only if hit with interrupt signal
*/
if (signo == SIGINT) {
gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
if (gn != NULL) {
Compat_Make(gn, gn);
1993-03-21 12:45:37 +03:00
}
}
1993-03-21 12:45:37 +03:00
}
if (signo == SIGQUIT)
_exit(signo);
bmake_signal(signo, SIG_DFL);
kill(myPid, signo);
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* CompatRunCommand --
* Execute the next command for a target. If the command returns an
* error, the node's made field is set to ERROR and creation stops.
*
* Input:
* cmdp Command to execute
* gnp Node from which the command came
*
1993-03-21 12:45:37 +03:00
* Results:
* 0 if the command succeeded, 1 if an error occurred.
*
* Side Effects:
* The node's 'made' field may be set to ERROR.
*
*-----------------------------------------------------------------------
*/
int
CompatRunCommand(void *cmdp, void *gnp)
1993-03-21 12:45:37 +03:00
{
char *cmdStart; /* Start of expanded command */
char *cp, *bp;
1993-03-21 12:45:37 +03:00
Boolean silent, /* Don't print command */
2006-10-22 20:23:20 +04:00
doIt; /* Execute even if -n */
volatile Boolean errCheck; /* Check errors */
int reason; /* Reason for child's death */
1993-03-21 12:45:37 +03:00
int status; /* Description of child's death */
pid_t cpid; /* Child actually found */
pid_t retstat; /* Result of wait */
1993-03-21 12:45:37 +03:00
LstNode cmdNode; /* Node where current command is located */
2006-10-22 20:23:20 +04:00
const char ** volatile av; /* Argument vector for thing to exec */
char ** volatile mav;/* Copy of the argument vector for freeing */
int argc; /* Number of arguments in av or 0 if not
1993-03-21 12:45:37 +03:00
* dynamically allocated */
Boolean local; /* TRUE if command should be executed
* locally */
Boolean useShell; /* TRUE if command should be executed
* using a shell */
2006-10-22 20:23:20 +04:00
char * volatile cmd = (char *)cmdp;
GNode *gn = (GNode *)gnp;
1993-03-21 12:45:37 +03:00
silent = gn->type & OP_SILENT;
errCheck = !(gn->type & OP_IGNORE);
doIt = FALSE;
cmdNode = Lst_Member(gn->commands, cmd);
cmdStart = Var_Subst(NULL, cmd, gn, FALSE);
1993-03-21 12:45:37 +03:00
/*
* brk_string will return an argv with a NULL in av[0], thus causing
1993-03-21 12:45:37 +03:00
* execvp to choke and die horribly. Besides, how can we execute a null
* command? In any case, we warn the user that the command expanded to
* nothing (is this the right thing to do?).
*/
1993-03-21 12:45:37 +03:00
if (*cmdStart == '\0') {
free(cmdStart);
1993-03-21 12:45:37 +03:00
return(0);
}
2009-01-17 00:14:30 +03:00
cmd = cmdStart;
Lst_Replace(cmdNode, cmdStart);
1993-03-21 12:45:37 +03:00
if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {
(void)Lst_AtEnd(ENDNode->commands, cmdStart);
1993-03-21 12:45:37 +03:00
return(0);
2009-01-17 00:14:30 +03:00
}
if (strcmp(cmdStart, "...") == 0) {
1993-03-21 12:45:37 +03:00
gn->type |= OP_SAVE_CMDS;
return(0);
}
while ((*cmd == '@') || (*cmd == '-') || (*cmd == '+')) {
switch (*cmd) {
case '@':
silent = DEBUG(LOUD) ? FALSE : TRUE;
break;
case '-':
1993-03-21 12:45:37 +03:00
errCheck = FALSE;
break;
case '+':
doIt = TRUE;
if (!meta[0]) /* we came here from jobs */
Compat_Init();
break;
1993-03-21 12:45:37 +03:00
}
cmd++;
}
while (isspace((unsigned char)*cmd))
cmd++;
/*
* If we did not end up with a command, just skip it.
*/
if (!*cmd)
return (0);
#if !defined(MAKE_NATIVE)
/*
* In a non-native build, the host environment might be weird enough
* that it's necessary to go through a shell to get the correct
* behaviour. Or perhaps the shell has been replaced with something
* that does extra logging, and that should not be bypassed.
*/
useShell = TRUE;
#else
1993-03-21 12:45:37 +03:00
/*
* Search for meta characters in the command. If there are no meta
* characters, there's no need to execute a shell to execute the
* command.
*/
for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {
1993-03-21 12:45:37 +03:00
continue;
}
useShell = (*cp != '\0');
#endif
1993-03-21 12:45:37 +03:00
/*
* Print the command before echoing if we're not supposed to be quiet for
* this one. We also print the command if -n given.
*/
if (!silent || NoExecute(gn)) {
printf("%s\n", cmd);
1993-03-21 12:45:37 +03:00
fflush(stdout);
}
/*
* If we're not supposed to execute any commands, this is as far as
* we go...
*/
if (!doIt && NoExecute(gn)) {
1993-03-21 12:45:37 +03:00
return (0);
}
2009-01-17 00:14:30 +03:00
if (DEBUG(JOB))
fprintf(debug_file, "Execute: '%s'\n", cmd);
2008-12-20 01:01:19 +03:00
again:
if (useShell) {
1993-03-21 12:45:37 +03:00
/*
* We need to pass the command off to the shell, typically
* because the command contains a "meta" character.
1993-03-21 12:45:37 +03:00
*/
static const char *shargv[5];
int shargc;
1993-03-21 12:45:37 +03:00
shargc = 0;
shargv[shargc++] = shellPath;
/*
* The following work for any of the builtin shell specs.
*/
if (errCheck && shellErrFlag) {
shargv[shargc++] = shellErrFlag;
}
if (DEBUG(SHELL))
shargv[shargc++] = "-xc";
else
shargv[shargc++] = "-c";
shargv[shargc++] = cmd;
shargv[shargc++] = NULL;
1993-03-21 12:45:37 +03:00
av = shargv;
argc = 0;
bp = NULL;
mav = NULL;
1993-03-21 12:45:37 +03:00
} else {
/*
* No meta-characters, so no need to exec a shell. Break the command
* into words to form an argument vector we can execute.
*/
2008-12-20 01:01:19 +03:00
mav = brk_string(cmd, &argc, TRUE, &bp);
if (mav == NULL) {
useShell = 1;
goto again;
}
av = (void *)mav;
1993-03-21 12:45:37 +03:00
}
1993-03-21 12:45:37 +03:00
local = TRUE;
#ifdef USE_META
if (useMeta) {
meta_compat_start();
}
#endif
1993-03-21 12:45:37 +03:00
/*
* Fork and execute the single command. If the fork fails, we abort.
*/
cpid = vFork();
1993-03-21 12:45:37 +03:00
if (cpid < 0) {
Fatal("Could not fork");
}
if (cpid == 0) {
Var_ExportVars();
#ifdef USE_META
if (useMeta) {
meta_compat_child();
}
#endif
if (local)
2003-07-14 22:19:11 +04:00
(void)execvp(av[0], (char *const *)UNCONST(av));
else
2003-07-14 22:19:11 +04:00
(void)execv(av[0], (char *const *)UNCONST(av));
execError("exec", av[0]);
_exit(1);
1993-03-21 12:45:37 +03:00
}
if (mav)
free(mav);
if (bp)
free(bp);
Lst_Replace(cmdNode, NULL);
#ifdef USE_META
if (useMeta) {
meta_compat_parent();
}
#endif
1993-03-21 12:45:37 +03:00
/*
* The child is off and running. Now all we can do is wait...
*/
while (1) {
1993-03-21 12:45:37 +03:00
while ((retstat = wait(&reason)) != cpid) {
if (retstat > 0)
JobReapChild(retstat, reason, FALSE); /* not ours? */
if (retstat == -1 && errno != EINTR) {
1993-03-21 12:45:37 +03:00
break;
}
}
if (retstat > -1) {
1993-03-21 12:45:37 +03:00
if (WIFSTOPPED(reason)) {
status = WSTOPSIG(reason); /* stopped */
1993-03-21 12:45:37 +03:00
} else if (WIFEXITED(reason)) {
status = WEXITSTATUS(reason); /* exited */
#if defined(USE_META) && defined(USE_FILEMON_ONCE)
if (useMeta) {
meta_cmd_finish(NULL);
}
#endif
1993-03-21 12:45:37 +03:00
if (status != 0) {
if (DEBUG(ERROR)) {
fprintf(debug_file, "\n*** Failed target: %s\n*** Failed command: ",
gn->name);
for (cp = cmd; *cp; ) {
if (isspace((unsigned char)*cp)) {
fprintf(debug_file, " ");
while (isspace((unsigned char)*cp))
cp++;
} else {
fprintf(debug_file, "%c", *cp);
cp++;
}
}
fprintf(debug_file, "\n");
}
printf("*** Error code %d", status);
1993-03-21 12:45:37 +03:00
}
} else {
status = WTERMSIG(reason); /* signaled */
printf("*** Signal %d", status);
}
1993-03-21 12:45:37 +03:00
if (!WIFEXITED(reason) || (status != 0)) {
if (errCheck) {
#ifdef USE_META
if (useMeta) {
meta_job_error(NULL, gn, 0, status);
}
#endif
1993-03-21 12:45:37 +03:00
gn->made = ERROR;
if (keepgoing) {
/*
* Abort the current target, but let others
* continue.
*/
printf(" (continuing)\n");
1993-03-21 12:45:37 +03:00
}
} else {
/*
* Continue executing commands for this target.
* If we return 0, this will happen...
*/
printf(" (ignored)\n");
1993-03-21 12:45:37 +03:00
status = 0;
}
}
break;
} else {
Fatal("error in wait: %d: %s", retstat, strerror(errno));
1993-03-21 12:45:37 +03:00
/*NOTREACHED*/
}
}
free(cmdStart);
1993-03-21 12:45:37 +03:00
return (status);
}
/*-
*-----------------------------------------------------------------------
* Compat_Make --
1993-03-21 12:45:37 +03:00
* Make a target.
*
* Input:
* gnp The node to make
* pgnp Parent to abort if necessary
*
1993-03-21 12:45:37 +03:00
* Results:
* 0
*
* Side Effects:
* If an error is detected and not being ignored, the process exits.
*
*-----------------------------------------------------------------------
*/
int
Compat_Make(void *gnp, void *pgnp)
1993-03-21 12:45:37 +03:00
{
GNode *gn = (GNode *)gnp;
GNode *pgn = (GNode *)pgnp;
if (!meta[0]) /* we came here from jobs */
Compat_Init();
if (gn->made == UNMADE && (gn == pgn || (pgn->type & OP_MADE) == 0)) {
1993-03-21 12:45:37 +03:00
/*
* First mark ourselves to be made, then apply whatever transformations
* the suffix module thinks are necessary. Once that's done, we can
* descend and make all our children. If any of them has an error
* but the -k flag was given, our 'make' field will be set FALSE again.
* This is our signal to not attempt to do anything but abort our
* parent as well.
*/
gn->flags |= REMAKE;
1993-03-21 12:45:37 +03:00
gn->made = BEINGMADE;
if ((gn->type & OP_MADE) == 0)
Suff_FindDeps(gn);
Lst_ForEach(gn->children, Compat_Make, gn);
if ((gn->flags & REMAKE) == 0) {
1993-03-21 12:45:37 +03:00
gn->made = ABORTED;
pgn->flags &= ~REMAKE;
goto cohorts;
1993-03-21 12:45:37 +03:00
}
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
Make_SetImpsrcLocalVar(gn, pgn);
1993-03-21 12:45:37 +03:00
/*
* All the children were made ok. Now cmgn->mtime contains the
* modification time of the newest child, we need to find out if we
* exist and when we were modified last. The criteria for datedness
* are defined by the Make_OODate function.
1993-03-21 12:45:37 +03:00
*/
if (DEBUG(MAKE)) {
fprintf(debug_file, "Examining %s...", gn->name);
1993-03-21 12:45:37 +03:00
}
if (! Make_OODate(gn)) {
gn->made = UPTODATE;
if (DEBUG(MAKE)) {
fprintf(debug_file, "up-to-date.\n");
1993-03-21 12:45:37 +03:00
}
goto cohorts;
1993-03-21 12:45:37 +03:00
} else if (DEBUG(MAKE)) {
fprintf(debug_file, "out-of-date.\n");
1993-03-21 12:45:37 +03:00
}
/*
* If the user is just seeing if something is out-of-date, exit now
* to tell him/her "yes".
*/
if (queryFlag) {
exit(1);
1993-03-21 12:45:37 +03:00
}
/*
* 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
* Make_DoAllVar().
*/
Make_DoAllVar(gn);
1993-03-21 12:45:37 +03:00
/*
* Alter our type to tell if errors should be ignored or things
* should not be printed so CompatRunCommand knows what to do.
*/
if (Targ_Ignore(gn)) {
1993-03-21 12:45:37 +03:00
gn->type |= OP_IGNORE;
}
if (Targ_Silent(gn)) {
1993-03-21 12:45:37 +03:00
gn->type |= OP_SILENT;
}
if (Job_CheckCommands(gn, Fatal)) {
1993-03-21 12:45:37 +03:00
/*
* Our commands are ok, but we still have to worry about the -t
* flag...
*/
if (!touchFlag || (gn->type & OP_MAKE)) {
1993-03-21 12:45:37 +03:00
curTarg = gn;
#ifdef USE_META
if (useMeta && !NoExecute(gn)) {
meta_job_start(NULL, gn);
}
#endif
Lst_ForEach(gn->commands, CompatRunCommand, gn);
curTarg = NULL;
1993-03-21 12:45:37 +03:00
} else {
Job_Touch(gn, gn->type & OP_SILENT);
1993-03-21 12:45:37 +03:00
}
} else {
gn->made = ERROR;
}
#ifdef USE_META
if (useMeta && !NoExecute(gn)) {
meta_job_finish(NULL);
}
#endif
1993-03-21 12:45:37 +03:00
if (gn->made != ERROR) {
/*
* If the node was made successfully, mark it so, update
* its modification time and timestamp all its parents. Note
* that for .ZEROTIME targets, the timestamping isn't done.
* This is to keep its state from affecting that of its parent.
*/
gn->made = MADE;
pgn->flags |= Make_Recheck(gn) == 0 ? FORCE : 0;
1993-03-21 12:45:37 +03:00
if (!(gn->type & OP_EXEC)) {
pgn->flags |= CHILDMADE;
1993-03-21 12:45:37 +03:00
Make_TimeStamp(pgn, gn);
}
} else if (keepgoing) {
pgn->flags &= ~REMAKE;
1993-03-21 12:45:37 +03:00
} else {
PrintOnError(gn, "\n\nStop.");
exit(1);
1993-03-21 12:45:37 +03:00
}
} else if (gn->made == ERROR) {
/*
* Already had an error when making this beastie. Tell the parent
* to abort.
*/
pgn->flags &= ~REMAKE;
1993-03-21 12:45:37 +03:00
} else {
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
Make_SetImpsrcLocalVar(gn, pgn);
1993-03-21 12:45:37 +03:00
switch(gn->made) {
case BEINGMADE:
2002-03-21 04:24:43 +03:00
Error("Graph cycles through %s", gn->name);
1993-03-21 12:45:37 +03:00
gn->made = ERROR;
pgn->flags &= ~REMAKE;
1993-03-21 12:45:37 +03:00
break;
case MADE:
if ((gn->type & OP_EXEC) == 0) {
pgn->flags |= CHILDMADE;
1993-03-21 12:45:37 +03:00
Make_TimeStamp(pgn, gn);
}
break;
case UPTODATE:
if ((gn->type & OP_EXEC) == 0) {
Make_TimeStamp(pgn, gn);
}
break;
default:
break;
1993-03-21 12:45:37 +03:00
}
}
cohorts:
Lst_ForEach(gn->cohorts, Compat_Make, pgnp);
1993-03-21 12:45:37 +03:00
return (0);
}
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* Compat_Run --
* Initialize this mode and start making.
*
* Input:
* targs List of target nodes to re-create
*
1993-03-21 12:45:37 +03:00
* Results:
* None.
*
* Side Effects:
* Guess what?
*
*-----------------------------------------------------------------------
*/
void
Compat_Run(Lst targs)
1993-03-21 12:45:37 +03:00
{
GNode *gn = NULL;/* Current root target */
1993-03-21 12:45:37 +03:00
int errors; /* Number of targets not remade due to errors */
Compat_Init();
if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGINT, CompatInterrupt);
1993-03-21 12:45:37 +03:00
}
if (bmake_signal(SIGTERM, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGTERM, CompatInterrupt);
1993-03-21 12:45:37 +03:00
}
if (bmake_signal(SIGHUP, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGHUP, CompatInterrupt);
1993-03-21 12:45:37 +03:00
}
if (bmake_signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGQUIT, CompatInterrupt);
1993-03-21 12:45:37 +03:00
}
ENDNode = Targ_FindNode(".END", TARG_CREATE);
ENDNode->type = OP_SPECIAL;
1993-03-21 12:45:37 +03:00
/*
* If the user has defined a .BEGIN target, execute the commands attached
* to it.
*/
if (!queryFlag) {
gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
if (gn != NULL) {
Compat_Make(gn, gn);
if (gn->made == ERROR) {
PrintOnError(gn, "\n\nStop.");
exit(1);
}
1993-03-21 12:45:37 +03:00
}
}
/*
* Expand .USE nodes right now, because they can modify the structure
* of the tree.
*/
Make_ExpandUse(targs);
1993-03-21 12:45:37 +03:00
/*
* For each entry in the list of targets to create, call Compat_Make on
* it to create the thing. Compat_Make will leave the 'made' field of gn
1993-03-21 12:45:37 +03:00
* in one of several states:
* UPTODATE gn was already up-to-date
* MADE gn was recreated successfully
* ERROR An error occurred while gn was being created
* ABORTED gn was not remade because one of its inferiors
* could not be made due to errors.
*/
errors = 0;
while (!Lst_IsEmpty (targs)) {
gn = (GNode *)Lst_DeQueue(targs);
Compat_Make(gn, gn);
1993-03-21 12:45:37 +03:00
if (gn->made == UPTODATE) {
printf("`%s' is up to date.\n", gn->name);
1993-03-21 12:45:37 +03:00
} else if (gn->made == ABORTED) {
printf("`%s' not remade because of errors.\n", gn->name);
1993-03-21 12:45:37 +03:00
errors += 1;
}
}
/*
* If the user has defined a .END target, run its commands.
*/
if (errors == 0) {
Compat_Make(ENDNode, ENDNode);
if (gn->made == ERROR) {
PrintOnError(gn, "\n\nStop.");
exit(1);
}
1993-03-21 12:45:37 +03:00
}
}