mirror of
https://github.com/mirror/make.git
synced 2026-08-20 00:43:29 +08:00
Compare commits
10 Commits
3.82
...
filedef-cl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
646aeb50a1 | ||
|
|
fed90f1fa8 | ||
|
|
6a1a4343f3 | ||
|
|
e27c3fc91b | ||
|
|
9f3539c4ae | ||
|
|
1b40ffb900 | ||
|
|
0d621b0627 | ||
|
|
5ed230d3f8 | ||
|
|
b0e3148933 | ||
|
|
3b4369f170 |
116
ChangeLog
116
ChangeLog
@@ -1,3 +1,119 @@
|
||||
2000-03-13 Tim Magill <magill@gate.net>
|
||||
|
||||
* remake.c:
|
||||
(update_file_1):
|
||||
(check_dep): fixed problem with double colon rules and circular
|
||||
precursor detection.
|
||||
|
||||
2000-03-12 Tim Magill <magill@gate.net>
|
||||
|
||||
* remake.c (update_goal_chain): re-arranged logic so that it makes
|
||||
more sense. After update_file(), the target status is used to
|
||||
handle the goal and possibly remove it from the goal chain.
|
||||
|
||||
* remake.c (update_file_1): simplified handling of files with no
|
||||
command into a single block.
|
||||
|
||||
* remake.c (notice_finished_file): fixed obsolete comment.
|
||||
|
||||
* remake.c (update_file): If -q we can bail as soon as we detect
|
||||
that something needs to be remade.
|
||||
|
||||
|
||||
|
||||
2000-03-11 Tim Magill <magill@gate.net>
|
||||
|
||||
* remake.c
|
||||
(update_file): If not -k, we can bail when a failure is detected.
|
||||
If we don't, its possible that dependecies of double_colon rules
|
||||
will get built after a failure has been detected.
|
||||
|
||||
(update_goal_chain): removed unused updating_makefiles
|
||||
(update_file_1): cleaned up post remake_file() handling
|
||||
|
||||
2000-02-29 Tim Magill <magill@gate.net>
|
||||
|
||||
* remake.c (update_goal_chain): eliminated double colon loop.
|
||||
update_file() handles the double colon logic, so
|
||||
update_goal_chain() doesn't have to.
|
||||
|
||||
|
||||
* remake.c (update_file):
|
||||
(update_file_1): Moved consedered test to update_file_1() so
|
||||
update_file() can more easily return a target_state_t which
|
||||
represents the state of the entire double colon rule.
|
||||
|
||||
|
||||
2000-02-20 Tim Magill <magill@gate.net>
|
||||
|
||||
* remake.c (check_dep):
|
||||
(update_file_1):
|
||||
(update_goal_chain):
|
||||
(check_dep): Changed return value of target updating functions to
|
||||
be enum target_state_t. This allows each caller to know the state
|
||||
of the target being processed after each call. Thus,
|
||||
update_goal_chain() can know from the return value of
|
||||
update_file() whether or not a target has completed and can be
|
||||
removed from the goal chain.
|
||||
|
||||
* remake.c (update_goal_chain): removed variable
|
||||
ocommands_started, it was essentially unused.
|
||||
|
||||
|
||||
2000-02-12 Tim Magill <magill@gate.net>
|
||||
|
||||
* remake.c (update_file_1):
|
||||
(notice_finished_file):
|
||||
(remake_file):
|
||||
|
||||
* main.c (main):
|
||||
|
||||
* job.c (reap_children):
|
||||
(start_job_command):
|
||||
|
||||
* file.c (enter_file)
|
||||
(remove_intermediates):
|
||||
(print_file):
|
||||
|
||||
* filedef.h: converted update_status field from a short int, to an
|
||||
unsigned int :1. previously, update status indicated whether the
|
||||
file had actually executed any commands, won, lost, or lost under
|
||||
-q conditions. command_state indicates more clearly whether or
|
||||
not any commands have been executed for this file. lost or lost
|
||||
under -q conditions can be determined by a combination of
|
||||
question_flag and lost. Thus, update_status needs only indicate
|
||||
won or lost.
|
||||
|
||||
|
||||
* implicit.c (try_implicit_rule):
|
||||
* remake.c (check_dep):
|
||||
* remake.c (update_file_1):
|
||||
move setting of tried_implicit into try_implicit_rule(). It is
|
||||
only called in two places and the flag is set immediately after.
|
||||
|
||||
|
||||
* remake.c (update_file_1): collapsed if statement based on
|
||||
file->command_state into switch statment which immediately
|
||||
follows. Removed code that could not be reached.
|
||||
|
||||
* remake.c (update_file): advance f pointer so as not to consider
|
||||
same file twice after breaking loop.
|
||||
|
||||
* file.c (rehash_file): replaced hard coded check_renamed loop
|
||||
with standard macro. seemed like the right thing to do.
|
||||
|
||||
|
||||
2000-02-09 Tim Magill <magill@gate.net>
|
||||
Started branch for cleaning up internal make structure regarding
|
||||
recursion paths. Branch name is filedef-cleanup and was started
|
||||
from a point on the mainline at filedef-cleanup-base. either tags
|
||||
are suitable for cvs commands.
|
||||
|
||||
* file.c, filedef.h, main.c, remake.c (updated): Removed updated
|
||||
member from 'struct filedef'. filedef->command_state fully
|
||||
contains the same information and more.
|
||||
|
||||
|
||||
2000-02-07 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
For += target-specific variables we need to remember which
|
||||
|
||||
27
file.c
27
file.c
@@ -166,7 +166,7 @@ enter_file (name)
|
||||
new = (struct file *) xmalloc (sizeof (struct file));
|
||||
bzero ((char *) new, sizeof (struct file));
|
||||
new->name = new->hname = name;
|
||||
new->update_status = -1;
|
||||
new->update_status = 0; /* assume the file won */
|
||||
|
||||
if (f == 0)
|
||||
{
|
||||
@@ -199,8 +199,7 @@ rehash_file (file, name)
|
||||
register unsigned int oldhash;
|
||||
register char *n;
|
||||
|
||||
while (file->renamed != 0)
|
||||
file = file->renamed;
|
||||
check_renamed(file);
|
||||
|
||||
/* Find the hash values of the old and new names. */
|
||||
|
||||
@@ -361,7 +360,6 @@ in favor of those for `%s'."),
|
||||
MERGE (precious);
|
||||
MERGE (tried_implicit);
|
||||
MERGE (updating);
|
||||
MERGE (updated);
|
||||
MERGE (is_target);
|
||||
MERGE (cmd_target);
|
||||
MERGE (phony);
|
||||
@@ -397,7 +395,7 @@ remove_intermediates (sig)
|
||||
&& !f->secondary)
|
||||
{
|
||||
int status;
|
||||
if (f->update_status == -1)
|
||||
if (f->command_state == cs_not_started)
|
||||
/* If nothing would have created this file yet,
|
||||
don't print an "rm" command for it. */
|
||||
continue;
|
||||
@@ -659,7 +657,7 @@ print_file (f)
|
||||
file_timestamp_sprintf (buf, f->last_mtime);
|
||||
printf (_("# Last modified %s\n"), buf);
|
||||
}
|
||||
puts (f->updated
|
||||
puts ((f->command_state == cs_finished)
|
||||
? _("# File has been updated.") : _("# File has not been updated."));
|
||||
switch (f->command_state)
|
||||
{
|
||||
@@ -670,26 +668,19 @@ print_file (f)
|
||||
puts (_("# Dependencies commands running (THIS IS A BUG)."));
|
||||
break;
|
||||
case cs_not_started:
|
||||
break;
|
||||
case cs_finished:
|
||||
switch (f->update_status)
|
||||
{
|
||||
case -1:
|
||||
break;
|
||||
case 0:
|
||||
/* file won */
|
||||
puts (_("# Successfully updated."));
|
||||
break;
|
||||
case 1:
|
||||
assert (question_flag);
|
||||
puts (_("# Needs to be updated (-q is set)."));
|
||||
/* file lost */
|
||||
puts (question_flag ? _("# Needs to be updated (-q is set).")
|
||||
:_("# Failed to be updated."));
|
||||
break;
|
||||
case 2:
|
||||
puts (_("# Failed to be updated."));
|
||||
break;
|
||||
default:
|
||||
puts (_("# Invalid value in `update_status' member!"));
|
||||
fflush (stdout);
|
||||
fflush (stderr);
|
||||
abort ();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -60,9 +60,6 @@ struct file
|
||||
the same file. Otherwise this is null. */
|
||||
struct file *double_colon;
|
||||
|
||||
short int update_status; /* Status of the last attempt to update,
|
||||
or -1 if none has been made. */
|
||||
|
||||
enum /* State of the commands. */
|
||||
{ /* Note: It is important that cs_not_started be zero. */
|
||||
cs_not_started, /* Not yet started. */
|
||||
@@ -71,12 +68,15 @@ struct file
|
||||
cs_finished /* Commands finished. */
|
||||
} command_state ENUM_BITFIELD (2);
|
||||
|
||||
|
||||
unsigned int update_status:1; /* update status signifies only
|
||||
whether the file won or lost */
|
||||
|
||||
unsigned int precious:1; /* Non-0 means don't delete file on quit */
|
||||
unsigned int tried_implicit:1; /* Nonzero if have searched
|
||||
for implicit rule for making
|
||||
this file; don't search again. */
|
||||
unsigned int updating:1; /* Nonzero while updating deps of this file */
|
||||
unsigned int updated:1; /* Nonzero if this file has been remade. */
|
||||
unsigned int is_target:1; /* Nonzero if file is described as target. */
|
||||
unsigned int cmd_target:1; /* Nonzero if file was given on cmd line. */
|
||||
unsigned int phony:1; /* Nonzero if this is a phony file
|
||||
|
||||
12
implicit.c
12
implicit.c
@@ -37,6 +37,7 @@ try_implicit_rule (file, depth)
|
||||
struct file *file;
|
||||
unsigned int depth;
|
||||
{
|
||||
int ret = 0;
|
||||
DBF (DB_IMPLICIT, _("Looking for an implicit rule for `%s'.\n"));
|
||||
|
||||
/* The order of these searches was previously reversed. My logic now is
|
||||
@@ -45,21 +46,24 @@ try_implicit_rule (file, depth)
|
||||
should come first. */
|
||||
|
||||
if (pattern_search (file, 0, depth, 0))
|
||||
return 1;
|
||||
ret = 1;
|
||||
|
||||
#ifndef NO_ARCHIVES
|
||||
/* If this is an archive member reference, use just the
|
||||
archive member name to search for implicit rules. */
|
||||
if (ar_name (file->name))
|
||||
else if (ar_name (file->name))
|
||||
{
|
||||
DBF (DB_IMPLICIT,
|
||||
_("Looking for archive-member implicit rule for `%s'.\n"));
|
||||
if (pattern_search (file, 1, depth, 0))
|
||||
return 1;
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
file->tried_implicit = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
6
job.c
6
job.c
@@ -665,7 +665,7 @@ reap_children (block, err)
|
||||
delete non-precious targets, and abort. */
|
||||
static int delete_on_error = -1;
|
||||
child_error (c->file->name, exit_code, exit_sig, coredump, 0);
|
||||
c->file->update_status = 2;
|
||||
c->file->update_status = 1;
|
||||
if (delete_on_error == -1)
|
||||
{
|
||||
struct file *f = lookup_file (".DELETE_ON_ERROR");
|
||||
@@ -693,7 +693,7 @@ reap_children (block, err)
|
||||
Since there are more commands that wanted to be run,
|
||||
the target was not completely remade. So we treat
|
||||
this as if a command had failed. */
|
||||
c->file->update_status = 2;
|
||||
c->file->update_status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1250,7 +1250,7 @@ start_job_command (child)
|
||||
return;
|
||||
|
||||
error:
|
||||
child->file->update_status = 2;
|
||||
child->file->update_status = 1;
|
||||
notice_finished_file (child->file);
|
||||
return;
|
||||
}
|
||||
|
||||
25
main.c
25
main.c
@@ -1254,7 +1254,6 @@ int main (int argc, char ** argv)
|
||||
/* Make sure the temporary file will not be remade. */
|
||||
stdin_nm = savestring (name, sizeof (name) -1);
|
||||
f = enter_file (stdin_nm);
|
||||
f->updated = 1;
|
||||
f->update_status = 0;
|
||||
f->command_state = cs_finished;
|
||||
/* Can't be intermediate, or it'll be removed too early for
|
||||
@@ -1518,7 +1517,6 @@ int main (int argc, char ** argv)
|
||||
{
|
||||
f = enter_command_line_file (*p);
|
||||
f->last_mtime = f->mtime_before_update = (FILE_TIMESTAMP) 1;
|
||||
f->updated = 1;
|
||||
f->update_status = 0;
|
||||
f->command_state = cs_finished;
|
||||
}
|
||||
@@ -1606,17 +1604,11 @@ int main (int argc, char ** argv)
|
||||
|
||||
switch (update_goal_chain (read_makefiles, 1))
|
||||
{
|
||||
case 1:
|
||||
default:
|
||||
#define BOGUS_UPDATE_STATUS 0
|
||||
assert (BOGUS_UPDATE_STATUS);
|
||||
break;
|
||||
|
||||
case -1:
|
||||
/* Did nothing. */
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 1:
|
||||
/* Failed to update. Figure out if we care. */
|
||||
{
|
||||
/* Nonzero if any makefile was successfully remade. */
|
||||
@@ -1633,7 +1625,7 @@ int main (int argc, char ** argv)
|
||||
again to print an error. */
|
||||
d->file->considered = 0;
|
||||
|
||||
if (d->file->updated)
|
||||
if (d->file->command_state == cs_finished)
|
||||
{
|
||||
/* This makefile was updated. */
|
||||
if (d->file->update_status == 0)
|
||||
@@ -1836,18 +1828,19 @@ int main (int argc, char ** argv)
|
||||
{
|
||||
case -1:
|
||||
/* Nothing happened. */
|
||||
/* FALL THRU */
|
||||
case 0:
|
||||
/* Updated successfully. */
|
||||
status = EXIT_SUCCESS;
|
||||
break;
|
||||
case 2:
|
||||
/* Updating failed. POSIX.2 specifies exit status >1 for this;
|
||||
but in VMS, there is only success and failure. */
|
||||
status = EXIT_FAILURE ? 2 : EXIT_FAILURE;
|
||||
break;
|
||||
case 1:
|
||||
if (question_flag)
|
||||
/* We are under -q and would run some commands. */
|
||||
status = EXIT_FAILURE;
|
||||
status = EXIT_FAILURE;
|
||||
else
|
||||
/* Updating failed. POSIX.2 specifies exit status >1 for this;
|
||||
but in VMS, there is only success and failure. */
|
||||
status = EXIT_FAILURE ? 2 : EXIT_FAILURE;
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
|
||||
415
remake.c
415
remake.c
@@ -43,12 +43,39 @@ Boston, MA 02111-1307, USA. */
|
||||
extern int try_implicit_rule PARAMS ((struct file *file, unsigned int depth));
|
||||
|
||||
|
||||
/* this enum encapsulates the return status of the recursive update
|
||||
functions. Note: these values are important so that the state of
|
||||
precursors can be or'ed together */
|
||||
typedef enum {
|
||||
ts_done = 0, /* all precursors and target are complete */
|
||||
ts_incomplete = 1, /* some precursor or target is still running */
|
||||
ts_failed = 3, /* some precursor or target failed */
|
||||
ts_sentinal /* make ANSI happy with non trailing , */
|
||||
} target_state_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/* the test for circular dependencies is based just on the 'updating'
|
||||
bit in 'struct file'. However double colon targets have seperate
|
||||
'struct file's. Therefore, we will lose if we don't notice that a
|
||||
double colon targets are really the same file. Use the 'struct
|
||||
file' at the base of the double colon chain. */
|
||||
|
||||
#define set_updating(file) (((file)->double_colon ? \
|
||||
(file)->double_colon : (file))->updating = 1)
|
||||
#define clr_updating(file) (((file)->double_colon ? \
|
||||
(file)->double_colon : (file))->updating = 0)
|
||||
#define tst_updating(file) (((file)->double_colon ? \
|
||||
(file)->double_colon : (file))->updating)
|
||||
|
||||
|
||||
/* Incremented when a command is started (under -n, when one would be). */
|
||||
unsigned int commands_started = 0;
|
||||
|
||||
static int update_file PARAMS ((struct file *file, unsigned int depth));
|
||||
static int update_file_1 PARAMS ((struct file *file, unsigned int depth));
|
||||
static int check_dep PARAMS ((struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr));
|
||||
static target_state_t update_file PARAMS ((struct file *file, unsigned int depth));
|
||||
static target_state_t update_file_1 PARAMS ((struct file *file, unsigned int depth));
|
||||
static target_state_t check_dep PARAMS ((struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr));
|
||||
static int touch_file PARAMS ((struct file *file));
|
||||
static void remake_file PARAMS ((struct file *file));
|
||||
static FILE_TIMESTAMP name_mtime PARAMS ((char *name));
|
||||
@@ -62,8 +89,6 @@ static int library_search PARAMS ((char **lib, FILE_TIMESTAMP *mtime_ptr));
|
||||
should only make one goal at a time and return as soon as one goal whose
|
||||
`changed' member is nonzero is successfully made. */
|
||||
|
||||
/* We need to know this "lower down" for correct error handling. */
|
||||
static int updating_makefiles = 0;
|
||||
|
||||
int
|
||||
update_goal_chain (goals, makefiles)
|
||||
@@ -74,10 +99,6 @@ update_goal_chain (goals, makefiles)
|
||||
unsigned int j = job_slots;
|
||||
int status = -1;
|
||||
|
||||
updating_makefiles = makefiles;
|
||||
|
||||
#define MTIME(file) (makefiles ? file_mtime_no_search (file) \
|
||||
: file_mtime (file))
|
||||
|
||||
/* Duplicate the chain so we can remove things from it. */
|
||||
|
||||
@@ -117,103 +138,73 @@ update_goal_chain (goals, makefiles)
|
||||
{
|
||||
/* Iterate over all double-colon entries for this file. */
|
||||
struct file *file;
|
||||
int stop = 0, any_not_updated = 0;
|
||||
target_state_t target_state;
|
||||
|
||||
for (file = g->file->double_colon ? g->file->double_colon : g->file;
|
||||
file != NULL;
|
||||
file = file->prev)
|
||||
target_state = ts_done;
|
||||
|
||||
file = g->file;
|
||||
check_renamed (file);
|
||||
if (makefiles)
|
||||
{
|
||||
unsigned int ocommands_started;
|
||||
int x;
|
||||
check_renamed (file);
|
||||
if (makefiles)
|
||||
if (file->cmd_target)
|
||||
{
|
||||
if (file->cmd_target)
|
||||
{
|
||||
touch_flag = t;
|
||||
question_flag = q;
|
||||
just_print_flag = n;
|
||||
}
|
||||
else
|
||||
touch_flag = question_flag = just_print_flag = 0;
|
||||
touch_flag = t;
|
||||
question_flag = q;
|
||||
just_print_flag = n;
|
||||
}
|
||||
|
||||
/* Save the old value of `commands_started' so we can compare
|
||||
later. It will be incremented when any commands are
|
||||
actually run. */
|
||||
ocommands_started = commands_started;
|
||||
|
||||
x = update_file (file, makefiles ? 1 : 0);
|
||||
check_renamed (file);
|
||||
|
||||
/* Set the goal's `changed' flag if any commands were started
|
||||
by calling update_file above. We check this flag below to
|
||||
decide when to give an "up to date" diagnostic. */
|
||||
g->changed += commands_started - ocommands_started;
|
||||
|
||||
/* If we updated a file and STATUS was not already 1, set it to
|
||||
1 if updating failed, or to 0 if updating succeeded. Leave
|
||||
STATUS as it is if no updating was done. */
|
||||
|
||||
stop = 0;
|
||||
if ((x != 0 || file->updated) && status < 1)
|
||||
{
|
||||
if (file->update_status != 0)
|
||||
{
|
||||
/* Updating failed, or -q triggered. The STATUS value
|
||||
tells our caller which. */
|
||||
status = file->update_status;
|
||||
/* If -q just triggered, stop immediately. It doesn't
|
||||
matter how much more we run, since we already know
|
||||
the answer to return. */
|
||||
stop = (!keep_going_flag && !question_flag
|
||||
&& !makefiles);
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE_TIMESTAMP mtime = MTIME (file);
|
||||
check_renamed (file);
|
||||
|
||||
if (file->updated && g->changed &&
|
||||
mtime != file->mtime_before_update)
|
||||
{
|
||||
/* Updating was done. If this is a makefile and
|
||||
just_print_flag or question_flag is set (meaning
|
||||
-n or -q was given and this file was specified
|
||||
as a command-line target), don't change STATUS.
|
||||
If STATUS is changed, we will get re-exec'd, and
|
||||
enter an infinite loop. */
|
||||
if (!makefiles
|
||||
|| (!just_print_flag && !question_flag))
|
||||
status = 0;
|
||||
if (makefiles && file->dontcare)
|
||||
/* This is a default makefile; stop remaking. */
|
||||
stop = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep track if any double-colon entry is not finished.
|
||||
When they are all finished, the goal is finished. */
|
||||
any_not_updated |= !file->updated;
|
||||
|
||||
if (stop)
|
||||
break;
|
||||
else
|
||||
touch_flag = question_flag = just_print_flag = 0;
|
||||
}
|
||||
|
||||
/* Reset FILE since it is null at the end of the loop. */
|
||||
file = g->file;
|
||||
commands_started = 0;
|
||||
|
||||
if (stop || !any_not_updated)
|
||||
target_state = update_file (file, makefiles ? 1 : 0);
|
||||
check_renamed (file);
|
||||
|
||||
/* Set the goal's `changed' flag if any commands were started
|
||||
by calling update_file above. We check this flag below to
|
||||
decide when to give an "up to date" diagnostic. */
|
||||
g->changed |= commands_started ? 1 : 0;
|
||||
|
||||
|
||||
/* process the file according to its return */
|
||||
switch (target_state)
|
||||
{
|
||||
/* If we have found nothing whatever to do for the goal,
|
||||
print a message saying nothing needs doing. */
|
||||
case ts_failed:
|
||||
/* Bail early? */
|
||||
if (!keep_going_flag && !question_flag && !makefiles)
|
||||
return 1;
|
||||
|
||||
status = 1; /* mark status failed, keep going */
|
||||
/* -k, Fall Though !!! */
|
||||
|
||||
case ts_done:
|
||||
{
|
||||
FILE_TIMESTAMP mtime =
|
||||
(makefiles ? file_mtime_no_search (file) : file_mtime (file));
|
||||
|
||||
check_renamed (file);
|
||||
|
||||
if (g->changed && mtime != file->mtime_before_update)
|
||||
{
|
||||
/* Updating was done. If this is a makefile and
|
||||
just_print_flag or question_flag is set (meaning
|
||||
-n or -q was given and this file was specified
|
||||
as a command-line target), don't change STATUS.
|
||||
If STATUS is changed, we will get re-exec'd, and
|
||||
enter an infinite loop. */
|
||||
if (status < 0)
|
||||
{
|
||||
if (!makefiles || (!just_print_flag && !question_flag))
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!makefiles
|
||||
/* If the update_status is zero, we updated successfully
|
||||
or not at all. G->changed will have been set above if
|
||||
any commands were actually started for this goal. */
|
||||
&& file->update_status == 0 && !g->changed
|
||||
&& !file->update_status && !g->changed
|
||||
/* Never give a message under -s or -q. */
|
||||
&& !silent_flag && !question_flag)
|
||||
message (1, ((file->phony || file->cmds == 0)
|
||||
@@ -221,24 +212,27 @@ update_goal_chain (goals, makefiles)
|
||||
: _("`%s' is up to date.")),
|
||||
file->name);
|
||||
|
||||
/* This goal is finished. Remove it from the chain. */
|
||||
case ts_incomplete:
|
||||
break; /* do nothing */
|
||||
}
|
||||
|
||||
|
||||
/* advance to next target in goal chain */
|
||||
if (target_state == ts_incomplete)
|
||||
{
|
||||
lastgoal = g;
|
||||
g = g->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastgoal == 0)
|
||||
goals = g->next;
|
||||
else
|
||||
lastgoal->next = g->next;
|
||||
|
||||
/* Free the storage. */
|
||||
free ((char *) g);
|
||||
free (g);
|
||||
|
||||
g = lastgoal == 0 ? goals : lastgoal->next;
|
||||
|
||||
if (stop)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastgoal = g;
|
||||
g = g->next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,9 +252,10 @@ update_goal_chain (goals, makefiles)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* If FILE is not up to date, execute the commands for it.
|
||||
Return 0 if successful, 1 if unsuccessful;
|
||||
but with some flag settings, just call `exit' if unsuccessful.
|
||||
/* If FILE is not up to date, execute the commands for it. Return
|
||||
ts_done if FILE has completed successfully, ts_incomplete if FILE
|
||||
or any of its precursors are incomplete, or ts_failed if FILE or
|
||||
any of its precursors failed.
|
||||
|
||||
DEPTH is the depth in recursions of this function.
|
||||
We increment it during the consideration of our dependencies,
|
||||
@@ -270,36 +265,32 @@ update_goal_chain (goals, makefiles)
|
||||
If there are multiple double-colon entries for FILE,
|
||||
each is considered in turn. */
|
||||
|
||||
static int
|
||||
static target_state_t
|
||||
update_file (file, depth)
|
||||
struct file *file;
|
||||
unsigned int depth;
|
||||
{
|
||||
register int status = 0;
|
||||
register target_state_t status = ts_done;
|
||||
register struct file *f;
|
||||
|
||||
f = file->double_colon ? file->double_colon : file;
|
||||
|
||||
/* Prune the dependency graph: if we've already been here on _this_
|
||||
pass through the dependency graph, we don't have to go any further.
|
||||
We won't reap_children until we start the next pass, so no state
|
||||
change is possible below here until then. */
|
||||
if (f->considered == considered)
|
||||
{
|
||||
DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This loop runs until we start commands for a double colon rule, or until
|
||||
the chain is exhausted. */
|
||||
for (; f != 0; f = f->prev)
|
||||
{
|
||||
f->considered = considered;
|
||||
|
||||
status |= update_file_1 (f, depth);
|
||||
check_renamed (f);
|
||||
|
||||
if (status != 0 && !keep_going_flag)
|
||||
if (status == ts_failed)
|
||||
{
|
||||
if (!keep_going_flag || question_flag)
|
||||
return ts_failed;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == ts_incomplete)
|
||||
break;
|
||||
|
||||
if (f->command_state == cs_running
|
||||
@@ -307,65 +298,88 @@ update_file (file, depth)
|
||||
{
|
||||
/* Don't run the other :: rules for this
|
||||
file until this rule is finished. */
|
||||
status = 0;
|
||||
status = ts_incomplete;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process the remaining rules in the double colon chain so they're marked
|
||||
considered. Start their prerequisites, too. */
|
||||
for (; f != 0 ; f = f->prev)
|
||||
for (f = (f ? f->prev : 0); f != 0 ; f = f->prev)
|
||||
{
|
||||
struct dep *d;
|
||||
|
||||
f->considered = considered;
|
||||
|
||||
for (d = f->deps; d != 0; d = d->next)
|
||||
status |= update_file (d->file, depth + 1);
|
||||
if ((status |= update_file (d->file, depth + 1)) == ts_failed)
|
||||
{
|
||||
if (!keep_going_flag || question_flag)
|
||||
return ts_failed;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Consider a single `struct file' and update it as appropriate. */
|
||||
/* Consider a single `struct file' and update it as appropriate.
|
||||
|
||||
static int
|
||||
Return ts_done if FILE has completed successfully, ts_incomplete if
|
||||
FILE or any of its precursors are incomplete, or ts_failed if FILE
|
||||
or any of its precursors failed.
|
||||
*/
|
||||
|
||||
static target_state_t
|
||||
update_file_1 (file, depth)
|
||||
struct file *file;
|
||||
unsigned int depth;
|
||||
{
|
||||
register FILE_TIMESTAMP this_mtime;
|
||||
int noexist, must_make, deps_changed;
|
||||
int dep_status = 0;
|
||||
target_state_t dep_status = ts_done;
|
||||
register struct dep *d, *lastd;
|
||||
int running = 0;
|
||||
|
||||
/* Prune the dependency graph: if we've already been here on _this_
|
||||
pass through the dependency graph, we don't have to go any further.
|
||||
We won't reap_children until we start the next pass, so no state
|
||||
change is possible below here until then. */
|
||||
if (file->considered == considered)
|
||||
{
|
||||
DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
|
||||
if (file->command_state == cs_finished)
|
||||
{
|
||||
return file->update_status ? ts_failed : ts_done;
|
||||
}
|
||||
return ts_incomplete;
|
||||
}
|
||||
file->considered = considered;
|
||||
|
||||
|
||||
DBF (DB_VERBOSE, _("Considering target file `%s'.\n"));
|
||||
|
||||
if (file->updated)
|
||||
{
|
||||
if (file->update_status > 0)
|
||||
{
|
||||
DBF (DB_VERBOSE,
|
||||
_("Recently tried and failed to update file `%s'.\n"));
|
||||
return file->update_status;
|
||||
}
|
||||
|
||||
DBF (DB_VERBOSE, _("File `%s' was considered already.\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (file->command_state)
|
||||
{
|
||||
case cs_not_started:
|
||||
case cs_deps_running:
|
||||
break;
|
||||
|
||||
case cs_running:
|
||||
DBF (DB_VERBOSE, _("Still updating file `%s'.\n"));
|
||||
return 0;
|
||||
return ts_incomplete;
|
||||
|
||||
case cs_finished:
|
||||
DBF (DB_VERBOSE, _("Finished updating file `%s'.\n"));
|
||||
return file->update_status;
|
||||
if (file->update_status != 0)
|
||||
{
|
||||
DBF (DB_VERBOSE,
|
||||
_("Recently tried and failed to update file `%s'.\n"));
|
||||
return ts_failed;
|
||||
}
|
||||
|
||||
DBF (DB_VERBOSE, _("File `%s' was considered already.\n"));
|
||||
return ts_done;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
@@ -373,7 +387,7 @@ update_file_1 (file, depth)
|
||||
++depth;
|
||||
|
||||
/* Notice recursive update of the same file. */
|
||||
file->updating = 1;
|
||||
set_updating(file);
|
||||
|
||||
/* Looking at the file's modtime beforehand allows the possibility
|
||||
that its name may be changed by a VPATH search, and thus it may
|
||||
@@ -383,28 +397,30 @@ update_file_1 (file, depth)
|
||||
|
||||
this_mtime = file_mtime (file);
|
||||
check_renamed (file);
|
||||
noexist = this_mtime == (FILE_TIMESTAMP) -1;
|
||||
must_make = noexist = this_mtime == (FILE_TIMESTAMP) -1;
|
||||
if (noexist)
|
||||
DBF (DB_BASIC, _("File `%s' does not exist.\n"));
|
||||
|
||||
must_make = noexist;
|
||||
|
||||
|
||||
/* If file was specified as a target with no commands,
|
||||
come up with some default commands. */
|
||||
|
||||
if (!file->phony && file->cmds == 0 && !file->tried_implicit)
|
||||
if (file->cmds == 0)
|
||||
{
|
||||
if (try_implicit_rule (file, depth))
|
||||
DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
|
||||
else
|
||||
DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
|
||||
file->tried_implicit = 1;
|
||||
}
|
||||
if (file->cmds == 0 && !file->is_target
|
||||
&& default_file != 0 && default_file->cmds != 0)
|
||||
{
|
||||
DBF (DB_IMPLICIT, _("Using default commands for `%s'.\n"));
|
||||
file->cmds = default_file->cmds;
|
||||
if (!file->phony && !file->tried_implicit)
|
||||
{
|
||||
if (try_implicit_rule (file, depth))
|
||||
DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
|
||||
else
|
||||
DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
|
||||
}
|
||||
if (!file->is_target
|
||||
&& default_file != 0 && default_file->cmds != 0)
|
||||
{
|
||||
DBF (DB_IMPLICIT, _("Using default commands for `%s'.\n"));
|
||||
file->cmds = default_file->cmds;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update all non-intermediate files we depend on, if necessary,
|
||||
@@ -421,7 +437,7 @@ update_file_1 (file, depth)
|
||||
mtime = file_mtime (d->file);
|
||||
check_renamed (d->file);
|
||||
|
||||
if (d->file->updating)
|
||||
if (tst_updating(d->file))
|
||||
{
|
||||
error (NILF, _("Circular %s <- %s dependency dropped."),
|
||||
file->name, d->file->name);
|
||||
@@ -453,7 +469,7 @@ update_file_1 (file, depth)
|
||||
while (f != 0);
|
||||
}
|
||||
|
||||
if (dep_status != 0 && !keep_going_flag)
|
||||
if (dep_status == ts_failed && !keep_going_flag)
|
||||
break;
|
||||
|
||||
if (!running)
|
||||
@@ -490,7 +506,7 @@ update_file_1 (file, depth)
|
||||
while (f != 0);
|
||||
}
|
||||
|
||||
if (dep_status != 0 && !keep_going_flag)
|
||||
if (dep_status == ts_failed && !keep_going_flag)
|
||||
break;
|
||||
|
||||
if (!running)
|
||||
@@ -499,7 +515,7 @@ update_file_1 (file, depth)
|
||||
}
|
||||
}
|
||||
|
||||
file->updating = 0;
|
||||
clr_updating(file);
|
||||
|
||||
DBF (DB_VERBOSE, _("Finished prerequisites of target file `%s'.\n"));
|
||||
|
||||
@@ -508,14 +524,14 @@ update_file_1 (file, depth)
|
||||
set_command_state (file, cs_deps_running);
|
||||
--depth;
|
||||
DBF (DB_VERBOSE, _("The prerequisites of `%s' are being made.\n"));
|
||||
return 0;
|
||||
return ts_incomplete;
|
||||
}
|
||||
|
||||
/* If any dependency failed, give up now. */
|
||||
|
||||
if (dep_status != 0)
|
||||
if (dep_status == ts_failed)
|
||||
{
|
||||
file->update_status = dep_status;
|
||||
file->update_status = 1; /* if any precursors failed, so did we */
|
||||
notice_finished_file (file);
|
||||
|
||||
depth--;
|
||||
@@ -527,7 +543,7 @@ update_file_1 (file, depth)
|
||||
error (NILF,
|
||||
_("Target `%s' not remade because of errors."), file->name);
|
||||
|
||||
return dep_status;
|
||||
return ts_failed;
|
||||
}
|
||||
|
||||
if (file->command_state == cs_deps_running)
|
||||
@@ -632,7 +648,7 @@ update_file_1 (file, depth)
|
||||
file = file->prev;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ts_done;
|
||||
}
|
||||
|
||||
DBF (DB_BASIC, _("Must remake target `%s'.\n"));
|
||||
@@ -651,32 +667,24 @@ update_file_1 (file, depth)
|
||||
if (file->command_state != cs_finished)
|
||||
{
|
||||
DBF (DB_VERBOSE, _("Commands of `%s' are being run.\n"));
|
||||
return 0;
|
||||
return ts_incomplete;
|
||||
}
|
||||
|
||||
switch (file->update_status)
|
||||
if (file->update_status)
|
||||
{
|
||||
case 2:
|
||||
DBF (DB_BASIC, _("Failed to remake target file `%s'.\n"));
|
||||
break;
|
||||
case 0:
|
||||
DBF (DB_BASIC, _("Successfully remade target file `%s'.\n"));
|
||||
break;
|
||||
case 1:
|
||||
DBF (DB_BASIC, _("Target file `%s' needs remade under -q.\n"));
|
||||
break;
|
||||
default:
|
||||
assert (file->update_status >= 0 && file->update_status <= 2);
|
||||
break;
|
||||
DBF (DB_BASIC, (question_flag ? _("Target file `%s' needs remade under -q.\n")
|
||||
: _("Failed to remake target file `%s'.\n")));
|
||||
return ts_failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBF (DB_BASIC, _("Successfully remade target file `%s'.\n"));
|
||||
return ts_done;
|
||||
}
|
||||
|
||||
file->updated = 1;
|
||||
return file->update_status;
|
||||
}
|
||||
|
||||
/* Set FILE's `updated' flag and re-check its mtime and the mtime's of all
|
||||
files listed in its `also_make' member. Under -t, this function also
|
||||
touches FILE.
|
||||
/* re-check FILE's mtime and the mtime's of all files listed in its
|
||||
`also_make' member. Under -t, this function also touches FILE.
|
||||
|
||||
On return, FILE->update_status will no longer be -1 if it was. */
|
||||
|
||||
@@ -688,7 +696,6 @@ notice_finished_file (file)
|
||||
int ran = file->command_state == cs_running;
|
||||
|
||||
file->command_state = cs_finished;
|
||||
file->updated = 1;
|
||||
|
||||
if (touch_flag
|
||||
/* The update status will be:
|
||||
@@ -715,7 +722,7 @@ notice_finished_file (file)
|
||||
file->update_status = 0;
|
||||
else
|
||||
/* Should set file's modification date and do nothing else. */
|
||||
file->update_status = touch_file (file);
|
||||
file->update_status = touch_file (file) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,7 +758,7 @@ notice_finished_file (file)
|
||||
f->last_mtime = file->last_mtime;
|
||||
}
|
||||
|
||||
if (ran && file->update_status != -1)
|
||||
if (ran)
|
||||
/* We actually tried to update FILE, which has
|
||||
updated its also_make's as well (if it worked).
|
||||
If it didn't work, it wouldn't work again for them.
|
||||
@@ -759,7 +766,6 @@ notice_finished_file (file)
|
||||
for (d = file->also_make; d != 0; d = d->next)
|
||||
{
|
||||
d->file->command_state = cs_finished;
|
||||
d->file->updated = 1;
|
||||
d->file->update_status = file->update_status;
|
||||
|
||||
if (ran && !d->file->phony)
|
||||
@@ -769,10 +775,6 @@ notice_finished_file (file)
|
||||
never be done because the target is already updated. */
|
||||
(void) f_mtime (d->file, 0);
|
||||
}
|
||||
else if (file->update_status == -1)
|
||||
/* Nothing was done for FILE, but it needed nothing done.
|
||||
So mark it now as "succeeded". */
|
||||
file->update_status = 0;
|
||||
}
|
||||
|
||||
/* Check whether another file (whose mtime is THIS_MTIME)
|
||||
@@ -780,9 +782,13 @@ notice_finished_file (file)
|
||||
If it does, store 1 in *MUST_MAKE_PTR.
|
||||
In the process, update any non-intermediate files
|
||||
that FILE depends on (including FILE itself).
|
||||
Return nonzero if any updating failed. */
|
||||
|
||||
static int
|
||||
Return ts_done if FILE has completed successfully, ts_incomplete if
|
||||
FILE or any of its precursors are incomplete, or ts_failed if FILE
|
||||
or any of its precursors failed.
|
||||
*/
|
||||
|
||||
static target_state_t
|
||||
check_dep (file, depth, this_mtime, must_make_ptr)
|
||||
struct file *file;
|
||||
unsigned int depth;
|
||||
@@ -790,10 +796,10 @@ check_dep (file, depth, this_mtime, must_make_ptr)
|
||||
int *must_make_ptr;
|
||||
{
|
||||
register struct dep *d;
|
||||
int dep_status = 0;
|
||||
target_state_t dep_status = ts_done;
|
||||
|
||||
++depth;
|
||||
file->updating = 1;
|
||||
set_updating(file);
|
||||
|
||||
if (!file->intermediate)
|
||||
/* If this is a non-intermediate file, update it and record
|
||||
@@ -818,7 +824,6 @@ check_dep (file, depth, this_mtime, must_make_ptr)
|
||||
DBF (DB_IMPLICIT, _("Found an implicit rule for `%s'.\n"));
|
||||
else
|
||||
DBF (DB_IMPLICIT, _("No implicit rule found for `%s'.\n"));
|
||||
file->tried_implicit = 1;
|
||||
}
|
||||
if (file->cmds == 0 && !file->is_target
|
||||
&& default_file != 0 && default_file->cmds != 0)
|
||||
@@ -845,7 +850,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
|
||||
d = file->deps;
|
||||
while (d != 0)
|
||||
{
|
||||
if (d->file->updating)
|
||||
if (tst_updating(d->file))
|
||||
{
|
||||
error (NILF, _("Circular %s <- %s dependency dropped."),
|
||||
file->name, d->file->name);
|
||||
@@ -868,7 +873,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
|
||||
dep_status |= check_dep (d->file, depth, this_mtime,
|
||||
must_make_ptr);
|
||||
check_renamed (d->file);
|
||||
if (dep_status != 0 && !keep_going_flag)
|
||||
if (dep_status == ts_failed && !keep_going_flag)
|
||||
break;
|
||||
|
||||
if (d->file->command_state == cs_running
|
||||
@@ -884,7 +889,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
file->updating = 0;
|
||||
clr_updating(file);
|
||||
return dep_status;
|
||||
}
|
||||
|
||||
@@ -985,7 +990,7 @@ remake_file (file)
|
||||
error (NILF, msg_parent, "*** ",
|
||||
file->name, file->parent->name, ".");
|
||||
}
|
||||
file->update_status = 2;
|
||||
file->update_status = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1138,7 +1143,7 @@ f_mtime (file, search)
|
||||
static FILE_TIMESTAMP now = 0;
|
||||
if (!clock_skew_detected
|
||||
&& mtime != (FILE_TIMESTAMP)-1 && mtime > now
|
||||
&& !file->updated)
|
||||
&& !(file->command_state == cs_finished))
|
||||
{
|
||||
/* This file's time appears to be in the future.
|
||||
Update our concept of the present, and compare again. */
|
||||
|
||||
Reference in New Issue
Block a user