aboutsummaryrefslogtreecommitdiff
path: root/make.h
diff options
context:
space:
mode:
Diffstat (limited to 'make.h')
-rw-r--r--make.h274
1 files changed, 159 insertions, 115 deletions
diff --git a/make.h b/make.h
index 0c10706d3632..2803ceac3f95 100644
--- a/make.h
+++ b/make.h
@@ -1,4 +1,4 @@
-/* $NetBSD: make.h,v 1.179 2020/11/01 17:47:26 rillig Exp $ */
+/* $NetBSD: make.h,v 1.210 2020/11/16 21:53:10 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -135,6 +135,8 @@
#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */
#endif
+#define MAKE_INLINE static inline MAKE_ATTR_UNUSED
+
/*
* A boolean type is defined as an integer, not an enum, for historic reasons.
* The only allowed values are the constants TRUE and FALSE (1 and 0).
@@ -187,7 +189,7 @@ typedef int Boolean;
#define POSIX_SIGNALS
#endif
-typedef enum {
+typedef enum GNodeMade {
UNMADE, /* Not examined yet */
DEFERRED, /* Examined once (building child) */
REQUESTED, /* on toBeMade list */
@@ -207,6 +209,8 @@ typedef enum {
*
* Some of the OP_ constants can be combined, others cannot. */
typedef enum GNodeType {
+ OP_NONE = 0,
+
/* The dependency operator ':' is the most common one. The commands of
* this node are executed if any child is out-of-date. */
OP_DEPENDS = 1 << 0,
@@ -215,7 +219,8 @@ typedef enum GNodeType {
OP_FORCE = 1 << 1,
/* The dependency operator '::' behaves like ':', except that it allows
* multiple dependency groups to be defined. Each of these groups is
- * executed on its own, independently from the others. */
+ * executed on its own, independently from the others. Each individual
+ * dependency group is called a cohort. */
OP_DOUBLEDEP = 1 << 2,
/* Matches the dependency operators ':', '!' and '::'. */
@@ -246,7 +251,7 @@ typedef enum GNodeType {
/* Like .USE, only prepend commands */
OP_USEBEFORE = 1 << 13,
/* The node is invisible to its parents. I.e. it doesn't show up in the
- * parents' local variables. */
+ * parents' local variables (.IMPSRC, .ALLSRC). */
OP_INVISIBLE = 1 << 14,
/* The node is exempt from normal 'main target' processing in parse.c */
OP_NOTMAIN = 1 << 15,
@@ -254,7 +259,10 @@ typedef enum GNodeType {
OP_PHONY = 1 << 16,
/* Don't search for file in the path */
OP_NOPATH = 1 << 17,
- /* .WAIT phony node */
+ /* In a dependency line "target: source1 .WAIT source2", source1 is made
+ * first, including its children. Once that is finished, source2 is made,
+ * including its children. The .WAIT keyword may appear more than once in
+ * a single dependency declaration. */
OP_WAIT = 1 << 18,
/* .NOMETA do not create a .meta file */
OP_NOMETA = 1 << 19,
@@ -267,7 +275,7 @@ typedef enum GNodeType {
/* Attributes applied by PMake */
- /* The node is a transformation rule */
+ /* The node is a transformation rule, such as ".c.o". */
OP_TRANSFORM = 1 << 31,
/* Target is a member of an archive */
/* XXX: How does this differ from OP_ARCHV? */
@@ -337,7 +345,7 @@ typedef struct GNode {
int unmade; /* The number of unmade children */
/* The modification time; 0 means the node does not have a corresponding
- * file; see Make_OODate. */
+ * file; see GNode_IsOODate. */
time_t mtime;
struct GNode *youngestChild;
@@ -346,9 +354,6 @@ typedef struct GNode {
* file.c has the node for file.o in this list. */
GNodeList *implicitParents;
- /* Other nodes of the same name, for the '::' operator. */
- GNodeList *cohorts;
-
/* The nodes that depend on this one, or in other words, the nodes for
* which this is a source. */
GNodeList *parents;
@@ -364,6 +369,8 @@ typedef struct GNode {
* in the normal sense. */
GNodeList *order_succ;
+ /* Other nodes of the same name, for the '::' dependency operator. */
+ GNodeList *cohorts;
/* The "#n" suffix for this cohort, or "" for other nodes */
char cohort_num[8];
/* The number of unmade instances on the cohorts list */
@@ -389,20 +396,20 @@ typedef struct GNode {
* but the Suff module) */
struct Suff *suffix;
- /* filename where the GNode got defined */
+ /* Filename where the GNode got defined */
+ /* XXX: What is the lifetime of this string? */
const char *fname;
- /* line number where the GNode got defined */
+ /* Line number where the GNode got defined */
int lineno;
} GNode;
-/*
- * Error levels for parsing. PARSE_FATAL means the process cannot continue
- * once the top-level makefile has been parsed. PARSE_WARNING and PARSE_INFO
- * mean it can.
- */
+/* Error levels for diagnostics during parsing. */
typedef enum ParseErrorLevel {
+ /* Exit when the current top-level makefile has been parsed completely. */
PARSE_FATAL = 1,
+ /* Print "warning"; may be upgraded to fatal by the -w option. */
PARSE_WARNING,
+ /* Informational, mainly used during development of makefiles. */
PARSE_INFO
} ParseErrorLevel;
@@ -415,9 +422,7 @@ typedef enum CondEvalResult {
COND_INVALID /* Not a conditional statement */
} CondEvalResult;
-/*
- * Definitions for the "local" variables. Used only for clarity.
- */
+/* Names of the variables that are "local" to a specific target. */
#define TARGET "@" /* Target of dependency */
#define OODATE "?" /* All out-of-date sources */
#define ALLSRC ">" /* All sources */
@@ -426,58 +431,77 @@ typedef enum CondEvalResult {
#define ARCHIVE "!" /* Archive in "archive(member)" syntax */
#define MEMBER "%" /* Member in "archive(member)" syntax */
-#define FTARGET "@F" /* file part of TARGET */
-#define DTARGET "@D" /* directory part of TARGET */
-#define FIMPSRC "<F" /* file part of IMPSRC */
-#define DIMPSRC "<D" /* directory part of IMPSRC */
-#define FPREFIX "*F" /* file part of PREFIX */
-#define DPREFIX "*D" /* directory part of PREFIX */
-
/*
* Global Variables
*/
-extern SearchPath *dirSearchPath;
- /* The list of directories to search when
- * looking for targets */
-extern Boolean allPrecious; /* True if every target is precious */
-extern Boolean deleteOnError; /* True if failed targets should be deleted */
-extern Boolean doing_depend; /* TRUE if processing .depend */
-
-extern GNode *DEFAULT; /* .DEFAULT rule */
-
-extern GNode *VAR_INTERNAL; /* Variables defined internally by make
- * which should not override those set by
- * makefiles.
- */
-extern GNode *VAR_GLOBAL; /* Variables defined in a global context, e.g
- * in the Makefile itself */
-extern GNode *VAR_CMDLINE; /* Variables defined on the command line */
-extern char var_Error[]; /* Value returned by Var_Parse when an error
- * is encountered. It actually points to
- * an empty string, so naive callers needn't
- * worry about it. */
-
-extern time_t now; /* The time at the start of this whole
- * process */
-
-extern Boolean oldVars; /* Do old-style variable substitution */
-extern SearchPath *sysIncPath; /* The system include path. */
-extern SearchPath *defSysIncPath; /* The default system include path. */
+/* True if every target is precious */
+extern Boolean allPrecious;
+/* True if failed targets should be deleted */
+extern Boolean deleteOnError;
+/* TRUE while processing .depend */
+extern Boolean doing_depend;
+/* .DEFAULT rule */
+extern GNode *defaultNode;
+
+/* Variables defined internally by make which should not override those set
+ * by makefiles. */
+extern GNode *VAR_INTERNAL;
+/* Variables defined in a global context, e.g in the Makefile itself. */
+extern GNode *VAR_GLOBAL;
+/* Variables defined on the command line. */
+extern GNode *VAR_CMDLINE;
+
+/* Value returned by Var_Parse when an error is encountered. It actually
+ * points to an empty string, so naive callers needn't worry about it. */
+extern char var_Error[];
+
+/* The time at the start of this whole process */
+extern time_t now;
-extern char curdir[]; /* Startup directory */
-extern char *progname; /* The program name */
-extern char *makeDependfile; /* .depend */
-extern char **savedEnv; /* if we replaced environ this will be non-NULL */
+/*
+ * If FALSE (the default behavior), undefined subexpressions in a variable
+ * expression are discarded. If TRUE (only during variable assignments using
+ * the ':=' assignment operator, no matter how deeply nested), they are
+ * preserved and possibly expanded later when the variable from the
+ * subexpression has been defined.
+ *
+ * Example for a ':=' assignment:
+ * CFLAGS = $(.INCLUDES)
+ * CFLAGS := -I.. $(CFLAGS)
+ * # If .INCLUDES (an undocumented special variable, by the way) is
+ * # still undefined, the updated CFLAGS becomes "-I.. $(.INCLUDES)".
+ */
+extern Boolean preserveUndefined;
-extern int makelevel;
+/* The list of directories to search when looking for targets (set by the
+ * special target .PATH). */
+extern SearchPath *dirSearchPath;
+/* Used for .include "...". */
+extern SearchPath *parseIncPath;
+/* Used for .include <...>, for the built-in sys.mk and makefiles from the
+ * command line arguments. */
+extern SearchPath *sysIncPath;
+/* The default for sysIncPath. */
+extern SearchPath *defSysIncPath;
+
+/* Startup directory */
+extern char curdir[];
+/* The basename of the program name, suffixed with [n] for sub-makes. */
+extern char *progname;
+/* Name of the .depend makefile */
+extern char *makeDependfile;
+/* If we replaced environ, this will be non-NULL. */
+extern char **savedEnv;
+
+extern int makelevel;
/*
* We cannot vfork() in a child of vfork().
* Most systems do not enforce this but some do.
*/
#define vFork() ((getpid() == myPid) ? vfork() : fork())
-extern pid_t myPid;
+extern pid_t myPid;
#define MAKEFLAGS ".MAKEFLAGS"
#define MAKEOVERRIDES ".MAKEOVERRIDES"
@@ -485,7 +509,7 @@ extern pid_t myPid;
#define MAKE_EXPORTED ".MAKE.EXPORTED" /* variables we export */
#define MAKE_MAKEFILES ".MAKE.MAKEFILES" /* all makefiles already loaded */
#define MAKE_LEVEL ".MAKE.LEVEL" /* recursion level */
-#define MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE"
+#define MAKE_MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE"
#define MAKE_DEPENDFILE ".MAKE.DEPENDFILE" /* .depend */
#define MAKE_MODE ".MAKE.MODE"
#ifndef MAKE_LEVEL_ENV
@@ -493,29 +517,28 @@ extern pid_t myPid;
#endif
typedef enum DebugFlags {
+ DEBUG_NONE = 0,
DEBUG_ARCH = 1 << 0,
DEBUG_COND = 1 << 1,
- DEBUG_DIR = 1 << 2,
- DEBUG_GRAPH1 = 1 << 3,
- DEBUG_GRAPH2 = 1 << 4,
- DEBUG_JOB = 1 << 5,
- DEBUG_MAKE = 1 << 6,
- DEBUG_SUFF = 1 << 7,
- DEBUG_TARG = 1 << 8,
- DEBUG_VAR = 1 << 9,
- DEBUG_FOR = 1 << 10,
- DEBUG_SHELL = 1 << 11,
- DEBUG_ERROR = 1 << 12,
- DEBUG_LOUD = 1 << 13,
- DEBUG_META = 1 << 14,
- DEBUG_HASH = 1 << 15,
-
- DEBUG_GRAPH3 = 1 << 16,
- DEBUG_SCRIPT = 1 << 17,
- DEBUG_PARSE = 1 << 18,
- DEBUG_CWD = 1 << 19,
-
- DEBUG_LINT = 1 << 20
+ DEBUG_CWD = 1 << 2,
+ DEBUG_DIR = 1 << 3,
+ DEBUG_ERROR = 1 << 4,
+ DEBUG_FOR = 1 << 5,
+ DEBUG_GRAPH1 = 1 << 6,
+ DEBUG_GRAPH2 = 1 << 7,
+ DEBUG_GRAPH3 = 1 << 8,
+ DEBUG_HASH = 1 << 9,
+ DEBUG_JOB = 1 << 10,
+ DEBUG_LOUD = 1 << 11,
+ DEBUG_MAKE = 1 << 12,
+ DEBUG_META = 1 << 13,
+ DEBUG_PARSE = 1 << 14,
+ DEBUG_SCRIPT = 1 << 15,
+ DEBUG_SHELL = 1 << 16,
+ DEBUG_SUFF = 1 << 17,
+ DEBUG_TARG = 1 << 18,
+ DEBUG_VAR = 1 << 19,
+ DEBUG_ALL = (1 << 20) - 1
} DebugFlags;
#define CONCAT(a,b) a##b
@@ -549,8 +572,9 @@ void debug_printf(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
else debug_printf(fmt, arg1, arg2, arg3, arg4, arg5)
typedef enum PrintVarsMode {
- COMPAT_VARS = 1,
- EXPAND_VARS
+ PVM_NONE,
+ PVM_UNEXPANDED,
+ PVM_EXPANDED
} PrintVarsMode;
/* Command line options */
@@ -565,6 +589,12 @@ typedef struct CmdOpts {
/* -df: debug output is written here - default stderr */
FILE *debug_file;
+ /* -dL: lint mode
+ *
+ * Runs make in strict mode, with additional checks and better error
+ * handling. */
+ Boolean lint;
+
/* -dV: for the -V option, print unexpanded variable values */
Boolean debugVflag;
@@ -630,49 +660,49 @@ extern CmdOpts opts;
#include "nonints.h"
-void Make_TimeStamp(GNode *, GNode *);
-Boolean Make_OODate(GNode *);
+void GNode_UpdateYoungestChild(GNode *, GNode *);
+Boolean GNode_IsOODate(GNode *);
void Make_ExpandUse(GNodeList *);
time_t Make_Recheck(GNode *);
void Make_HandleUse(GNode *, GNode *);
void Make_Update(GNode *);
void Make_DoAllVar(GNode *);
Boolean Make_Run(GNodeList *);
-int dieQuietly(GNode *, int);
+Boolean shouldDieQuietly(GNode *, int);
void PrintOnError(GNode *, const char *);
void Main_ExportMAKEFLAGS(Boolean);
-Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
+Boolean Main_SetObjdir(Boolean, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
int mkTempFile(const char *, char **);
-int str2Lst_Append(StringList *, char *, const char *);
+int str2Lst_Append(StringList *, char *);
void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *);
Boolean GNode_ShouldExecute(GNode *gn);
/* See if the node was seen on the left-hand side of a dependency operator. */
-static MAKE_ATTR_UNUSED Boolean
+MAKE_INLINE Boolean
GNode_IsTarget(const GNode *gn)
{
return (gn->type & OP_OPMASK) != 0;
}
-static MAKE_ATTR_UNUSED const char *
+MAKE_INLINE const char *
GNode_Path(const GNode *gn)
{
return gn->path != NULL ? gn->path : gn->name;
}
-static MAKE_ATTR_UNUSED const char *
+MAKE_INLINE const char *
GNode_VarTarget(GNode *gn) { return Var_ValueDirect(TARGET, gn); }
-static MAKE_ATTR_UNUSED const char *
+MAKE_INLINE const char *
GNode_VarOodate(GNode *gn) { return Var_ValueDirect(OODATE, gn); }
-static MAKE_ATTR_UNUSED const char *
+MAKE_INLINE const char *
GNode_VarAllsrc(GNode *gn) { return Var_ValueDirect(ALLSRC, gn); }
-static MAKE_ATTR_UNUSED const char *
+MAKE_INLINE const char *
GNode_VarImpsrc(GNode *gn) { return Var_ValueDirect(IMPSRC, gn); }
-static MAKE_ATTR_UNUSED const char *
+MAKE_INLINE const char *
GNode_VarPrefix(GNode *gn) { return Var_ValueDirect(PREFIX, gn); }
-static MAKE_ATTR_UNUSED const char *
+MAKE_INLINE const char *
GNode_VarArchive(GNode *gn) { return Var_ValueDirect(ARCHIVE, gn); }
-static MAKE_ATTR_UNUSED const char *
+MAKE_INLINE const char *
GNode_VarMember(GNode *gn) { return Var_ValueDirect(MEMBER, gn); }
#ifdef __GNUC__
@@ -703,35 +733,49 @@ GNode_VarMember(GNode *gn) { return Var_ValueDirect(MEMBER, gn); }
#define KILLPG(pid, sig) killpg((pid), (sig))
#endif
-static inline MAKE_ATTR_UNUSED Boolean ch_isalnum(char ch)
-{ return isalnum((unsigned char)ch) != 0; }
-static inline MAKE_ATTR_UNUSED Boolean ch_isalpha(char ch)
-{ return isalpha((unsigned char)ch) != 0; }
-static inline MAKE_ATTR_UNUSED Boolean ch_isdigit(char ch)
-{ return isdigit((unsigned char)ch) != 0; }
-static inline MAKE_ATTR_UNUSED Boolean ch_isspace(char ch)
-{ return isspace((unsigned char)ch) != 0; }
-static inline MAKE_ATTR_UNUSED Boolean ch_isupper(char ch)
-{ return isupper((unsigned char)ch) != 0; }
-static inline MAKE_ATTR_UNUSED char ch_tolower(char ch)
-{ return (char)tolower((unsigned char)ch); }
-static inline MAKE_ATTR_UNUSED char ch_toupper(char ch)
-{ return (char)toupper((unsigned char)ch); }
-
-static inline MAKE_ATTR_UNUSED void
+MAKE_INLINE Boolean
+ch_isalnum(char ch) { return isalnum((unsigned char)ch) != 0; }
+MAKE_INLINE Boolean
+ch_isalpha(char ch) { return isalpha((unsigned char)ch) != 0; }
+MAKE_INLINE Boolean
+ch_isdigit(char ch) { return isdigit((unsigned char)ch) != 0; }
+MAKE_INLINE Boolean
+ch_isspace(char ch) { return isspace((unsigned char)ch) != 0; }
+MAKE_INLINE Boolean
+ch_isupper(char ch) { return isupper((unsigned char)ch) != 0; }
+MAKE_INLINE char
+ch_tolower(char ch) { return (char)tolower((unsigned char)ch); }
+MAKE_INLINE char
+ch_toupper(char ch) { return (char)toupper((unsigned char)ch); }
+
+MAKE_INLINE void
cpp_skip_whitespace(const char **pp)
{
while (ch_isspace(**pp))
(*pp)++;
}
-static inline MAKE_ATTR_UNUSED void
+MAKE_INLINE void
+cpp_skip_hspace(const char **pp)
+{
+ while (**pp == ' ' || **pp == '\t')
+ (*pp)++;
+}
+
+MAKE_INLINE void
pp_skip_whitespace(char **pp)
{
while (ch_isspace(**pp))
(*pp)++;
}
+MAKE_INLINE void
+pp_skip_hspace(char **pp)
+{
+ while (**pp == ' ' || **pp == '\t')
+ (*pp)++;
+}
+
#ifdef MAKE_NATIVE
# include <sys/cdefs.h>
# ifndef lint