diff options
author | Simon J. Gerraty <sjg@FreeBSD.org> | 2025-03-19 21:01:12 +0000 |
---|---|---|
committer | Simon J. Gerraty <sjg@FreeBSD.org> | 2025-03-19 21:01:12 +0000 |
commit | 397f57656d61ec830291c670fb8e33b18bf36ce9 (patch) | |
tree | 8cafd13e62c525f5d3c8aedbc079fcf09831faa7 | |
parent | 5ad769f660f3d00853bc739f82d9bc62f6a682cb (diff) |
Import bmake-20250308vendor/NetBSD/bmake/20250308vendor/NetBSD/bmake
Intersting/relevant changes since bmake-20250125
ChangeLog since bmake-20250125
2025-03-08 Simon J Gerraty <sjg@beast.crufty.net>
* bsd.after-import.mk: by default generate makefiles
closer to BSD style.
* VERSION (_MAKE_VERSION): 20250308
Merge with NetBSD make, pick up
o clean up comments and code for parallel mode
o job.c: avoid SIGPIPE for children, call Job_Wait befor abort.
2025-02-27 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20250225
Merge with NetBSD make, pick up
o job.c: reliably remove targets on interrupt,
by passing signal to children first.
mk/ChangeLog since bmake-20250125
2025-03-14 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20250314
* meta.stage.mk: StageFiles --subdir: preserve the dir part of
each file under $dest
2025-03-12 Simon J Gerraty <sjg@beast.crufty.net>
* meta.autodep.mk: do a better job of handling MAKESYSPATH in
GENDIRDEPS_ENV. If we have MAKE_VERSION >= 20230123 we can just
use .SYSPATH, otherwise it is a bit more complicated.
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | bmake.cat1 | 2 | ||||
-rw-r--r-- | bsd.after-import.mk | 39 | ||||
-rw-r--r-- | job.c | 251 | ||||
-rw-r--r-- | main.c | 22 | ||||
-rw-r--r-- | make.h | 3 | ||||
-rw-r--r-- | mk/ChangeLog | 13 | ||||
-rw-r--r-- | mk/install-mk | 6 | ||||
-rw-r--r-- | mk/jobs.mk | 6 | ||||
-rw-r--r-- | mk/meta.autodep.mk | 20 | ||||
-rw-r--r-- | mk/meta.stage.mk | 29 | ||||
-rw-r--r-- | mk/sys.vars.mk | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | os.sh | 10 |
15 files changed, 210 insertions, 225 deletions
diff --git a/ChangeLog b/ChangeLog index 212b0fcfaacb..15a58e2a0924 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2025-03-08 Simon J Gerraty <sjg@beast.crufty.net> + + * bsd.after-import.mk: by default generate makefiles + closer to BSD style. + + * VERSION (_MAKE_VERSION): 20250308 + Merge with NetBSD make, pick up + o clean up comments and code for parallel mode + o job.c: avoid SIGPIPE for children, call Job_Wait befor abort. + +2025-02-27 Simon J Gerraty <sjg@beast.crufty.net> + + * VERSION (_MAKE_VERSION): 20250225 + Merge with NetBSD make, pick up + o job.c: reliably remove targets on interrupt, + by passing signal to children first. + 2025-01-25 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20250125 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.132 2024/09/22 19:56:26 sjg Exp $ +# $Id: Makefile,v 1.133 2025/03/08 20:12:56 sjg Exp $ PROG = bmake @@ -65,7 +65,7 @@ COPTS.main.c += "-D$x=\"${$x}\"" USE_FILEMON ?= no .if ${USE_FILEMON:tl} != "no" .PATH: ${srcdir}/filemon -SRCS+= filemon_${USE_FILEMON}.c +SRCS += filemon_${USE_FILEMON}.c COPTS.meta.c += -DUSE_FILEMON -DUSE_FILEMON_${USE_FILEMON:tu} COPTS.job.c += ${COPTS.meta.c} @@ -134,7 +134,7 @@ SYMLINKS += ${PROG_NAME} ${BINDIR}/${PROG} .endif .endif -EXTRACT_MAN=no +EXTRACT_MAN = no # end-delete1 .if make(obj) || make(clean) @@ -182,7 +182,7 @@ SED_CMDS.${MAN} += -e 's/^\.Nx/NetBSD/' ${MAN}: ${SRCS.${MAN}} _GENFILES_USE all man beforeinstall: ${MAN} -_mfromdir=. +_mfromdir = . .endif .endif # MK_GEN_MAN @@ -1,2 +1,2 @@ # keep this compatible with sh and make -_MAKE_VERSION=20250125 +_MAKE_VERSION=20250308 diff --git a/bmake.cat1 b/bmake.cat1 index 8a1909e684ed..7e6f25524a05 100644 --- a/bmake.cat1 +++ b/bmake.cat1 @@ -1793,4 +1793,4 @@ BBUUGGSS attempt to suppress a cascade of unnecessary errors, can result in a seemingly unexplained `*** Error code 6' -FreeBSD 14.1-RELEASE-p5 November 14, 2024 FreeBSD 14.1-RELEASE-p5 +FreeBSD 14.1-RELEASE-p7 November 14, 2024 FreeBSD 14.1-RELEASE-p7 diff --git a/bsd.after-import.mk b/bsd.after-import.mk index f2948b855753..74811e98f979 100644 --- a/bsd.after-import.mk +++ b/bsd.after-import.mk @@ -1,4 +1,4 @@ -# $Id: bsd.after-import.mk,v 1.19 2024/09/21 22:44:55 sjg Exp $ +# $Id: bsd.after-import.mk,v 1.22 2025/03/09 02:56:42 sjg Exp $ # This makefile is for use when integrating bmake into a BSD build # system. Use this makefile after importing bmake. @@ -9,6 +9,7 @@ # The goal is to allow the benefits of autoconf without # the overhead of running configure. +.MAIN: all all: _makefile _utmakefile all: after-import @@ -64,6 +65,18 @@ MAKEFILE_SED = sed -e '/^MACHINE/d' \ -e '/^\..*include *</ { s,<\([a-z]\),<bsd.\1,;/autoconf/d; }' \ -e 's,${SRCTOP},$${SRCTOP},g' +.ifdef WITH_SPACE_ASSIGN +.space := ${x x:L:S/x//Wg} +.else +.space = +# this line noise achieves the equivalent of negating +# /^(.if|.elif|#)|==/ +# +MAKEFILE_SED += \ + -e '/^\.[e ]*l*if/!{/^\#/!{/==/!s,^\([^[:space:]][^=]*\)[[:space:]][[:space:]]*\([!?:+]*=\),\1\2,;};}' \ + +.endif + # These are the simple files we want to capture configured_files= config.h Makefile.config unit-tests/Makefile.config @@ -86,37 +99,41 @@ after-import: bootstrap ${MAKEFILE} @(echo '# This is a generated file, do NOT edit!'; \ echo '# See ${_this:S,${SRCTOP}/,,}'; \ echo '#'; ${ECHO_TAG} '# $$${HOST_OS}$$'; echo; \ - echo 'SRCTOP?= $${.CURDIR:${${.CURDIR}/$f:L:H:S,${SRCTOP}/,,:C,[^/]+,H,g:S,/,:,g}}'; echo; \ + echo 'SRCTOP${.space}?= $${.CURDIR:${${.CURDIR}/$f:L:H:S,${SRCTOP}/,,:C,[^/]+,H,g:S,/,:,g}}'; echo; \ ${MAKEFILE_SED} ${HOST_OS}/$f ) > ${.CURDIR}/$f .endfor +.if make(all) +_makefile _utmakefile: bootstrap ${MAKEFILE} +.endif + # this needs the most work -_makefile: bootstrap ${MAKEFILE} +_makefile: @echo Generating ${.CURDIR}/Makefile @(echo '# This is a generated file, do NOT edit!'; \ echo '# See ${_this:S,${SRCTOP}/,,}'; \ echo '#'; ${ECHO_TAG} '# $$${HOST_OS}$$'; \ - echo; echo 'SRCTOP?= $${.CURDIR:${.CURDIR:S,${SRCTOP}/,,:C,[^/]+,H,g:S,/,:,g}}'; \ + echo; echo 'SRCTOP${.space}?= $${.CURDIR:${.CURDIR:S,${SRCTOP}/,,:C,[^/]+,H,g:S,/,:,g}}'; \ echo; echo '# look here first for config.h'; \ - echo 'CFLAGS+= -I$${.CURDIR}'; echo; \ + echo 'CFLAGS${.space}+= -I$${.CURDIR}'; echo; \ echo '# for after-import'; \ - echo 'CLEANDIRS+= ${HOST_OS}'; \ - echo 'CLEANFILES+= bootstrap'; echo; \ + echo 'CLEANDIRS${.space}+= ${HOST_OS}'; \ + echo 'CLEANFILES${.space}+= bootstrap'; echo; \ ${MAKEFILE_SED} \ ${1 2:L:@n@-e '/start-delete$n/,/end-delete$n/d'@} \ ${BMAKE_SRC}/Makefile; \ echo; echo '# override some simple things'; \ - echo 'BINDIR= /usr/bin'; \ - echo 'MANDIR= ${MANDIR:U/usr/share/man}'; \ + echo 'BINDIR${.space}= /usr/bin'; \ + echo 'MANDIR${.space}= ${MANDIR:U/usr/share/man}'; \ echo; echo '# make sure we get this'; \ - echo 'CFLAGS+= $${COPTS.$${.IMPSRC:T}}'; \ + echo 'CFLAGS${.space}+= $${COPTS.$${.IMPSRC:T}}'; \ echo; echo 'after-import: ${_this:S,${SRCTOP},\${SRCTOP},}'; \ echo ' cd $${.CURDIR} && $${.MAKE} -f ${_this:S,${SRCTOP},\${SRCTOP},}'; \ echo ) > ${.TARGET} @cmp -s ${.TARGET} ${.CURDIR}/Makefile || \ mv ${.TARGET} ${.CURDIR}/Makefile -_utmakefile: bootstrap ${MAKEFILE} +_utmakefile: @echo Generating ${.CURDIR}/unit-tests/Makefile @mkdir -p ${.CURDIR}/unit-tests @(echo '# This is a generated file, do NOT edit!'; \ @@ -1,4 +1,4 @@ -/* $NetBSD: job.c,v 1.485 2025/01/19 10:57:10 rillig Exp $ */ +/* $NetBSD: job.c,v 1.489 2025/03/08 20:15:03 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -102,10 +102,7 @@ * define the shell that is used for the creation * commands in jobs mode. * - * Job_Finish Perform any final processing which needs doing. - * This includes the execution of any commands - * which have been/were attached to the .END - * target. It should only be called when the + * Job_Finish Make the .END target. Should only be called when the * job table is empty. * * Job_AbortAll Abort all currently running jobs. Do not handle @@ -154,7 +151,7 @@ #include "trace.h" /* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: job.c,v 1.485 2025/01/19 10:57:10 rillig Exp $"); +MAKE_RCSID("$NetBSD: job.c,v 1.489 2025/03/08 20:15:03 rillig Exp $"); /* * A shell defines how the commands are run. All commands for a target are @@ -673,7 +670,7 @@ JobPassSig_suspend(int signo) act.sa_flags = 0; (void)sigaction(signo, &act, NULL); - DEBUG1(JOB, "JobPassSig passing signal %d to self.\n", signo); + DEBUG1(JOB, "JobPassSig_suspend passing signal %d to self.\n", signo); (void)kill(getpid(), signo); @@ -1235,8 +1232,16 @@ JobFinish (Job *job, WAIT_T status) if (return_job_token) Job_TokenReturn(); - if (aborting == ABORT_ERROR && jobTokensRunning == 0) - Finish(job_errors); + if (aborting == ABORT_ERROR && jobTokensRunning == 0) { + if (shouldDieQuietly(NULL, -1)) { + /* + * TODO: better clean up properly, to avoid killing + * child processes by SIGPIPE. + */ + exit(2); + } + Fatal("%d error%s", job_errors, job_errors == 1 ? "" : "s"); + } } static void @@ -1945,27 +1950,14 @@ JobRun(GNode *targ) } } -/* - * Handle the exit of a child. Called from Make_Make. - * - * The job descriptor is removed from the list of children. - * - * Notes: - * We do waits, blocking or not, according to the wisdom of our - * caller, until there are no more children to report. For each - * job, call JobFinish to finish things off. - */ void Job_CatchChildren(void) { - int pid; /* pid of dead child */ - WAIT_T status; /* Exit/termination status */ + int pid; + WAIT_T status; - /* Don't even bother if we know there's no one around. */ if (jobTokensRunning == 0) return; - - /* Have we received SIGCHLD since last call? */ if (caught_sigchld == 0) return; caught_sigchld = 0; @@ -1984,21 +1976,19 @@ Job_CatchChildren(void) void JobReapChild(pid_t pid, WAIT_T status, bool isJobs) { - Job *job; /* job descriptor for dead child */ + Job *job; - /* Don't even bother if we know there's no one around. */ if (jobTokensRunning == 0) return; job = JobFindPid(pid, JOB_ST_RUNNING, isJobs); if (job == NULL) { - if (isJobs) { - if (!lurking_children) - Error("Child (%d) status %x not in table?", - pid, status); - } - return; /* not ours */ + if (isJobs && !lurking_children) + Error("Child (%d) status %x not in table?", + pid, status); + return; } + if (WIFSTOPPED(status)) { DEBUG2(JOB, "Process %d (%s) stopped.\n", job->pid, job->node->name); @@ -2030,12 +2020,6 @@ JobReapChild(pid_t pid, WAIT_T status, bool isJobs) JobFinish(job, status); } -/* - * Catch the output from our children, if we're using pipes do so. Otherwise - * just block time until we get a signal(most likely a SIGCHLD) since there's - * no point in just spinning when there's nothing to do and the reaping of a - * child can wait for a while. - */ void Job_CatchOutput(void) { @@ -2045,7 +2029,7 @@ Job_CatchOutput(void) (void)fflush(stdout); - /* The first fd in the list is the job token pipe */ + /* Skip the first fd in the list, as it is the job token pipe. */ do { nready = poll(fds + 1 - wantToken, fdsLen - 1 + wantToken, POLL_MSEC); @@ -2056,13 +2040,12 @@ Job_CatchOutput(void) if (nready > 0 && readyfd(&childExitJob)) { char token = 0; - ssize_t count; - count = read(childExitJob.inPipe, &token, 1); + ssize_t count = read(childExitJob.inPipe, &token, 1); if (count == 1) { if (token == DO_JOB_RESUME[0]) /* * Complete relay requested from our SIGCONT - * handler + * handler. */ JobRestartJobs(); } else if (count == 0) @@ -2143,10 +2126,7 @@ Shell_Init(void) } } -/* - * Return the string literal that is used in the current command shell - * to produce a newline character. - */ +/* Return the shell string literal that results in a newline character. */ const char * Shell_GetNewline(void) { @@ -2175,12 +2155,11 @@ AddSig(int sig, SignalProc handler) } } -/* Initialize the process module. */ void Job_Init(void) { Job_SetPrefix(); - /* Allocate space for all the job info */ + job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table); memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table); job_table_end = job_table + opts.maxJobs; @@ -2191,8 +2170,8 @@ Job_Init(void) job_errors = 0; /* - * There is a non-zero chance that we already have children. - * eg after 'make -f- <<EOF' + * There is a non-zero chance that we already have children, + * e.g. after 'make -f- <<EOF'. * Since their termination causes a 'Child (pid) not in table' * message, Collect the status of any that are already dead, and * suppress the error message if there are any undead ones. @@ -2214,7 +2193,6 @@ Job_Init(void) JobCreatePipe(&childExitJob, 3); { - /* Preallocate enough for the maximum number of jobs. */ size_t nfds = (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job(); fds = bmake_malloc(sizeof *fds * nfds); @@ -2226,24 +2204,19 @@ Job_Init(void) watchfd(&childExitJob); sigemptyset(&caught_signals); - /* Install a SIGCHLD handler. */ (void)bmake_signal(SIGCHLD, JobChildSig); sigaddset(&caught_signals, SIGCHLD); - /* - * Catch the four signals that POSIX specifies if they aren't ignored. - * JobPassSig will take care of calling JobInterrupt if appropriate. - */ + /* Handle the signals specified by POSIX. */ AddSig(SIGINT, JobPassSig_int); AddSig(SIGHUP, JobPassSig_term); AddSig(SIGTERM, JobPassSig_term); AddSig(SIGQUIT, JobPassSig_term); /* - * There are additional signals that need to be caught and passed if - * either the export system wants to be told directly of signals or if - * we're giving each job its own process group (since then it won't get - * signals from the terminal driver as we own the terminal) + * These signals need to be passed to the jobs, as each job has its + * own process group and thus the terminal driver doesn't forward the + * signals itself. */ AddSig(SIGTSTP, JobPassSig_suspend); AddSig(SIGTTOU, JobPassSig_suspend); @@ -2252,10 +2225,7 @@ Job_Init(void) AddSig(SIGCONT, JobContinueSig); (void)Job_RunTarget(".BEGIN", NULL); - /* - * Create the .END node now, even though no code in the unit tests - * depends on it. See also Targ_GetEndNode in Compat_MakeAll. - */ + /* Create the .END node, see Targ_GetEndNode in Compat_MakeAll. */ (void)Targ_GetEndNode(); } @@ -2281,7 +2251,6 @@ JobSigReset(void) (void)bmake_signal(SIGCHLD, SIG_DFL); } -/* Find a shell in 'shells' given its name, or return NULL. */ static Shell * FindShellByName(const char *name) { @@ -2303,40 +2272,35 @@ FindShellByName(const char *name) * line The shell spec * * Results: - * false if the specification was incorrect. - * - * Side Effects: - * 'shell' points to a Shell structure (either predefined or - * created from the shell spec), shellPath is the full path of the - * shell described by 'shell', while shellName is just the - * final component of shellPath. + * Returns false if the specification was incorrect. + * If successful, 'shell' is usable, shellPath is the full path of the + * shell described by 'shell', and shellName is the final component of + * shellPath. * * Notes: - * A shell specification consists of a .SHELL target, with dependency - * operator, followed by a series of blank-separated words. Double - * quotes can be used to use blanks in words. A backslash escapes + * A shell specification has the form ".SHELL: keyword=value...". Double + * quotes can be used to enclose blanks in words. A backslash escapes * anything (most notably a double-quote and a space) and - * provides the functionality it does in C. Each word consists of - * keyword and value separated by an equal sign. There should be no - * unnecessary spaces in the word. The keywords are as follows: + * provides the usual escape sequences from C. There should be no + * unnecessary spaces in the word. The keywords are: * name Name of shell. * path Location of shell. * quiet Command to turn off echoing. * echo Command to turn echoing on - * filter Result of turning off echoing that shouldn't be - * printed. - * echoFlag Flag to turn echoing on at the start - * errFlag Flag to turn error checking on at the start - * hasErrCtl True if shell has error checking control - * newline String literal to represent a newline char - * check Command to turn on error checking if hasErrCtl - * is true or template of command to echo a command - * for which error checking is off if hasErrCtl is - * false. - * ignore Command to turn off error checking if hasErrCtl - * is true or template of command to execute a - * command so as to ignore any errors it returns if - * hasErrCtl is false. + * filter The output from the shell command that turns off + * echoing, to be filtered from the final output. + * echoFlag Flag to turn echoing on at the start. + * errFlag Flag to turn error checking on at the start. + * hasErrCtl True if the shell has error checking control. + * newline String literal to represent a newline character. + * check If hasErrCtl is true: The command to turn on error + * checking. If hasErrCtl is false: The template for a + * shell command that echoes a command for which error + * checking is off. + * ignore If hasErrCtl is true: The command to turn off error + * checking. If hasErrCtl is false: The template for a + * shell command that executes a command so as to ignore + * any errors it returns. */ bool Job_ParseShell(char *line) @@ -2357,7 +2321,6 @@ Job_ParseShell(char *line) memset(&newShell, 0, sizeof newShell); - /* Parse the specification by keyword. */ wordsList = Str_Words(line, true); words = wordsList.words; argc = wordsList.len; @@ -2421,12 +2384,6 @@ Job_ParseShell(char *line) } if (path == NULL) { - /* - * If no path was given, the user wants one of the - * pre-defined shells, yes? So we find the one s/he wants - * with the help of FindShellByName and set things up the - * right way. shellPath will be set up by Shell_Init. - */ if (newShell.name == NULL) { Parse_Error(PARSE_FATAL, "Neither path nor name specified"); @@ -2442,10 +2399,6 @@ Job_ParseShell(char *line) shell = sh; shellName = newShell.name; if (shellPath != NULL) { - /* - * Shell_Init has already been called! - * Do it again. - */ free(shellPath); shellPath = NULL; Shell_Init(); @@ -2468,7 +2421,7 @@ Job_ParseShell(char *line) shell = bmake_malloc(sizeof *shell); *shell = newShell; } - /* this will take care of shellErrFlag */ + /* This will take care of shellErrFlag. */ Shell_Init(); } @@ -2483,7 +2436,7 @@ Job_ParseShell(char *line) } /* - * Do not free up the words themselves, since they might be in use + * Do not free up the words themselves, since they may be in use * by the shell specification. */ free(words); @@ -2491,36 +2444,22 @@ Job_ParseShell(char *line) } /* - * Handle the receipt of an interrupt. - * - * All children are killed. Another job will be started if the .INTERRUPT - * target is defined. - * - * Input: - * runINTERRUPT Non-zero if commands for the .INTERRUPT target - * should be executed - * signo signal received + * After receiving an interrupt signal, terminate all child processes and if + * necessary make the .INTERRUPT target. */ static void JobInterrupt(bool runINTERRUPT, int signo) { - Job *job; /* job descriptor in that element */ - GNode *interrupt; /* the node describing the .INTERRUPT target */ + Job *job; + GNode *interrupt; sigset_t mask; - GNode *gn; aborting = ABORT_INTERRUPT; JobSigLock(&mask); for (job = job_table; job < job_table_end; job++) { - if (job->status != JOB_ST_RUNNING) - continue; - - gn = job->node; - - JobDeleteTarget(gn); - if (job->pid != 0) { + if (job->status == JOB_ST_RUNNING && job->pid != 0) { DEBUG2(JOB, "JobInterrupt passing signal %d to child %d.\n", signo, job->pid); @@ -2528,6 +2467,14 @@ JobInterrupt(bool runINTERRUPT, int signo) } } + for (job = job_table; job < job_table_end; job++) { + if (job->status == JOB_ST_RUNNING && job->pid != 0) { + int status; + (void)waitpid(job->pid, &status, 0); + JobDeleteTarget(job->node); + } + } + JobSigUnlock(&mask); if (runINTERRUPT && !opts.touch) { @@ -2541,11 +2488,7 @@ JobInterrupt(bool runINTERRUPT, int signo) exit(signo); /* XXX: why signo? */ } -/* - * Do the final processing, i.e. run the commands attached to the .END target. - * - * Return the number of errors reported. - */ +/* Make the .END target, returning the number of job-related errors. */ int Job_Finish(void) { @@ -2561,7 +2504,6 @@ Job_Finish(void) } #ifdef CLEANUP -/* Clean up any memory used by the jobs module. */ void Job_End(void) { @@ -2569,14 +2511,11 @@ Job_End(void) } #endif -/* - * Waits for all running jobs to finish and returns. - * Sets 'aborting' to ABORT_WAIT to prevent other jobs from starting. - */ +/* Waits for all running jobs to finish. */ void Job_Wait(void) { - aborting = ABORT_WAIT; + aborting = ABORT_WAIT; /* Prevent other jobs from starting. */ while (jobTokensRunning != 0) { Job_CatchOutput(); } @@ -2587,14 +2526,12 @@ Job_Wait(void) * Abort all currently running jobs without handling output or anything. * This function is to be called only in the event of a major error. * Most definitely NOT to be called from JobInterrupt. - * - * All children are killed, not just the firstborn. */ void Job_AbortAll(void) { - Job *job; /* the job descriptor in that element */ - WAIT_T foo; + Job *job; + WAIT_T status; aborting = ABORT_ERROR; @@ -2602,25 +2539,18 @@ Job_AbortAll(void) for (job = job_table; job < job_table_end; job++) { if (job->status != JOB_ST_RUNNING) continue; - /* - * kill the child process with increasingly drastic - * signals to make darn sure it's dead. - */ KILLPG(job->pid, SIGINT); KILLPG(job->pid, SIGKILL); } } - /* - * Catch as many children as want to report in at first, then give up - */ - while (waitpid((pid_t)-1, &foo, WNOHANG) > 0) + while (waitpid((pid_t)-1, &status, WNOHANG) > 0) continue; } /* * Tries to restart stopped jobs if there are slots available. - * Called in process context in response to a SIGCONT. + * Called in response to a SIGCONT. */ static void JobRestartJobs(void) @@ -2685,10 +2615,6 @@ clearfd(Job *job) fdsLen--; #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) if (useMeta) { - /* - * Sanity check: there should be two fds per job, so the job's - * pollfd number should be even. - */ assert(nfds_per_job() == 2); if (i % 2 != 0) Punt("odd-numbered fd with meta"); @@ -2727,7 +2653,7 @@ JobTokenAdd(void) { char tok = JOB_TOKENS[aborting], tok1; - /* If we are depositing an error token flush everything else */ + /* If we are depositing an error token, flush everything else. */ while (tok != '+' && read(tokenWaitJob.inPipe, &tok1, 1) == 1) continue; @@ -2737,7 +2663,6 @@ JobTokenAdd(void) continue; } -/* Get a temp file */ int Job_TempFile(const char *pattern, char *tfile, size_t tfile_sz) { @@ -2753,7 +2678,7 @@ Job_TempFile(const char *pattern, char *tfile, size_t tfile_sz) return fd; } -/* Prep the job token pipe in the root make process. */ +/* Prepare the job token pipe in the root make process. */ void Job_ServerStart(int max_tokens, int jp_0, int jp_1) { @@ -2761,7 +2686,6 @@ Job_ServerStart(int max_tokens, int jp_0, int jp_1) char jobarg[64]; if (jp_0 >= 0 && jp_1 >= 0) { - /* Pipe passed in from parent */ tokenWaitJob.inPipe = jp_0; tokenWaitJob.outPipe = jp_1; (void)fcntl(jp_0, F_SETFD, FD_CLOEXEC); @@ -2803,7 +2727,7 @@ Job_TokenReturn(void) /* * Attempt to withdraw a token from the pool. * - * If pool is empty, set wantToken so that we wake up when a token is + * If the pool is empty, set wantToken so that we wake up when a token is * released. * * Returns true if a token was withdrawn, and false if the pool is currently @@ -2842,8 +2766,10 @@ Job_TokenWithdraw(void) while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN) continue; - if (shouldDieQuietly(NULL, 1)) - exit(6); /* we aborted */ + if (shouldDieQuietly(NULL, 1)) { + Job_Wait(); + exit(6); + } Fatal("A failure has been detected " "in another branch of the parallel make"); } @@ -2859,12 +2785,7 @@ Job_TokenWithdraw(void) return true; } -/* - * Run the named target if found. If a filename is specified, then set that - * to the sources. - * - * Exits if the target fails. - */ +/* Make the named target if found, exit if the target fails. */ bool Job_RunTarget(const char *target, const char *fname) { @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.638 2025/01/19 12:59:39 rillig Exp $ */ +/* $NetBSD: main.c,v 1.639 2025/03/07 06:50:34 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -83,9 +83,6 @@ * Fatal Print an error message and exit. * * Punt Abort all jobs and exit with a message. - * - * Finish Finish things up by printing the number of errors - * that occurred, and exit. */ #include <sys/types.h> @@ -111,7 +108,7 @@ #include "trace.h" /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: main.c,v 1.638 2025/01/19 12:59:39 rillig Exp $"); +MAKE_RCSID("$NetBSD: main.c,v 1.639 2025/03/07 06:50:34 rillig Exp $"); #if defined(MAKE_NATIVE) __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " "The Regents of the University of California. " @@ -1783,7 +1780,7 @@ Cmd_Exec(const char *cmd, char **error) int pipefds[2]; int cpid; /* Child PID */ int pid; /* PID from wait() */ - int status; /* command exit status */ + WAIT_T status; /* command exit status */ Buffer buf; /* buffer to store the result */ ssize_t bytes_read; char *output; @@ -1962,19 +1959,6 @@ DieHorribly(void) exit(2); /* Not 1 so -q can distinguish error */ } -/* - * Called when aborting due to errors in child shell to signal abnormal exit. - * The program exits. - * Errors is the number of errors encountered in Make_Make. - */ -void -Finish(int errs) -{ - if (shouldDieQuietly(NULL, -1)) - exit(2); - Fatal("%d error%s", errs, errs == 1 ? "" : "s"); -} - int unlink_file(const char *file) { @@ -1,4 +1,4 @@ -/* $NetBSD: make.h,v 1.349 2025/01/19 10:57:10 rillig Exp $ */ +/* $NetBSD: make.h,v 1.350 2025/03/07 06:50:34 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -889,7 +889,6 @@ void Error(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2); void Fatal(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2) MAKE_ATTR_DEAD; void Punt(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2) MAKE_ATTR_DEAD; void DieHorribly(void) MAKE_ATTR_DEAD; -void Finish(int) MAKE_ATTR_DEAD; int unlink_file(const char *) MAKE_ATTR_USE; void execDie(const char *, const char *); char *getTmpdir(void) MAKE_ATTR_USE; diff --git a/mk/ChangeLog b/mk/ChangeLog index 4274d9d3483b..99f4b05be61c 100644 --- a/mk/ChangeLog +++ b/mk/ChangeLog @@ -1,3 +1,16 @@ +2025-03-14 Simon J Gerraty <sjg@beast.crufty.net> + + * install-mk (MK_VERSION): 20250314 + + * meta.stage.mk: StageFiles --subdir: preserve the dir part of + each file under $dest + +2025-03-12 Simon J Gerraty <sjg@beast.crufty.net> + + * meta.autodep.mk: do a better job of handling MAKESYSPATH in + GENDIRDEPS_ENV. If we have MAKE_VERSION >= 20230123 we can just + use .SYSPATH, otherwise it is a bit more complicated. + 2025-01-10 Simon J Gerraty <sjg@beast.crufty.net> * rust.mk: use RUST_LIBS and RUST_PROGS diff --git a/mk/install-mk b/mk/install-mk index b455832b7726..d765fbba2251 100644 --- a/mk/install-mk +++ b/mk/install-mk @@ -59,9 +59,9 @@ # Simon J. Gerraty <sjg@crufty.net> # RCSid: -# $Id: install-mk,v 1.262 2025/01/05 01:16:19 sjg Exp $ +# $Id: install-mk,v 1.263 2025/03/14 20:29:35 sjg Exp $ # -# @(#) Copyright (c) 1994-2024 Simon J. Gerraty +# @(#) Copyright (c) 1994-2025 Simon J. Gerraty # # This file is provided in the hope that it will # be of use. There is absolutely NO WARRANTY. @@ -74,7 +74,7 @@ # sjg@crufty.net # -MK_VERSION=20250101 +MK_VERSION=20250314 OWNER= GROUP= MODE=444 diff --git a/mk/jobs.mk b/mk/jobs.mk index f39f1eb178ae..e304e16a9c56 100644 --- a/mk/jobs.mk +++ b/mk/jobs.mk @@ -1,8 +1,8 @@ # SPDX-License-Identifier: BSD-2-Clause # -# $Id: jobs.mk,v 1.17 2024/02/17 17:26:57 sjg Exp $ +# $Id: jobs.mk,v 1.19 2025/02/03 21:18:44 sjg Exp $ # -# @(#) Copyright (c) 2012-2023, Simon J. Gerraty +# @(#) Copyright (c) 2012-2025, Simon J. Gerraty # # This file is provided in the hope that it will # be of use. There is absolutely NO WARRANTY. @@ -68,7 +68,7 @@ NEWLOG_SH := ${(type newlog.sh) 2> /dev/null:L:sh:M/*} .endif .endif .if !empty(NEWLOG_SH) && exists(${NEWLOG_SH}) -NEWLOG := sh ${NEWLOG_SH} +NEWLOG := ${.SHELL:Ush} ${NEWLOG_SH} JOB_NEWLOG_ARGS ?= -S -n ${JOB_LOG_GENS} .else NEWLOG = : diff --git a/mk/meta.autodep.mk b/mk/meta.autodep.mk index 55f2d66e56aa..b94891b1b93f 100644 --- a/mk/meta.autodep.mk +++ b/mk/meta.autodep.mk @@ -1,9 +1,9 @@ # SPDX-License-Identifier: BSD-2-Clause # -# $Id: meta.autodep.mk,v 1.63 2024/04/24 18:56:41 sjg Exp $ +# $Id: meta.autodep.mk,v 1.65 2025/03/14 20:28:42 sjg Exp $ # -# @(#) Copyright (c) 2010, Simon J. Gerraty +# @(#) Copyright (c) 2010-2025, Simon J. Gerraty # # This file is provided in the hope that it will # be of use. There is absolutely NO WARRANTY. @@ -281,14 +281,26 @@ META_FILES := ${META_XTRAS:U:O:u} ${META_FILES:U:T:O:u:${META_FILE_FILTER:ts:}} .export META_FILES .endif +_this_dir := ${_PARSEDIR} +.if ${MAKE_VERSION} < 20230123 # we might have .../ in MAKESYSPATH -_makesyspath:= ${_PARSEDIR} +_makesyspath := ${MAKESYSPATH:U${_this_dir}} +.if ${.MAKEFLAGS:M-m} != "" +_makesyspath := ${.MAKEFLAGS:S,-m ,-m,gW:M-m*:S,-m, ,:ts:}:${_makesyspath} +.endif +_makesyspath := ${_makesyspath:C,\.\.\./[^:]*,${_this_dir},} +GENDIRDEPS_ENV += MAKESYSPATH=${_makesyspath} +.else +# add this if not already there +.SYSPATH: ${_this_dir} +GENDIRDEPS_ENV += MAKESYSPATH=${.SYSPATH:ts:} +.endif + ${_DEPENDFILE}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.META.CREATED} @echo Checking $@: ${.OODATE:T:[1..8]} @(cd . && ${GENDIRDEPS_ENV} \ SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS:O:u}' \ DPADD='${FORCE_DPADD:O:u}' ${_gendirdeps_mutex} \ - MAKESYSPATH=${_makesyspath} \ ${.MAKE} -f gendirdeps.mk RELDIR=${RELDIR} _DEPENDFILE=${_DEPENDFILE}) @test -s $@ && touch $@; : .endif diff --git a/mk/meta.stage.mk b/mk/meta.stage.mk index 345df6aae16b..97e4dce83e5d 100644 --- a/mk/meta.stage.mk +++ b/mk/meta.stage.mk @@ -1,8 +1,8 @@ # SPDX-License-Identifier: BSD-2-Clause # -# $Id: meta.stage.mk,v 1.69 2024/02/17 17:26:57 sjg Exp $ +# $Id: meta.stage.mk,v 1.71 2025/03/14 20:28:42 sjg Exp $ # -# @(#) Copyright (c) 2011-2017, Simon J. Gerraty +# @(#) Copyright (c) 2011-2025, Simon J. Gerraty # # This file is provided in the hope that it will # be of use. There is absolutely NO WARRANTY. @@ -40,9 +40,11 @@ CLEANFILES+= .dirdep .if defined(NO_POSIX_SHELL) || ${type printf:L:sh:Mbuiltin} == "" _stage_file_basename = `basename $$f` +_stage_file_dirname = `dirname $$f` _stage_target_dirname = `dirname $$t` .else _stage_file_basename = $${f\#\#*/} +_stage_file_dirname = $${f%/*} _stage_target_dirname = $${t%/*} .endif @@ -86,22 +88,37 @@ STAGE_DIRDEP_SCRIPT = ${LN_CP_SCRIPT}; StageDirdep() { \ if [ -s $$t.dirdep ]; then \ cmp -s .dirdep $$t.dirdep && return; \ x=`cat $$t.dirdep`; \ - case "${RELDIR}:${_dirdep}" in $${x%.*}:$${x}*) ;; \ + case "${RELDIR}:${_dirdep}" in \ + $${x%.*}:$${x}*) ;; \ *) echo "${STAGE_CONFLICT}: $$t installed by $$x not ${_dirdep}" >&2; \ - ${STAGE_CONFLICT_ACTION} ;; esac; \ + ${STAGE_CONFLICT_ACTION} ;; \ + esac; \ fi; \ LnCp .dirdep $$t.dirdep || exit 1; } # common logic for staging files # this all relies on RELDIR being set to a subdir of SRCTOP # we use ln(1) if we can, else cp(1) +# if --subdir is given the dirname part of each file will be preserved STAGE_FILE_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageFiles() { \ - case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \ + mode= subdir=; \ + while : ; do \ + case "$$1" in \ + "") return;; \ + -m) mode=$$2; shift 2;; \ + --subdir) subdir=1; shift;; \ + *) break;; \ + esac; \ + done; \ dest=$$1; shift; \ mkdir -p $$dest; \ [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \ for f in "$$@"; do \ - case "$$f" in */*) t=$$dest/${_stage_file_basename};; *) t=$$dest/$$f;; esac; \ + case "$$subdir,$$f" in \ + 1,*/*) t=$$dest/$$f; mkdir -p $$dest/${_stage_file_dirname};; \ + */*) t=$$dest/${_stage_file_basename};; \ + *) t=$$dest/$$f;; \ + esac; \ StageDirdep $$t; \ LnCp $$f $$t || exit 1; \ [ -z "$$mode" ] || chmod $$mode $$t; \ diff --git a/mk/sys.vars.mk b/mk/sys.vars.mk index 49d1a71b1d98..c3daf745fb5c 100644 --- a/mk/sys.vars.mk +++ b/mk/sys.vars.mk @@ -1,6 +1,6 @@ # SPDX-License-Identifier: BSD-2-Clause # -# $Id: sys.vars.mk,v 1.17 2024/09/28 04:06:47 sjg Exp $ +# $Id: sys.vars.mk,v 1.18 2025/03/09 02:47:59 sjg Exp $ # # @(#) Copyright (c) 2003-2023, Simon J. Gerraty # @@ -140,8 +140,9 @@ M_mtime = tW:S,^,${STAT:Ustat} -f %m ,:sh M_mtime = mtime${M_mtime_fallback:U} .endif -# This line noise allows doing .tab and .bel below +# This line noise allows doing .bel .space and .tab below # don't expect sane results if input is more than a single word M_CharLiteral = L:@c@$${x x:L:$${:Uts$$c}:S/x//Wg}@ -.tab := ${\t:${M_CharLiteral}} .bel := ${\007:${M_CharLiteral}} +.space := ${\040:${M_CharLiteral}} +.tab := ${\t:${M_CharLiteral}} @@ -17,7 +17,7 @@ # Simon J. Gerraty <sjg@crufty.net> # RCSid: -# $Id: os.sh,v 1.66 2024/09/25 18:16:09 sjg Exp $ +# $Id: os.sh,v 1.67 2025/02/13 21:04:34 sjg Exp $ # # @(#) Copyright (c) 1994 Simon J. Gerraty # @@ -38,8 +38,12 @@ _OS_SH=: OS=`uname` OSREL=`uname -r` OSMAJOR=`IFS=.; set $OSREL; echo $1` -MACHINE=`uname -m` -MACHINE_ARCH=`uname -p 2>/dev/null || echo $MACHINE` +# we want to retain the raw output from uname -m and -p +OS_MACHINE=`uname -m` +OS_MACHINE_ARCH=`uname -p 2>/dev/null || echo $OS_MACHINE` + +MACHINE=$OS_MACHINE +MACHINE_ARCH=$OS_MACHINE_ARCH # there is at least one case of `uname -p` # and even `uname -m` outputting usless info |