diff options
| author | Simon J. Gerraty <sjg@FreeBSD.org> | 2026-05-13 04:20:50 +0000 |
|---|---|---|
| committer | Simon J. Gerraty <sjg@FreeBSD.org> | 2026-05-13 04:20:50 +0000 |
| commit | ef402bba84260816d3e8d6e2439b0bc7eddc9446 (patch) | |
| tree | dd34b0ce295c31fa6eacc9ac6efbf7451115660b | |
| parent | fe271bdb43cf88ee129d94c0e286fe618fd28e89 (diff) | |
| -rw-r--r-- | ChangeLog | 16 | ||||
| -rw-r--r-- | Makefile.config.in | 1 | ||||
| -rw-r--r-- | VERSION | 2 | ||||
| -rw-r--r-- | arch.c | 16 | ||||
| -rw-r--r-- | bmake.1 | 6 | ||||
| -rw-r--r-- | bmake.cat1 | 22 | ||||
| -rw-r--r-- | cond.c | 12 | ||||
| -rwxr-xr-x | configure | 35 | ||||
| -rw-r--r-- | configure.in | 21 | ||||
| -rw-r--r-- | dir.c | 8 | ||||
| -rw-r--r-- | for.c | 14 | ||||
| -rw-r--r-- | job.c | 11 | ||||
| -rw-r--r-- | main.c | 6 | ||||
| -rwxr-xr-x | make-bootstrap.sh.in | 4 | ||||
| -rw-r--r-- | make.1 | 6 | ||||
| -rw-r--r-- | make.c | 13 | ||||
| -rw-r--r-- | make.h | 14 | ||||
| -rw-r--r-- | meta.c | 8 | ||||
| -rw-r--r-- | mk/ChangeLog | 26 | ||||
| -rw-r--r-- | mk/dirdeps.mk | 23 | ||||
| -rw-r--r-- | mk/gendirdeps.mk | 8 | ||||
| -rw-r--r-- | mk/install-mk | 4 | ||||
| -rw-r--r-- | mk/lib.mk | 4 | ||||
| -rw-r--r-- | mk/meta.sys.mk | 8 | ||||
| -rw-r--r-- | mk/sys.dependfile.mk | 4 | ||||
| -rw-r--r-- | mk/sys.dirdeps.mk | 5 | ||||
| -rw-r--r-- | mk/sys.mk | 10 | ||||
| -rw-r--r-- | mk/sys.vars.mk | 4 | ||||
| -rw-r--r-- | parse.c | 6 | ||||
| -rw-r--r-- | var.c | 13 |
30 files changed, 208 insertions, 122 deletions
diff --git a/ChangeLog b/ChangeLog index 2145b25f809f..5189ec11ca1a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2026-05-08 Simon J Gerraty <sjg@beast.crufty.net> + + * VERSION (_MAKE_VERSION): 20260508 + Merge with NetBSD make, pick up + o make.1: fix description of '-' handling in jobs-mod + by intenting it correctly. + +2026-04-13 Simon J Gerraty <sjg@beast.crufty.net> + + * VERSION (_MAKE_VERSION): 20260406 + Merge with NetBSD make, pick up + o cleanup unnecessary parens + + * configure.in: add --with-save-dollars to control default for + .MAKE.SAVE.DOLLARS - address FreeBSD PR 294436 + 2026-03-12 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20260313 diff --git a/Makefile.config.in b/Makefile.config.in index 43ad1b9a397a..f1e041d705c4 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -9,6 +9,7 @@ CC= @CC@ @force_machine@MACHINE?= @machine@ @force_machine_arch@MACHINE_ARCH?= @machine_arch@ DEFAULT_SYS_PATH?= @default_sys_path@ +MAKE_SAVE_DOLLARS_DEFAULT?= @save_dollars@ EGREP = @egrep@ CPPFLAGS+= @CPPFLAGS@ @@ -1,2 +1,2 @@ # keep this compatible with sh and make -_MAKE_VERSION=20260313 +_MAKE_VERSION=20260508 @@ -1,4 +1,4 @@ -/* $NetBSD: arch.c,v 1.223 2025/06/28 22:39:27 rillig Exp $ */ +/* $NetBSD: arch.c,v 1.224 2026/04/06 17:13:54 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -147,10 +147,10 @@ struct ar_hdr { #include "dir.h" /* "@(#)arch.c 8.2 (Berkeley) 1/2/94" */ -MAKE_RCSID("$NetBSD: arch.c,v 1.223 2025/06/28 22:39:27 rillig Exp $"); +MAKE_RCSID("$NetBSD: arch.c,v 1.224 2026/04/06 17:13:54 rillig Exp $"); -typedef struct List ArchList; -typedef struct ListNode ArchListNode; +typedef List ArchList; +typedef ListNode ArchListNode; static ArchList archives; /* The archives we've already examined */ @@ -737,9 +737,9 @@ ArchFindMember(const char *archive, const char *member, * BSD 4.4 extended AR format: #1/<namelen>, with name as the * first <namelen> bytes of the file */ - if (strncmp(out_arh->AR_NAME, AR_EFMT1, sizeof AR_EFMT1 - 1) == - 0 && - (ch_isdigit(out_arh->AR_NAME[sizeof AR_EFMT1 - 1]))) { + if (strncmp(out_arh->AR_NAME, AR_EFMT1, sizeof AR_EFMT1 - 1) + == 0 && + ch_isdigit(out_arh->AR_NAME[sizeof AR_EFMT1 - 1])) { size_t elen = (size_t)atoi( &out_arh->AR_NAME[sizeof AR_EFMT1 - 1]); char ename[MAXPATHLEN + 1]; @@ -982,7 +982,7 @@ Arch_LibOODate(GNode *gn) if (!GNode_IsTarget(gn) && Lst_IsEmpty(&gn->children)) return false; if ((!Lst_IsEmpty(&gn->children) && gn->youngestChild == NULL) || - (gn->mtime > now) || + gn->mtime > now || (gn->youngestChild != NULL && gn->mtime < gn->youngestChild->mtime)) return true; @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.390 2026/02/08 11:02:03 rillig Exp $ +.\" $NetBSD: make.1,v 1.391 2026/05/08 16:11:21 sjg Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 .\" -.Dd February 8, 2026 +.Dd May 8, 2026 .Dt BMAKE 1 .Os .Sh NAME @@ -556,7 +556,6 @@ except that the effect can be limited to a single line of a script. .It Ic \- in compatibility mode causes any non-zero exit status of the command line to be ignored. -.El .Pp When .Nm @@ -578,6 +577,7 @@ Otherwise affects the entire job; the script stops at the first command line that fails, but the target is not deemed to have failed. +.El .Pp Makefiles should be written so that the mode of .Nm diff --git a/bmake.cat1 b/bmake.cat1 index ecfa7cbadf9a..32fbf8979d8b 100644 --- a/bmake.cat1 +++ b/bmake.cat1 @@ -344,15 +344,17 @@ SSHHEELLLL CCOOMMMMAANNDDSS -- in compatibility mode causes any non-zero exit status of the command line to be ignored. - When bbmmaakkee is run in jobs mode with --jj _m_a_x___j_o_b_s, the entire script for - the target is fed to a single instance of the shell. In compatibility - (non-jobs) mode, each command is run in a separate process. If the - command contains any shell meta characters (`#=|^(){};&<>*?[]:$`\\n'), it - is passed to the shell; otherwise bbmmaakkee attempts direct execution. If a - line starts with `--' and the shell has ErrCtl enabled, failure of the - command line is ignored as in compatibility mode. Otherwise `--' affects - the entire job; the script stops at the first command line that fails, - but the target is not deemed to have failed. + When bbmmaakkee is run in jobs mode with --jj _m_a_x___j_o_b_s, the entire + script for the target is fed to a single instance of the + shell. In compatibility (non-jobs) mode, each command is + run in a separate process. If the command contains any + shell meta characters (`#=|^(){};&<>*?[]:$`\\n'), it is + passed to the shell; otherwise bbmmaakkee attempts direct + execution. If a line starts with `--' and the shell has + ErrCtl enabled, failure of the command line is ignored as + in compatibility mode. Otherwise `--' affects the entire + job; the script stops at the first command line that fails, + but the target is not deemed to have failed. Makefiles should be written so that the mode of bbmmaakkee operation does not change their behavior. For example, any command which uses "cd" or @@ -1880,4 +1882,4 @@ BBUUGGSS attempt to suppress a cascade of unnecessary errors, can result in a seemingly unexplained `*** Error code 6' -FreeBSD 14.3-RELEASE-p9 February 8, 2026 FreeBSD 14.3-RELEASE-p9 +FreeBSD 14.3-RELEASE-p9 May 8, 2026 FreeBSD 14.3-RELEASE-p9 @@ -1,4 +1,4 @@ -/* $NetBSD: cond.c,v 1.378 2025/07/06 07:56:16 rillig Exp $ */ +/* $NetBSD: cond.c,v 1.379 2026/04/06 17:13:54 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -90,7 +90,7 @@ #include "dir.h" /* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */ -MAKE_RCSID("$NetBSD: cond.c,v 1.378 2025/07/06 07:56:16 rillig Exp $"); +MAKE_RCSID("$NetBSD: cond.c,v 1.379 2026/04/06 17:13:54 rillig Exp $"); /* * Conditional expressions conform to this grammar: @@ -623,7 +623,7 @@ done_lhs: /* * The argument to empty() is a variable name, optionally followed by - * variable modifiers. + * modifiers. */ static bool CondParser_FuncCallEmpty(CondParser *par, bool doEval, Token *out_token) @@ -641,8 +641,6 @@ CondParser_FuncCallEmpty(CondParser *par, bool doEval, Token *out_token) p--; /* Make p[1] point to the '('. */ val = Var_Parse(&p, SCOPE_CMDLINE, doEval ? VARE_EVAL : VARE_PARSE); - /* TODO: handle errors */ - if (val.str == var_Error) tok = TOK_ERROR; else { @@ -1013,7 +1011,7 @@ unknown_directive: CondResult Cond_EvalLine(const char *line) { - typedef enum IfState { + typedef enum { /* None of the previous <cond> evaluated to true. */ IFS_INITIAL = 0, @@ -1032,7 +1030,7 @@ Cond_EvalLine(const char *line) } IfState; - static enum IfState *cond_states = NULL; + static IfState *cond_states = NULL; static unsigned cond_states_cap = 128; bool plain; diff --git a/configure b/configure index 9bbdb8d2b36b..2b64187bdd36 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for bmake 20251111. +# Generated by GNU Autoconf 2.72 for bmake 20260406. # # Report bugs to <sjg@NetBSD.org>. # @@ -603,8 +603,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='bmake' PACKAGE_TARNAME='bmake' -PACKAGE_VERSION='20251111' -PACKAGE_STRING='bmake 20251111' +PACKAGE_VERSION='20260406' +PACKAGE_STRING='bmake 20260406' PACKAGE_BUGREPORT='sjg@NetBSD.org' PACKAGE_URL='' @@ -648,6 +648,7 @@ lua filemon_h use_filemon use_meta +save_dollars diff_u diff GCC @@ -720,6 +721,7 @@ with_defshell with_makefile with_meta with_filemon +with_save_dollars with_bmake_strftime with_lua with_machine @@ -1288,7 +1290,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures bmake 20251111 to adapt to many kinds of systems. +'configure' configures bmake 20260406 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1350,7 +1352,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bmake 20251111:";; + short | recursive ) echo "Configuration of bmake 20260406:";; esac cat <<\_ACEOF @@ -1372,7 +1374,8 @@ Optional Packages: --without-makefile disable use of generated makefile --without-meta disable use of meta-mode --with-filemon={no,dev,ktrace,path/filemon.h} indicate filemon method for meta-mode. Path to filemon.h implies dev - --with-bmake-strftime force use of bmake strftime + --with-save-dollars={yes,no} control default for .MAKE.SAVE_DOLLARS - default is "no" + --with-bmake-strftime force use of bmake strftime --without-lua do not use check-expect.lua --with-machine=MACHINE explicitly set MACHINE --with-force-machine=MACHINE set FORCE_MACHINE @@ -1461,7 +1464,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bmake configure 20251111 +bmake configure 20260406 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. @@ -1984,7 +1987,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bmake $as_me 20251111, which was +It was created by bmake $as_me 20260406, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -2900,6 +2903,17 @@ esac esac fi +save_dollars=no + +# Check whether --with-save_dollars was given. +if test ${with_save_dollars+y} +then : + withval=$with_save_dollars; case "${withval}" in +yes|no) MAKE_SAVE_DOLLARS_DEFAULT=${withval} ;; +*) as_fn_error $? "bad value ${withval} given for save_dollars" "$LINENO" 5 ;; +esac +fi + # Check whether --with-bmake_strftime was given. if test ${with_bmake_strftime+y} @@ -7312,6 +7326,7 @@ esac + bm_outfiles="Makefile.config unit-tests/Makefile.config make-bootstrap.sh" if test $use_makefile = yes; then bm_outfiles="makefile $bm_outfiles" @@ -7833,7 +7848,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by bmake $as_me 20251111, which was +This file was extended by bmake $as_me 20260406, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7897,7 +7912,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -bmake config.status 20251111 +bmake config.status 20260406 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" diff --git a/configure.in b/configure.in index f378b57fd14a..8b4bd45af361 100644 --- a/configure.in +++ b/configure.in @@ -1,11 +1,11 @@ dnl dnl RCSid: -dnl $Id: configure.in,v 1.111 2025/11/11 18:43:59 sjg Exp $ +dnl $Id: configure.in,v 1.114 2026/04/13 18:40:26 sjg Exp $ dnl dnl Process this file with autoconf to produce a configure script dnl AC_PREREQ([2.71]) -AC_INIT([bmake],[20251111],[sjg@NetBSD.org]) +AC_INIT([bmake],[20260406],[sjg@NetBSD.org]) AC_CONFIG_HEADERS(config.h) dnl make srcdir absolute @@ -135,9 +135,23 @@ dev) ;; *) filemon_h=no;; esac ]) +dnl +dnl in 2020 NetBSD make changed the handling of $$ in := +dnl bmake introduced .MAKE.SAVE_DOLLARS defaulting to "no" to retain +dnl the traditional behavior. +dnl Use "yes" to be compatible with NetBSD make. +dnl +save_dollars=no +AC_ARG_WITH(save_dollars, +[ --with-save-dollars={yes,no} control default for .MAKE.SAVE_DOLLARS - default is "no"], +[case "${withval}" in +yes|no) MAKE_SAVE_DOLLARS_DEFAULT=${withval} ;; +*) AC_MSG_ERROR(bad value ${withval} given for save_dollars) ;; +esac]) +dnl dnl some systems have broken/incomplete strftime AC_ARG_WITH(bmake_strftime, -[ --with-bmake-strftime force use of bmake strftime], +[ --with-bmake-strftime force use of bmake strftime], [case "${withval}" in yes|no) bmake_strftime=$withval;; esac]) @@ -608,6 +622,7 @@ AC_SUBST(INSTALL) AC_SUBST(GCC) AC_SUBST(diff) AC_SUBST(diff_u) +AC_SUBST(save_dollars) AC_SUBST(use_meta) AC_SUBST(use_filemon) AC_SUBST(filemon_h) @@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.297 2025/06/12 18:51:05 rillig Exp $ */ +/* $NetBSD: dir.c,v 1.298 2026/04/06 17:13:54 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -132,7 +132,7 @@ #include "job.h" /* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */ -MAKE_RCSID("$NetBSD: dir.c,v 1.297 2025/06/12 18:51:05 rillig Exp $"); +MAKE_RCSID("$NetBSD: dir.c,v 1.298 2026/04/06 17:13:54 rillig Exp $"); /* * A search path is a list of CachedDir structures. A CachedDir has in it the @@ -1123,7 +1123,7 @@ FindFileAbsolute(SearchPath *path, bool seenDotLast, DEBUG0(DIR, " Trying exact path matches...\n"); if (!seenDotLast && cur != NULL && - ((file = DirLookupAbs(cur, name, base)) != NULL)) + (file = DirLookupAbs(cur, name, base)) != NULL) goto found; for (ln = path->dirs.first; ln != NULL; ln = ln->next) { @@ -1135,7 +1135,7 @@ FindFileAbsolute(SearchPath *path, bool seenDotLast, } if (seenDotLast && cur != NULL && - ((file = DirLookupAbs(cur, name, base)) != NULL)) + (file = DirLookupAbs(cur, name, base)) != NULL) goto found; return false; @@ -1,4 +1,4 @@ -/* $NetBSD: for.c,v 1.186 2025/06/28 22:39:27 rillig Exp $ */ +/* $NetBSD: for.c,v 1.187 2026/04/06 17:13:54 rillig Exp $ */ /* * Copyright (c) 1992, The Regents of the University of California. @@ -50,15 +50,15 @@ * that, the body is treated like a file from an .include directive. * * Interface: - * For_Eval Evaluate the loop in the passed line. + * For_Eval Evaluate the loop directive in a line. * - * For_Run Run accumulated loop + * For_Run Run the previously accumulated loop. */ #include "make.h" /* "@(#)for.c 8.1 (Berkeley) 6/6/93" */ -MAKE_RCSID("$NetBSD: for.c,v 1.186 2025/06/28 22:39:27 rillig Exp $"); +MAKE_RCSID("$NetBSD: for.c,v 1.187 2026/04/06 17:13:54 rillig Exp $"); typedef struct ForLoop { @@ -226,13 +226,13 @@ IsEndfor(const char *p) } /* - * Evaluate the for loop in the passed line. The line looks like this: + * Evaluate the for loop in the line, which has this form: * .for <varname...> in <value...> * * Results: - * 0 not a .for directive * 1 found a .for directive - * -1 erroneous .for directive + * 0 not a .for directive + * -1 misplaced .endfor directive */ int For_Eval(const char *line) @@ -1,4 +1,4 @@ -/* $NetBSD: job.c,v 1.528 2026/03/03 20:12:20 sjg Exp $ */ +/* $NetBSD: job.c,v 1.529 2026/04/06 17:13:54 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -137,7 +137,7 @@ #include "trace.h" /* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: job.c,v 1.528 2026/03/03 20:12:20 sjg Exp $"); +MAKE_RCSID("$NetBSD: job.c,v 1.529 2026/04/06 17:13:54 rillig Exp $"); #ifdef USE_SELECT @@ -1301,8 +1301,7 @@ JobFinish (Job *job, WAIT_T status) DEBUG3(JOB, "JobFinish: target %s, pid %d, status %#x\n", job->node->name, job->pid, status); - if ((WIFEXITED(status) && - ((WEXITSTATUS(status) != 0 && !job->ignerr))) || + if ((WIFEXITED(status) && WEXITSTATUS(status) != 0 && !job->ignerr) || WIFSIGNALED(status)) { /* Finished because of an error. */ @@ -1346,7 +1345,7 @@ JobFinish (Job *job, WAIT_T status) Trace_Log(JOBEND, job); if (!job->special) { if (WAIT_STATUS(status) != 0 || - (aborting == ABORT_ERROR) || aborting == ABORT_INTERRUPT) + aborting == ABORT_ERROR || aborting == ABORT_INTERRUPT) return_job_token = true; } @@ -1922,7 +1921,7 @@ again: SwitchOutputTo(job->node); #ifdef USE_META if (useMeta) - meta_job_output(job, p, (i < max) ? i : max); + meta_job_output(job, p, i < max ? i : max); #endif (void)fwrite(p, 1, (size_t)(job->outBuf + i - p), stdout); (void)fflush(stdout); @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.668 2026/03/13 04:22:03 sjg Exp $ */ +/* $NetBSD: main.c,v 1.669 2026/04/06 17:13:54 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -111,7 +111,7 @@ #include "trace.h" /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: main.c,v 1.668 2026/03/13 04:22:03 sjg Exp $"); +MAKE_RCSID("$NetBSD: main.c,v 1.669 2026/04/06 17:13:54 rillig Exp $"); #if defined(MAKE_NATIVE) __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " "The Regents of the University of California. " @@ -417,7 +417,7 @@ MainParseArgJobs(const char *arg) double d; if (*p == 'C') - d = (opts.maxJobs > 0) ? opts.maxJobs : 1; + d = opts.maxJobs > 0 ? opts.maxJobs : 1; else if (*p == '.') { d = strtod(arg, &end); p = end; diff --git a/make-bootstrap.sh.in b/make-bootstrap.sh.in index d4f3c0a39c89..c73a9cdcf967 100755 --- a/make-bootstrap.sh.in +++ b/make-bootstrap.sh.in @@ -20,7 +20,9 @@ MDEFS="-DMAKE_VERSION=\"$MAKE_VERSION\" \ -D@force_machine@MACHINE=\"@machine@\" \ -D@force_machine_arch@MACHINE_ARCH=\"@machine_arch@\" \ -D@force_make_os@MAKE_OS=\"@make_os@\" \ --D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"" +-D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\" \ +-DMAKE_SAVE_DOLLARS_DEFAULT=\"@save_dollars@\" \ +" LDFLAGS="@LDFLAGS@" @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.390 2026/02/08 11:02:03 rillig Exp $ +.\" $NetBSD: make.1,v 1.391 2026/05/08 16:11:21 sjg Exp $ .\" .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 .\" -.Dd February 8, 2026 +.Dd May 8, 2026 .Dt MAKE 1 .Os .Sh NAME @@ -556,7 +556,6 @@ except that the effect can be limited to a single line of a script. .It Ic \- in compatibility mode causes any non-zero exit status of the command line to be ignored. -.El .Pp When .Nm @@ -578,6 +577,7 @@ Otherwise affects the entire job; the script stops at the first command line that fails, but the target is not deemed to have failed. +.El .Pp Makefiles should be written so that the mode of .Nm @@ -1,4 +1,4 @@ -/* $NetBSD: make.c,v 1.274 2026/02/10 18:53:34 sjg Exp $ */ +/* $NetBSD: make.c,v 1.275 2026/04/06 17:13:54 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -107,7 +107,7 @@ #endif /* "@(#)make.c 8.1 (Berkeley) 6/6/93" */ -MAKE_RCSID("$NetBSD: make.c,v 1.274 2026/02/10 18:53:34 sjg Exp $"); +MAKE_RCSID("$NetBSD: make.c,v 1.275 2026/04/06 17:13:54 rillig Exp $"); /* Sequence # to detect recursion. */ static unsigned checked_seqno = 1; @@ -211,7 +211,7 @@ GNode_FprintDetails(FILE *f, const char *prefix, const GNode *gn, bool GNode_ShouldExecute(GNode *gn) { - return !((gn->type & OP_MAKE) + return !(gn->type & OP_MAKE ? opts.noRecursiveExecute : opts.noExecute); } @@ -315,9 +315,8 @@ GNode_IsOODate(GNode *gn) * always out of date if no children and :: target * or nonexistent. */ - oodate = (gn->mtime == 0 || Arch_LibOODate(gn) || - (gn->youngestChild == NULL && - (gn->type & OP_DOUBLEDEP))); + oodate = gn->mtime == 0 || Arch_LibOODate(gn) || + (gn->youngestChild == NULL && (gn->type & OP_DOUBLEDEP)); } else if (gn->type & OP_JOIN) { /* * A target with the .JOIN attribute is only considered @@ -863,7 +862,7 @@ MakeAddAllSrc(GNode *cgn, GNode *pgn) if (cgn->made == MADE) Var_Append(pgn, OODATE, child); - } else if ((pgn->mtime < cgn->mtime) || + } else if (pgn->mtime < cgn->mtime || (cgn->mtime >= now && cgn->made == MADE)) { /* * It goes in the OODATE variable if the parent is @@ -1,4 +1,4 @@ -/* $NetBSD: make.h,v 1.365 2026/03/13 04:22:03 sjg Exp $ */ +/* $NetBSD: make.h,v 1.366 2026/04/06 17:13:54 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -294,7 +294,7 @@ typedef enum GNodeType { /* * 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. Each + * groups is executed on its own, independently of the others. Each * individual dependency group is called a cohort. */ OP_DOUBLEDEP = 1 << 2, @@ -427,11 +427,11 @@ typedef struct GNodeFlags { bool doneCycle:1; } GNodeFlags; -typedef struct List StringList; -typedef struct ListNode StringListNode; +typedef List StringList; +typedef ListNode StringListNode; -typedef struct List GNodeList; -typedef struct ListNode GNodeListNode; +typedef List GNodeList; +typedef ListNode GNodeListNode; typedef struct SearchPath { List /* of CachedDir */ dirs; @@ -616,7 +616,7 @@ extern GNode *defaultNode; * by makefiles. */ extern GNode *SCOPE_INTERNAL; -/* Variables defined in a global scope, e.g in the makefile itself. */ +/* Variables defined in a global scope, e.g. in the makefile itself. */ extern GNode *SCOPE_GLOBAL; /* Variables defined on the command line. */ extern GNode *SCOPE_CMDLINE; @@ -1,4 +1,4 @@ -/* $NetBSD: meta.c,v 1.220 2026/02/10 18:53:34 sjg Exp $ */ +/* $NetBSD: meta.c,v 1.221 2026/04/06 17:13:54 rillig Exp $ */ /* * Implement 'meta' mode. @@ -458,8 +458,6 @@ meta_create(BuildMon *pbm, GNode *gn) fprintf(stdout, "%s\n", mp); free(mp); } - /* Get the basename of the target */ - cp = str_basename(tname); fflush(stdout); @@ -1511,7 +1509,7 @@ meta_oodate(GNode *gn, bool oodate) if (p != NULL && !hasOODATE && !(gn->type & OP_NOMETA_CMP) && - (meta_cmd_cmp(gn, p, cmd, cmp_filter) != 0)) { + meta_cmd_cmp(gn, p, cmd, cmp_filter) != 0) { DEBUG4(META, "%s:%u: a build command has changed\n%s\nvs\n%s\n", fname, lineno, p, cmd); if (!metaIgnoreCMDs) @@ -1555,7 +1553,7 @@ meta_oodate(GNode *gn, bool oodate) /* if target is in .CURDIR we do not need a meta file */ if (gn->path != NULL && (cp = strrchr(gn->path, '/')) != NULL && - (cp > gn->path)) { + cp > gn->path) { if (strncmp(curdir, gn->path, (size_t)(cp - gn->path)) != 0) { cp = NULL; /* not in .CURDIR */ } diff --git a/mk/ChangeLog b/mk/ChangeLog index 0322cae09232..a8805fa774bf 100644 --- a/mk/ChangeLog +++ b/mk/ChangeLog @@ -1,3 +1,29 @@ +2026-05-09 Simon J Gerraty <sjg@beast.crufty.net> + + * gendirdeps.mk: also apply ':S,/$,,' and ':C,/(\.[^.]*)$,\1,' + when setting DIRDEPS prior to saving. + + * dirdeps.mk: when debugging it is handy to be able to skip + recursing so if DEBUG_DIRDEPS contains 'norecurse' we will only + process the immediate DIRDEPS. + Also if DEBUG_DIRDEPS contains '-V' we process sections normally + skipped when doing 'make -V'. + o ensure we do not get duplicate build dirs due to someone + adding a trailing '/' or '/.${TARGET_SPEC}' to a DIRDEPS entry. + Add ':S,/$,,' when setting '__depdirs' and + add ':C,/(\.[^.]*)$,\1,' when setting '__qual_depdirs'. + +2026-04-24 Simon J Gerraty <sjg@beast.crufty.net> + + * install-mk (MK_VERSION): 20260424 + + * Use MK_META_AUTODEP to control use of meta.autodep.mk + so it can be used independently of MK_DIRDEPS_BUILD for + bootstrapping. + + * sys.vars.mk (M_type): use :sh rather than :sh1 to avoid + surprises in a .for loop. + 2026-03-12 Simon J Gerraty <sjg@beast.crufty.net> * install-mk (MK_VERSION): 20260313 diff --git a/mk/dirdeps.mk b/mk/dirdeps.mk index 9f51713cc5d5..abd3407eddf4 100644 --- a/mk/dirdeps.mk +++ b/mk/dirdeps.mk @@ -1,8 +1,8 @@ -# $Id: dirdeps.mk,v 1.176 2026/02/23 21:37:10 sjg Exp $ +# $Id: dirdeps.mk,v 1.178 2026/05/09 20:33:46 sjg Exp $ # SPDX-License-Identifier: BSD-2-Clause # -# Copyright (c) 2010-2023, Simon J. Gerraty +# Copyright (c) 2010-2026, Simon J. Gerraty # Copyright (c) 2010-2018, Juniper Networks, Inc. # All rights reserved. # @@ -322,6 +322,12 @@ _debug_search = 1 .else _debug_search = 0 .endif +.if ${DEBUG_DIRDEPS:Mno*recurse} != "" +BUILD_DIRDEPS_RECURSE = no +.endif +.if ${DEBUG_DIRDEPS:M-V} != "" +_V_READ_DIRDEPS = yes +.endif # First off, we want to know what ${MACHINE} to build for. # This can be complicated if we are using a mixture of ${MACHINE} specific @@ -720,12 +726,12 @@ DEP_DIRDEPS_BUILD_DIR_FILTER = u .endif # this is what we start with -__depdirs := ${DIRDEPS:${NSkipDir}:${DEP_DIRDEPS_FILTER:ts:}:C,//+,/,g:O:u:@d@${SRCTOP}/$d@} +__depdirs := ${DIRDEPS:${NSkipDir}:${DEP_DIRDEPS_FILTER:ts:}:C,//+,/,g:S,/$,,:O:u:@d@${SRCTOP}/$d@} # some entries may be qualified with .<machine> or .<target_spec> # we can tell the unqualified ones easily - because they exist __unqual_depdirs := ${__depdirs:@d@${exists($d):?$d:}@} -__qual_depdirs := ${__depdirs:${__unqual_depdirs:Uno:${M_ListToSkip}}} +__qual_depdirs := ${__depdirs:${__unqual_depdirs:Uno:${M_ListToSkip}}:C,/(\.[^.]*)$,\1,} .if ${DEP_RELDIR} == ${_DEP_RELDIR} # if it was called out - we likely need it. @@ -750,16 +756,13 @@ _build_dirs += \ ${_machines:Nhost*:@m@${__unqual_depdirs:@d@$d.$m@}@} # qualify everything now -.if ${_debug_reldir} -.info _build_dirs=${_build_dirs:${DEBUG_DIRDEPS_LIST_FILTER:U:N/:ts:}} -.endif # make sure we do not mess with qualifying "host" entries _build_dirs := ${_build_dirs:M*.host*:${M_dep_qual_fixes.host:ts:}} \ ${_build_dirs:N*.host*:${M_dep_qual_fixes:ts:}} # some filters can only be applied now _build_dirs := ${_build_dirs:${DEP_DIRDEPS_BUILD_DIR_FILTER:ts:}:O:u} .if ${_debug_reldir} -.info _build_dirs=${_build_dirs:${DEBUG_DIRDEPS_LIST_FILTER:U:N/:ts:}} +.info _build_dirs=${_build_dirs:S,^${SRCTOP}/,,:${DEBUG_DIRDEPS_LIST_FILTER:U:N/:ts:}} .endif .endif # empty DIRDEPS @@ -796,7 +799,7 @@ dirdeps: ${_build_all_dirs} ${_build_all_dirs}: _DIRDEP_USE .if ${_debug_reldir} -.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs:S,^${SRCTOP}/,,:${DEBUG_DIRDEPS_LIST_FILTER:U:N/:ts:}} +.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_all_dirs:S,^${SRCTOP}/,,:${DEBUG_DIRDEPS_LIST_FILTER:U:N/:ts:}} .endif # this builds the dependency graph @@ -863,6 +866,7 @@ DIRDEPS_EXPORT_VARS = DEP_EXPORT_VARS = .endif +.if ${BUILD_DIRDEPS_RECURSE:Uyes} != "no" # Now find more dependencies - and recurse. .for d in ${_build_all_dirs} .if !target(_dirdeps_checked.$d) @@ -914,6 +918,7 @@ DIRDEPS = .endif .endif .endfor +.endif .endif # -V .endif # BUILD_DIRDEPS diff --git a/mk/gendirdeps.mk b/mk/gendirdeps.mk index ab1786f3603f..85af65668407 100644 --- a/mk/gendirdeps.mk +++ b/mk/gendirdeps.mk @@ -1,8 +1,8 @@ -# $Id: gendirdeps.mk,v 1.54 2025/08/12 21:36:43 sjg Exp $ +# $Id: gendirdeps.mk,v 1.55 2026/05/09 20:46:13 sjg Exp $ # SPDX-License-Identifier: BSD-2-Clause # -# Copyright (c) 2011-2025, Simon J. Gerraty +# Copyright (c) 2011-2026, Simon J. Gerraty # Copyright (c) 2010-2018, Juniper Networks, Inc. # All rights reserved. # @@ -331,7 +331,7 @@ DIRDEPS += \ # what modifiers do we allow in GENDIRDEPS_FILTER GENDIRDEPS_FILTER_MASK += @CMNS -DIRDEPS := ${DIRDEPS:${GENDIRDEPS_FILTER:UNno:M[${GENDIRDEPS_FILTER_MASK:O:u:ts}]*:ts:}:C,//+,/,g:O:u} +DIRDEPS := ${DIRDEPS:${GENDIRDEPS_FILTER:UNno:M[${GENDIRDEPS_FILTER_MASK:O:u:ts}]*:ts:}:C,//+,/,g:S,/$,,:C,/(\.[^.]+)$,\1,:O:u} .if ${_debug.gendirdeps} .info ${RELDIR}: M2D_OBJROOTS=${M2D_OBJROOTS} @@ -353,7 +353,7 @@ src_dirdep_list = \ SRC_DIRDEPS = \ ${src_dirdep_list:N${RELDIR}:N${RELDIR}/*:C,(/h)/.*,,} -SRC_DIRDEPS := ${SRC_DIRDEPS:${GENDIRDEPS_SRC_FILTER:UN/*:ts:}:C,//+,/,g:O:u} +SRC_DIRDEPS := ${SRC_DIRDEPS:${GENDIRDEPS_SRC_FILTER:UN/*:ts:}:C,//+,/,g:S,/$,,:C,/(\.[^.]+)$,\1,:O:u} # if you want to capture SRC_DIRDEPS in .MAKE.DEPENDFILE put # SRC_DIRDEPS_FILE = ${_DEPENDFILE} diff --git a/mk/install-mk b/mk/install-mk index 20b24ca92ee0..c272b63f2b54 100644 --- a/mk/install-mk +++ b/mk/install-mk @@ -59,7 +59,7 @@ # Simon J. Gerraty <sjg@crufty.net> # RCSid: -# $Id: install-mk,v 1.274 2026/03/13 05:13:00 sjg Exp $ +# $Id: install-mk,v 1.275 2026/04/24 19:56:48 sjg Exp $ # # @(#) Copyright (c) 1994-2025 Simon J. Gerraty # @@ -69,7 +69,7 @@ # sjg@crufty.net # -MK_VERSION=20260313 +MK_VERSION=20260424 OWNER= GROUP= MODE=444 diff --git a/mk/lib.mk b/mk/lib.mk index 708a2a1994cc..68d34ada0e0c 100644 --- a/mk/lib.mk +++ b/mk/lib.mk @@ -1,4 +1,4 @@ -# $Id: lib.mk,v 1.86 2025/05/20 17:19:37 sjg Exp $ +# $Id: lib.mk,v 1.87 2026/04/24 19:56:01 sjg Exp $ # should be set properly in sys.mk _this ?= ${.PARSEFILE:S,bsd.,,} @@ -251,7 +251,7 @@ DLLIB ?= -ldl # is a waste of time, this tells meta.autodep.mk to just pick one # (typically ${PICO}) # yes, 42 is a random number. -.if ${MK_DIRDEPS_BUILD} == "yes" && ${SRCS:Uno:[\#]} > 42 +.if ${MK_META_AUTODEP} == "yes" && ${SRCS:Uno:[\#]} > 42 OPTIMIZE_OBJECT_META_FILES ?= yes .endif diff --git a/mk/meta.sys.mk b/mk/meta.sys.mk index c5fcdaa801e4..846f623e60d5 100644 --- a/mk/meta.sys.mk +++ b/mk/meta.sys.mk @@ -1,4 +1,4 @@ -# $Id: meta.sys.mk,v 1.57 2025/08/09 22:42:24 sjg Exp $ +# $Id: meta.sys.mk,v 1.58 2026/04/24 19:56:01 sjg Exp $ # # @(#) Copyright (c) 2010-2023, Simon J. Gerraty # @@ -66,7 +66,7 @@ META_MODE += silent=yes .endif .endif -.if ${MK_DIRDEPS_BUILD:Uno} == "yes" +.if ${MK_META_AUTODEP:Uno} == "yes" .if !defined(META2DEPS) .if defined(PYTHON) && exists(${PYTHON}) @@ -79,6 +79,7 @@ META2DEPS := ${META2DEPS} .export META2DEPS .endif +.if ${MK_DIRDEPS_BUILD:Uno} == "yes" MAKE_PRINT_VAR_ON_ERROR += \ .ERROR_TARGET \ .ERROR_EXIT \ @@ -89,6 +90,7 @@ MAKE_PRINT_VAR_ON_ERROR += \ MK_META_ERROR_TARGET = yes .endif +.endif .if ${MK_META_ERROR_TARGET:Uno} == "yes" @@ -121,7 +123,9 @@ _metaError: .NOMETA .NOTMAIN # Are we, after all, in meta mode? .if ${.MAKE.MODE:Uno:Mmeta*} != "" +.if ${MK_META_AUTODEP:Uno} == "yes" MKDEP_MK ?= meta.autodep.mk +.endif # we can afford to use cookies to prevent some targets # re-running needlessly diff --git a/mk/sys.dependfile.mk b/mk/sys.dependfile.mk index 84c5c898b6af..b7515cc21bd4 100644 --- a/mk/sys.dependfile.mk +++ b/mk/sys.dependfile.mk @@ -1,4 +1,4 @@ -# $Id: sys.dependfile.mk,v 1.12 2025/08/09 22:42:24 sjg Exp $ +# $Id: sys.dependfile.mk,v 1.13 2026/04/24 19:56:01 sjg Exp $ # # @(#) Copyright (c) 2012-2023, Simon J. Gerraty # @@ -11,7 +11,7 @@ .if !target(__${.PARSEFILE}__) __${.PARSEFILE}__: .NOTMAIN -# This only makes sense for DIRDEPS_BUILD. +# This only makes sense for DIRDEPS_BUILD or META_AUTODEP. # This allows a mixture of auto generated as well as manually edited # dependency files, which can be differentiated by their names. # As per dirdeps.mk we only require: diff --git a/mk/sys.dirdeps.mk b/mk/sys.dirdeps.mk index 2d68c0490d81..bba3bfb9c678 100644 --- a/mk/sys.dirdeps.mk +++ b/mk/sys.dirdeps.mk @@ -1,4 +1,4 @@ -# $Id: sys.dirdeps.mk,v 1.17 2026/02/15 17:04:27 sjg Exp $ +# $Id: sys.dirdeps.mk,v 1.20 2026/04/24 19:56:01 sjg Exp $ # # @(#) Copyright (c) 2012-2023, Simon J. Gerraty # @@ -15,6 +15,7 @@ # Include from [local.]sys.mk - if doing DIRDEPS_BUILD # we should not be here otherwise MK_DIRDEPS_BUILD ?= yes +MK_META_AUTODEP ?= yes # these are all implied MK_AUTO_OBJ ?= yes MK_META_MODE ?= yes @@ -192,7 +193,7 @@ RELSRCTOP?= ${RELTOP} .undef .MAKE.DEPENDFILE .endif # just in case -.MAKE.DEPENDFILE ?= Makefile.depend +.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFIX} # Makefile.depend* often refer to DEP_MACHINE etc, # we need defaults for both first include in a leaf dir diff --git a/mk/sys.mk b/mk/sys.mk index 5b8d55e53604..600095844bd0 100644 --- a/mk/sys.mk +++ b/mk/sys.mk @@ -1,4 +1,4 @@ -# $Id: sys.mk,v 1.67 2026/02/23 21:37:10 sjg Exp $ +# $Id: sys.mk,v 1.68 2026/04/24 19:56:01 sjg Exp $ # # @(#) Copyright (c) 2003-2023, Simon J. Gerraty # @@ -90,6 +90,7 @@ OPTIONS_DEFAULT_NO += \ OPTIONS_DEFAULT_DEPENDENT += \ AUTO_OBJ/DIRDEPS_BUILD \ + META_AUTODEP/DIRDEPS_BUILD \ META_ERROR_TARGET/DIRDEPS_BUILD \ META_MODE/DIRDEPS_BUILD \ STAGING/DIRDEPS_BUILD \ @@ -105,7 +106,12 @@ OPTIONS_DEFAULT_DEPENDENT += \ .endif .if ${MK_META_MODE:Uno} == "yes" .-include <meta.sys.mk> -.MAKE.MODE ?= meta verbose {META_MODE} +.MAKE.MODE ?= meta verbose ${META_MODE} +.elif ${MK_META_AUTODEP:Uno} == "yes" +MK_META_AUTODEP = no +.if ${.MAKE.LEVEL} == 0 +.warning ignoring META_AUTODEP: requires META_MODE +.endif .endif # make sure we have a harmless value .MAKE.MODE ?= normal diff --git a/mk/sys.vars.mk b/mk/sys.vars.mk index 7d9cd2f6641f..2a6472c58668 100644 --- a/mk/sys.vars.mk +++ b/mk/sys.vars.mk @@ -1,4 +1,4 @@ -# $Id: sys.vars.mk,v 1.27 2026/03/13 16:02:44 sjg Exp $ +# $Id: sys.vars.mk,v 1.28 2026/04/24 19:50:26 sjg Exp $ # # @(#) Copyright (c) 2003-2023, Simon J. Gerraty # @@ -69,7 +69,7 @@ M_sh1 = sh1 .endif # AUTOCONF := ${autoconf:L:${M_whence}} -M_type = @x@(${_type_sh:Utype} $x) 2> /dev/null; echo;@:${M_sh1:Ush}:[0]:N* found*:[@]:C,[()],,g +M_type = @x@(${_type_sh:Utype} $x) 2> /dev/null; echo;@:sh:[0]:N* found*:[@]:C,[()],,g M_whence = ${M_type}:M/*:[1] # produce similar output to jot(1) or seq(1) @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.755 2026/02/10 18:53:34 sjg Exp $ */ +/* $NetBSD: parse.c,v 1.756 2026/04/06 17:13:55 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -110,7 +110,7 @@ #include "pathnames.h" /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: parse.c,v 1.755 2026/02/10 18:53:34 sjg Exp $"); +MAKE_RCSID("$NetBSD: parse.c,v 1.756 2026/04/06 17:13:55 rillig Exp $"); /* Detects a multiple-inclusion guard in a makefile. */ typedef enum { @@ -724,7 +724,7 @@ TryApplyDependencyOperator(GNode *gn, GNodeType op) * operator also defines a dependency, they must match. */ if ((op & OP_OPMASK) && (gn->type & OP_OPMASK) && - ((op & OP_OPMASK) != (gn->type & OP_OPMASK))) { + (op & OP_OPMASK) != (gn->type & OP_OPMASK)) { Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); return false; @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.1179 2026/03/13 04:22:03 sjg Exp $ */ +/* $NetBSD: var.c,v 1.1180 2026/04/06 17:13:55 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -145,7 +145,7 @@ #endif /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: var.c,v 1.1179 2026/03/13 04:22:03 sjg Exp $"); +MAKE_RCSID("$NetBSD: var.c,v 1.1180 2026/04/06 17:13:55 rillig Exp $"); /* * Variables are defined using one of the VAR=value assignments. Their @@ -3397,8 +3397,8 @@ SubNumAsc(const void *sa, const void *sb) { NUM_TYPE a, b; - a = num_val(*((const Substring *)sa)); - b = num_val(*((const Substring *)sb)); + a = num_val(*(const Substring *)sa); + b = num_val(*(const Substring *)sb); return a > b ? 1 : b > a ? -1 : 0; } @@ -4428,7 +4428,7 @@ CheckVarname(Substring name) ch_isprint(*p) ? "Invalid character \"%c\" in variable name \"%.*s\"" : "Invalid character \"\\x%02x\" in variable name \"%.*s\"", - (int)(*p), + (int)*p, (int)Substring_Length(name), name.start); } } @@ -4909,8 +4909,7 @@ Var_Stats(void) static int StrAsc(const void *sa, const void *sb) { - return strcmp( - *((const char *const *)sa), *((const char *const *)sb)); + return strcmp(*(const char *const *)sa, *(const char *const *)sb); } |
