From 023e89e5efa694577b481488bb5ea251d3ec1966 Mon Sep 17 00:00:00 2001 From: "Simon J. Gerraty" Date: Mon, 20 Apr 2015 03:45:54 +0000 Subject: Import bmake-20150418 --- ChangeLog | 70 +++++++- FILES | 97 +++++++---- Makefile | 10 +- PSD.doc/Makefile | 6 +- PSD.doc/tutorial.ms | 12 +- bmake.1 | 210 ++++++++++++++++++------ bmake.cat1 | 173 +++++++++++++------- compat.c | 6 +- configure | 2 + configure.in | 4 +- job.c | 26 +-- lst.h | 2 +- lst.lib/lstInt.h | 2 +- lst.lib/lstRemove.c | 6 +- main.c | 22 +-- make.1 | 210 ++++++++++++++++++------ make.c | 8 +- make.h | 3 +- meta.c | 89 +++++++--- mk/ChangeLog | 108 +++++++++++++ mk/FILES | 4 + mk/auto.dep.mk | 4 +- mk/auto.obj.mk | 9 +- mk/autodep.mk | 7 +- mk/cython.mk | 96 +++++++++++ mk/dep.mk | 14 +- mk/dirdeps.mk | 161 +++++++++++++++++-- mk/gendirdeps.mk | 13 +- mk/install-mk | 4 +- mk/links.mk | 13 +- mk/manifest.mk | 66 ++++++++ mk/meta.autodep.mk | 5 +- mk/meta.stage.mk | 39 ++++- mk/meta.sys.mk | 20 ++- mk/meta2deps.py | 220 ++++++++++++++----------- mk/meta2deps.sh | 30 +++- mk/mk-files.txt | 20 ++- mk/mkopt.sh | 94 +++++++++++ mk/own.mk | 4 +- mk/sys.dependfile.mk | 8 +- mk/whats.mk | 63 ++++++++ nonints.h | 2 +- parse.c | 87 +++++++++- suff.c | 6 +- targ.c | 6 +- unit-tests/Makefile.in | 108 +++++++++---- unit-tests/comment | 31 ---- unit-tests/comment.exp | 5 + unit-tests/comment.mk | 31 ++++ unit-tests/cond1 | 109 ------------- unit-tests/cond1.exp | 23 +++ unit-tests/cond1.mk | 109 +++++++++++++ unit-tests/doterror | 20 --- unit-tests/doterror.exp | 9 ++ unit-tests/doterror.mk | 20 +++ unit-tests/dotwait | 61 ------- unit-tests/dotwait.exp | 30 ++++ unit-tests/dotwait.mk | 61 +++++++ unit-tests/error | 10 -- unit-tests/error.exp | 4 + unit-tests/error.mk | 10 ++ unit-tests/escape.exp | 104 ++++++++++++ unit-tests/escape.mk | 246 ++++++++++++++++++++++++++++ unit-tests/export | 22 --- unit-tests/export-all | 23 --- unit-tests/export-all.exp | 12 ++ unit-tests/export-all.mk | 23 +++ unit-tests/export-env | 24 --- unit-tests/export-env.exp | 9 ++ unit-tests/export-env.mk | 24 +++ unit-tests/export.exp | 6 + unit-tests/export.mk | 22 +++ unit-tests/forloop | 45 ------ unit-tests/forloop.exp | 19 +++ unit-tests/forloop.mk | 45 ++++++ unit-tests/forsubst | 10 -- unit-tests/forsubst.exp | 2 + unit-tests/forsubst.mk | 10 ++ unit-tests/hash | 18 --- unit-tests/hash.exp | 9 ++ unit-tests/hash.mk | 18 +++ unit-tests/impsrc.exp | 13 ++ unit-tests/impsrc.mk | 43 +++++ unit-tests/misc | 16 -- unit-tests/misc.exp | 1 + unit-tests/misc.mk | 16 ++ unit-tests/moderrs | 31 ---- unit-tests/moderrs.exp | 16 ++ unit-tests/moderrs.mk | 31 ++++ unit-tests/modmatch | 25 --- unit-tests/modmatch.exp | 17 ++ unit-tests/modmatch.mk | 25 +++ unit-tests/modmisc | 38 ----- unit-tests/modmisc.exp | 10 ++ unit-tests/modmisc.mk | 38 +++++ unit-tests/modorder | 22 --- unit-tests/modorder.exp | 11 ++ unit-tests/modorder.mk | 22 +++ unit-tests/modts | 43 ----- unit-tests/modts.exp | 33 ++++ unit-tests/modts.mk | 43 +++++ unit-tests/modword | 151 ----------------- unit-tests/modword.exp | 122 ++++++++++++++ unit-tests/modword.mk | 151 +++++++++++++++++ unit-tests/order | 20 --- unit-tests/order.exp | 4 + unit-tests/order.mk | 20 +++ unit-tests/phony-end | 9 -- unit-tests/phony-end.exp | 6 + unit-tests/phony-end.mk | 9 ++ unit-tests/posix | 24 --- unit-tests/posix.exp | 23 +++ unit-tests/posix.mk | 24 +++ unit-tests/posix1.exp | 185 +++++++++++++++++++++ unit-tests/posix1.mk | 184 +++++++++++++++++++++ unit-tests/qequals | 8 - unit-tests/qequals.exp | 2 + unit-tests/qequals.mk | 8 + unit-tests/suffixes.exp | 35 ++++ unit-tests/suffixes.mk | 89 ++++++++++ unit-tests/sunshcmd | 10 -- unit-tests/sunshcmd.exp | 4 + unit-tests/sunshcmd.mk | 10 ++ unit-tests/sysv | 26 --- unit-tests/sysv.exp | 7 + unit-tests/sysv.mk | 26 +++ unit-tests/ternary | 8 - unit-tests/ternary.exp | 10 ++ unit-tests/ternary.mk | 8 + unit-tests/test.exp | 383 -------------------------------------------- unit-tests/unexport | 8 - unit-tests/unexport-env | 14 -- unit-tests/unexport-env.exp | 2 + unit-tests/unexport-env.mk | 14 ++ unit-tests/unexport.exp | 4 + unit-tests/unexport.mk | 8 + unit-tests/varcmd | 49 ------ unit-tests/varcmd.exp | 9 ++ unit-tests/varcmd.mk | 49 ++++++ unit-tests/varmisc.exp | 2 + unit-tests/varmisc.mk | 8 + unit-tests/varshell.exp | 10 ++ unit-tests/varshell.mk | 19 +++ var.c | 67 ++++---- 144 files changed, 3958 insertions(+), 1758 deletions(-) create mode 100644 mk/cython.mk create mode 100644 mk/manifest.mk create mode 100755 mk/mkopt.sh create mode 100644 mk/whats.mk delete mode 100644 unit-tests/comment create mode 100644 unit-tests/comment.exp create mode 100644 unit-tests/comment.mk delete mode 100644 unit-tests/cond1 create mode 100644 unit-tests/cond1.exp create mode 100644 unit-tests/cond1.mk delete mode 100644 unit-tests/doterror create mode 100644 unit-tests/doterror.exp create mode 100644 unit-tests/doterror.mk delete mode 100644 unit-tests/dotwait create mode 100644 unit-tests/dotwait.exp create mode 100644 unit-tests/dotwait.mk delete mode 100644 unit-tests/error create mode 100644 unit-tests/error.exp create mode 100644 unit-tests/error.mk create mode 100644 unit-tests/escape.exp create mode 100644 unit-tests/escape.mk delete mode 100644 unit-tests/export delete mode 100644 unit-tests/export-all create mode 100644 unit-tests/export-all.exp create mode 100644 unit-tests/export-all.mk delete mode 100644 unit-tests/export-env create mode 100644 unit-tests/export-env.exp create mode 100644 unit-tests/export-env.mk create mode 100644 unit-tests/export.exp create mode 100644 unit-tests/export.mk delete mode 100644 unit-tests/forloop create mode 100644 unit-tests/forloop.exp create mode 100644 unit-tests/forloop.mk delete mode 100644 unit-tests/forsubst create mode 100644 unit-tests/forsubst.exp create mode 100644 unit-tests/forsubst.mk delete mode 100644 unit-tests/hash create mode 100644 unit-tests/hash.exp create mode 100644 unit-tests/hash.mk create mode 100644 unit-tests/impsrc.exp create mode 100644 unit-tests/impsrc.mk delete mode 100644 unit-tests/misc create mode 100644 unit-tests/misc.exp create mode 100644 unit-tests/misc.mk delete mode 100644 unit-tests/moderrs create mode 100644 unit-tests/moderrs.exp create mode 100644 unit-tests/moderrs.mk delete mode 100644 unit-tests/modmatch create mode 100644 unit-tests/modmatch.exp create mode 100644 unit-tests/modmatch.mk delete mode 100644 unit-tests/modmisc create mode 100644 unit-tests/modmisc.exp create mode 100644 unit-tests/modmisc.mk delete mode 100644 unit-tests/modorder create mode 100644 unit-tests/modorder.exp create mode 100644 unit-tests/modorder.mk delete mode 100644 unit-tests/modts create mode 100644 unit-tests/modts.exp create mode 100644 unit-tests/modts.mk delete mode 100644 unit-tests/modword create mode 100644 unit-tests/modword.exp create mode 100644 unit-tests/modword.mk delete mode 100644 unit-tests/order create mode 100644 unit-tests/order.exp create mode 100644 unit-tests/order.mk delete mode 100644 unit-tests/phony-end create mode 100644 unit-tests/phony-end.exp create mode 100644 unit-tests/phony-end.mk delete mode 100644 unit-tests/posix create mode 100644 unit-tests/posix.exp create mode 100644 unit-tests/posix.mk create mode 100644 unit-tests/posix1.exp create mode 100644 unit-tests/posix1.mk delete mode 100644 unit-tests/qequals create mode 100644 unit-tests/qequals.exp create mode 100644 unit-tests/qequals.mk create mode 100644 unit-tests/suffixes.exp create mode 100644 unit-tests/suffixes.mk delete mode 100644 unit-tests/sunshcmd create mode 100644 unit-tests/sunshcmd.exp create mode 100644 unit-tests/sunshcmd.mk delete mode 100644 unit-tests/sysv create mode 100644 unit-tests/sysv.exp create mode 100644 unit-tests/sysv.mk delete mode 100644 unit-tests/ternary create mode 100644 unit-tests/ternary.exp create mode 100644 unit-tests/ternary.mk delete mode 100644 unit-tests/test.exp delete mode 100644 unit-tests/unexport delete mode 100644 unit-tests/unexport-env create mode 100644 unit-tests/unexport-env.exp create mode 100644 unit-tests/unexport-env.mk create mode 100644 unit-tests/unexport.exp create mode 100644 unit-tests/unexport.mk delete mode 100644 unit-tests/varcmd create mode 100644 unit-tests/varcmd.exp create mode 100644 unit-tests/varcmd.mk create mode 100644 unit-tests/varmisc.exp create mode 100644 unit-tests/varmisc.mk create mode 100644 unit-tests/varshell.exp create mode 100644 unit-tests/varshell.mk diff --git a/ChangeLog b/ChangeLog index 1dbf0ef01f2c..2fe736917f37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,76 @@ +2015-04-18 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150418 + Merge with NetBSD make, pick up + o job.c: use memmove() rather than memcpy() + + * unit-tests/varshell.mk: SunOS cannot handle the TERMINATED_BY_SIGNAL + case, so skip it. + +2015-04-11 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150411 + bump version - only mk/ changes. + +2015-04-10 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150410 + Merge with NetBSD make, pick up + o document different handling of '-' in jobs mode vs compat + o fix jobs mode so that '-' only applies to whole job + when shell lacks hasErrCtl + o meta.c: use separate vars to track lcwd and latestdir (read) + per process + +2015-04-01 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150401 + Merge with NetBSD make, pick up + o meta.c: close meta file in child + + * Makefile: use BINDIR.bmake if set. + Same for MANDIR and SHAREDIR + Handy for testing release candidates + in various environments. + +2015-03-26 Simon J. Gerraty + + * move initialization of savederr to block where it is used + to avoid spurious warning from gcc5 + +2014-11-11 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20141111 + just a cooler number + +2014-11-05 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20141105 + Merge with NetBSD make, pick up + o revert major overhaul of suffix handling + and POSIX compliance - too much breakage + and impossible to make backwards compatible. + o we still have the new unit test structure which is ok. + o meta.c ensure "-- filemon" is at start of line. + +2014-09-17 Simon J. Gerraty + + * configure.in: test that result of getconf PATH_MAX is numeric + and discard if not. Apparently needed for Hurd. + +2014-08-30 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20140830 + Merge with NetBSD make, pick up + o major overhaul of suffix handling + o improved POSIX compliance + o overhauled unit-tests + 2014-06-20 Simon J. Gerraty * Makefile (MAKE_VERSION): 20140620 Merge with NetBSD make, pick up - o var.c return varNoError rather than var_Error for ::= modidiers. + o var.c return varNoError rather than var_Error for ::= modifiers. 2014-05-22 Simon J. Gerraty diff --git a/FILES b/FILES index d4b5dca38c89..81899731ec49 100644 --- a/FILES +++ b/FILES @@ -92,35 +92,74 @@ targ.c trace.c trace.h unit-tests/Makefile.in -unit-tests/comment -unit-tests/cond1 -unit-tests/doterror -unit-tests/dotwait -unit-tests/error -unit-tests/export -unit-tests/export-all -unit-tests/export-env -unit-tests/forloop -unit-tests/forsubst -unit-tests/hash -unit-tests/misc -unit-tests/moderrs -unit-tests/modmatch -unit-tests/modmisc -unit-tests/modorder -unit-tests/modts -unit-tests/modword -unit-tests/order -unit-tests/phony-end -unit-tests/posix -unit-tests/qequals -unit-tests/sunshcmd -unit-tests/sysv -unit-tests/ternary -unit-tests/test.exp -unit-tests/unexport -unit-tests/unexport-env -unit-tests/varcmd +unit-tests/comment.exp +unit-tests/comment.mk +unit-tests/cond1.exp +unit-tests/cond1.mk +unit-tests/doterror.exp +unit-tests/doterror.mk +unit-tests/dotwait.exp +unit-tests/dotwait.mk +unit-tests/error.exp +unit-tests/error.mk +unit-tests/escape.exp +unit-tests/escape.mk +unit-tests/export-all.exp +unit-tests/export-all.mk +unit-tests/export-env.exp +unit-tests/export-env.mk +unit-tests/export.exp +unit-tests/export.mk +unit-tests/forloop.exp +unit-tests/forloop.mk +unit-tests/forsubst.exp +unit-tests/forsubst.mk +unit-tests/hash.exp +unit-tests/hash.mk +unit-tests/impsrc.exp +unit-tests/impsrc.mk +unit-tests/misc.exp +unit-tests/misc.mk +unit-tests/moderrs.exp +unit-tests/moderrs.mk +unit-tests/modmatch.exp +unit-tests/modmatch.mk +unit-tests/modmisc.exp +unit-tests/modmisc.mk +unit-tests/modorder.exp +unit-tests/modorder.mk +unit-tests/modts.exp +unit-tests/modts.mk +unit-tests/modword.exp +unit-tests/modword.mk +unit-tests/order.exp +unit-tests/order.mk +unit-tests/phony-end.exp +unit-tests/phony-end.mk +unit-tests/posix.exp +unit-tests/posix.mk +unit-tests/posix1.exp +unit-tests/posix1.mk +unit-tests/qequals.exp +unit-tests/qequals.mk +unit-tests/suffixes.exp +unit-tests/suffixes.mk +unit-tests/sunshcmd.exp +unit-tests/sunshcmd.mk +unit-tests/sysv.exp +unit-tests/sysv.mk +unit-tests/ternary.exp +unit-tests/ternary.mk +unit-tests/unexport-env.exp +unit-tests/unexport-env.mk +unit-tests/unexport.exp +unit-tests/unexport.mk +unit-tests/varcmd.exp +unit-tests/varcmd.mk +unit-tests/varmisc.exp +unit-tests/varmisc.mk +unit-tests/varshell.exp +unit-tests/varshell.mk util.c var.c wait.h diff --git a/Makefile b/Makefile index 42258c4e854e..9a0abc6ab613 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -# $Id: Makefile,v 1.27 2014/06/20 14:51:54 sjg Exp $ +# $Id: Makefile,v 1.36 2015/04/18 19:58:53 sjg Exp $ # Base version on src date -MAKE_VERSION= 20140620 +MAKE_VERSION= 20150418 PROG= bmake @@ -180,9 +180,9 @@ COPTS.parse.c += -Wno-format-nonliteral COPTS.var.c += -Wno-format-nonliteral # Force these -SHAREDIR= ${prefix}/share -BINDIR= ${prefix}/bin -MANDIR= ${SHAREDIR}/man +SHAREDIR= ${SHAREDIR.bmake:U${prefix}/share} +BINDIR= ${BINDIR.bmake:U${prefix}/bin} +MANDIR= ${MANDIR.bmake:U${SHAREDIR}/man} .if !exists(.depend) ${OBJS}: config.h diff --git a/PSD.doc/Makefile b/PSD.doc/Makefile index 8e1f1fa0705b..67702b80e2c1 100644 --- a/PSD.doc/Makefile +++ b/PSD.doc/Makefile @@ -1,8 +1,10 @@ -# $NetBSD: Makefile,v 1.2 1995/06/14 15:20:23 christos Exp $ +# $NetBSD: Makefile,v 1.4 2014/07/05 19:22:43 dholland Exp $ # @(#)Makefile 8.1 (Berkeley) 8/14/93 -DIR= psd/12.make +SECTION=reference/ref1 +ARTICLE=make SRCS= tutorial.ms MACROS= -ms +EXTRAHTMLFILES=make1.png make2.png .include diff --git a/PSD.doc/tutorial.ms b/PSD.doc/tutorial.ms index c1a6444d48c6..d5c8a7d54f96 100644 --- a/PSD.doc/tutorial.ms +++ b/PSD.doc/tutorial.ms @@ -1,4 +1,4 @@ -.\" $NetBSD: tutorial.ms,v 1.11 2011/08/18 15:19:30 sjg Exp $ +.\" $NetBSD: tutorial.ms,v 1.12 2014/09/30 21:33:14 christos Exp $ .\" Copyright (c) 1988, 1989, 1993 .\" The Regents of the University of California. All rights reserved. .\" @@ -67,6 +67,16 @@ .\" .EH 'PSD:12-%''PMake \*- A Tutorial' .OH 'PMake \*- A Tutorial''PSD:12-%' +.\" Ix is an indexing macro similar to .IX but I've disabled it for now +.\" Since that would require 2 passes and I am not in the mood for that. +.de Ix +.. +.\" Rd is section (region) define and Rm is region mention? Again disable for +.\" now. +.de Rd +.. +.de Rm +.. .\" xH is a macro to provide numbered headers that are automatically stuffed .\" into a table-of-contents, properly indented, etc. If the first argument .\" is numeric, it is taken as the depth for numbering (as for .NH), else diff --git a/bmake.1 b/bmake.1 index 5363e88b9b86..702d392cc794 100644 --- a/bmake.1 +++ b/bmake.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.229 2014/01/19 10:23:29 apb Exp $ +.\" $NetBSD: make.1,v 1.247 2015/04/10 08:43:32 wiz 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 14, 2014 +.Dd April 9, 2015 .Dt MAKE 1 .Os .Sh NAME @@ -209,8 +209,6 @@ Force the option to print raw values of variables. .It Ar v Print debugging information about variable assignment. -.It Ar w -Print entering and leaving directory messages, pre and post processing. .It Ar x Run shell commands with .Fl x @@ -352,6 +350,8 @@ contains a then the value will be expanded before printing. .It Fl W Treat any warnings during makefile parsing as errors. +.It Fl w +Print entering and leaving directory messages, pre and post processing. .It Fl X Don't export variables passed on the command line to the environment individually. @@ -441,17 +441,29 @@ The value need not necessarily be used to describe existing files. Expansion is in directory order, not alphabetically as done in the shell. .Sh SHELL COMMANDS -Each target may have associated with it a series of shell commands, normally +Each target may have associated with it one or more lines of shell +commands, normally used to create the target. -Each of the commands in this script +Each of the lines in this script .Em must be preceded by a tab. -While any target may appear on a dependency line, only one of these -dependencies may be followed by a creation script, unless the +(For historical reasons, spaces are not accepted.) +While targets can appear in many dependency lines if desired, by +default only one of these rules may be followed by a creation +script. +If the .Ql Ic \&:: -operator is used. +operator is used, however, all rules may include scripts and the +scripts are executed in the order found. .Pp -If the first characters of the command line are any combination of +Each line is treated as a separate shell command, unless the end of +line is escaped with a backslash +.Pq Ql \e +in which case that line and the next are combined. +.\" The escaped newline is retained and passed to the shell, which +.\" normally ignores it. +.\" However, the tab at the beginning of the following line is removed. +If the first characters of the command are any combination of .Ql Ic @ , .Ql Ic + , or @@ -469,6 +481,7 @@ This is similar to the effect of the .MAKE special source, except that the effect can be limited to a single line of a script. A .Ql Ic \- +in compatibility mode causes any non-zero exit status of the command line to be ignored. .Pp When @@ -477,22 +490,21 @@ is run in jobs mode with .Fl j Ar max_jobs , the entire script for the target is fed to a single instance of the shell. -.Pp In compatibility (non-jobs) mode, each command is run in a separate process. If the command contains any shell meta characters .Pq Ql #=|^(){};&<>*?[]:$`\e\en -it will be passed to the shell, otherwise +it will be passed to the shell; otherwise .Nm will attempt direct execution. -.Pp -Since -.Nm -will -.Xr chdir 2 -to -.Ql Va .OBJDIR -before executing any targets, each child process -starts with that as its current working directory. +If a line starts with +.Ql Ic \- +and the shell has ErrCtl enabled then failure of the command line +will be ignored as in compatibility mode. +Otherwise +.Ql Ic \- +affects the entire job; +the script will stop at the first command line that fails, +but the target will not be deemed to have failed. .Pp Makefiles should be written so that the mode of .Nm @@ -500,20 +512,32 @@ operation does not change their behavior. For example, any command which needs to use .Dq cd or -.Dq chdir , -without side-effect should be put in parenthesis: +.Dq chdir +without potentially changing the directory for subsequent commands +should be put in parentheses so it executes in a subshell. +To force the use of one shell, escape the line breaks so as to make +the whole script one command. +For example: .Bd -literal -offset indent - avoid-chdir-side-effects: @echo Building $@ in `pwd` - @(cd ${.CURDIR} && ${.MAKE} $@) + @(cd ${.CURDIR} && ${MAKE} $@) @echo Back in `pwd` ensure-one-shell-regardless-of-mode: - @echo Building $@ in `pwd`; \\ - (cd ${.CURDIR} && ${.MAKE} $@); \\ + @echo Building $@ in `pwd`; \e + (cd ${.CURDIR} && ${MAKE} $@); \e echo Back in `pwd` .Ed +.Pp +Since +.Nm +will +.Xr chdir 2 +to +.Ql Va .OBJDIR +before executing any targets, each child process +starts with that as its current working directory. .Sh VARIABLE ASSIGNMENTS Variables in make are much like variables in the shell, and, by tradition, consist of all upper-case letters. @@ -624,13 +648,19 @@ Variables defined in the makefile or in included makefiles. Variables defined as part of the command line. .It Local variables Variables that are defined specific to a certain target. +.El +.Pp +Local variables are all built in and their values vary magically from +target to target. +It is not currently possible to define new local variables. The seven local variables are as follows: -.Bl -tag -width ".ARCHIVE" +.Bl -tag -width ".ARCHIVE" -offset indent .It Va .ALLSRC The list of all sources for this target; also known as .Ql Va \&\*[Gt] . .It Va .ARCHIVE -The name of the archive file. +The name of the archive file; also known as +.Ql Va \&! . .It Va .IMPSRC In suffix-transformation rules, the name/path of the source from which the target is to be transformed (the @@ -639,7 +669,8 @@ source); also known as .Ql Va \&\*[Lt] . It is not defined in explicit rules. .It Va .MEMBER -The name of the archive member. +The name of the archive member; also known as +.Ql Va % . .It Va .OODATE The list of sources for this target that were deemed out-of-date; also known as @@ -648,31 +679,41 @@ known as The file prefix of the target, containing only the file portion, no suffix or preceding directory components; also known as .Ql Va * . +The suffix must be one of the known suffixes declared with +.Ic .SUFFIXES +or it will not be recognized. .It Va .TARGET The name of the target; also known as .Ql Va @ . .El .Pp The shorter forms -.Ql Va @ , +.Ql ( Va \*[Gt] , +.Ql Va \&! , +.Ql Va \*[Lt] , +.Ql Va % , .Ql Va \&? , -.Ql Va \&\*[Lt] , -.Ql Va \&\*[Gt] , +.Ql Va * , and -.Ql Va * +.Ql Va @ ) are permitted for backward -compatibility with historical makefiles and are not recommended. -The six variables -.Ql Va "@F" , -.Ql Va "@D" , -.Ql Va "\*[Lt]F" , -.Ql Va "\*[Lt]D" , -.Ql Va "*F" , +compatibility with historical makefiles and legacy POSIX make and are +not recommended. +.Pp +Variants of these variables with the punctuation followed immediately by +.Ql D +or +.Ql F , +e.g. +.Ql Va $(@D) , +are legacy forms equivalent to using the +.Ql :H and -.Ql Va "*D" -are permitted for compatibility with +.Ql :T +modifiers. +These forms are accepted for compatibility with .At V -makefiles and are not recommended. +makefiles and POSIX but are not recommended. .Pp Four of the local variables may be used in sources on dependency lines because they expand to the proper value for each target on the line. @@ -682,7 +723,6 @@ These variables are .Ql Va .ARCHIVE , and .Ql Va .MEMBER . -.El .Ss Additional built-in variables In addition, .Nm @@ -2119,19 +2159,87 @@ system makefile system makefile directory .El .Sh COMPATIBILITY -The basic make syntax is compatible between different versions of make, +The basic make syntax is compatible between different versions of make; however the special variables, variable modifiers and conditionals are not. -.Pp -The way that parallel makes are scheduled changed in -NetBSD 4.0 -so that .ORDER and .WAIT apply recursively to the dependent nodes. -The algorithms used may change again in the future. +.Ss Older versions +An incomplete list of changes in older versions of +.Nm : .Pp The way that .for loop variables are substituted changed after NetBSD 5.0 so that they still appear to be variable expansions. In particular this stops them being treated as syntax, and removes some obscure problems using them in .if statements. +.Pp +The way that parallel makes are scheduled changed in +NetBSD 4.0 +so that .ORDER and .WAIT apply recursively to the dependent nodes. +The algorithms used may change again in the future. +.Ss Other make dialects +Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not +support most of the features of +.Nm +as described in this manual. +Most notably: +.Bl -bullet -offset indent +.It +The +.Ic .WAIT +and +.Ic .ORDER +declarations and most functionality pertaining to parallelization. +(GNU make supports parallelization but lacks these features needed to +control it effectively.) +.It +Directives, including for loops and conditionals and most of the +forms of include files. +(GNU make has its own incompatible and less powerful syntax for +conditionals.) +.It +All built-in variables that begin with a dot. +.It +Most of the special sources and targets that begin with a dot, +with the notable exception of +.Ic .PHONY , +.Ic .PRECIOUS , +and +.Ic .SUFFIXES . +.It +Variable modifiers, except for the +.Dl :old=new +string substitution, which does not portably support globbing with +.Ql % +and historically only works on declared suffixes. +.It +The +.Ic $> +variable even in its short form; most makes support this functionality +but its name varies. +.El +.Pp +Some features are somewhat more portable, such as assignment with +.Ic += , +.Ic ?= , +and +.Ic != . +The +.Ic .PATH +functionality is based on an older feature +.Ic VPATH +found in GNU make and many versions of SVR4 make; however, +historically its behavior is too ill-defined (and too buggy) to rely +upon. +.Pp +The +.Ic $@ +and +.Ic $< +variables are more or less universally portable, as is the +.Ic $(MAKE) +variable. +Basic use of suffix rules (for files only in the current directory, +not trying to chain transformations together, etc.) is also reasonably +portable. .Sh SEE ALSO .Xr mkdep 1 .Sh HISTORY diff --git a/bmake.cat1 b/bmake.cat1 index 0ce26a5a1cc0..5c62c1ba8e4c 100644 --- a/bmake.cat1 +++ b/bmake.cat1 @@ -122,9 +122,6 @@ DDEESSCCRRIIPPTTIIOONN _v Print debugging information about variable assignment. - _w Print entering and leaving directory messages, pre and - post processing. - _x Run shell commands with --xx so the actual commands are printed as they are executed. @@ -221,6 +218,9 @@ DDEESSCCRRIIPPTTIIOONN --WW Treat any warnings during makefile parsing as errors. + --ww Print entering and leaving directory messages, pre and post pro- + cessing. + --XX Don't export variables passed on the command line to the environ- ment individually. Variables passed on the command line are still exported via the _M_A_K_E_F_L_A_G_S environment variable. This @@ -273,46 +273,55 @@ FFIILLEE DDEEPPEENNDDEENNCCYY SSPPEECCIIFFIICCAATTIIOO done in the shell. SSHHEELLLL CCOOMMMMAANNDDSS - Each target may have associated with it a series of shell commands, nor- - mally used to create the target. Each of the commands in this script - _m_u_s_t be preceded by a tab. While any target may appear on a dependency - line, only one of these dependencies may be followed by a creation - script, unless the `::::' operator is used. - - If the first characters of the command line are any combination of `@@', - `++', or `--', the command is treated specially. A `@@' causes the command - not to be echoed before it is executed. A `++' causes the command to be - executed even when --nn is given. This is similar to the effect of the - .MAKE special source, except that the effect can be limited to a single - line of a script. A `--' causes any non-zero exit status of the command - line to be ignored. + Each target may have associated with it one or more lines of shell com- + mands, normally used to create the target. Each of the lines in this + script _m_u_s_t be preceded by a tab. (For historical reasons, spaces are + not accepted.) While targets can appear in many dependency lines if + desired, by default only one of these rules may be followed by a creation + script. If the `::::' operator is used, however, all rules may include + scripts and the scripts are executed in the order found. + + Each line is treated as a separate shell command, unless the end of line + is escaped with a backslash (`\') in which case that line and the next + are combined. If the first characters of the command are any combination + of `@@', `++', or `--', the command is treated specially. A `@@' causes the + command not to be echoed before it is executed. A `++' causes the command + to be executed even when --nn is given. This is similar to the effect of + the .MAKE special source, except that the effect can be limited to a sin- + gle line of a script. A `--' 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 will be passed to the shell, otherwise - bbmmaakkee will attempt direct execution. - - Since bbmmaakkee will chdir(2) to `_._O_B_J_D_I_R' before executing any targets, each - child process starts with that as its current working directory. + 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 com- + mand contains any shell meta characters (`#=|^(){};&<>*?[]:$`\\n') it + will be passed to the shell; otherwise bbmmaakkee will attempt direct execu- + tion. If a line starts with `--' and the shell has ErrCtl enabled then + failure of the command line will be ignored as in compatibility mode. + Otherwise `--' affects the entire job; the script will stop at the first + command line that fails, but the target will not be 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 needs to use - ``cd'' or ``chdir'', without side-effect should be put in parenthesis: - + ``cd'' or ``chdir'' without potentially changing the directory for subse- + quent commands should be put in parentheses so it executes in a subshell. + To force the use of one shell, escape the line breaks so as to make the + whole script one command. For example: avoid-chdir-side-effects: @echo Building $@ in `pwd` - @(cd ${.CURDIR} && ${.MAKE} $@) + @(cd ${.CURDIR} && ${MAKE} $@) @echo Back in `pwd` ensure-one-shell-regardless-of-mode: @echo Building $@ in `pwd`; \ - (cd ${.CURDIR} && ${.MAKE} $@); \ + (cd ${.CURDIR} && ${MAKE} $@); \ echo Back in `pwd` + Since bbmmaakkee will chdir(2) to `_._O_B_J_D_I_R' before executing any targets, each + child process starts with that as its current working directory. + VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS Variables in make are much like variables in the shell, and, by tradi- tion, consist of all upper-case letters. @@ -402,40 +411,47 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS Variables defined as part of the command line. Local variables - Variables that are defined specific to a certain target. The - seven local variables are as follows: + Variables that are defined specific to a certain target. + + Local variables are all built in and their values vary magically from + target to target. It is not currently possible to define new local vari- + ables. The seven local variables are as follows: - _._A_L_L_S_R_C The list of all sources for this target; also known as - `_>'. + _._A_L_L_S_R_C The list of all sources for this target; also known as + `_>'. - _._A_R_C_H_I_V_E The name of the archive file. + _._A_R_C_H_I_V_E The name of the archive file; also known as `_!'. - _._I_M_P_S_R_C In suffix-transformation rules, the name/path of the - source from which the target is to be transformed (the - ``implied'' source); also known as `_<'. It is not - defined in explicit rules. + _._I_M_P_S_R_C In suffix-transformation rules, the name/path of the + source from which the target is to be transformed (the + ``implied'' source); also known as `_<'. It is not + defined in explicit rules. - _._M_E_M_B_E_R The name of the archive member. + _._M_E_M_B_E_R The name of the archive member; also known as `_%'. - _._O_O_D_A_T_E The list of sources for this target that were deemed - out-of-date; also known as `_?'. + _._O_O_D_A_T_E The list of sources for this target that were deemed out- + of-date; also known as `_?'. - _._P_R_E_F_I_X The file prefix of the target, containing only the file - portion, no suffix or preceding directory components; - also known as `_*'. + _._P_R_E_F_I_X The file prefix of the target, containing only the file + portion, no suffix or preceding directory components; + also known as `_*'. The suffix must be one of the known + suffixes declared with ..SSUUFFFFIIXXEESS or it will not be recog- + nized. - _._T_A_R_G_E_T The name of the target; also known as `_@'. + _._T_A_R_G_E_T The name of the target; also known as `_@'. - The shorter forms `_@', `_?', `_<', `_>', and `_*' are permitted for - backward compatibility with historical makefiles and are not rec- - ommended. The six variables `_@_F', `_@_D', `_<_F', `_<_D', `_*_F', and - `_*_D' are permitted for compatibility with AT&T System V UNIX - makefiles and are not recommended. + The shorter forms (`_>', `_!', `_<', `_%', `_?', `_*', and `_@') are permitted + for backward compatibility with historical makefiles and legacy POSIX + make and are not recommended. - Four of the local variables may be used in sources on dependency - lines because they expand to the proper value for each target on - the line. These variables are `_._T_A_R_G_E_T', `_._P_R_E_F_I_X', `_._A_R_C_H_I_V_E', - and `_._M_E_M_B_E_R'. + Variants of these variables with the punctuation followed immediately by + `D' or `F', e.g. `_$_(_@_D_)', are legacy forms equivalent to using the `:H' + and `:T' modifiers. These forms are accepted for compatibility with AT&T + System V UNIX makefiles and POSIX but are not recommended. + + Four of the local variables may be used in sources on dependency lines + because they expand to the proper value for each target on the line. + These variables are `_._T_A_R_G_E_T', `_._P_R_E_F_I_X', `_._A_R_C_H_I_V_E', and `_._M_E_M_B_E_R'. AAddddiittiioonnaall bbuuiilltt--iinn vvaarriiaabblleess In addition, bbmmaakkee sets or knows about the following variables: @@ -1356,19 +1372,58 @@ FFIILLEESS /usr/share/mk system makefile directory CCOOMMPPAATTIIBBIILLIITTYY - The basic make syntax is compatible between different versions of make, + The basic make syntax is compatible between different versions of make; however the special variables, variable modifiers and conditionals are not. - The way that parallel makes are scheduled changed in NetBSD 4.0 so that - .ORDER and .WAIT apply recursively to the dependent nodes. The algo- - rithms used may change again in the future. + OOllddeerr vveerrssiioonnss + An incomplete list of changes in older versions of bbmmaakkee: The way that .for loop variables are substituted changed after NetBSD 5.0 so that they still appear to be variable expansions. In particular this stops them being treated as syntax, and removes some obscure problems using them in .if statements. + The way that parallel makes are scheduled changed in NetBSD 4.0 so that + .ORDER and .WAIT apply recursively to the dependent nodes. The algo- + rithms used may change again in the future. + + OOtthheerr mmaakkee ddiiaalleeccttss + Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not sup- + port most of the features of bbmmaakkee as described in this manual. Most + notably: + + ++oo The ..WWAAIITT and ..OORRDDEERR declarations and most functionality per- + taining to parallelization. (GNU make supports parallelization + but lacks these features needed to control it effectively.) + + ++oo Directives, including for loops and conditionals and most of + the forms of include files. (GNU make has its own incompatible + and less powerful syntax for conditionals.) + + ++oo All built-in variables that begin with a dot. + + ++oo Most of the special sources and targets that begin with a dot, + with the notable exception of ..PPHHOONNYY, ..PPRREECCIIOOUUSS, and ..SSUUFFFFIIXXEESS. + + ++oo Variable modifiers, except for the + :old=new + string substitution, which does not portably support globbing + with `%' and historically only works on declared suffixes. + + ++oo The $$>> variable even in its short form; most makes support this + functionality but its name varies. + + Some features are somewhat more portable, such as assignment with ++==, ??==, + and !!==. The ..PPAATTHH functionality is based on an older feature VVPPAATTHH found + in GNU make and many versions of SVR4 make; however, historically its + behavior is too ill-defined (and too buggy) to rely upon. + + The $$@@ and $$<< variables are more or less universally portable, as is the + $$((MMAAKKEE)) variable. Basic use of suffix rules (for files only in the cur- + rent directory, not trying to chain transformations together, etc.) is + also reasonably portable. + SSEEEE AALLSSOO mkdep(1) @@ -1394,4 +1449,4 @@ BBUUGGSS There is no way of escaping a space character in a filename. -NetBSD 5.1 February 14, 2014 NetBSD 5.1 +NetBSD 5.1 April 9, 2015 NetBSD 5.1 diff --git a/compat.c b/compat.c index 97fcfe42ace2..fd00eb7e03c3 100644 --- a/compat.c +++ b/compat.c @@ -1,4 +1,4 @@ -/* $NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $ */ +/* $NetBSD: compat.c,v 1.96 2014/09/07 20:55:34 joerg Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -70,14 +70,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $"; +static char rcsid[] = "$NetBSD: compat.c,v 1.96 2014/09/07 20:55:34 joerg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: compat.c,v 1.94 2014/01/03 00:02:01 sjg Exp $"); +__RCSID("$NetBSD: compat.c,v 1.96 2014/09/07 20:55:34 joerg Exp $"); #endif #endif /* not lint */ #endif diff --git a/configure b/configure index e3ff4de5b042..08b21b324ab1 100755 --- a/configure +++ b/configure @@ -4247,6 +4247,8 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' if test -x /usr/bin/getconf; then bmake_path_max=`getconf PATH_MAX / 2> /dev/null` + # only a numeric response is useful + test ${bmake_path_max:-0} -gt 0 2> /dev/null || bmake_path_max= fi bmake_path_max=${bmake_path_max:-1024} if test $bmake_path_max -gt 1024; then diff --git a/configure.in b/configure.in index ecaa53aa900f..e2249b0db261 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl dnl RCSid: -dnl $Id: configure.in,v 1.52 2014/02/15 22:27:59 sjg Exp $ +dnl $Id: configure.in,v 1.53 2014/11/06 01:49:40 sjg Exp $ dnl dnl Process this file with autoconf to produce a configure script dnl @@ -82,6 +82,8 @@ dnl dnl Hurd refuses to define PATH_MAX or MAXPATHLEN if test -x /usr/bin/getconf; then bmake_path_max=`getconf PATH_MAX / 2> /dev/null` + # only a numeric response is useful + test ${bmake_path_max:-0} -gt 0 2> /dev/null || bmake_path_max= fi bmake_path_max=${bmake_path_max:-1024} if test $bmake_path_max -gt 1024; then diff --git a/job.c b/job.c index b5dbf4cb56f1..6dfdce4c2ff4 100644 --- a/job.c +++ b/job.c @@ -1,4 +1,4 @@ -/* $NetBSD: job.c,v 1.176 2013/08/04 16:48:15 sjg Exp $ */ +/* $NetBSD: job.c,v 1.180 2015/04/16 13:31:03 joerg Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -70,14 +70,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: job.c,v 1.176 2013/08/04 16:48:15 sjg Exp $"; +static char rcsid[] = "$NetBSD: job.c,v 1.180 2015/04/16 13:31:03 joerg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: job.c,v 1.176 2013/08/04 16:48:15 sjg Exp $"); +__RCSID("$NetBSD: job.c,v 1.180 2015/04/16 13:31:03 joerg Exp $"); #endif #endif /* not lint */ #endif @@ -728,7 +728,6 @@ JobPrintCommand(void *cmdp, void *jobp) shutUp = DEBUG(LOUD) ? FALSE : TRUE; break; case '-': - job->flags |= JOB_IGNERR; errOff = TRUE; break; case '+': @@ -807,6 +806,7 @@ JobPrintCommand(void *cmdp, void *jobp) * to ignore errors. Set cmdTemplate to use the weirdness * instead of the simple "%s\n" template. */ + job->flags |= JOB_IGNERR; if (!(job->flags & JOB_SILENT) && !shutUp) { if (commandShell->hasEchoCtl) { DBPRINTF("%s\n", commandShell->echoOff); @@ -1360,7 +1360,7 @@ JobExec(Job *job, char **argv) (void)fcntl(0, F_SETFD, 0); (void)lseek(0, (off_t)0, SEEK_SET); - if (job->node->type & OP_MAKE) { + if (job->node->type & (OP_MAKE | OP_SUBMAKE)) { /* * Pass job token pipe to submakes. */ @@ -1894,16 +1894,16 @@ end_loop: (void)fflush(stdout); } } - if (i < max - 1) { - /* shift the remaining characters down */ - (void)memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); + /* + * max is the last offset still in the buffer. Move any remaining + * characters to the start of the buffer and update the end marker + * curPos. + */ + if (i < max) { + (void)memmove(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); job->curPos = max - (i + 1); - } else { - /* - * We have written everything out, so we just start over - * from the start of the buffer. No copying. No nothing. - */ + assert(i == max); job->curPos = 0; } } diff --git a/lst.h b/lst.h index e0674071a98f..e207bc808bf9 100644 --- a/lst.h +++ b/lst.h @@ -1,4 +1,4 @@ -/* $NetBSD: lst.h,v 1.18 2009/01/23 21:58:27 dsl Exp $ */ +/* $NetBSD: lst.h,v 1.20 2014/09/07 20:55:34 joerg Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. diff --git a/lst.lib/lstInt.h b/lst.lib/lstInt.h index 34a2fbdce96a..ac53dcb67d77 100644 --- a/lst.lib/lstInt.h +++ b/lst.lib/lstInt.h @@ -1,4 +1,4 @@ -/* $NetBSD: lstInt.h,v 1.20 2009/01/24 14:43:29 dsl Exp $ */ +/* $NetBSD: lstInt.h,v 1.22 2014/09/07 20:55:34 joerg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 diff --git a/lst.lib/lstRemove.c b/lst.lib/lstRemove.c index 54d7b33df017..7480d30ba4f4 100644 --- a/lst.lib/lstRemove.c +++ b/lst.lib/lstRemove.c @@ -1,4 +1,4 @@ -/* $NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $ */ +/* $NetBSD: lstRemove.c,v 1.16 2014/09/07 20:55:34 joerg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -33,14 +33,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $"; +static char rcsid[] = "$NetBSD: lstRemove.c,v 1.16 2014/09/07 20:55:34 joerg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)lstRemove.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $"); +__RCSID("$NetBSD: lstRemove.c,v 1.16 2014/09/07 20:55:34 joerg Exp $"); #endif #endif /* not lint */ #endif diff --git a/main.c b/main.c index f86184c37db7..3287115cf8b2 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.226 2014/02/07 17:23:35 pooka Exp $ */ +/* $NetBSD: main.c,v 1.232 2015/03/26 22:20:42 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,7 +69,7 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: main.c,v 1.226 2014/02/07 17:23:35 pooka Exp $"; +static char rcsid[] = "$NetBSD: main.c,v 1.232 2015/03/26 22:20:42 sjg Exp $"; #else #include #ifndef lint @@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\ #if 0 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: main.c,v 1.226 2014/02/07 17:23:35 pooka Exp $"); +__RCSID("$NetBSD: main.c,v 1.232 2015/03/26 22:20:42 sjg Exp $"); #endif #endif /* not lint */ #endif @@ -99,14 +99,14 @@ __RCSID("$NetBSD: main.c,v 1.226 2014/02/07 17:23:35 pooka Exp $"); * * Error Print a tagged error message. The global * MAKE variable must have been defined. This - * takes a format string and two optional - * arguments for it. + * takes a format string and optional arguments + * for it. * * Fatal Print an error message and exit. Also takes - * a format string and two arguments. + * a format string and arguments for it. * * Punt Aborts all jobs and exits with a message. Also - * takes a format string and two arguments. + * takes a format string and arguments for it. * * Finish Finish things up by printing the number of * errors which occurred, as passed to it, and @@ -1522,7 +1522,8 @@ Cmd_Exec(const char *cmd, const char **errnum) WAIT_T status; /* command exit status */ Buffer buf; /* buffer to store the result */ char *cp; - int cc; + int cc; /* bytes read, or -1 */ + int savederr; /* saved errno */ *errnum = NULL; @@ -1579,6 +1580,7 @@ Cmd_Exec(const char *cmd, const char **errnum) */ (void)close(fds[1]); + savederr = 0; Buf_Init(&buf, 0); do { @@ -1588,6 +1590,8 @@ Cmd_Exec(const char *cmd, const char **errnum) Buf_AddBytes(&buf, cc, result); } while (cc > 0 || (cc == -1 && errno == EINTR)); + if (cc == -1) + savederr = errno; /* * Close the input side of the pipe. @@ -1604,7 +1608,7 @@ Cmd_Exec(const char *cmd, const char **errnum) cc = Buf_Size(&buf); res = Buf_Destroy(&buf, FALSE); - if (cc == 0) + if (savederr != 0) *errnum = "Couldn't read shell's output for \"%s\""; if (WIFSIGNALED(status)) diff --git a/make.1 b/make.1 index ccc483251131..fae034b941d4 100644 --- a/make.1 +++ b/make.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: make.1,v 1.230 2014/02/15 18:55:30 sjg Exp $ +.\" $NetBSD: make.1,v 1.247 2015/04/10 08:43:32 wiz 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 14, 2014 +.Dd April 9, 2015 .Dt MAKE 1 .Os .Sh NAME @@ -209,8 +209,6 @@ Force the option to print raw values of variables. .It Ar v Print debugging information about variable assignment. -.It Ar w -Print entering and leaving directory messages, pre and post processing. .It Ar x Run shell commands with .Fl x @@ -352,6 +350,8 @@ contains a then the value will be expanded before printing. .It Fl W Treat any warnings during makefile parsing as errors. +.It Fl w +Print entering and leaving directory messages, pre and post processing. .It Fl X Don't export variables passed on the command line to the environment individually. @@ -441,17 +441,29 @@ The value need not necessarily be used to describe existing files. Expansion is in directory order, not alphabetically as done in the shell. .Sh SHELL COMMANDS -Each target may have associated with it a series of shell commands, normally +Each target may have associated with it one or more lines of shell +commands, normally used to create the target. -Each of the commands in this script +Each of the lines in this script .Em must be preceded by a tab. -While any target may appear on a dependency line, only one of these -dependencies may be followed by a creation script, unless the +(For historical reasons, spaces are not accepted.) +While targets can appear in many dependency lines if desired, by +default only one of these rules may be followed by a creation +script. +If the .Ql Ic \&:: -operator is used. +operator is used, however, all rules may include scripts and the +scripts are executed in the order found. .Pp -If the first characters of the command line are any combination of +Each line is treated as a separate shell command, unless the end of +line is escaped with a backslash +.Pq Ql \e +in which case that line and the next are combined. +.\" The escaped newline is retained and passed to the shell, which +.\" normally ignores it. +.\" However, the tab at the beginning of the following line is removed. +If the first characters of the command are any combination of .Ql Ic @ , .Ql Ic + , or @@ -469,6 +481,7 @@ This is similar to the effect of the .MAKE special source, except that the effect can be limited to a single line of a script. A .Ql Ic \- +in compatibility mode causes any non-zero exit status of the command line to be ignored. .Pp When @@ -477,22 +490,21 @@ is run in jobs mode with .Fl j Ar max_jobs , the entire script for the target is fed to a single instance of the shell. -.Pp In compatibility (non-jobs) mode, each command is run in a separate process. If the command contains any shell meta characters .Pq Ql #=|^(){};&<>*?[]:$`\e\en -it will be passed to the shell, otherwise +it will be passed to the shell; otherwise .Nm will attempt direct execution. -.Pp -Since -.Nm -will -.Xr chdir 2 -to -.Ql Va .OBJDIR -before executing any targets, each child process -starts with that as its current working directory. +If a line starts with +.Ql Ic \- +and the shell has ErrCtl enabled then failure of the command line +will be ignored as in compatibility mode. +Otherwise +.Ql Ic \- +affects the entire job; +the script will stop at the first command line that fails, +but the target will not be deemed to have failed. .Pp Makefiles should be written so that the mode of .Nm @@ -500,20 +512,32 @@ operation does not change their behavior. For example, any command which needs to use .Dq cd or -.Dq chdir , -without side-effect should be put in parenthesis: +.Dq chdir +without potentially changing the directory for subsequent commands +should be put in parentheses so it executes in a subshell. +To force the use of one shell, escape the line breaks so as to make +the whole script one command. +For example: .Bd -literal -offset indent - avoid-chdir-side-effects: @echo Building $@ in `pwd` - @(cd ${.CURDIR} && ${.MAKE} $@) + @(cd ${.CURDIR} && ${MAKE} $@) @echo Back in `pwd` ensure-one-shell-regardless-of-mode: - @echo Building $@ in `pwd`; \\ - (cd ${.CURDIR} && ${.MAKE} $@); \\ + @echo Building $@ in `pwd`; \e + (cd ${.CURDIR} && ${MAKE} $@); \e echo Back in `pwd` .Ed +.Pp +Since +.Nm +will +.Xr chdir 2 +to +.Ql Va .OBJDIR +before executing any targets, each child process +starts with that as its current working directory. .Sh VARIABLE ASSIGNMENTS Variables in make are much like variables in the shell, and, by tradition, consist of all upper-case letters. @@ -624,13 +648,19 @@ Variables defined in the makefile or in included makefiles. Variables defined as part of the command line. .It Local variables Variables that are defined specific to a certain target. +.El +.Pp +Local variables are all built in and their values vary magically from +target to target. +It is not currently possible to define new local variables. The seven local variables are as follows: -.Bl -tag -width ".ARCHIVE" +.Bl -tag -width ".ARCHIVE" -offset indent .It Va .ALLSRC The list of all sources for this target; also known as .Ql Va \&\*[Gt] . .It Va .ARCHIVE -The name of the archive file. +The name of the archive file; also known as +.Ql Va \&! . .It Va .IMPSRC In suffix-transformation rules, the name/path of the source from which the target is to be transformed (the @@ -639,7 +669,8 @@ source); also known as .Ql Va \&\*[Lt] . It is not defined in explicit rules. .It Va .MEMBER -The name of the archive member. +The name of the archive member; also known as +.Ql Va % . .It Va .OODATE The list of sources for this target that were deemed out-of-date; also known as @@ -648,31 +679,41 @@ known as The file prefix of the target, containing only the file portion, no suffix or preceding directory components; also known as .Ql Va * . +The suffix must be one of the known suffixes declared with +.Ic .SUFFIXES +or it will not be recognized. .It Va .TARGET The name of the target; also known as .Ql Va @ . .El .Pp The shorter forms -.Ql Va @ , +.Ql ( Va \*[Gt] , +.Ql Va \&! , +.Ql Va \*[Lt] , +.Ql Va % , .Ql Va \&? , -.Ql Va \&\*[Lt] , -.Ql Va \&\*[Gt] , +.Ql Va * , and -.Ql Va * +.Ql Va @ ) are permitted for backward -compatibility with historical makefiles and are not recommended. -The six variables -.Ql Va "@F" , -.Ql Va "@D" , -.Ql Va "\*[Lt]F" , -.Ql Va "\*[Lt]D" , -.Ql Va "*F" , +compatibility with historical makefiles and legacy POSIX make and are +not recommended. +.Pp +Variants of these variables with the punctuation followed immediately by +.Ql D +or +.Ql F , +e.g. +.Ql Va $(@D) , +are legacy forms equivalent to using the +.Ql :H and -.Ql Va "*D" -are permitted for compatibility with +.Ql :T +modifiers. +These forms are accepted for compatibility with .At V -makefiles and are not recommended. +makefiles and POSIX but are not recommended. .Pp Four of the local variables may be used in sources on dependency lines because they expand to the proper value for each target on the line. @@ -682,7 +723,6 @@ These variables are .Ql Va .ARCHIVE , and .Ql Va .MEMBER . -.El .Ss Additional built-in variables In addition, .Nm @@ -2119,19 +2159,87 @@ system makefile system makefile directory .El .Sh COMPATIBILITY -The basic make syntax is compatible between different versions of make, +The basic make syntax is compatible between different versions of make; however the special variables, variable modifiers and conditionals are not. -.Pp -The way that parallel makes are scheduled changed in -.Nx 4.0 -so that .ORDER and .WAIT apply recursively to the dependent nodes. -The algorithms used may change again in the future. +.Ss Older versions +An incomplete list of changes in older versions of +.Nm : .Pp The way that .for loop variables are substituted changed after .Nx 5.0 so that they still appear to be variable expansions. In particular this stops them being treated as syntax, and removes some obscure problems using them in .if statements. +.Pp +The way that parallel makes are scheduled changed in +.Nx 4.0 +so that .ORDER and .WAIT apply recursively to the dependent nodes. +The algorithms used may change again in the future. +.Ss Other make dialects +Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not +support most of the features of +.Nm +as described in this manual. +Most notably: +.Bl -bullet -offset indent +.It +The +.Ic .WAIT +and +.Ic .ORDER +declarations and most functionality pertaining to parallelization. +(GNU make supports parallelization but lacks these features needed to +control it effectively.) +.It +Directives, including for loops and conditionals and most of the +forms of include files. +(GNU make has its own incompatible and less powerful syntax for +conditionals.) +.It +All built-in variables that begin with a dot. +.It +Most of the special sources and targets that begin with a dot, +with the notable exception of +.Ic .PHONY , +.Ic .PRECIOUS , +and +.Ic .SUFFIXES . +.It +Variable modifiers, except for the +.Dl :old=new +string substitution, which does not portably support globbing with +.Ql % +and historically only works on declared suffixes. +.It +The +.Ic $> +variable even in its short form; most makes support this functionality +but its name varies. +.El +.Pp +Some features are somewhat more portable, such as assignment with +.Ic += , +.Ic ?= , +and +.Ic != . +The +.Ic .PATH +functionality is based on an older feature +.Ic VPATH +found in GNU make and many versions of SVR4 make; however, +historically its behavior is too ill-defined (and too buggy) to rely +upon. +.Pp +The +.Ic $@ +and +.Ic $< +variables are more or less universally portable, as is the +.Ic $(MAKE) +variable. +Basic use of suffix rules (for files only in the current directory, +not trying to chain transformations together, etc.) is also reasonably +portable. .Sh SEE ALSO .Xr mkdep 1 .Sh HISTORY diff --git a/make.c b/make.c index 7905f8c1910c..fde185065fab 100644 --- a/make.c +++ b/make.c @@ -1,4 +1,4 @@ -/* $NetBSD: make.c,v 1.88 2012/11/09 18:53:05 sjg Exp $ */ +/* $NetBSD: make.c,v 1.91 2014/10/18 08:33:30 snj Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: make.c,v 1.88 2012/11/09 18:53:05 sjg Exp $"; +static char rcsid[] = "$NetBSD: make.c,v 1.91 2014/10/18 08:33:30 snj Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: make.c,v 1.88 2012/11/09 18:53:05 sjg Exp $"); +__RCSID("$NetBSD: make.c,v 1.91 2014/10/18 08:33:30 snj Exp $"); #endif #endif /* not lint */ #endif @@ -563,7 +563,7 @@ MakeHandleUse(void *cgnp, void *pgnp) * in the comments below. * * Results: - * returns 0 if the gnode does not exist, or it's filesystem + * returns 0 if the gnode does not exist, or its filesystem * time if it does. * * Side Effects: diff --git a/make.h b/make.h index 7579f6214304..9cf7243b58c9 100644 --- a/make.h +++ b/make.h @@ -1,4 +1,4 @@ -/* $NetBSD: make.h,v 1.92 2013/09/04 15:38:26 sjg Exp $ */ +/* $NetBSD: make.h,v 1.95 2014/09/07 20:55:34 joerg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -289,6 +289,7 @@ typedef struct GNode { #define OP_NOMETA 0x00080000 /* .NOMETA do not create a .meta file */ #define OP_META 0x00100000 /* .META we _do_ want a .meta file */ #define OP_NOMETA_CMP 0x00200000 /* Do not compare commands in .meta file */ +#define OP_SUBMAKE 0x00400000 /* Possibly a submake node */ /* Attributes applied by PMake */ #define OP_TRANSFORM 0x80000000 /* The node is a transformation rule */ #define OP_MEMBER 0x40000000 /* Target is a member of an archive */ diff --git a/meta.c b/meta.c index 3ec0bdca5c6e..5600a772bed4 100644 --- a/meta.c +++ b/meta.c @@ -1,4 +1,4 @@ -/* $NetBSD: meta.c,v 1.33 2013/10/01 05:37:17 sjg Exp $ */ +/* $NetBSD: meta.c,v 1.38 2015/04/11 05:24:30 sjg Exp $ */ /* * Implement 'meta' mode. @@ -155,8 +155,8 @@ filemon_open(BuildMon *pbm) static void filemon_read(FILE *mfp, int fd) { - FILE *fp; char buf[BUFSIZ]; + int n; /* Check if we're not writing to a meta data file.*/ if (mfp == NULL) { @@ -166,17 +166,14 @@ filemon_read(FILE *mfp, int fd) } /* rewind */ (void)lseek(fd, (off_t)0, SEEK_SET); - if ((fp = fdopen(fd, "r")) == NULL) - err(1, "Could not read build monitor file '%d'", fd); - fprintf(mfp, "-- filemon acquired metadata --\n"); + fprintf(mfp, "\n-- filemon acquired metadata --\n"); - while (fgets(buf, sizeof(buf), fp)) { - fprintf(mfp, "%s", buf); + while ((n = read(fd, buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, mfp); } fflush(mfp); - clearerr(fp); - fclose(fp); + close(fd); } #endif @@ -662,17 +659,21 @@ meta_job_child(Job *job) { #ifdef USE_FILEMON BuildMon *pbm; - pid_t pid; if (job != NULL) { pbm = &job->bm; } else { pbm = &Mybm; } - pid = getpid(); - if (pbm->mfp != NULL && useFilemon) { - if (ioctl(pbm->filemon_fd, FILEMON_SET_PID, &pid) < 0) { - err(1, "Could not set filemon pid!"); + if (pbm->mfp != NULL) { + close(fileno(pbm->mfp)); + if (useFilemon) { + pid_t pid; + + pid = getpid(); + if (ioctl(pbm->filemon_fd, FILEMON_SET_PID, &pid) < 0) { + err(1, "Could not set filemon pid!"); + } } } #endif @@ -844,9 +845,10 @@ string_match(const void *p, const void *q) /* * When running with 'meta' functionality, a target can be out-of-date - * if any of the references in it's meta data file is more recent. + * if any of the references in its meta data file is more recent. * We have to track the latestdir on a per-process basis. */ +#define LCWD_VNAME_FMT ".meta.%d.lcwd" #define LDIR_VNAME_FMT ".meta.%d.ldir" /* @@ -872,11 +874,14 @@ meta_oodate(GNode *gn, Boolean oodate) { static char *tmpdir = NULL; static char cwd[MAXPATHLEN]; + char lcwd_vname[64]; char ldir_vname[64]; + char lcwd[MAXPATHLEN]; char latestdir[MAXPATHLEN]; char fname[MAXPATHLEN]; char fname1[MAXPATHLEN]; char fname2[MAXPATHLEN]; + char fname3[MAXPATHLEN]; char *p; char *cp; char *link_src; @@ -928,6 +933,8 @@ meta_oodate(GNode *gn, Boolean oodate) err(1, "Could not get current working directory"); cwdlen = strlen(cwd); } + strlcpy(lcwd, cwd, sizeof(lcwd)); + strlcpy(latestdir, cwd, sizeof(latestdir)); if (!tmpdir) { tmpdir = getTmpdir(); @@ -1011,9 +1018,11 @@ meta_oodate(GNode *gn, Boolean oodate) char *tp; if (lastpid > 0) { - /* We need to remember this. */ + /* We need to remember these. */ + Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0); Var_Set(ldir_vname, latestdir, VAR_GLOBAL, 0); } + snprintf(lcwd_vname, sizeof(lcwd_vname), LCWD_VNAME_FMT, pid); snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid); lastpid = pid; ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp); @@ -1021,15 +1030,22 @@ meta_oodate(GNode *gn, Boolean oodate) strlcpy(latestdir, ldir, sizeof(latestdir)); if (tp) free(tp); - } else - strlcpy(latestdir, cwd, sizeof(latestdir)); + } + ldir = Var_Value(lcwd_vname, VAR_GLOBAL, &tp); + if (ldir) { + strlcpy(lcwd, ldir, sizeof(lcwd)); + if (tp) + free(tp); + } } /* Skip past the pid. */ if (strsep(&p, " ") == NULL) continue; #ifdef DEBUG_META_MODE if (DEBUG(META)) - fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, latestdir); + fprintf(debug_file, "%s: %d: %d: %c: cwd=%s lcwd=%s ldir=%s\n", + fname, lineno, + pid, buf[0], cwd, lcwd, latestdir); #endif break; } @@ -1039,6 +1055,7 @@ meta_oodate(GNode *gn, Boolean oodate) /* Process according to record type. */ switch (buf[0]) { case 'X': /* eXit */ + Var_Delete(lcwd_vname, VAR_GLOBAL); Var_Delete(ldir_vname, VAR_GLOBAL); lastpid = 0; /* no need to save ldir_vname */ break; @@ -1050,15 +1067,30 @@ meta_oodate(GNode *gn, Boolean oodate) child = atoi(p); if (child > 0) { + snprintf(cldir, sizeof(cldir), LCWD_VNAME_FMT, child); + Var_Set(cldir, lcwd, VAR_GLOBAL, 0); snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child); Var_Set(cldir, latestdir, VAR_GLOBAL, 0); +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: %d: cwd=%s lcwd=%s ldir=%s\n", + fname, lineno, + child, cwd, lcwd, latestdir); +#endif } } break; case 'C': /* Chdir */ - /* Update the latest directory. */ - strlcpy(latestdir, p, sizeof(latestdir)); + /* Update lcwd and latest directory. */ + strlcpy(latestdir, p, sizeof(latestdir)); + strlcpy(lcwd, p, sizeof(lcwd)); + Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0); + Var_Set(ldir_vname, lcwd, VAR_GLOBAL, 0); +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, lcwd); +#endif break; case 'M': /* renaMe */ @@ -1207,11 +1239,16 @@ meta_oodate(GNode *gn, Boolean oodate) snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p); sdirs[sdx++] = fname1; - if (strcmp(latestdir, cwd) != 0) { - /* Check vs cwd */ - snprintf(fname2, sizeof(fname2), "%s/%s", cwd, p); + if (strcmp(latestdir, lcwd) != 0) { + /* Check vs lcwd */ + snprintf(fname2, sizeof(fname2), "%s/%s", lcwd, p); sdirs[sdx++] = fname2; } + if (strcmp(lcwd, cwd) != 0) { + /* Check vs cwd */ + snprintf(fname3, sizeof(fname3), "%s/%s", cwd, p); + sdirs[sdx++] = fname3; + } } sdirs[sdx++] = NULL; @@ -1250,6 +1287,10 @@ meta_oodate(GNode *gn, Boolean oodate) oodate = TRUE; } } + if (buf[0] == 'E') { + /* previous latestdir is no longer relevant */ + strlcpy(latestdir, lcwd, sizeof(latestdir)); + } break; default: break; diff --git a/mk/ChangeLog b/mk/ChangeLog index 80671ef13f00..597d81458827 100644 --- a/mk/ChangeLog +++ b/mk/ChangeLog @@ -1,3 +1,111 @@ +2015-04-16 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150411 + bump version + + * own.mk: put AUTO_OBJ in OPTIONS_DEFAULT_NO rather than YES. + it is here mainly for documentation purposes, since + if using auto.obj.mk it is better done via sys.mk + +2015-04-01 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150401 + + * meta2deps.sh: support @list + + * meta2deps.py: updates from Juniper + o add EXCLUDES + o skip bogus input files. + o treat 'M' and 'L' as both an 'R' and a 'W' + +2015-03-03 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150303 + + * dirdeps.mk: if MK_DIRDEPS_CACHE is yes, use dirdeps-cache + which is built via sub-make so we have a .meta file to tell if + it is out-of-date. + The dirdeps-cache contains the same dependency rules that we + normaly construct on the fly. + This adds a few seconds overhead when the cache is out of date, + but for a large target, the savings can be significant (10-20min). + +2014-11-18 Simon J. Gerraty + + * install-mk (MK_VERSION): 20141118 + + * meta.stage.mk: add stale_staged + + * dirdeps.mk (_DIRDEP_USE_LEVEL): allow this to be tweaked + only useful under very rare conditions such as + FreeBSD's make universe. + + * auto.obj.mk: Allow MK_AUTO_OBJ to set MKOBJDIRS=auto + +2014-11-11 Simon J. Gerraty + + * install-mk (MK_VERSION): 20141111 + + * mkopt.sh: use consistent semantics for _mk_opt and _mk_opts + +2014-11-09 Simon J. Gerraty + + * FILES: include mkopt.sh which allows handling options in shell + scripts in a manner compatible with options.mk + +2014-10-12 Simon J. Gerraty + + * meta.stage.mk: ensure only _STAGED_DIRS under objroot are used + for GENDIRDEPS_FILTER to avoid surprises. + +2014-10-10 Simon J. Gerraty + + * dirdeps.mk (NSkipHostDir): this needs SRCTOP prepended since by + the time it is applied to __depdirs they have. + + * dirdeps.mk fix filtering of _machines since M_dep_qual_fixes + expects patterns like *.${MACHINE} + + * cython.mk (pyprefix?): use pyprefix to find python bits + since prefix might be something else (where we install our + stuff) + +2014-09-11 Simon J. Gerraty + + * install-mk (MK_VERSION): 20140911 + + * dirdeps.mk: add bootstrap target to simplify adding support for + new MACHINE. + +2014-09-01 Simon J. Gerraty + + * gendirdeps.mk: Add handling of GENDIRDEPS_FILTER_DIR_VARS and + GENDIRDEPS_FILTER_VARS to make it easier to produce sharable + Makefile.depend files. + +2014-08-28 Simon J. Gerraty + + * install-mk (MK_VERSION): 20140828 + + * cython.mk: capture logic for building python extension modules + with Cython. + +2014-08-08 Simon J. Gerraty + + * meta.stage.mk (_STAGE_AS_BASENAME_USE): Add StageAs variant + +2014-08-02 Simon J. Gerraty + + * install-mk (MK_VERSION): 20140801 + + * dep.mk: use explicit MKDEP_MK rather than overload MKDEP to + identify the autodep.mk variant. + + * sys.dependfile.mk: delete .MAKE.DEPENDFILE if its + initial value does not match .MAKE.DEPENDFILE_PREFIX + + * meta.autodep.mk: if _bootstrap_dirdeps add RELDIR to DIRDEPS + 2014-05-22 Simon J. Gerraty * install-mk (MK_VERSION): 20140522 diff --git a/mk/FILES b/mk/FILES index 443aa2e9644c..0a72c673f43c 100644 --- a/mk/FILES +++ b/mk/FILES @@ -5,6 +5,7 @@ auto.obj.mk autoconf.mk autodep.mk auto.dep.mk +cython.mk dep.mk doc.mk dpadd.mk @@ -20,7 +21,9 @@ libnames.mk libs.mk links.mk man.mk +manifest.mk mk-files.txt +mkopt.sh nls.mk obj.mk options.mk @@ -49,6 +52,7 @@ sys/SunOS.mk sys/UnixWare.mk target-flags.mk warnings.mk +whats.mk yacc.mk dirdeps.mk gendirdeps.mk diff --git a/mk/auto.dep.mk b/mk/auto.dep.mk index bb2d4c195a77..33137248d450 100644 --- a/mk/auto.dep.mk +++ b/mk/auto.dep.mk @@ -1,6 +1,6 @@ # # RCSid: -# $Id: auto.dep.mk,v 1.2 2010/04/19 17:37:19 sjg Exp $ +# $Id: auto.dep.mk,v 1.3 2014/08/04 05:19:10 sjg Exp $ # # @(#) Copyright (c) 2010, Simon J. Gerraty # @@ -18,7 +18,7 @@ # This module provides automagic dependency generation along the # lines suggested in the GNU make.info -# set MKDEP=auto.dep and dep.mk will include us +# set MKDEP_MK=auto.dep.mk and dep.mk will include us # This version differs from autodep.mk, in that # we use ${.TARGET:T}.d rather than ${.TARGET:T:R}.d diff --git a/mk/auto.obj.mk b/mk/auto.obj.mk index adccd4b87c8c..e25a721cdf69 100644 --- a/mk/auto.obj.mk +++ b/mk/auto.obj.mk @@ -1,4 +1,4 @@ -# $Id: auto.obj.mk,v 1.8 2011/08/08 17:35:20 sjg Exp $ +# $Id: auto.obj.mk,v 1.10 2015/04/16 16:59:00 sjg Exp $ # # @(#) Copyright (c) 2004, Simon J. Gerraty # @@ -34,10 +34,14 @@ Mkdirs= Mkdirs() { \ # if MKOBJDIRS is set to auto (and NOOBJ isn't defined) do some magic... # This will automatically create objdirs as needed. # Skip it if we are just doing 'clean'. +.if ${MK_AUTO_OBJ:Uno} == "yes" +MKOBJDIRS= auto +.endif .if !defined(NOOBJ) && !defined(NO_OBJ) && ${MKOBJDIRS:Uno} == auto # Use __objdir here so it is easier to tweak without impacting # the logic. __objdir?= ${MAKEOBJDIR} +__objdir:= ${__objdir:tA} .if ${.OBJDIR} != ${__objdir} # We need to chdir, make the directory if needed .if !exists(${__objdir}/) && \ @@ -46,11 +50,12 @@ __objdir?= ${MAKEOBJDIR} __objdir_made != echo ${__objdir}/; umask ${OBJDIR_UMASK:U002}; \ ${ECHO_TRACE} "[Creating objdir ${__objdir}...]" >&2; \ ${Mkdirs}; Mkdirs ${__objdir} +__objdir:= ${__objdir:tA} .endif # This causes make to use the specified directory as .OBJDIR .OBJDIR: ${__objdir} .if ${.OBJDIR} != ${__objdir} && ${__objdir_made:Uno:M${__objdir}/*} != "" -.error could not use ${__objdir} +.error could not use ${__objdir}: .OBJDIR=${.OBJDIR} .endif .endif .endif diff --git a/mk/autodep.mk b/mk/autodep.mk index 818c474e843f..84dea816fa35 100644 --- a/mk/autodep.mk +++ b/mk/autodep.mk @@ -1,6 +1,6 @@ # # RCSid: -# $Id: autodep.mk,v 1.33 2014/04/05 22:56:54 sjg Exp $ +# $Id: autodep.mk,v 1.34 2014/08/04 05:12:27 sjg Exp $ # # @(#) Copyright (c) 1999-2010, Simon J. Gerraty # @@ -19,14 +19,9 @@ # The depend target is mainly for backwards compatibility, # dependencies are normally updated as part of compilation. -# set MKDEP=autodep and dep.mk will include us .if !target(__${.PARSEFILE}__) __${.PARSEFILE}__: -# different versions of bsd.dep.mk use these -MKDEP=autodep -MKDEPCMD=autodep - DEPENDFILE?= .depend .for d in ${DEPENDFILE:N.depend} # bmake only groks .depend diff --git a/mk/cython.mk b/mk/cython.mk new file mode 100644 index 000000000000..7d9b8cd6a5b5 --- /dev/null +++ b/mk/cython.mk @@ -0,0 +1,96 @@ +# RCSid: +# $Id: cython.mk,v 1.6 2014/10/15 06:23:51 sjg Exp $ +# +# @(#) Copyright (c) 2014, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# this is what we build +CYTHON_MODULE = ${CYTHON_MODULE_NAME}${CYTHON_PYVERSION}.so + +CYTHON_MODULE_NAME?= it +CYTHON_SRCS?= ${CYTHON_MODULE_NAME}.pyx + +# this is where we save generated src +CYTHON_SAVEGENDIR?= ${.CURDIR}/gen + +# pyprefix is where python bits are +# which may not be where we want to put ours (prefix) +.if exists(/usr/pkg/include) +pyprefix?= /usr/pkg +.endif +pyprefix?= /usr/local + +PYTHON_VERSION?= 2.7 +PYTHON_H?= ${pyprefix}/include/python${PYTHON_VERSION}/Python.h +PYVERSION:= ${PYTHON_VERSION:C,\..*,,} + +# set this empty if you don't want to handle multiple versions +.if !defined(CYTHON_PYVERSION) +CYTHON_PYVERSION:= ${PYVERSION} +.endif + +CFLAGS+= -I${PYTHON_H:H} + +CYTHON_GENSRCS= ${CYTHON_SRCS:R:S,$,${CYTHON_PYVERSION}.c,} +SRCS+= ${CYTHON_GENSRCS} + +.SUFFIXES: .pyx .c .So + +CYTHON?= ${pyprefix}/bin/cython + +# if we don't have cython we can use pre-generated srcs +.if ${type ${CYTHON} 2> /dev/null || echo:L:sh:M/*} == "" +.PATH: ${CYTHON_SAVEGENDIR} +.else + +.if !empty(CYTHON_PYVERSION) +.for c in ${CYTHON_SRCS} +${c:R}${CYTHON_PYVERSION}.${c:E}: $c + ln -sf ${.ALLSRC:M*pyx} ${.TARGET} +.endfor +.endif + +.pyx.c: + ${CYTHON} ${CYTHON_FLAGS} -${PYVERSION} -o ${.TARGET} ${.IMPSRC} + + +save-gen: ${CYTHON_GENSRCS} + mkdir -p ${CYTHON_SAVEGENDIR} + cp -p ${.ALLSRC} ${CYTHON_SAVEGENDIR} + +.endif + +COMPILE.c?= ${CC} -c ${CFLAGS} + +.c.So: + ${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET} + +${CYTHON_MODULE}: ${SRCS:S,.c,.So,} + ${CC} ${CC_SHARED:U-shared} -o ${.TARGET} ${.ALLSRC:M*.So} ${LDADD} + +# conf.host_target() is limited to uname -m rather than uname -p +_HOST_MACHINE!= uname -m +.if ${HOST_TARGET:M*${_HOST_MACHINE}} == "" +PY_HOST_TARGET:= ${HOST_TARGET:S,${_HOST_ARCH:U${uname -p:L:sh}}$,${_HOST_MACHINE},} +.endif + +MODULE_BINDIR?= ${.CURDIR:H}/${PY_HOST_TARGET:U${HOST_TARGET}} + +build-cython-module: ${CYTHON_MODULE} + +install-cython-module: ${CYTHON_MODULE} + test -d ${DESTDIR}${MODULE_BINDIR} || \ + ${INSTALL} -d ${DESTDIR}${MODULE_BINDIR} + ${INSTALL} -m 755 ${.ALLSRC} ${DESTDIR}${MODULE_BINDIR} + +CLEANFILES+= *.So ${CYTHON_MODULE} diff --git a/mk/dep.mk b/mk/dep.mk index b75450097277..b07191a09cbf 100644 --- a/mk/dep.mk +++ b/mk/dep.mk @@ -1,4 +1,4 @@ -# $Id: dep.mk,v 1.16 2012/11/11 22:37:02 sjg Exp $ +# $Id: dep.mk,v 1.17 2014/08/04 05:12:27 sjg Exp $ .if !target(__${.PARSEFILE}__) __${.PARSEFILE}__: @@ -34,21 +34,15 @@ MKDEP ?= ${MKDEP_CMD} .NOPATH: .depend -.if ${MKDEP} == "auto.dep" && make(depend) +.if ${MKDEP_MK:Uno} == "auto.dep.mk" && make(depend) # auto.dep.mk does not "do" depend MK_AUTODEP= no .endif .if ${MK_AUTODEP} == yes -.if ${MKDEP:T:S,auto,,} != ${MKDEP:T} -.include <${MKDEP}.mk> +MKDEP_MK ?= autodep.mk +.include <${MKDEP_MK}> .else -.include -.endif -.else -.if ${MKDEP:T:S,auto,,} != ${MKDEP:T} -MKDEP = ${MKDEP_CMD} -.endif MKDEP_ENV_VARS += CC CXX .for v in ${MKDEP_ENV_VARS:O:u} .if !empty($v) diff --git a/mk/dirdeps.mk b/mk/dirdeps.mk index 8c342be86fc2..fd03c827578e 100644 --- a/mk/dirdeps.mk +++ b/mk/dirdeps.mk @@ -1,4 +1,4 @@ -# $Id: dirdeps.mk,v 1.35 2014/05/03 06:27:56 sjg Exp $ +# $Id: dirdeps.mk,v 1.49 2015/03/11 21:39:28 sjg Exp $ # Copyright (c) 2010-2013, Juniper Networks, Inc. # All rights reserved. @@ -111,7 +111,9 @@ # TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} # -.if ${.MAKE.LEVEL} == 0 +# touch this at your peril +_DIRDEP_USE_LEVEL?= 0 +.if ${.MAKE.LEVEL} == ${_DIRDEP_USE_LEVEL} # only the first instance is interested in all this # First off, we want to know what ${MACHINE} to build for. @@ -121,6 +123,12 @@ .if !target(_DIRDEP_USE) # do some setup we only need once _CURDIR ?= ${.CURDIR} +_OBJDIR ?= ${.OBJDIR} + +now_utc = ${%s:L:gmtime} +.if !defined(start_utc) +start_utc := ${now_utc} +.endif # make sure these are empty to start with _DEP_TARGET_SPEC = @@ -201,7 +209,7 @@ _last_dependfile := ${.INCLUDEDFROMFILE:M${.MAKE.DEPENDFILE_PREFIX}*} .else _last_dependfile := ${.MAKE.MAKEFILES:M*/${.MAKE.DEPENDFILE_PREFIX}*:[-1]} .endif -.if !empty(_debug_reldir) +.if ${_debug_reldir:U0} .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _last_dependfile='${_last_dependfile}' .endif @@ -260,7 +268,7 @@ _DEP_RELDIR := ${DEP_RELDIR} # things we skip for host tools SKIP_HOSTDIR ?= -NSkipHostDir = ${SKIP_HOSTDIR:N*.host:S,$,.host,:N.host:${M_ListToSkip}} +NSkipHostDir = ${SKIP_HOSTDIR:N*.host*:S,$,.host*,:N.host*:S,^,${SRCTOP}/,:${M_ListToSkip}} # things we always skip # SKIP_DIRDEPS allows for adding entries on command line. @@ -332,8 +340,78 @@ _only_machines := ${_only_machines:${NOT_MACHINE_LIST:${M_ListToSkip}}} DIRDEPS ?= ${RELDIR} .endif # target -_debug_reldir := ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.${DEP_MACHINE}:L:M$x}@} -_debug_search := ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.depend:L:M$x}@} +# if repeatedly building the same target, +# we can avoid the overhead of re-computing the tree dependencies. +MK_DIRDEPS_CACHE ?= no +BUILD_DIRDEPS_CACHE ?= no +BUILD_DIRDEPS ?= yes + +.if !defined(NO_DIRDEPS) +.if ${MK_DIRDEPS_CACHE} == "yes" +# this is where we will cache all our work +DIRDEPS_CACHE?= ${_OBJDIR}/dirdeps.cache${.TARGETS:Nall:O:u:ts-:S,^,.,:N.} + +# just ensure this exists +build-dirdeps: + +M_oneperline = @x@\\${.newline} $$x@ + +.if ${BUILD_DIRDEPS_CACHE} == "no" +.if !target(dirdeps-cached) +# we do this via sub-make +BUILD_DIRDEPS = no + +dirdeps: dirdeps-cached +dirdeps-cached: ${DIRDEPS_CACHE} .MAKE + @echo "${TRACER}Using ${DIRDEPS_CACHE}" + @MAKELEVEL=${.MAKE.LEVEL} ${.MAKE} -C ${_CURDIR} -f ${DIRDEPS_CACHE} \ + dirdeps MK_DIRDEPS_CACHE=no BUILD_DIRDEPS=no + +# these should generally do +BUILD_DIRDEPS_MAKEFILE ?= ${MAKEFILE} +BUILD_DIRDEPS_TARGETS ?= ${.TARGETS} + +# we need the .meta file to ensure we update if +# any of the Makefile.depend* changed. +# We do not want to compare the command line though. +${DIRDEPS_CACHE}: .META .NOMETA_CMP + +@{ echo '# Autogenerated - do NOT edit!'; echo; \ + echo 'BUILD_DIRDEPS=no'; echo; \ + echo '.include '; \ + } > ${.TARGET}.new + +@MAKELEVEL=${.MAKE.LEVEL} DIRDEPS_CACHE=${DIRDEPS_CACHE} \ + DIRDEPS="${DIRDEPS}" \ + MAKEFLAGS= ${.MAKE} -C ${_CURDIR} -f ${BUILD_DIRDEPS_MAKEFILE} \ + ${BUILD_DIRDEPS_TARGETS} BUILD_DIRDEPS_CACHE=yes \ + 3>&1 1>&2 | sed 's,${SRCTOP},$${SRCTOP},g' >> ${.TARGET}.new && \ + mv ${.TARGET}.new ${.TARGET} + +.endif +.elif !target(_count_dirdeps) +# we want to capture the dirdeps count in the cache +.END: _count_dirdeps +_count_dirdeps: .NOMETA + @echo '.info $${.newline}$${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]}' >&3 + +.endif +.endif +.elif !target(_count_dirdeps) +beforedirdeps: _count_dirdeps +_count_dirdeps: .NOMETA + @echo "${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]} seconds=`expr ${now_utc} - ${start_utc}`" + +.endif +.if ${BUILD_DIRDEPS} == "yes" +.if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.${DEP_MACHINE}:L:M$x}@} != "" +_debug_reldir = 1 +.else +_debug_reldir = 0 +.endif +.if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.depend:L:M$x}@} != "" +_debug_search = 1 +.else +_debug_search = 0 +.endif # the rest is done repeatedly for every Makefile.depend we read. # if we are anything but the original dir we care only about the @@ -368,7 +446,8 @@ _machines := ${_machines:O:u} # we need to tweak _machines _dm := ${DEP_MACHINE} # apply the same filtering that we do when qualifying DIRDEPS. -_machines := ${_machines:@DEP_MACHINE@${DEP_TARGET_SPEC}@:${M_dep_qual_fixes:ts:}:O:u} +# M_dep_qual_fixes expects .${MACHINE}* so add (and remove) '.' +_machines := ${_machines:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:${M_dep_qual_fixes:ts:}:O:u:S,^.,,} DEP_MACHINE := ${_dm} .endif @@ -388,7 +467,7 @@ _build_dirs += ${_machines:N${DEP_TARGET_SPEC}:@m@${_CURDIR}.$m@} .endif .endif -.if !empty(_debug_reldir) +.if ${_debug_reldir} .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: DIRDEPS='${DIRDEPS}' .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _machines='${_machines}' .endif @@ -419,7 +498,7 @@ __hostdpadd := ${DPADD:U.:M${HOST_OBJTOP}/*:S,${HOST_OBJTOP}/,,:H:${NSkipDir}:${ __qual_depdirs += ${__hostdpadd} .endif -.if !empty(_debug_reldir) +.if ${_debug_reldir} .info depdirs=${__depdirs} .info qualified=${__qual_depdirs} .info unqualified=${__unqual_depdirs} @@ -429,7 +508,8 @@ __qual_depdirs += ${__hostdpadd} _build_dirs += \ ${__qual_depdirs:M*.host:${NSkipHostDir}:N.host} \ ${__qual_depdirs:N*.host} \ - ${_machines:@m@${__unqual_depdirs:@d@$d.$m@}@} + ${_machines:Mhost*:@m@${__unqual_depdirs:@d@$d.$m@}@:${NSkipHostDir}:N.host} \ + ${_machines:Nhost*:@m@${__unqual_depdirs:@d@$d.$m@}@} # qualify everything now _build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u} @@ -441,11 +521,17 @@ _build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u} # but if we want to count the number of Makefile.depend* read, we do. .if ${.MAKEFLAGS:M-V${_V_READ_DIRDEPS}} == "" .if !empty(_build_dirs) +.if ${BUILD_DIRDEPS_CACHE} == "yes" +x!= { echo; echo '\# ${DEP_RELDIR}.${DEP_TARGET_SPEC}'; \ + echo 'dirdeps: ${_build_dirs:${M_oneperline}}'; echo; } >&3; echo +x!= { ${_build_dirs:@x@${target($x):?:echo '$x: _DIRDEP_USE';}@} echo; } >&3; echo +.else # this makes it all happen dirdeps: ${_build_dirs} +.endif ${_build_dirs}: _DIRDEP_USE -.if !empty(_debug_reldir) +.if ${_debug_reldir} .info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs} .endif @@ -454,16 +540,24 @@ ${_build_dirs}: _DIRDEP_USE # it would be nice to do :N${.TARGET} .if !empty(__qual_depdirs) .for q in ${__qual_depdirs:${M_dep_qual_fixes:ts:}:E:O:u:N$m} -.if !empty(_debug_reldir) || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != "" +.if ${_debug_reldir} || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != "" .info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$q} .endif +.if ${BUILD_DIRDEPS_CACHE} == "yes" +x!= { echo; echo '${_this_dir}.$m: ${_build_dirs:M*.$q:${M_oneperline}}'; echo; } >&3; echo +.else ${_this_dir}.$m: ${_build_dirs:M*.$q} +.endif .endfor .endif -.if !empty(_debug_reldir) +.if ${_debug_reldir} .info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m} .endif +.if ${BUILD_DIRDEPS_CACHE} == "yes" +x!= { echo; echo '${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m:${M_oneperline}}'; echo; } >&3; echo +.else ${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m} +.endif .endfor .endif @@ -473,7 +567,7 @@ ${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m} .if ${_DIRDEP_CHECKED:M$d} == "" # once only _DIRDEP_CHECKED += $d -.if !empty(_debug_search) +.if ${_debug_search} .info checking $d .endif # Note: _build_dirs is fully qualifed so d:R is always the directory @@ -485,14 +579,14 @@ _m := ${.MAKE.DEPENDFILE_PREFERENCE:T:S;${TARGET_SPEC}$;${d:E};:S;${MACHINE};${d .if !empty(_m) # M_dep_qual_fixes isn't geared to Makefile.depend _qm := ${_m:C;(\.depend)$;\1.${d:E};:${M_dep_qual_fixes:ts:}} -.if !empty(_debug_search) +.if ${_debug_search} .info Looking for ${_qm} .endif # we pass _DEP_TARGET_SPEC to tell the next step what we want _DEP_TARGET_SPEC := ${d:E} # some makefiles may still look at this _DEP_MACHINE := ${d:E:C/,.*//} -.if !empty(_debug_reldir) && ${_qm} != ${_m} +.if ${_debug_reldir} && ${_qm} != ${_m} .info loading ${_m} for ${d:E} .endif .include <${_m}> @@ -502,6 +596,7 @@ _DEP_MACHINE := ${d:E:C/,.*//} .endfor .endif # -V +.endif # BUILD_DIRDEPS .elif ${.MAKE.LEVEL} > 42 .error You should have stopped recursing by now. @@ -511,3 +606,37 @@ _DEP_RELDIR := ${DEP_RELDIR} .-include <.depend> .endif +# bootstrapping new dependencies made easy? +.if make(bootstrap*) && !target(bootstrap) + +.if exists(${.CURDIR}/${.MAKE.DEPENDFILE:T}) +# stop here +${.TARGETS:Mboot*}: +.else +# find a Makefile.depend to use as _src +_src != cd ${.CURDIR} && for m in ${.MAKE.DEPENDFILE_PREFERENCE:T:S,${MACHINE},*,}; do test -s $$m || continue; echo $$m; break; done; echo +.if empty(_src) +.error cannot find any of ${.MAKE.DEPENDFILE_PREFERENCE:T} +.endif + +_src?= ${.MAKE.DEPENDFILE:T} + +bootstrap-this: .NOTMAIN + @echo Bootstrapping ${RELDIR}/${.MAKE.DEPENDFILE:T} from ${_src:T} + (cd ${.CURDIR} && sed 's,${_src:E},${MACHINE},g' ${_src} > ${.MAKE.DEPENDFILE:T}) + +bootstrap: bootstrap-recurse +bootstrap-recurse: bootstrap-this + +_mf := ${.PARSEFILE} +bootstrap-recurse: .NOTMAIN .MAKE + @cd ${SRCTOP} && \ + for d in `cd ${RELDIR} && ${.MAKE} -B -f ${"${.MAKEFLAGS:M-n}":?${_src}:${.MAKE.DEPENDFILE:T}} -V DIRDEPS`; do \ + test -d $$d || d=$${d%.*}; \ + test -d $$d || continue; \ + echo "Checking $$d for bootstrap ..."; \ + (cd $$d && ${.MAKE} -f ${_mf} bootstrap-recurse); \ + done + +.endif +.endif diff --git a/mk/gendirdeps.mk b/mk/gendirdeps.mk index b313298b3fef..28e1f21652ad 100644 --- a/mk/gendirdeps.mk +++ b/mk/gendirdeps.mk @@ -1,4 +1,4 @@ -# $Id: gendirdeps.mk,v 1.25 2014/03/14 21:28:37 sjg Exp $ +# $Id: gendirdeps.mk,v 1.26 2014/09/05 04:40:52 sjg Exp $ # Copyright (c) 2010-2013, Juniper Networks, Inc. # All rights reserved. @@ -93,6 +93,17 @@ _skip_gendirdeps = egrep -v '^(${SKIP_GENDIRDEPS:O:u:ts|})' | _skip_gendirdeps = .endif +# Below we will turn _{VAR} into ${VAR} which keeps this simple +# GENDIRDEPS_FILTER_DIR_VARS is a list of dirs to be substiuted for. +# GENDIRDEPS_FILTER_VARS is more general. +# In each case order matters. +.if !empty(GENDIRDEPS_FILTER_DIR_VARS) +GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_DIR_VARS:@v@S,${$v},_{${v}},@} +.endif +.if !empty(GENDIRDEPS_FILTER_VARS) +GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_VARS:@v@S,/${$v}/,/_{${v}}/,@:NS,//,*:u} +.endif + # this (*should* be set in meta.sys.mk) # is the script that extracts what we want. META2DEPS ?= ${.PARSEDIR}/meta2deps.sh diff --git a/mk/install-mk b/mk/install-mk index 7e4ee8bba5e7..047fcfda9280 100644 --- a/mk/install-mk +++ b/mk/install-mk @@ -55,7 +55,7 @@ # Simon J. Gerraty # RCSid: -# $Id: install-mk,v 1.100 2014/05/23 01:30:36 sjg Exp $ +# $Id: install-mk,v 1.109 2015/04/16 16:59:00 sjg Exp $ # # @(#) Copyright (c) 1994 Simon J. Gerraty # @@ -70,7 +70,7 @@ # sjg@crufty.net # -MK_VERSION=20140522 +MK_VERSION=20150411 OWNER= GROUP= MODE=444 diff --git a/mk/links.mk b/mk/links.mk index 4ec8a01c415c..aac3914fdd00 100644 --- a/mk/links.mk +++ b/mk/links.mk @@ -1,4 +1,4 @@ -# $Id: links.mk,v 1.5 2005/07/11 18:01:05 sjg Exp $ +# $Id: links.mk,v 1.6 2014/09/29 17:14:40 sjg Exp $ # # @(#) Copyright (c) 2005, Simon J. Gerraty # @@ -22,9 +22,14 @@ SYMLINKS?= __SYMLINK_SCRIPT= \ ${ECHO} "$$t -> $$l"; \ - mkdir -p `dirname $$t`; \ - rm -f $$t; \ - ${LN} -s $$l $$t + case `'ls' -l $$t 2> /dev/null` in \ + *"> $$l") ;; \ + *) \ + mkdir -p `dirname $$t`; \ + rm -f $$t; \ + ${LN} -s $$l $$t;; \ + esac + __LINK_SCRIPT= \ ${ECHO} "$$t -> $$l"; \ diff --git a/mk/manifest.mk b/mk/manifest.mk new file mode 100644 index 000000000000..797038d19391 --- /dev/null +++ b/mk/manifest.mk @@ -0,0 +1,66 @@ +# $Id: manifest.mk,v 1.2 2014/10/31 18:06:17 sjg Exp $ +# +# @(#) Copyright (c) 2014, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# generate mtree style manifest supported by makefs in FreeBSD + +# input looks like +# MANIFEST= my.mtree +# for each MANIFEST we have a list of dirs +# ${MANIFEST}.DIRS += bin sbin usr/bin ... +# for each dir we have a ${MANIFEST}.SRCS.$dir +# that provides the absolute path to the contents +# ${MANIFEST}.SRCS.bin += ${OBJTOP}/bin/sh/sh +# ${MANIFEST}.SYMLINKS is a list of src target pairs +# for each file/dir there are a number of attributes +# UID GID MODE FLAGS +# which can be set per dir, per file or we use defaults +# eg. +# MODE.sbin = 550 +# MODE.usr/sbin = 550 +# MODE.dirs = 555 +# means that sbin and usr/sbin get 550 all other dirs get 555 +# MODE.usr/bin/passwd = 4555 +# MODE.usr/bin.files = 555 +# MODE.usr/sbin.files = 500 +# means passwd gets 4555 other files in usr/bin get 555 and +# files in usr/sbin get 500 +# STORE defaults to basename of src and target directory +# but we can use +# ${MANIFEST}.SRCS.sbin += ${OBJTOP}/bin/sh-static/sh-static +# STORE.sbin/sh-static = sbin/sh +# +# the above is a little overkill but means we can easily adapt to +# different formats + +UID.dirs ?= 0 +GID.dirs ?= 0 +MODE.dirs ?= 775 +FLAGS.dirs ?= + +UID.files ?= 0 +GID.files ?= 0 +MODE.files ?= 555 + +# a is attribute name d is dirname +M_DIR_ATTR = L:@a@$${$$a.$$d:U$${$$a.dirs}}@ +# as above and s is set to the name we store f as +M_FILE_ATTR = L:@a@$${$$a.$$s:U$${$$a.$$d.files:U$${$$a.files}}}@ + +# this produces the body of the manifest +# there should typically be a header prefixed +_GEN_MTREE_MANIFEST_USE: .USE + @(${${.TARGET}.DIRS:O:u:@d@echo '$d type=dir uid=${UID:${M_DIR_ATTR}} gid=${GID:${M_DIR_ATTR}} mode=${MODE:${M_DIR_ATTR}} ${FLAGS:${M_DIR_ATTR}}';@} \ + ${${.TARGET}.DIRS:O:u:@d@${${.TARGET}.SRCS.$d:O:u:@f@echo '${s::=${STORE.$d/${f:T}:U$d/${f:T}}}$s contents="$f" type=file uid=${UID:${M_FILE_ATTR}} gid=${GID:${M_FILE_ATTR}} mode=${MODE:${M_FILE_ATTR}} ${FLAGS:${M_FILE_ATTR}}';@}@} \ + set ${${.TARGET}.SYMLINKS}; while test $$# -ge 2; do echo "$$2 type=link link=$$1"; shift 2; done) > ${.TARGET} diff --git a/mk/meta.autodep.mk b/mk/meta.autodep.mk index a961bffb4646..64bc30bd4757 100644 --- a/mk/meta.autodep.mk +++ b/mk/meta.autodep.mk @@ -1,4 +1,4 @@ -# $Id: meta.autodep.mk,v 1.35 2014/05/09 00:05:46 sjg Exp $ +# $Id: meta.autodep.mk,v 1.36 2014/08/02 23:10:29 sjg Exp $ # # @(#) Copyright (c) 2010, Simon J. Gerraty @@ -254,6 +254,9 @@ ${_DEPENDFILE}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.MET .endif .if ${_bootstrap_dirdeps} == "yes" +.if ${BUILD_AT_LEVEL0:Uno} == "no" +DIRDEPS+= ${RELDIR}.${TARGET_SPEC:U${MACHINE}} +.endif # make sure this is included at least once .include .else diff --git a/mk/meta.stage.mk b/mk/meta.stage.mk index 2f02700fdc19..cd951136fb72 100644 --- a/mk/meta.stage.mk +++ b/mk/meta.stage.mk @@ -1,4 +1,4 @@ -# $Id: meta.stage.mk,v 1.30 2013/04/19 16:32:57 sjg Exp $ +# $Id: meta.stage.mk,v 1.34 2014/11/20 22:40:08 sjg Exp $ # # @(#) Copyright (c) 2011, Simon J. Gerraty # @@ -35,7 +35,13 @@ _stage_file_basename = $${f\#\#*/} _stage_target_dirname = $${t%/*} .endif +_OBJROOT ?= ${OBJROOT:U${OBJTOP:H}} +.if ${_OBJROOT:M*/} != "" +_objroot ?= ${_OBJROOT:tA}/ +.else _objroot ?= ${_OBJROOT:tA} +.endif + # make sure this is global _STAGED_DIRS ?= .export _STAGED_DIRS @@ -46,7 +52,7 @@ STAGE_DIR_FILTER = tA:@d@$${_STAGED_DIRS::+=$$d}$$d@ # convert _STAGED_DIRS into suitable filters GENDIRDEPS_FILTER += Nnot-empty-is-important \ ${_STAGED_DIRS:O:u:M${OBJTOP}*:S,${OBJTOP}/,N,} \ - ${_STAGED_DIRS:O:u:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,} + ${_STAGED_DIRS:O:u:M${_objroot}*:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,} LN_CP_SCRIPT = LnCp() { \ rm -f $$2 2> /dev/null; \ @@ -113,10 +119,14 @@ STAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \ _STAGE_BASENAME_USE: .USE ${.TARGET:T} @${STAGE_FILE_SCRIPT}; StageFiles ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} +_STAGE_AS_BASENAME_USE: .USE ${.TARGET:T} + @${STAGE_AS_SCRIPT}; StageAs ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} ${STAGE_AS_${.TARGET:T}:U${.TARGET:T}} + .if !empty(STAGE_INCSDIR) STAGE_TARGETS += stage_incs STAGE_INCS ?= ${.ALLSRC:N.dirdep} +stage_includes: stage_incs stage_incs: .dirdep @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_INCSDIR:${STAGE_DIR_FILTER}} ${STAGE_INCS} @touch $@ @@ -129,11 +139,13 @@ STAGE_LIBS ?= ${.ALLSRC:N.dirdep} stage_libs: .dirdep @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${STAGE_LIBS} +.if !defined(NO_SHLIB_LINKS) .if !empty(SHLIB_LINKS) @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} \ ${SHLIB_LINKS:@t@${STAGE_LIBS:T:M$t.*} $t@} .elif !empty(SHLIB_LINK) && !empty(SHLIB_NAME) @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${SHLIB_NAME} ${SHLIB_LINK} ${SYMLINKS:T} +.endif .endif @touch $@ .endif @@ -212,7 +224,7 @@ stage_as.$s: .dirdep .endfor .endif -CLEANFILES += ${STAGE_TARGETS} +CLEANFILES += ${STAGE_TARGETS} stage_incs stage_includes # stage_*links usually needs to follow any others. .for t in ${STAGE_TARGETS:N*links:O:u} @@ -240,5 +252,26 @@ INSTALL := ${STAGE_INSTALL} beforeinstall: .dirdep .endif .endif +.NOPATH: ${STAGE_FILES} + +.if !empty(STAGE_TARGETS) +MK_STALE_STAGED?= no +.if ${MK_STALE_STAGED} == "yes" +all: stale_staged +# get a list of paths that we have just staged +# get a list of paths that we have previously staged to those same dirs +# anything in the 2nd list but not the first is stale - remove it. +stale_staged: staging .NOMETA + @egrep '^[WL] .*${STAGE_OBJTOP}' /dev/null ${.MAKE.META.FILES:M*stage_*} | \ + sed "/\.dirdep/d;s,.* '*\(${STAGE_OBJTOP}/[^ '][^ ']*\).*,\1," | \ + sort > ${.TARGET}.staged1 + @grep -l '${_dirdep}' /dev/null ${_STAGED_DIRS:M${STAGE_OBJTOP}*:O:u:@d@$d/*.dirdep@} | \ + sed 's,\.dirdep,,' | sort > ${.TARGET}.staged2 + @comm -13 ${.TARGET}.staged1 ${.TARGET}.staged2 > ${.TARGET}.stale + @test ! -s ${.TARGET}.stale || { \ + echo "Removing stale staged files..."; \ + sed 's,.*,& &.dirdep,' ${.TARGET}.stale | xargs rm -f; } .endif +.endif +.endif diff --git a/mk/meta.sys.mk b/mk/meta.sys.mk index 1707a6670bb5..bcafd5593212 100644 --- a/mk/meta.sys.mk +++ b/mk/meta.sys.mk @@ -1,4 +1,4 @@ -# $Id: meta.sys.mk,v 1.16 2012/07/03 05:26:00 sjg Exp $ +# $Id: meta.sys.mk,v 1.20 2014/08/04 05:12:27 sjg Exp $ # # @(#) Copyright (c) 2010, Simon J. Gerraty @@ -106,7 +106,13 @@ _metaError: .NOMETA .NOTMAIN # Are we, after all, in meta mode? .if ${.MAKE.MODE:Mmeta*} != "" -MKDEP = meta.autodep +MKDEP_MK = meta.autodep.mk + +# if we think we are updating dependencies, +# then filemon had better be present +.if ${UPDATE_DEPENDFILE:Uyes:tl} != "no" && !exists(/dev/filemon) +.error ${.newline}ERROR: The filemon module (/dev/filemon) is not loaded. +.endif .if ${.MAKE.LEVEL} == 0 # make sure dirdeps target exists and do it first @@ -121,19 +127,11 @@ dirdeps: # tell dirdeps.mk what we want BUILD_AT_LEVEL0 = no .endif - -.if ${.MAKE.DEPENDFILE:E} == ${MACHINE} +.if ${.TARGETS:Nall} == "" # it works best if we do everything via sub-makes BUILD_AT_LEVEL0 ?= no .endif -BUILD_AT_LEVEL0 ?= yes -.endif -# if we think we are updating dependencies, -# then filemon had better be present -.if ${UPDATE_DEPENDFILE:Uyes:tl} != "no" && !exists(/dev/filemon) -.error ${.newline}ERROR: The filemon module (/dev/filemon) is not loaded. .endif - .endif .endif diff --git a/mk/meta2deps.py b/mk/meta2deps.py index 8e349e702e5b..ed183f0b944c 100755 --- a/mk/meta2deps.py +++ b/mk/meta2deps.py @@ -37,7 +37,7 @@ We only pay attention to a subset of the information in the """ RCSid: - $Id: meta2deps.py,v 1.17 2014/04/05 22:56:54 sjg Exp $ + $Id: meta2deps.py,v 1.18 2015/04/03 18:23:25 sjg Exp $ Copyright (c) 2011-2013, Juniper Networks, Inc. All rights reserved. @@ -112,7 +112,8 @@ def abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): rpath = resolve(path, cwd, last_dir, debug, debug_out) if rpath: path = rpath - if (path.find('./') > 0 or + if (path.find('/') < 0 or + path.find('./') > 0 or path.endswith('/..') or os.path.islink(path)): return os.path.realpath(path) @@ -142,7 +143,7 @@ class MetaFile: host_target = None srctops = [] objroots = [] - + excludes = [] seen = {} obj_deps = [] src_deps = [] @@ -179,6 +180,10 @@ class MetaFile: This can allow 'bmake' to learn all the dirs within the tree that depend on 'foo.h' + EXCLUDES + A list of paths to ignore. + ccache(1) can otherwise be trouble. + debug desired debug level debug_out open file to send debug output to (sys.stderr) @@ -236,11 +241,14 @@ class MetaFile: # we want the longest match self.srctops.sort(reverse=True) self.objroots.sort(reverse=True) - + + self.excludes = getv(conf, 'EXCLUDES', []) + if self.debug: print("host_target=", self.host_target, file=self.debug_out) print("srctops=", self.srctops, file=self.debug_out) print("objroots=", self.objroots, file=self.debug_out) + print("excludes=", self.excludes, file=self.debug_out) self.dirdep_re = re.compile(r'([^/]+)/(.+)') @@ -257,6 +265,7 @@ class MetaFile: self.dpdeps = None # we cannot do it? self.cwd = os.getcwd() # make sure this is initialized + self.last_dir = self.cwd if name: self.try_parse() @@ -360,18 +369,18 @@ class MetaFile: V 3 C "pid" "cwd" E "pid" "path" - F "pid" "child" + F "pid" "child" R "pid" "path" W "pid" "path" X "pid" "status" - D "pid" "path" - L "pid" "src" "target" - M "pid" "old" "new" - S "pid" "path" - # Bye bye - - We go to some effort to avoid processing a dependency more than once. - Of the above record types only C,E,F,L,R,V and W are of interest. + D "pid" "path" + L "pid" "src" "target" + M "pid" "old" "new" + S "pid" "path" + # Bye bye + + We go to some effort to avoid processing a dependency more than once. + Of the above record types only C,E,F,L,R,V and W are of interest. """ version = 0 # unknown @@ -379,7 +388,7 @@ class MetaFile: self.name = name; if file: f = file - cwd = last_dir = self.cwd + cwd = self.last_dir = self.cwd else: f = open(self.name, 'r') skip = True @@ -412,7 +421,7 @@ class MetaFile: interesting += 'W' """ elif w[0] == 'CWD': - self.cwd = cwd = last_dir = w[1] + self.cwd = cwd = self.last_dir = w[1] self.seenit(cwd) # ignore this if self.debug: print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out) @@ -422,9 +431,9 @@ class MetaFile: if pid != last_pid: if last_pid: pid_cwd[last_pid] = cwd - pid_last_dir[last_pid] = last_dir + pid_last_dir[last_pid] = self.last_dir cwd = getv(pid_cwd, pid, self.cwd) - last_dir = getv(pid_last_dir, pid, self.cwd) + self.last_dir = getv(pid_last_dir, pid, self.cwd) last_pid = pid # process operations @@ -438,7 +447,7 @@ class MetaFile: cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) if cwd.endswith('/.'): cwd = cwd[0:-2] - last_dir = cwd + self.last_dir = cwd if self.debug > 1: print("cwd=", cwd, file=self.debug_out) continue @@ -449,98 +458,114 @@ class MetaFile: continue # file operations if w[0] in 'ML': - path = w[2].strip("'") - else: - path = w[2] - # we are never interested in .dirdep files as dependencies - if path.endswith('.dirdep'): + # these are special, tread src as read and + # target as write + self.parse_path(w[1].strip("'"), cwd, 'R', w) + self.parse_path(w[2].strip("'"), cwd, 'W', w) continue - # we don't want to resolve the last component if it is - # a symlink - path = resolve(path, cwd, last_dir, self.debug, self.debug_out) - if not path: - continue - dir,base = os.path.split(path) - if dir in self.seen: + elif w[0] in 'ERWS': + path = w[2] + self.parse_path(path, cwd, w[0], w) + + if not file: + f.close() + + def parse_path(self, path, cwd, op=None, w=[]): + """look at a path for the op specified""" + + if not op: + op = w[0] + + # we are never interested in .dirdep files as dependencies + if path.endswith('.dirdep'): + return + for p in self.excludes: + if p and path.startswith(p): if self.debug > 2: - print("seen:", dir, file=self.debug_out) - continue - # we can have a path in an objdir which is a link - # to the src dir, we may need to add dependencies for each - rdir = dir - dir = abspath(dir, cwd, last_dir, self.debug, self.debug_out) - if rdir == dir or rdir.find('./') > 0: - rdir = None - # now put path back together - path = '/'.join([dir,base]) - if self.debug > 1: - print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) - if w[0] in 'SRWL': - if w[0] == 'W' and path.endswith('.dirdep'): - continue - if path in [last_dir, cwd, self.cwd, self.curdir]: - if self.debug > 1: - print("skipping:", path, file=self.debug_out) - continue - if os.path.isdir(path): - if w[0] in 'RW': - last_dir = path; - if self.debug > 1: - print("ldir=", last_dir, file=self.debug_out) - continue + print >> self.debug_out, "exclude:", p, path + return + # we don't want to resolve the last component if it is + # a symlink + path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out) + if not path: + return + dir,base = os.path.split(path) + if dir in self.seen: + if self.debug > 2: + print("seen:", dir, file=self.debug_out) + return + # we can have a path in an objdir which is a link + # to the src dir, we may need to add dependencies for each + rdir = dir + dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out) + if rdir == dir or rdir.find('./') > 0: + rdir = None + # now put path back together + path = '/'.join([dir,base]) + if self.debug > 1: + print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) + if op in 'RWS': + if path in [self.last_dir, cwd, self.cwd, self.curdir]: + if self.debug > 1: + print("skipping:", path, file=self.debug_out) + return + if os.path.isdir(path): + if op in 'RW': + self.last_dir = path; + if self.debug > 1: + print("ldir=", self.last_dir, file=self.debug_out) + return + + if op in 'ERW': + # finally, we get down to it + if dir == self.cwd or dir == self.curdir: + return + srctop = self.find_top(path, self.srctops) + if srctop: + if self.dpdeps: + self.add(self.file_deps, path.replace(srctop,''), 'file') + self.add(self.src_deps, dir.replace(srctop,''), 'src') + self.seenit(w[2]) + self.seenit(dir) + if rdir and not rdir.startswith(srctop): + dir = rdir # for below + rdir = None + else: + return - if w[0] in 'REWML': - # finally, we get down to it - if dir == self.cwd or dir == self.curdir: + objroot = None + for dir in [dir,rdir]: + if not dir: continue - srctop = self.find_top(path, self.srctops) - if srctop: - if self.dpdeps: - self.add(self.file_deps, path.replace(srctop,''), 'file') - self.add(self.src_deps, dir.replace(srctop,''), 'src') - self.seenit(w[2]) - self.seenit(dir) - if rdir and not rdir.startswith(srctop): - dir = rdir # for below - rdir = None - else: - continue - - objroot = None - for dir in [dir,rdir]: - if not dir: - continue - objroot = self.find_top(dir, self.objroots) - if objroot: - break + objroot = self.find_top(dir, self.objroots) if objroot: - ddep = self.find_obj(objroot, dir, path, w[2]) - if ddep: - self.add(self.obj_deps, ddep, 'obj') - else: - # don't waste time looking again - self.seenit(w[2]) - self.seenit(dir) - if not file: - f.close() + break + if objroot: + ddep = self.find_obj(objroot, dir, path, w[2]) + if ddep: + self.add(self.obj_deps, ddep, 'obj') + else: + # don't waste time looking again + self.seenit(w[2]) + self.seenit(dir) def main(argv, klass=MetaFile, xopts='', xoptf=None): """Simple driver for class MetaFile. Usage: - script [options] [key=value ...] "meta" ... + script [options] [key=value ...] "meta" ... Options and key=value pairs contribute to the dictionary passed to MetaFile. -S "SRCTOP" - add "SRCTOP" to the "SRCTOPS" list. + add "SRCTOP" to the "SRCTOPS" list. -C "CURDIR" -O "OBJROOT" - add "OBJROOT" to the "OBJROOTS" list. + add "OBJROOT" to the "OBJROOTS" list. -m "MACHINE" @@ -550,7 +575,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None): -D "DPDEPS" - -d bumps debug level + -d bumps debug level """ import getopt @@ -568,6 +593,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None): conf = { 'SRCTOPS': [], 'OBJROOTS': [], + 'EXCLUDES': [], } try: @@ -589,7 +615,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None): debug = 0 output = True - opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:' + xopts) + opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts) for o, a in opts: if o == '-a': conf['MACHINE_ARCH'] = a @@ -615,6 +641,9 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None): conf['MACHINE'] = a elif o == '-T': conf['TARGET_SPEC'] = a + elif o == '-X': + if a not in conf['EXCLUDES']: + conf['EXCLUDES'].append(a) elif xoptf: xoptf(o, a, conf) @@ -649,16 +678,21 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None): for k,v in list(conf.items()): print("%s=%s" % (k,v), file=debug_out) + m = None for a in args: if a.endswith('.meta'): + if not os.path.exists(a): + continue m = klass(a, conf) elif a.startswith('@'): # there can actually multiple files per line for line in open(a[1:]): for f in line.strip().split(): + if not os.path.exists(f): + continue m = klass(f, conf) - if output: + if output and m: print(m.dirdeps()) print(m.src_dirdeps('\nsrc:')) diff --git a/mk/meta2deps.sh b/mk/meta2deps.sh index d96ce07c5af4..2a79be17a331 100755 --- a/mk/meta2deps.sh +++ b/mk/meta2deps.sh @@ -77,7 +77,7 @@ # RCSid: -# $Id: meta2deps.sh,v 1.7 2014/04/05 22:56:54 sjg Exp $ +# $Id: meta2deps.sh,v 1.9 2015/04/03 18:23:25 sjg Exp $ # Copyright (c) 2010-2013, Juniper Networks, Inc. # All rights reserved. @@ -139,10 +139,15 @@ add_list() { eval "$name=\"$list\"" } +_excludes_f() { + egrep -v "$EXCLUDES" +} + meta2deps() { DPDEPS= SRCTOPS=$SRCTOP OBJROOTS= + EXCLUDES= while : do case "$1" in @@ -153,6 +158,7 @@ meta2deps() { -H) HOST_TARGET=$2; shift 2;; -S) add_list SRCTOPS $2; shift 2;; -O) add_list OBJROOTS $2; shift 2;; + -X) add_list EXCLUDES '|' $2; shift 2;; -R) RELDIR=$2; shift 2;; -T) TARGET_SPEC=$2; shift 2;; *) break;; @@ -212,8 +218,26 @@ meta2deps() { seenit= seensrc= lpid= - cat /dev/null "$@" | - sed -e 's,^CWD,C C,;/^[CREFL] /!d' -e "s,',,g" | + case "$EXCLUDES" in + "") _excludes=cat;; + *) _excludes=_excludes_f;; + esac + # handle @list files + case "$@" in + *@[!.]*) + for f in "$@" + do + case "$f" in + *.meta) cat $f;; + @*) xargs cat < ${f#@};; + *) cat $f;; + esac + done + ;; + *) cat /dev/null "$@";; + esac 2> /dev/null | + sed -e 's,^CWD,C C,;/^[CREFLM] /!d' -e "s,',,g" | + $_excludes | while read op pid path junk do : op=$op pid=$pid path=$path diff --git a/mk/mk-files.txt b/mk/mk-files.txt index 78826417b859..7eebfd6bcb36 100644 --- a/mk/mk-files.txt +++ b/mk/mk-files.txt @@ -432,13 +432,27 @@ You should never need to edit ``warnings.mk``, it will include ``warnings-sets.mk`` if it exists and you use that to make any local customizations. +rst2htm.mk +---------- + +Logic to simplify generating HTML (and PDF) documents from ReStructuredText. + +cython.mk +--------- + +Logic to build Python C interface modules using Cython_ + +.. _Cython: http://www.cython.org/ + Meta mode ========= The 20110505 and later versions of ``mk-files`` include a number of -makefile contributed by Juniper Networks, Inc. -These allow the latest version of bmake_ to run in `meta mode`_. +makefiles contributed by Juniper Networks, Inc. +These allow the latest version of bmake_ to run in `meta mode`_ +see `dirdeps.mk`_ +.. _`dirdeps.mk`: /help/sjg/dirdeps.htm .. _`meta mode`: bmake-meta-mode.htm Install @@ -463,5 +477,5 @@ where you unpacked the tar file, you can:: .. _mk.tar.gz: http://www.crufty.net/ftp/pub/sjg/mk.tar.gz :Author: sjg@crufty.net -:Revision: $Id: mk-files.txt,v 1.15 2011/06/08 07:06:18 sjg Exp $ +:Revision: $Id: mk-files.txt,v 1.16 2014/09/05 04:41:16 sjg Exp $ :Copyright: Crufty.NET diff --git a/mk/mkopt.sh b/mk/mkopt.sh new file mode 100755 index 000000000000..38b624ef1d24 --- /dev/null +++ b/mk/mkopt.sh @@ -0,0 +1,94 @@ +: +# $Id: mkopt.sh,v 1.8 2014/11/15 07:07:18 sjg Exp $ +# +# @(#) Copyright (c) 2014, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# handle WITH[OUT]_* options in a manner compatible with +# options.mk and bsd.mkopt.mk in recent FreeBSD + +# no need to be included more than once +_MKOPT_SH=: + +# +# _mk_opt OPT default +# +# Set MK_$OPT +# +# The semantics are simple, if MK_$OPT has no value +# WITHOUT_$OPT results in MK_$OPT=no +# otherwise WITH_$OPT results in MK_$OPT=yes. +# Note WITHOUT_$OPT overrides WITH_$OPT. +# +# For backwards compatability reasons we treat WITH_$OPT=no +# the same as WITHOUT_$OPT. +# +_mk_opt() { + _d=$1 + _mo=MK_$2 _wo=WITHOUT_$2 _wi=WITH_$2 + eval "_mov=\$$_mo _wov=\$$_wo _wiv=\$$_wi" + + case "$_wiv" in + no) _wov=no;; + esac + _v=${_mov:-${_wov:+no}} + _v=${_v:-${_wiv:+yes}} + _v=${_v:-$_d} + _opt_list="$_opt_list $_mo" + case "$_v" in + yes|no) ;; # sane + 0|[NnFf]*) _v=no;; # they mean no + 1|[YyTt]*) _v=yes;; # they mean yes + *) _v=$_d;; # ignore bogus value + esac + eval "$_mo=$_v" +} + +# +# _mk_opts default opt ... [default [opt] ...] +# +# see _mk_opts_defaults for example +# +_mk_opts() { + _d=no + for _o in "$@" + do + case "$_o" in + yes|no) _d=$_o; continue;; + esac + _mk_opt $_d $_o + done +} + +_mk_opts_defaults() { + _mk_opts no $__DEFAULT_NO_OPTIONS yes $__DEFAULT_YES_OPTIONS +} + +case "/$0" in +*/mkopt*) + _list=no + while : + do + case "$1" in + *=*) eval "$1"; shift;; + --no|no) _list="$_list no"; shift;; + --yes|yes) _list="$_list yes"; shift;; + -DWITH*) eval "${1#-D}=1"; shift;; + [A-Z]*) _list="$_list $1"; shift;; + *) break;; + esac + done + _mk_opts $_list + ;; +esac + diff --git a/mk/own.mk b/mk/own.mk index e29ff9e6d6c7..f090bbe8e537 100644 --- a/mk/own.mk +++ b/mk/own.mk @@ -1,4 +1,4 @@ -# $Id: own.mk,v 1.27 2013/07/18 05:46:24 sjg Exp $ +# $Id: own.mk,v 1.28 2015/04/16 16:59:00 sjg Exp $ .if !target(__${.PARSEFILE}__) __${.PARSEFILE}__: @@ -89,6 +89,7 @@ OPTIONS_DEFAULT_NO+= DPADD_MK # process options OPTIONS_DEFAULT_NO+= \ + AUTO_OBJ \ INSTALL_AS_USER \ GPROF \ LIBTOOL \ @@ -98,7 +99,6 @@ OPTIONS_DEFAULT_NO+= \ OPTIONS_DEFAULT_YES+= \ ARCHIVE \ AUTODEP \ - AUTO_OBJ \ CRYPTO \ DOC \ DPADD_MK \ diff --git a/mk/sys.dependfile.mk b/mk/sys.dependfile.mk index 42cec61fce13..e915082e778c 100644 --- a/mk/sys.dependfile.mk +++ b/mk/sys.dependfile.mk @@ -1,4 +1,4 @@ -# $Id: sys.dependfile.mk,v 1.5 2013/03/08 00:59:21 sjg Exp $ +# $Id: sys.dependfile.mk,v 1.6 2014/08/02 18:02:06 sjg Exp $ # # @(#) Copyright (c) 2012, Simon J. Gerraty # @@ -25,6 +25,12 @@ # All depend file names should start with this .MAKE.DEPENDFILE_PREFIX ?= Makefile.depend +.if !empty(.MAKE.DEPENDFILE) && \ + ${.MAKE.DEPENDFILE:M${.MAKE.DEPENDFILE_PREFIX}*} == "" +# let us do our thing below... +.undef .MAKE.DEPENDFILE +.endif + # The order of preference: we will use the first one of these we find. # It usually makes sense to order from most specific to least. .MAKE.DEPENDFILE_PREFERENCE ?= \ diff --git a/mk/whats.mk b/mk/whats.mk new file mode 100644 index 000000000000..d17c3ef290ea --- /dev/null +++ b/mk/whats.mk @@ -0,0 +1,63 @@ +# $Id: whats.mk,v 1.1 2014/08/30 22:40:47 sjg Exp $ +# +# @(#) Copyright (c) 2014, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if ${MK_WHATSTRING:Uno} != "no" +what_build_exts?= o +# it can be useful to embed a what(1) string in binaries +# so that the build location can be seen from a core file. +.if defined(PROG) && ${.MAKE.MAKEFILES:M*prog.mk} != "" +what_thing?= ${PROGNAME:U${PROG}} +what_build_thing?= ${PROG} +.elif defined(LIB) && ${.MAKE.MAKEFILES:M*lib.mk} != "" +# probably only makes sense for shared libs +# and the plumbing needed varies depending on *lib.mk +what_thing?= lib${LIB} +.if !empty(SOBJS) +_soe:= ${SOBJS:E:[1]} +what_build_exts= ${_soe} +SOBJS+= ${what_uuid}.${_soe} +.endif +.elif defined(KMOD) && ${.MAKE.MAKEFILES:M*kmod.mk} != "" +what_thing?= ${KMOD} +what_build_thing?= ${KMOD}.ko +.endif + +.if !empty(what_thing) +# a unique name that won't conflict with anything +what_uuid = what_${.CURDIR:T:hash} + +.if !empty(what_build_thing) +${what_build_thing}: ${what_build_exts:@e@${what_uuid}.$e@} +.endif +OBJS+= ${what_uuid}.o +CLEANFILES+= ${what_uuid}.c + +# we do not need to capture this +SUPPRESS_DEPEND+= *${what_uuid}.c + +SB?= ${SRCTOP:H} +SB_LOCATION?= ${HOST}:${SB} +what_location:= ${.OBJDIR:S,${SB},${SB_LOCATION},} + +# this works with clang and gcc +_what_t= const char __attribute__ ((section(".data"))) +_what1:= @(\#)${what_thing:tu} built ${%Y%m%d:L:localtime} by ${USER} +_what2:= @(\#)${what_location} + +${what_uuid}.c: + echo '${_what_t} ${what_uuid}1[] = "${_what1}";' > $@ ${.OODATE:MNO_META_CMP} + echo '${_what_t} ${what_uuid}2[] = "${_what2}";' >> $@ +.endif +.endif diff --git a/nonints.h b/nonints.h index c19ba895de9b..b244f0bd89b0 100644 --- a/nonints.h +++ b/nonints.h @@ -1,4 +1,4 @@ -/* $NetBSD: nonints.h,v 1.65 2012/08/30 21:17:05 sjg Exp $ */ +/* $NetBSD: nonints.h,v 1.67 2014/09/07 20:55:34 joerg Exp $ */ /*- * Copyright (c) 1988, 1989, 1990, 1993 diff --git a/parse.c b/parse.c index 0f9a8fcc336d..a55582ec1cd2 100644 --- a/parse.c +++ b/parse.c @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $ */ +/* $NetBSD: parse.c,v 1.204 2014/09/18 08:06:13 dholland Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $"; +static char rcsid[] = "$NetBSD: parse.c,v 1.204 2014/09/18 08:06:13 dholland Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: parse.c,v 1.194 2014/02/15 00:17:17 christos Exp $"); +__RCSID("$NetBSD: parse.c,v 1.204 2014/09/18 08:06:13 dholland Exp $"); #endif #endif /* not lint */ #endif @@ -1203,7 +1203,17 @@ ParseDoDependency(char *line) curTargs = Lst_Init(FALSE); + /* + * First, grind through the targets. + */ + do { + /* + * Here LINE points to the beginning of the next word, and + * LSTART points to the actual beginning of the line. + */ + + /* Find the end of the next word. */ for (cp = line; *cp && (ParseIsEscaped(lstart, cp) || !(isspace((unsigned char)*cp) || *cp == '!' || *cp == ':' || *cp == LPAREN)); @@ -1226,6 +1236,10 @@ ParseDoDependency(char *line) } } + /* + * If the word is followed by a left parenthesis, it's the + * name of an object file inside an archive (ar file). + */ if (!ParseIsEscaped(lstart, cp) && *cp == LPAREN) { /* * Archives must be handled specially to make sure the OP_ARCHV @@ -1242,13 +1256,16 @@ ParseDoDependency(char *line) "Error in archive specification: \"%s\"", line); goto out; } else { + /* Done with this word; on to the next. */ continue; } } - savec = *cp; if (!*cp) { /* + * We got to the end of the line while we were still + * looking at targets. + * * Ending a dependency line without an operator is a Bozo * no-no. As a heuristic, this is also often triggered by * undetected conflicts from cvs/rcs merges. @@ -1263,10 +1280,13 @@ ParseDoDependency(char *line) : "Need an operator"); goto out; } + + /* Insert a null terminator. */ + savec = *cp; *cp = '\0'; /* - * Have a word in line. See if it's a special target and set + * Got the word. See if it's a special target and if so set * specType to match it. */ if (*line == '.' && isupper ((unsigned char)line[1])) { @@ -1405,6 +1425,8 @@ ParseDoDependency(char *line) (void)Lst_AtEnd(curTargs, line); } + /* Apply the targets. */ + while(!Lst_IsEmpty(curTargs)) { char *targName = (char *)Lst_DeQueue(curTargs); @@ -1422,7 +1444,9 @@ ParseDoDependency(char *line) Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); } + /* Don't need the inserted null terminator any more. */ *cp = savec; + /* * If it is a special type and not .PATH, it's the only target we * allow on this line... @@ -1498,12 +1522,21 @@ ParseDoDependency(char *line) goto out; } - cp++; /* Advance beyond operator */ + /* Advance beyond the operator */ + cp++; + /* + * Apply the operator to the target. This is how we remember which + * operator a target was defined with. It fails if the operator + * used isn't consistent across all references. + */ Lst_ForEach(targets, ParseDoOp, &op); /* - * Get to the first source + * Onward to the sources. + * + * LINE will now point to the first source word, if any, or the + * end of the string if not. */ while (*cp && isspace ((unsigned char)*cp)) { cp++; @@ -1962,6 +1995,40 @@ Parse_DoVar(char *line, GNode *ctxt) } +/* + * ParseMaybeSubMake -- + * Scan the command string to see if it a possible submake node + * Input: + * cmd the command to scan + * Results: + * TRUE if the command is possibly a submake, FALSE if not. + */ +static Boolean +ParseMaybeSubMake(const char *cmd) +{ + size_t i; + static struct { + const char *name; + size_t len; + } vals[] = { +#define MKV(A) { A, sizeof(A) - 1 } + MKV("${MAKE}"), + MKV("${.MAKE}"), + MKV("$(MAKE)"), + MKV("$(.MAKE)"), + MKV("make"), + }; + for (i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) { + char *ptr; + if ((ptr = strstr(cmd, vals[i].name)) == NULL) + continue; + if ((ptr == cmd || !isalnum((unsigned char)ptr[-1])) + && !isalnum((unsigned char)ptr[vals[i].len])) + return TRUE; + } + return FALSE; +} + /*- * ParseAddCmd -- * Lst_ForEach function to add a command line to all targets @@ -1974,7 +2041,9 @@ Parse_DoVar(char *line, GNode *ctxt) * Always 0 * * Side Effects: - * A new element is added to the commands list of the node. + * A new element is added to the commands list of the node, + * and the node can be marked as a submake node if the command is + * determined to be that. */ static int ParseAddCmd(void *gnp, void *cmd) @@ -1988,6 +2057,8 @@ ParseAddCmd(void *gnp, void *cmd) /* if target already supplied, ignore commands */ if (!(gn->type & OP_HAS_COMMANDS)) { (void)Lst_AtEnd(gn->commands, cmd); + if (ParseMaybeSubMake(cmd)) + gn->type |= OP_SUBMAKE; ParseMark(gn); } else { #ifdef notyet diff --git a/suff.c b/suff.c index d4f0eb183fc7..c42d2ec57e8f 100644 --- a/suff.c +++ b/suff.c @@ -1,4 +1,4 @@ -/* $NetBSD: suff.c,v 1.70 2013/05/18 13:13:34 sjg Exp $ */ +/* $NetBSD: suff.c,v 1.73 2014/09/07 20:55:34 joerg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: suff.c,v 1.70 2013/05/18 13:13:34 sjg Exp $"; +static char rcsid[] = "$NetBSD: suff.c,v 1.73 2014/09/07 20:55:34 joerg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94"; #else -__RCSID("$NetBSD: suff.c,v 1.70 2013/05/18 13:13:34 sjg Exp $"); +__RCSID("$NetBSD: suff.c,v 1.73 2014/09/07 20:55:34 joerg Exp $"); #endif #endif /* not lint */ #endif diff --git a/targ.c b/targ.c index d26b845c80a6..527206ec90c0 100644 --- a/targ.c +++ b/targ.c @@ -1,4 +1,4 @@ -/* $NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $ */ +/* $NetBSD: targ.c,v 1.59 2014/09/07 20:55:34 joerg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $"; +static char rcsid[] = "$NetBSD: targ.c,v 1.59 2014/09/07 20:55:34 joerg Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $"); +__RCSID("$NetBSD: targ.c,v 1.59 2014/09/07 20:55:34 joerg Exp $"); #endif #endif /* not lint */ #endif diff --git a/unit-tests/Makefile.in b/unit-tests/Makefile.in index 3f70f8a4d9fa..f5f528c291e2 100644 --- a/unit-tests/Makefile.in +++ b/unit-tests/Makefile.in @@ -1,17 +1,18 @@ -# $Id: Makefile.in,v 1.44 2013/08/28 22:09:29 sjg Exp $ +# $Id: Makefile.in,v 1.46 2014/11/06 01:47:57 sjg Exp $ # -# $NetBSD: Makefile,v 1.38 2013/08/28 21:56:50 sjg Exp $ +# $NetBSD: Makefile,v 1.51 2014/10/20 23:21:11 sjg Exp $ # # Unit tests for make(1) # The main targets are: # # all: run all the tests -# test: run 'all', capture output and compare to expected results +# test: run 'all', and compare to expected results # accept: move generated output to expected results # # Adding a test case. # Each feature should get its own set of tests in its own suitably -# named makefile which should be added to SUBFILES to hook it in. +# named makefile (*.mk), with its own set of expected results (*.exp), +# and it should be added to the TESTNAMES list. # srcdir= @srcdir@ @@ -19,10 +20,11 @@ srcdir= @srcdir@ .MAIN: all UNIT_TESTS:= ${srcdir} +.PATH: ${UNIT_TESTS} -# Simple sub-makefiles - we run them as a black box -# keep the list sorted. -SUBFILES= \ +# Each test is in a sub-makefile. +# Keep the list sorted. +TESTNAMES= \ comment \ cond1 \ error \ @@ -42,7 +44,6 @@ SUBFILES= \ modts \ modword \ order \ - phony-end \ posix \ qequals \ sunshcmd \ @@ -50,23 +51,36 @@ SUBFILES= \ ternary \ unexport \ unexport-env \ - varcmd + varcmd \ + varmisc \ + varshell -all: ${SUBFILES} +# these tests were broken by referting POSIX chanegs +STRICT_POSIX_TESTS = \ + escape \ + impsrc \ + phony-end \ + posix1 \ + suffixes +# Override make flags for certain tests flags.doterror= flags.order=-j1 -# the tests are actually done with sub-makes. -.PHONY: ${SUBFILES} -.PRECIOUS: ${SUBFILES} -${SUBFILES}: - -@${.MAKE} ${flags.$@:U-k} -f ${UNIT_TESTS}/$@ +OUTFILES= ${TESTNAMES:S/$/.out/} -clean: - rm -f *.out *.fail *.core +all: ${OUTFILES} -.-include +CLEANFILES += *.rawout *.out *.status *.tmp *.core *.tmp +CLEANFILES += obj*.[och] lib*.a # posix1.mk +CLEANFILES += issue* .[ab]* # suffixes.mk +CLEANRECURSIVE += dir dummy # posix1.mk + +clean: + rm -f ${CLEANFILES} +.if !empty(CLEANRECURSIVE) + rm -rf ${CLEANRECURSIVE} +.endif TEST_MAKE?= ${.MAKE} TOOL_SED?= sed @@ -81,22 +95,56 @@ LANG= C .export LANG LC_ALL .endif -# The driver. +# some tests need extra post-processing +SED_CMDS.varshell = -e 's,^[a-z]*sh: ,,' \ + -e '/command/s,No such.*,not found,' + +# the tests are actually done with sub-makes. +.SUFFIXES: .mk .rawout .out +.mk.rawout: + @echo ${TEST_MAKE} ${flags.${.TARGET:R}:U-k} -f ${.IMPSRC} + -@cd ${.OBJDIR} && \ + { ${TEST_MAKE} ${flags.${.TARGET:R}:U-k} -f ${.IMPSRC} \ + 2>&1 ; echo $$? >${.TARGET:R}.status ; } > ${.TARGET}.tmp + @mv ${.TARGET}.tmp ${.TARGET} + # We always pretend .MAKE was called 'make' # and strip ${.CURDIR}/ from the output # and replace anything after 'stopped in' with unit-tests # so the results can be compared. -test: - @echo "${TEST_MAKE} -f ${MAKEFILE} > ${.TARGET}.out 2>&1" - @cd ${.OBJDIR} && ${TEST_MAKE} -f ${MAKEFILE} 2>&1 | \ - ${TOOL_TR} -d '\015' | \ - ${TOOL_SED} -e 's,^${TEST_MAKE:T:C/\./\\\./g}[^:]*:,make:,' \ - -e '/stopped/s, /.*, unit-tests,' \ - -e 's,${.CURDIR:C/\./\\\./g}/,,g' \ - -e 's,${UNIT_TESTS:C/\./\\\./g}/,,g' > ${.TARGET}.out || { \ - tail ${.TARGET}.out; mv ${.TARGET}.out ${.TARGET}.fail; exit 1; } - ${TOOL_DIFF} ${DIFF_FLAGS} ${UNIT_TESTS}/${.TARGET}.exp ${.TARGET}.out +.rawout.out: + @echo postprocess ${.TARGET} + @${TOOL_SED} -e 's,^${TEST_MAKE:T:C/\./\\\./g}[][0-9]*:,make:,' \ + -e 's,${TEST_MAKE:C/\./\\\./g},make,' \ + -e '/stopped/s, /.*, unit-tests,' \ + -e 's,${.CURDIR:C/\./\\\./g}/,,g' \ + -e 's,${UNIT_TESTS:C/\./\\\./g}/,,g' ${SED_CMDS.${.TARGET:T:R}} \ + < ${.IMPSRC} > ${.TARGET}.tmp + @echo "exit status `cat ${.TARGET:R}.status`" >> ${.TARGET}.tmp + @mv ${.TARGET}.tmp ${.TARGET} + +# Compare all output files +test: ${OUTFILES} .PHONY + @failed= ; \ + for test in ${TESTNAMES}; do \ + ${TOOL_DIFF} -u ${UNIT_TESTS}/$${test}.exp $${test}.out \ + || failed="$${failed}$${failed:+ }$${test}" ; \ + done ; \ + if [ -n "$${failed}" ]; then \ + echo "Failed tests: $${failed}" ; false ; \ + else \ + echo "All tests passed" ; \ + fi accept: - mv test.out ${srcdir}/test.exp + @for test in ${TESTNAMES}; do \ + cmp -s ${UNIT_TESTS}/$${test}.exp $${test}.out \ + || { echo "Replacing $${test}.exp" ; \ + cp $${test}.out ${UNIT_TESTS}/$${test}.exp ; } \ + done +.if exists(${TEST_MAKE}) +${TESTNAMES:S/$/.rawout/}: ${TEST_MAKE} +.endif + +.-include diff --git a/unit-tests/comment b/unit-tests/comment deleted file mode 100644 index 7dd7dbbe28b5..000000000000 --- a/unit-tests/comment +++ /dev/null @@ -1,31 +0,0 @@ -# This is a comment -.if ${MACHINE_ARCH} == something -FOO=bar -.endif - -#\ - Multiline comment - -BAR=# defined -FOOBAR= # defined - -# This is an escaped comment \ -that keeps going until the end of this line - -# Another escaped comment \ -that \ -goes \ -on - -# This is NOT an escaped comment due to the double backslashes \\ -all: hi foo bar - @echo comment testing done - -hi: - @echo comment testing start - -foo: - @echo this is $@ - -bar: - @echo This is how a comment looks: '# comment' diff --git a/unit-tests/comment.exp b/unit-tests/comment.exp new file mode 100644 index 000000000000..9a97df0b7320 --- /dev/null +++ b/unit-tests/comment.exp @@ -0,0 +1,5 @@ +comment testing start +this is foo +This is how a comment looks: # comment +comment testing done +exit status 0 diff --git a/unit-tests/comment.mk b/unit-tests/comment.mk new file mode 100644 index 000000000000..7dd7dbbe28b5 --- /dev/null +++ b/unit-tests/comment.mk @@ -0,0 +1,31 @@ +# This is a comment +.if ${MACHINE_ARCH} == something +FOO=bar +.endif + +#\ + Multiline comment + +BAR=# defined +FOOBAR= # defined + +# This is an escaped comment \ +that keeps going until the end of this line + +# Another escaped comment \ +that \ +goes \ +on + +# This is NOT an escaped comment due to the double backslashes \\ +all: hi foo bar + @echo comment testing done + +hi: + @echo comment testing start + +foo: + @echo this is $@ + +bar: + @echo This is how a comment looks: '# comment' diff --git a/unit-tests/cond1 b/unit-tests/cond1 deleted file mode 100644 index c877c3db31b8..000000000000 --- a/unit-tests/cond1 +++ /dev/null @@ -1,109 +0,0 @@ -# $Id: cond1,v 1.1.1.3 2011/03/06 00:04:58 sjg Exp $ - -# hard code these! -TEST_UNAME_S= NetBSD -TEST_UNAME_M= sparc -TEST_MACHINE= i386 - -.if ${TEST_UNAME_S} -Ok=var, -.endif -.if ("${TEST_UNAME_S}") -Ok+=(\"var\"), -.endif -.if (${TEST_UNAME_M} != ${TEST_MACHINE}) -Ok+=(var != var), -.endif -.if ${TEST_UNAME_M} != ${TEST_MACHINE} -Ok+= var != var, -.endif -.if !((${TEST_UNAME_M} != ${TEST_MACHINE}) && defined(X)) -Ok+= !((var != var) && defined(name)), -.endif -# from bsd.obj.mk -MKOBJ?=no -.if ${MKOBJ} == "no" -o= no -Ok+= var == "quoted", -.else -.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) -.if defined(notMAKEOBJDIRPREFIX) -o=${MAKEOBJDIRPREFIX}${__curdir} -.else -o= ${MAKEOBJDIR} -.endif -.endif -o= o -.endif - -# repeat the above to check we get the same result -.if ${MKOBJ} == "no" -o2= no -.else -.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) -.if defined(notMAKEOBJDIRPREFIX) -o2=${MAKEOBJDIRPREFIX}${__curdir} -.else -o2= ${MAKEOBJDIR} -.endif -.endif -o2= o -.endif - -PRIMES=2 3 5 7 11 -NUMBERS=1 2 3 4 5 - -n=2 -.if ${PRIMES:M$n} == "" -X=not -.else -X= -.endif - -.if ${MACHINE_ARCH} == no-such -A=one -.else -.if ${MACHINE_ARCH} == not-this -.if ${MACHINE_ARCH} == something-else -A=unlikely -.else -A=no -.endif -.endif -A=other -# We expect an extra else warning - we're not skipping here -.else -A=this should be an error -.endif - -.if $X != "" -.if $X == not -B=one -.else -B=other -# We expect an extra else warning - we are skipping here -.else -B=this should be an error -.endif -.else -B=unknown -.endif - -.if "quoted" == quoted -C=clever -.else -C=dim -.endif - -.if defined(nosuch) && ${nosuch:Mx} != "" -# this should not happen -.info nosuch is x -.endif - -all: - @echo "$n is $X prime" - @echo "A='$A' B='$B' C='$C' o='$o,${o2}'" - @echo "Passed:${.newline} ${Ok:S/,/${.newline}/}" - @echo "${NUMBERS:@n@$n is ${("${PRIMES:M$n}" == ""):?not:} prime${.newline}@}" - @echo "${"${DoNotQuoteHere:U0}" > 0:?OK:No}" - @echo "${${NoSuchNumber:U42} > 0:?OK:No}" diff --git a/unit-tests/cond1.exp b/unit-tests/cond1.exp new file mode 100644 index 000000000000..701d504fcc6b --- /dev/null +++ b/unit-tests/cond1.exp @@ -0,0 +1,23 @@ +make: "cond1.mk" line 75: warning: extra else +make: "cond1.mk" line 85: warning: extra else +2 is prime +A='other' B='unknown' C='clever' o='no,no' +Passed: + var + ("var") + (var != var) + var != var + !((var != var) && defined(name)) + var == quoted + +1 is not prime +2 is prime +3 is prime +4 is not prime +5 is prime + +make: warning: String comparison operator should be either == or != +make: Bad conditional expression `"0" > 0' in "0" > 0?OK:No + +OK +exit status 0 diff --git a/unit-tests/cond1.mk b/unit-tests/cond1.mk new file mode 100644 index 000000000000..2fc2c7c64b85 --- /dev/null +++ b/unit-tests/cond1.mk @@ -0,0 +1,109 @@ +# $Id: cond1.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +# hard code these! +TEST_UNAME_S= NetBSD +TEST_UNAME_M= sparc +TEST_MACHINE= i386 + +.if ${TEST_UNAME_S} +Ok=var, +.endif +.if ("${TEST_UNAME_S}") +Ok+=(\"var\"), +.endif +.if (${TEST_UNAME_M} != ${TEST_MACHINE}) +Ok+=(var != var), +.endif +.if ${TEST_UNAME_M} != ${TEST_MACHINE} +Ok+= var != var, +.endif +.if !((${TEST_UNAME_M} != ${TEST_MACHINE}) && defined(X)) +Ok+= !((var != var) && defined(name)), +.endif +# from bsd.obj.mk +MKOBJ?=no +.if ${MKOBJ} == "no" +o= no +Ok+= var == "quoted", +.else +.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) +.if defined(notMAKEOBJDIRPREFIX) +o=${MAKEOBJDIRPREFIX}${__curdir} +.else +o= ${MAKEOBJDIR} +.endif +.endif +o= o +.endif + +# repeat the above to check we get the same result +.if ${MKOBJ} == "no" +o2= no +.else +.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) +.if defined(notMAKEOBJDIRPREFIX) +o2=${MAKEOBJDIRPREFIX}${__curdir} +.else +o2= ${MAKEOBJDIR} +.endif +.endif +o2= o +.endif + +PRIMES=2 3 5 7 11 +NUMBERS=1 2 3 4 5 + +n=2 +.if ${PRIMES:M$n} == "" +X=not +.else +X= +.endif + +.if ${MACHINE_ARCH} == no-such +A=one +.else +.if ${MACHINE_ARCH} == not-this +.if ${MACHINE_ARCH} == something-else +A=unlikely +.else +A=no +.endif +.endif +A=other +# We expect an extra else warning - we're not skipping here +.else +A=this should be an error +.endif + +.if $X != "" +.if $X == not +B=one +.else +B=other +# We expect an extra else warning - we are skipping here +.else +B=this should be an error +.endif +.else +B=unknown +.endif + +.if "quoted" == quoted +C=clever +.else +C=dim +.endif + +.if defined(nosuch) && ${nosuch:Mx} != "" +# this should not happen +.info nosuch is x +.endif + +all: + @echo "$n is $X prime" + @echo "A='$A' B='$B' C='$C' o='$o,${o2}'" + @echo "Passed:${.newline} ${Ok:S/,/${.newline}/}" + @echo "${NUMBERS:@n@$n is ${("${PRIMES:M$n}" == ""):?not:} prime${.newline}@}" + @echo "${"${DoNotQuoteHere:U0}" > 0:?OK:No}" + @echo "${${NoSuchNumber:U42} > 0:?OK:No}" diff --git a/unit-tests/doterror b/unit-tests/doterror deleted file mode 100644 index 75d8920ac7e7..000000000000 --- a/unit-tests/doterror +++ /dev/null @@ -1,20 +0,0 @@ -# $Id: doterror,v 1.1.1.1 2010/04/08 17:43:00 sjg Exp $ - - -.BEGIN: - @echo At first, I am - -.END: - @echo not reached - -.ERROR: - @echo "$@: Looks like '${.ERROR_TARGET}' is upset." - -all: happy sad - -happy: - @echo $@ - -sad: - @echo and now: $@; exit 1 - diff --git a/unit-tests/doterror.exp b/unit-tests/doterror.exp new file mode 100644 index 000000000000..0447a519344c --- /dev/null +++ b/unit-tests/doterror.exp @@ -0,0 +1,9 @@ +At first, I am +happy +and now: sad +.ERROR: Looks like 'sad' is upset. +*** Error code 1 + +Stop. +make: stopped in unit-tests +exit status 1 diff --git a/unit-tests/doterror.mk b/unit-tests/doterror.mk new file mode 100644 index 000000000000..9030dce93bee --- /dev/null +++ b/unit-tests/doterror.mk @@ -0,0 +1,20 @@ +# $Id: doterror.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + + +.BEGIN: + @echo At first, I am + +.END: + @echo not reached + +.ERROR: + @echo "$@: Looks like '${.ERROR_TARGET}' is upset." + +all: happy sad + +happy: + @echo $@ + +sad: + @echo and now: $@; exit 1 + diff --git a/unit-tests/dotwait b/unit-tests/dotwait deleted file mode 100644 index 43706afe64b8..000000000000 --- a/unit-tests/dotwait +++ /dev/null @@ -1,61 +0,0 @@ -# $NetBSD: dotwait,v 1.1 2006/02/26 22:45:46 apb Exp $ - -THISMAKEFILE:= ${.PARSEDIR}/${.PARSEFILE} - -TESTS= simple recursive shared cycle -PAUSE= sleep 1 - -# Use a .for loop rather than dependencies here, to ensure -# that the tests are run one by one, with parallelism -# only within tests. -# Ignore "--- target ---" lines printed by parallel make. -all: -.for t in ${TESTS} - @${.MAKE} -f ${THISMAKEFILE} -j4 $t | grep -v "^--- " -.endfor - -# -# Within each test, the names of the sub-targets follow these -# conventions: -# * If it's expected that two or more targets may be made in parallel, -# then the target names will differ only in an alphabetic component -# such as ".a" or ".b". -# * If it's expected that two or more targets should be made in sequence -# then the target names will differ in numeric components, such that -# lexical ordering of the target names matches the expected order -# in which the targets should be made. -# -# Targets may echo ${PARALLEL_TARG} to print a modified version -# of their own name, in which alphabetic components like ".a" or ".b" -# are converted to ".*". Two targets that are expected to -# be made in parallel will thus print the same strings, so that the -# output is independent of the order in which these targets are made. -# -PARALLEL_TARG= ${.TARGET:C/\.[a-z]/.*/g:Q} -.DEFAULT: - @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} -_ECHOUSE: .USE - @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} - -# simple: no recursion, no cycles -simple: simple.1 .WAIT simple.2 - -# recursive: all children of the left hand side of the .WAIT -# must be made before any child of the right hand side. -recursive: recursive.1.99 .WAIT recursive.2.99 -recursive.1.99: recursive.1.1.a recursive.1.1.b _ECHOUSE -recursive.2.99: recursive.2.1.a recursive.2.1.b _ECHOUSE - -# shared: both shared.1.99 and shared.2.99 depend on shared.0. -# shared.0 must be made first, even though it is a child of -# the right hand side of the .WAIT. -shared: shared.1.99 .WAIT shared.2.99 -shared.1.99: shared.0 _ECHOUSE -shared.2.99: shared.2.1 shared.0 _ECHOUSE - -# cycle: the cyclic dependency must not cause infinite recursion -# leading to stack overflow and a crash. -cycle: cycle.1.99 .WAIT cycle.2.99 -cycle.2.99: cycle.2.98 _ECHOUSE -cycle.2.98: cycle.2.97 _ECHOUSE -cycle.2.97: cycle.2.99 _ECHOUSE diff --git a/unit-tests/dotwait.exp b/unit-tests/dotwait.exp new file mode 100644 index 000000000000..6bf96e301c19 --- /dev/null +++ b/unit-tests/dotwait.exp @@ -0,0 +1,30 @@ +simple.1 +simple.1 +simple.2 +simple.2 +recursive.1.1.* +recursive.1.1.* +recursive.1.1.* +recursive.1.1.* +recursive.1.99 +recursive.1.99 +recursive.2.1.* +recursive.2.1.* +recursive.2.1.* +recursive.2.1.* +recursive.2.99 +recursive.2.99 +shared.0 +shared.0 +shared.1.99 +shared.1.99 +shared.2.1 +shared.2.1 +shared.2.99 +shared.2.99 +make: Graph cycles through `cycle.2.99' +make: Graph cycles through `cycle.2.98' +make: Graph cycles through `cycle.2.97' +cycle.1.99 +cycle.1.99 +exit status 0 diff --git a/unit-tests/dotwait.mk b/unit-tests/dotwait.mk new file mode 100644 index 000000000000..9bdaaba399d1 --- /dev/null +++ b/unit-tests/dotwait.mk @@ -0,0 +1,61 @@ +# $NetBSD: dotwait.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +THISMAKEFILE:= ${.PARSEDIR}/${.PARSEFILE} + +TESTS= simple recursive shared cycle +PAUSE= sleep 1 + +# Use a .for loop rather than dependencies here, to ensure +# that the tests are run one by one, with parallelism +# only within tests. +# Ignore "--- target ---" lines printed by parallel make. +all: +.for t in ${TESTS} + @${.MAKE} -f ${THISMAKEFILE} -j4 $t | grep -v "^--- " +.endfor + +# +# Within each test, the names of the sub-targets follow these +# conventions: +# * If it's expected that two or more targets may be made in parallel, +# then the target names will differ only in an alphabetic component +# such as ".a" or ".b". +# * If it's expected that two or more targets should be made in sequence +# then the target names will differ in numeric components, such that +# lexical ordering of the target names matches the expected order +# in which the targets should be made. +# +# Targets may echo ${PARALLEL_TARG} to print a modified version +# of their own name, in which alphabetic components like ".a" or ".b" +# are converted to ".*". Two targets that are expected to +# be made in parallel will thus print the same strings, so that the +# output is independent of the order in which these targets are made. +# +PARALLEL_TARG= ${.TARGET:C/\.[a-z]/.*/g:Q} +.DEFAULT: + @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} +_ECHOUSE: .USE + @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} + +# simple: no recursion, no cycles +simple: simple.1 .WAIT simple.2 + +# recursive: all children of the left hand side of the .WAIT +# must be made before any child of the right hand side. +recursive: recursive.1.99 .WAIT recursive.2.99 +recursive.1.99: recursive.1.1.a recursive.1.1.b _ECHOUSE +recursive.2.99: recursive.2.1.a recursive.2.1.b _ECHOUSE + +# shared: both shared.1.99 and shared.2.99 depend on shared.0. +# shared.0 must be made first, even though it is a child of +# the right hand side of the .WAIT. +shared: shared.1.99 .WAIT shared.2.99 +shared.1.99: shared.0 _ECHOUSE +shared.2.99: shared.2.1 shared.0 _ECHOUSE + +# cycle: the cyclic dependency must not cause infinite recursion +# leading to stack overflow and a crash. +cycle: cycle.1.99 .WAIT cycle.2.99 +cycle.2.99: cycle.2.98 _ECHOUSE +cycle.2.98: cycle.2.97 _ECHOUSE +cycle.2.97: cycle.2.99 _ECHOUSE diff --git a/unit-tests/error b/unit-tests/error deleted file mode 100644 index c0a1403a4008..000000000000 --- a/unit-tests/error +++ /dev/null @@ -1,10 +0,0 @@ -# $Id: error,v 1.1.1.2 2010/05/24 23:36:03 sjg Exp $ - -.info just FYI -.warning this could be serious -.error this is fatal - -all: - -.info.html: - @echo this should be ignored diff --git a/unit-tests/error.exp b/unit-tests/error.exp new file mode 100644 index 000000000000..a2bf71b7127f --- /dev/null +++ b/unit-tests/error.exp @@ -0,0 +1,4 @@ +make: "error.mk" line 3: just FYI +make: "error.mk" line 4: warning: this could be serious +make: "error.mk" line 5: this is fatal +exit status 1 diff --git a/unit-tests/error.mk b/unit-tests/error.mk new file mode 100644 index 000000000000..c6b553e2e48a --- /dev/null +++ b/unit-tests/error.mk @@ -0,0 +1,10 @@ +# $Id: error.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +.info just FYI +.warning this could be serious +.error this is fatal + +all: + +.info.html: + @echo this should be ignored diff --git a/unit-tests/escape.exp b/unit-tests/escape.exp new file mode 100644 index 000000000000..6238e27b0191 --- /dev/null +++ b/unit-tests/escape.exp @@ -0,0 +1,104 @@ +var-1bs +printf "%s=:%s:\n" VAR1BS 111\\111; printf "%s=:%s:\n" VAR1BSa 111\\aaa; printf "%s=:%s:\n" VAR1BSA 111\\aaa; printf "%s=:%s:\n" VAR1BSda 111\\\$\{a\}; printf "%s=:%s:\n" VAR1BSdA 111\\\$\{A\}; printf "%s=:%s:\n" VAR1BSc 111\#\ backslash\ escapes\ comment\ char,\ so\ this\ is\ part\ of\ the\ value; printf "%s=:%s:\n" VAR1BSsc 111\\\ ; +VAR1BS=:111\111: +VAR1BSa=:111\aaa: +VAR1BSA=:111\aaa: +VAR1BSda=:111\${a}: +VAR1BSdA=:111\${A}: +VAR1BSc=:111# backslash escapes comment char, so this is part of the value: +VAR1BSsc=:111\ : +var-2bs +printf "%s=:%s:\n" VAR2BS 222\\\\222; printf "%s=:%s:\n" VAR2BSa 222\\\\aaa; printf "%s=:%s:\n" VAR2BSA 222\\\\aaa; printf "%s=:%s:\n" VAR2BSda 222\\\\\$\{a\}; printf "%s=:%s:\n" VAR2BSdA 222\\\\\$\{A\}; printf "%s=:%s:\n" VAR2BSc 222\\\\; printf "%s=:%s:\n" VAR2BSsc 222\\\\; +VAR2BS=:222\\222: +VAR2BSa=:222\\aaa: +VAR2BSA=:222\\aaa: +VAR2BSda=:222\\${a}: +VAR2BSdA=:222\\${A}: +VAR2BSc=:222\\: +VAR2BSsc=:222\\: +var-1bsnl +printf "%s=:%s:\n" VAR1BSNL 111\ 111; printf "%s=:%s:\n" VAR1BSNLa 111\ aaa; printf "%s=:%s:\n" VAR1BSNLA 111\ aaa; printf "%s=:%s:\n" VAR1BSNLda 111\ \$\{a\}; printf "%s=:%s:\n" VAR1BSNLdA 111\ \$\{A\}; printf "%s=:%s:\n" VAR1BSNLc 111; printf "%s=:%s:\n" VAR1BSNLsc 111; +VAR1BSNL=:111 111: +VAR1BSNLa=:111 aaa: +VAR1BSNLA=:111 aaa: +VAR1BSNLda=:111 ${a}: +VAR1BSNLdA=:111 ${A}: +VAR1BSNLc=:111: +VAR1BSNLsc=:111: +var-2bsnl +printf "%s=:%s:\n" VAR2BSNL 222\\\\; printf "%s=:%s:\n" VAR2BSNLa 222\\\\; printf "%s=:%s:\n" VAR2BSNLA 222\\\\; printf "%s=:%s:\n" VAR2BSNLda 222\\\\; printf "%s=:%s:\n" VAR2BSNLdA 222\\\\; printf "%s=:%s:\n" VAR2BSNLc 222\\\\; printf "%s=:%s:\n" VAR2BSNLsc 222\\\\; +VAR2BSNL=:222\\: +VAR2BSNLa=:222\\: +VAR2BSNLA=:222\\: +VAR2BSNLda=:222\\: +VAR2BSNLdA=:222\\: +VAR2BSNLc=:222\\: +VAR2BSNLsc=:222\\: +var-3bsnl +printf "%s=:%s:\n" VAR3BSNL 333\\\\\ 333=; printf "%s=:%s:\n" VAR3BSNLa 333\\\\\ aaa=; printf "%s=:%s:\n" VAR3BSNLA 333\\\\\ aaa=; printf "%s=:%s:\n" VAR3BSNLda 333\\\\\ \$\{a\}=; printf "%s=:%s:\n" VAR3BSNLdA 333\\\\\ \$\{A\}=; printf "%s=:%s:\n" VAR3BSNLc 333\\\\; printf "%s=:%s:\n" VAR3BSNLsc 333\\\\; +VAR3BSNL=:333\\ 333=: +VAR3BSNLa=:333\\ aaa=: +VAR3BSNLA=:333\\ aaa=: +VAR3BSNLda=:333\\ ${a}=: +VAR3BSNLdA=:333\\ ${A}=: +VAR3BSNLc=:333\\: +VAR3BSNLsc=:333\\: +var-1bsnl-space +printf "%s=:%s:\n" VAR1BSNL00 first\ line; printf "%s=:%s:\n" VAR1BSNL0 first\ line\ no\ space\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLs first\ line\ one\ space\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLss first\ line\ two\ spaces\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLt first\ line\ one\ tab\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLtt first\ line\ two\ tabs\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLxx first\ line\ many\ spaces\ and\ tabs\ \[\ \ \ \ \]\ on\ second\ line; +VAR1BSNL00=:first line: +VAR1BSNL0=:first line no space on second line: +VAR1BSNLs=:first line one space on second line: +VAR1BSNLss=:first line two spaces on second line: +VAR1BSNLt=:first line one tab on second line: +VAR1BSNLtt=:first line two tabs on second line: +VAR1BSNLxx=:first line many spaces and tabs [ ] on second line: +cmd-1bsnl +echo :'first line\ +#second line without space\ +third line': +:first line\ +#second line without space\ +third line: +echo :'first line\ + second line spaces should be retained': +:first line\ + second line spaces should be retained: +echo :'first line\ +second line tab should be elided': +:first line\ +second line tab should be elided: +echo :'first line\ + only one tab should be elided, second tab remains' +:first line\ + only one tab should be elided, second tab remains +cmd-1bsnl-eof +echo :'command ending with backslash-newline'; \ + +:command ending with backslash-newline +cmd-2bsnl +echo take one\\ +take one\ +echo take two\\ +take two\ +echo take three\\ +take three\ +cmd-3bsnl +echo :'first line\\\ +#second line without space\\\ +third line': +:first line\\\ +#second line without space\\\ +third line: +echo :'first line\\\ + second line spaces should be retained': +:first line\\\ + second line spaces should be retained: +echo :'first line\\\ +second line tab should be elided': +:first line\\\ +second line tab should be elided: +echo :'first line\\\ + only one tab should be elided, second tab remains' +:first line\\\ + only one tab should be elided, second tab remains +exit status 0 diff --git a/unit-tests/escape.mk b/unit-tests/escape.mk new file mode 100644 index 000000000000..bb37c9217f4c --- /dev/null +++ b/unit-tests/escape.mk @@ -0,0 +1,246 @@ +# $Id: escape.mk,v 1.1.1.2 2014/11/06 01:40:37 sjg Exp $ +# +# Test backslash escaping. + +# Extracts from the POSIX 2008 specification +# : +# +# Comments start with a ( '#' ) and continue until an +# unescaped is reached. +# +# When an escaped (one preceded by a ) is found +# anywhere in the makefile except in a command line, an include +# line, or a line immediately preceding an include line, it shall +# be replaced, along with any leading white space on the following +# line, with a single . +# +# When an escaped is found in a command line in a +# makefile, the command line shall contain the , the +# , and the next line, except that the first character of +# the next line shall not be included if it is a . +# +# When an escaped is found in an include line or in a +# line immediately preceding an include line, the behavior is +# unspecified. +# +# Notice that the behaviour of or +# is not mentioned. I think +# this implies that should be taken literally everywhere +# except before . +# +# Our practice, despite what POSIX might say, is that "\#" +# in a variable assignment stores "#" as part of the value. +# The "\" is not taken literally, and the "#" does not begin a comment. +# +# Also, our practice is that an even number of backslashes before a +# newline in a variable assignment simply stores the backslashes as part +# of the value, and treats the newline as though it was not escaped. +# Similarly, ann even number of backslashes before a newline in a +# command simply uses the backslashes as part of the command test, but +# does not escape the newline. This is compatible with GNU make. + +all: .PHONY +# We will add dependencies like "all: yet-another-test" later. + +# Some variables to be expanded in tests +# +a = aaa +A = ${a} + +# Backslash at end of line in a comment\ +should continue the comment. \ +# This is also tested in comment.mk. + +__printvars: .USE .MADE + @echo ${.TARGET} + ${.ALLSRC:@v@ printf "%s=:%s:\n" ${v:Q} ${${v}:Q}; @} + +# Embedded backslash in variable should be taken literally. +# +VAR1BS = 111\111 +VAR1BSa = 111\${a} +VAR1BSA = 111\${A} +VAR1BSda = 111\$${a} +VAR1BSdA = 111\$${A} +VAR1BSc = 111\# backslash escapes comment char, so this is part of the value +VAR1BSsc = 111\ # This is a comment. Value ends with + +all: var-1bs +var-1bs: .PHONY __printvars VAR1BS VAR1BSa VAR1BSA VAR1BSda VAR1BSdA \ + VAR1BSc VAR1BSsc + +# Double backslash in variable should be taken as two literal backslashes. +# +VAR2BS = 222\\222 +VAR2BSa = 222\\${a} +VAR2BSA = 222\\${A} +VAR2BSda = 222\\$${a} +VAR2BSdA = 222\\$${A} +VAR2BSc = 222\\# backslash does not escape comment char, so this is a comment +VAR2BSsc = 222\\ # This is a comment. Value ends with + +all: var-2bs +var-2bs: .PHONY __printvars VAR2BS VAR2BSa VAR2BSA VAR2BSda VAR2BSdA \ + VAR2BSc VAR2BSsc + +# Backslash-newline in a variable setting is replaced by a single space. +# +VAR1BSNL = 111\ +111 +VAR1BSNLa = 111\ +${a} +VAR1BSNLA = 111\ +${A} +VAR1BSNLda = 111\ +$${a} +VAR1BSNLdA = 111\ +$${A} +VAR1BSNLc = 111\ +# this should be processed as a comment +VAR1BSNLsc = 111\ + # this should be processed as a comment + +all: var-1bsnl +var-1bsnl: .PHONY +var-1bsnl: .PHONY __printvars \ + VAR1BSNL VAR1BSNLa VAR1BSNLA VAR1BSNLda VAR1BSNLdA \ + VAR1BSNLc VAR1BSNLsc + +# Double-backslash-newline in a variable setting. +# Both backslashes should be taken literally, and the newline is NOT escaped. +# +# The second lines below each end with '=' so that they will not +# generate syntax errors regardless of whether or not they are +# treated as part of the value. +# +VAR2BSNL = 222\\ +222= +VAR2BSNLa = 222\\ +${a}= +VAR2BSNLA = 222\\ +${A}= +VAR2BSNLda = 222\\ +$${a}= +VAR2BSNLdA = 222\\ +$${A}= +VAR2BSNLc = 222\\ +# this should be processed as a comment +VAR2BSNLsc = 222\\ + # this should be processed as a comment + +all: var-2bsnl +var-2bsnl: .PHONY __printvars \ + VAR2BSNL VAR2BSNLa VAR2BSNLA VAR2BSNLda VAR2BSNLdA \ + VAR2BSNLc VAR2BSNLsc + +# Triple-backslash-newline in a variable setting. +# First two should be taken literally, and last should escape the newline. +# +# The second lines below each end with '=' so that they will not +# generate syntax errors regardless of whether or not they are +# treated as part of the value. +# +VAR3BSNL = 333\\\ +333= +VAR3BSNLa = 333\\\ +${a}= +VAR3BSNLA = 333\\\ +${A}= +VAR3BSNLda = 333\\\ +$${a}= +VAR3BSNLdA = 333\\\ +$${A}= +VAR3BSNLc = 333\\\ +# this should be processed as a comment +VAR3BSNLsc = 333\\\ + # this should be processed as a comment + +all: var-3bsnl +var-3bsnl: .PHONY __printvars \ + VAR3BSNL VAR3BSNLa VAR3BSNLA VAR3BSNLda VAR3BSNLdA \ + VAR3BSNLc VAR3BSNLsc + +# Backslash-newline in a variable setting, plus any amount of white space +# on the next line, is replaced by a single space. +# +VAR1BSNL00= first line\ + +# above line is entirely empty, and this is a comment +VAR1BSNL0= first line\ +no space on second line +VAR1BSNLs= first line\ + one space on second line +VAR1BSNLss= first line\ + two spaces on second line +VAR1BSNLt= first line\ + one tab on second line +VAR1BSNLtt= first line\ + two tabs on second line +VAR1BSNLxx= first line\ + many spaces and tabs [ ] on second line + +all: var-1bsnl-space +var-1bsnl-space: .PHONY __printvars \ + VAR1BSNL00 VAR1BSNL0 VAR1BSNLs VAR1BSNLss VAR1BSNLt VAR1BSNLtt \ + VAR1BSNLxx + +# Backslash-newline in a command is retained. +# +# The "#" in "# second line without space" makes it a comment instead +# of a syntax error if the preceding line is parsed incorretly. +# The ":" in "third line':" makes it look like the start of a +# target instead of a syntax error if the first line is parsed incorrectly. +# +all: cmd-1bsnl +cmd-1bsnl: .PHONY + @echo ${.TARGET} + echo :'first line\ +#second line without space\ +third line': + echo :'first line\ + second line spaces should be retained': + echo :'first line\ + second line tab should be elided': + echo :'first line\ + only one tab should be elided, second tab remains' + +# When backslash-newline appears at the end of a command script, +# both the backslash and the newline should be passed to the shell. +# The shell should elide the backslash-newline. +# +all: cmd-1bsnl-eof +cmd-1bsnl-eof: + @echo ${.TARGET} + echo :'command ending with backslash-newline'; \ + +# above line must be blank + +# Double-backslash-newline in a command. +# Both backslashes are retained, but the newline is not escaped. +# XXX: This may differ from POSIX, but matches gmake. +# +# When make passes two backslashes to the shell, the shell will pass one +# backslash to the echo commant. +# +all: cmd-2bsnl +cmd-2bsnl: .PHONY + @echo ${.TARGET} + echo take one\\ +# this should be a comment + echo take two\\ + echo take three\\ + +# Triple-backslash-newline in a command is retained. +# +all: cmd-3bsnl +cmd-3bsnl: .PHONY + @echo ${.TARGET} + echo :'first line\\\ +#second line without space\\\ +third line': + echo :'first line\\\ + second line spaces should be retained': + echo :'first line\\\ + second line tab should be elided': + echo :'first line\\\ + only one tab should be elided, second tab remains' diff --git a/unit-tests/export b/unit-tests/export deleted file mode 100644 index 3e2ad9537f67..000000000000 --- a/unit-tests/export +++ /dev/null @@ -1,22 +0,0 @@ -# $Id: export,v 1.1.1.1 2007/10/08 20:30:12 sjg Exp $ - -UT_TEST=export -UT_FOO=foo${BAR} -UT_FU=fubar -UT_ZOO=hoopie -UT_NO=all -# belive it or not, we expect this one to come out with $UT_FU unexpanded. -UT_DOLLAR= This is $$UT_FU - -.export UT_FU UT_FOO -.export UT_DOLLAR -# this one will be ignored -.export .MAKE.PID - -BAR=bar is ${UT_FU} - -.MAKE.EXPORTED+= UT_ZOO UT_TEST - -all: - @env | grep '^UT_' | sort - diff --git a/unit-tests/export-all b/unit-tests/export-all deleted file mode 100644 index a243fe3e35f7..000000000000 --- a/unit-tests/export-all +++ /dev/null @@ -1,23 +0,0 @@ -# $Id: export-all,v 1.1.1.2 2010/04/21 04:26:14 sjg Exp $ - -UT_OK=good -UT_F=fine - -# the old way to do :tA -M_tAbad = C,.*,cd & \&\& 'pwd',:sh -# the new -M_tA = tA - -here := ${.PARSEDIR} - -# this will cause trouble (recursing if we let it) -UT_BADDIR = ${${here}/../${here:T}:L:${M_tAbad}:T} -# this will be ok -UT_OKDIR = ${${here}/../${here:T}:L:${M_tA}:T} - -.export - -.include "export" - -UT_TEST=export-all -UT_ALL=even this gets exported diff --git a/unit-tests/export-all.exp b/unit-tests/export-all.exp new file mode 100644 index 000000000000..e3aefd4f9e7d --- /dev/null +++ b/unit-tests/export-all.exp @@ -0,0 +1,12 @@ +UT_ALL=even this gets exported +UT_BADDIR=unit-tests +UT_DOLLAR=This is $UT_FU +UT_F=fine +UT_FOO=foobar is fubar +UT_FU=fubar +UT_NO=all +UT_OK=good +UT_OKDIR=unit-tests +UT_TEST=export-all +UT_ZOO=hoopie +exit status 0 diff --git a/unit-tests/export-all.mk b/unit-tests/export-all.mk new file mode 100644 index 000000000000..200412f3b90a --- /dev/null +++ b/unit-tests/export-all.mk @@ -0,0 +1,23 @@ +# $Id: export-all.mk,v 1.1.1.2 2015/04/10 20:43:38 sjg Exp $ + +UT_OK=good +UT_F=fine + +# the old way to do :tA +M_tAbad = C,.*,cd & \&\& 'pwd',:sh +# the new +M_tA = tA + +here := ${.PARSEDIR} + +# this will cause trouble (recursing if we let it) +UT_BADDIR = ${${here}/../${here:T}:L:${M_tAbad}:T} +# this will be ok +UT_OKDIR = ${${here}/../${here:T}:L:${M_tA}:T} + +.export + +.include "export.mk" + +UT_TEST=export-all +UT_ALL=even this gets exported diff --git a/unit-tests/export-env b/unit-tests/export-env deleted file mode 100644 index b6ce6a251cc6..000000000000 --- a/unit-tests/export-env +++ /dev/null @@ -1,24 +0,0 @@ -# $Id: export-env,v 1.1.1.1 2013/03/23 02:26:59 sjg Exp $ - -# our normal .export, subsequent changes affect the environment -UT_TEST=this -.export UT_TEST -UT_TEST:= ${.PARSEFILE} - -# not so with .export-env -UT_ENV=exported -.export-env UT_ENV -UT_ENV=not-exported - -# gmake style export goes further; affects nothing but the environment -UT_EXP=before-export -export UT_EXP=exported -UT_EXP=not-exported - -all: - @echo make:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=${$v};@} - @echo env:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=$${$v};@} - - - - diff --git a/unit-tests/export-env.exp b/unit-tests/export-env.exp new file mode 100644 index 000000000000..6221232a2a1b --- /dev/null +++ b/unit-tests/export-env.exp @@ -0,0 +1,9 @@ +make: +UT_TEST=export-env.mk +UT_ENV=not-exported +UT_EXP=not-exported +env: +UT_TEST=export-env.mk +UT_ENV=exported +UT_EXP=exported +exit status 0 diff --git a/unit-tests/export-env.mk b/unit-tests/export-env.mk new file mode 100644 index 000000000000..6b7cd4c3060c --- /dev/null +++ b/unit-tests/export-env.mk @@ -0,0 +1,24 @@ +# $Id: export-env.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +# our normal .export, subsequent changes affect the environment +UT_TEST=this +.export UT_TEST +UT_TEST:= ${.PARSEFILE} + +# not so with .export-env +UT_ENV=exported +.export-env UT_ENV +UT_ENV=not-exported + +# gmake style export goes further; affects nothing but the environment +UT_EXP=before-export +export UT_EXP=exported +UT_EXP=not-exported + +all: + @echo make:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=${$v};@} + @echo env:; ${UT_TEST UT_ENV UT_EXP:L:@v@echo $v=$${$v};@} + + + + diff --git a/unit-tests/export.exp b/unit-tests/export.exp new file mode 100644 index 000000000000..143771ce90ae --- /dev/null +++ b/unit-tests/export.exp @@ -0,0 +1,6 @@ +UT_DOLLAR=This is $UT_FU +UT_FOO=foobar is fubar +UT_FU=fubar +UT_TEST=export +UT_ZOO=hoopie +exit status 0 diff --git a/unit-tests/export.mk b/unit-tests/export.mk new file mode 100644 index 000000000000..01f69f918161 --- /dev/null +++ b/unit-tests/export.mk @@ -0,0 +1,22 @@ +# $Id: export.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +UT_TEST=export +UT_FOO=foo${BAR} +UT_FU=fubar +UT_ZOO=hoopie +UT_NO=all +# belive it or not, we expect this one to come out with $UT_FU unexpanded. +UT_DOLLAR= This is $$UT_FU + +.export UT_FU UT_FOO +.export UT_DOLLAR +# this one will be ignored +.export .MAKE.PID + +BAR=bar is ${UT_FU} + +.MAKE.EXPORTED+= UT_ZOO UT_TEST + +all: + @env | grep '^UT_' | sort + diff --git a/unit-tests/forloop b/unit-tests/forloop deleted file mode 100644 index 0b50e6675f6c..000000000000 --- a/unit-tests/forloop +++ /dev/null @@ -1,45 +0,0 @@ -# $Id: forloop,v 1.1.1.1 2012/06/19 23:30:49 sjg Exp $ - -all: for-loop - -LIST = one "two and three" four "five" - -.if make(for-fail) -for-fail: - -XTRA_LIST = xtra -.else - -.for x in ${LIST} -X!= echo 'x=$x' >&2; echo -.endfor - -CFL = -I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" -cfl= -.for x in ${CFL} -X!= echo 'x=$x' >&2; echo -.if empty(cfl) -cfl= $x -.else -cfl+= $x -.endif -.endfor -X!= echo 'cfl=${cfl}' >&2; echo - -.if ${cfl} != ${CFL} -.error ${.newline}'${cfl}' != ${.newline}'${CFL}' -.endif - -.for a b in ${EMPTY} -X!= echo 'a=$a b=$b' >&2; echo -.endfor -.endif - -.for a b in ${LIST} ${LIST:tu} ${XTRA_LIST} -X!= echo 'a=$a b=$b' >&2; echo -.endfor - -for-loop: - @echo We expect an error next: - @(cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} for-fail) && \ - { echo "Oops that should have failed!"; exit 1; } || echo OK diff --git a/unit-tests/forloop.exp b/unit-tests/forloop.exp new file mode 100644 index 000000000000..df14b751224c --- /dev/null +++ b/unit-tests/forloop.exp @@ -0,0 +1,19 @@ +x=one +x="two and three" +x=four +x="five" +x=-I/this +x=-I"This or that" +x=-Ithat +x="-DTHIS=\"this and that\"" +cfl=-I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" +a=one b="two and three" +a=four b="five" +a=ONE b="TWO AND THREE" +a=FOUR b="FIVE" +We expect an error next: +make: "forloop.mk" line 38: Wrong number of words (9) in .for substitution list with 2 vars +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +OK +exit status 0 diff --git a/unit-tests/forloop.mk b/unit-tests/forloop.mk new file mode 100644 index 000000000000..9aad7c6b998a --- /dev/null +++ b/unit-tests/forloop.mk @@ -0,0 +1,45 @@ +# $Id: forloop.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +all: for-loop + +LIST = one "two and three" four "five" + +.if make(for-fail) +for-fail: + +XTRA_LIST = xtra +.else + +.for x in ${LIST} +X!= echo 'x=$x' >&2; echo +.endfor + +CFL = -I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" +cfl= +.for x in ${CFL} +X!= echo 'x=$x' >&2; echo +.if empty(cfl) +cfl= $x +.else +cfl+= $x +.endif +.endfor +X!= echo 'cfl=${cfl}' >&2; echo + +.if ${cfl} != ${CFL} +.error ${.newline}'${cfl}' != ${.newline}'${CFL}' +.endif + +.for a b in ${EMPTY} +X!= echo 'a=$a b=$b' >&2; echo +.endfor +.endif + +.for a b in ${LIST} ${LIST:tu} ${XTRA_LIST} +X!= echo 'a=$a b=$b' >&2; echo +.endfor + +for-loop: + @echo We expect an error next: + @(cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} for-fail) && \ + { echo "Oops that should have failed!"; exit 1; } || echo OK diff --git a/unit-tests/forsubst b/unit-tests/forsubst deleted file mode 100644 index d3a7de1b38da..000000000000 --- a/unit-tests/forsubst +++ /dev/null @@ -1,10 +0,0 @@ -# $Id: forsubst,v 1.1.1.1 2009/10/07 18:53:35 sjg Exp $ - -all: for-subst - -here := ${.PARSEDIR} -# this should not run foul of the parser -.for file in ${.PARSEFILE} -for-subst: ${file:S;^;${here}/;g} - @echo ".for with :S;... OK" -.endfor diff --git a/unit-tests/forsubst.exp b/unit-tests/forsubst.exp new file mode 100644 index 000000000000..0a98c00aff30 --- /dev/null +++ b/unit-tests/forsubst.exp @@ -0,0 +1,2 @@ +.for with :S;... OK +exit status 0 diff --git a/unit-tests/forsubst.mk b/unit-tests/forsubst.mk new file mode 100644 index 000000000000..2923e4b369f9 --- /dev/null +++ b/unit-tests/forsubst.mk @@ -0,0 +1,10 @@ +# $Id: forsubst.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +all: for-subst + +here := ${.PARSEDIR} +# this should not run foul of the parser +.for file in ${.PARSEFILE} +for-subst: ${file:S;^;${here}/;g} + @echo ".for with :S;... OK" +.endfor diff --git a/unit-tests/hash b/unit-tests/hash deleted file mode 100644 index 1ed84e776d09..000000000000 --- a/unit-tests/hash +++ /dev/null @@ -1,18 +0,0 @@ -STR1= -STR2= a -STR3= ab -STR4= abc -STR5= abcd -STR6= abcde -STR7= abcdef -STR8= abcdefghijklmnopqrstuvwxyz - -all: - @echo ${STR1:hash} - @echo ${STR2:hash} - @echo ${STR3:hash} - @echo ${STR4:hash} - @echo ${STR5:hash} - @echo ${STR6:hash} - @echo ${STR7:hash} - @echo ${STR8:hash} diff --git a/unit-tests/hash.exp b/unit-tests/hash.exp new file mode 100644 index 000000000000..0a2423436e77 --- /dev/null +++ b/unit-tests/hash.exp @@ -0,0 +1,9 @@ +b2af338b +3360ac65 +7747f046 +9ca87054 +880fe816 +208fcbd3 +d5d376eb +de41416c +exit status 0 diff --git a/unit-tests/hash.mk b/unit-tests/hash.mk new file mode 100644 index 000000000000..1ed84e776d09 --- /dev/null +++ b/unit-tests/hash.mk @@ -0,0 +1,18 @@ +STR1= +STR2= a +STR3= ab +STR4= abc +STR5= abcd +STR6= abcde +STR7= abcdef +STR8= abcdefghijklmnopqrstuvwxyz + +all: + @echo ${STR1:hash} + @echo ${STR2:hash} + @echo ${STR3:hash} + @echo ${STR4:hash} + @echo ${STR5:hash} + @echo ${STR6:hash} + @echo ${STR7:hash} + @echo ${STR8:hash} diff --git a/unit-tests/impsrc.exp b/unit-tests/impsrc.exp new file mode 100644 index 000000000000..23e8347d205d --- /dev/null +++ b/unit-tests/impsrc.exp @@ -0,0 +1,13 @@ +expected: source4 +actual: source4 +expected: target1.x +actual: target1.x +expected: target1.y +actual: target1.y +expected: source1 +actual: source1 +expected: source2 +actual: source2 +expected: source1 +actual: source1 +exit status 0 diff --git a/unit-tests/impsrc.mk b/unit-tests/impsrc.mk new file mode 100644 index 000000000000..95ae0c34f3b5 --- /dev/null +++ b/unit-tests/impsrc.mk @@ -0,0 +1,43 @@ +# $NetBSD: impsrc.mk,v 1.2 2014/08/30 22:21:07 sjg Exp $ + +# Does ${.IMPSRC} work properly? +# It should be set, in order of precedence, to ${.TARGET} of: +# 1) the implied source of a transformation rule, +# 2) the first prerequisite from the dependency line of an explicit rule, or +# 3) the first prerequisite of an explicit rule. +# + +all: target1.z target2 target3 target4 + +.SUFFIXES: .x .y .z + +.x.y: source1 + @echo 'expected: target1.x' + @echo 'actual: $<' + +.y.z: source2 + @echo 'expected: target1.y' + @echo 'actual: $<' + +target1.y: source3 + +target1.x: source4 + @echo 'expected: source4' + @echo 'actual: $<' + +target2: source1 source2 + @echo 'expected: source1' + @echo 'actual: $<' + +target3: source1 +target3: source2 source3 + @echo 'expected: source2' + @echo 'actual: $<' + +target4: source1 +target4: + @echo 'expected: source1' + @echo 'actual: $<' + +source1 source2 source3 source4: + diff --git a/unit-tests/misc b/unit-tests/misc deleted file mode 100644 index 4ba3655f4fa0..000000000000 --- a/unit-tests/misc +++ /dev/null @@ -1,16 +0,0 @@ -# $Id: misc,v 1.1.1.1 2011/03/06 00:04:58 sjg Exp $ - -.if !exists(${.CURDIR}/) -.warning ${.CURDIR}/ doesn't exist ? -.endif - -.if !exists(${.CURDIR}/.) -.warning ${.CURDIR}/. doesn't exist ? -.endif - -.if !exists(${.CURDIR}/..) -.warning ${.CURDIR}/.. doesn't exist ? -.endif - -all: - @: all is well diff --git a/unit-tests/misc.exp b/unit-tests/misc.exp new file mode 100644 index 000000000000..39a9383953dd --- /dev/null +++ b/unit-tests/misc.exp @@ -0,0 +1 @@ +exit status 0 diff --git a/unit-tests/misc.mk b/unit-tests/misc.mk new file mode 100644 index 000000000000..030115079a94 --- /dev/null +++ b/unit-tests/misc.mk @@ -0,0 +1,16 @@ +# $Id: misc.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +.if !exists(${.CURDIR}/) +.warning ${.CURDIR}/ doesn't exist ? +.endif + +.if !exists(${.CURDIR}/.) +.warning ${.CURDIR}/. doesn't exist ? +.endif + +.if !exists(${.CURDIR}/..) +.warning ${.CURDIR}/.. doesn't exist ? +.endif + +all: + @: all is well diff --git a/unit-tests/moderrs b/unit-tests/moderrs deleted file mode 100644 index b8f78ce3836b..000000000000 --- a/unit-tests/moderrs +++ /dev/null @@ -1,31 +0,0 @@ -# $Id: moderrs,v 1.2 2006/05/11 18:53:39 sjg Exp $ -# -# various modifier error tests - -VAR=TheVariable -# incase we have to change it ;-) -MOD_UNKN=Z -MOD_TERM=S,V,v -MOD_S:= ${MOD_TERM}, - -all: modunkn modunknV varterm vartermV modtermV - -modunkn: - @echo "Expect: Unknown modifier 'Z'" - @echo "VAR:Z=${VAR:Z}" - -modunknV: - @echo "Expect: Unknown modifier 'Z'" - @echo "VAR:${MOD_UNKN}=${VAR:${MOD_UNKN}}" - -varterm: - @echo "Expect: Unclosed variable specification for VAR" - @echo VAR:S,V,v,=${VAR:S,V,v, - -vartermV: - @echo "Expect: Unclosed variable specification for VAR" - @echo VAR:${MOD_TERM},=${VAR:${MOD_S} - -modtermV: - @echo "Expect: Unclosed substitution for VAR (, missing)" - -@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}" diff --git a/unit-tests/moderrs.exp b/unit-tests/moderrs.exp new file mode 100644 index 000000000000..cb51aa09d909 --- /dev/null +++ b/unit-tests/moderrs.exp @@ -0,0 +1,16 @@ +Expect: Unknown modifier 'Z' +make: Unknown modifier 'Z' +VAR:Z= +Expect: Unknown modifier 'Z' +make: Unknown modifier 'Z' +VAR:Z= +Expect: Unclosed variable specification for VAR +make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S +VAR:S,V,v,=Thevariable +Expect: Unclosed variable specification for VAR +make: Unclosed variable specification after complex modifier (expecting '}') for VAR +VAR:S,V,v,=Thevariable +Expect: Unclosed substitution for VAR (, missing) +make: Unclosed substitution for VAR (, missing) +VAR:S,V,v= +exit status 0 diff --git a/unit-tests/moderrs.mk b/unit-tests/moderrs.mk new file mode 100644 index 000000000000..d0eb17ff6df6 --- /dev/null +++ b/unit-tests/moderrs.mk @@ -0,0 +1,31 @@ +# $Id: moderrs.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ +# +# various modifier error tests + +VAR=TheVariable +# incase we have to change it ;-) +MOD_UNKN=Z +MOD_TERM=S,V,v +MOD_S:= ${MOD_TERM}, + +all: modunkn modunknV varterm vartermV modtermV + +modunkn: + @echo "Expect: Unknown modifier 'Z'" + @echo "VAR:Z=${VAR:Z}" + +modunknV: + @echo "Expect: Unknown modifier 'Z'" + @echo "VAR:${MOD_UNKN}=${VAR:${MOD_UNKN}}" + +varterm: + @echo "Expect: Unclosed variable specification for VAR" + @echo VAR:S,V,v,=${VAR:S,V,v, + +vartermV: + @echo "Expect: Unclosed variable specification for VAR" + @echo VAR:${MOD_TERM},=${VAR:${MOD_S} + +modtermV: + @echo "Expect: Unclosed substitution for VAR (, missing)" + -@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}" diff --git a/unit-tests/modmatch b/unit-tests/modmatch deleted file mode 100644 index 48a1befb58b6..000000000000 --- a/unit-tests/modmatch +++ /dev/null @@ -1,25 +0,0 @@ - -X=a b c d e - -.for x in $X -LIB${x:tu}=/tmp/lib$x.a -.endfor - -X_LIBS= ${LIBA} ${LIBD} ${LIBE} - -LIB?=a - -var = head -res = no -.if !empty(var:M${:Uhead\:tail:C/:.*//}) -res = OK -.endif - -all: - @for x in $X; do ${.MAKE} -f ${MAKEFILE} show LIB=$$x; done - @echo "Mscanner=${res}" - -show: - @echo 'LIB=${LIB} X_LIBS:M$${LIB$${LIB:tu}} is "${X_LIBS:M${LIB${LIB:tu}}}"' - @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a is "${X_LIBS:M*/lib${LIB}.a}"' - @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a:tu is "${X_LIBS:M*/lib${LIB}.a:tu}"' diff --git a/unit-tests/modmatch.exp b/unit-tests/modmatch.exp new file mode 100644 index 000000000000..fcaf6c02ed69 --- /dev/null +++ b/unit-tests/modmatch.exp @@ -0,0 +1,17 @@ +LIB=a X_LIBS:M${LIB${LIB:tu}} is "/tmp/liba.a" +LIB=a X_LIBS:M*/lib${LIB}.a is "/tmp/liba.a" +LIB=a X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBA.A" +LIB=b X_LIBS:M${LIB${LIB:tu}} is "" +LIB=b X_LIBS:M*/lib${LIB}.a is "" +LIB=b X_LIBS:M*/lib${LIB}.a:tu is "" +LIB=c X_LIBS:M${LIB${LIB:tu}} is "" +LIB=c X_LIBS:M*/lib${LIB}.a is "" +LIB=c X_LIBS:M*/lib${LIB}.a:tu is "" +LIB=d X_LIBS:M${LIB${LIB:tu}} is "/tmp/libd.a" +LIB=d X_LIBS:M*/lib${LIB}.a is "/tmp/libd.a" +LIB=d X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBD.A" +LIB=e X_LIBS:M${LIB${LIB:tu}} is "/tmp/libe.a" +LIB=e X_LIBS:M*/lib${LIB}.a is "/tmp/libe.a" +LIB=e X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBE.A" +Mscanner=OK +exit status 0 diff --git a/unit-tests/modmatch.mk b/unit-tests/modmatch.mk new file mode 100644 index 000000000000..48a1befb58b6 --- /dev/null +++ b/unit-tests/modmatch.mk @@ -0,0 +1,25 @@ + +X=a b c d e + +.for x in $X +LIB${x:tu}=/tmp/lib$x.a +.endfor + +X_LIBS= ${LIBA} ${LIBD} ${LIBE} + +LIB?=a + +var = head +res = no +.if !empty(var:M${:Uhead\:tail:C/:.*//}) +res = OK +.endif + +all: + @for x in $X; do ${.MAKE} -f ${MAKEFILE} show LIB=$$x; done + @echo "Mscanner=${res}" + +show: + @echo 'LIB=${LIB} X_LIBS:M$${LIB$${LIB:tu}} is "${X_LIBS:M${LIB${LIB:tu}}}"' + @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a is "${X_LIBS:M*/lib${LIB}.a}"' + @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a:tu is "${X_LIBS:M*/lib${LIB}.a:tu}"' diff --git a/unit-tests/modmisc b/unit-tests/modmisc deleted file mode 100644 index d562e46a5487..000000000000 --- a/unit-tests/modmisc +++ /dev/null @@ -1,38 +0,0 @@ -# $Id: modmisc,v 1.1.1.5 2011/04/11 15:10:32 sjg Exp $ -# -# miscellaneous modifier tests - -# do not put any dirs in this list which exist on some -# but not all target systems - an exists() check is below. -path=:/bin:/tmp::/:.:/no/such/dir:. -# strip cwd from path. -MOD_NODOT=S/:/ /g:N.:ts: -# and decorate, note that $'s need to be doubled. Also note that -# the modifier_variable can be used with other modifiers. -MOD_NODOTX=S/:/ /g:N.:@d@'$$d'@ -# another mod - pretend it is more interesting -MOD_HOMES=S,/home/,/homes/, -MOD_OPT=@d@$${exists($$d):?$$d:$${d:S,/usr,/opt,}}@ -MOD_SEP=S,:, ,g - -all: modvar modvarloop modsysv - -modsysv: - @echo "The answer is ${libfoo.a:L:libfoo.a=42}" - -modvar: - @echo "path='${path}'" - @echo "path='${path:${MOD_NODOT}}'" - @echo "path='${path:S,home,homes,:${MOD_NODOT}}'" - @echo "path=${path:${MOD_NODOTX}:ts:}" - @echo "path=${path:${MOD_HOMES}:${MOD_NODOTX}:ts:}" - -.for d in ${path:${MOD_SEP}:N.} /usr/xbin -path_$d?= ${d:${MOD_OPT}:${MOD_HOMES}}/ -paths+= ${d:${MOD_OPT}:${MOD_HOMES}} -.endfor - -modvarloop: - @echo "path_/usr/xbin=${path_/usr/xbin}" - @echo "paths=${paths}" - @echo "PATHS=${paths:tu}" diff --git a/unit-tests/modmisc.exp b/unit-tests/modmisc.exp new file mode 100644 index 000000000000..e406647bc41f --- /dev/null +++ b/unit-tests/modmisc.exp @@ -0,0 +1,10 @@ +path=':/bin:/tmp::/:.:/no/such/dir:.' +path='/bin:/tmp:/:/no/such/dir' +path='/bin:/tmp:/:/no/such/dir' +path='/bin':'/tmp':'/':'/no/such/dir' +path='/bin':'/tmp':'/':'/no/such/dir' +path_/usr/xbin=/opt/xbin/ +paths=/bin /tmp / /no/such/dir /opt/xbin +PATHS=/BIN /TMP / /NO/SUCH/DIR /OPT/XBIN +The answer is 42 +exit status 0 diff --git a/unit-tests/modmisc.mk b/unit-tests/modmisc.mk new file mode 100644 index 000000000000..043498fb1af4 --- /dev/null +++ b/unit-tests/modmisc.mk @@ -0,0 +1,38 @@ +# $Id: modmisc.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ +# +# miscellaneous modifier tests + +# do not put any dirs in this list which exist on some +# but not all target systems - an exists() check is below. +path=:/bin:/tmp::/:.:/no/such/dir:. +# strip cwd from path. +MOD_NODOT=S/:/ /g:N.:ts: +# and decorate, note that $'s need to be doubled. Also note that +# the modifier_variable can be used with other modifiers. +MOD_NODOTX=S/:/ /g:N.:@d@'$$d'@ +# another mod - pretend it is more interesting +MOD_HOMES=S,/home/,/homes/, +MOD_OPT=@d@$${exists($$d):?$$d:$${d:S,/usr,/opt,}}@ +MOD_SEP=S,:, ,g + +all: modvar modvarloop modsysv + +modsysv: + @echo "The answer is ${libfoo.a:L:libfoo.a=42}" + +modvar: + @echo "path='${path}'" + @echo "path='${path:${MOD_NODOT}}'" + @echo "path='${path:S,home,homes,:${MOD_NODOT}}'" + @echo "path=${path:${MOD_NODOTX}:ts:}" + @echo "path=${path:${MOD_HOMES}:${MOD_NODOTX}:ts:}" + +.for d in ${path:${MOD_SEP}:N.} /usr/xbin +path_$d?= ${d:${MOD_OPT}:${MOD_HOMES}}/ +paths+= ${d:${MOD_OPT}:${MOD_HOMES}} +.endfor + +modvarloop: + @echo "path_/usr/xbin=${path_/usr/xbin}" + @echo "paths=${paths}" + @echo "PATHS=${paths:tu}" diff --git a/unit-tests/modorder b/unit-tests/modorder deleted file mode 100644 index 68b66fb6226d..000000000000 --- a/unit-tests/modorder +++ /dev/null @@ -1,22 +0,0 @@ -# $NetBSD: modorder,v 1.2 2007/10/05 15:27:46 sjg Exp $ - -LIST= one two three four five six seven eight nine ten -LISTX= ${LIST:Ox} -LISTSX:= ${LIST:Ox} -TEST_RESULT= && echo Ok || echo Failed - -# unit-tests have to produce the same results on each run -# so we cannot actually include :Ox output. -all: - @echo "LIST = ${LIST}" - @echo "LIST:O = ${LIST:O}" - # Note that 1 in every 10! trials two independently generated - # randomized orderings will be the same. The test framework doesn't - # support checking probabilistic output, so we accept that the test - # will incorrectly fail with probability 2.8E-7. - @echo "LIST:Ox = `test '${LIST:Ox}' != '${LIST:Ox}' ${TEST_RESULT}`" - @echo "LIST:O:Ox = `test '${LIST:O:Ox}' != '${LIST:O:Ox}' ${TEST_RESULT}`" - @echo "LISTX = `test '${LISTX}' != '${LISTX}' ${TEST_RESULT}`" - @echo "LISTSX = `test '${LISTSX}' = '${LISTSX}' ${TEST_RESULT}`" - @echo "BADMOD 1 = ${LIST:OX}" - @echo "BADMOD 2 = ${LIST:OxXX}" diff --git a/unit-tests/modorder.exp b/unit-tests/modorder.exp new file mode 100644 index 000000000000..411742738d63 --- /dev/null +++ b/unit-tests/modorder.exp @@ -0,0 +1,11 @@ +LIST = one two three four five six seven eight nine ten +LIST:O = eight five four nine one seven six ten three two +LIST:Ox = Ok +LIST:O:Ox = Ok +LISTX = Ok +LISTSX = Ok +make: Bad modifier `:OX' for LIST +BADMOD 1 = } +make: Bad modifier `:OxXX' for LIST +BADMOD 2 = XX} +exit status 0 diff --git a/unit-tests/modorder.mk b/unit-tests/modorder.mk new file mode 100644 index 000000000000..bc24d339f45a --- /dev/null +++ b/unit-tests/modorder.mk @@ -0,0 +1,22 @@ +# $NetBSD: modorder.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +LIST= one two three four five six seven eight nine ten +LISTX= ${LIST:Ox} +LISTSX:= ${LIST:Ox} +TEST_RESULT= && echo Ok || echo Failed + +# unit-tests have to produce the same results on each run +# so we cannot actually include :Ox output. +all: + @echo "LIST = ${LIST}" + @echo "LIST:O = ${LIST:O}" + # Note that 1 in every 10! trials two independently generated + # randomized orderings will be the same. The test framework doesn't + # support checking probabilistic output, so we accept that the test + # will incorrectly fail with probability 2.8E-7. + @echo "LIST:Ox = `test '${LIST:Ox}' != '${LIST:Ox}' ${TEST_RESULT}`" + @echo "LIST:O:Ox = `test '${LIST:O:Ox}' != '${LIST:O:Ox}' ${TEST_RESULT}`" + @echo "LISTX = `test '${LISTX}' != '${LISTX}' ${TEST_RESULT}`" + @echo "LISTSX = `test '${LISTSX}' = '${LISTSX}' ${TEST_RESULT}`" + @echo "BADMOD 1 = ${LIST:OX}" + @echo "BADMOD 2 = ${LIST:OxXX}" diff --git a/unit-tests/modts b/unit-tests/modts deleted file mode 100644 index 616bd8944f21..000000000000 --- a/unit-tests/modts +++ /dev/null @@ -1,43 +0,0 @@ - -LIST= one two three -LIST+= four five six - -FU_mod-ts = a / b / cool - -AAA= a a a -B.aaa= Baaa - -all: mod-ts - -# Use print or printf iff they are builtin. -# XXX note that this causes problems, when make decides -# there is no need to use a shell, so avoid where possible. -.if ${type print 2> /dev/null || echo:L:sh:Mbuiltin} != "" -PRINT= print -r -- -.elif ${type printf 2> /dev/null || echo:L:sh:Mbuiltin} != "" -PRINT= printf '%s\n' -.else -PRINT= echo -.endif - -mod-ts: - @echo 'LIST="${LIST}"' - @echo 'LIST:ts,="${LIST:ts,}"' - @echo 'LIST:ts/:tu="${LIST:ts/:tu}"' - @echo 'LIST:ts::tu="${LIST:ts::tu}"' - @echo 'LIST:ts:tu="${LIST:ts:tu}"' - @echo 'LIST:tu:ts/="${LIST:tu:ts/}"' - @echo 'LIST:ts:="${LIST:ts:}"' - @echo 'LIST:ts="${LIST:ts}"' - @echo 'LIST:ts:S/two/2/="${LIST:ts:S/two/2/}"' - @echo 'LIST:S/two/2/:ts="${LIST:S/two/2/:ts}"' - @echo 'LIST:ts/:S/two/2/="${LIST:ts/:S/two/2/}"' - @echo "Pretend the '/' in '/n' etc. below are back-slashes." - @${PRINT} 'LIST:ts/n="${LIST:ts\n}"' - @${PRINT} 'LIST:ts/t="${LIST:ts\t}"' - @${PRINT} 'LIST:ts/012:tu="${LIST:ts\012:tu}"' - @${PRINT} 'LIST:tx="${LIST:tx}"' - @${PRINT} 'LIST:ts/x:tu="${LIST:ts\x:tu}"' - @${PRINT} 'FU_$@="${FU_${@:ts}:ts}"' - @${PRINT} 'FU_$@:ts:T="${FU_${@:ts}:ts:T}" == cool?' - @${PRINT} 'B.$${AAA:ts}="${B.${AAA:ts}}" == Baaa?' diff --git a/unit-tests/modts.exp b/unit-tests/modts.exp new file mode 100644 index 000000000000..cf3c91d43c0c --- /dev/null +++ b/unit-tests/modts.exp @@ -0,0 +1,33 @@ +LIST="one two three four five six" +LIST:ts,="one,two,three,four,five,six" +LIST:ts/:tu="ONE/TWO/THREE/FOUR/FIVE/SIX" +LIST:ts::tu="ONE:TWO:THREE:FOUR:FIVE:SIX" +LIST:ts:tu="ONETWOTHREEFOURFIVESIX" +LIST:tu:ts/="ONE/TWO/THREE/FOUR/FIVE/SIX" +LIST:ts:="one:two:three:four:five:six" +LIST:ts="onetwothreefourfivesix" +LIST:ts:S/two/2/="one2threefourfivesix" +LIST:S/two/2/:ts="one2threefourfivesix" +LIST:ts/:S/two/2/="one/2/three/four/five/six" +Pretend the '/' in '/n' etc. below are back-slashes. +LIST:ts/n="one +two +three +four +five +six" +LIST:ts/t="one two three four five six" +LIST:ts/012:tu="ONE +TWO +THREE +FOUR +FIVE +SIX" +make: Bad modifier `:tx' for LIST +LIST:tx="}" +make: Bad modifier `:ts\x' for LIST +LIST:ts/x:tu="\x:tu}" +FU_mod-ts="a/b/cool" +FU_mod-ts:ts:T="cool" == cool? +B.${AAA:ts}="Baaa" == Baaa? +exit status 0 diff --git a/unit-tests/modts.mk b/unit-tests/modts.mk new file mode 100644 index 000000000000..616bd8944f21 --- /dev/null +++ b/unit-tests/modts.mk @@ -0,0 +1,43 @@ + +LIST= one two three +LIST+= four five six + +FU_mod-ts = a / b / cool + +AAA= a a a +B.aaa= Baaa + +all: mod-ts + +# Use print or printf iff they are builtin. +# XXX note that this causes problems, when make decides +# there is no need to use a shell, so avoid where possible. +.if ${type print 2> /dev/null || echo:L:sh:Mbuiltin} != "" +PRINT= print -r -- +.elif ${type printf 2> /dev/null || echo:L:sh:Mbuiltin} != "" +PRINT= printf '%s\n' +.else +PRINT= echo +.endif + +mod-ts: + @echo 'LIST="${LIST}"' + @echo 'LIST:ts,="${LIST:ts,}"' + @echo 'LIST:ts/:tu="${LIST:ts/:tu}"' + @echo 'LIST:ts::tu="${LIST:ts::tu}"' + @echo 'LIST:ts:tu="${LIST:ts:tu}"' + @echo 'LIST:tu:ts/="${LIST:tu:ts/}"' + @echo 'LIST:ts:="${LIST:ts:}"' + @echo 'LIST:ts="${LIST:ts}"' + @echo 'LIST:ts:S/two/2/="${LIST:ts:S/two/2/}"' + @echo 'LIST:S/two/2/:ts="${LIST:S/two/2/:ts}"' + @echo 'LIST:ts/:S/two/2/="${LIST:ts/:S/two/2/}"' + @echo "Pretend the '/' in '/n' etc. below are back-slashes." + @${PRINT} 'LIST:ts/n="${LIST:ts\n}"' + @${PRINT} 'LIST:ts/t="${LIST:ts\t}"' + @${PRINT} 'LIST:ts/012:tu="${LIST:ts\012:tu}"' + @${PRINT} 'LIST:tx="${LIST:tx}"' + @${PRINT} 'LIST:ts/x:tu="${LIST:ts\x:tu}"' + @${PRINT} 'FU_$@="${FU_${@:ts}:ts}"' + @${PRINT} 'FU_$@:ts:T="${FU_${@:ts}:ts:T}" == cool?' + @${PRINT} 'B.$${AAA:ts}="${B.${AAA:ts}}" == Baaa?' diff --git a/unit-tests/modword b/unit-tests/modword deleted file mode 100644 index 39355d7bacfa..000000000000 --- a/unit-tests/modword +++ /dev/null @@ -1,151 +0,0 @@ -# $Id: modword,v 1.1.1.1 2003/09/28 17:01:48 sjg Exp $ -# -# Test behaviour of new :[] modifier - -all: mod-squarebrackets mod-S-W mod-C-W mod-tW-tw - -LIST= one two three -LIST+= four five six -LONGLIST= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 - -EMPTY= # the space should be ignored -ESCAPEDSPACE=\ # escaped space before the '#' -REALLYSPACE:=${EMPTY:C/^/ /W} -HASH= \# -AT= @ -STAR= * -ZERO= 0 -ONE= 1 -MINUSONE= -1 - -mod-squarebrackets: mod-squarebrackets-0-star-at \ - mod-squarebrackets-hash \ - mod-squarebrackets-n \ - mod-squarebrackets-start-end \ - mod-squarebrackets-nested - -mod-squarebrackets-0-star-at: - @echo 'LIST:[]="${LIST:[]}" is an error' - @echo 'LIST:[0]="${LIST:[0]}"' - @echo 'LIST:[0x0]="${LIST:[0x0]}"' - @echo 'LIST:[000]="${LIST:[000]}"' - @echo 'LIST:[*]="${LIST:[*]}"' - @echo 'LIST:[@]="${LIST:[@]}"' - @echo 'LIST:[0]:C/ /,/="${LIST:[0]:C/ /,/}"' - @echo 'LIST:[0]:C/ /,/g="${LIST:[0]:C/ /,/g}"' - @echo 'LIST:[0]:C/ /,/1g="${LIST:[0]:C/ /,/1g}"' - @echo 'LIST:[*]:C/ /,/="${LIST:[*]:C/ /,/}"' - @echo 'LIST:[*]:C/ /,/g="${LIST:[*]:C/ /,/g}"' - @echo 'LIST:[*]:C/ /,/1g="${LIST:[*]:C/ /,/1g}"' - @echo 'LIST:[@]:C/ /,/="${LIST:[@]:C/ /,/}"' - @echo 'LIST:[@]:C/ /,/g="${LIST:[@]:C/ /,/g}"' - @echo 'LIST:[@]:C/ /,/1g="${LIST:[@]:C/ /,/1g}"' - @echo 'LIST:[@]:[0]:C/ /,/="${LIST:[@]:[0]:C/ /,/}"' - @echo 'LIST:[0]:[@]:C/ /,/="${LIST:[0]:[@]:C/ /,/}"' - @echo 'LIST:[@]:[*]:C/ /,/="${LIST:[@]:[*]:C/ /,/}"' - @echo 'LIST:[*]:[@]:C/ /,/="${LIST:[*]:[@]:C/ /,/}"' - -mod-squarebrackets-hash: - @echo 'EMPTY="${EMPTY}"' - @echo 'EMPTY:[#]="${EMPTY:[#]}" == 1 ?' - @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' - @echo 'ESCAPEDSPACE:[#]="${ESCAPEDSPACE:[#]}" == 1 ?' - @echo 'REALLYSPACE="${REALLYSPACE}"' - @echo 'REALLYSPACE:[#]="${REALLYSPACE:[#]}" == 1 ?' - @echo 'LIST:[#]="${LIST:[#]}"' - @echo 'LIST:[0]:[#]="${LIST:[0]:[#]}" == 1 ?' - @echo 'LIST:[*]:[#]="${LIST:[*]:[#]}" == 1 ?' - @echo 'LIST:[@]:[#]="${LIST:[@]:[#]}"' - @echo 'LIST:[1]:[#]="${LIST:[1]:[#]}"' - @echo 'LIST:[1..3]:[#]="${LIST:[1..3]:[#]}"' - -mod-squarebrackets-n: - @echo 'EMPTY:[1]="${EMPTY:[1]}"' - @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' - @echo 'ESCAPEDSPACE:[1]="${ESCAPEDSPACE:[1]}"' - @echo 'REALLYSPACE="${REALLYSPACE}"' - @echo 'REALLYSPACE:[1]="${REALLYSPACE:[1]}" == "" ?' - @echo 'REALLYSPACE:[*]:[1]="${REALLYSPACE:[*]:[1]}" == " " ?' - @echo 'LIST:[1]="${LIST:[1]}"' - @echo 'LIST:[1.]="${LIST:[1.]}" is an error' - @echo 'LIST:[1].="${LIST:[1].}" is an error' - @echo 'LIST:[2]="${LIST:[2]}"' - @echo 'LIST:[6]="${LIST:[6]}"' - @echo 'LIST:[7]="${LIST:[7]}"' - @echo 'LIST:[999]="${LIST:[999]}"' - @echo 'LIST:[-]="${LIST:[-]}" is an error' - @echo 'LIST:[--]="${LIST:[--]}" is an error' - @echo 'LIST:[-1]="${LIST:[-1]}"' - @echo 'LIST:[-2]="${LIST:[-2]}"' - @echo 'LIST:[-6]="${LIST:[-6]}"' - @echo 'LIST:[-7]="${LIST:[-7]}"' - @echo 'LIST:[-999]="${LIST:[-999]}"' - @echo 'LONGLIST:[17]="${LONGLIST:[17]}"' - @echo 'LONGLIST:[0x11]="${LONGLIST:[0x11]}"' - @echo 'LONGLIST:[021]="${LONGLIST:[021]}"' - @echo 'LIST:[0]:[1]="${LIST:[0]:[1]}"' - @echo 'LIST:[*]:[1]="${LIST:[*]:[1]}"' - @echo 'LIST:[@]:[1]="${LIST:[@]:[1]}"' - @echo 'LIST:[0]:[2]="${LIST:[0]:[2]}"' - @echo 'LIST:[*]:[2]="${LIST:[*]:[2]}"' - @echo 'LIST:[@]:[2]="${LIST:[@]:[2]}"' - @echo 'LIST:[*]:C/ /,/:[2]="${LIST:[*]:C/ /,/:[2]}"' - @echo 'LIST:[*]:C/ /,/:[*]:[2]="${LIST:[*]:C/ /,/:[*]:[2]}"' - @echo 'LIST:[*]:C/ /,/:[@]:[2]="${LIST:[*]:C/ /,/:[@]:[2]}"' - -mod-squarebrackets-start-end: - @echo 'LIST:[1.]="${LIST:[1.]}" is an error' - @echo 'LIST:[1..]="${LIST:[1..]}" is an error' - @echo 'LIST:[1..1]="${LIST:[1..1]}"' - @echo 'LIST:[1..1.]="${LIST:[1..1.]}" is an error' - @echo 'LIST:[1..2]="${LIST:[1..2]}"' - @echo 'LIST:[2..1]="${LIST:[2..1]}"' - @echo 'LIST:[3..-2]="${LIST:[3..-2]}"' - @echo 'LIST:[-4..4]="${LIST:[-4..4]}"' - @echo 'LIST:[0..1]="${LIST:[0..1]}" is an error' - @echo 'LIST:[-1..0]="${LIST:[-1..0]}" is an error' - @echo 'LIST:[-1..1]="${LIST:[-1..1]}"' - @echo 'LIST:[0..0]="${LIST:[0..0]}"' - @echo 'LIST:[3..99]="${LIST:[3..99]}"' - @echo 'LIST:[-3..-99]="${LIST:[-3..-99]}"' - @echo 'LIST:[-99..-3]="${LIST:[-99..-3]}"' - -mod-squarebrackets-nested: - @echo 'HASH="${HASH}" == "#" ?' - @echo 'LIST:[$${HASH}]="${LIST:[${HASH}]}"' - @echo 'LIST:[$${ZERO}]="${LIST:[${ZERO}]}"' - @echo 'LIST:[$${ZERO}x$${ONE}]="${LIST:[${ZERO}x${ONE}]}"' - @echo 'LIST:[$${ONE}]="${LIST:[${ONE}]}"' - @echo 'LIST:[$${MINUSONE}]="${LIST:[${MINUSONE}]}"' - @echo 'LIST:[$${STAR}]="${LIST:[${STAR}]}"' - @echo 'LIST:[$${AT}]="${LIST:[${AT}]}"' - @echo 'LIST:[$${EMPTY}]="${LIST:[${EMPTY}]}" is an error' - @echo 'LIST:[$${LONGLIST:[21]:S/2//}]="${LIST:[${LONGLIST:[21]:S/2//}]}"' - @echo 'LIST:[$${LIST:[#]}]="${LIST:[${LIST:[#]}]}"' - @echo 'LIST:[$${LIST:[$${HASH}]}]="${LIST:[${LIST:[${HASH}]}]}"' - -mod-C-W: - @echo 'LIST:C/ /,/="${LIST:C/ /,/}"' - @echo 'LIST:C/ /,/W="${LIST:C/ /,/W}"' - @echo 'LIST:C/ /,/gW="${LIST:C/ /,/gW}"' - @echo 'EMPTY:C/^/,/="${EMPTY:C/^/,/}"' - @echo 'EMPTY:C/^/,/W="${EMPTY:C/^/,/W}"' - -mod-S-W: - @echo 'LIST:S/ /,/="${LIST:S/ /,/}"' - @echo 'LIST:S/ /,/W="${LIST:S/ /,/W}"' - @echo 'LIST:S/ /,/gW="${LIST:S/ /,/gW}"' - @echo 'EMPTY:S/^/,/="${EMPTY:S/^/,/}"' - @echo 'EMPTY:S/^/,/W="${EMPTY:S/^/,/W}"' - -mod-tW-tw: - @echo 'LIST:tW="${LIST:tW}"' - @echo 'LIST:tw="${LIST:tw}"' - @echo 'LIST:tW:C/ /,/="${LIST:tW:C/ /,/}"' - @echo 'LIST:tW:C/ /,/g="${LIST:tW:C/ /,/g}"' - @echo 'LIST:tW:C/ /,/1g="${LIST:tW:C/ /,/1g}"' - @echo 'LIST:tw:C/ /,/="${LIST:tw:C/ /,/}"' - @echo 'LIST:tw:C/ /,/g="${LIST:tw:C/ /,/g}"' - @echo 'LIST:tw:C/ /,/1g="${LIST:tw:C/ /,/1g}"' - @echo 'LIST:tw:tW:C/ /,/="${LIST:tw:tW:C/ /,/}"' - @echo 'LIST:tW:tw:C/ /,/="${LIST:tW:tw:C/ /,/}"' diff --git a/unit-tests/modword.exp b/unit-tests/modword.exp new file mode 100644 index 000000000000..258d7eadd6ce --- /dev/null +++ b/unit-tests/modword.exp @@ -0,0 +1,122 @@ +make: Bad modifier `:[]' for LIST +LIST:[]="" is an error +LIST:[0]="one two three four five six" +LIST:[0x0]="one two three four five six" +LIST:[000]="one two three four five six" +LIST:[*]="one two three four five six" +LIST:[@]="one two three four five six" +LIST:[0]:C/ /,/="one,two three four five six" +LIST:[0]:C/ /,/g="one,two,three,four,five,six" +LIST:[0]:C/ /,/1g="one,two,three,four,five,six" +LIST:[*]:C/ /,/="one,two three four five six" +LIST:[*]:C/ /,/g="one,two,three,four,five,six" +LIST:[*]:C/ /,/1g="one,two,three,four,five,six" +LIST:[@]:C/ /,/="one two three four five six" +LIST:[@]:C/ /,/g="one two three four five six" +LIST:[@]:C/ /,/1g="one two three four five six" +LIST:[@]:[0]:C/ /,/="one,two three four five six" +LIST:[0]:[@]:C/ /,/="one two three four five six" +LIST:[@]:[*]:C/ /,/="one,two three four five six" +LIST:[*]:[@]:C/ /,/="one two three four five six" +EMPTY="" +EMPTY:[#]="1" == 1 ? +ESCAPEDSPACE="\ " +ESCAPEDSPACE:[#]="1" == 1 ? +REALLYSPACE=" " +REALLYSPACE:[#]="1" == 1 ? +LIST:[#]="6" +LIST:[0]:[#]="1" == 1 ? +LIST:[*]:[#]="1" == 1 ? +LIST:[@]:[#]="6" +LIST:[1]:[#]="1" +LIST:[1..3]:[#]="3" +EMPTY:[1]="" +ESCAPEDSPACE="\ " +ESCAPEDSPACE:[1]="\ " +REALLYSPACE=" " +REALLYSPACE:[1]="" == "" ? +REALLYSPACE:[*]:[1]=" " == " " ? +LIST:[1]="one" +make: Bad modifier `:[1.]' for LIST +LIST:[1.]="" is an error +make: Bad modifier `:[1].' for LIST +LIST:[1].="}" is an error +LIST:[2]="two" +LIST:[6]="six" +LIST:[7]="" +LIST:[999]="" +make: Bad modifier `:[-]' for LIST +LIST:[-]="" is an error +make: Bad modifier `:[--]' for LIST +LIST:[--]="" is an error +LIST:[-1]="six" +LIST:[-2]="five" +LIST:[-6]="one" +LIST:[-7]="" +LIST:[-999]="" +LONGLIST:[17]="17" +LONGLIST:[0x11]="17" +LONGLIST:[021]="17" +LIST:[0]:[1]="one two three four five six" +LIST:[*]:[1]="one two three four five six" +LIST:[@]:[1]="one" +LIST:[0]:[2]="" +LIST:[*]:[2]="" +LIST:[@]:[2]="two" +LIST:[*]:C/ /,/:[2]="" +LIST:[*]:C/ /,/:[*]:[2]="" +LIST:[*]:C/ /,/:[@]:[2]="three" +make: Bad modifier `:[1.]' for LIST +LIST:[1.]="" is an error +make: Bad modifier `:[1..]' for LIST +LIST:[1..]="" is an error +LIST:[1..1]="one" +make: Bad modifier `:[1..1.]' for LIST +LIST:[1..1.]="" is an error +LIST:[1..2]="one two" +LIST:[2..1]="two one" +LIST:[3..-2]="three four five" +LIST:[-4..4]="three four" +make: Bad modifier `:[0..1]' for LIST +LIST:[0..1]="" is an error +make: Bad modifier `:[-1..0]' for LIST +LIST:[-1..0]="" is an error +LIST:[-1..1]="six five four three two one" +LIST:[0..0]="one two three four five six" +LIST:[3..99]="three four five six" +LIST:[-3..-99]="four three two one" +LIST:[-99..-3]="one two three four" +HASH="#" == "#" ? +LIST:[${HASH}]="6" +LIST:[${ZERO}]="one two three four five six" +LIST:[${ZERO}x${ONE}]="one" +LIST:[${ONE}]="one" +LIST:[${MINUSONE}]="six" +LIST:[${STAR}]="one two three four five six" +LIST:[${AT}]="one two three four five six" +make: Bad modifier `:[${EMPTY' for LIST +LIST:[${EMPTY}]="" is an error +LIST:[${LONGLIST:[21]:S/2//}]="one" +LIST:[${LIST:[#]}]="six" +LIST:[${LIST:[${HASH}]}]="six" +LIST:S/ /,/="one two three four five six" +LIST:S/ /,/W="one,two three four five six" +LIST:S/ /,/gW="one,two,three,four,five,six" +EMPTY:S/^/,/="," +EMPTY:S/^/,/W="," +LIST:C/ /,/="one two three four five six" +LIST:C/ /,/W="one,two three four five six" +LIST:C/ /,/gW="one,two,three,four,five,six" +EMPTY:C/^/,/="," +EMPTY:C/^/,/W="," +LIST:tW="one two three four five six" +LIST:tw="one two three four five six" +LIST:tW:C/ /,/="one,two three four five six" +LIST:tW:C/ /,/g="one,two,three,four,five,six" +LIST:tW:C/ /,/1g="one,two,three,four,five,six" +LIST:tw:C/ /,/="one two three four five six" +LIST:tw:C/ /,/g="one two three four five six" +LIST:tw:C/ /,/1g="one two three four five six" +LIST:tw:tW:C/ /,/="one,two three four five six" +LIST:tW:tw:C/ /,/="one two three four five six" +exit status 0 diff --git a/unit-tests/modword.mk b/unit-tests/modword.mk new file mode 100644 index 000000000000..1327624f7e19 --- /dev/null +++ b/unit-tests/modword.mk @@ -0,0 +1,151 @@ +# $Id: modword.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ +# +# Test behaviour of new :[] modifier + +all: mod-squarebrackets mod-S-W mod-C-W mod-tW-tw + +LIST= one two three +LIST+= four five six +LONGLIST= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + +EMPTY= # the space should be ignored +ESCAPEDSPACE=\ # escaped space before the '#' +REALLYSPACE:=${EMPTY:C/^/ /W} +HASH= \# +AT= @ +STAR= * +ZERO= 0 +ONE= 1 +MINUSONE= -1 + +mod-squarebrackets: mod-squarebrackets-0-star-at \ + mod-squarebrackets-hash \ + mod-squarebrackets-n \ + mod-squarebrackets-start-end \ + mod-squarebrackets-nested + +mod-squarebrackets-0-star-at: + @echo 'LIST:[]="${LIST:[]}" is an error' + @echo 'LIST:[0]="${LIST:[0]}"' + @echo 'LIST:[0x0]="${LIST:[0x0]}"' + @echo 'LIST:[000]="${LIST:[000]}"' + @echo 'LIST:[*]="${LIST:[*]}"' + @echo 'LIST:[@]="${LIST:[@]}"' + @echo 'LIST:[0]:C/ /,/="${LIST:[0]:C/ /,/}"' + @echo 'LIST:[0]:C/ /,/g="${LIST:[0]:C/ /,/g}"' + @echo 'LIST:[0]:C/ /,/1g="${LIST:[0]:C/ /,/1g}"' + @echo 'LIST:[*]:C/ /,/="${LIST:[*]:C/ /,/}"' + @echo 'LIST:[*]:C/ /,/g="${LIST:[*]:C/ /,/g}"' + @echo 'LIST:[*]:C/ /,/1g="${LIST:[*]:C/ /,/1g}"' + @echo 'LIST:[@]:C/ /,/="${LIST:[@]:C/ /,/}"' + @echo 'LIST:[@]:C/ /,/g="${LIST:[@]:C/ /,/g}"' + @echo 'LIST:[@]:C/ /,/1g="${LIST:[@]:C/ /,/1g}"' + @echo 'LIST:[@]:[0]:C/ /,/="${LIST:[@]:[0]:C/ /,/}"' + @echo 'LIST:[0]:[@]:C/ /,/="${LIST:[0]:[@]:C/ /,/}"' + @echo 'LIST:[@]:[*]:C/ /,/="${LIST:[@]:[*]:C/ /,/}"' + @echo 'LIST:[*]:[@]:C/ /,/="${LIST:[*]:[@]:C/ /,/}"' + +mod-squarebrackets-hash: + @echo 'EMPTY="${EMPTY}"' + @echo 'EMPTY:[#]="${EMPTY:[#]}" == 1 ?' + @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' + @echo 'ESCAPEDSPACE:[#]="${ESCAPEDSPACE:[#]}" == 1 ?' + @echo 'REALLYSPACE="${REALLYSPACE}"' + @echo 'REALLYSPACE:[#]="${REALLYSPACE:[#]}" == 1 ?' + @echo 'LIST:[#]="${LIST:[#]}"' + @echo 'LIST:[0]:[#]="${LIST:[0]:[#]}" == 1 ?' + @echo 'LIST:[*]:[#]="${LIST:[*]:[#]}" == 1 ?' + @echo 'LIST:[@]:[#]="${LIST:[@]:[#]}"' + @echo 'LIST:[1]:[#]="${LIST:[1]:[#]}"' + @echo 'LIST:[1..3]:[#]="${LIST:[1..3]:[#]}"' + +mod-squarebrackets-n: + @echo 'EMPTY:[1]="${EMPTY:[1]}"' + @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' + @echo 'ESCAPEDSPACE:[1]="${ESCAPEDSPACE:[1]}"' + @echo 'REALLYSPACE="${REALLYSPACE}"' + @echo 'REALLYSPACE:[1]="${REALLYSPACE:[1]}" == "" ?' + @echo 'REALLYSPACE:[*]:[1]="${REALLYSPACE:[*]:[1]}" == " " ?' + @echo 'LIST:[1]="${LIST:[1]}"' + @echo 'LIST:[1.]="${LIST:[1.]}" is an error' + @echo 'LIST:[1].="${LIST:[1].}" is an error' + @echo 'LIST:[2]="${LIST:[2]}"' + @echo 'LIST:[6]="${LIST:[6]}"' + @echo 'LIST:[7]="${LIST:[7]}"' + @echo 'LIST:[999]="${LIST:[999]}"' + @echo 'LIST:[-]="${LIST:[-]}" is an error' + @echo 'LIST:[--]="${LIST:[--]}" is an error' + @echo 'LIST:[-1]="${LIST:[-1]}"' + @echo 'LIST:[-2]="${LIST:[-2]}"' + @echo 'LIST:[-6]="${LIST:[-6]}"' + @echo 'LIST:[-7]="${LIST:[-7]}"' + @echo 'LIST:[-999]="${LIST:[-999]}"' + @echo 'LONGLIST:[17]="${LONGLIST:[17]}"' + @echo 'LONGLIST:[0x11]="${LONGLIST:[0x11]}"' + @echo 'LONGLIST:[021]="${LONGLIST:[021]}"' + @echo 'LIST:[0]:[1]="${LIST:[0]:[1]}"' + @echo 'LIST:[*]:[1]="${LIST:[*]:[1]}"' + @echo 'LIST:[@]:[1]="${LIST:[@]:[1]}"' + @echo 'LIST:[0]:[2]="${LIST:[0]:[2]}"' + @echo 'LIST:[*]:[2]="${LIST:[*]:[2]}"' + @echo 'LIST:[@]:[2]="${LIST:[@]:[2]}"' + @echo 'LIST:[*]:C/ /,/:[2]="${LIST:[*]:C/ /,/:[2]}"' + @echo 'LIST:[*]:C/ /,/:[*]:[2]="${LIST:[*]:C/ /,/:[*]:[2]}"' + @echo 'LIST:[*]:C/ /,/:[@]:[2]="${LIST:[*]:C/ /,/:[@]:[2]}"' + +mod-squarebrackets-start-end: + @echo 'LIST:[1.]="${LIST:[1.]}" is an error' + @echo 'LIST:[1..]="${LIST:[1..]}" is an error' + @echo 'LIST:[1..1]="${LIST:[1..1]}"' + @echo 'LIST:[1..1.]="${LIST:[1..1.]}" is an error' + @echo 'LIST:[1..2]="${LIST:[1..2]}"' + @echo 'LIST:[2..1]="${LIST:[2..1]}"' + @echo 'LIST:[3..-2]="${LIST:[3..-2]}"' + @echo 'LIST:[-4..4]="${LIST:[-4..4]}"' + @echo 'LIST:[0..1]="${LIST:[0..1]}" is an error' + @echo 'LIST:[-1..0]="${LIST:[-1..0]}" is an error' + @echo 'LIST:[-1..1]="${LIST:[-1..1]}"' + @echo 'LIST:[0..0]="${LIST:[0..0]}"' + @echo 'LIST:[3..99]="${LIST:[3..99]}"' + @echo 'LIST:[-3..-99]="${LIST:[-3..-99]}"' + @echo 'LIST:[-99..-3]="${LIST:[-99..-3]}"' + +mod-squarebrackets-nested: + @echo 'HASH="${HASH}" == "#" ?' + @echo 'LIST:[$${HASH}]="${LIST:[${HASH}]}"' + @echo 'LIST:[$${ZERO}]="${LIST:[${ZERO}]}"' + @echo 'LIST:[$${ZERO}x$${ONE}]="${LIST:[${ZERO}x${ONE}]}"' + @echo 'LIST:[$${ONE}]="${LIST:[${ONE}]}"' + @echo 'LIST:[$${MINUSONE}]="${LIST:[${MINUSONE}]}"' + @echo 'LIST:[$${STAR}]="${LIST:[${STAR}]}"' + @echo 'LIST:[$${AT}]="${LIST:[${AT}]}"' + @echo 'LIST:[$${EMPTY}]="${LIST:[${EMPTY}]}" is an error' + @echo 'LIST:[$${LONGLIST:[21]:S/2//}]="${LIST:[${LONGLIST:[21]:S/2//}]}"' + @echo 'LIST:[$${LIST:[#]}]="${LIST:[${LIST:[#]}]}"' + @echo 'LIST:[$${LIST:[$${HASH}]}]="${LIST:[${LIST:[${HASH}]}]}"' + +mod-C-W: + @echo 'LIST:C/ /,/="${LIST:C/ /,/}"' + @echo 'LIST:C/ /,/W="${LIST:C/ /,/W}"' + @echo 'LIST:C/ /,/gW="${LIST:C/ /,/gW}"' + @echo 'EMPTY:C/^/,/="${EMPTY:C/^/,/}"' + @echo 'EMPTY:C/^/,/W="${EMPTY:C/^/,/W}"' + +mod-S-W: + @echo 'LIST:S/ /,/="${LIST:S/ /,/}"' + @echo 'LIST:S/ /,/W="${LIST:S/ /,/W}"' + @echo 'LIST:S/ /,/gW="${LIST:S/ /,/gW}"' + @echo 'EMPTY:S/^/,/="${EMPTY:S/^/,/}"' + @echo 'EMPTY:S/^/,/W="${EMPTY:S/^/,/W}"' + +mod-tW-tw: + @echo 'LIST:tW="${LIST:tW}"' + @echo 'LIST:tw="${LIST:tw}"' + @echo 'LIST:tW:C/ /,/="${LIST:tW:C/ /,/}"' + @echo 'LIST:tW:C/ /,/g="${LIST:tW:C/ /,/g}"' + @echo 'LIST:tW:C/ /,/1g="${LIST:tW:C/ /,/1g}"' + @echo 'LIST:tw:C/ /,/="${LIST:tw:C/ /,/}"' + @echo 'LIST:tw:C/ /,/g="${LIST:tw:C/ /,/g}"' + @echo 'LIST:tw:C/ /,/1g="${LIST:tw:C/ /,/1g}"' + @echo 'LIST:tw:tW:C/ /,/="${LIST:tw:tW:C/ /,/}"' + @echo 'LIST:tW:tw:C/ /,/="${LIST:tW:tw:C/ /,/}"' diff --git a/unit-tests/order b/unit-tests/order deleted file mode 100644 index 175da471fe36..000000000000 --- a/unit-tests/order +++ /dev/null @@ -1,20 +0,0 @@ -# $NetBSD: order,v 1.1 2012/11/09 19:08:28 sjg Exp $ - -# Test that .ORDER is handled correctly. -# The explicit dependency the.o: the.h will make us examine the.h -# the .ORDER will prevent us building it immediately, -# we should then examine the.c rather than stop. - -all: the.o - -.ORDER: the.c the.h - -the.c the.h: - @echo Making $@ - -.SUFFIXES: .o .c - -.c.o: - @echo Making $@ from $? - -the.o: the.h diff --git a/unit-tests/order.exp b/unit-tests/order.exp new file mode 100644 index 000000000000..d876914ffc9d --- /dev/null +++ b/unit-tests/order.exp @@ -0,0 +1,4 @@ +Making the.c +Making the.h +Making the.o from the.h the.c +exit status 0 diff --git a/unit-tests/order.mk b/unit-tests/order.mk new file mode 100644 index 000000000000..f90b627d9e5f --- /dev/null +++ b/unit-tests/order.mk @@ -0,0 +1,20 @@ +# $NetBSD: order.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +# Test that .ORDER is handled correctly. +# The explicit dependency the.o: the.h will make us examine the.h +# the .ORDER will prevent us building it immediately, +# we should then examine the.c rather than stop. + +all: the.o + +.ORDER: the.c the.h + +the.c the.h: + @echo Making $@ + +.SUFFIXES: .o .c + +.c.o: + @echo Making $@ from $? + +the.o: the.h diff --git a/unit-tests/phony-end b/unit-tests/phony-end deleted file mode 100644 index d61884cafc44..000000000000 --- a/unit-tests/phony-end +++ /dev/null @@ -1,9 +0,0 @@ -# $Id: phony-end,v 1.1.1.1 2011/10/01 17:19:39 sjg Exp $ - -all ok also.ok bug phony: - @echo '${.TARGET .PREFIX .IMPSRC:L:@v@$v="${$v}"@}' - -.END: ok also.ok bug - -phony bug: .PHONY -all: phony diff --git a/unit-tests/phony-end.exp b/unit-tests/phony-end.exp new file mode 100644 index 000000000000..c3c517ccc25c --- /dev/null +++ b/unit-tests/phony-end.exp @@ -0,0 +1,6 @@ +.TARGET="phony" .PREFIX="phony" .IMPSRC="" +.TARGET="all" .PREFIX="all" .IMPSRC="phony" +.TARGET="ok" .PREFIX="ok" .IMPSRC="" +.TARGET="also.ok" .PREFIX="also.ok" .IMPSRC="" +.TARGET="bug" .PREFIX="bug" .IMPSRC="" +exit status 0 diff --git a/unit-tests/phony-end.mk b/unit-tests/phony-end.mk new file mode 100644 index 000000000000..07f4b029e31e --- /dev/null +++ b/unit-tests/phony-end.mk @@ -0,0 +1,9 @@ +# $Id: phony-end.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +all ok also.ok bug phony: + @echo '${.TARGET .PREFIX .IMPSRC:L:@v@$v="${$v}"@}' + +.END: ok also.ok bug + +phony bug: .PHONY +all: phony diff --git a/unit-tests/posix b/unit-tests/posix deleted file mode 100644 index 48ed7a3cacd7..000000000000 --- a/unit-tests/posix +++ /dev/null @@ -1,24 +0,0 @@ -# $Id: posix,v 1.1.1.1 2004/05/08 16:45:39 sjg Exp $ - -all: x plus subs err - -x: - @echo "Posix says we should execute the command as if run by system(3)" - @echo "Expect 'Hello,' and 'World!'" - @echo Hello,; false; echo "World!" - -plus: - @echo a command - +@echo "a command prefixed by '+' executes even with -n" - @echo another command - -subs: - @echo make -n - @${.MAKE} -f ${MAKEFILE} -n plus - @echo make -n -j1 - @${.MAKE} -f ${MAKEFILE} -n -j1 plus - -err: - @(echo Now we expect an error...; exit 1) - @echo "Oops! you shouldn't see this!" - diff --git a/unit-tests/posix.exp b/unit-tests/posix.exp new file mode 100644 index 000000000000..7e74cabadfb5 --- /dev/null +++ b/unit-tests/posix.exp @@ -0,0 +1,23 @@ +Posix says we should execute the command as if run by system(3) +Expect 'Hello,' and 'World!' +Hello, +World! +a command +a command prefixed by '+' executes even with -n +another command +make -n +echo a command +echo "a command prefixed by '+' executes even with -n" +a command prefixed by '+' executes even with -n +echo another command +make -n -j1 +{ echo a command +} || exit $? +echo "a command prefixed by '+' executes even with -n" +a command prefixed by '+' executes even with -n +{ echo another command +} || exit $? +Now we expect an error... +*** Error code 1 (continuing) +`all' not remade because of errors. +exit status 0 diff --git a/unit-tests/posix.mk b/unit-tests/posix.mk new file mode 100644 index 000000000000..608a24ab83f7 --- /dev/null +++ b/unit-tests/posix.mk @@ -0,0 +1,24 @@ +# $Id: posix.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +all: x plus subs err + +x: + @echo "Posix says we should execute the command as if run by system(3)" + @echo "Expect 'Hello,' and 'World!'" + @echo Hello,; false; echo "World!" + +plus: + @echo a command + +@echo "a command prefixed by '+' executes even with -n" + @echo another command + +subs: + @echo make -n + @${.MAKE} -f ${MAKEFILE} -n plus + @echo make -n -j1 + @${.MAKE} -f ${MAKEFILE} -n -j1 plus + +err: + @(echo Now we expect an error...; exit 1) + @echo "Oops! you shouldn't see this!" + diff --git a/unit-tests/posix1.exp b/unit-tests/posix1.exp new file mode 100644 index 000000000000..92809e61c690 --- /dev/null +++ b/unit-tests/posix1.exp @@ -0,0 +1,185 @@ +${VAR} = "foo bar baz" +a +b +c +foo baR baz, bar baz, foo bar baz, fooadd baradd bazadd +mkdir -p 'dir' +touch 'dir/obj_1.h' +mkdir -p 'dir' +printf '#include "obj_1.h"\nconst char* obj_1 = "dir/obj_1.c";\n' \ + >'dir/obj_1.c' +Local variables + ${@}="dir/obj_1.o" ${<}="dir/obj_1.c" + ${*}="dir/obj_1" ${?}="dir/obj_1.h dir/obj_1.c" + ${%}="" + +Directory and filename parts of local variables + ${@D}="dir" ${@F}="obj_1.o" + ${'obj_2.c' +mkdir -p '.' +touch 'obj_2.h' +Local variables + ${@}="obj2.o" ${<}="obj_2.c" + ${*}="obj2" ${?}="obj_2.c obj_2.h dir/obj_1.h" + ${%}="" + +Directory and filename parts of local variables + ${@D}="." ${@F}="obj2.o" + ${'obj3.c' +Local variables + ${@}="lib.a" ${<}="obj3.c" + ${*}="obj3" ${?}="obj3.h dir/dummy obj3.c" + ${%}="obj3.o" + +Directory and filename parts of local variables + ${@D}="." ${@F}="lib.a" + ${'${@}' + +dir/obj_1.h obj_2.h obj3.h dummy dir/dummy: + mkdir -p '${@D}' + touch '${@}' diff --git a/unit-tests/qequals b/unit-tests/qequals deleted file mode 100644 index e23078e5fd98..000000000000 --- a/unit-tests/qequals +++ /dev/null @@ -1,8 +0,0 @@ -# $Id: qequals,v 1.1.1.1 2008/03/31 00:13:05 sjg Exp $ - -M= i386 -V.i386= OK -V.$M ?= bug - -all: - @echo 'V.$M ?= ${V.$M}' diff --git a/unit-tests/qequals.exp b/unit-tests/qequals.exp new file mode 100644 index 000000000000..6b2f4dce6994 --- /dev/null +++ b/unit-tests/qequals.exp @@ -0,0 +1,2 @@ +V.i386 ?= OK +exit status 0 diff --git a/unit-tests/qequals.mk b/unit-tests/qequals.mk new file mode 100644 index 000000000000..67a48ad32ef3 --- /dev/null +++ b/unit-tests/qequals.mk @@ -0,0 +1,8 @@ +# $Id: qequals.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +M= i386 +V.i386= OK +V.$M ?= bug + +all: + @echo 'V.$M ?= ${V.$M}' diff --git a/unit-tests/suffixes.exp b/unit-tests/suffixes.exp new file mode 100644 index 000000000000..2a46e1cfa8e8 --- /dev/null +++ b/unit-tests/suffixes.exp @@ -0,0 +1,35 @@ +make: don't know how to make issue3 (continuing) +There should be no text after the colon: +touch .a +There should be no text after the colon: +touch .a.b +There should be no text after the colon: +touch .b.a +touch issue5a.c +first set +cp issue5a.c issue5a.d +touch issue5b.d +first set +cp issue5b.d issue5b.c +touch issue5c.d +first set +cp issue5c.d issue5c +touch issue5d.d +first set +cp issue5d.d issue5d.e +touch issue5e.e +first set +cp issue5e.e issue5e.d +make: don't know how to make issue6.f (continuing) +touch issue10.d +first set +cp issue10.d issue10.e +touch issue11.h +touch issue11.first +.ALLSRC: issue11.h issue11.first +cp issue11.h issue11.i +touch issue11.second +.ALLSRC: issue11.i issue11.second +cp issue11.i issue11.j +`all' not remade because of errors. +exit status 0 diff --git a/unit-tests/suffixes.mk b/unit-tests/suffixes.mk new file mode 100644 index 000000000000..113484a590af --- /dev/null +++ b/unit-tests/suffixes.mk @@ -0,0 +1,89 @@ +# $NetBSD: suffixes.mk,v 1.3 2014/08/30 22:21:08 sjg Exp $ + +# Issues from PR 49086 + +# Issue 3: single suffix rules remain active after .SUFFIXES is cleared +# +# There's a rule for issue3.a, but .a is no longer a known suffix when +# targets are being made, so issue3 should not get made. +all: issue3 + +# Issue 4: suffix rules do not become regular rules when .SUFFIXES is cleared +# +# When the rules were encountered, .a and .b were known suffices, but later +# on they were forgotten. These should get created as regular targets. +all: .a .a.b .b.a + +# Issue 5: adding more suffixes does not make existing rules into suffix rules +# +# When the targets .c.d, .d.c, .d, .d.e, and .e.d were encountered, only .a, +# .b and .c were known suffixes, so all of them were regular rules. Later +# rest of the suffixes were made known, so they should all be suffix +# transformation rules. +all: issue5a.d issue5b.c issue5c issue5d.e issue5e.d + +# Issue 6: transformation search can end up in an infinite loop +# +# There is no file or target from which issue6.f could be made from so +# this should fail. The bug was that because rules .e.f, .d.e and .e.d +# exist, make would try to make .f from .e and then infinitely try +# to do .e from .d and vice versa. +all: issue6.f + +# Issue 10: explicit dependencies affect transformation rule selection +# +# If issue10.e is wanted and both issue10.d and issue10.f are available, +# make should choose the .d.e rule, because .d is before .f in .SUFFIXES. +# The bug was that if issue10.d had an explicit dependency on issue10.f, +# it would choose .f.e instead. +all: issue10.e + +# Issue 11: sources from transformation rules are expanded incorrectly +# +# issue11.j should depend on issue11.i and issue11.second and issue11.i +# should depend on issue11.h and issue11.first. The bug was that +# the dynamic sources were expanded before ${.PREFIX} and ${.TARGET} were +# available, so they would have expanded to a null string. +all: issue11.j + +# we need to clean for repeatable results +.BEGIN: clean +clean: + @rm -f issue* .[ab]* + +.SUFFIXES: .a .b .c + +.a .a.b .b.a: + @echo 'There should be no text after the colon: ${.IMPSRC}' + touch ${.TARGET} + +.c.d .d.c .d .d.e .e.d: + @echo 'first set' + cp ${.IMPSRC} ${.TARGET} + +.SUFFIXES: +.SUFFIXES: .c .d .e .f .g + +.e .e.f .f.e: + @echo 'second set' + cp ${.IMPSRC} ${.TARGET} + +issue3.a: + @echo 'There is a bug if you see this.' + touch ${.TARGET} + +issue5a.c issue5b.d issue5c.d issue5d.d issue5e.e issue10.d issue10.f: + touch ${.TARGET} + +.SUFFIXES: .h .i .j + +.h.i: ${.PREFIX}.first + @echo '.ALLSRC: ${.ALLSRC}' + cp ${.IMPSRC} ${.TARGET} + +.i.j: ${.PREFIX}.second + @echo '.ALLSRC: ${.ALLSRC}' + cp ${.IMPSRC} ${.TARGET} + +issue11.h issue11.first issue11.second: + touch ${.TARGET} diff --git a/unit-tests/sunshcmd b/unit-tests/sunshcmd deleted file mode 100644 index e3baf901e51d..000000000000 --- a/unit-tests/sunshcmd +++ /dev/null @@ -1,10 +0,0 @@ -BYECMD = echo bye -LATERCMD = echo later -TEST1 :sh = echo hello -TEST2 :sh = ${BYECMD} -TEST3 = ${LATERCMD:sh} - -all: - @echo "TEST1=${TEST1}" - @echo "TEST2=${TEST2}" - @echo "TEST3=${TEST3}" diff --git a/unit-tests/sunshcmd.exp b/unit-tests/sunshcmd.exp new file mode 100644 index 000000000000..b14f6b68a41f --- /dev/null +++ b/unit-tests/sunshcmd.exp @@ -0,0 +1,4 @@ +TEST1=hello +TEST2=bye +TEST3=later +exit status 0 diff --git a/unit-tests/sunshcmd.mk b/unit-tests/sunshcmd.mk new file mode 100644 index 000000000000..e3baf901e51d --- /dev/null +++ b/unit-tests/sunshcmd.mk @@ -0,0 +1,10 @@ +BYECMD = echo bye +LATERCMD = echo later +TEST1 :sh = echo hello +TEST2 :sh = ${BYECMD} +TEST3 = ${LATERCMD:sh} + +all: + @echo "TEST1=${TEST1}" + @echo "TEST2=${TEST2}" + @echo "TEST3=${TEST3}" diff --git a/unit-tests/sysv b/unit-tests/sysv deleted file mode 100644 index 9eedacba3b67..000000000000 --- a/unit-tests/sysv +++ /dev/null @@ -1,26 +0,0 @@ -# $Id: sysv,v 1.1.1.2 2011/06/05 04:23:49 sjg Exp $ - -FOO ?= -FOOBAR = $(FOO:=bar) - -_this := ${.PARSEDIR}/${.PARSEFILE} - -B = /b -S = / -FUN = ${B}${S}fun -SUN = the Sun - -# we expect nothing when FOO is empty -all: foo fun - -foo: - @echo FOOBAR = $(FOOBAR) -.if empty(FOO) - @FOO="foo fu" ${.MAKE} -f ${_this} foo -.endif - -fun: - @echo ${FUN:T} - @echo ${FUN:${B}${S}fun=fun} - @echo ${FUN:${B}${S}%=%} - @echo ${In:L:%=% ${SUN}} diff --git a/unit-tests/sysv.exp b/unit-tests/sysv.exp new file mode 100644 index 000000000000..4cce2de31918 --- /dev/null +++ b/unit-tests/sysv.exp @@ -0,0 +1,7 @@ +FOOBAR = +FOOBAR = foobar fubar +fun +fun +fun +In the Sun +exit status 0 diff --git a/unit-tests/sysv.mk b/unit-tests/sysv.mk new file mode 100644 index 000000000000..d5e99ff950ae --- /dev/null +++ b/unit-tests/sysv.mk @@ -0,0 +1,26 @@ +# $Id: sysv.mk,v 1.2 2014/08/30 22:25:14 sjg Exp $ + +FOO ?= +FOOBAR = ${FOO:=bar} + +_this := ${.PARSEDIR}/${.PARSEFILE} + +B = /b +S = / +FUN = ${B}${S}fun +SUN = the Sun + +# we expect nothing when FOO is empty +all: foo fun + +foo: + @echo FOOBAR = ${FOOBAR} +.if empty(FOO) + @FOO="foo fu" ${.MAKE} -f ${_this} foo +.endif + +fun: + @echo ${FUN:T} + @echo ${FUN:${B}${S}fun=fun} + @echo ${FUN:${B}${S}%=%} + @echo ${In:L:%=% ${SUN}} diff --git a/unit-tests/ternary b/unit-tests/ternary deleted file mode 100644 index 77f834981c6c..000000000000 --- a/unit-tests/ternary +++ /dev/null @@ -1,8 +0,0 @@ - -all: - @for x in "" A= A=42; do ${.MAKE} -f ${MAKEFILE} show $$x; done - -show: - @echo "The answer is ${A:?known:unknown}" - @echo "The answer is ${A:?$A:unknown}" - @echo "The answer is ${empty(A):?empty:$A}" diff --git a/unit-tests/ternary.exp b/unit-tests/ternary.exp new file mode 100644 index 000000000000..ed9c1bd9200e --- /dev/null +++ b/unit-tests/ternary.exp @@ -0,0 +1,10 @@ +The answer is unknown +The answer is unknown +The answer is empty +The answer is known +The answer is +The answer is empty +The answer is known +The answer is 42 +The answer is 42 +exit status 0 diff --git a/unit-tests/ternary.mk b/unit-tests/ternary.mk new file mode 100644 index 000000000000..77f834981c6c --- /dev/null +++ b/unit-tests/ternary.mk @@ -0,0 +1,8 @@ + +all: + @for x in "" A= A=42; do ${.MAKE} -f ${MAKEFILE} show $$x; done + +show: + @echo "The answer is ${A:?known:unknown}" + @echo "The answer is ${A:?$A:unknown}" + @echo "The answer is ${empty(A):?empty:$A}" diff --git a/unit-tests/test.exp b/unit-tests/test.exp deleted file mode 100644 index aaecb960fc99..000000000000 --- a/unit-tests/test.exp +++ /dev/null @@ -1,383 +0,0 @@ -comment testing start -this is foo -This is how a comment looks: # comment -comment testing done -make: "cond1" line 75: warning: extra else -make: "cond1" line 85: warning: extra else -2 is prime -A='other' B='unknown' C='clever' o='no,no' -Passed: - var - ("var") - (var != var) - var != var - !((var != var) && defined(name)) - var == quoted - -1 is not prime -2 is prime -3 is prime -4 is not prime -5 is prime - -make: warning: String comparison operator should be either == or != -make: Bad conditional expression `"0" > 0' in "0" > 0?OK:No - -OK -make: "error" line 3: just FYI -make: "error" line 4: warning: this could be serious -make: "error" line 5: this is fatal -UT_DOLLAR=This is $UT_FU -UT_FOO=foobar is fubar -UT_FU=fubar -UT_TEST=export -UT_ZOO=hoopie -UT_ALL=even this gets exported -UT_BADDIR=unit-tests -UT_DOLLAR=This is $UT_FU -UT_F=fine -UT_FOO=foobar is fubar -UT_FU=fubar -UT_NO=all -UT_OK=good -UT_OKDIR=unit-tests -UT_TEST=export-all -UT_ZOO=hoopie -make: -UT_TEST=export-env -UT_ENV=not-exported -UT_EXP=not-exported -env: -UT_TEST=export-env -UT_ENV=exported -UT_EXP=exported -At first, I am -happy -and now: sad -.ERROR: Looks like 'sad' is upset. -*** Error code 1 - -Stop. -make: stopped in unit-tests -simple.1 -simple.1 -simple.2 -simple.2 -recursive.1.1.* -recursive.1.1.* -recursive.1.1.* -recursive.1.1.* -recursive.1.99 -recursive.1.99 -recursive.2.1.* -recursive.2.1.* -recursive.2.1.* -recursive.2.1.* -recursive.2.99 -recursive.2.99 -shared.0 -shared.0 -shared.1.99 -shared.1.99 -shared.2.1 -shared.2.1 -shared.2.99 -shared.2.99 -make: Graph cycles through `cycle.2.99' -make: Graph cycles through `cycle.2.98' -make: Graph cycles through `cycle.2.97' -cycle.1.99 -cycle.1.99 -x=one -x="two and three" -x=four -x="five" -x=-I/this -x=-I"This or that" -x=-Ithat -x="-DTHIS=\"this and that\"" -cfl=-I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" -a=one b="two and three" -a=four b="five" -a=ONE b="TWO AND THREE" -a=FOUR b="FIVE" -We expect an error next: -make: "forloop" line 38: Wrong number of words (9) in .for substitution list with 2 vars -make: Fatal errors encountered -- cannot continue -make: stopped in unit-tests -OK -.for with :S;... OK -b2af338b -3360ac65 -7747f046 -9ca87054 -880fe816 -208fcbd3 -d5d376eb -de41416c -Expect: Unknown modifier 'Z' -make: Unknown modifier 'Z' -VAR:Z= -Expect: Unknown modifier 'Z' -make: Unknown modifier 'Z' -VAR:Z= -Expect: Unclosed variable specification for VAR -make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S -VAR:S,V,v,=Thevariable -Expect: Unclosed variable specification for VAR -make: Unclosed variable specification after complex modifier (expecting '}') for VAR -VAR:S,V,v,=Thevariable -Expect: Unclosed substitution for VAR (, missing) -make: Unclosed substitution for VAR (, missing) -VAR:S,V,v= -LIB=a X_LIBS:M${LIB${LIB:tu}} is "/tmp/liba.a" -LIB=a X_LIBS:M*/lib${LIB}.a is "/tmp/liba.a" -LIB=a X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBA.A" -LIB=b X_LIBS:M${LIB${LIB:tu}} is "" -LIB=b X_LIBS:M*/lib${LIB}.a is "" -LIB=b X_LIBS:M*/lib${LIB}.a:tu is "" -LIB=c X_LIBS:M${LIB${LIB:tu}} is "" -LIB=c X_LIBS:M*/lib${LIB}.a is "" -LIB=c X_LIBS:M*/lib${LIB}.a:tu is "" -LIB=d X_LIBS:M${LIB${LIB:tu}} is "/tmp/libd.a" -LIB=d X_LIBS:M*/lib${LIB}.a is "/tmp/libd.a" -LIB=d X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBD.A" -LIB=e X_LIBS:M${LIB${LIB:tu}} is "/tmp/libe.a" -LIB=e X_LIBS:M*/lib${LIB}.a is "/tmp/libe.a" -LIB=e X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBE.A" -Mscanner=OK -path=':/bin:/tmp::/:.:/no/such/dir:.' -path='/bin:/tmp:/:/no/such/dir' -path='/bin:/tmp:/:/no/such/dir' -path='/bin':'/tmp':'/':'/no/such/dir' -path='/bin':'/tmp':'/':'/no/such/dir' -path_/usr/xbin=/opt/xbin/ -paths=/bin /tmp / /no/such/dir /opt/xbin -PATHS=/BIN /TMP / /NO/SUCH/DIR /OPT/XBIN -The answer is 42 -LIST = one two three four five six seven eight nine ten -LIST:O = eight five four nine one seven six ten three two -LIST:Ox = Ok -LIST:O:Ox = Ok -LISTX = Ok -LISTSX = Ok -make: Bad modifier `:OX' for LIST -BADMOD 1 = } -make: Bad modifier `:OxXX' for LIST -BADMOD 2 = XX} -LIST="one two three four five six" -LIST:ts,="one,two,three,four,five,six" -LIST:ts/:tu="ONE/TWO/THREE/FOUR/FIVE/SIX" -LIST:ts::tu="ONE:TWO:THREE:FOUR:FIVE:SIX" -LIST:ts:tu="ONETWOTHREEFOURFIVESIX" -LIST:tu:ts/="ONE/TWO/THREE/FOUR/FIVE/SIX" -LIST:ts:="one:two:three:four:five:six" -LIST:ts="onetwothreefourfivesix" -LIST:ts:S/two/2/="one2threefourfivesix" -LIST:S/two/2/:ts="one2threefourfivesix" -LIST:ts/:S/two/2/="one/2/three/four/five/six" -Pretend the '/' in '/n' etc. below are back-slashes. -LIST:ts/n="one -two -three -four -five -six" -LIST:ts/t="one two three four five six" -LIST:ts/012:tu="ONE -TWO -THREE -FOUR -FIVE -SIX" -make: Bad modifier `:tx' for LIST -LIST:tx="}" -make: Bad modifier `:ts\x' for LIST -LIST:ts/x:tu="\x:tu}" -FU_mod-ts="a/b/cool" -FU_mod-ts:ts:T="cool" == cool? -B.${AAA:ts}="Baaa" == Baaa? -make: Bad modifier `:[]' for LIST -LIST:[]="" is an error -LIST:[0]="one two three four five six" -LIST:[0x0]="one two three four five six" -LIST:[000]="one two three four five six" -LIST:[*]="one two three four five six" -LIST:[@]="one two three four five six" -LIST:[0]:C/ /,/="one,two three four five six" -LIST:[0]:C/ /,/g="one,two,three,four,five,six" -LIST:[0]:C/ /,/1g="one,two,three,four,five,six" -LIST:[*]:C/ /,/="one,two three four five six" -LIST:[*]:C/ /,/g="one,two,three,four,five,six" -LIST:[*]:C/ /,/1g="one,two,three,four,five,six" -LIST:[@]:C/ /,/="one two three four five six" -LIST:[@]:C/ /,/g="one two three four five six" -LIST:[@]:C/ /,/1g="one two three four five six" -LIST:[@]:[0]:C/ /,/="one,two three four five six" -LIST:[0]:[@]:C/ /,/="one two three four five six" -LIST:[@]:[*]:C/ /,/="one,two three four five six" -LIST:[*]:[@]:C/ /,/="one two three four five six" -EMPTY="" -EMPTY:[#]="1" == 1 ? -ESCAPEDSPACE="\ " -ESCAPEDSPACE:[#]="1" == 1 ? -REALLYSPACE=" " -REALLYSPACE:[#]="1" == 1 ? -LIST:[#]="6" -LIST:[0]:[#]="1" == 1 ? -LIST:[*]:[#]="1" == 1 ? -LIST:[@]:[#]="6" -LIST:[1]:[#]="1" -LIST:[1..3]:[#]="3" -EMPTY:[1]="" -ESCAPEDSPACE="\ " -ESCAPEDSPACE:[1]="\ " -REALLYSPACE=" " -REALLYSPACE:[1]="" == "" ? -REALLYSPACE:[*]:[1]=" " == " " ? -LIST:[1]="one" -make: Bad modifier `:[1.]' for LIST -LIST:[1.]="" is an error -make: Bad modifier `:[1].' for LIST -LIST:[1].="}" is an error -LIST:[2]="two" -LIST:[6]="six" -LIST:[7]="" -LIST:[999]="" -make: Bad modifier `:[-]' for LIST -LIST:[-]="" is an error -make: Bad modifier `:[--]' for LIST -LIST:[--]="" is an error -LIST:[-1]="six" -LIST:[-2]="five" -LIST:[-6]="one" -LIST:[-7]="" -LIST:[-999]="" -LONGLIST:[17]="17" -LONGLIST:[0x11]="17" -LONGLIST:[021]="17" -LIST:[0]:[1]="one two three four five six" -LIST:[*]:[1]="one two three four five six" -LIST:[@]:[1]="one" -LIST:[0]:[2]="" -LIST:[*]:[2]="" -LIST:[@]:[2]="two" -LIST:[*]:C/ /,/:[2]="" -LIST:[*]:C/ /,/:[*]:[2]="" -LIST:[*]:C/ /,/:[@]:[2]="three" -make: Bad modifier `:[1.]' for LIST -LIST:[1.]="" is an error -make: Bad modifier `:[1..]' for LIST -LIST:[1..]="" is an error -LIST:[1..1]="one" -make: Bad modifier `:[1..1.]' for LIST -LIST:[1..1.]="" is an error -LIST:[1..2]="one two" -LIST:[2..1]="two one" -LIST:[3..-2]="three four five" -LIST:[-4..4]="three four" -make: Bad modifier `:[0..1]' for LIST -LIST:[0..1]="" is an error -make: Bad modifier `:[-1..0]' for LIST -LIST:[-1..0]="" is an error -LIST:[-1..1]="six five four three two one" -LIST:[0..0]="one two three four five six" -LIST:[3..99]="three four five six" -LIST:[-3..-99]="four three two one" -LIST:[-99..-3]="one two three four" -HASH="#" == "#" ? -LIST:[${HASH}]="6" -LIST:[${ZERO}]="one two three four five six" -LIST:[${ZERO}x${ONE}]="one" -LIST:[${ONE}]="one" -LIST:[${MINUSONE}]="six" -LIST:[${STAR}]="one two three four five six" -LIST:[${AT}]="one two three four five six" -make: Bad modifier `:[${EMPTY' for LIST -LIST:[${EMPTY}]="" is an error -LIST:[${LONGLIST:[21]:S/2//}]="one" -LIST:[${LIST:[#]}]="six" -LIST:[${LIST:[${HASH}]}]="six" -LIST:S/ /,/="one two three four five six" -LIST:S/ /,/W="one,two three four five six" -LIST:S/ /,/gW="one,two,three,four,five,six" -EMPTY:S/^/,/="," -EMPTY:S/^/,/W="," -LIST:C/ /,/="one two three four five six" -LIST:C/ /,/W="one,two three four five six" -LIST:C/ /,/gW="one,two,three,four,five,six" -EMPTY:C/^/,/="," -EMPTY:C/^/,/W="," -LIST:tW="one two three four five six" -LIST:tw="one two three four five six" -LIST:tW:C/ /,/="one,two three four five six" -LIST:tW:C/ /,/g="one,two,three,four,five,six" -LIST:tW:C/ /,/1g="one,two,three,four,five,six" -LIST:tw:C/ /,/="one two three four five six" -LIST:tw:C/ /,/g="one two three four five six" -LIST:tw:C/ /,/1g="one two three four five six" -LIST:tw:tW:C/ /,/="one,two three four five six" -LIST:tW:tw:C/ /,/="one two three four five six" -Making the.c -Making the.h -Making the.o from the.h the.c -.TARGET="phony" .PREFIX="phony" .IMPSRC="" -.TARGET="all" .PREFIX="all" .IMPSRC="" -.TARGET="ok" .PREFIX="ok" .IMPSRC="" -.TARGET="also.ok" .PREFIX="also.ok" .IMPSRC="" -.TARGET="bug" .PREFIX="bug" .IMPSRC="" -Posix says we should execute the command as if run by system(3) -Expect 'Hello,' and 'World!' -Hello, -World! -a command -a command prefixed by '+' executes even with -n -another command -make -n -echo a command -echo "a command prefixed by '+' executes even with -n" -a command prefixed by '+' executes even with -n -echo another command -make -n -j1 -{ echo a command -} || exit $? -echo "a command prefixed by '+' executes even with -n" -a command prefixed by '+' executes even with -n -{ echo another command -} || exit $? -Now we expect an error... -*** Error code 1 (continuing) -`all' not remade because of errors. -V.i386 ?= OK -TEST1=hello -TEST2=bye -TEST3=later -FOOBAR = -FOOBAR = foobar fubar -fun -fun -fun -In the Sun -The answer is unknown -The answer is unknown -The answer is empty -The answer is known -The answer is -The answer is empty -The answer is known -The answer is 42 -The answer is 42 -UT_DOLLAR=This is $UT_FU -UT_FU=fubar -UT_TEST=unexport -UT_TEST=unexport-env -default FU=fu FOO=foo VAR= -two FU=bar FOO=goo VAR= -three FU=bar FOO=goo VAR= -four FU=bar FOO=goo VAR=Internal -five FU=bar FOO=goo VAR=Internal -five v=is x k=is x -six v=is y k=is y -show-v v=override k=override -*** Error code 1 (ignored) -*** Error code 1 (ignored) diff --git a/unit-tests/unexport b/unit-tests/unexport deleted file mode 100644 index fb40d0ccf742..000000000000 --- a/unit-tests/unexport +++ /dev/null @@ -1,8 +0,0 @@ -# $Id: unexport,v 1.1.1.1 2009/11/19 00:31:11 sjg Exp $ - -# pick up a bunch of exported vars -.include "export" - -.unexport UT_ZOO UT_FOO - -UT_TEST = unexport diff --git a/unit-tests/unexport-env b/unit-tests/unexport-env deleted file mode 100644 index f6a2ff998268..000000000000 --- a/unit-tests/unexport-env +++ /dev/null @@ -1,14 +0,0 @@ -# $Id: unexport-env,v 1.1.1.1 2009/11/19 00:31:11 sjg Exp $ - -# pick up a bunch of exported vars -.include "export" - -# an example of setting up a minimal environment. -PATH = /bin:/usr/bin:/sbin:/usr/sbin - -# now clobber the environment to just PATH and UT_TEST -UT_TEST = unexport-env - -# this removes everything -.unexport-env -.export PATH UT_TEST diff --git a/unit-tests/unexport-env.exp b/unit-tests/unexport-env.exp new file mode 100644 index 000000000000..6d43cab48a58 --- /dev/null +++ b/unit-tests/unexport-env.exp @@ -0,0 +1,2 @@ +UT_TEST=unexport-env +exit status 0 diff --git a/unit-tests/unexport-env.mk b/unit-tests/unexport-env.mk new file mode 100644 index 000000000000..aaabcd46464a --- /dev/null +++ b/unit-tests/unexport-env.mk @@ -0,0 +1,14 @@ +# $Id: unexport-env.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +# pick up a bunch of exported vars +.include "export.mk" + +# an example of setting up a minimal environment. +PATH = /bin:/usr/bin:/sbin:/usr/sbin + +# now clobber the environment to just PATH and UT_TEST +UT_TEST = unexport-env + +# this removes everything +.unexport-env +.export PATH UT_TEST diff --git a/unit-tests/unexport.exp b/unit-tests/unexport.exp new file mode 100644 index 000000000000..7b16ea3659a8 --- /dev/null +++ b/unit-tests/unexport.exp @@ -0,0 +1,4 @@ +UT_DOLLAR=This is $UT_FU +UT_FU=fubar +UT_TEST=unexport +exit status 0 diff --git a/unit-tests/unexport.mk b/unit-tests/unexport.mk new file mode 100644 index 000000000000..0f1245292ba5 --- /dev/null +++ b/unit-tests/unexport.mk @@ -0,0 +1,8 @@ +# $Id: unexport.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +# pick up a bunch of exported vars +.include "export.mk" + +.unexport UT_ZOO UT_FOO + +UT_TEST = unexport diff --git a/unit-tests/varcmd b/unit-tests/varcmd deleted file mode 100644 index a58e01430264..000000000000 --- a/unit-tests/varcmd +++ /dev/null @@ -1,49 +0,0 @@ -# $Id: varcmd,v 1.3 2008/05/15 04:30:47 sjg Exp $ -# -# Test behaviour of recursive make and vars set on command line. - -FU=fu -FOO?=foo -.if !empty(.TARGETS) -TAG=${.TARGETS} -.endif -TAG?=default - -all: one - -show: - @echo "${TAG} FU=${FU} FOO=${FOO} VAR=${VAR}" - -one: show - @${.MAKE} -f ${MAKEFILE} FU=bar FOO=goo two - -two: show - @${.MAKE} -f ${MAKEFILE} three - -three: show - @${.MAKE} -f ${MAKEFILE} four - - -.ifmake four -VAR=Internal -.MAKEOVERRIDES+= VAR -.endif - -four: show - @${.MAKE} -f ${MAKEFILE} five - -M = x -V.y = is y -V.x = is x -V := ${V.$M} -K := ${V} - -show-v: - @echo '${TAG} v=${V} k=${K}' - -five: show show-v - @${.MAKE} -f ${MAKEFILE} M=y six - -six: show-v - @${.MAKE} -f ${MAKEFILE} V=override show-v - diff --git a/unit-tests/varcmd.exp b/unit-tests/varcmd.exp new file mode 100644 index 000000000000..34dd637f93ee --- /dev/null +++ b/unit-tests/varcmd.exp @@ -0,0 +1,9 @@ +default FU=fu FOO=foo VAR= +two FU=bar FOO=goo VAR= +three FU=bar FOO=goo VAR= +four FU=bar FOO=goo VAR=Internal +five FU=bar FOO=goo VAR=Internal +five v=is x k=is x +six v=is y k=is y +show-v v=override k=override +exit status 0 diff --git a/unit-tests/varcmd.mk b/unit-tests/varcmd.mk new file mode 100644 index 000000000000..a5fd198e6b8f --- /dev/null +++ b/unit-tests/varcmd.mk @@ -0,0 +1,49 @@ +# $Id: varcmd.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ +# +# Test behaviour of recursive make and vars set on command line. + +FU=fu +FOO?=foo +.if !empty(.TARGETS) +TAG=${.TARGETS} +.endif +TAG?=default + +all: one + +show: + @echo "${TAG} FU=${FU} FOO=${FOO} VAR=${VAR}" + +one: show + @${.MAKE} -f ${MAKEFILE} FU=bar FOO=goo two + +two: show + @${.MAKE} -f ${MAKEFILE} three + +three: show + @${.MAKE} -f ${MAKEFILE} four + + +.ifmake four +VAR=Internal +.MAKEOVERRIDES+= VAR +.endif + +four: show + @${.MAKE} -f ${MAKEFILE} five + +M = x +V.y = is y +V.x = is x +V := ${V.$M} +K := ${V} + +show-v: + @echo '${TAG} v=${V} k=${K}' + +five: show show-v + @${.MAKE} -f ${MAKEFILE} M=y six + +six: show-v + @${.MAKE} -f ${MAKEFILE} V=override show-v + diff --git a/unit-tests/varmisc.exp b/unit-tests/varmisc.exp new file mode 100644 index 000000000000..1636aafc11e5 --- /dev/null +++ b/unit-tests/varmisc.exp @@ -0,0 +1,2 @@ + +exit status 0 diff --git a/unit-tests/varmisc.mk b/unit-tests/varmisc.mk new file mode 100644 index 000000000000..4b4a931a37ac --- /dev/null +++ b/unit-tests/varmisc.mk @@ -0,0 +1,8 @@ +# $Id: varmisc.mk,v 1.2 2014/08/30 22:25:14 sjg Exp $ +# +# Miscellaneous variable tests. + +all: unmatched_var_paren + +unmatched_var_paren: + @echo ${foo::=foo-text} diff --git a/unit-tests/varshell.exp b/unit-tests/varshell.exp new file mode 100644 index 000000000000..dae2c6b9dff5 --- /dev/null +++ b/unit-tests/varshell.exp @@ -0,0 +1,10 @@ +make: "varshell.mk" line 5: warning: "/bin/no/such/command 2> /dev/null" returned non-zero status +make: "varshell.mk" line 8: warning: "false" returned non-zero status +make: "varshell.mk" line 9: warning: "echo "output before the error"; false" returned non-zero status +EXEC_FAILED='' +TERMINATED_BY_SIGNAL='' +ERROR_NO_OUTPUT='' +ERROR_WITH_OUTPUT='output before the error' +NO_ERROR_NO_OUTPUT='' +NO_ERROR_WITH_OUTPUT='this is good' +exit status 0 diff --git a/unit-tests/varshell.mk b/unit-tests/varshell.mk new file mode 100644 index 000000000000..9c8baacc6474 --- /dev/null +++ b/unit-tests/varshell.mk @@ -0,0 +1,19 @@ +# $Id: varshell.mk,v 1.4 2015/04/20 03:16:39 sjg Exp $ +# +# Test VAR != shell command + +EXEC_FAILED != /bin/no/such/command 2> /dev/null +# SunOS cannot handle this one +#TERMINATED_BY_SIGNAL != kill -14 $$$$ +ERROR_NO_OUTPUT != false +ERROR_WITH_OUTPUT != echo "output before the error"; false +NO_ERROR_NO_OUTPUT != true +NO_ERROR_WITH_OUTPUT != echo "this is good" + +allvars= EXEC_FAILED TERMINATED_BY_SIGNAL ERROR_NO_OUTPUT ERROR_WITH_OUTPUT \ + NO_ERROR_NO_OUTPUT NO_ERROR_WITH_OUTPUT + +all: +.for v in ${allvars} + @echo ${v}=\'${${v}}\' +.endfor diff --git a/var.c b/var.c index 26e3f4bd10d3..bb48fae80859 100644 --- a/var.c +++ b/var.c @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.186 2014/06/20 06:13:45 sjg Exp $ */ +/* $NetBSD: var.c,v 1.191 2014/09/14 02:32:51 dholland Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,14 +69,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: var.c,v 1.186 2014/06/20 06:13:45 sjg Exp $"; +static char rcsid[] = "$NetBSD: var.c,v 1.191 2014/09/14 02:32:51 dholland Exp $"; #else #include #ifndef lint #if 0 static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: var.c,v 1.186 2014/06/20 06:13:45 sjg Exp $"); +__RCSID("$NetBSD: var.c,v 1.191 2014/09/14 02:32:51 dholland Exp $"); #endif #endif /* not lint */ #endif @@ -3599,14 +3599,13 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, * expanding it in a non-local context. This * is done to support dynamic sources. The * result is just the invocation, unaltered */ - Var_Parse_State parsestate; /* Flags passed to helper functions */ + const char *extramodifiers; /* extra modifiers to apply first */ char name[2]; *freePtr = NULL; + extramodifiers = NULL; dynamic = FALSE; start = str; - parsestate.oneBigWord = FALSE; - parsestate.varSpace = ' '; /* word separator */ startc = str[1]; if (startc != PROPEN && startc != BROPEN) { @@ -3734,7 +3733,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, */ if ((v == NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) && (vlen == 2) && (str[1] == 'F' || str[1] == 'D') && - strchr("@%*!<>", str[0]) != NULL) { + strchr("@%?*!<>", str[0]) != NULL) { /* * Well, it's local -- go look for it. */ @@ -3743,29 +3742,12 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, v = VarFind(name, ctxt, 0); if (v != NULL) { - /* - * No need for nested expansion or anything, as we're - * the only one who sets these things and we sure don't - * but nested invocations in them... - */ - nstr = Buf_GetAll(&v->val, NULL); - if (str[1] == 'D') { - nstr = VarModify(ctxt, &parsestate, nstr, VarHead, - NULL); - } else { - nstr = VarModify(ctxt, &parsestate, nstr, VarTail, - NULL); + extramodifiers = "H:"; + } + else { /* F */ + extramodifiers = "T:"; } - /* - * Resulting string is dynamically allocated, so - * tell caller to free it. - */ - *freePtr = nstr; - *lengthPtr = tstr-start+1; - Buf_Destroy(&buf, TRUE); - VarFreeEnv(v, TRUE); - return nstr; } } @@ -3860,16 +3842,29 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr, v->flags &= ~VAR_IN_USE; - if ((nstr != NULL) && haveModifier) { + if ((nstr != NULL) && (haveModifier || extramodifiers != NULL)) { + void *extraFree; int used; - /* - * Skip initial colon. - */ - tstr++; - nstr = ApplyModifiers(nstr, tstr, startc, endc, - v, ctxt, errnum, &used, freePtr); - tstr += used; + extraFree = NULL; + if (extramodifiers != NULL) { + nstr = ApplyModifiers(nstr, extramodifiers, '(', ')', + v, ctxt, errnum, &used, &extraFree); + } + + if (haveModifier) { + /* Skip initial colon. */ + tstr++; + + nstr = ApplyModifiers(nstr, tstr, startc, endc, + v, ctxt, errnum, &used, freePtr); + tstr += used; + if (extraFree) { + free(extraFree); + } + } else { + *freePtr = extraFree; + } } if (*tstr) { *lengthPtr = tstr - start + 1; -- cgit v1.2.3