/* $NetBSD: make.h,v 1.361 2025/07/06 07:11:31 rillig Exp $ */12/*3* Copyright (c) 1988, 1989, 1990, 19934* The Regents of the University of California. All rights reserved.5*6* This code is derived from software contributed to Berkeley by7* Adam de Boor.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17* 3. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*33* from: @(#)make.h 8.3 (Berkeley) 6/13/9534*/3536/*37* Copyright (c) 1989 by Berkeley Softworks38* All rights reserved.39*40* This code is derived from software contributed to Berkeley by41* Adam de Boor.42*43* Redistribution and use in source and binary forms, with or without44* modification, are permitted provided that the following conditions45* are met:46* 1. Redistributions of source code must retain the above copyright47* notice, this list of conditions and the following disclaimer.48* 2. Redistributions in binary form must reproduce the above copyright49* notice, this list of conditions and the following disclaimer in the50* documentation and/or other materials provided with the distribution.51* 3. All advertising materials mentioning features or use of this software52* must display the following acknowledgement:53* This product includes software developed by the University of54* California, Berkeley and its contributors.55* 4. Neither the name of the University nor the names of its contributors56* may be used to endorse or promote products derived from this software57* without specific prior written permission.58*59* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND60* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE61* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE62* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE63* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL64* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS65* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)66* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT67* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY68* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF69* SUCH DAMAGE.70*71* from: @(#)make.h 8.3 (Berkeley) 6/13/9572*/7374/*75* make.h --76* The global definitions for make77*/7879#ifndef MAKE_MAKE_H80#define MAKE_MAKE_H8182#ifdef HAVE_CONFIG_H83# include "config.h"84#endif8586#include <sys/types.h>87#include <sys/param.h>88#include <sys/stat.h>8990#include <assert.h>91#include <ctype.h>92#include <fcntl.h>93#include <stdarg.h>94#include <stdio.h>95#include <stdlib.h>96#ifdef HAVE_STRING_H97#include <string.h>98#else99#include <strings.h>100#endif101#include <unistd.h>102#include <sys/cdefs.h>103104#ifndef FD_CLOEXEC105#define FD_CLOEXEC 1106#endif107108#if defined(__GNUC__)109#define MAKE_GNUC_PREREQ(x, y) \110((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \111(__GNUC__ > (x)))112#else113#define MAKE_GNUC_PREREQ(x, y) 0114#endif115116#if MAKE_GNUC_PREREQ(2, 7) || lint117#define MAKE_ATTR_UNUSED __attribute__((__unused__))118#else119#define MAKE_ATTR_UNUSED /* delete */120#endif121122#if MAKE_GNUC_PREREQ(2, 5)123#define MAKE_ATTR_DEAD __attribute__((__noreturn__))124#elif defined(__GNUC__)125#define MAKE_ATTR_DEAD __volatile126#else127#define MAKE_ATTR_DEAD /* delete */128#endif129130#if MAKE_GNUC_PREREQ(2, 7)131#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) \132__attribute__((__format__ (__printf__, fmtarg, firstvararg)))133#else134#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */135#endif136137#if MAKE_GNUC_PREREQ(4, 0)138#define MAKE_ATTR_USE __attribute__((__warn_unused_result__))139#else140#define MAKE_ATTR_USE /* delete */141#endif142143#if MAKE_GNUC_PREREQ(8, 0)144#define MAKE_ATTR_NOINLINE __attribute__((__noinline__))145#else146#define MAKE_ATTR_NOINLINE /* delete */147#endif148149#if __STDC_VERSION__ >= 199901L || defined(lint)150#define MAKE_INLINE static inline MAKE_ATTR_UNUSED151#else152#define MAKE_INLINE static MAKE_ATTR_UNUSED153#endif154155/* MAKE_STATIC marks a function that may or may not be inlined. */156#if defined(lint)157/* As of 2021-07-31, NetBSD lint ignores __attribute__((unused)). */158#define MAKE_STATIC MAKE_INLINE159#else160#define MAKE_STATIC static MAKE_ATTR_UNUSED161#endif162163#if __STDC_VERSION__ >= 199901L || defined(lint) || defined(USE_C99_BOOLEAN)164#include <stdbool.h>165#elif defined(__bool_true_false_are_defined)166/*167* All files of make must be compiled with the same definition of bool.168* Since one of the files includes <stdbool.h>, that means the header is169* available on this platform. Recompile everything with -DUSE_C99_BOOLEAN.170*/171#error "<stdbool.h> is included in pre-C99 mode"172#elif defined(bool) || defined(true) || defined(false)173/*174* In pre-C99 mode, make does not expect that bool is already defined.175* You need to ensure that all translation units use the same definition for176* bool.177*/178#error "bool/true/false is defined in pre-C99 mode"179#else180typedef unsigned char bool;181#define true 1182#define false 0183#endif184185/*186* In code coverage mode with gcc>=12, calling vfork/exec does not mark any187* further code from the parent process as covered. gcc-10.5.0 is fine, as188* are fork/exec calls, as well as posix_spawn.189*/190#ifndef FORK_FUNCTION191#define FORK_FUNCTION vfork192#endif193194#include "lst.h"195#include "make_malloc.h"196#include "str.h"197#include "hash.h"198#include "make-conf.h"199#include "buf.h"200201/*202* some vendors don't have this --sjg203*/204#if defined(S_IFDIR) && !defined(S_ISDIR)205# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)206#endif207208#if defined(sun) && (defined(__svr4__) || defined(__SVR4))209# define POSIX_SIGNALS210#endif211212/*213* IRIX defines OP_NONE in sys/fcntl.h214*/215#if defined(OP_NONE)216# undef OP_NONE217#endif218219/*220* The typical flow of states is:221*222* The direct successful path:223* UNMADE -> BEINGMADE -> MADE.224*225* The direct error path:226* UNMADE -> BEINGMADE -> ERROR.227*228* The successful path when dependencies need to be made first:229* UNMADE -> DEFERRED -> REQUESTED -> BEINGMADE -> MADE.230*231* A node that has dependencies, and one of the dependencies cannot be made:232* UNMADE -> DEFERRED -> ABORTED.233*234* A node that turns out to be up-to-date:235* UNMADE -> BEINGMADE -> UPTODATE.236*/237typedef enum GNodeMade {238/* Not examined yet. */239UNMADE,240/*241* The node has been examined but is not yet ready since its242* dependencies have to be made first.243*/244DEFERRED,245246/* The node is on the toBeMade list. */247REQUESTED,248249/*250* The node is already being made. Trying to build a node in this251* state indicates a cycle in the graph.252*/253BEINGMADE,254255/* Was out-of-date and has been made. */256MADE,257/* Was already up-to-date, does not need to be made. */258UPTODATE,259/*260* An error occurred while it was being made. Used only in compat261* mode.262*/263ERROR,264/*265* The target was aborted due to an error making a dependency. Used266* only in compat mode.267*/268ABORTED269} GNodeMade;270271/*272* The OP_ constants are used when parsing a dependency line as a way of273* communicating to other parts of the program the way in which a target274* should be made.275*276* Some of the OP_ constants can be combined, others cannot.277*278* See the tests depsrc-*.mk and deptgt-*.mk.279*/280typedef enum GNodeType {281OP_NONE = 0,282283/*284* The dependency operator ':' is the most common one. The commands285* of this node are executed if any child is out-of-date.286*/287OP_DEPENDS = 1 << 0,288/*289* The dependency operator '!' always executes its commands, even if290* its children are up-to-date.291*/292OP_FORCE = 1 << 1,293/*294* The dependency operator '::' behaves like ':', except that it295* allows multiple dependency groups to be defined. Each of these296* groups is executed on its own, independently from the others. Each297* individual dependency group is called a cohort.298*/299OP_DOUBLEDEP = 1 << 2,300301/* Matches the dependency operators ':', '!' and '::'. */302OP_OPMASK = OP_DEPENDS | OP_FORCE | OP_DOUBLEDEP,303304/* Don't care if the target doesn't exist and can't be created. */305OP_OPTIONAL = 1 << 3,306/* Use associated commands for parents. */307OP_USE = 1 << 4,308/*309* Target is never out of date, but always execute commands anyway.310* Its time doesn't matter, so it has none...sort of.311*/312OP_EXEC = 1 << 5,313/*314* Ignore non-zero exit status from shell commands when creating the315* node.316*/317OP_IGNORE = 1 << 6,318/* Don't remove the target when interrupted. */319OP_PRECIOUS = 1 << 7,320/* Don't echo commands when executed. */321OP_SILENT = 1 << 8,322/*323* Target is a recursive make so its commands should always be324* executed when it is out of date, regardless of the state of the -n325* or -t flags.326*/327OP_MAKE = 1 << 9,328/*329* Target is out-of-date only if any of its children was out-of-date.330*/331OP_JOIN = 1 << 10,332/* Assume the children of the node have been already made. */333OP_MADE = 1 << 11,334/* Special .BEGIN, .END or .INTERRUPT. */335OP_SPECIAL = 1 << 12,336/* Like .USE, only prepend commands. */337OP_USEBEFORE = 1 << 13,338/*339* The node is invisible to its parents. I.e. it doesn't show up in340* the parents' local variables (.IMPSRC, .ALLSRC).341*/342OP_INVISIBLE = 1 << 14,343/*344* The node does not become the main target, even if it is the first345* target in the first makefile.346*/347OP_NOTMAIN = 1 << 15,348/* Not a file target; run always. */349OP_PHONY = 1 << 16,350/* Don't search for the file in the path. */351OP_NOPATH = 1 << 17,352/*353* In a dependency line "target: source1 .WAIT source2", source1 is354* made first, including its children. Once that is finished,355* source2 is made, including its children. The .WAIT keyword may356* appear more than once in a single dependency declaration.357*/358OP_WAIT = 1 << 18,359/* .NOMETA do not create a .meta file */360OP_NOMETA = 1 << 19,361/* .META we _do_ want a .meta file */362OP_META = 1 << 20,363/* Do not compare commands in .meta file */364OP_NOMETA_CMP = 1 << 21,365/* Possibly a submake node */366OP_SUBMAKE = 1 << 22,367368/* Attributes applied by PMake */369370/* The node is a transformation rule, such as ".c.o". */371OP_TRANSFORM = 1 << 30,372/* Target is a member of an archive */373/* XXX: How does this differ from OP_ARCHV? */374OP_MEMBER = 1 << 29,375/*376* The node is a library, its name has the form "-l<libname>".377*/378OP_LIB = 1 << 28,379/*380* The node is an archive member, its name has the form381* "archive(member)".382*/383/* XXX: How does this differ from OP_MEMBER? */384OP_ARCHV = 1 << 27,385/*386* Target has all the commands it should. Used when parsing to catch387* multiple command groups for a target. Only applies to the388* dependency operators ':' and '!', but not to '::'.389*/390OP_HAS_COMMANDS = 1 << 26,391/*392* The special command "..." has been seen. All further commands from393* this node will be saved on the .END node instead, to be executed394* at the very end.395*/396OP_SAVE_CMDS = 1 << 25,397/*398* Already processed by Suff_FindDeps, to find dependencies from399* suffix transformation rules.400*/401OP_DEPS_FOUND = 1 << 24,402/* Node found while expanding .ALLSRC */403OP_MARK = 1 << 23404} GNodeType;405406typedef struct GNodeFlags {407/* this target needs to be (re)made */408bool remake:1;409/* children of this target were made */410bool childMade:1;411/* children don't exist, and we pretend made */412bool force:1;413/* Set by Make_ProcessWait() */414bool doneWait:1;415/* Build requested by .ORDER processing */416bool doneOrder:1;417/* Node created from .depend */418bool fromDepend:1;419/* We do it once only */420bool doneAllsrc:1;421/* Used by MakePrintStatus */422bool cycle:1;423/* Used by MakePrintStatus */424bool doneCycle:1;425} GNodeFlags;426427typedef struct List StringList;428typedef struct ListNode StringListNode;429430typedef struct List GNodeList;431typedef struct ListNode GNodeListNode;432433typedef struct SearchPath {434List /* of CachedDir */ dirs;435} SearchPath;436437/*438* A graph node represents a target that can possibly be made, including its439* relation to other targets.440*/441typedef struct GNode {442/* The target's name, such as "clean" or "make.c" */443char *name;444/* The unexpanded name of a .USE node */445char *uname;446/*447* The full pathname of the file belonging to the target.448*449* XXX: What about .PHONY targets? These don't have an associated450* path.451*/452char *path;453454/*455* The type of operator used to define the sources (see the OP flags456* below).457*458* XXX: This looks like a wild mixture of type and flags.459*/460GNodeType type;461GNodeFlags flags;462463/* The state of processing on this node */464GNodeMade made;465/* The number of unmade children */466int unmade;467468/*469* The modification time; 0 means the node does not have a470* corresponding file; see GNode_IsOODate.471*/472time_t mtime;473struct GNode *youngestChild;474475/*476* The GNodes for which this node is an implied source. May be empty.477* For example, when there is an inference rule for .c.o, the node478* for file.c has the node for file.o in this list.479*/480GNodeList implicitParents;481482/*483* The nodes that depend on this one, or in other words, the nodes484* for which this is a source.485*/486GNodeList parents;487/* The nodes on which this one depends. */488GNodeList children;489490/*491* .ORDER nodes we need made. The nodes that must be made (if they're492* made) before this node can be made, but that do not enter into the493* datedness of this node.494*/495GNodeList order_pred;496/*497* .ORDER nodes who need us. The nodes that must be made (if they're498* made at all) after this node is made, but that do not depend on499* this node, in the normal sense.500*/501GNodeList order_succ;502503/*504* Other nodes of the same name, for targets that were defined using505* the '::' dependency operator (OP_DOUBLEDEP).506*/507GNodeList cohorts;508/* The "#n" suffix for this cohort, or "" for other nodes */509char cohort_num[8];510/* The number of unmade instances on the cohorts list */511int unmade_cohorts;512/*513* Pointer to the first instance of a '::' node; only set when on a514* cohorts list515*/516struct GNode *centurion;517518/* Last time (sequence number) we tried to make this node */519unsigned checked_seqno;520521/*522* The "local" variables that are specific to this target and this523* target only, such as $@, $<, $?.524*525* Also used for the global variable scopes SCOPE_GLOBAL,526* SCOPE_CMDLINE, SCOPE_INTERNAL, which contain variables with527* arbitrary names.528*/529HashTable /* of Var pointer */ vars;530531/* The commands to be given to a shell to create this target. */532StringList commands;533534/*535* Suffix for the node (determined by Suff_FindDeps and opaque to536* everyone but the Suff module)537*/538struct Suffix *suffix;539540/* Filename where the GNode got defined, unlimited lifetime */541const char *fname;542/* Line number where the GNode got defined, 1-based */543unsigned lineno;544int exit_status;545} GNode;546547/*548* Keep track of whether to include <posix.mk> when parsing the line549* '.POSIX:'.550*/551extern enum PosixState {552PS_NOT_YET,553PS_MAYBE_NEXT_LINE,554PS_NOW_OR_NEVER,555PS_SET,556PS_TOO_LATE557} posix_state;558559/* Error levels for diagnostics during parsing. */560typedef enum ParseErrorLevel {561/*562* Exit when the current top-level makefile has been parsed563* completely.564*/565PARSE_FATAL = 1,566/* Print "warning"; may be upgraded to fatal by the -w option. */567PARSE_WARNING,568/* Informational, mainly used during development of makefiles. */569PARSE_INFO570} ParseErrorLevel;571572/*573* Values returned by Cond_EvalLine and Cond_EvalCondition.574*/575typedef enum CondResult {576CR_TRUE, /* Parse the next lines */577CR_FALSE, /* Skip the next lines */578CR_ERROR /* Unknown directive or parse error */579} CondResult;580581typedef struct {582enum GuardKind {583GK_VARIABLE,584GK_TARGET585} kind;586char *name;587} Guard;588589/* Names of the variables that are "local" to a specific target. */590#define TARGET "@" /* Target of dependency */591#define OODATE "?" /* All out-of-date sources */592#define ALLSRC ">" /* All sources */593#define IMPSRC "<" /* Source implied by transformation */594#define PREFIX "*" /* Common prefix */595#define ARCHIVE "!" /* Archive in "archive(member)" syntax */596#define MEMBER "%" /* Member in "archive(member)" syntax */597598/*599* Global Variables600*/601602/* True if every target is precious */603extern bool allPrecious;604/* True if failed targets should be deleted */605extern bool deleteOnError;606/* true while processing .depend */607extern bool doing_depend;608/* .DEFAULT rule */609extern GNode *defaultNode;610611/*612* Variables defined internally by make which should not override those set613* by makefiles.614*/615extern GNode *SCOPE_INTERNAL;616/* Variables defined in a global scope, e.g in the makefile itself. */617extern GNode *SCOPE_GLOBAL;618/* Variables defined on the command line. */619extern GNode *SCOPE_CMDLINE;620621/*622* Value returned by Var_Parse when an error is encountered. It points to an623* empty string, so naive callers needn't worry about it.624*/625extern char var_Error[];626627/* The time at the start of this whole process */628extern time_t now;629630/*631* The list of directories to search when looking for targets (set by the632* special target .PATH).633*/634extern SearchPath dirSearchPath;635/* Used for .include "...". */636extern SearchPath *parseIncPath;637/*638* Used for .include <...>, for the built-in sys.mk and for makefiles from639* the command line arguments.640*/641extern SearchPath *sysIncPath;642/* The default for sysIncPath. */643extern SearchPath *defSysIncPath;644645/* Startup directory */646extern char curdir[];647/* The basename of the program name, suffixed with [n] for sub-makes. */648extern const char *progname;649extern int makelevel;650/* Name of the .depend makefile */651extern char *makeDependfile;652/* If we replaced environ, this will be non-NULL. */653extern char **savedEnv;654extern GNode *mainNode;655656extern pid_t myPid;657658#define MAKEFLAGS ".MAKEFLAGS"659#ifndef MAKE_LEVEL_ENV660# define MAKE_LEVEL_ENV "MAKELEVEL"661#endif662663typedef struct DebugFlags {664bool DEBUG_ARCH:1;665bool DEBUG_COND:1;666bool DEBUG_CWD:1;667bool DEBUG_DIR:1;668bool DEBUG_ERROR:1;669bool DEBUG_FOR:1;670bool DEBUG_GRAPH1:1;671bool DEBUG_GRAPH2:1;672bool DEBUG_GRAPH3:1;673bool DEBUG_HASH:1;674bool DEBUG_JOB:1;675bool DEBUG_LOUD:1;676bool DEBUG_MAKE:1;677bool DEBUG_META:1;678bool DEBUG_PARSE:1;679bool DEBUG_SCRIPT:1;680bool DEBUG_SHELL:1;681bool DEBUG_SUFF:1;682bool DEBUG_TARG:1;683bool DEBUG_VAR:1;684} DebugFlags;685686#define CONCAT(a, b) a##b687688#define DEBUG(module) (opts.debug.CONCAT(DEBUG_, module))689690void debug_printf(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);691692#define DEBUG_IMPL(module, args) \693do { \694if (DEBUG(module)) \695debug_printf args; \696} while (false)697698#define DEBUG0(module, fmt) \699DEBUG_IMPL(module, (fmt))700#define DEBUG1(module, fmt, arg1) \701DEBUG_IMPL(module, (fmt, arg1))702#define DEBUG2(module, fmt, arg1, arg2) \703DEBUG_IMPL(module, (fmt, arg1, arg2))704#define DEBUG3(module, fmt, arg1, arg2, arg3) \705DEBUG_IMPL(module, (fmt, arg1, arg2, arg3))706#define DEBUG4(module, fmt, arg1, arg2, arg3, arg4) \707DEBUG_IMPL(module, (fmt, arg1, arg2, arg3, arg4))708#define DEBUG5(module, fmt, arg1, arg2, arg3, arg4, arg5) \709DEBUG_IMPL(module, (fmt, arg1, arg2, arg3, arg4, arg5))710711typedef enum PrintVarsMode {712PVM_NONE,713PVM_UNEXPANDED,714PVM_EXPANDED715} PrintVarsMode;716717/* Command line options */718typedef struct CmdOpts {719/* -B: whether to be compatible to traditional make */720bool compatMake;721722/*723* -d: debug control: There is one flag per module. It is up to the724* module what debug information to print.725*/726DebugFlags debug;727728/* -dF: debug output is written here - default stderr */729FILE *debug_file;730731/*732* -dL: lint mode733*734* Runs make in strict mode, with additional checks and better error735* handling.736*/737bool strict;738739/* -dV: for the -V option, print unexpanded variable values */740bool debugVflag;741742/* -e: check environment variables before global variables */743bool checkEnvFirst;744745/* -f: the makefiles to read */746StringList makefiles;747748/* -i: if true, ignore all errors from shell commands */749bool ignoreErrors;750751/*752* -j: the maximum number of jobs that can run in parallel; this is753* coordinated with the submakes754*/755int maxJobs;756757/*758* -k: if true and an error occurs while making a node, continue759* making nodes that do not depend on the erroneous node760*/761bool keepgoing;762763/* -N: execute no commands from the targets */764bool noRecursiveExecute;765766/* -n: execute almost no commands from the targets */767bool noExecute;768769/*770* -q: if true, do not really make anything, just see if the targets771* are out-of-date772*/773bool query;774775/* -r: raw mode, do not load the builtin rules. */776bool noBuiltins;777778/* -s: don't echo the shell commands before executing them */779bool silent;780781/*782* -t: touch the targets if they are out-of-date, but don't actually783* make them784*/785bool touch;786787/* -[Vv]: print expanded or unexpanded selected variables */788PrintVarsMode printVars;789/* -[Vv]: the variables to print */790StringList variables;791792/* -W: if true, makefile parsing warnings are treated as errors */793bool parseWarnFatal;794795/* -w: print 'Entering' and 'Leaving' for submakes */796bool enterFlag;797798/*799* -X: if true, do not export variables set on the command line to800* the environment.801*/802bool varNoExportEnv;803804/*805* The target names specified on the command line. Used to resolve806* .if make(...) statements.807*/808StringList create;809810/*811* Randomize the order in which the targets from toBeMade are made,812* to catch undeclared dependencies.813*/814bool randomizeTargets;815} CmdOpts;816817extern CmdOpts opts;818extern bool forceJobs;819extern char **environ;820821/* arch.c */822void Arch_Init(void);823#ifdef CLEANUP824void Arch_End(void);825#endif826827bool Arch_ParseArchive(char **, GNodeList *, GNode *);828void Arch_Touch(GNode *);829void Arch_TouchLib(GNode *);830void Arch_UpdateMTime(GNode *);831void Arch_UpdateMemberMTime(GNode *);832void Arch_FindLib(GNode *, SearchPath *);833bool Arch_LibOODate(GNode *) MAKE_ATTR_USE;834bool Arch_IsLib(GNode *) MAKE_ATTR_USE;835836/* compat.c */837bool Compat_RunCommand(const char *, GNode *, StringListNode *);838void Compat_MakeAll(GNodeList *);839void Compat_Make(GNode *, GNode *);840841/* cond.c */842extern unsigned cond_depth;843CondResult Cond_EvalCondition(const char *) MAKE_ATTR_USE;844CondResult Cond_EvalLine(const char *) MAKE_ATTR_USE;845Guard *Cond_ExtractGuard(const char *) MAKE_ATTR_USE;846void Cond_EndFile(void);847848/* dir.c; see also dir.h */849850MAKE_INLINE const char * MAKE_ATTR_USE851str_basename(const char *pathname)852{853const char *lastSlash = strrchr(pathname, '/');854return lastSlash != NULL ? lastSlash + 1 : pathname;855}856857MAKE_INLINE SearchPath * MAKE_ATTR_USE858SearchPath_New(void)859{860SearchPath *path = bmake_malloc(sizeof *path);861Lst_Init(&path->dirs);862return path;863}864865void SearchPath_Free(SearchPath *);866867/* for.c */868struct ForLoop;869int For_Eval(const char *) MAKE_ATTR_USE;870bool For_Accum(const char *, int *) MAKE_ATTR_USE;871void For_Run(unsigned, unsigned);872bool For_NextIteration(struct ForLoop *, Buffer *);873char *ForLoop_Details(const struct ForLoop *);874void ForLoop_Free(struct ForLoop *);875void For_Break(struct ForLoop *);876877/* job.c */878void JobReapChild(pid_t, int, bool);879880/* longer than this we use a temp file */881#ifndef MAKE_CMDLEN_LIMIT882# define MAKE_CMDLEN_LIMIT 1000883#endif884/* main.c */885void Main_ParseArgLine(const char *);886void Cmd_Argv(const char *, size_t, const char *[5], char *, size_t,887bool, bool);888char *Cmd_Exec(const char *, char **) MAKE_ATTR_USE;889void Var_ExportStackTrace(const char *, const char *);890void Error(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);891void Fatal(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2) MAKE_ATTR_DEAD;892void Punt(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2) MAKE_ATTR_DEAD;893void DieHorribly(void) MAKE_ATTR_DEAD;894int unlink_file(const char *) MAKE_ATTR_USE;895void execDie(const char *, const char *);896char *getTmpdir(void) MAKE_ATTR_USE;897bool ParseBoolean(const char *, bool) MAKE_ATTR_USE;898const char *cached_realpath(const char *, char *);899bool GetBooleanExpr(const char *, bool);900901/* parse.c */902extern int parseErrors;903void Parse_Init(void);904#ifdef CLEANUP905void Parse_End(void);906#endif907908void PrintLocation(FILE *, bool, const GNode *);909const char *GetParentStackTrace(void);910char *GetStackTrace(bool);911void PrintStackTrace(bool);912void Parse_Error(ParseErrorLevel, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);913bool Parse_VarAssign(const char *, bool, GNode *) MAKE_ATTR_USE;914void Parse_File(const char *, int);915void Parse_PushInput(const char *, unsigned, unsigned, Buffer,916struct ForLoop *);917void Parse_MainName(GNodeList *);918unsigned CurFile_CondMinDepth(void) MAKE_ATTR_USE;919void Parse_GuardElse(void);920void Parse_GuardEndif(void);921922923/* suff.c */924void Suff_Init(void);925#ifdef CLEANUP926void Suff_End(void);927#endif928929void Suff_ClearSuffixes(void);930bool Suff_IsTransform(const char *) MAKE_ATTR_USE;931GNode *Suff_AddTransform(const char *);932void Suff_EndTransform(GNode *);933void Suff_AddSuffix(const char *);934SearchPath *Suff_GetPath(const char *) MAKE_ATTR_USE;935void Suff_ExtendPaths(void);936void Suff_AddInclude(const char *);937void Suff_AddLib(const char *);938void Suff_FindDeps(GNode *);939SearchPath *Suff_FindPath(GNode *) MAKE_ATTR_USE;940void Suff_SetNull(const char *);941void Suff_PrintAll(void);942char *Suff_NamesStr(void) MAKE_ATTR_USE;943944/* targ.c */945void Targ_Init(void);946void Targ_End(void);947948void Targ_Stats(void);949GNodeList *Targ_List(void) MAKE_ATTR_USE;950GNode *GNode_New(const char *) MAKE_ATTR_USE;951GNode *Targ_FindNode(const char *) MAKE_ATTR_USE;952GNode *Targ_GetNode(const char *) MAKE_ATTR_USE;953GNode *Targ_NewInternalNode(const char *) MAKE_ATTR_USE;954GNode *Targ_GetEndNode(void);955void Targ_FindList(GNodeList *, StringList *);956void Targ_PrintCmds(GNode *);957void Targ_PrintNode(GNode *, int);958void Targ_PrintNodes(GNodeList *, int);959const char *Targ_FmtTime(time_t) MAKE_ATTR_USE;960void Targ_PrintType(GNodeType);961void Targ_PrintGraph(int);962void Targ_Propagate(void);963const char *GNodeMade_Name(GNodeMade) MAKE_ATTR_USE;964#ifdef CLEANUP965void Parse_RegisterCommand(char *);966#else967MAKE_INLINE968void Parse_RegisterCommand(char *cmd MAKE_ATTR_UNUSED)969{970}971#endif972973/* var.c */974975typedef enum VarEvalMode {976977/*978* Only parse the expression but don't evaluate any part of it.979*980* TODO: Document what Var_Parse and Var_Subst return in this mode.981* As of 2021-03-15, they return unspecified, inconsistent results.982*/983VARE_PARSE,984985/*986* Parse text in which '${...}' and '$(...)' are not parsed as987* subexpressions (with all their individual escaping rules) but988* instead simply as text with balanced '${}' or '$()'. Other '$'989* are copied verbatim.990*/991VARE_PARSE_BALANCED,992993/* Parse and evaluate the expression. */994VARE_EVAL,995996/*997* Parse and evaluate the expression. It is an error if a998* subexpression evaluates to undefined.999*/1000VARE_EVAL_DEFINED_LOUD,10011002/*1003* Parse and evaluate the expression. It is a silent error if a1004* subexpression evaluates to undefined.1005*/1006VARE_EVAL_DEFINED,10071008/*1009* Parse and evaluate the expression. Keep undefined variables as-is1010* instead of expanding them to an empty string.1011*1012* Example for a ':=' assignment:1013* CFLAGS = $(.INCLUDES)1014* CFLAGS := -I.. $(CFLAGS)1015* # If .INCLUDES (an undocumented special variable, by the1016* # way) is still undefined, the updated CFLAGS becomes1017* # "-I.. $(.INCLUDES)".1018*/1019VARE_EVAL_KEEP_UNDEFINED,10201021/*1022* Parse and evaluate the expression. Keep '$$' as '$$' and preserve1023* undefined subexpressions.1024*/1025VARE_EVAL_KEEP_DOLLAR_AND_UNDEFINED1026} VarEvalMode;10271028typedef enum VarSetFlags {1029VAR_SET_NONE = 0,10301031/* do not export */1032VAR_SET_NO_EXPORT = 1 << 0,10331034/*1035* Make the variable read-only. No further modification is possible,1036* except for another call to Var_Set with the same flag. See the1037* special targets '.NOREADONLY' and '.READONLY'.1038*/1039VAR_SET_READONLY = 1 << 1,1040VAR_SET_INTERNAL = 1 << 21041} VarSetFlags;10421043typedef enum VarExportMode {1044/* .export-all */1045VEM_ALL,1046/* .export-env */1047VEM_ENV,1048/* .export: Initial export or update an already exported variable. */1049VEM_PLAIN,1050/* .export-literal: Do not expand the variable value. */1051VEM_LITERAL1052} VarExportMode;10531054void Var_Delete(GNode *, const char *);1055#ifdef CLEANUP1056void Var_DeleteAll(GNode *scope);1057#endif1058void Var_Undef(const char *);1059void Var_Set(GNode *, const char *, const char *);1060void Var_SetExpand(GNode *, const char *, const char *);1061void Var_SetWithFlags(GNode *, const char *, const char *, VarSetFlags);1062void Var_Append(GNode *, const char *, const char *);1063void Var_AppendExpand(GNode *, const char *, const char *);1064bool Var_Exists(GNode *, const char *) MAKE_ATTR_USE;1065bool Var_ExistsExpand(GNode *, const char *) MAKE_ATTR_USE;1066FStr Var_Value(GNode *, const char *) MAKE_ATTR_USE;1067const char *GNode_ValueDirect(GNode *, const char *) MAKE_ATTR_USE;1068FStr Var_Parse(const char **, GNode *, VarEvalMode);1069char *Var_Subst(const char *, GNode *, VarEvalMode);1070char *Var_SubstInTarget(const char *, GNode *);1071void Var_Expand(FStr *, GNode *, VarEvalMode);1072void Var_Stats(void);1073void Var_Dump(GNode *);1074void Var_ReexportVars(GNode *);1075void Var_Export(VarExportMode, const char *);1076void Var_ExportVars(const char *);1077void Var_UnExport(bool, const char *);1078void Var_ReadOnly(const char *, bool);10791080void Global_Set(const char *, const char *);1081void Global_Append(const char *, const char *);1082void Global_Delete(const char *);1083void Global_Set_ReadOnly(const char *, const char *);10841085void EvalStack_PushMakeflags(const char *);1086void EvalStack_Pop(void);1087bool EvalStack_Details(Buffer *buf) MAKE_ATTR_USE;10881089/* util.c */1090typedef void (*SignalProc)(int);1091SignalProc bmake_signal(int, SignalProc);10921093/* make.c */1094void GNode_UpdateYoungestChild(GNode *, GNode *);1095bool GNode_IsOODate(GNode *) MAKE_ATTR_USE;1096void Make_ExpandUse(GNodeList *);1097time_t Make_Recheck(GNode *) MAKE_ATTR_USE;1098void Make_HandleUse(GNode *, GNode *);1099void Make_Update(GNode *);1100void GNode_SetLocalVars(GNode *);1101bool Make_MakeParallel(GNodeList *);1102bool shouldDieQuietly(GNode *, int) MAKE_ATTR_USE;1103void PrintOnError(GNode *, const char *);1104void Main_ExportMAKEFLAGS(bool);1105bool Main_SetObjdir(bool, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);1106int mkTempFile(const char *, char *, size_t) MAKE_ATTR_USE;1107void AppendWords(StringList *, char *);1108void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *);1109bool GNode_ShouldExecute(GNode *gn) MAKE_ATTR_USE;1110char *GNodeType_ToString(GNodeType);11111112#ifndef HAVE_STRLCPY1113size_t strlcpy(char *, const char *, size_t);1114#endif11151116/* See if the node was seen on the left-hand side of a dependency operator. */1117MAKE_INLINE bool MAKE_ATTR_USE1118GNode_IsTarget(const GNode *gn)1119{1120return (gn->type & OP_OPMASK) != OP_NONE;1121}11221123MAKE_INLINE const char * MAKE_ATTR_USE1124GNode_Path(const GNode *gn)1125{1126return gn->path != NULL ? gn->path : gn->name;1127}11281129MAKE_INLINE bool MAKE_ATTR_USE1130GNode_IsWaitingFor(const GNode *gn)1131{1132return gn->flags.remake && gn->made <= REQUESTED;1133}11341135MAKE_INLINE bool MAKE_ATTR_USE1136GNode_IsReady(const GNode *gn)1137{1138return gn->made > DEFERRED;1139}11401141MAKE_INLINE bool MAKE_ATTR_USE1142GNode_IsDone(const GNode *gn)1143{1144return gn->made >= MADE;1145}11461147MAKE_INLINE bool MAKE_ATTR_USE1148GNode_IsError(const GNode *gn)1149{1150return gn->made == ERROR || gn->made == ABORTED;1151}11521153MAKE_INLINE bool MAKE_ATTR_USE1154GNode_IsMainCandidate(const GNode *gn)1155{1156return (gn->type & (OP_NOTMAIN | OP_USE | OP_USEBEFORE |1157OP_EXEC | OP_TRANSFORM)) == 0;1158}11591160/* Return whether the target file should be preserved on interrupt. */1161MAKE_INLINE bool MAKE_ATTR_USE1162GNode_IsPrecious(const GNode *gn)1163{1164/* XXX: Why are '::' targets precious? */1165return allPrecious || gn->type & (OP_PRECIOUS | OP_DOUBLEDEP);1166}11671168MAKE_INLINE const char * MAKE_ATTR_USE1169GNode_VarTarget(GNode *gn) { return GNode_ValueDirect(gn, TARGET); }1170MAKE_INLINE const char * MAKE_ATTR_USE1171GNode_VarOodate(GNode *gn) { return GNode_ValueDirect(gn, OODATE); }1172MAKE_INLINE const char * MAKE_ATTR_USE1173GNode_VarAllsrc(GNode *gn) { return GNode_ValueDirect(gn, ALLSRC); }1174MAKE_INLINE const char * MAKE_ATTR_USE1175GNode_VarImpsrc(GNode *gn) { return GNode_ValueDirect(gn, IMPSRC); }1176MAKE_INLINE const char * MAKE_ATTR_USE1177GNode_VarPrefix(GNode *gn) { return GNode_ValueDirect(gn, PREFIX); }1178MAKE_INLINE const char * MAKE_ATTR_USE1179GNode_VarArchive(GNode *gn) { return GNode_ValueDirect(gn, ARCHIVE); }1180MAKE_INLINE const char * MAKE_ATTR_USE1181GNode_VarMember(GNode *gn) { return GNode_ValueDirect(gn, MEMBER); }11821183MAKE_INLINE void * MAKE_ATTR_USE1184UNCONST(const void *ptr)1185{1186void *ret;1187memcpy(&ret, &ptr, sizeof(ret));1188return ret;1189}11901191/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */1192#ifdef HAVE_LIMITS_H1193#include <limits.h>1194#endif1195#ifndef MAXPATHLEN1196#define MAXPATHLEN BMAKE_PATH_MAX1197#endif1198#ifndef PATH_MAX1199#define PATH_MAX MAXPATHLEN1200#endif12011202#if defined(SYSV)1203#define KILLPG(pid, sig) kill(-(pid), (sig))1204#else1205#define KILLPG(pid, sig) killpg((pid), (sig))1206#endif12071208MAKE_INLINE bool MAKE_ATTR_USE1209ch_isalnum(char ch) { return isalnum((unsigned char)ch) != 0; }1210MAKE_INLINE bool MAKE_ATTR_USE1211ch_isalpha(char ch) { return isalpha((unsigned char)ch) != 0; }1212MAKE_INLINE bool MAKE_ATTR_USE1213ch_isdigit(char ch) { return isdigit((unsigned char)ch) != 0; }1214MAKE_INLINE bool MAKE_ATTR_USE1215ch_islower(char ch) { return islower((unsigned char)ch) != 0; }1216MAKE_INLINE bool MAKE_ATTR_USE1217ch_isprint(char ch) { return isprint((unsigned char)ch) != 0; }1218MAKE_INLINE bool MAKE_ATTR_USE1219ch_isspace(char ch) { return isspace((unsigned char)ch) != 0; }1220MAKE_INLINE bool MAKE_ATTR_USE1221ch_isupper(char ch) { return isupper((unsigned char)ch) != 0; }1222MAKE_INLINE char MAKE_ATTR_USE1223ch_tolower(char ch) { return (char)tolower((unsigned char)ch); }1224MAKE_INLINE char MAKE_ATTR_USE1225ch_toupper(char ch) { return (char)toupper((unsigned char)ch); }12261227MAKE_INLINE void1228cpp_skip_whitespace(const char **pp)1229{1230while (ch_isspace(**pp))1231(*pp)++;1232}12331234MAKE_INLINE void1235cpp_skip_hspace(const char **pp)1236{1237while (**pp == ' ' || **pp == '\t')1238(*pp)++;1239}12401241MAKE_INLINE bool1242cpp_skip_string(const char **pp, const char *s)1243{1244const char *p = *pp;1245while (*p == *s && *s != '\0')1246p++, s++;1247if (*s == '\0')1248*pp = p;1249return *s == '\0';1250}12511252MAKE_INLINE void1253pp_skip_whitespace(char **pp)1254{1255while (ch_isspace(**pp))1256(*pp)++;1257}12581259MAKE_INLINE void1260pp_skip_hspace(char **pp)1261{1262while (**pp == ' ' || **pp == '\t')1263(*pp)++;1264}12651266#if defined(lint)1267void do_not_define_rcsid(void); /* for lint */1268# define MAKE_RCSID(id) void do_not_define_rcsid(void)1269#elif defined(MAKE_NATIVE)1270# include <sys/cdefs.h>1271# ifndef __IDSTRING1272# define __IDSTRING(name,string) \1273static const char name[] MAKE_ATTR_UNUSED = string1274# endif1275# ifndef __RCSID1276# define __RCSID(s) __IDSTRING(rcsid,s)1277# endif1278# ifndef __COPYRIGHT1279# define __COPYRIGHT(s) __IDSTRING(copyright,s)1280# endif1281# define MAKE_RCSID(id) __RCSID(id)1282#elif defined(MAKE_ALL_IN_ONE) && defined(__COUNTER__)1283# define MAKE_RCSID_CONCAT(x, y) CONCAT(x, y)1284# define MAKE_RCSID(id) static volatile char \1285MAKE_RCSID_CONCAT(rcsid_, __COUNTER__)[] = id1286#elif defined(MAKE_ALL_IN_ONE)1287# define MAKE_RCSID(id) void do_not_define_rcsid(void)1288#else1289# define MAKE_RCSID(id) static volatile char rcsid[] = id1290#endif12911292#endif129312941295