Import bmake-

This commit is contained in:
nia 2020-05-24 05:35:51 +00:00
parent 41f4d684ea
commit 8c218dc01b
156 changed files with 20356 additions and 2423 deletions

View File

@ -1,3 +1,633 @@
2020-05-17 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200517
Merge with NetBSD make, pick up
o modified dollar tests to avoid shell dependencies
o new tests for .INCLUDEFROM
2020-05-16 Simon J Gerraty <sjg@beast.crufty.net>
* unit-tests/dollar.mk: tweak '1 dollar literal' test
to not depend so much on shell behavior
2020-05-10 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200510
Merge with NetBSD make, pick up
o unit test for dollar handling
2020-05-06 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200506
Merge with NetBSD make, pick up
o str.c: empty string does not match % pattern
plus unit-test changes
2020-05-04 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200504
May the 4th be with you
Merge with NetBSD make, pick up
o var.c: import handling of old sysV style modifier using '%'
o str.c: refactor brk_string
o unit-tests: add test case for lazy conditions
2020-04-18 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200418
* configure.in: use_makefile=no for cygwin et al.
case insensitive filesystems just don't work if both
makefile and Makefile exist.
NOTE: bmake does not support cygwin and likely never will,
but if brave souls want to try it - help them out.
2020-04-02 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200402
Merge with NetBSD make, pick up
o meta.c: meta_oodate, CHECK_VALID_META is too aggressive for CMD
a blank command is perfectly valid.
2020-03-30 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200330
Merge with NetBSD make, pick up
o make.h: extern debug_file
2020-03-18 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200318
Merge with NetBSD make, pick up
o meta.c: meta_oodate, check for corrupted meta file
earlier and more often.
2020-02-20 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200220
2020-02-19 Simon J Gerraty <sjg@beast.crufty.net>
* boot-strap: unset MAKEFLAGS
2020-02-12 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200212
* meta.c: meta_compat_parent check for USE_FILEMON
patch from Soeren Tempel
2020-02-05 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20200205
Merge with NetBSD make, pick up
o meta.c: fix compat mode, need to call meta_job_output()
o job.c: extra fds for meta mode not needed if using filemon_dev
2020-01-22 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20200122
Merge with NetBSD make, pick up
o meta.c: avoid passing NULL to filemon_*() when meta_needed()
returns FALSE.
2020-01-21 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20200121
Merge with NetBSD make, pick up
o filemon/filemon_{dev,ktrace}.c: allow selection of
filemon implementation. filemon_dev.c uses the kernel module
while filemon_ktrace.c leverages the fktrace api available in
NetBSD. filemon_ktrace.c can hopefully form the basis for
adding support for other tracing mechanisms such as strace on
Linux.
o meta.c: when target is out-of-date per normal make rules
record value of .OODATE in meta file.
2019-09-26 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20190926
Merge with NetBSD make, pick up
o parse.c: don't pass NULL to realpath(3)
some versions cannot handle it.
2019-04-09 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20190409
Merge with NetBSD make, pick up
o parse.c: ParseDoDependency: free paths rather than assert
2018-12-22 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20181222
* configure.in: add --without-makefile to avoid generating
makefile and make-bootstrap.sh
* include Makefile.inc if it exists
* Use Makefile and Makefile.config.in in unit-tests
so we can use just: make obj && make && make test
when bmake is already available.
We add --without-makefile to CONFIGURE_ARGS in this case.
* tweak bsd.after-import.mk (captures Makefile.config etc
after import to FreeBSD for example) to cope with all the above.
2018-12-21 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20181221
Merge with NetBSD make, pick up
o parse.c: ParseVErrorInternal use .PARSEDIR
and apply if relative, and then use .PARSEFILE
for consistent result.
2018-12-20 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20181220
Merge with NetBSD make, pick up
o parse.c: ParseVErrorInternal use .CURDIR if .PARSEDIR
is relative
o var.c: avoid SEGFAULT in .unexport-env
when MAKELEVEL is not set
2018-12-16 Simon J Gerraty <sjg@beast.crufty.net>
* VERSION: 20181216
Merge with NetBSD make, pick up
o fix for unit-tests/varquote.mk on Debian
2018-09-21 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20180919
Merge with NetBSD make, pick up
o var.c: add :q
o dir.c: cleanup caching of stats
2018-09-21 Simon J Gerraty <sjg@beast.crufty.net>
* Makefile.config.in: use += where it makes sense.
2018-05-12 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20180512
Merge with NetBSD make, pick up
o job.c: skip polling job token pipe
2018-04-05 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20180405
Merge with NetBSD make, pick up
o parse.c: be more cautious about detecting depenency line
rather than sysV style include.
2018-02-22 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20180222
Merge with NetBSD make, pick up
o parse.c: avoid calling sysconf for every call to loadfile
2018-02-18 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20180218
Merge with NetBSD make, pick up
o var.c: Var_Set handle NULL value anytime.
2018-02-12 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20180212
Merge with NetBSD make, pick up
o parse.c: do not treat .info as warning with -W
2017-12-07 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20171207
Merge with NetBSD make, pick up
o var.c: Var_Append use Var_Set if var not previously set
so that VAR_CMD is handled correctly.
Add a suitable unit-test.
2017-11-26 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION (_MAKE_VERSION): 20171126
* aclocal.m4: use AC_LINK_IFELSE for AC_C___ATTRIBUTE__
since AC_TRY_COMPILE puts input inside main()
which upsets modern compilers.
2017-11-18 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20171118
Merge with NetBSD make, pick up
o var.c: do not append to variable set on command line
add unit-test to catch this.
2017-10-28 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20171028
Merge with NetBSD make, pick up
o main.c: ignore empty MAKEOBJDIR
* Makefile.config.in:
make @prefix@ @machine*@ and @default_sys_path@ defaults.
2017-10-05 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION: 20171005
* unit-tests/dotwait.mk: redirect stderr through pipe for more
consistent result on some platforms.
2017-08-13 Simon J. Gerraty <sjg@bad.crufty.net>
* machine.sh: entry for AIX
2017-08-12 Simon J. Gerraty <sjg@bad.crufty.net>
* VERSION (_MAKE_VERSION): Move the setting of _MAKE_VERSION
to a file that can be included by configure as well as make.
This allows configure to set set _MAKE_VERSION in make-bootstrap.sh
2017-08-10 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170810
Merge with NetBSD make, pick up
o meta.c: if target is in subdir we only need subdir name in
meta_name.
2017-07-20 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170720
Merge with NetBSD make, pick up
o compat.c: pass SIGINT etc onto child and wait for it to exit
before we self-terminate.
2017-07-11 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170711
forgot to update after merge on 20170708 ;-)
o main.c: refactor to reduce size of main function.
add -v option to always fully expand values.
o meta.c: ensure command output in meta file has ending newline
even when filemon not being used.
When matching ${.MAKE.META.IGNORE_PATTERNS} do not use
pathname via ':L' since any ':' in pathname breaks that.
Instead set a '${.p.}' to pathname in the target context and
use that.
2017-05-10 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170510
Merge with NetBSD make, pick up
o main.c: Main_SetObjdir: ensure buf2 is in scope
2017-05-08 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170505
see mk/ChangeLog
2017-05-05 Simon J. Gerraty <sjg@bad.crufty.net>
* parse.c: not everyone has stdint.h
2017-05-01 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170501
see mk/ChangeLog
2017-04-21 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170421
Merge with NetBSD make, pick up
o str.c: Str_Match: fix closure tests for [^] and add unit-test.
2017-04-20 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170420
Merge with NetBSD make, pick up
o main.c: only use -C arg "as is" if it contains no
relative component.
2017-04-18 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170418
Merge with NetBSD make, pick up
o main.c: fix Main_SetObjdir() for relative paths (eg obj).
2017-04-17 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170417
Merge with NetBSD make, pick up
o fixes a number of coverity complaints
- check return value of fseek, fcntl
- plug memory leak in Dir_FindFile, Var_LoopExpand,
JobPrintCommand, ParseTraditionalInclude
- use bmake_malloc() where NULL is not tollerated
- use MAKE_ATTR_UNUSED rather that kludges like
return(unused ? 0 : 0)
- use purge_cached_realpaths() rather than abuse cached_realpath()
2017-04-13 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170413
Merge with NetBSD make, pick up
o main.c: when setting .OBJDIR ignore '$' in paths.
* job.c: use MALLOC_OPTIONS to set malloc_options.
2017-04-11 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170411
Merge with NetBSD make, pick up
o str.c: Str_Match: allow [^a-z] to behave as expected.
2017-03-26 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170326
Merge with NetBSD make, pick up
o main.c: purge relative paths from realpath cache when .OBJDIR
is changed.
2017-03-11 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170311
Merge with NetBSD make, pick up
o main.c: only use -C arg "as is" if it starts with '/'.
2017-03-01 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170301
Merge with NetBSD make, pick up
o main.c: use -C arg "as is" rather than getcwd()
if they identify the same directory.
o parse.c: ensure loadfile buffer is \n terminated in non-mmap case
2017-02-01 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170201
Merge with NetBSD make, pick up
o var.c: allow :_=var and avoid use of special context.
2017-01-30 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170130
Merge with NetBSD make, pick up
o var.c: add :range and :_
o main.c: partially initialize Dir_* before MainParseArgs()
can be called.
If -V, skip Main_ExportMAKEFLAGS()
2017-01-14 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20170114
Merge with NetBSD make, pick up
o var.c: allow specifying the utc value used by :{gm,local}time
2016-12-12 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20161212
Merge with NetBSD make, pick up
o main.c: look for obj.${MACHINE}-${MACHINE_ARCH} too.
2016-12-09 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20161209
Merge with NetBSD make, pick up
o main.c: cleanup setting of .OBJDIR
o parse.c: avoid coredump from (var)=val
2016-11-26 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20161126
Merge with NetBSD make, pick up
o make.c: Make_OODate: report src node name if path not set
2016-09-26 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160926
Merge with NetBSD make, pick up
o support for .DELETE_ON_ERROR: (remove targets that fail)
2016-09-26 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile MAN: tweak .Dt to match ${PROG}
2016-08-18 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160818
its a neater number; pick up whitespace fixes to man page.
2016-08-17 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160817
Merge with NetBSD make, pick up
o meta.c: move handling of .MAKE.META.IGNORE_* to meta_ignore()
so we can call it before adding entries to missingFiles.
Thus we do not track files we have been told to ignore.
2016-08-15 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160815
Merge with NetBSD make, pick up
o meta_oodate: apply .MAKE.META.IGNORE_FILTER (if defined) to
pathnames, and skip if the expansion is empty.
Useful for dirdeps.mk when checking DIRDEPS_CACHE.
2016-08-12 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160812
Merge with NetBSD make, pick up
o meta.c: remove all missingFiles entries that match a deleted
dir.
o main.c: set .ERROR_CMD if possible.
2016-06-06 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160606
Merge with NetBSD make, pick up
o dir.c: extend mtimes cache to others via cached_stat()
2016-06-04 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160604
Merge with NetBSD make, pick up
o meta.c: missing filemon data is only relevant if we read a
meta file.
Also do not return oodate for a missing metafile if gn->path
points to .CURDIR
2016-06-02 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160602
Merge with NetBSD make, pick up
o cached_realpath(): avoid hitting filesystem more than necessary.
o meta.c: refactor need_meta decision, add knobs for
missing meta file and filemon data wrt out-of-datedness.
2016-05-28 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160528
* boot-strap, make-bootstrap.sh.in: Makefile now uses _MAKE_VERSION
2016-05-12 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160512
Merge with NetBSD make, pick up
o meta.c: ignore paths that match .MAKE.META.IGNORE_PATTERNS
this is useful for gcov builds.
o propagate errors from filemon(4).
2016-05-09 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160509
Merge with NetBSD make, pick up
o remove use of non-standard types u_int etc.
o meta.c: apply realpath() before matching against metaIgnorePaths
2016-04-04 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160404
Merge with NetBSD make, pick up
o allow makefile to set .MAKE.JOBS
* Makefile (PROG_NAME): use ${_MAKE_VERSION}
2016-03-15 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): 20160315
Merge with NetBSD make, pick up
o fix handling of archive members
2016-03-13 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (_MAKE_VERSION): rename variable to avoid interference
with checks for ${MAKE_VERSION}
2016-03-10 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160310
Merge with NetBSD make, pick up
o meta.c: treat missing Read file same as Write, incase we Delete it.
2016-03-07 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160307
Merge with NetBSD make, pick up
o var.c: fix :ts\nnn to be octal by default.
o meta.c: meta_finish() to cleanup memory.
2016-02-26 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160226
Merge with NetBSD make, pick up
o meta.c: allow meta file for makeDepend if makefiles want it.
2016-02-19 Simon J. Gerraty <sjg@bad.crufty.net>
* var.c: default .MAKE.SAVE_DOLLARS to FALSE
for backwards compatability.
* Makefile (MAKE_VERSION): 20160220
Merge with NetBSD make, pick up
o var.c: add knob to control handling of '$$' in :=
2016-02-18 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160218
Merge with NetBSD make, pick up
o var.c: add .export-literal allows us to fix sys.clean-env.mk
post the changes to Var_Subst.
Var_Subst now takes flags, and does not consume '$$' in :=
2016-02-17 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160217
Merge with NetBSD make, pick up
o var.c: preserve '$$' in :=
o parse.c: add .dinclude for handling included
makefile like .depend
2015-12-20 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20151220
Merge with NetBSD make, pick up
o suff.c: re-initialize suffNull when clearing suffixes.
2015-12-01 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20151201
Merge with NetBSD make, pick up
o cond.c: CondCvtArg: avoid access beyond end of empty buffer.
o meta.c: meta_oodate: use lstat(2) for checking link target
in case it is a symlink.
o var.c: avoid calling brk_string and Var_Export1 with empty
strings.
2015-11-26 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20151126
Merge with NetBSD make, pick up
o parse.c: ParseTrackInput don't access beyond
end of old value.
2015-10-22 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20151022
* Add support for BSD/OS which lacks inttypes.h
and really needs sys/param.h for sys/sysctl.h
also 'type' is not a shell builtin.
* var.c: eliminate uint32_t and need for inttypes.h
* main.c: PrintOnError flush stdout before run .ERROR
* parse.c: cope with _SC_PAGESIZE not being defined.
2015-10-20 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20151020
Merge with NetBSD make, pick up
o var.c: fix uninitialized var
2015-10-12 Simon J. Gerraty <sjg@bad.crufty.net>
* var.c: the conditional expressions used with ':?' can be
expensive, if already discarding do not evaluate or expand
anything.
2015-10-10 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20151010
Merge with NetBSD make, pick up
o Add Boolean wantit flag to Var_Subst and Var_Parse
when FALSE we know we are discarding the result and can
skip operations like Cmd_Exec.
2015-10-09 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20151009
Merge with NetBSD make, pick up
o var.c: don't check for NULL before free()
o meta.c: meta_oodate, do not hard code ignore of makeDependfile
2015-09-10 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20150910
Merge with NetBSD make, pick up
o main.c: with -w print Enter/Leaving messages for objdir too
if necessary.
o centralize shell metachar handling
* FILES: add metachar.[ch]
2015-06-06 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20150606
Merge with NetBSD make, pick up
o make.1: document .OBJDIR target
2015-05-05 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20150505

View File

@ -5,6 +5,7 @@ Makefile.config.in
PSD.doc/Makefile
PSD.doc/tutorial.ms
README
VERSION
aclocal.m4
arch.c
bmake.1
@ -21,6 +22,9 @@ configure.in
dir.c
dir.h
dirname.c
filemon/filemon.h
filemon/filemon_dev.c
filemon/filemon_ktrace.c
find_lib.sh
for.c
getopt.c
@ -71,6 +75,8 @@ make_malloc.h
makefile.in
meta.c
meta.h
metachar.c
metachar.h
missing/sys/cdefs.h
mkdeps.sh
nonints.h
@ -91,13 +97,18 @@ suff.c
targ.c
trace.c
trace.h
unit-tests/Makefile.in
unit-tests/Makefile
unit-tests/Makefile.config.in
unit-tests/comment.exp
unit-tests/comment.mk
unit-tests/cond1.exp
unit-tests/cond1.mk
unit-tests/cond2.exp
unit-tests/cond2.mk
unit-tests/cond-late.mk
unit-tests/cond-late.exp
unit-tests/dollar.exp
unit-tests/dollar.mk
unit-tests/doterror.exp
unit-tests/doterror.mk
unit-tests/dotwait.exp
@ -120,6 +131,10 @@ unit-tests/hash.exp
unit-tests/hash.mk
unit-tests/impsrc.exp
unit-tests/impsrc.mk
unit-tests/include-main.exp
unit-tests/include-main.mk
unit-tests/include-sub.mk
unit-tests/include-subsub.mk
unit-tests/misc.exp
unit-tests/misc.mk
unit-tests/moderrs.exp
@ -160,6 +175,10 @@ unit-tests/varcmd.exp
unit-tests/varcmd.mk
unit-tests/varmisc.exp
unit-tests/varmisc.mk
unit-tests/varmod-edge.exp
unit-tests/varmod-edge.mk
unit-tests/varquote.exp
unit-tests/varquote.mk
unit-tests/varshell.exp
unit-tests/varshell.mk
util.c

View File

@ -1,7 +1,4 @@
# $Id: Makefile,v 1.1.1.1 2015/05/19 21:36:43 joerg Exp $
# Base version on src date
MAKE_VERSION= 20150505
# $Id: Makefile,v 1.1.1.2 2020/05/24 05:35:51 nia Exp $
PROG= bmake
@ -18,6 +15,7 @@ SRCS= \
make.c \
make_malloc.c \
meta.c \
metachar.c \
parse.c \
str.c \
strlist.c \
@ -57,6 +55,9 @@ SRCS+= \
lstReplace.c \
lstSucc.c
.-include "VERSION"
.-include "Makefile.inc"
# this file gets generated by configure
.-include "Makefile.config"
@ -75,13 +76,25 @@ CFLAGS+= ${CPPFLAGS}
CFLAGS+= -D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"
CFLAGS+= -I. -I${srcdir} ${XDEFS} -DMAKE_NATIVE
CFLAGS+= ${COPTS.${.ALLSRC:M*.c:T:u}}
COPTS.main.c+= "-DMAKE_VERSION=\"${MAKE_VERSION}\""
COPTS.main.c+= "-DMAKE_VERSION=\"${_MAKE_VERSION}\""
# meta mode can be useful even without filemon
# meta mode can be useful even without filemon
# should be set by now
USE_FILEMON ?= no
.if ${USE_FILEMON:tl} != "no"
.PATH: ${.CURDIR}/filemon
SRCS+= filemon_${USE_FILEMON}.c
COPTS.meta.c+= -DUSE_FILEMON -DUSE_FILEMON_${USE_FILEMON:tu}
COPTS.job.c+= ${COPTS.meta.c}
.if ${USE_FILEMON} == "dev"
FILEMON_H ?= /usr/include/dev/filemon/filemon.h
.if exists(${FILEMON_H}) && ${FILEMON_H:T} == "filemon.h"
COPTS.meta.c += -DHAVE_FILEMON_H -I${FILEMON_H:H}
COPTS.filemon_dev.c += -DHAVE_FILEMON_H -I${FILEMON_H:H}
.endif
.endif # USE_FILEMON == dev
.endif # USE_FILEMON
.PATH: ${srcdir}
.PATH: ${srcdir}/lst.lib
@ -130,9 +143,9 @@ OPTIONS_DEFAULT_NO+= \
.include <own.mk>
.if ${MK_PROG_VERSION} == "yes"
PROG_NAME= ${PROG}-${MAKE_VERSION}
PROG_NAME= ${PROG}-${_MAKE_VERSION}
.if ${MK_PROG_LINK} == "yes"
SYMLINKS+= ${PROG}-${MAKE_VERSION} ${BINDIR}/${PROG}
SYMLINKS+= ${PROG_NAME} ${BINDIR}/${PROG}
.endif
.endif
@ -155,7 +168,10 @@ my.history: ${MAKEFILE}
.NOPATH: ${MAN}
${MAN}: make.1 my.history
@echo making $@
@sed -e 's/^.Nx/NetBSD/' -e '/^.Nm/s/make/${PROG}/' \
@sed \
-e '/^.Dt/s/MAKE/${PROG:tu}/' \
-e 's/^.Nx/NetBSD/' \
-e '/^.Nm/s/make/${PROG}/' \
-e '/^.Sh HISTORY/rmy.history' \
-e '/^.Sh HISTORY/,$$s,^.Nm,make,' ${srcdir}/make.1 > $@
@ -188,11 +204,15 @@ MANDIR= ${MANDIR.bmake:U${SHAREDIR}/man}
${OBJS}: config.h
.endif
# make sure that MAKE_VERSION gets updated.
main.o: ${SRCS} ${MAKEFILE}
# start-delete2 for bsd.after-import.mk
# make sure that MAKE_VERSION gets updated.
main.o: ${SRCS} ${.CURDIR}/VERSION
.if ${MK_AUTOCONF_MK} == "yes"
CONFIGURE_DEPS += ${.CURDIR}/VERSION
# we do not need or want the generated makefile
CONFIGURE_ARGS += --without-makefile
.include <autoconf.mk>
.endif
SHARE_MK?=${SHAREDIR}/mk

View File

@ -1,20 +1,22 @@
# things set by configure
prefix= @prefix@
_MAKE_VERSION?=@_MAKE_VERSION@
prefix?= @prefix@
srcdir= @srcdir@
CC?= @CC@
MACHINE= @machine@
MACHINE_ARCH= @machine_arch@
DEFAULT_SYS_PATH= @default_sys_path@
MACHINE?= @machine@
MACHINE_ARCH?= @machine_arch@
DEFAULT_SYS_PATH?= @default_sys_path@
CPPFLAGS+= @CPPFLAGS@
CFLAGS+= ${CPPFLAGS} @DEFS@
LDFLAGS= @LDFLAGS@
LIBOBJS= @LIBOBJS@
LDADD= @LIBS@
USE_META= @use_meta@
FILEMON_H= @filemon_h@
LDFLAGS+= @LDFLAGS@
LIBOBJS+= @LIBOBJS@
LDADD+= @LIBS@
USE_META?= @use_meta@
USE_FILEMON?= @use_filemon@
FILEMON_H?= @filemon_h@
BMAKE_PATH_MAX?= @bmake_path_max@
# used if MAXPATHLEN not defined
CPPFLAGS+= -DBMAKE_PATH_MAX=${BMAKE_PATH_MAX}

View File

@ -1,4 +1,4 @@
.\" $NetBSD: tutorial.ms,v 1.1.1.4 2015/05/19 21:36:45 joerg Exp $
.\" $NetBSD: tutorial.ms,v 1.1.1.5 2020/05/24 05:35:53 nia Exp $
.\" Copyright (c) 1988, 1989, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@ -117,6 +117,15 @@
.de No
.br
.ne 0.5i
.ie n \{\
.nr g3 \w'NOTE '
.po -\\n(g3u
.br
NOTE
.br
.po +\\n(g3u
.\}
.el \{\
.po -0.5i
.br
.mk
@ -148,12 +157,14 @@
.rt
.ft \\n(g3
.ps \\n(g4
.\}
..
.de Bp
.ie !\\n(.$ .IP \(bu 2
.el .IP "\&" 2
..
.po +.3i
.ie n .po +\w'NOTE 'u
.el .po +.3i
.TL
PMake \*- A Tutorial
.AU

View File

@ -1,47 +1,52 @@
bmake
*****
This directory contains a port of the BSD make tool (from NetBSD)
I have run it on SunOS,Solaris,HP-UX,AIX,IRIX,FreeBSD and Linux.
This directory contains a port of the BSD make tool (from NetBSD).
Since 1993 I have run it on AIX, BSDi, Darwin, FreeBSD, HP-UX, IRIX,
Linux, Minix, OSF, Solaris, SunOS and even UTS.
Others have run it on many more systems.
Version 3 was re-worked from scratch to better facilitate
importing newer make(1) versions from NetBSD. The original code base
was NetBSD-1.0, so version 3 was built by doing a fresh import of the
NetBSD-1.0 usr.bin/make, adding the autoconf and other portability
patches to sync it with bmake v2, and then NetBSD's make
of Feb 20, 2000 was imported and conflicts dealt with.
NetBSD's make was again imported on June 6 and December 15, 2000.
Currently each release is tested on NetBSD, FreeBSD, Solaris and Linux.
In 2003 bmake switched to a date based version (first was 20030714)
Since 2003 bmake switched to a date based version (first was 20030714)
which generally represents the date it was last merged with NetBSD's
make. Since then, NetBSD's make is imported within a week of any
interesting changes, so that bmake tracks it very closely.
Building:
Building
========
The preferred way to bootstrap bmake is:
The preferred way to bootstrap bmake is::
./bmake/boot-strap
./bmake/boot-strap
there are a number of args - most of which get passed to configure,
eg.
::
./bmake/boot-strap --prefix=/opt
./bmake/boot-strap --prefix=/opt
see the boot-strap script for details.
For folk that hate to read anything, since 20121212 you can also use
the GNU standard process of::
./configure; make; make install
To make much use of bmake you will need the bsd.*.mk macros or my
portable *.mk macros. See
portable *.mk macros which are included with bmake since 20121212
and separately available from
http://www.crufty.net/ftp/pub/sjg/mk.tar.gz
which will be links to the latest versions.
On a non-BSD system, you would want to unpack mk[-YYYYmmdd].tar.gz in
the same directory as bmake (so ./mk and ./bmake exist), and
./bmake/boot-strap will do the rest.
Porting
=======
If you want to do it all by hand then read boot-strap first to get the
idea.
If you encounter a system that bmake does not build or work on *out of
the box*, I welcome patches.
If you can provide access to a suitable machine - even better.
Even if you have an earlier version of bmake installed, use boot-strap
to ensure that all goes well.
More info can be found at http://www.crufty.net/help/sjg/bmake.htm
--sjg <sjg@crufty.net>
--sjg

View File

@ -0,0 +1,2 @@
# keep this compatible with sh and make
_MAKE_VERSION=20200517

View File

@ -1,5 +1,5 @@
dnl RCSid:
dnl $Id: aclocal.m4,v 1.1.1.3 2009/09/18 20:55:24 joerg Exp $
dnl $Id: aclocal.m4,v 1.1.1.4 2020/05/24 05:35:51 nia Exp $
dnl
dnl
@ -55,10 +55,9 @@ dnl
AC_DEFUN(AC_C___ATTRIBUTE__, [
AC_MSG_CHECKING(for __attribute__)
AC_CACHE_VAL(ac_cv___attribute__, [
AC_TRY_COMPILE([
AC_LINK_IFELSE([
#include <stdlib.h>
],
[
static void foo(void) __attribute__ ((noreturn));
static void
@ -66,6 +65,12 @@ foo(void)
{
exit(1);
}
int
main(int argc, char **argv)
{
foo();
}
],
ac_cv___attribute__=yes,
ac_cv___attribute__=no)])

View File

@ -1,4 +1,4 @@
/* $NetBSD: arch.c,v 1.1.1.8 2015/05/19 21:36:43 joerg Exp $ */
/* $NetBSD: arch.c,v 1.1.1.9 2020/05/24 05:35:51 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: arch.c,v 1.1.1.8 2015/05/19 21:36:43 joerg Exp $";
static char rcsid[] = "$NetBSD: arch.c,v 1.1.1.9 2020/05/24 05:35:51 nia Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
#else
__RCSID("$NetBSD: arch.c,v 1.1.1.8 2015/05/19 21:36:43 joerg Exp $");
__RCSID("$NetBSD: arch.c,v 1.1.1.9 2020/05/24 05:35:51 nia Exp $");
#endif
#endif /* not lint */
#endif
@ -136,7 +136,6 @@ __RCSID("$NetBSD: arch.c,v 1.1.1.8 2015/05/19 21:36:43 joerg Exp $");
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/param.h>
#include <ctype.h>
#ifdef HAVE_AR_H
#include <ar.h>
#else
@ -156,7 +155,6 @@ struct ar_hdr {
#if defined(HAVE_RANLIB_H) && !(defined(__ELF__) || defined(NO_RANLIB))
#include <ranlib.h>
#endif
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UTIME_H
@ -254,8 +252,7 @@ ArchFree(void *ap)
free(Hash_GetValue(entry));
free(a->name);
if (a->fnametab)
free(a->fnametab);
free(a->fnametab);
Hash_DeleteTable(&a->members);
free(a);
}
@ -310,9 +307,10 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
void *freeIt;
char *result;
result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
if (freeIt)
free(freeIt);
result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES,
&length, &freeIt);
free(freeIt);
if (result == var_Error) {
return(FAILURE);
} else {
@ -325,7 +323,7 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
*cp++ = '\0';
if (subLibName) {
libName = Var_Subst(NULL, libName, ctxt, TRUE);
libName = Var_Subst(NULL, libName, ctxt, VARF_UNDEFERR|VARF_WANTRES);
}
@ -351,9 +349,10 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
void *freeIt;
char *result;
result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
if (freeIt)
free(freeIt);
result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES,
&length, &freeIt);
free(freeIt);
if (result == var_Error) {
return(FAILURE);
} else {
@ -404,7 +403,8 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
char *oldMemName = memName;
size_t sz;
memName = Var_Subst(NULL, memName, ctxt, TRUE);
memName = Var_Subst(NULL, memName, ctxt,
VARF_UNDEFERR|VARF_WANTRES);
/*
* Now form an archive spec and recurse to deal with nested
@ -682,7 +682,7 @@ ArchStatMember(char *archive, char *member, Boolean hash)
arh.AR_SIZE[sizeof(arh.AR_SIZE)-1] = '\0';
size = (int)strtol(arh.AR_SIZE, NULL, 10);
(void)strncpy(memName, arh.AR_NAME, sizeof(arh.AR_NAME));
memcpy(memName, arh.AR_NAME, sizeof(arh.AR_NAME));
for (cp = &memName[AR_MAX_NAME_LEN]; *cp == ' '; cp--) {
continue;
}
@ -726,7 +726,8 @@ ArchStatMember(char *archive, char *member, Boolean hash)
if (fread(memName, elen, 1, arch) != 1)
goto badarch;
memName[elen] = '\0';
fseek(arch, -elen, SEEK_CUR);
if (fseek(arch, -elen, SEEK_CUR) != 0)
goto badarch;
if (DEBUG(ARCH) || DEBUG(MAKE)) {
fprintf(debug_file, "ArchStat: Extended format entry for %s\n", memName);
}
@ -737,7 +738,8 @@ ArchStatMember(char *archive, char *member, Boolean hash)
Hash_SetValue(he, bmake_malloc(sizeof(struct ar_hdr)));
memcpy(Hash_GetValue(he), &arh, sizeof(struct ar_hdr));
}
fseek(arch, (size + 1) & ~1, SEEK_CUR);
if (fseek(arch, (size + 1) & ~1, SEEK_CUR) != 0)
goto badarch;
}
fclose(arch);
@ -759,8 +761,7 @@ ArchStatMember(char *archive, char *member, Boolean hash)
badarch:
fclose(arch);
Hash_DeleteTable(&ar->members);
if (ar->fnametab)
free(ar->fnametab);
free(ar->fnametab);
free(ar);
return NULL;
}
@ -833,7 +834,7 @@ ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch)
}
if (DEBUG(ARCH)) {
fprintf(debug_file, "Found svr4 archive name table with %lu entries\n",
(u_long)entry);
(unsigned long)entry);
}
return 0;
}
@ -851,7 +852,7 @@ ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch)
if (entry >= ar->fnamesize) {
if (DEBUG(ARCH)) {
fprintf(debug_file, "SVR4 entry offset %s is greater than %lu\n",
name, (u_long)ar->fnamesize);
name, (unsigned long)ar->fnamesize);
}
return 2;
}
@ -957,7 +958,10 @@ ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr,
* the file at the actual member, rather than its header, but
* not here...
*/
fseek(arch, -sizeof(struct ar_hdr), SEEK_CUR);
if (fseek(arch, -sizeof(struct ar_hdr), SEEK_CUR) != 0) {
fclose(arch);
return NULL;
}
return (arch);
}
} else
@ -987,10 +991,17 @@ ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr,
}
if (strncmp(ename, member, len) == 0) {
/* Found as extended name */
fseek(arch, -sizeof(struct ar_hdr) - elen, SEEK_CUR);
if (fseek(arch, -sizeof(struct ar_hdr) - elen,
SEEK_CUR) != 0) {
fclose(arch);
return NULL;
}
return (arch);
}
fseek(arch, -elen, SEEK_CUR);
if (fseek(arch, -elen, SEEK_CUR) != 0) {
fclose(arch);
return NULL;
}
goto skip;
} else
#endif
@ -1003,9 +1014,12 @@ skip:
* extract the size of the file from the 'size' field of the
* header and round it up during the seek.
*/
arhPtr->ar_size[sizeof(arhPtr->AR_SIZE)-1] = '\0';
arhPtr->AR_SIZE[sizeof(arhPtr->AR_SIZE)-1] = '\0';
size = (int)strtol(arhPtr->AR_SIZE, NULL, 10);
fseek(arch, (size + 1) & ~1, SEEK_CUR);
if (fseek(arch, (size + 1) & ~1, SEEK_CUR) != 0) {
fclose(arch);
return NULL;
}
}
}
@ -1045,10 +1059,10 @@ Arch_Touch(GNode *gn)
arch = ArchFindMember(Var_Value(ARCHIVE, gn, &p1),
Var_Value(MEMBER, gn, &p2),
&arh, "r+");
if (p1)
free(p1);
if (p2)
free(p2);
free(p1);
free(p2);
snprintf(arh.AR_DATE, sizeof(arh.AR_DATE), "%-12ld", (long) now);
if (arch != NULL) {
@ -1127,10 +1141,9 @@ Arch_MTime(GNode *gn)
arhPtr = ArchStatMember(Var_Value(ARCHIVE, gn, &p1),
Var_Value(MEMBER, gn, &p2),
TRUE);
if (p1)
free(p1);
if (p2)
free(p2);
free(p1);
free(p2);
if (arhPtr != NULL) {
modTime = (time_t)strtol(arhPtr->AR_DATE, NULL, 10);

View File

@ -1,4 +1,4 @@
.\" $NetBSD: bmake.1,v 1.1.1.5 2015/05/19 21:36:43 joerg Exp $
.\" $NetBSD: bmake.1,v 1.1.1.6 2020/05/24 05:35:51 nia Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,8 +29,8 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
.Dd April 9, 2015
.Dt MAKE 1
.Dd May 26, 2018
.Dt BMAKE 1
.Os
.Sh NAME
.Nm bmake
@ -48,6 +48,7 @@
.Op Fl m Ar directory
.Op Fl T Ar file
.Op Fl V Ar variable
.Op Fl v Ar variable
.Op Ar variable=value
.Op Ar target ...
.Sh DESCRIPTION
@ -206,7 +207,9 @@ Print debugging information about target list maintenance.
.It Ar V
Force the
.Fl V
option to print raw values of variables.
option to print raw values of variables, overriding the default behavior
set via
.Va .MAKE.EXPAND_VARIABLES .
.It Ar v
Print debugging information about variable assignment.
.It Ar x
@ -293,7 +296,7 @@ then
will search for the specified file or directory named in the remaining part
of the argument string.
The search starts with the current directory of
the Makefile and then works upward towards the root of the filesystem.
the Makefile and then works upward towards the root of the file system.
If the search is successful, then the resulting directory replaces the
.Qq \&.../
specification in the
@ -334,20 +337,39 @@ for each job started and completed.
Rather than re-building a target as specified in the makefile, create it
or update its modification time to make it appear up-to-date.
.It Fl V Ar variable
Print
.Nm Ns 's
idea of the value of
.Ar variable ,
in the global context.
Print the value of
.Ar variable .
Do not build any targets.
Multiple instances of this option may be specified;
the variables will be printed one per line,
with a blank line for each null or undefined variable.
The value printed is extracted from the global context after all
makefiles have been read.
By default, the raw variable contents (which may
include additional unexpanded variable references) are shown.
If
.Ar variable
contains a
.Ql \&$
then the value will be expanded before printing.
then the value will be recursively expanded to its complete resultant
text before printing.
The expanded value will also be printed if
.Va .MAKE.EXPAND_VARIABLES
is set to true and
the
.Fl dV
option has not been used to override it.
Note that loop-local and target-local variables, as well as values
taken temporarily by global variables during makefile processing, are
not accessible via this option.
The
.Fl dv
debug mode can be used to see these at the cost of generating
substantial extraneous output.
.It Fl v Ar variable
Like
.Fl V
but the variable is always expanded to its complete value.
.It Fl W
Treat any warnings during makefile parsing as errors.
.It Fl w
@ -657,7 +679,7 @@ The seven local variables are as follows:
.Bl -tag -width ".ARCHIVE" -offset indent
.It Va .ALLSRC
The list of all sources for this target; also known as
.Ql Va \&\*[Gt] .
.Ql Va \&> .
.It Va .ARCHIVE
The name of the archive file; also known as
.Ql Va \&! .
@ -666,7 +688,7 @@ In suffix-transformation rules, the name/path of the source from which the
target is to be transformed (the
.Dq implied
source); also known as
.Ql Va \&\*[Lt] .
.Ql Va \&< .
It is not defined in explicit rules.
.It Va .MEMBER
The name of the archive member; also known as
@ -685,12 +707,15 @@ or it will not be recognized.
.It Va .TARGET
The name of the target; also known as
.Ql Va @ .
For compatibility with other makes this is an alias for
.Ic .ARCHIVE
in archive member rules.
.El
.Pp
The shorter forms
.Ql ( Va \*[Gt] ,
.Ql ( Va > ,
.Ql Va \&! ,
.Ql Va \*[Lt] ,
.Ql Va < ,
.Ql Va % ,
.Ql Va \&? ,
.Ql Va * ,
@ -773,6 +798,10 @@ from which generated dependencies are read.
A boolean that controls the default behavior of the
.Fl V
option.
If true, variable values printed with
.Fl V
are fully expanded; if false, the raw variable contents (which may
include additional unexpanded variable references) are shown.
.It Va .MAKE.EXPORTED
The list of variables exported by
.Nm .
@ -843,7 +872,7 @@ Can affect the mode that
.Nm
runs in.
It can contain a number of keywords:
.Bl -hang -width ignore-cmd
.Bl -hang -width missing-filemon=bf.
.It Pa compat
Like
.Fl B ,
@ -867,8 +896,19 @@ will not create .meta files in
This can be overridden by setting
.Va bf
to a value which represents True.
.It Pa missing-meta= Ar bf
If
.Va bf
is True, then a missing .meta file makes the target out-of-date.
.It Pa missing-filemon= Ar bf
If
.Va bf
is True, then missing filemon data makes the target out-of-date.
.It Pa nofilemon
Do not use
.Xr filemon 4 .
.It Pa env
For debugging, it can be useful to inlcude the environment
For debugging, it can be useful to include the environment
in the .meta file.
.It Pa verbose
If in "meta" mode, print a clue about the target being built.
@ -910,6 +950,12 @@ Provides a list of path prefixes that should be ignored;
because the contents are expected to change over time.
The default list includes:
.Ql Pa /dev /etc /proc /tmp /var/run /var/tmp
.It Va .MAKE.META.IGNORE_PATTERNS
Provides a list of patterns to match against pathnames.
Ignore any that match.
.It Va .MAKE.META.IGNORE_FILTER
Provides a list of variable modifiers to apply to each pathname.
Ignore if the expansion is an empty string.
.It Va .MAKE.META.PREFIX
Defines the message printed for each meta file updated in "meta verbose" mode.
The default value is:
@ -918,7 +964,7 @@ The default value is:
This variable is used to record the names of variables assigned to
on the command line, so that they may be exported as part of
.Ql Ev MAKEFLAGS .
This behaviour can be disabled by assigning an empty value to
This behavior can be disabled by assigning an empty value to
.Ql Va .MAKEOVERRIDES
within a makefile.
Extra variables can be exported from a makefile
@ -941,10 +987,35 @@ The process-id of
.It Va .MAKE.PPID
The parent process-id of
.Nm .
.It Va .MAKE.SAVE_DOLLARS
value should be a boolean that controls whether
.Ql $$
are preserved when doing
.Ql :=
assignments.
The default is false, for backwards compatibility.
Set to true for compatability with other makes.
If set to false,
.Ql $$
becomes
.Ql $
per normal evaluation rules.
.It Va MAKE_PRINT_VAR_ON_ERROR
When
.Nm
stops due to an error, it prints its name and the value of
stops due to an error, it sets
.Ql Va .ERROR_TARGET
to the name of the target that failed,
.Ql Va .ERROR_CMD
to the commands of the failed target,
and in "meta" mode, it also sets
.Ql Va .ERROR_CWD
to the
.Xr getcwd 3 ,
and
.Ql Va .ERROR_META_FILE
to the path of the meta file (if any) describing the failed target.
It then prints its name and the value of
.Ql Va .CURDIR
as well as the value of any variables named in
.Ql Va MAKE_PRINT_VAR_ON_ERROR .
@ -993,14 +1064,15 @@ This is especially useful with
.Ql Ev MAKEOBJDIR .
.Pp
.Ql Va .OBJDIR
may be modified in the makefile as a global variable.
may be modified in the makefile via the special target
.Ql Ic .OBJDIR .
In all cases,
.Nm
will
.Xr chdir 2
to
to the specified directory if it exists, and set
.Ql Va .OBJDIR
and set
and
.Ql Ev PWD
to that directory before executing any targets.
.
@ -1043,7 +1115,7 @@ sets
to the value of
.Ql Ev PWD
instead.
This behaviour is disabled if
This behavior is disabled if
.Ql Ev MAKEOBJDIRPREFIX
is set or
.Ql Ev MAKEOBJDIR
@ -1113,7 +1185,7 @@ The wildcard characters may be escaped with a backslash
As a consequence of the way values are split into words, matched,
and then joined, a construct like
.Dl ${VAR:M*}
will normalise the inter-word spacing, removing all leading and
will normalize the inter-word spacing, removing all leading and
trailing space, and converting multiple consecutive spaces
to single spaces.
.
@ -1133,7 +1205,7 @@ Randomize words in variable.
The results will be different each time you are referring to the
modified variable; use the assignment with expansion
.Pq Ql Cm \&:=
to prevent such behaviour.
to prevent such behavior.
For example,
.Bd -literal -offset indent
LIST= uno due tre quattro
@ -1155,22 +1227,39 @@ due uno quattro tre
.Ed
.It Cm \&:Q
Quotes every shell meta-character in the variable, so that it can be passed
safely to the shell.
.It Cm \&:q
Quotes every shell meta-character in the variable, and also doubles
.Sq $
characters so that it can be passed
safely through recursive invocations of
.Nm .
This is equivalent to:
.Sq \&:S/\e\&$/&&/g:Q .
.It Cm \&:R
Replaces each word in the variable with everything but its suffix.
.It Cm \&:gmtime
.It Cm \&:range[=count]
The value is an integer sequence representing the words of the original
value, or the supplied
.Va count .
.It Cm \&:gmtime[=utc]
The value is a format string for
.Xr strftime 3 ,
using the current
using
.Xr gmtime 3 .
If a
.Va utc
value is not provided or is 0, the current time is used.
.It Cm \&:hash
Compute a 32bit hash of the value and encode it as hex digits.
.It Cm \&:localtime
Compute a 32-bit hash of the value and encode it as hex digits.
.It Cm \&:localtime[=utc]
The value is a format string for
.Xr strftime 3 ,
using the current
using
.Xr localtime 3 .
If a
.Va utc
value is not provided or is 0, the current time is used.
.It Cm \&:tA
Attempt to convert variable to an absolute path using
.Xr realpath 3 ,
@ -1231,7 +1320,7 @@ it is anchored at the end of each word.
Inside
.Ar new_string ,
an ampersand
.Pq Ql \*[Am]
.Pq Ql &
is replaced by
.Ar old_string
(without any
@ -1370,6 +1459,27 @@ For example.
.Pp
However a single character variable is often more readable:
.Dl ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}
.It Cm \&:_[=var]
Save the current variable value in
.Ql $_
or the named
.Va var
for later reference.
Example usage:
.Bd -literal -offset indent
M_cmpv.units = 1 1000 1000000
M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \&\\
\\* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh
.Dv .if ${VERSION:${M_cmpv}} < ${3.1.12:L:${M_cmpv}}
.Ed
Here
.Ql $_
is used to save the result of the
.Ql :S
modifier which is later referenced using the index values from
.Ql :range .
.It Cm \&:U Ns Ar newval
If the variable is undefined
.Ar newval
@ -1443,7 +1553,7 @@ value is divided into words.
.Pp
Ordinarily, a value is treated as a sequence of words
delimited by white space.
Some modifiers suppress this behaviour,
Some modifiers suppress this behavior,
causing a value to be treated as a single word
(possibly containing embedded white space).
An empty value, or a value that consists entirely of white-space,
@ -1529,12 +1639,20 @@ For compatibility with other versions of
.Nm
.Ql include file ...
is also accepted.
.Pp
If the include statement is written as
.Cm .-include
or as
.Cm .sinclude
then errors locating and/or opening include files are ignored.
.Pp
If the include statement is written as
.Cm .dinclude
not only are errors locating and/or opening include files ignored,
but stale dependencies within the included file will be ignored
just like
.Va .MAKE.DEPENDFILE .
.Pp
Conditional expressions are also preceded by a single dot as the first
character of a line.
The possible conditionals are as follows:
@ -1570,6 +1688,10 @@ This allows exporting a value to the environment which is different from that
used by
.Nm
internally.
.It Ic .export-literal Ar variable ...
The same as
.Ql .export-env ,
except that variables in the value are not expanded.
.It Ic .info Ar message
The message is printed along with the name of the makefile and line number.
.It Ic .undef Ar variable
@ -1662,7 +1784,7 @@ may be any one of the following:
.Bl -tag -width "Cm XX"
.It Cm \&|\&|
Logical OR.
.It Cm \&\*[Am]\*[Am]
.It Cm \&&&
Logical
.Tn AND ;
of higher precedence than
@ -1679,7 +1801,7 @@ The boolean operator
may be used to logically negate an entire
conditional.
It is of higher precedence than
.Ql Ic \&\*[Am]\*[Am] .
.Ql Ic \&&& .
.Pp
The value of
.Ar expression
@ -1750,7 +1872,8 @@ expression is applied.
Similarly, if the form is
.Ql Ic .ifmake
or
.Ql Ic .ifnmake , the
.Ql Ic .ifnmake ,
the
.Dq make
expression is applied.
.Pp
@ -1953,6 +2076,14 @@ variable of a target that inherits
.Ic .DEFAULT Ns 's
commands is set
to the target's own name.
.It Ic .DELETE_ON_ERROR
If this target is present in the makefile, it globally causes make to
delete targets whose commands fail.
(By default, only targets whose commands are interrupted during
execution are deleted.
This is the historical behavior.)
This setting can be used to help prevent half-finished or malformed
targets from being left around and corrupting future rebuilds.
.It Ic .END
Any command lines attached to this target are executed after everything
else is done.
@ -2001,6 +2132,15 @@ Disable parallel mode.
Synonym for
.Ic .NOTPARALLEL ,
for compatibility with other pmake variants.
.It Ic .OBJDIR
The source is a new value for
.Ql Va .OBJDIR .
If it exists,
.Nm
will
.Xr chdir 2
to it and update the value of
.Ql Va .OBJDIR .
.It Ic .ORDER
The named targets are made in sequence.
This ordering does not add targets to the list of targets to be made.
@ -2058,7 +2198,7 @@ The sources are a set of
pairs.
.Bl -tag -width hasErrCtls
.It Ar name
This is the minimal specification, used to select one of the builtin
This is the minimal specification, used to select one of the built-in
shell specs;
.Ar sh ,
.Ar ksh ,

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -89,6 +89,10 @@
# disable use of filemon(9) which is currently only
# available for NetBSD and FreeBSD.
#
# --with-filemon=ktrace
# on NetBSD or others with fktrace(2), use ktrace
# version of filemon.
#
# --with-filemon="path/to/filemon.h"
# enables use of filemon(9) by meta mode.
#
@ -111,7 +115,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
# $Id: boot-strap,v 1.1.1.11 2015/05/19 21:36:43 joerg Exp $
# $Id: boot-strap,v 1.1.1.12 2020/05/24 05:35:51 nia Exp $
#
# @(#) Copyright (c) 2001 Simon J. Gerraty
#
@ -161,6 +165,8 @@ cmd_args="$@"
# clear some things from the environment that we care about
unset MAKEOBJDIR MAKEOBJDIRPREFIX
# or that might be incompatible
unset MAKE MAKEFLAGS
# --install[-host-target] will set this
INSTALL_PREFIX=
@ -395,8 +401,15 @@ Bmake() {
)
}
# there is actually a shell where type is not a builtin
# if type is missing, which(1) had better exists!
if (type cat) > /dev/null 2>&1; then
which() {
type "$@" | sed 's,[()],,g;s,^[^/][^/]*,,;q'
}
fi
# make sure test below uses the same diff that configure did
TOOL_DIFF=`type diff | sed 's,[()],,g;s,^[^/][^/]*,,;q'`
TOOL_DIFF=`which diff`
export TOOL_DIFF
op_configure() {
@ -444,7 +457,7 @@ op_all() {
op_install
else
op_test
MAKE_VERSION=`sed -n '/^MAKE_VERSION/ { s,.*= *,,;p; }' $srcdir/Makefile`
MAKE_VERSION=`sed -n '/^_MAKE_VERSION/ { s,.*= *,,;p; }' $srcdir/Makefile`
echo You can install by running:
echo
echo $0 $cmd_args op=install

View File

@ -1,4 +1,4 @@
# $Id: bsd.after-import.mk,v 1.1.1.1 2015/05/19 21:36:43 joerg Exp $
# $Id: bsd.after-import.mk,v 1.1.1.2 2020/05/24 05:35:51 nia Exp $
# This makefile is for use when integrating bmake into a BSD build
# system. Use this makefile after importing bmake.
@ -56,13 +56,14 @@ bootstrap: ${BMAKE_SRC}/boot-strap ${MAKEFILE}
# Makefiles need a little more tweaking than say config.h
MAKEFILE_SED = sed -e '/^MACHINE/d' \
-e '/include.*VERSION/d' \
-e '/^PROG/ { s,=,?=,;s,bmake,$${.CURDIR:T},; }' \
-e 's,^.-include,.sinclude,' \
-e '/^\..*include *</ { s,<,<bsd.,;/autoconf/d; }' \
-e 's,${SRCTOP},$${SRCTOP},g'
# These are the simple files we want to capture
configured_files= config.h Makefile.config unit-tests/Makefile
configured_files= config.h Makefile.config unit-tests/Makefile.config
after-import: bootstrap ${MAKEFILE}
.for f in ${configured_files:M*.[ch]}
@ -86,7 +87,6 @@ _makefile: bootstrap ${MAKEFILE}
@(echo '# This is a generated file, do NOT edit!'; \
echo '# See ${_this:S,${SRCTOP}/,,}'; \
echo '#'; echo '# $$${HOST_OS}$$'; \
echo; echo '.sinclude "Makefile.inc"'; \
echo; echo 'SRCTOP?= $${.CURDIR:${.CURDIR:S,${SRCTOP}/,,:C,[^/]+,H,g:S,/,:,g}}'; \
echo; echo '# look here first for config.h'; \
echo 'CFLAGS+= -I$${.CURDIR}'; echo; \

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.h,v 1.1.1.5 2015/05/19 21:36:43 joerg Exp $ */
/* $NetBSD: buf.h,v 1.1.1.6 2020/05/24 05:35:51 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -77,8 +77,8 @@
* Header for users of the buf library.
*/
#ifndef _BUF_H
#define _BUF_H
#ifndef MAKE_BUF_H
#define MAKE_BUF_H
typedef char Byte;
@ -116,4 +116,4 @@ void Buf_Init(Buffer *, int);
Byte *Buf_Destroy(Buffer *, Boolean);
Byte *Buf_DestroyCompact(Buffer *);
#endif /* _BUF_H */
#endif /* MAKE_BUF_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: compat.c,v 1.1.1.9 2015/05/19 21:36:43 joerg Exp $ */
/* $NetBSD: compat.c,v 1.1.1.10 2020/05/24 05:35:51 nia 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.1.1.9 2015/05/19 21:36:43 joerg Exp $";
static char rcsid[] = "$NetBSD: compat.c,v 1.1.1.10 2020/05/24 05:35:51 nia Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: compat.c,v 1.1.1.9 2015/05/19 21:36:43 joerg Exp $");
__RCSID("$NetBSD: compat.c,v 1.1.1.10 2020/05/24 05:35:51 nia Exp $");
#endif
#endif /* not lint */
#endif
@ -111,35 +111,33 @@ __RCSID("$NetBSD: compat.c,v 1.1.1.9 2015/05/19 21:36:43 joerg Exp $");
#include "hash.h"
#include "dir.h"
#include "job.h"
#include "metachar.h"
#include "pathnames.h"
/*
* The following array is used to make a fast determination of which
* characters are interpreted specially by the shell. If a command
* contains any of these characters, it is executed by the shell, not
* directly by us.
*/
static char meta[256];
static GNode *curTarg = NULL;
static GNode *ENDNode;
static void CompatInterrupt(int);
static pid_t compatChild;
static int compatSigno;
/*
* CompatDeleteTarget -- delete a failed, interrupted, or otherwise
* duffed target if not inhibited by .PRECIOUS.
*/
static void
Compat_Init(void)
CompatDeleteTarget(GNode *gn)
{
const char *cp;
if ((gn != NULL) && !Targ_Precious (gn)) {
char *p1;
char *file = Var_Value(TARGET, gn, &p1);
Shell_Init(); /* setup default shell */
for (cp = "~#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++) {
meta[(unsigned char) *cp] = 1;
if (!noExecute && eunlink(file) != -1) {
Error("*** %s removed", file);
}
free(p1);
}
/*
* The null character serves as a sentinel in the string.
*/
meta[0] = 1;
}
/*-
@ -155,6 +153,9 @@ Compat_Init(void)
* The target is removed and the process exits. If .INTERRUPT exists,
* its commands are run first WITH INTERRUPTS IGNORED..
*
* XXX: is .PRECIOUS supposed to inhibit .INTERRUPT? I doubt it, but I've
* left the logic alone for now. - dholland 20160826
*
*-----------------------------------------------------------------------
*/
static void
@ -162,16 +163,9 @@ CompatInterrupt(int signo)
{
GNode *gn;
CompatDeleteTarget(curTarg);
if ((curTarg != NULL) && !Targ_Precious (curTarg)) {
char *p1;
char *file = Var_Value(TARGET, curTarg, &p1);
if (!noExecute && eunlink(file) != -1) {
Error("*** %s removed", file);
}
if (p1)
free(p1);
/*
* Run .INTERRUPT only if hit with interrupt signal
*/
@ -181,12 +175,20 @@ CompatInterrupt(int signo)
Compat_Make(gn, gn);
}
}
}
if (signo == SIGQUIT)
_exit(signo);
bmake_signal(signo, SIG_DFL);
kill(myPid, signo);
/*
* If there is a child running, pass the signal on
* we will exist after it has exited.
*/
compatSigno = signo;
if (compatChild > 0) {
KILLPG(compatChild, signo);
} else {
bmake_signal(signo, SIG_DFL);
kill(myPid, signo);
}
}
/*-
@ -236,7 +238,7 @@ CompatRunCommand(void *cmdp, void *gnp)
doIt = FALSE;
cmdNode = Lst_Member(gn->commands, cmd);
cmdStart = Var_Subst(NULL, cmd, gn, FALSE);
cmdStart = Var_Subst(NULL, cmd, gn, VARF_WANTRES);
/*
* brk_string will return an argv with a NULL in av[0], thus causing
@ -271,8 +273,8 @@ CompatRunCommand(void *cmdp, void *gnp)
break;
case '+':
doIt = TRUE;
if (!meta[0]) /* we came here from jobs */
Compat_Init();
if (!shellName) /* we came here from jobs */
Shell_Init();
break;
}
cmd++;
@ -300,11 +302,13 @@ CompatRunCommand(void *cmdp, void *gnp)
* Search for meta characters in the command. If there are no meta
* characters, there's no need to execute a shell to execute the
* command.
*
* Additionally variable assignments and empty commands
* go to the shell. Therefore treat '=' and ':' like shell
* meta characters as documented in make(1).
*/
for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {
continue;
}
useShell = (*cp != '\0');
useShell = needshell(cmd, FALSE);
#endif
/*
@ -377,7 +381,7 @@ again:
/*
* Fork and execute the single command. If the fork fails, we abort.
*/
cpid = vFork();
compatChild = cpid = vFork();
if (cpid < 0) {
Fatal("Could not fork");
}
@ -395,15 +399,15 @@ again:
execError("exec", av[0]);
_exit(1);
}
if (mav)
free(mav);
if (bp)
free(bp);
free(mav);
free(bp);
Lst_Replace(cmdNode, NULL);
#ifdef USE_META
if (useMeta) {
meta_compat_parent();
meta_compat_parent(cpid);
}
#endif
@ -468,6 +472,11 @@ again:
* continue.
*/
printf(" (continuing)\n");
} else {
printf("\n");
}
if (deleteOnError) {
CompatDeleteTarget(gn);
}
} else {
/*
@ -485,7 +494,12 @@ again:
}
}
free(cmdStart);
compatChild = 0;
if (compatSigno) {
bmake_signal(compatSigno, SIG_DFL);
kill(myPid, compatSigno);
}
return (status);
}
@ -512,8 +526,8 @@ Compat_Make(void *gnp, void *pgnp)
GNode *gn = (GNode *)gnp;
GNode *pgn = (GNode *)pgnp;
if (!meta[0]) /* we came here from jobs */
Compat_Init();
if (!shellName) /* we came here from jobs */
Shell_Init();
if (gn->made == UNMADE && (gn == pgn || (pgn->type & OP_MADE) == 0)) {
/*
* First mark ourselves to be made, then apply whatever transformations
@ -537,8 +551,7 @@ Compat_Make(void *gnp, void *pgnp)
if (Lst_Member(gn->iParents, pgn) != NULL) {
char *p1;
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn, 0);
if (p1)
free(p1);
free(p1);
}
/*
@ -608,7 +621,8 @@ Compat_Make(void *gnp, void *pgnp)
}
#ifdef USE_META
if (useMeta && !NoExecute(gn)) {
meta_job_finish(NULL);
if (meta_job_finish(NULL) != 0)
gn->made = ERROR;
}
#endif
@ -628,7 +642,7 @@ Compat_Make(void *gnp, void *pgnp)
} else if (keepgoing) {
pgn->flags &= ~REMAKE;
} else {
PrintOnError(gn, "\n\nStop.");
PrintOnError(gn, "\nStop.");
exit(1);
}
} else if (gn->made == ERROR) {
@ -641,8 +655,7 @@ Compat_Make(void *gnp, void *pgnp)
if (Lst_Member(gn->iParents, pgn) != NULL) {
char *p1;
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn, 0);
if (p1)
free(p1);
free(p1);
}
switch(gn->made) {
case BEINGMADE:
@ -693,7 +706,8 @@ Compat_Run(Lst targs)
GNode *gn = NULL;/* Current root target */
int errors; /* Number of targets not remade due to errors */
Compat_Init();
if (!shellName)
Shell_Init();
if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN) {
bmake_signal(SIGINT, CompatInterrupt);
@ -719,7 +733,7 @@ Compat_Run(Lst targs)
if (gn != NULL) {
Compat_Make(gn, gn);
if (gn->made == ERROR) {
PrintOnError(gn, "\n\nStop.");
PrintOnError(gn, "\nStop.");
exit(1);
}
}
@ -760,7 +774,7 @@ Compat_Run(Lst targs)
if (errors == 0) {
Compat_Make(ENDNode, ENDNode);
if (gn->made == ERROR) {
PrintOnError(gn, "\n\nStop.");
PrintOnError(gn, "\nStop.");
exit(1);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cond.c,v 1.1.1.8 2015/05/19 21:36:43 joerg Exp $ */
/* $NetBSD: cond.c,v 1.1.1.9 2020/05/24 05:35:51 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: cond.c,v 1.1.1.8 2015/05/19 21:36:43 joerg Exp $";
static char rcsid[] = "$NetBSD: cond.c,v 1.1.1.9 2020/05/24 05:35:51 nia Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94";
#else
__RCSID("$NetBSD: cond.c,v 1.1.1.8 2015/05/19 21:36:43 joerg Exp $");
__RCSID("$NetBSD: cond.c,v 1.1.1.9 2020/05/24 05:35:51 nia Exp $");
#endif
#endif /* not lint */
#endif
@ -91,6 +91,7 @@ __RCSID("$NetBSD: cond.c,v 1.1.1.8 2015/05/19 21:36:43 joerg Exp $");
*
*/
#include <assert.h>
#include <ctype.h>
#include <errno.h> /* For strtoul() error checking */
@ -289,10 +290,10 @@ CondGetArg(char **linePtr, char **argPtr, const char *func)
int len;
void *freeIt;
cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &freeIt);
cp2 = Var_Parse(cp, VAR_CMD, VARF_UNDEFERR|VARF_WANTRES,
&len, &freeIt);
Buf_AddBytes(&buf, strlen(cp2), cp2);
if (freeIt)
free(freeIt);
free(freeIt);
cp += len;
continue;
}
@ -346,8 +347,8 @@ CondDoDefined(int argLen MAKE_ATTR_UNUSED, const char *arg)
} else {
result = FALSE;
}
if (p1)
free(p1);
free(p1);
return (result);
}
@ -490,6 +491,10 @@ CondCvtArg(char *str, double *value)
double d_val;
errno = 0;
if (!*str) {
*value = (double)0;
return TRUE;
}
l_val = strtoul(str, &eptr, str[1] == 'x' ? 16 : 10);
ech = *eptr;
if (ech == 0 && errno != ERANGE) {
@ -570,8 +575,9 @@ CondGetString(Boolean doEval, Boolean *quoted, void **freeIt, Boolean strictLHS)
break;
case '$':
/* if we are in quotes, then an undefined variable is ok */
str = Var_Parse(condExpr, VAR_CMD, (qt ? 0 : doEval),
&len, freeIt);
str = Var_Parse(condExpr, VAR_CMD,
((!qt && doEval) ? VARF_UNDEFERR : 0) |
VARF_WANTRES, &len, freeIt);
if (str == var_Error) {
if (*freeIt) {
free(*freeIt);
@ -801,10 +807,8 @@ do_string_compare:
}
done:
if (lhsFree)
free(lhsFree);
if (rhsFree)
free(rhsFree);
free(lhsFree);
free(rhsFree);
return t;
}
@ -823,7 +827,7 @@ get_mpt_arg(char **linePtr, char **argPtr, const char *func MAKE_ATTR_UNUSED)
/* We do all the work here and return the result as the length */
*argPtr = NULL;
val = Var_Parse(cp - 1, VAR_CMD, FALSE, &length, &freeIt);
val = Var_Parse(cp - 1, VAR_CMD, VARF_WANTRES, &length, &freeIt);
/*
* Advance *linePtr to beyond the closing ). Note that
* we subtract one because 'length' is calculated from 'cp - 1'.
@ -844,8 +848,7 @@ get_mpt_arg(char **linePtr, char **argPtr, const char *func MAKE_ATTR_UNUSED)
* true/false here.
*/
length = *val ? 2 : 1;
if (freeIt)
free(freeIt);
free(freeIt);
return length;
}
@ -896,8 +899,7 @@ compare_function(Boolean doEval)
}
/* Evaluate the argument using the required function. */
t = !doEval || fn_def->fn_proc(arglen, arg);
if (arg)
free(arg);
free(arg);
condExpr = cp;
return t;
}
@ -929,8 +931,7 @@ compare_function(Boolean doEval)
* be empty - even if it contained a variable expansion.
*/
t = !doEval || if_info->defProc(arglen, arg) != if_info->doNot;
if (arg)
free(arg);
free(arg);
return t;
}
@ -1174,8 +1175,9 @@ Cond_EvalExpression(const struct If *info, char *line, Boolean *value, int eprin
break;
dflt_info = info;
}
assert(info != NULL);
if_info = info != NULL ? info : ifs + 4;
if_info = info;
condExpr = line;
condPushBack = TOK_NONE;

View File

@ -59,6 +59,12 @@
/* Define to 1 if you have the `killpg' function. */
#undef HAVE_KILLPG
/* Define to 1 if you have the <libgen.h> header file. */
#undef HAVE_LIBGEN_H
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
@ -137,7 +143,7 @@
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if `struct stat' is a member of `st_rdev'. */
/* Define to 1 if `st_rdev' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_RDEV
/* Define to 1 if your `struct stat' has `st_rdev'. Deprecated, use
@ -158,6 +164,9 @@
*/
#undef HAVE_SYS_NDIR_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
@ -304,12 +313,20 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT32_T
/* C99 function name */
#undef __func__
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t
/* Define to `long int' if <sys/types.h> does not define. */
#undef off_t
@ -319,5 +336,9 @@
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#undef uint32_t
/* Define as `fork' if `vfork' does not work. */
#undef vfork

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
dnl
dnl RCSid:
dnl $Id: configure.in,v 1.1.1.7 2015/05/19 21:36:43 joerg Exp $
dnl $Id: configure.in,v 1.1.1.8 2020/05/24 05:35:51 nia Exp $
dnl
dnl Process this file with autoconf to produce a configure script
dnl
AC_PREREQ(2.50)
AC_INIT([bmake], [20140214], [sjg@NetBSD.org])
AC_INIT([bmake], [20200418], [sjg@NetBSD.org])
AC_CONFIG_HEADERS(config.h)
dnl make srcdir absolute
@ -14,6 +14,10 @@ case "$srcdir" in
*) srcdir=`cd $srcdir && pwd`;;
esac
dnl get _MAKE_VERSION
. $srcdir/VERSION
OS=`uname -s`
dnl
AC_ARG_WITH(defshell,
[ --with-defshell=SHELL use SHELL by default - must be sh compatible, use sh or ksh to pick the internal definitions],
@ -29,6 +33,17 @@ no) ;;
;;
esac])
dnl
case "$OS" in
CYGWIN*|MINGW*) use_makefile=no;;
*) use_makefile=yes;;
esac
AC_ARG_WITH(makefile,
[ --without-makefile dissable use of generated makefile],
[case "${withval}" in
yes|no) use_makefile=${withval};;
*) AC_MSG_ERROR(bad value ${withval} given for makefile) ;;
esac])
dnl
use_meta=yes
AC_ARG_WITH(meta,
[ --without-meta dissable use of meta-mode],
@ -38,30 +53,41 @@ yes|no) use_meta=${withval};;
esac])
dnl
AC_ARG_WITH(filemon,
[ --with-filemon=path/filemon.h indicate path to filemon.h for meta-mode],
[ --with-filemon={no,dev,ktrace,path/filemon.h} indicate filemon method for meta-mode. Path to filemon.h implies dev],
[ case "/${withval}" in
/no|*/filemon.h) filemon_h="${withval}";;
/no) use_filemon=no;;
/*trace) filemon_h=no use_filemon="${withval}";;
*/filemon.h) filemon_h="${withval}";;
*/filemon*) filemon_h="${withval}/filemon.h";;
*) AC_MSG_ERROR(bad value ${withval} given for filemon) ;;
esac],
[
OS=`uname -s`
for d in "/usr/include/dev/filemon" "$prefix/include/dev/filemon" "$srcdir/filemon" "$srcdir/../filemon" "$srcdir/../../sys/dev/filemon"
do
for x in "/$OS" ""
do
filemon_h="$d$x/filemon.h"
test -s "$filemon_h" && break
done
test -s "$filemon_h" && break
done
test -s "${filemon_h:-/dev/null}" || filemon_h=no
case "$OS" in
NetBSD) filemon_h=no use_filemon=ktrace;;
*)
for d in "/usr/include/dev/filemon" "$prefix/include/dev/filemon" "$srcdir/../../sys/dev/filemon"
do
for x in "/$OS" ""
do
filemon_h="$d$x/filemon.h"
test -s "$filemon_h" && break
done
test -s "$filemon_h" && { use_filemon=dev; break; }
done
;;
esac
use_filemon=${use_filemon:-no}
case "$use_filemon" in
dev) ;;
*) filemon_h=no;;
esac
])
dnl echo "Note: use_meta=$use_meta filemon_h=$filemon_h" >&6
dnl echo "Note: use_meta=$use_meta use_filemon=$use_filemon filemon_h=$filemon_h" >&6
case "$use_meta" in
yes)
case "$filemon_h" in
*.h) echo "Using: filemon=$filemon_h" >&6;;
case "$use_filemon" in
no) ;;
*) echo "Using: filemon_${use_filemon}.c" >&6;;
esac
;;
esac
@ -101,10 +127,20 @@ AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_HEADER_DIRENT
dnl Keep this list sorted
AC_CHECK_HEADERS(sys/param.h)
dnl On BSDi at least we really need sys/param.h for sys/sysctl.h
AC_CHECK_HEADERS([sys/sysctl.h], [], [],
[#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
# endif
])
AC_CHECK_HEADERS( \
ar.h \
err.h \
fcntl.h \
libgen.h \
limits.h \
paths.h \
poll.h \
ranlib.h \
@ -112,7 +148,6 @@ AC_CHECK_HEADERS( \
sys/mman.h \
sys/select.h \
sys/socket.h \
sys/sysctl.h \
sys/time.h \
sys/uio.h \
unistd.h \
@ -139,9 +174,11 @@ dnl Checks for typedefs, structures, and compiler characteristics.
AC_C___ATTRIBUTE__
AC_C_BIGENDIAN
AC_C_CONST
AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_UINT32_T
AC_DECL_SYS_SIGLIST
AC_HEADER_TIME
AC_STRUCT_TM
@ -374,9 +411,14 @@ AC_SUBST(INSTALL)
AC_SUBST(GCC)
AC_SUBST(diff_u)
AC_SUBST(use_meta)
AC_SUBST(use_filemon)
AC_SUBST(filemon_h)
AC_OUTPUT(makefile Makefile.config make-bootstrap.sh unit-tests/Makefile)
AC_SUBST(_MAKE_VERSION)
bm_outfiles="Makefile.config unit-tests/Makefile.config make-bootstrap.sh"
if test $use_makefile = yes; then
bm_outfiles="makefile $bm_outfiles"
fi
AC_OUTPUT($bm_outfiles)
cat <<EOF
You can now run

View File

@ -1,4 +1,4 @@
/* $NetBSD: dir.c,v 1.1.1.7 2015/05/19 21:36:43 joerg Exp $ */
/* $NetBSD: dir.c,v 1.1.1.8 2020/05/24 05:35:52 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: dir.c,v 1.1.1.7 2015/05/19 21:36:43 joerg Exp $";
static char rcsid[] = "$NetBSD: dir.c,v 1.1.1.8 2020/05/24 05:35:52 nia Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94";
#else
__RCSID("$NetBSD: dir.c,v 1.1.1.7 2015/05/19 21:36:43 joerg Exp $");
__RCSID("$NetBSD: dir.c,v 1.1.1.8 2020/05/24 05:35:52 nia Exp $");
#endif
#endif /* not lint */
#endif
@ -244,6 +244,7 @@ static Hash_Table mtimes; /* Results of doing a last-resort stat in
* be two rules to update a single file, so this
* should be ok, but... */
static Hash_Table lmtimes; /* same as mtimes but for lstat */
static int DirFindName(const void *, const void *);
static int DirMatchFiles(const char *, Path *, Lst);
@ -256,6 +257,79 @@ static char *DirLookupSubdir(Path *, const char *);
static char *DirFindDot(Boolean, const char *, const char *);
static char *DirLookupAbs(Path *, const char *, const char *);
/*
* We use stat(2) a lot, cache the results
* mtime and mode are all we care about.
*/
struct cache_st {
time_t mtime;
mode_t mode;
};
/* minimize changes below */
#define CST_LSTAT 1
#define CST_UPDATE 2
static int
cached_stats(Hash_Table *htp, const char *pathname, struct stat *st, int flags)
{
Hash_Entry *entry;
struct cache_st *cst;
int rc;
if (!pathname || !pathname[0])
return -1;
entry = Hash_FindEntry(htp, pathname);
if (entry && (flags & CST_UPDATE) == 0) {
cst = entry->clientPtr;
memset(st, 0, sizeof(*st));
st->st_mtime = cst->mtime;
st->st_mode = cst->mode;
if (DEBUG(DIR)) {
fprintf(debug_file, "Using cached time %s for %s\n",
Targ_FmtTime(st->st_mtime), pathname);
}
return 0;
}
rc = (flags & CST_LSTAT) ? lstat(pathname, st) : stat(pathname, st);
if (rc == -1)
return -1;
if (st->st_mtime == 0)
st->st_mtime = 1; /* avoid confusion with missing file */
if (!entry)
entry = Hash_CreateEntry(htp, pathname, NULL);
if (!entry->clientPtr)
entry->clientPtr = bmake_malloc(sizeof(*cst));
cst = entry->clientPtr;
cst->mtime = st->st_mtime;
cst->mode = st->st_mode;
if (DEBUG(DIR)) {
fprintf(debug_file, " Caching %s for %s\n",
Targ_FmtTime(st->st_mtime), pathname);
}
return 0;
}
int
cached_stat(const char *pathname, void *st)
{
return cached_stats(&mtimes, pathname, st, 0);
}
int
cached_lstat(const char *pathname, void *st)
{
return cached_stats(&lmtimes, pathname, st, CST_LSTAT);
}
/*-
*-----------------------------------------------------------------------
* Dir_Init --
@ -271,10 +345,13 @@ static char *DirLookupAbs(Path *, const char *, const char *);
void
Dir_Init(const char *cdname)
{
dirSearchPath = Lst_Init(FALSE);
openDirectories = Lst_Init(FALSE);
Hash_InitTable(&mtimes, 0);
if (!cdname) {
dirSearchPath = Lst_Init(FALSE);
openDirectories = Lst_Init(FALSE);
Hash_InitTable(&mtimes, 0);
Hash_InitTable(&lmtimes, 0);
return;
}
Dir_InitCur(cdname);
dotLast = bmake_malloc(sizeof(Path));
@ -725,11 +802,11 @@ DirExpandInt(const char *word, Lst path, Lst expansions)
*-----------------------------------------------------------------------
*/
static int
DirPrintWord(void *word, void *dummy)
DirPrintWord(void *word, void *dummy MAKE_ATTR_UNUSED)
{
fprintf(debug_file, "%s ", (char *)word);
return(dummy ? 0 : 0);
return 0;
}
/*-
@ -901,7 +978,6 @@ static char *
DirLookupSubdir(Path *p, const char *name)
{
struct stat stb; /* Buffer for stat, if necessary */
Hash_Entry *entry; /* Entry for mtimes table */
char *file; /* the current filename to check */
if (p != dot) {
@ -917,19 +993,7 @@ DirLookupSubdir(Path *p, const char *name)
fprintf(debug_file, "checking %s ...\n", file);
}
if (stat(file, &stb) == 0) {
if (stb.st_mtime == 0)
stb.st_mtime = 1;
/*
* Save the modification time so if it's needed, we don't have
* to fetch it again.
*/
if (DEBUG(DIR)) {
fprintf(debug_file, " Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
file);
}
entry = Hash_CreateEntry(&mtimes, file, NULL);
Hash_SetTimeValue(entry, stb.st_mtime);
if (cached_stat(file, &stb) == 0) {
nearmisses += 1;
return (file);
}
@ -1061,7 +1125,6 @@ Dir_FindFile(const char *name, Lst path)
Boolean hasLastDot = FALSE; /* true we should search dot last */
Boolean hasSlash; /* true if 'name' contains a / */
struct stat stb; /* Buffer for stat, if necessary */
Hash_Entry *entry; /* Entry for mtimes table */
const char *trailing_dot = ".";
/*
@ -1242,8 +1305,14 @@ Dir_FindFile(const char *name, Lst path)
fprintf(debug_file, " Trying exact path matches...\n");
}
if (!hasLastDot && cur && (file = DirLookupAbs(cur, name, cp)) != NULL)
return *file?file:NULL;
if (!hasLastDot && cur && ((file = DirLookupAbs(cur, name, cp))
!= NULL)) {
if (file[0] == '\0') {
free(file);
return NULL;
}
return file;
}
(void)Lst_Open(path);
while ((ln = Lst_Next(path)) != NULL) {
@ -1252,13 +1321,23 @@ Dir_FindFile(const char *name, Lst path)
continue;
if ((file = DirLookupAbs(p, name, cp)) != NULL) {
Lst_Close(path);
return *file?file:NULL;
if (file[0] == '\0') {
free(file);
return NULL;
}
return file;
}
}
Lst_Close(path);
if (hasLastDot && cur && (file = DirLookupAbs(cur, name, cp)) != NULL)
return *file?file:NULL;
if (hasLastDot && cur && ((file = DirLookupAbs(cur, name, cp))
!= NULL)) {
if (file[0] == '\0') {
free(file);
return NULL;
}
return file;
}
}
/*
@ -1306,28 +1385,14 @@ Dir_FindFile(const char *name, Lst path)
}
bigmisses += 1;
entry = Hash_FindEntry(&mtimes, name);
if (entry != NULL) {
if (DEBUG(DIR)) {
fprintf(debug_file, " got it (in mtime cache)\n");
}
return(bmake_strdup(name));
} else if (stat(name, &stb) == 0) {
if (stb.st_mtime == 0)
stb.st_mtime = 1;
entry = Hash_CreateEntry(&mtimes, name, NULL);
if (DEBUG(DIR)) {
fprintf(debug_file, " Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
name);
}
Hash_SetTimeValue(entry, stb.st_mtime);
if (cached_stat(name, &stb) == 0) {
return (bmake_strdup(name));
} else {
if (DEBUG(DIR)) {
fprintf(debug_file, " failed. Returning NULL\n");
}
return NULL;
}
if (DEBUG(DIR)) {
fprintf(debug_file, " failed. Returning NULL\n");
}
return NULL;
#endif /* notdef */
}
@ -1368,7 +1433,7 @@ Dir_FindHereOrAbove(char *here, char *search_path, char *result, int rlen) {
/* try and stat(2) it ... */
snprintf(try, sizeof(try), "%s/%s", dirbase, search_path);
if (stat(try, &st) != -1) {
if (cached_stat(try, &st) != -1) {
/*
* success! if we found a file, chop off
* the filename so we return a directory.
@ -1433,7 +1498,6 @@ Dir_MTime(GNode *gn, Boolean recheck)
{
char *fullName; /* the full pathname of name */
struct stat stb; /* buffer for finding the mod time */
Hash_Entry *entry;
if (gn->type & OP_ARCHV) {
return Arch_MTime(gn);
@ -1484,17 +1548,7 @@ Dir_MTime(GNode *gn, Boolean recheck)
fullName = bmake_strdup(gn->name);
}
if (!recheck)
entry = Hash_FindEntry(&mtimes, fullName);
else
entry = NULL;
if (entry != NULL) {
if (DEBUG(DIR)) {
fprintf(debug_file, "Using cached time %s for %s\n",
Targ_FmtTime(Hash_GetTimeValue(entry)), fullName);
}
stb.st_mtime = Hash_GetTimeValue(entry);
} else if (stat(fullName, &stb) < 0) {
if (cached_stats(&mtimes, fullName, &stb, recheck ? CST_UPDATE : 0) < 0) {
if (gn->type & OP_MEMBER) {
if (fullName != gn->path)
free(fullName);
@ -1502,18 +1556,8 @@ Dir_MTime(GNode *gn, Boolean recheck)
} else {
stb.st_mtime = 0;
}
} else {
if (stb.st_mtime == 0) {
/*
* 0 handled specially by the code, if the time is really 0,
* return something else instead
*/
stb.st_mtime = 1;
}
entry = Hash_CreateEntry(&mtimes, fullName, NULL);
Hash_SetTimeValue(entry, stb.st_mtime);
}
if (fullName && gn->path == NULL) {
gn->path = fullName;
}
@ -1792,10 +1836,10 @@ Dir_PrintDirectories(void)
}
static int
DirPrintDir(void *p, void *dummy)
DirPrintDir(void *p, void *dummy MAKE_ATTR_UNUSED)
{
fprintf(debug_file, "%s ", ((Path *)p)->name);
return (dummy ? 0 : 0);
return 0;
}
void

View File

@ -1,4 +1,4 @@
/* $NetBSD: dir.h,v 1.1.1.5 2015/05/19 21:36:44 joerg Exp $ */
/* $NetBSD: dir.h,v 1.1.1.6 2020/05/24 05:35:52 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -75,8 +75,8 @@
/* dir.h --
*/
#ifndef _DIR
#define _DIR
#ifndef MAKE_DIR_H
#define MAKE_DIR_H
typedef struct Path {
char *name; /* Name of directory */
@ -105,4 +105,4 @@ void Dir_PrintPath(Lst);
void Dir_Destroy(void *);
void * Dir_CopyDir(void *);
#endif /* _DIR */
#endif /* MAKE_DIR_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: dirname.c,v 1.1.1.1 2011/06/18 22:17:55 bsiegert Exp $ */
/* $NetBSD: dirname.c,v 1.1.1.2 2020/05/24 05:35:52 nia Exp $ */
/*-
* Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
@ -35,7 +35,15 @@
#ifndef HAVE_DIRNAME
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: dirname.c,v 1.1.1.2 2020/05/24 05:35:52 nia Exp $");
#endif /* !LIBC_SCCS && !lint */
#include "namespace.h"
#include <sys/param.h>
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@ -45,51 +53,74 @@
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
#ifndef MIN
# define MIN(a, b) ((a < b) ? a : b)
#endif
char *
dirname(char *path)
static size_t
xdirname_r(const char *path, char *buf, size_t buflen)
{
static char result[PATH_MAX];
const char *lastp;
const char *endp;
size_t len;
/*
* If `path' is a null pointer or points to an empty string,
* return a pointer to the string ".".
*/
if ((path == NULL) || (*path == '\0'))
goto singledot;
if (path == NULL || *path == '\0') {
path = ".";
len = 1;
goto out;
}
/* Strip trailing slashes, if any. */
lastp = path + strlen(path) - 1;
while (lastp != path && *lastp == '/')
lastp--;
endp = path + strlen(path) - 1;
while (endp != path && *endp == '/')
endp--;
/* Terminate path at the last occurence of '/'. */
do {
if (*lastp == '/') {
/* Strip trailing slashes, if any. */
while (lastp != path && *lastp == '/')
lastp--;
/* Find the start of the dir */
while (endp > path && *endp != '/')
endp--;
/* ...and copy the result into the result buffer. */
len = (lastp - path) + 1 /* last char */;
if (len > (PATH_MAX - 1))
len = PATH_MAX - 1;
if (endp == path) {
path = *endp == '/' ? "/" : ".";
len = 1;
goto out;
}
memcpy(result, path, len);
result[len] = '\0';
do
endp--;
while (endp > path && *endp == '/');
return (result);
}
} while (--lastp >= path);
len = endp - path + 1;
out:
if (buf != NULL && buflen != 0) {
buflen = MIN(len, buflen - 1);
if (buf != path)
memcpy(buf, path, buflen);
buf[buflen] = '\0';
}
return len;
}
/* No /'s found, return a pointer to the string ".". */
singledot:
result[0] = '.';
result[1] = '\0';
char *
dirname(char *path)
{
static char result[PATH_MAX];
(void)xdirname_r(path, result, sizeof(result));
return result;
}
return (result);
#ifdef MAIN
#include <stdlib.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
printf("%s\n", dirname(argv[1]));
exit(0);
}
#endif
#endif

View File

@ -0,0 +1,53 @@
/* $NetBSD: filemon.h,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $ */
/*-
* Copyright (c) 2019 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Taylor R. Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FILEMON_H_
#define FILEMON_H_
#include <sys/types.h>
struct filemon;
const char *
filemon_path(void);
struct filemon *
filemon_open(void);
int filemon_close(struct filemon *);
int filemon_setfd(struct filemon *, int);
void filemon_setpid_parent(struct filemon *, pid_t);
int filemon_setpid_child(const struct filemon *, pid_t);
int filemon_readfd(const struct filemon *);
int filemon_process(struct filemon *);
#endif /* FILEMON_H_ */

View File

@ -0,0 +1,151 @@
/* $NetBSD: filemon_dev.c,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $ */
/*-
* Copyright (c) 2020 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Taylor R. Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "filemon.h"
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef HAVE_FILEMON_H
# include <filemon.h>
#endif
#ifndef _PATH_FILEMON
#define _PATH_FILEMON "/dev/filemon"
#endif
struct filemon {
int fd;
};
const char *
filemon_path(void)
{
return _PATH_FILEMON;
}
struct filemon *
filemon_open(void)
{
struct filemon *F;
unsigned i;
int error;
/* Allocate and zero a struct filemon object. */
F = calloc(1, sizeof(*F));
if (F == NULL)
return NULL;
/* Try opening /dev/filemon, up to six times (cargo cult!). */
for (i = 0; (F->fd = open(_PATH_FILEMON, O_RDWR)) == -1; i++) {
if (i == 5) {
error = errno;
goto fail0;
}
}
/* Success! */
return F;
fail0: free(F);
errno = error;
return NULL;
}
int
filemon_setfd(struct filemon *F, int fd)
{
/* Point the kernel at this file descriptor. */
if (ioctl(F->fd, FILEMON_SET_FD, &fd) == -1)
return -1;
/* No need for it in userland any more; close it. */
(void)close(fd);
/* Success! */
return 0;
}
void
filemon_setpid_parent(struct filemon *F, pid_t pid)
{
/* Nothing to do! */
}
int
filemon_setpid_child(const struct filemon *F, pid_t pid)
{
/* Just pass it on to the kernel. */
return ioctl(F->fd, FILEMON_SET_PID, &pid);
}
int
filemon_close(struct filemon *F)
{
int error = 0;
/* Close the filemon device fd. */
if (close(F->fd) == -1 && error == 0)
error = errno;
/* Free the filemon descriptor. */
free(F);
/* Set errno and return -1 if anything went wrong. */
if (error) {
errno = error;
return -1;
}
/* Success! */
return 0;
}
int
filemon_readfd(const struct filemon *F)
{
return -1;
}
int
filemon_process(struct filemon *F)
{
return 0;
}

View File

@ -0,0 +1,878 @@
/* $NetBSD: filemon_ktrace.c,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $ */
/*-
* Copyright (c) 2019 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Taylor R. Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define _KERNTYPES /* register_t */
#include "filemon.h"
#include <sys/param.h>
#include <sys/types.h>
#include <sys/rbtree.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <sys/ktrace.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef AT_CWD
#define AT_CWD -1
#endif
struct filemon;
struct filemon_key;
struct filemon_state;
typedef struct filemon_state *filemon_syscall_t(struct filemon *,
const struct filemon_key *, const struct ktr_syscall *);
static filemon_syscall_t filemon_sys_chdir;
static filemon_syscall_t filemon_sys_execve;
static filemon_syscall_t filemon_sys_exit;
static filemon_syscall_t filemon_sys_fork;
static filemon_syscall_t filemon_sys_link;
static filemon_syscall_t filemon_sys_open;
static filemon_syscall_t filemon_sys_openat;
static filemon_syscall_t filemon_sys_symlink;
static filemon_syscall_t filemon_sys_unlink;
static filemon_syscall_t filemon_sys_rename;
static filemon_syscall_t *const filemon_syscalls[] = {
[SYS_chdir] = &filemon_sys_chdir,
[SYS_execve] = &filemon_sys_execve,
[SYS_exit] = &filemon_sys_exit,
[SYS_fork] = &filemon_sys_fork,
[SYS_link] = &filemon_sys_link,
[SYS_open] = &filemon_sys_open,
[SYS_openat] = &filemon_sys_openat,
[SYS_symlink] = &filemon_sys_symlink,
[SYS_unlink] = &filemon_sys_unlink,
[SYS_rename] = &filemon_sys_rename,
};
struct filemon {
int ktrfd; /* kernel writes ktrace events here */
FILE *in; /* we read ktrace events from here */
FILE *out; /* we write filemon events to here */
rb_tree_t active;
pid_t child;
/* I/O state machine. */
enum {
FILEMON_START = 0,
FILEMON_HEADER,
FILEMON_PAYLOAD,
FILEMON_ERROR,
} state;
unsigned char *p;
size_t resid;
/* I/O buffer. */
struct ktr_header hdr;
union {
struct ktr_syscall syscall;
struct ktr_sysret sysret;
char namei[PATH_MAX];
unsigned char buf[4096];
} payload;
};
struct filemon_state {
struct filemon_key {
pid_t pid;
lwpid_t lid;
} key;
struct rb_node node;
int syscode;
void (*show)(struct filemon *, const struct filemon_state *,
const struct ktr_sysret *);
unsigned i;
unsigned npath;
char *path[/*npath*/];
};
static int
compare_filemon_states(void *cookie, const void *na, const void *nb)
{
const struct filemon_state *Sa = na;
const struct filemon_state *Sb = nb;
if (Sa->key.pid < Sb->key.pid)
return -1;
if (Sa->key.pid > Sb->key.pid)
return +1;
if (Sa->key.lid < Sb->key.lid)
return -1;
if (Sa->key.lid > Sb->key.lid)
return +1;
return 0;
}
static int
compare_filemon_key(void *cookie, const void *n, const void *k)
{
const struct filemon_state *S = n;
const struct filemon_key *key = k;
if (S->key.pid < key->pid)
return -1;
if (S->key.pid > key->pid)
return +1;
if (S->key.lid < key->lid)
return -1;
if (S->key.lid > key->lid)
return +1;
return 0;
}
static const rb_tree_ops_t filemon_rb_ops = {
.rbto_compare_nodes = &compare_filemon_states,
.rbto_compare_key = &compare_filemon_key,
.rbto_node_offset = offsetof(struct filemon_state, node),
.rbto_context = NULL,
};
/*
* filemon_path()
*
* Return a pointer to a constant string denoting the `path' of
* the filemon.
*/
const char *
filemon_path(void)
{
return "ktrace";
}
/*
* filemon_open()
*
* Allocate a filemon descriptor. Returns NULL and sets errno on
* failure.
*/
struct filemon *
filemon_open(void)
{
struct filemon *F;
int ktrpipe[2];
int error;
/* Allocate and zero a struct filemon object. */
F = calloc(1, sizeof(*F));
if (F == NULL)
return NULL;
/* Create a pipe for ktrace events. */
if (pipe2(ktrpipe, O_CLOEXEC|O_NONBLOCK) == -1) {
error = errno;
goto fail0;
}
/* Create a file stream for reading the ktrace events. */
if ((F->in = fdopen(ktrpipe[0], "r")) == NULL) {
error = errno;
goto fail1;
}
ktrpipe[0] = -1; /* claimed by fdopen */
/*
* Set the fd for writing ktrace events and initialize the
* rbtree. The rest can be safely initialized to zero.
*/
F->ktrfd = ktrpipe[1];
rb_tree_init(&F->active, &filemon_rb_ops);
/* Success! */
return F;
fail2: __unused
(void)fclose(F->in);
fail1: (void)close(ktrpipe[0]);
(void)close(ktrpipe[1]);
fail0: free(F);
errno = error;
return NULL;
}
/*
* filemon_closefd(F)
*
* Internal subroutine to try to flush and close the output file.
* If F is not open for output, do nothing. Never leaves F open
* for output even on failure. Returns 0 on success; sets errno
* and return -1 on failure.
*/
static int
filemon_closefd(struct filemon *F)
{
int error = 0;
/* If we're not open, nothing to do. */
if (F->out == NULL)
return 0;
/*
* Flush it, close it, and null it unconditionally, but be
* careful to return the earliest error in errno.
*/
if (fflush(F->out) == EOF && error == 0)
error = errno;
if (fclose(F->out) == EOF && error == 0)
error = errno;
F->out = NULL;
/* Set errno and return -1 if anything went wrong. */
if (error) {
errno = error;
return -1;
}
/* Success! */
return 0;
}
/*
* filemon_setfd(F, fd)
*
* Cause filemon activity on F to be sent to fd. Claims ownership
* of fd; caller should not use fd afterward, and any duplicates
* of fd may see their file positions changed.
*/
int
filemon_setfd(struct filemon *F, int fd)
{
/*
* Close an existing output file if done. Fail now if there's
* an error closing.
*/
if ((filemon_closefd(F)) == -1)
return -1;
assert(F->out == NULL);
/* Open a file stream and claim ownership of the fd. */
if ((F->out = fdopen(fd, "a")) == NULL)
return -1;
/*
* Print the opening output. Any failure will be deferred
* until closing. For hysterical raisins, we show the parent
* pid, not the child pid.
*/
fprintf(F->out, "# filemon version 4\n");
fprintf(F->out, "# Target pid %jd\n", (intmax_t)getpid());
fprintf(F->out, "V 4\n");
/* Success! */
return 0;
}
/*
* filemon_setpid_parent(F, pid)
*
* Set the traced pid, from the parent. Never fails.
*/
void
filemon_setpid_parent(struct filemon *F, pid_t pid)
{
F->child = pid;
}
/*
* filemon_setpid_child(F, pid)
*
* Set the traced pid, from the child. Returns 0 on success; sets
* errno and returns -1 on failure.
*/
int
filemon_setpid_child(const struct filemon *F, pid_t pid)
{
int ops, trpoints;
ops = KTROP_SET|KTRFLAG_DESCEND;
trpoints = KTRFACv2;
trpoints |= KTRFAC_SYSCALL|KTRFAC_NAMEI|KTRFAC_SYSRET;
trpoints |= KTRFAC_INHERIT;
if (fktrace(F->ktrfd, ops, trpoints, pid) == -1)
return -1;
return 0;
}
/*
* filemon_close(F)
*
* Close F for output if necessary, and free a filemon descriptor.
* Returns 0 on success; sets errno and returns -1 on failure, but
* frees the filemon descriptor either way;
*/
int
filemon_close(struct filemon *F)
{
struct filemon_state *S;
int error = 0;
/* Close for output. */
if (filemon_closefd(F) == -1 && error == 0)
error = errno;
/* Close the ktrace pipe. */
if (fclose(F->in) == EOF && error == 0)
error = errno;
if (close(F->ktrfd) == -1 && error == 0)
error = errno;
/* Free any active records. */
while ((S = RB_TREE_MIN(&F->active)) != NULL) {
rb_tree_remove_node(&F->active, S);
free(S);
}
/* Free the filemon descriptor. */
free(F);
/* Set errno and return -1 if anything went wrong. */
if (error) {
errno = error;
return -1;
}
/* Success! */
return 0;
}
/*
* filemon_readfd(F)
*
* Returns a file descriptor which will select/poll ready for read
* when there are filemon events to be processed by
* filemon_process, or -1 if anything has gone wrong.
*/
int
filemon_readfd(const struct filemon *F)
{
if (F->state == FILEMON_ERROR)
return -1;
return fileno(F->in);
}
/*
* filemon_dispatch(F)
*
* Internal subroutine to dispatch a filemon ktrace event.
* Silently ignore events that we don't recognize.
*/
static void
filemon_dispatch(struct filemon *F)
{
const struct filemon_key key = {
.pid = F->hdr.ktr_pid,
.lid = F->hdr.ktr_lid,
};
struct filemon_state *S;
switch (F->hdr.ktr_type) {
case KTR_SYSCALL: {
struct ktr_syscall *call = &F->payload.syscall;
struct filemon_state *S1;
/* Validate the syscall code. */
if (call->ktr_code < 0 ||
(size_t)call->ktr_code >= __arraycount(filemon_syscalls) ||
filemon_syscalls[call->ktr_code] == NULL)
break;
/*
* Invoke the syscall-specific logic to create a new
* active state.
*/
S = (*filemon_syscalls[call->ktr_code])(F, &key, call);
if (S == NULL)
break;
/*
* Insert the active state, or ignore it if there
* already is one.
*
* Collisions shouldn't happen because the states are
* keyed by <pid,lid>, in which syscalls should happen
* sequentially in CALL/RET pairs, but let's be
* defensive.
*/
S1 = rb_tree_insert_node(&F->active, S);
if (S1 != S) {
/* XXX Which one to drop? */
free(S);
break;
}
break;
}
case KTR_NAMEI:
/* Find an active syscall state, or drop it. */
S = rb_tree_find_node(&F->active, &key);
if (S == NULL)
break;
/* Find the position of the next path, or drop it. */
if (S->i >= S->npath)
break;
/* Record the path. */
S->path[S->i++] = strndup(F->payload.namei,
sizeof F->payload.namei);
break;
case KTR_SYSRET: {
struct ktr_sysret *ret = &F->payload.sysret;
unsigned i;
/* Find and remove an active syscall state, or drop it. */
S = rb_tree_find_node(&F->active, &key);
if (S == NULL)
break;
rb_tree_remove_node(&F->active, S);
/*
* If the active syscall state matches this return,
* invoke the syscall-specific logic to show a filemon
* event.
*/
/* XXX What to do if syscall code doesn't match? */
if (S->i == S->npath && S->syscode == ret->ktr_code)
(*S->show)(F, S, ret);
/* Free the state now that it is no longer active. */
for (i = 0; i < S->i; i++)
free(S->path[i]);
free(S);
break;
}
default:
/* Ignore all other ktrace events. */
break;
}
}
/*
* filemon_process(F)
*
* Process all pending events after filemon_readfd(F) has
* selected/polled ready for read.
*
* Returns -1 on failure, 0 on end of events, and anything else if
* there may be more events.
*
* XXX What about fairness to other activities in the event loop?
* If we stop while there's events buffered in F->in, then select
* or poll may not return ready even though there's work queued up
* in the buffer of F->in, but if we don't stop then ktrace events
* may overwhelm all other activity in the event loop.
*/
int
filemon_process(struct filemon *F)
{
size_t nread;
top: /* If the child has exited, nothing to do. */
/* XXX What if one thread calls exit while another is running? */
if (F->child == 0)
return 0;
/* If we're waiting for input, read some. */
if (F->resid) {
nread = fread(F->p, 1, F->resid, F->in);
if (nread == 0) {
if (feof(F->in))
return 0;
assert(ferror(F->in));
/*
* If interrupted or would block, there may be
* more events. Otherwise fail.
*/
if (errno == EAGAIN || errno == EINTR)
return 1;
F->state = FILEMON_ERROR;
F->p = NULL;
F->resid = 0;
return -1;
}
assert(nread <= F->resid);
F->p += nread;
F->resid -= nread;
if (F->resid) /* may be more events */
return 1;
}
/* Process a state transition now that we've read a buffer. */
switch (F->state) {
case FILEMON_START: /* just started filemon; read header next */
F->state = FILEMON_HEADER;
F->p = (void *)&F->hdr;
F->resid = sizeof F->hdr;
goto top;
case FILEMON_HEADER: /* read header */
/* Sanity-check ktrace header; then read payload. */
if (F->hdr.ktr_len < 0 ||
(size_t)F->hdr.ktr_len > sizeof F->payload) {
F->state = FILEMON_ERROR;
F->p = NULL;
F->resid = 0;
errno = EIO;
return -1;
}
F->state = FILEMON_PAYLOAD;
F->p = (void *)&F->payload;
F->resid = (size_t)F->hdr.ktr_len;
goto top;
case FILEMON_PAYLOAD: /* read header and payload */
/* Dispatch ktrace event; then read next header. */
filemon_dispatch(F);
F->state = FILEMON_HEADER;
F->p = (void *)&F->hdr;
F->resid = sizeof F->hdr;
goto top;
default: /* paranoia */
F->state = FILEMON_ERROR;
/*FALLTHROUGH*/
case FILEMON_ERROR: /* persistent error indicator */
F->p = NULL;
F->resid = 0;
errno = EIO;
return -1;
}
}
static struct filemon_state *
syscall_enter(struct filemon *F,
const struct filemon_key *key, const struct ktr_syscall *call,
unsigned npath,
void (*show)(struct filemon *, const struct filemon_state *,
const struct ktr_sysret *))
{
struct filemon_state *S;
unsigned i;
S = calloc(1, offsetof(struct filemon_state, path[npath]));
if (S == NULL)
return NULL;
S->key = *key;
S->show = show;
S->syscode = call->ktr_code;
S->i = 0;
S->npath = npath;
for (i = 0; i < npath; i++)
S->path[i] = NULL; /* paranoia */
return S;
}
static void
show_paths(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret, const char *prefix)
{
unsigned i;
/* Caller must ensure all paths have been specified. */
assert(S->i == S->npath);
/*
* Ignore it if it failed or yielded EJUSTRETURN (-2), or if
* we're not producing output.
*/
if (ret->ktr_error && ret->ktr_error != -2)
return;
if (F->out == NULL)
return;
/*
* Print the prefix, pid, and paths -- with the paths quoted if
* there's more than one.
*/
fprintf(F->out, "%s %jd", prefix, (intmax_t)S->key.pid);
for (i = 0; i < S->npath; i++) {
const char *q = S->npath > 1 ? "'" : "";
fprintf(F->out, " %s%s%s", q, S->path[i], q);
}
fprintf(F->out, "\n");
}
static void
show_retval(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret, const char *prefix)
{
/*
* Ignore it if it failed or yielded EJUSTRETURN (-2), or if
* we're not producing output.
*/
if (ret->ktr_error && ret->ktr_error != -2)
return;
if (F->out == NULL)
return;
fprintf(F->out, "%s %jd %jd\n", prefix, (intmax_t)S->key.pid,
(intmax_t)ret->ktr_retval);
}
static void
show_chdir(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
show_paths(F, S, ret, "C");
}
static void
show_execve(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
return show_paths(F, S, ret, "E");
}
static void
show_fork(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
show_retval(F, S, ret, "F");
}
static void
show_link(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
show_paths(F, S, ret, "L"); /* XXX same as symlink */
}
static void
show_open_read(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
show_paths(F, S, ret, "R");
}
static void
show_open_write(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
show_paths(F, S, ret, "W");
}
static void
show_open_readwrite(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
show_paths(F, S, ret, "R");
show_paths(F, S, ret, "W");
}
static void
show_openat_read(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
if (S->path[0][0] != '/')
show_paths(F, S, ret, "A");
show_paths(F, S, ret, "R");
}
static void
show_openat_write(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
if (S->path[0][0] != '/')
show_paths(F, S, ret, "A");
show_paths(F, S, ret, "W");
}
static void
show_openat_readwrite(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
if (S->path[0][0] != '/')
show_paths(F, S, ret, "A");
show_paths(F, S, ret, "R");
show_paths(F, S, ret, "W");
}
static void
show_symlink(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
show_paths(F, S, ret, "L"); /* XXX same as link */
}
static void
show_unlink(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
show_paths(F, S, ret, "D");
}
static void
show_rename(struct filemon *F, const struct filemon_state *S,
const struct ktr_sysret *ret)
{
show_paths(F, S, ret, "M");
}
static struct filemon_state *
filemon_sys_chdir(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
return syscall_enter(F, key, call, 1, &show_chdir);
}
static struct filemon_state *
filemon_sys_execve(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
return syscall_enter(F, key, call, 1, &show_execve);
}
static struct filemon_state *
filemon_sys_exit(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
const register_t *args = (const void *)&call[1];
int status = args[0];
if (F->out) {
fprintf(F->out, "X %jd %d\n", (intmax_t)key->pid, status);
if (key->pid == F->child) {
fprintf(F->out, "# Bye bye\n");
F->child = 0;
}
}
return NULL;
}
static struct filemon_state *
filemon_sys_fork(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
return syscall_enter(F, key, call, 0, &show_fork);
}
static struct filemon_state *
filemon_sys_link(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
return syscall_enter(F, key, call, 2, &show_link);
}
static struct filemon_state *
filemon_sys_open(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
const register_t *args = (const void *)&call[1];
int flags;
if (call->ktr_argsize < 2)
return NULL;
flags = args[1];
if ((flags & O_RDWR) == O_RDWR)
return syscall_enter(F, key, call, 1, &show_open_readwrite);
else if ((flags & O_WRONLY) == O_WRONLY)
return syscall_enter(F, key, call, 1, &show_open_write);
else if ((flags & O_RDONLY) == O_RDONLY)
return syscall_enter(F, key, call, 1, &show_open_read);
else
return NULL; /* XXX Do we care if no read or write? */
}
static struct filemon_state *
filemon_sys_openat(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
const register_t *args = (const void *)&call[1];
int flags, fd;
if (call->ktr_argsize < 3)
return NULL;
fd = args[0];
flags = args[2];
if (fd == AT_CWD) {
if ((flags & O_RDWR) == O_RDWR)
return syscall_enter(F, key, call, 1,
&show_open_readwrite);
else if ((flags & O_WRONLY) == O_WRONLY)
return syscall_enter(F, key, call, 1,
&show_open_write);
else if ((flags & O_RDONLY) == O_RDONLY)
return syscall_enter(F, key, call, 1, &show_open_read);
else
return NULL;
} else {
if ((flags & O_RDWR) == O_RDWR)
return syscall_enter(F, key, call, 1,
&show_openat_readwrite);
else if ((flags & O_WRONLY) == O_WRONLY)
return syscall_enter(F, key, call, 1,
&show_openat_write);
else if ((flags & O_RDONLY) == O_RDONLY)
return syscall_enter(F, key, call, 1,
&show_openat_read);
else
return NULL;
}
}
static struct filemon_state *
filemon_sys_symlink(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
return syscall_enter(F, key, call, 2, &show_symlink);
}
static struct filemon_state *
filemon_sys_unlink(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
return syscall_enter(F, key, call, 1, &show_unlink);
}
static struct filemon_state *
filemon_sys_rename(struct filemon *F, const struct filemon_key *key,
const struct ktr_syscall *call)
{
return syscall_enter(F, key, call, 2, &show_rename);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: for.c,v 1.1.1.8 2015/05/19 21:36:44 joerg Exp $ */
/* $NetBSD: for.c,v 1.1.1.9 2020/05/24 05:35:52 nia Exp $ */
/*
* Copyright (c) 1992, The Regents of the University of California.
@ -30,14 +30,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: for.c,v 1.1.1.8 2015/05/19 21:36:44 joerg Exp $";
static char rcsid[] = "$NetBSD: for.c,v 1.1.1.9 2020/05/24 05:35:52 nia Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: for.c,v 1.1.1.8 2015/05/19 21:36:44 joerg Exp $");
__RCSID("$NetBSD: for.c,v 1.1.1.9 2020/05/24 05:35:52 nia Exp $");
#endif
#endif /* not lint */
#endif
@ -216,7 +216,7 @@ For_Eval(char *line)
* We can't do the escapes here - because we don't know whether
* we are substuting into ${...} or $(...).
*/
sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
sub = Var_Subst(NULL, ptr, VAR_GLOBAL, VARF_WANTRES);
/*
* Split into words allowing for quoted strings.
@ -427,7 +427,7 @@ For_Iterate(void *v_arg, size_t *ret_len)
for (cp = cmd_cp; (cp = strchr(cp, '$')) != NULL;) {
char ech;
ch = *++cp;
if ((ch == '(' && (ech = ')')) || (ch == '{' && (ech = '}'))) {
if ((ch == '(' && (ech = ')', 1)) || (ch == '{' && (ech = '}', 1))) {
cp++;
/* Check variable name against the .for loop variables */
STRLIST_FOREACH(var, &arg->vars, i) {

View File

@ -1,3 +1,5 @@
/* $NetBSD: getopt.c,v 1.1.1.4 2020/05/24 05:35:52 nia Exp $ */
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
@ -10,11 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@ -35,11 +33,7 @@
# include "config.h"
#endif
#if !defined(HAVE_GETOPT) || defined(WANT_GETOPT_LONG) || defined(BROKEN_GETOPT)
#if defined(LIBC_SCCS) && !defined(lint)
/* static char sccsid[] = "from: @(#)getopt.c 8.2 (Berkeley) 4/2/94"; */
static char *rcsid = "$Id: getopt.c,v 1.1.1.3 2009/09/18 20:55:25 joerg Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
#include <stdio.h>
#include <stdlib.h>
@ -61,13 +55,10 @@ char *optarg; /* argument associated with option */
* Parse argc/argv argument vector.
*/
int
getopt(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
getopt(int nargc, char * const nargv[], const char *ostr)
{
extern char *__progname;
static char *place = EMSG; /* option letter processing */
static const char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
#ifndef BSD4_4
@ -79,43 +70,63 @@ getopt(nargc, nargv, ostr)
}
#endif
if (optreset || !*place) { /* update scanning pointer */
if (optreset || *place == 0) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = nargv[optind];
if (optind >= nargc || *place++ != '-') {
/* Argument is absent or is not an option */
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-' /* found "--" */
&& !place[1]) { /* and not "--foo" */
optopt = *place++;
if (optopt == '-' && *place == 0) {
/* "--" => end of options */
++optind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int)'-')
return (-1);
if (!*place)
if (optopt == 0) {
/* Solitary '-', treat as a '-' option
if the program (eg su) is looking for it. */
place = EMSG;
if (strchr(ostr, '-') == NULL)
return -1;
optopt = '-';
}
} else
optopt = *place++;
/* See if option letter is one the caller wanted... */
if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
if (*place == 0)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", __progname, optopt);
"%s: unknown option -- %c\n", __progname, optopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
/* Does this option need an argument? */
if (oli[1] != ':') {
/* don't need argument */
optarg = NULL;
if (!*place)
if (*place == 0)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
} else {
/* Option-argument is either the rest of this argument or the
entire next argument. */
if (*place)
optarg = __UNCONST(place);
else if (oli[2] == ':')
/*
* GNU Extension, for optional arguments if the rest of
* the argument is empty, we return NULL
*/
optarg = NULL;
else if (nargc > ++optind)
optarg = nargv[optind];
else {
/* option-argument absent */
place = EMSG;
if (*ostr == ':')
return (BADARG);
@ -125,12 +136,10 @@ getopt(nargc, nargv, ostr)
__progname, optopt);
return (BADCH);
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
return (optopt); /* return option letter */
}
#endif
#ifdef MAIN

View File

@ -1,4 +1,4 @@
/* $NetBSD: hash.h,v 1.1.1.3 2009/09/18 20:55:26 joerg Exp $ */
/* $NetBSD: hash.h,v 1.1.1.4 2020/05/24 05:35:52 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -78,8 +78,8 @@
* which maintains hash tables.
*/
#ifndef _HASH
#define _HASH
#ifndef _HASH_H
#define _HASH_H
/*
* The following defines one entry in the hash table.
@ -89,10 +89,7 @@ typedef struct Hash_Entry {
struct Hash_Entry *next; /* Used to link together all the
* entries associated with the same
* bucket. */
union {
void *clientPtr; /* Arbitrary pointer */
time_t clientTime; /* Arbitrary Time */
} clientInfo;
void *clientPtr; /* Arbitrary pointer */
unsigned namehash; /* hash value of key */
char name[1]; /* key string */
} Hash_Entry;
@ -125,8 +122,7 @@ typedef struct Hash_Search {
* Hash_Entry *h;
*/
#define Hash_GetValue(h) ((h)->clientInfo.clientPtr)
#define Hash_GetTimeValue(h) ((h)->clientInfo.clientTime)
#define Hash_GetValue(h) ((h)->clientPtr)
/*
* Hash_SetValue(h, val);
@ -134,8 +130,7 @@ typedef struct Hash_Search {
* char *val;
*/
#define Hash_SetValue(h, val) ((h)->clientInfo.clientPtr = (val))
#define Hash_SetTimeValue(h, val) ((h)->clientInfo.clientTime = (val))
#define Hash_SetValue(h, val) ((h)->clientPtr = (val))
/*
* Hash_Size(n) returns the number of words in an object of n bytes
@ -151,4 +146,4 @@ void Hash_DeleteEntry(Hash_Table *, Hash_Entry *);
Hash_Entry *Hash_EnumFirst(Hash_Table *, Hash_Search *);
Hash_Entry *Hash_EnumNext(Hash_Search *);
#endif /* _HASH */
#endif /* _HASH_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $ */
/* $NetBSD: job.c,v 1.1.1.11 2020/05/24 05:35:52 nia 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.1.1.10 2015/05/19 21:36:44 joerg Exp $";
static char rcsid[] = "$NetBSD: job.c,v 1.1.1.11 2020/05/24 05:35:52 nia Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $");
__RCSID("$NetBSD: job.c,v 1.1.1.11 2020/05/24 05:35:52 nia Exp $");
#endif
#endif /* not lint */
#endif
@ -102,7 +102,7 @@ __RCSID("$NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $");
* a time given by the SEL_* constants, below,
* or until output is ready.
*
* Job_Init Called to intialize this module. in addition,
* Job_Init Called to initialize this module. in addition,
* any commands attached to the .BEGIN target
* are executed before this function returns.
* Hence, the makefile must have been parsed
@ -144,7 +144,6 @@ __RCSID("$NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $");
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#if !defined(USE_SELECT) && defined(HAVE_POLL_H)
#include <poll.h>
#else
@ -343,17 +342,14 @@ static Job childExitJob; /* child exit pseudo-job */
#define CHILD_EXIT "."
#define DO_JOB_RESUME "R"
static const int npseudojobs = 2; /* number of pseudo-jobs */
#define TARG_FMT "%s %s ---\n" /* Default format */
#define MESSAGE(fp, gn) \
if (maxJobs != 1 && targPrefix && *targPrefix) \
(void)fprintf(fp, TARG_FMT, targPrefix, gn->name)
static sigset_t caught_signals; /* Set of signals we handle */
#if defined(SYSV)
#define KILLPG(pid, sig) kill(-(pid), (sig))
#else
#define KILLPG(pid, sig) killpg((pid), (sig))
#endif
static void JobChildSig(int);
static void JobContinueSig(int);
@ -374,7 +370,20 @@ static void JobSigLock(sigset_t *);
static void JobSigUnlock(sigset_t *);
static void JobSigReset(void);
const char *malloc_options="A";
#if !defined(MALLOC_OPTIONS)
# define MALLOC_OPTIONS "A"
#endif
const char *malloc_options= MALLOC_OPTIONS;
static unsigned
nfds_per_job(void)
{
#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
if (useMeta)
return 2;
#endif
return 1;
}
static void
job_table_dump(const char *where)
@ -388,6 +397,21 @@ job_table_dump(const char *where)
}
}
/*
* Delete the target of a failed, interrupted, or otherwise
* unsuccessful job unless inhibited by .PRECIOUS.
*/
static void
JobDeleteTarget(GNode *gn)
{
if ((gn->type & (OP_JOIN|OP_PHONY)) == 0 && !Targ_Precious(gn)) {
char *file = (gn->path == NULL ? gn->name : gn->path);
if (!noExecute && eunlink(file) != -1) {
Error("*** %s removed", file);
}
}
}
/*
* JobSigLock/JobSigUnlock
*
@ -410,7 +434,7 @@ static void JobSigUnlock(sigset_t *omaskp)
static void
JobCreatePipe(Job *job, int minfd)
{
int i, fd;
int i, fd, flags;
if (pipe(job->jobPipe) == -1)
Punt("Cannot create pipe: %s", strerror(errno));
@ -425,8 +449,10 @@ JobCreatePipe(Job *job, int minfd)
}
/* Set close-on-exec flag for both */
(void)fcntl(job->jobPipe[0], F_SETFD, 1);
(void)fcntl(job->jobPipe[1], F_SETFD, 1);
if (fcntl(job->jobPipe[0], F_SETFD, FD_CLOEXEC) == -1)
Punt("Cannot set close-on-exec: %s", strerror(errno));
if (fcntl(job->jobPipe[1], F_SETFD, FD_CLOEXEC) == -1)
Punt("Cannot set close-on-exec: %s", strerror(errno));
/*
* We mark the input side of the pipe non-blocking; we poll(2) the
@ -434,8 +460,12 @@ JobCreatePipe(Job *job, int minfd)
* race for the token when a new one becomes available, so the read
* from the pipe should not block.
*/
fcntl(job->jobPipe[0], F_SETFL,
fcntl(job->jobPipe[0], F_GETFL, 0) | O_NONBLOCK);
flags = fcntl(job->jobPipe[0], F_GETFL, 0);
if (flags == -1)
Punt("Cannot get flags: %s", strerror(errno));
flags |= O_NONBLOCK;
if (fcntl(job->jobPipe[0], F_SETFL, flags) == -1)
Punt("Cannot set flags: %s", strerror(errno));
}
/*-
@ -715,7 +745,7 @@ JobPrintCommand(void *cmdp, void *jobp)
numCommands += 1;
cmdStart = cmd = Var_Subst(NULL, cmd, job->node, FALSE);
cmdStart = cmd = Var_Subst(NULL, cmd, job->node, VARF_WANTRES);
cmdTemplate = "%s\n";
@ -737,6 +767,7 @@ JobPrintCommand(void *cmdp, void *jobp)
* but this one needs to be - use compat mode just for it.
*/
CompatRunCommand(cmdp, job->node);
free(cmdStart);
return 0;
}
break;
@ -866,8 +897,7 @@ JobPrintCommand(void *cmdp, void *jobp)
DBPRINTF(cmdTemplate, cmd);
free(cmdStart);
if (escCmd)
free(escCmd);
free(escCmd);
if (errOff) {
/*
* If echoing is already off, there's no point in issuing the
@ -903,7 +933,7 @@ JobPrintCommand(void *cmdp, void *jobp)
static int
JobSaveCommand(void *cmd, void *gn)
{
cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, FALSE);
cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, VARF_WANTRES);
(void)Lst_AtEnd(postCommands->commands, cmd);
return(0);
}
@ -1035,6 +1065,9 @@ JobFinish (Job *job, WAIT_T status)
if (job->flags & JOB_IGNERR) {
WAIT_STATUS(status) = 0;
} else {
if (deleteOnError) {
JobDeleteTarget(job->node);
}
PrintOnError(job->node, NULL);
}
} else if (DEBUG(JOB)) {
@ -1052,13 +1085,20 @@ JobFinish (Job *job, WAIT_T status)
}
(void)printf("*** [%s] Signal %d\n",
job->node->name, WTERMSIG(status));
if (deleteOnError) {
JobDeleteTarget(job->node);
}
}
(void)fflush(stdout);
}
#ifdef USE_META
if (useMeta) {
meta_job_finish(job);
int x;
if ((x = meta_job_finish(job)) != 0 && status == 0) {
status = x;
}
}
#endif
@ -1234,8 +1274,7 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
*/
Make_HandleUse(DEFAULT, gn);
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn, 0);
if (p1)
free(p1);
free(p1);
} else if (Dir_MTime(gn, 0) == 0 && (gn->type & OP_SPECIAL) == 0) {
/*
* The node wasn't the target of an operator we have no .DEFAULT
@ -1357,15 +1396,27 @@ JobExec(Job *job, char **argv)
execError("dup2", "job->cmdFILE");
_exit(1);
}
(void)fcntl(0, F_SETFD, 0);
(void)lseek(0, (off_t)0, SEEK_SET);
if (fcntl(0, F_SETFD, 0) == -1) {
execError("fcntl clear close-on-exec", "stdin");
_exit(1);
}
if (lseek(0, (off_t)0, SEEK_SET) == -1) {
execError("lseek to 0", "stdin");
_exit(1);
}
if (job->node->type & (OP_MAKE | OP_SUBMAKE)) {
/*
* Pass job token pipe to submakes.
*/
fcntl(tokenWaitJob.inPipe, F_SETFD, 0);
fcntl(tokenWaitJob.outPipe, F_SETFD, 0);
if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1) {
execError("clear close-on-exec", "tokenWaitJob.inPipe");
_exit(1);
}
if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1) {
execError("clear close-on-exec", "tokenWaitJob.outPipe");
_exit(1);
}
}
/*
@ -1382,7 +1433,10 @@ JobExec(Job *job, char **argv)
* it before routing the shell's error output to the same place as
* its standard output.
*/
(void)fcntl(1, F_SETFD, 0);
if (fcntl(1, F_SETFD, 0) == -1) {
execError("clear close-on-exec", "stdout");
_exit(1);
}
if (dup2(1, 2) == -1) {
execError("dup2", "1, 2");
_exit(1);
@ -1416,6 +1470,12 @@ JobExec(Job *job, char **argv)
Trace_Log(JOBSTART, job);
#ifdef USE_META
if (useMeta) {
meta_job_parent(job, cpid);
}
#endif
/*
* Set the current position in the buffer to the beginning
* and mark another stream to watch in the outputs mask
@ -1598,7 +1658,7 @@ JobStart(GNode *gn, int flags)
if (job->cmdFILE == NULL) {
Punt("Could not fdopen %s", tfile);
}
(void)fcntl(FILENO(job->cmdFILE), F_SETFD, 1);
(void)fcntl(FILENO(job->cmdFILE), F_SETFD, FD_CLOEXEC);
/*
* Send the commands to the command file, flush all its buffers then
* rewind and remove the thing.
@ -2098,12 +2158,24 @@ Job_CatchOutput(void)
if (nready == 0)
return;
for (i = 2; i < nfds; i++) {
for (i = npseudojobs*nfds_per_job(); i < nfds; i++) {
if (!fds[i].revents)
continue;
job = jobfds[i];
if (job->job_state == JOB_ST_RUNNING)
JobDoOutput(job, FALSE);
#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
/*
* With meta mode, we may have activity on the job's filemon
* descriptor too, which at the moment is any pollfd other than
* job->inPollfd.
*/
if (useMeta && job->inPollfd != &fds[i]) {
if (meta_job_event(job) <= 0) {
fds[i].events = 0; /* never mind */
}
}
#endif
if (--nready == 0)
return;
}
@ -2194,7 +2266,8 @@ Job_SetPrefix(void)
Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL, 0);
}
targPrefix = Var_Subst(NULL, "${" MAKE_JOB_PREFIX "}", VAR_GLOBAL, 0);
targPrefix = Var_Subst(NULL, "${" MAKE_JOB_PREFIX "}",
VAR_GLOBAL, VARF_WANTRES);
}
/*-
@ -2247,9 +2320,11 @@ Job_Init(void)
JobCreatePipe(&childExitJob, 3);
/* We can only need to wait for tokens, children and output from each job */
fds = bmake_malloc(sizeof (*fds) * (2 + maxJobs));
jobfds = bmake_malloc(sizeof (*jobfds) * (2 + maxJobs));
/* Preallocate enough for the maximum number of jobs. */
fds = bmake_malloc(sizeof(*fds) *
(npseudojobs + maxJobs) * nfds_per_job());
jobfds = bmake_malloc(sizeof(*jobfds) *
(npseudojobs + maxJobs) * nfds_per_job());
/* These are permanent entries and take slots 0 and 1 */
watchfd(&tokenWaitJob);
@ -2401,8 +2476,7 @@ Job_ParseShell(char *line)
line++;
}
if (shellArgv)
free(UNCONST(shellArgv));
free(UNCONST(shellArgv));
memset(&newShell, 0, sizeof(newShell));
@ -2577,12 +2651,7 @@ JobInterrupt(int runINTERRUPT, int signo)
gn = job->node;
if ((gn->type & (OP_JOIN|OP_PHONY)) == 0 && !Targ_Precious(gn)) {
char *file = (gn->path == NULL ? gn->name : gn->path);
if (!noExecute && eunlink(file) != -1) {
Error("*** %s removed", file);
}
}
JobDeleteTarget(gn);
if (job->pid) {
if (DEBUG(JOB)) {
(void)fprintf(debug_file,
@ -2650,8 +2719,7 @@ void
Job_End(void)
{
#ifdef CLEANUP
if (shellArgv)
free(shellArgv);
free(shellArgv);
#endif
}
@ -2775,6 +2843,14 @@ watchfd(Job *job)
jobfds[nfds] = job;
job->inPollfd = &fds[nfds];
nfds++;
#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
if (useMeta) {
fds[nfds].fd = meta_job_fd(job);
fds[nfds].events = fds[nfds].fd == -1 ? 0 : POLLIN;
jobfds[nfds] = job;
nfds++;
}
#endif
}
static void
@ -2785,6 +2861,18 @@ clearfd(Job *job)
Punt("Unwatching unwatched job");
i = job->inPollfd - fds;
nfds--;
#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
if (useMeta) {
/*
* Sanity check: there should be two fds per job, so the job's
* pollfd number should be even.
*/
assert(nfds_per_job() == 2);
if (i % 2)
Punt("odd-numbered fd with meta");
nfds--;
}
#endif
/*
* Move last job in table into hole made by dead job.
*/
@ -2792,6 +2880,12 @@ clearfd(Job *job)
fds[i] = fds[nfds];
jobfds[i] = jobfds[nfds];
jobfds[i]->inPollfd = &fds[i];
#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
if (useMeta) {
fds[i + 1] = fds[nfds + 1];
jobfds[i + 1] = jobfds[nfds + 1];
}
#endif
}
job->inPollfd = NULL;
}
@ -2850,8 +2944,8 @@ Job_ServerStart(int max_tokens, int jp_0, int jp_1)
/* Pipe passed in from parent */
tokenWaitJob.inPipe = jp_0;
tokenWaitJob.outPipe = jp_1;
(void)fcntl(jp_0, F_SETFD, 1);
(void)fcntl(jp_1, F_SETFD, 1);
(void)fcntl(jp_0, F_SETFD, FD_CLOEXEC);
(void)fcntl(jp_1, F_SETFD, FD_CLOEXEC);
return;
}
@ -2933,7 +3027,6 @@ Job_TokenWithdraw(void)
}
if (DEBUG(JOB))
fprintf(debug_file, "(%d) blocked for token\n", getpid());
wantToken = 1;
return FALSE;
}

View File

@ -2,7 +2,7 @@
# derrived from /etc/rc_d/os.sh
# RCSid:
# $Id: machine.sh,v 1.1.1.5 2015/05/19 21:36:44 joerg Exp $
# $Id: machine.sh,v 1.1.1.6 2020/05/24 05:35:52 nia Exp $
#
# @(#) Copyright (c) 1994-2002 Simon J. Gerraty
#
@ -44,6 +44,12 @@ Which() {
}
case $OS in
AIX) # from http://gnats.netbsd.org/29386
OSMAJOR=`uname -v`
OSMINOR=`uname -r`
MACHINE=$OS$OSMAJOR.$OSMINOR
MACHINE_ARCH=`bootinfo -T`
;;
OpenBSD)
MACHINE=$OS$OSMAJOR.$machine
arch=`Which arch /usr/bin:/usr/ucb:$PATH`

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.1.1.11 2015/05/19 21:36:44 joerg Exp $ */
/* $NetBSD: main.c,v 1.1.1.12 2020/05/24 05:35:52 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,7 +69,7 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: main.c,v 1.1.1.11 2015/05/19 21:36:44 joerg Exp $";
static char rcsid[] = "$NetBSD: main.c,v 1.1.1.12 2020/05/24 05:35:52 nia Exp $";
#else
#include <sys/cdefs.h>
#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.1.1.11 2015/05/19 21:36:44 joerg Exp $");
__RCSID("$NetBSD: main.c,v 1.1.1.12 2020/05/24 05:35:52 nia Exp $");
#endif
#endif /* not lint */
#endif
@ -125,7 +125,6 @@ __RCSID("$NetBSD: main.c,v 1.1.1.11 2015/05/19 21:36:44 joerg Exp $");
#include "wait.h"
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@ -156,10 +155,13 @@ Lst create; /* Targets to be made */
time_t now; /* Time at start of make */
GNode *DEFAULT; /* .DEFAULT node */
Boolean allPrecious; /* .PRECIOUS given on line by itself */
Boolean deleteOnError; /* .DELETE_ON_ERROR: set */
static Boolean noBuiltins; /* -r flag */
static Lst makefiles; /* ordered list of makefiles to read */
static Boolean printVars; /* print value of one or more vars */
static int printVars; /* -[vV] argument */
#define COMPAT_VARS 1
#define EXPAND_VARS 2
static Lst variables; /* list of variables to print */
int maxJobs; /* -j argument */
static int maxJobTokens; /* -j argument */
@ -172,6 +174,7 @@ Boolean keepgoing; /* -k flag */
Boolean queryFlag; /* -q flag */
Boolean touchFlag; /* -t flag */
Boolean enterFlag; /* -w flag */
Boolean enterFlagObj; /* -w and objdir != srcdir */
Boolean ignoreErrors; /* -i flag */
Boolean beSilent; /* -s flag */
Boolean oldVars; /* variable substitution style */
@ -186,6 +189,7 @@ static const char * tracefile;
static void MainParseArgs(int, char **);
static int ReadMakefile(const void *, const void *);
static void usage(void) MAKE_ATTR_DEAD;
static void purge_cached_realpaths(void);
static Boolean ignorePWD; /* if we use -C, PWD is meaningless */
static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
@ -195,6 +199,8 @@ char *makeDependfile;
pid_t myPid;
int makelevel;
FILE *debug_file;
Boolean forceJobs = FALSE;
/*
@ -335,7 +341,7 @@ parse_debug_options(const char *argvalue)
goto debug_setbuf;
}
len = strlen(modules);
fname = malloc(len + 20);
fname = bmake_malloc(len + 20);
memcpy(fname, modules, len + 1);
/* Let the filename be modified by the pid */
if (strcmp(fname + len - 3, ".%d") == 0)
@ -366,6 +372,32 @@ debug_setbuf:
}
}
/*
* does path contain any relative components
*/
static int
is_relpath(const char *path)
{
const char *cp;
if (path[0] != '/')
return TRUE;
cp = path;
do {
cp = strstr(cp, "/.");
if (!cp)
break;
cp += 2;
if (cp[0] == '/' || cp[0] == '\0')
return TRUE;
else if (cp[0] == '.') {
if (cp[1] == '/' || cp[1] == '\0')
return TRUE;
}
} while (cp);
return FALSE;
}
/*-
* MainParseArgs --
* Parse a given argument vector. Called from main() and from
@ -388,11 +420,12 @@ MainParseArgs(int argc, char **argv)
int arginc;
char *argvalue;
const char *getopt_def;
struct stat sa, sb;
char *optscan;
Boolean inOption, dashDash = FALSE;
char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
#define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstw"
#define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w"
/* Can't actually use getopt(3) because rescanning is not portable */
getopt_def = OPTFLAGS;
@ -456,6 +489,12 @@ rearg:
(void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
exit(2);
}
if (!is_relpath(argvalue) &&
stat(argvalue, &sa) != -1 &&
stat(curdir, &sb) != -1 &&
sa.st_ino == sb.st_ino &&
sa.st_dev == sb.st_dev)
strncpy(curdir, argvalue, MAXPATHLEN);
ignorePWD = TRUE;
break;
case 'D':
@ -511,8 +550,9 @@ rearg:
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
break;
case 'V':
case 'v':
if (argvalue == NULL) goto noarg;
printVars = TRUE;
printVars = c == 'v' ? EXPAND_VARS : COMPAT_VARS;
(void)Lst_AtEnd(variables, argvalue);
Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
@ -695,8 +735,7 @@ Main_ParseArgLine(const char *line)
#endif
buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2);
(void)snprintf(buf, len, "%s %s", argv0, line);
if (p1)
free(p1);
free(p1);
argv = brk_string(buf, &argc, TRUE, &args);
if (argv == NULL) {
@ -712,22 +751,22 @@ Main_ParseArgLine(const char *line)
}
Boolean
Main_SetObjdir(const char *path)
Main_SetObjdir(const char *fmt, ...)
{
struct stat sb;
char *p = NULL;
char *path;
char buf[MAXPATHLEN + 1];
char buf2[MAXPATHLEN + 1];
Boolean rc = FALSE;
va_list ap;
/* expand variable substitutions */
if (strchr(path, '$') != 0) {
snprintf(buf, MAXPATHLEN, "%s", path);
path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
}
va_start(ap, fmt);
vsnprintf(path = buf, MAXPATHLEN, fmt, ap);
va_end(ap);
if (path[0] != '/') {
snprintf(buf, MAXPATHLEN, "%s/%s", curdir, path);
path = buf;
snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path);
path = buf2;
}
/* look for the directory and try to chdir there */
@ -740,15 +779,39 @@ Main_SetObjdir(const char *path)
Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0);
setenv("PWD", objdir, 1);
Dir_InitDot();
purge_cached_realpaths();
rc = TRUE;
if (enterFlag && strcmp(objdir, curdir) != 0)
enterFlagObj = TRUE;
}
}
if (p)
free(p);
return rc;
}
static Boolean
Main_SetVarObjdir(const char *var, const char *suffix)
{
char *p, *path, *xpath;
if ((path = Var_Value(var, VAR_CMD, &p)) == NULL ||
*path == '\0')
return FALSE;
/* expand variable substitutions */
if (strchr(path, '$') != 0)
xpath = Var_Subst(NULL, path, VAR_GLOBAL, VARF_WANTRES);
else
xpath = path;
(void)Main_SetObjdir("%s%s", xpath, suffix);
if (xpath != path)
free(xpath);
free(p);
return TRUE;
}
/*-
* ReadAllMakefiles --
* wrapper around ReadMakefile() to read all.
@ -803,7 +866,8 @@ MakeMode(const char *mode)
char *mp = NULL;
if (!mode)
mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}", VAR_GLOBAL, 0);
mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}",
VAR_GLOBAL, VARF_WANTRES);
if (mode && *mode) {
if (strstr(mode, "compat")) {
@ -815,8 +879,91 @@ MakeMode(const char *mode)
meta_mode_init(mode);
#endif
}
if (mp)
free(mp);
free(mp);
}
static void
doPrintVars(void)
{
LstNode ln;
Boolean expandVars;
if (printVars == EXPAND_VARS)
expandVars = TRUE;
else if (debugVflag)
expandVars = FALSE;
else
expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE);
for (ln = Lst_First(variables); ln != NULL;
ln = Lst_Succ(ln)) {
char *var = (char *)Lst_Datum(ln);
char *value;
char *p1;
if (strchr(var, '$')) {
value = p1 = Var_Subst(NULL, var, VAR_GLOBAL,
VARF_WANTRES);
} else if (expandVars) {
char tmp[128];
int len = snprintf(tmp, sizeof(tmp), "${%s}", var);
if (len >= (int)sizeof(tmp))
Fatal("%s: variable name too big: %s",
progname, var);
value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL,
VARF_WANTRES);
} else {
value = Var_Value(var, VAR_GLOBAL, &p1);
}
printf("%s\n", value ? value : "");
free(p1);
}
}
static Boolean
runTargets(void)
{
Lst targs; /* target nodes to create -- passed to Make_Init */
Boolean outOfDate; /* FALSE if all targets up to date */
/*
* Have now read the entire graph and need to make a list of
* targets to create. If none was given on the command line,
* we consult the parsing module to find the main target(s)
* to create.
*/
if (Lst_IsEmpty(create))
targs = Parse_MainName();
else
targs = Targ_FindList(create, TARG_CREATE);
if (!compatMake) {
/*
* Initialize job module before traversing the graph
* now that any .BEGIN and .END targets have been read.
* This is done only if the -q flag wasn't given
* (to prevent the .BEGIN from being executed should
* it exist).
*/
if (!queryFlag) {
Job_Init();
jobsRunning = TRUE;
}
/* Traverse the graph, checking on all the targets */
outOfDate = Make_Run(targs);
} else {
/*
* Compat_Init will take care of creating all the
* targets as well as initializing the module.
*/
Compat_Run(targs);
outOfDate = FALSE;
}
Lst_Destroy(targs, NULL);
return outOfDate;
}
/*-
@ -839,8 +986,7 @@ MakeMode(const char *mode)
int
main(int argc, char **argv)
{
Lst targs; /* target nodes to create -- passed to Make_Init */
Boolean outOfDate = FALSE; /* FALSE if all targets up to date */
Boolean outOfDate; /* FALSE if all targets up to date */
struct stat sb, sa;
char *p1, *path;
char mdpath[MAXPATHLEN];
@ -969,7 +1115,7 @@ main(int argc, char **argv)
create = Lst_Init(FALSE);
makefiles = Lst_Init(FALSE);
printVars = FALSE;
printVars = 0;
debugVflag = FALSE;
variables = Lst_Init(FALSE);
beSilent = FALSE; /* Print commands as executed */
@ -978,6 +1124,7 @@ main(int argc, char **argv)
noRecursiveExecute = FALSE; /* Execute all .MAKE targets */
keepgoing = FALSE; /* Stop on error */
allPrecious = FALSE; /* Remove targets when interrupted */
deleteOnError = FALSE; /* Historical default behavior */
queryFlag = FALSE; /* This is not just a check-run */
noBuiltins = FALSE; /* Read the built-in rules */
touchFlag = FALSE; /* Actually update targets */
@ -1013,7 +1160,7 @@ main(int argc, char **argv)
/*
* A relative path, canonicalize it.
*/
p1 = realpath(argv[0], mdpath);
p1 = cached_realpath(argv[0], mdpath);
if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) {
p1 = argv[0]; /* realpath failed */
}
@ -1052,6 +1199,8 @@ main(int argc, char **argv)
#ifdef USE_META
meta_init();
#endif
Dir_Init(NULL); /* Dir_* safe to call from MainParseArgs */
/*
* First snag any flags out of the MAKE environment variable.
* (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
@ -1127,37 +1276,20 @@ main(int argc, char **argv)
* MAKEOBJDIR is set in the environment, try only that value
* and fall back to .CURDIR if it does not exist.
*
* Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and
* finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none
* Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE,
* and * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none
* of these paths exist, just use .CURDIR.
*/
Dir_Init(curdir);
(void)Main_SetObjdir(curdir);
(void)Main_SetObjdir("%s", curdir);
if ((path = Var_Value("MAKEOBJDIRPREFIX", VAR_CMD, &p1)) != NULL) {
(void)snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir);
(void)Main_SetObjdir(mdpath);
free(p1);
} else if ((path = Var_Value("MAKEOBJDIR", VAR_CMD, &p1)) != NULL) {
(void)Main_SetObjdir(path);
free(p1);
} else {
(void)snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine);
if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) {
(void)snprintf(mdpath, MAXPATHLEN, "%s%s",
_PATH_OBJDIRPREFIX, curdir);
(void)Main_SetObjdir(mdpath);
}
}
if (!Main_SetVarObjdir("MAKEOBJDIRPREFIX", curdir) &&
!Main_SetVarObjdir("MAKEOBJDIR", "") &&
!Main_SetObjdir("%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) &&
!Main_SetObjdir("%s.%s", _PATH_OBJDIR, machine) &&
!Main_SetObjdir("%s", _PATH_OBJDIR))
(void)Main_SetObjdir("%s%s", _PATH_OBJDIRPREFIX, curdir);
/*
* Be compatible if user did not specify -j and did not explicitly
* turned compatibility on
*/
if (!compatMake && !forceJobs) {
compatMake = TRUE;
}
/*
* Initialize archive, target and suffix modules in preparation for
* parsing the makefile(s)
@ -1249,7 +1381,7 @@ main(int argc, char **argv)
(char *)Lst_Datum(ln));
} else {
p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
VAR_CMD, 0);
VAR_CMD, VARF_WANTRES);
if (p1) {
(void)str2Lst_Append(makefiles, p1, NULL);
(void)Lst_Find(makefiles, NULL, ReadMakefile);
@ -1260,17 +1392,49 @@ main(int argc, char **argv)
/* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
if (!noBuiltins || !printVars) {
makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
VAR_CMD, 0);
VAR_CMD, VARF_WANTRES);
doing_depend = TRUE;
(void)ReadMakefile(makeDependfile, NULL);
doing_depend = FALSE;
}
if (enterFlagObj)
printf("%s: Entering directory `%s'\n", progname, objdir);
MakeMode(NULL);
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
if (p1)
free(p1);
free(p1);
if (!forceJobs && !compatMake &&
Var_Exists(".MAKE.JOBS", VAR_GLOBAL)) {
char *value;
int n;
value = Var_Subst(NULL, "${.MAKE.JOBS}", VAR_GLOBAL, VARF_WANTRES);
n = strtol(value, NULL, 0);
if (n < 1) {
(void)fprintf(stderr, "%s: illegal value for .MAKE.JOBS -- must be positive integer!\n",
progname);
exit(1);
}
if (n != maxJobs) {
Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
Var_Append(MAKEFLAGS, value, VAR_GLOBAL);
}
maxJobs = n;
maxJobTokens = maxJobs;
forceJobs = TRUE;
free(value);
}
/*
* Be compatible if user did not specify -j and did not explicitly
* turned compatibility on
*/
if (!compatMake && !forceJobs) {
compatMake = TRUE;
}
if (!compatMake)
Job_ServerStart(maxJobTokens, jp_0, jp_1);
@ -1278,8 +1442,9 @@ main(int argc, char **argv)
fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
jp_0, jp_1, maxJobs, maxJobTokens, compatMake);
Main_ExportMAKEFLAGS(TRUE); /* initial export */
if (!printVars)
Main_ExportMAKEFLAGS(TRUE); /* initial export */
/*
* For compatibility, look at the directories in the VPATH variable
* and add them to the search path, if the variable is defined. The
@ -1295,7 +1460,7 @@ main(int argc, char **argv)
*/
static char VPATH[] = "${VPATH}";
vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
vpath = Var_Subst(NULL, VPATH, VAR_CMD, VARF_WANTRES);
path = vpath;
do {
/* skip to end of directory */
@ -1329,72 +1494,13 @@ main(int argc, char **argv)
/* print the values of any variables requested by the user */
if (printVars) {
LstNode ln;
Boolean expandVars;
if (debugVflag)
expandVars = FALSE;
else
expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE);
for (ln = Lst_First(variables); ln != NULL;
ln = Lst_Succ(ln)) {
char *var = (char *)Lst_Datum(ln);
char *value;
if (strchr(var, '$')) {
value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
} else if (expandVars) {
char tmp[128];
if (snprintf(tmp, sizeof(tmp), "${%s}", var) >= (int)(sizeof(tmp)))
Fatal("%s: variable name too big: %s",
progname, var);
value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
} else {
value = Var_Value(var, VAR_GLOBAL, &p1);
}
printf("%s\n", value ? value : "");
if (p1)
free(p1);
}
doPrintVars();
outOfDate = FALSE;
} else {
/*
* Have now read the entire graph and need to make a list of
* targets to create. If none was given on the command line,
* we consult the parsing module to find the main target(s)
* to create.
*/
if (Lst_IsEmpty(create))
targs = Parse_MainName();
else
targs = Targ_FindList(create, TARG_CREATE);
if (!compatMake) {
/*
* Initialize job module before traversing the graph
* now that any .BEGIN and .END targets have been read.
* This is done only if the -q flag wasn't given
* (to prevent the .BEGIN from being executed should
* it exist).
*/
if (!queryFlag) {
Job_Init();
jobsRunning = TRUE;
}
/* Traverse the graph, checking on all the targets */
outOfDate = Make_Run(targs);
} else {
/*
* Compat_Init will take care of creating all the
* targets as well as initializing the module.
*/
Compat_Run(targs);
}
outOfDate = runTargets();
}
#ifdef CLEANUP
Lst_Destroy(targs, NULL);
Lst_Destroy(variables, NULL);
Lst_Destroy(makefiles, NULL);
Lst_Destroy(create, (FreeProc *)free);
@ -1406,9 +1512,14 @@ main(int argc, char **argv)
Trace_Log(MAKEEND, 0);
if (enterFlagObj)
printf("%s: Leaving directory `%s'\n", progname, objdir);
if (enterFlag)
printf("%s: Leaving directory `%s'\n", progname, curdir);
#ifdef USE_META
meta_finish();
#endif
Suff_End();
Targ_End();
Arch_End();
@ -1477,8 +1588,7 @@ ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
name = Dir_FindFile(fname,
Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
if (!name || (fd = open(name, O_RDONLY)) == -1) {
if (name)
free(name);
free(name);
free(path);
return(-1);
}
@ -1849,10 +1959,70 @@ usage(void)
"usage: %s [-BeikNnqrstWwX] \n\
[-C directory] [-D variable] [-d flags] [-f makefile]\n\
[-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n\
[-V variable] [variable=value] [target ...]\n", progname);
[-V variable] [-v variable] [variable=value] [target ...]\n",
progname);
exit(2);
}
/*
* realpath(3) can get expensive, cache results...
*/
static GNode *cached_realpaths = NULL;
static GNode *
get_cached_realpaths(void)
{
if (!cached_realpaths) {
cached_realpaths = Targ_NewGN("Realpath");
#ifndef DEBUG_REALPATH_CACHE
cached_realpaths->flags = INTERNAL;
#endif
}
return cached_realpaths;
}
/* purge any relative paths */
static void
purge_cached_realpaths(void)
{
GNode *cache = get_cached_realpaths();
Hash_Entry *he, *nhe;
Hash_Search hs;
he = Hash_EnumFirst(&cache->context, &hs);
while (he) {
nhe = Hash_EnumNext(&hs);
if (he->name[0] != '/') {
if (DEBUG(DIR))
fprintf(stderr, "cached_realpath: purging %s\n", he->name);
Hash_DeleteEntry(&cache->context, he);
}
he = nhe;
}
}
char *
cached_realpath(const char *pathname, char *resolved)
{
GNode *cache;
char *rp, *cp;
if (!pathname || !pathname[0])
return NULL;
cache = get_cached_realpaths();
if ((rp = Var_Value(pathname, cache, &cp)) != NULL) {
/* a hit */
strlcpy(resolved, rp, MAXPATHLEN);
} else if ((rp = realpath(pathname, resolved)) != NULL) {
Var_Set(pathname, rp, cache, 0);
}
free(cp);
return rp ? resolved : NULL;
}
int
PrintAddr(void *a, void *b)
@ -1862,6 +2032,14 @@ PrintAddr(void *a, void *b)
}
static int
addErrorCMD(void *cmdp, void *gnp MAKE_ATTR_UNUSED)
{
if (cmdp == NULL)
return 1; /* stop */
Var_Append(".ERROR_CMD", cmdp, VAR_GLOBAL);
return 0;
}
void
PrintOnError(GNode *gn, const char *s)
@ -1882,15 +2060,19 @@ PrintOnError(GNode *gn, const char *s)
* We can print this even if there is no .ERROR target.
*/
Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL, 0);
Var_Delete(".ERROR_CMD", VAR_GLOBAL);
Lst_ForEach(gn->commands, addErrorCMD, gn);
}
strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
sizeof(tmp) - 1);
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
if (cp) {
if (*cp)
printf("%s", cp);
free(cp);
}
fflush(stdout);
/*
* Finally, see if there is a .ERROR target, and run it if so.
*/
@ -1914,7 +2096,7 @@ Main_ExportMAKEFLAGS(Boolean first)
strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
sizeof(tmp));
s = Var_Subst(NULL, tmp, VAR_CMD, 0);
s = Var_Subst(NULL, tmp, VAR_CMD, VARF_WANTRES);
if (s && *s) {
#ifdef POSIX
setenv("MAKEFLAGS", s, 1);
@ -1936,7 +2118,8 @@ getTmpdir(void)
* Honor $TMPDIR but only if it is valid.
* Ensure it ends with /.
*/
tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0);
tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL,
VARF_WANTRES);
if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
free(tmpdir);
tmpdir = bmake_strdup(_PATH_TMP);
@ -1976,6 +2159,44 @@ mkTempFile(const char *pattern, char **fnamep)
return fd;
}
/*
* Convert a string representation of a boolean.
* Anything that looks like "No", "False", "Off", "0" etc,
* is FALSE, otherwise TRUE.
*/
Boolean
s2Boolean(const char *s, Boolean bf)
{
if (s) {
switch(*s) {
case '\0': /* not set - the default wins */
break;
case '0':
case 'F':
case 'f':
case 'N':
case 'n':
bf = FALSE;
break;
case 'O':
case 'o':
switch (s[1]) {
case 'F':
case 'f':
bf = FALSE;
break;
default:
bf = TRUE;
break;
}
break;
default:
bf = TRUE;
break;
}
}
return (bf);
}
/*
* Return a Boolean based on setting of a knob.
@ -1990,32 +2211,11 @@ getBoolean(const char *name, Boolean bf)
char tmp[64];
char *cp;
if (snprintf(tmp, sizeof(tmp), "${%s:tl}", name) < (int)(sizeof(tmp))) {
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
if (snprintf(tmp, sizeof(tmp), "${%s:U:tl}", name) < (int)(sizeof(tmp))) {
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
if (cp) {
switch(*cp) {
case '\0': /* not set - the default wins */
break;
case '0':
case 'f':
case 'n':
bf = FALSE;
break;
case 'o':
switch (cp[1]) {
case 'f':
bf = FALSE;
break;
default:
bf = TRUE;
break;
}
break;
default:
bf = TRUE;
break;
}
bf = s2Boolean(cp, bf);
free(cp);
}
}

View File

@ -13,7 +13,7 @@ esac
CC="@CC@"
CFLAGS="@CFLAGS@ -I. -I${srcdir} @DEFS@ @CPPFLAGS@ -DMAKE_NATIVE ${XDEFS} -DBMAKE_PATH_MAX=@bmake_path_max@"
MAKE_VERSION=`sed -n '/^MAKE_VERSION=/s,.*=[^0-9]*,,p' $srcdir/Makefile`
MAKE_VERSION=@_MAKE_VERSION@
MDEFS="-DMAKE_VERSION=\"$MAKE_VERSION\" \
-D@force_machine@MACHINE=\"@machine@\" -DMACHINE_ARCH=\"@machine_arch@\" \
@ -23,6 +23,10 @@ MDEFS="-DMAKE_VERSION=\"$MAKE_VERSION\" \
LDFLAGS="@LDFLAGS@"
LIBS="@LIBS@"
toUpper() {
${TR:-tr} abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
}
do_compile2() {
obj="$1"; shift
src="$1"; shift
@ -32,7 +36,10 @@ do_compile2() {
do_compile() {
obj="$1"; shift
src=`basename "$obj" .o`.c
case "$1" in
*.c) src=$1; shift;;
*) src=`basename "$obj" .o`.c;;
esac
for d in "$srcdir" "$srcdir/lst.lib"
do
@ -52,7 +59,7 @@ do_link() {
}
BASE_OBJECTS="arch.o buf.o compat.o cond.o dir.o for.o getopt hash.o \
job.o make.o make_malloc.o parse.o sigcompat.o str.o strlist.o \
make.o make_malloc.o metachar.o parse.o sigcompat.o str.o strlist.o \
suff.o targ.o trace.o var.o util.o"
LST_OBJECTS="lstAppend.o lstDupl.o lstInit.o lstOpen.o \
@ -73,12 +80,22 @@ done
case "@use_meta@" in
yes)
case "@filemon_h@" in
*/filemon.h) FDEFS="-DHAVE_FILEMON_H -I`dirname @filemon_h@`";;
case "@use_filemon@" in
no) MDEFS=;;
*)
MDEFS="-DUSE_FILEMON -DUSE_FILEMON_`echo @use_filemon@ | toUpper`"
case "@use_filemon@,@filemon_h@" in
dev,*/filemon.h) FDEFS="-DHAVE_FILEMON_H -I`dirname @filemon_h@`";;
*) FDEFS=;;
esac
do_compile filemon_@use_filemon@.o filemon/filemon_@use_filemon@.c ${FDEFS}
BASE_OBJECTS="filemon_@use_filemon@.o $BASE_OBJECTS"
;;
esac
do_compile meta.o ${FDEFS}
BASE_OBJECTS="meta.o ${BASE_OBJECTS}"
;;
do_compile meta.o ${MDEFS}
BASE_OBJECTS="meta.o ${BASE_OBJECTS}"
;;
esac
do_compile job.o ${MDEFS}
do_link bmake main.o ${BASE_OBJECTS} ${LST_OBJECTS} ${LIB_OBJECTS}
do_link bmake main.o job.o ${BASE_OBJECTS} ${LST_OBJECTS} ${LIB_OBJECTS}

View File

@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $
.\" $NetBSD: make.1,v 1.1.1.11 2020/05/24 05:35:52 nia 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 April 9, 2015
.Dd April 27, 2020
.Dt MAKE 1
.Os
.Sh NAME
@ -48,6 +48,7 @@
.Op Fl m Ar directory
.Op Fl T Ar file
.Op Fl V Ar variable
.Op Fl v Ar variable
.Op Ar variable=value
.Op Ar target ...
.Sh DESCRIPTION
@ -206,7 +207,9 @@ Print debugging information about target list maintenance.
.It Ar V
Force the
.Fl V
option to print raw values of variables.
option to print raw values of variables, overriding the default behavior
set via
.Va .MAKE.EXPAND_VARIABLES .
.It Ar v
Print debugging information about variable assignment.
.It Ar x
@ -269,7 +272,7 @@ that do not depend on the target whose creation caused the error.
.It Fl m Ar directory
Specify a directory in which to search for sys.mk and makefiles included
via the
.Ao Ar file Ac Ns -style
.Li \&< Ns Ar file Ns Li \&> Ns -style
include statement.
The
.Fl m
@ -277,7 +280,7 @@ option can be used multiple times to form a search path.
This path will override the default system include path: /usr/share/mk.
Furthermore the system include path will be appended to the search path used
for
.Qo Ar file Qc Ns -style
.Li \*q Ns Ar file Ns Li \*q Ns -style
include statements (see the
.Fl I
option).
@ -293,7 +296,7 @@ then
will search for the specified file or directory named in the remaining part
of the argument string.
The search starts with the current directory of
the Makefile and then works upward towards the root of the filesystem.
the Makefile and then works upward towards the root of the file system.
If the search is successful, then the resulting directory replaces the
.Qq \&.../
specification in the
@ -334,20 +337,39 @@ for each job started and completed.
Rather than re-building a target as specified in the makefile, create it
or update its modification time to make it appear up-to-date.
.It Fl V Ar variable
Print
.Nm Ns 's
idea of the value of
.Ar variable ,
in the global context.
Print the value of
.Ar variable .
Do not build any targets.
Multiple instances of this option may be specified;
the variables will be printed one per line,
with a blank line for each null or undefined variable.
The value printed is extracted from the global context after all
makefiles have been read.
By default, the raw variable contents (which may
include additional unexpanded variable references) are shown.
If
.Ar variable
contains a
.Ql \&$
then the value will be expanded before printing.
then the value will be recursively expanded to its complete resultant
text before printing.
The expanded value will also be printed if
.Va .MAKE.EXPAND_VARIABLES
is set to true and
the
.Fl dV
option has not been used to override it.
Note that loop-local and target-local variables, as well as values
taken temporarily by global variables during makefile processing, are
not accessible via this option.
The
.Fl dv
debug mode can be used to see these at the cost of generating
substantial extraneous output.
.It Fl v Ar variable
Like
.Fl V
but the variable is always expanded to its complete value.
.It Fl W
Treat any warnings during makefile parsing as errors.
.It Fl w
@ -657,7 +679,7 @@ The seven local variables are as follows:
.Bl -tag -width ".ARCHIVE" -offset indent
.It Va .ALLSRC
The list of all sources for this target; also known as
.Ql Va \&\*[Gt] .
.Ql Va \&> .
.It Va .ARCHIVE
The name of the archive file; also known as
.Ql Va \&! .
@ -666,7 +688,7 @@ In suffix-transformation rules, the name/path of the source from which the
target is to be transformed (the
.Dq implied
source); also known as
.Ql Va \&\*[Lt] .
.Ql Va \&< .
It is not defined in explicit rules.
.It Va .MEMBER
The name of the archive member; also known as
@ -685,12 +707,15 @@ or it will not be recognized.
.It Va .TARGET
The name of the target; also known as
.Ql Va @ .
For compatibility with other makes this is an alias for
.Ic .ARCHIVE
in archive member rules.
.El
.Pp
The shorter forms
.Ql ( Va \*[Gt] ,
.Ql ( Va > ,
.Ql Va \&! ,
.Ql Va \*[Lt] ,
.Ql Va < ,
.Ql Va % ,
.Ql Va \&? ,
.Ql Va * ,
@ -773,6 +798,10 @@ from which generated dependencies are read.
A boolean that controls the default behavior of the
.Fl V
option.
If true, variable values printed with
.Fl V
are fully expanded; if false, the raw variable contents (which may
include additional unexpanded variable references) are shown.
.It Va .MAKE.EXPORTED
The list of variables exported by
.Nm .
@ -843,7 +872,7 @@ Can affect the mode that
.Nm
runs in.
It can contain a number of keywords:
.Bl -hang -width ignore-cmd
.Bl -hang -width missing-filemon=bf.
.It Pa compat
Like
.Fl B ,
@ -867,8 +896,19 @@ will not create .meta files in
This can be overridden by setting
.Va bf
to a value which represents True.
.It Pa missing-meta= Ar bf
If
.Va bf
is True, then a missing .meta file makes the target out-of-date.
.It Pa missing-filemon= Ar bf
If
.Va bf
is True, then missing filemon data makes the target out-of-date.
.It Pa nofilemon
Do not use
.Xr filemon 4 .
.It Pa env
For debugging, it can be useful to inlcude the environment
For debugging, it can be useful to include the environment
in the .meta file.
.It Pa verbose
If in "meta" mode, print a clue about the target being built.
@ -910,6 +950,12 @@ Provides a list of path prefixes that should be ignored;
because the contents are expected to change over time.
The default list includes:
.Ql Pa /dev /etc /proc /tmp /var/run /var/tmp
.It Va .MAKE.META.IGNORE_PATTERNS
Provides a list of patterns to match against pathnames.
Ignore any that match.
.It Va .MAKE.META.IGNORE_FILTER
Provides a list of variable modifiers to apply to each pathname.
Ignore if the expansion is an empty string.
.It Va .MAKE.META.PREFIX
Defines the message printed for each meta file updated in "meta verbose" mode.
The default value is:
@ -918,7 +964,7 @@ The default value is:
This variable is used to record the names of variables assigned to
on the command line, so that they may be exported as part of
.Ql Ev MAKEFLAGS .
This behaviour can be disabled by assigning an empty value to
This behavior can be disabled by assigning an empty value to
.Ql Va .MAKEOVERRIDES
within a makefile.
Extra variables can be exported from a makefile
@ -941,10 +987,35 @@ The process-id of
.It Va .MAKE.PPID
The parent process-id of
.Nm .
.It Va .MAKE.SAVE_DOLLARS
value should be a boolean that controls whether
.Ql $$
are preserved when doing
.Ql :=
assignments.
The default is false, for backwards compatibility.
Set to true for compatability with other makes.
If set to false,
.Ql $$
becomes
.Ql $
per normal evaluation rules.
.It Va MAKE_PRINT_VAR_ON_ERROR
When
.Nm
stops due to an error, it prints its name and the value of
stops due to an error, it sets
.Ql Va .ERROR_TARGET
to the name of the target that failed,
.Ql Va .ERROR_CMD
to the commands of the failed target,
and in "meta" mode, it also sets
.Ql Va .ERROR_CWD
to the
.Xr getcwd 3 ,
and
.Ql Va .ERROR_META_FILE
to the path of the meta file (if any) describing the failed target.
It then prints its name and the value of
.Ql Va .CURDIR
as well as the value of any variables named in
.Ql Va MAKE_PRINT_VAR_ON_ERROR .
@ -993,14 +1064,15 @@ This is especially useful with
.Ql Ev MAKEOBJDIR .
.Pp
.Ql Va .OBJDIR
may be modified in the makefile as a global variable.
may be modified in the makefile via the special target
.Ql Ic .OBJDIR .
In all cases,
.Nm
will
.Xr chdir 2
to
to the specified directory if it exists, and set
.Ql Va .OBJDIR
and set
and
.Ql Ev PWD
to that directory before executing any targets.
.
@ -1043,7 +1115,7 @@ sets
to the value of
.Ql Ev PWD
instead.
This behaviour is disabled if
This behavior is disabled if
.Ql Ev MAKEOBJDIRPREFIX
is set or
.Ql Ev MAKEOBJDIR
@ -1113,7 +1185,7 @@ The wildcard characters may be escaped with a backslash
As a consequence of the way values are split into words, matched,
and then joined, a construct like
.Dl ${VAR:M*}
will normalise the inter-word spacing, removing all leading and
will normalize the inter-word spacing, removing all leading and
trailing space, and converting multiple consecutive spaces
to single spaces.
.
@ -1133,7 +1205,7 @@ Randomize words in variable.
The results will be different each time you are referring to the
modified variable; use the assignment with expansion
.Pq Ql Cm \&:=
to prevent such behaviour.
to prevent such behavior.
For example,
.Bd -literal -offset indent
LIST= uno due tre quattro
@ -1155,22 +1227,39 @@ due uno quattro tre
.Ed
.It Cm \&:Q
Quotes every shell meta-character in the variable, so that it can be passed
safely to the shell.
.It Cm \&:q
Quotes every shell meta-character in the variable, and also doubles
.Sq $
characters so that it can be passed
safely through recursive invocations of
.Nm .
This is equivalent to:
.Sq \&:S/\e\&$/&&/g:Q .
.It Cm \&:R
Replaces each word in the variable with everything but its suffix.
.It Cm \&:gmtime
.It Cm \&:range[=count]
The value is an integer sequence representing the words of the original
value, or the supplied
.Va count .
.It Cm \&:gmtime[=utc]
The value is a format string for
.Xr strftime 3 ,
using the current
using
.Xr gmtime 3 .
If a
.Va utc
value is not provided or is 0, the current time is used.
.It Cm \&:hash
Compute a 32bit hash of the value and encode it as hex digits.
.It Cm \&:localtime
Compute a 32-bit hash of the value and encode it as hex digits.
.It Cm \&:localtime[=utc]
The value is a format string for
.Xr strftime 3 ,
using the current
using
.Xr localtime 3 .
If a
.Va utc
value is not provided or is 0, the current time is used.
.It Cm \&:tA
Attempt to convert variable to an absolute path using
.Xr realpath 3 ,
@ -1231,7 +1320,7 @@ it is anchored at the end of each word.
Inside
.Ar new_string ,
an ampersand
.Pq Ql \*[Am]
.Pq Ql &
is replaced by
.Ar old_string
(without any
@ -1340,6 +1429,29 @@ is the substring of
.Ar old_string
to be replaced in
.Ar new_string .
If only
.Ar old_string
contains the pattern matching character
.Ar % ,
and
.Ar old_string
matches, then the result is the
.Ar new_string .
If only the
.Ar new_string
contains the pattern matching character
.Ar % ,
then it is not treated specially and it is printed as a literal
.Ar %
on match.
If there is more than one pattern matching character
.Ar ( % )
in either the
.Ar new_string
or
.Ar old_string ,
only the first instance is treated specially (as the pattern character);
all subsequent instances are treated as regular characters
.Pp
Variable expansion occurs in the normal fashion inside both
.Ar old_string
@ -1370,6 +1482,27 @@ For example.
.Pp
However a single character variable is often more readable:
.Dl ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}
.It Cm \&:_[=var]
Save the current variable value in
.Ql $_
or the named
.Va var
for later reference.
Example usage:
.Bd -literal -offset indent
M_cmpv.units = 1 1000 1000000
M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \&\\
\\* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh
.Dv .if ${VERSION:${M_cmpv}} < ${3.1.12:L:${M_cmpv}}
.Ed
Here
.Ql $_
is used to save the result of the
.Ql :S
modifier which is later referenced using the index values from
.Ql :range .
.It Cm \&:U Ns Ar newval
If the variable is undefined
.Ar newval
@ -1443,7 +1576,7 @@ value is divided into words.
.Pp
Ordinarily, a value is treated as a sequence of words
delimited by white space.
Some modifiers suppress this behaviour,
Some modifiers suppress this behavior,
causing a value to be treated as a single word
(possibly containing embedded white space).
An empty value, or a value that consists entirely of white-space,
@ -1513,9 +1646,9 @@ dot
.Pq Ql \&.
character.
Files are included with either
.Cm \&.include Aq Ar file
.Cm \&.include \&< Ns Ar file Ns Cm \&>
or
.Cm \&.include Pf \*q Ar file Ns \*q .
.Cm \&.include \&\*q Ns Ar file Ns Cm \&\*q .
Variables between the angle brackets or double quotes are expanded
to form the file name.
If angle brackets are used, the included makefile is expected to be in
@ -1529,12 +1662,20 @@ For compatibility with other versions of
.Nm
.Ql include file ...
is also accepted.
.Pp
If the include statement is written as
.Cm .-include
or as
.Cm .sinclude
then errors locating and/or opening include files are ignored.
.Pp
If the include statement is written as
.Cm .dinclude
not only are errors locating and/or opening include files ignored,
but stale dependencies within the included file will be ignored
just like
.Va .MAKE.DEPENDFILE .
.Pp
Conditional expressions are also preceded by a single dot as the first
character of a line.
The possible conditionals are as follows:
@ -1570,6 +1711,10 @@ This allows exporting a value to the environment which is different from that
used by
.Nm
internally.
.It Ic .export-literal Ar variable ...
The same as
.Ql .export-env ,
except that variables in the value are not expanded.
.It Ic .info Ar message
The message is printed along with the name of the makefile and line number.
.It Ic .undef Ar variable
@ -1662,7 +1807,7 @@ may be any one of the following:
.Bl -tag -width "Cm XX"
.It Cm \&|\&|
Logical OR.
.It Cm \&\*[Am]\*[Am]
.It Cm \&&&
Logical
.Tn AND ;
of higher precedence than
@ -1679,7 +1824,7 @@ The boolean operator
may be used to logically negate an entire
conditional.
It is of higher precedence than
.Ql Ic \&\*[Am]\*[Am] .
.Ql Ic \&&& .
.Pp
The value of
.Ar expression
@ -1750,7 +1895,8 @@ expression is applied.
Similarly, if the form is
.Ql Ic .ifmake
or
.Ql Ic .ifnmake , the
.Ql Ic .ifnmake ,
the
.Dq make
expression is applied.
.Pp
@ -1953,6 +2099,14 @@ variable of a target that inherits
.Ic .DEFAULT Ns 's
commands is set
to the target's own name.
.It Ic .DELETE_ON_ERROR
If this target is present in the makefile, it globally causes make to
delete targets whose commands fail.
(By default, only targets whose commands are interrupted during
execution are deleted.
This is the historical behavior.)
This setting can be used to help prevent half-finished or malformed
targets from being left around and corrupting future rebuilds.
.It Ic .END
Any command lines attached to this target are executed after everything
else is done.
@ -2001,6 +2155,15 @@ Disable parallel mode.
Synonym for
.Ic .NOTPARALLEL ,
for compatibility with other pmake variants.
.It Ic .OBJDIR
The source is a new value for
.Ql Va .OBJDIR .
If it exists,
.Nm
will
.Xr chdir 2
to it and update the value of
.Ql Va .OBJDIR .
.It Ic .ORDER
The named targets are made in sequence.
This ordering does not add targets to the list of targets to be made.
@ -2058,7 +2221,7 @@ The sources are a set of
pairs.
.Bl -tag -width hasErrCtls
.It Ar name
This is the minimal specification, used to select one of the builtin
This is the minimal specification, used to select one of the built-in
shell specs;
.Ar sh ,
.Ar ksh ,
@ -2264,9 +2427,9 @@ file).
.Sh BUGS
The
.Nm
syntax is difficult to parse without actually acting of the data.
For instance finding the end of a variable use should involve scanning each
the modifiers using the correct terminator for each field.
syntax is difficult to parse without actually acting on the data.
For instance, finding the end of a variable's use should involve scanning
each of the modifiers, using the correct terminator for each field.
In many places
.Nm
just counts {} and () in order to find the end of a variable expansion.

View File

@ -1,4 +1,4 @@
/* $NetBSD: make.c,v 1.1.1.8 2015/05/19 21:36:44 joerg Exp $ */
/* $NetBSD: make.c,v 1.1.1.9 2020/05/24 05:35:52 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: make.c,v 1.1.1.8 2015/05/19 21:36:44 joerg Exp $";
static char rcsid[] = "$NetBSD: make.c,v 1.1.1.9 2020/05/24 05:35:52 nia Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: make.c,v 1.1.1.8 2015/05/19 21:36:44 joerg Exp $");
__RCSID("$NetBSD: make.c,v 1.1.1.9 2020/05/24 05:35:52 nia Exp $");
#endif
#endif /* not lint */
#endif
@ -308,7 +308,7 @@ Make_OODate(GNode *gn)
if (DEBUG(MAKE)) {
if (gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime) {
fprintf(debug_file, "modified before source %s...",
gn->cmgn->path);
gn->cmgn->path ? gn->cmgn->path : gn->cmgn->name);
} else if (gn->mtime == 0) {
fprintf(debug_file, "non-existent and no sources...");
} else {
@ -482,10 +482,9 @@ Make_HandleUse(GNode *cgn, GNode *pgn)
if (gn->uname == NULL) {
gn->uname = gn->name;
} else {
if (gn->name)
free(gn->name);
free(gn->name);
}
gn->name = Var_Subst(NULL, gn->uname, pgn, FALSE);
gn->name = Var_Subst(NULL, gn->uname, pgn, VARF_WANTRES);
if (gn->name && gn->uname && strcmp(gn->name, gn->uname) != 0) {
/* See if we have a target for this node. */
tgn = Targ_FindNode(gn->name, TARG_NOCREATE);
@ -692,8 +691,7 @@ Make_Update(GNode *cgn)
checked++;
cname = Var_Value(TARGET, cgn, &p1);
if (p1)
free(p1);
free(p1);
if (DEBUG(MAKE))
fprintf(debug_file, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num);
@ -838,8 +836,7 @@ Make_Update(GNode *cgn)
Var_Set(PREFIX, cpref, pgn, 0);
}
}
if (p1)
free(p1);
free(p1);
Lst_Close(cgn->iParents);
}
}
@ -907,8 +904,7 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
}
if (allsrc != NULL)
Var_Append(ALLSRC, allsrc, pgn);
if (p2)
free(p2);
free(p2);
if (pgn->type & OP_JOIN) {
if (cgn->made == MADE) {
Var_Append(OODATE, child, pgn);
@ -934,8 +930,7 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
*/
Var_Append(OODATE, child, pgn);
}
if (p1)
free(p1);
free(p1);
}
return (0);
}
@ -981,8 +976,7 @@ Make_DoAllVar(GNode *gn)
if (gn->type & OP_JOIN) {
char *p1;
Var_Set(TARGET, Var_Value(ALLSRC, gn, &p1), gn, 0);
if (p1)
free(p1);
free(p1);
}
gn->flags |= DONE_ALLSRC;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: make.h,v 1.1.1.8 2015/05/19 21:36:44 joerg Exp $ */
/* $NetBSD: make.h,v 1.1.1.9 2020/05/24 05:35:52 nia Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -88,6 +88,7 @@
#include <sys/param.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
@ -98,6 +99,10 @@
#include <unistd.h>
#include <sys/cdefs.h>
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
#if defined(__GNUC__)
#define MAKE_GNUC_PREREQ(x, y) \
((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \
@ -194,6 +199,7 @@ typedef struct GNode {
#define DONE_ALLSRC 0x40 /* We do it once only */
#define CYCLE 0x1000 /* Used by MakePrintStatus */
#define DONECYCLE 0x2000 /* Used by MakePrintStatus */
#define INTERNAL 0x4000 /* Internal use only */
enum enum_made {
UNMADE, DEFERRED, REQUESTED, BEINGMADE,
MADE, UPTODATE, ERROR, ABORTED
@ -340,6 +346,7 @@ typedef struct GNode {
* once the makefile has been parsed. PARSE_WARNING means it can. Passed
* as the first argument to Parse_Error.
*/
#define PARSE_INFO 3
#define PARSE_WARNING 2
#define PARSE_FATAL 1
@ -383,6 +390,7 @@ extern Boolean beSilent; /* True if should print no commands */
extern Boolean noExecute; /* True if should execute nothing */
extern Boolean noRecursiveExecute; /* True if should execute nothing */
extern Boolean allPrecious; /* True if every target is precious */
extern Boolean deleteOnError; /* True if failed targets should be deleted */
extern Boolean keepgoing; /* True if should continue on unaffected
* portions of the graph when have an error
* in one portion */
@ -456,7 +464,7 @@ extern pid_t myPid;
* There is one bit per module. It is up to the module what debug
* information to print.
*/
FILE *debug_file; /* Output written here - default stdout */
extern FILE *debug_file; /* Output written here - default stdout */
extern int debug;
#define DEBUG_ARCH 0x00001
#define DEBUG_COND 0x00002
@ -497,9 +505,15 @@ char * Check_Cwd_Cmd(const char *);
void Check_Cwd(const char **);
void PrintOnError(GNode *, const char *);
void Main_ExportMAKEFLAGS(Boolean);
Boolean Main_SetObjdir(const char *);
Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
int mkTempFile(const char *, char **);
int str2Lst_Append(Lst, char *, const char *);
int cached_lstat(const char *, void *);
int cached_stat(const char *, void *);
#define VARF_UNDEFERR 1
#define VARF_WANTRES 2
#define VARF_ASSIGN 4
#ifdef __GNUC__
#define UNCONST(ptr) ({ \
@ -519,8 +533,21 @@ int str2Lst_Append(Lst, char *, const char *);
#define MAX(a, b) ((a > b) ? a : b)
#endif
/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifndef MAXPATHLEN
#define MAXPATHLEN BMAKE_PATH_MAX
#define MAXPATHLEN BMAKE_PATH_MAX
#endif
#ifndef PATH_MAX
#define PATH_MAX MAXPATHLEN
#endif
#if defined(SYSV)
#define KILLPG(pid, sig) kill(-(pid), (sig))
#else
#define KILLPG(pid, sig) killpg((pid), (sig))
#endif
#endif /* _MAKE_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: make_malloc.c,v 1.1.1.3 2015/05/19 21:36:44 joerg Exp $ */
/* $NetBSD: make_malloc.c,v 1.1.1.4 2020/05/24 05:35:52 nia Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@ -28,7 +28,7 @@
#ifdef MAKE_NATIVE
#include <sys/cdefs.h>
__RCSID("$NetBSD: make_malloc.c,v 1.1.1.3 2015/05/19 21:36:44 joerg Exp $");
__RCSID("$NetBSD: make_malloc.c,v 1.1.1.4 2020/05/24 05:35:52 nia Exp $");
#endif
#include <stdio.h>
@ -39,13 +39,13 @@ __RCSID("$NetBSD: make_malloc.c,v 1.1.1.3 2015/05/19 21:36:44 joerg Exp $");
#include "make.h"
#ifndef USE_EMALLOC
static void enomem(void) MAKE_ATTR_DEAD;
static MAKE_ATTR_DEAD void enomem(void);
/*
* enomem --
* die when out of memory.
*/
static void
static MAKE_ATTR_DEAD void
enomem(void)
{
(void)fprintf(stderr, "%s: %s.\n", progname, strerror(ENOMEM));

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: meta.h,v 1.1.1.2 2015/05/19 21:36:44 joerg Exp $ */
/* $NetBSD: meta.h,v 1.1.1.3 2020/05/24 05:35:52 nia Exp $ */
/*
* Things needed for 'meta' mode.
@ -33,7 +33,7 @@
typedef struct BuildMon {
char meta_fname[MAXPATHLEN];
int filemon_fd;
struct filemon *filemon;
int mon_fd;
FILE *mfp;
} BuildMon;
@ -42,14 +42,18 @@ extern Boolean useMeta;
struct Job; /* not defined yet */
void meta_init(void);
void meta_finish(void);
void meta_mode_init(const char *);
void meta_job_start(struct Job *, GNode *);
void meta_job_child(struct Job *);
void meta_job_parent(struct Job *, pid_t);
int meta_job_fd(struct Job *);
int meta_job_event(struct Job *);
void meta_job_error(struct Job *, GNode *, int, int);
void meta_job_output(struct Job *, char *, const char *);
void meta_cmd_finish(void *);
void meta_job_finish(struct Job *);
int meta_cmd_finish(void *);
int meta_job_finish(struct Job *);
Boolean meta_oodate(GNode *, Boolean);
void meta_compat_start(void);
void meta_compat_child(void);
void meta_compat_parent(void);
void meta_compat_parent(pid_t);

View File

@ -0,0 +1,88 @@
/* $NetBSD: metachar.c,v 1.1.1.1 2020/05/24 05:35:52 nia Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#if defined(MAKE_NATIVE) || defined(HAVE_NBTOOL_CONFIG_H)
#include <sys/cdefs.h>
#endif
#if defined(__RCSID) && !defined(lint)
__RCSID("$NetBSD: metachar.c,v 1.1.1.1 2020/05/24 05:35:52 nia Exp $");
#endif
#include "metachar.h"
/*
* The following array is used to make a fast determination of which
* characters are interpreted specially by the shell. If a command
* contains any of these characters, it is executed by the shell, not
* directly by us.
*
* perhaps move it to ctype?
*/
unsigned char _metachar[128] = {
// nul soh stx etx eot enq ack bel
1, 0, 0, 0, 0, 0, 0, 0,
// bs ht nl vt np cr so si
0, 0, 1, 0, 0, 0, 0, 0,
// dle dc1 dc2 dc3 dc4 nak syn etb
0, 0, 0, 0, 0, 0, 0, 0,
// can em sub esc fs gs rs us
0, 0, 0, 0, 0, 0, 0, 0,
// sp ! " # $ % & '
0, 1, 1, 1, 1, 0, 1, 1,
// ( ) * + , - . /
1, 1, 1, 0, 0, 0, 0, 0,
// 0 1 2 3 4 5 6 7
0, 0, 0, 0, 0, 0, 0, 0,
// 8 9 : ; < = > ?
0, 0, 0, 1, 1, 0, 1, 1,
// @ A B C D E F G
0, 0, 0, 0, 0, 0, 0, 0,
// H I J K L M N O
0, 0, 0, 0, 0, 0, 0, 0,
// P Q R S T U V W
0, 0, 0, 0, 0, 0, 0, 0,
// X Y Z [ \ ] ^ _
0, 0, 0, 1, 1, 1, 1, 0,
// ` a b c d e f g
1, 0, 0, 0, 0, 0, 0, 0,
// h i j k l m n o
0, 0, 0, 0, 0, 0, 0, 0,
// p q r s t u v w
0, 0, 0, 0, 0, 0, 0, 0,
// x y z { | } ~ del
0, 0, 0, 1, 1, 1, 1, 0,
};

View File

@ -0,0 +1,61 @@
/* $NetBSD: metachar.h,v 1.1.1.1 2020/05/24 05:35:52 nia Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _METACHAR_H
#define _METACHAR_H
#include <ctype.h>
extern unsigned char _metachar[];
#define ismeta(c) _metachar[(c) & 0x7f]
static inline int
hasmeta(const char *cmd)
{
while (!ismeta(*cmd))
cmd++;
return *cmd != '\0';
}
static inline int
needshell(const char *cmd, int white)
{
while (!ismeta(*cmd) && *cmd != ':' && *cmd != '=') {
if (white && isspace((unsigned char)*cmd))
break;
cmd++;
}
return *cmd != '\0';
}
#endif /* _METACHAR_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,72 @@
ChangeLog
FILES
README
auto.obj.mk
autoconf.mk
autodep.mk
auto.dep.mk
compiler.mk
cython.mk
dep.mk
doc.mk
dpadd.mk
files.mk
final.mk
host-target.mk
host.libnames.mk
inc.mk
init.mk
install-mk
java.mk
ldorder.mk
lib.mk
libnames.mk
libs.mk
links.mk
man.mk
manifest.mk
mk-files.txt
mkopt.sh
nls.mk
obj.mk
options.mk
own.mk
prlist.mk
prog.mk
progs.mk
rst2htm.mk
scripts.mk
srctop.mk
stage-install.sh
subdir.mk
sys.mk
sys.clean-env.mk
sys.debug.mk
sys.dependfile.mk
sys.vars.mk
sys/AIX.mk
sys/Darwin.mk
sys/Generic.mk
sys/HP-UX.mk
sys/IRIX.mk
sys/Linux.mk
sys/NetBSD.mk
sys/OSF1.mk
sys/OpenBSD.mk
sys/SunOS.mk
sys/UnixWare.mk
target-flags.mk
warnings.mk
whats.mk
yacc.mk
dirdeps.mk
dirdeps-options.mk
dirdeps-targets.mk
gendirdeps.mk
install-new.mk
meta2deps.py
meta2deps.sh
meta.sys.mk
meta.autodep.mk
meta.stage.mk
meta.subdir.mk

401
devel/bmake/files/mk/README Normal file
View File

@ -0,0 +1,401 @@
# $Id: README,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
This directory contains some macro's derrived from the NetBSD bsd.*.mk
macros. They have the same names but without the bsd., separate macro
files are needed to ensure we can make them do what we want for
builing things outside of /usr/src. Nearly all the comments below
apply.
# $NetBSD: README,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# @(#)bsd.README 5.1 (Berkeley) 5/11/90
This is the README file for the new make "include" files for the BSD
source tree. The files are installed in /usr/share/mk, and are, by
convention, named with the suffix ".mk".
Note, this file is not intended to replace reading through the .mk
files for anything tricky.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
RANDOM THINGS WORTH KNOWING:
The files are simply C-style #include files, and pretty much behave like
you'd expect. The syntax is slightly different in that a single '.' is
used instead of the hash mark, i.e. ".include <bsd.prog.mk>".
One difference that will save you lots of debugging time is that inclusion
of the file is normally done at the *end* of the Makefile. The reason for
this is because .mk files often modify variables and behavior based on the
values of variables set in the Makefile. To make this work, remember that
the FIRST target found is the target that is used, i.e. if the Makefile has:
a:
echo a
a:
echo a number two
the command "make a" will echo "a". To make things confusing, the SECOND
variable assignment is the overriding one, i.e. if the Makefile has:
a= foo
a= bar
b:
echo ${a}
the command "make b" will echo "bar". This is for compatibility with the
way the V7 make behaved.
It's fairly difficult to make the BSD .mk files work when you're building
multiple programs in a single directory. It's a lot easier split up the
programs than to deal with the problem. Most of the agony comes from making
the "obj" directory stuff work right, not because we switch to a new version
of make. So, don't get mad at us, figure out a better way to handle multiple
architectures so we can quit using the symbolic link stuff. (Imake doesn't
count.)
The file .depend in the source directory is expected to contain dependencies
for the source files. This file is read automatically by make after reading
the Makefile.
The variable DESTDIR works as before. It's not set anywhere but will change
the tree where the file gets installed.
The profiled libraries are no longer built in a different directory than
the regular libraries. A new suffix, ".po", is used to denote a profiled
object.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The include file <sys.mk> has the default rules for all makes, in the BSD
environment or otherwise. You probably don't want to touch this file.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The include file <bsd.man.mk> handles installing manual pages and their
links.
It has a single target:
maninstall:
Install the manual pages and their links.
It sets/uses the following variables:
MANDIR Base path for manual installation.
MANGRP Manual group.
MANOWN Manual owner.
MANMODE Manual mode.
MANSUBDIR Subdirectory under the manual page section, i.e. "/vax"
or "/tahoe" for machine specific manual pages.
MAN The manual pages to be installed (use a .1 - .9 suffix).
MLINKS List of manual page links (using a .1 - .9 suffix). The
linked-to file must come first, the linked file second,
and there may be multiple pairs. The files are soft-linked.
The include file <bsd.man.mk> includes a file named "../Makefile.inc" if
it exists.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The include file <bsd.own.mk> contains source tree configuration parameters,
such as the owners, groups, etc. for both manual pages and binaries, and
a few global "feature configuration" parameters.
It has no targets.
To get system-specific configuration parameters, bsd.own.mk will try to
include the file specified by the "MAKECONF" variable. If MAKECONF is not
set, or no such file exists, the system make configuration file, /etc/mk.conf
is included. These files may define any of the variables described below.
bsd.own.mk sets the following variables, if they are not already defined
(defaults are in brackets):
BSDSRCDIR The real path to the system sources, so that 'make obj'
will work correctly. [/usr/src]
BSDOBJDIR The real path to the system 'obj' tree, so that 'make obj'
will work correctly. [/usr/obj]
BINGRP Binary group. [bin]
BINOWN Binary owner. [bin]
BINMODE Binary mode. [555]
NONBINMODE Mode for non-executable files. [444]
MANDIR Base path for manual installation. [/usr/share/man/cat]
MANGRP Manual group. [bin]
MANOWN Manual owner. [bin]
MANMODE Manual mode. [${NONBINMODE}]
LIBDIR Base path for library installation. [/usr/lib]
LINTLIBDIR Base path for lint(1) library installation. [/usr/libdata/lint]
LIBGRP Library group. [${BINGRP}]
LIBOWN Library owner. [${BINOWN}]
LIBMODE Library mode. [${NONBINMODE}]
DOCDIR Base path for system documentation (e.g. PSD, USD, etc.)
installation. [/usr/share/doc]
DOCGRP Documentation group. [bin]
DOCOWN Documentation owner. [bin]
DOCMODE Documentation mode. [${NONBINMODE}]
NLSDIR Base path for National Language Support files installation.
[/usr/share/nls]
NLSGRP National Language Support files group. [bin]
NLSOWN National Language Support files owner. [bin]
NLSMODE National Language Support files mode. [${NONBINMODE}]
STRIP The flag passed to the install program to cause the binary
to be stripped. This is to be used when building your
own install script so that the entire system can be made
stripped/not-stripped using a single knob. [-s]
COPY The flag passed to the install program to cause the binary
to be copied rather than moved. This is to be used when
building our own install script so that the entire system
can either be installed with copies, or with moves using
a single knob. [-c]
Additionally, the following variables may be set by bsd.own.mk or in a
make configuration file to modify the behaviour of the system build
process (default values are in brackets along with comments, if set by
bsd.own.mk):
EXPORTABLE_SYSTEM
Do not build /usr/src/domestic, even if it is present.
SKEY Compile in support for S/key authentication. [yes, set
unconditionally]
KERBEROS Compile in support for Kerberos 4 authentication.
KERBEROS5 Compile in support for Kerberos 5 authentication.
MANZ Compress manual pages at installation time.
SYS_INCLUDE Copy or symlink kernel include files into /usr/include.
Possible values are "symlinks" or "copies" (which is
the same as the variable being unset).
NOPROFILE Do not build profiled versions of system libraries
NOPIC Do not build PIC versions of system libraries, and
do not build shared libraries. [set if ${MACHINE_ARCH}
is "mips", "vax", "alpha" or "arm32", unset otherwise.]
NOLINT Do not build lint libraries. [set, set unconditionally]
bsd.own.mk is generally useful when building your own Makefiles so that
they use the same default owners etc. as the rest of the tree.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The include file <bsd.prog.mk> handles building programs from one or
more source files, along with their manual pages. It has a limited number
of suffixes, consistent with the current needs of the BSD tree.
It has eight targets:
all:
build the program and its manual page
clean:
remove the program, any object files and the files a.out,
Errs, errs, mklog, and core.
cleandir:
remove all of the files removed by the target clean, as
well as .depend, tags, and any manual pages.
depend:
make the dependencies for the source files, and store
them in the file .depend.
includes:
install any header files.
install:
install the program and its manual pages; if the Makefile
does not itself define the target install, the targets
beforeinstall and afterinstall may also be used to cause
actions immediately before and after the install target
is executed.
lint:
run lint on the source files
tags:
create a tags file for the source files.
It sets/uses the following variables:
BINGRP Binary group.
BINOWN Binary owner.
BINMODE Binary mode.
CLEANFILES Additional files to remove for the clean and cleandir targets.
COPTS Additional flags to the compiler when creating C objects.
HIDEGAME If HIDEGAME is defined, the binary is installed in
/usr/games/hide, and a symbolic link is created to
/usr/games/dm.
LDADD Additional loader objects. Usually used for libraries.
For example, to load with the compatibility and utility
libraries, use:
LDADD+=-lutil -lcompat
LDFLAGS Additional loader flags.
LINKS The list of binary links; should be full pathnames, the
linked-to file coming first, followed by the linked
file. The files are hard-linked. For example, to link
/bin/test and /bin/[, use:
LINKS= ${DESTDIR}/bin/test ${DESTDIR}/bin/[
MAN Manual pages (should end in .1 - .9). If no MAN variable is
defined, "MAN=${PROG}.1" is assumed.
PROG The name of the program to build. If not supplied, nothing
is built.
SRCS List of source files to build the program. If PROG is not
defined, it's assumed to be ${PROG}.c.
DPADD Additional dependencies for the program. Usually used for
libraries. For example, to depend on the compatibility and
utility libraries use:
DPADD+=${LIBCOMPAT} ${LIBUTIL}
The following libraries are predefined for DPADD:
LIBC /lib/libc.a
LIBCOMPAT /usr/lib/libcompat.a
LIBCRYPT /usr/lib/libcrypt.a
LIBCURSES /usr/lib/libcurses.a
LIBDBM /usr/lib/libdbm.a
LIBDES /usr/lib/libdes.a
LIBL /usr/lib/libl.a
LIBKDB /usr/lib/libkdb.a
LIBKRB /usr/lib/libkrb.a
LIBKVM /usr/lib/libkvm.a
LIBM /usr/lib/libm.a
LIBMP /usr/lib/libmp.a
LIBPC /usr/lib/libpc.a
LIBPLOT /usr/lib/libplot.a
LIBRPC /usr/lib/sunrpc.a
LIBTERM /usr/lib/libterm.a
LIBUTIL /usr/lib/libutil.a
SHAREDSTRINGS If defined, a new .c.o rule is used that results in shared
strings, using xstr(1). Note that this will not work with
parallel makes.
STRIP The flag passed to the install program to cause the binary
to be stripped.
SUBDIR A list of subdirectories that should be built as well.
Each of the targets will execute the same target in the
subdirectories.
The include file <bsd.prog.mk> includes the file named "../Makefile.inc"
if it exists, as well as the include file <bsd.man.mk>.
Some simple examples:
To build foo from foo.c with a manual page foo.1, use:
PROG= foo
.include <bsd.prog.mk>
To build foo from foo.c with a manual page foo.2, add the line:
MAN= foo.2
If foo does not have a manual page at all, add the line:
NOMAN= noman
If foo has multiple source files, add the line:
SRCS= a.c b.c c.c d.c
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The include file <bsd.subdir.mk> contains the default targets for building
subdirectories. It has the same eight targets as <bsd.prog.mk>: all,
clean, cleandir, depend, includes, install, lint, and tags. For all of
the directories listed in the variable SUBDIRS, the specified directory
will be visited and the target made. There is also a default target which
allows the command "make subdir" where subdir is any directory listed in
the variable SUBDIRS.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The include file <bsd.sys.mk> is used by <bsd.prog.mk> and
<bsd.lib.mk>. It contains overrides that are used when building
the NetBSD source tree. For instance, if "PARALLEL" is defined by
the program/library Makefile, it includes a set of rules for lex and
yacc that allow multiple lex and yacc targets to be built in parallel.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The include file <bsd.lib.mk> has support for building libraries. It has
the same eight targets as <bsd.prog.mk>: all, clean, cleandir, depend,
includes, install, lint, and tags. It has a limited number of suffixes,
consistent with the current needs of the BSD tree.
It sets/uses the following variables:
LIB The name of the library to build.
LIBDIR Target directory for libraries.
LINTLIBDIR Target directory for lint libraries.
LIBGRP Library group.
LIBOWN Library owner.
LIBMODE Library mode.
LDADD Additional loader objects.
MAN The manual pages to be installed (use a .1 - .9 suffix).
SRCS List of source files to build the library. Suffix types
.s, .c, and .f are supported. Note, .s files are preferred
to .c files of the same name. (This is not the default for
versions of make.)
The include file <bsd.lib.mk> includes the file named "../Makefile.inc"
if it exists, as well as the include file <bsd.man.mk>.
It has rules for building profiled objects; profiled libraries are
built by default.
Libraries are ranlib'd when made.

View File

@ -0,0 +1,74 @@
#
# RCSid:
# $Id: auto.dep.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2010, 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 module provides automagic dependency generation along the
# lines suggested in the GNU make.info
# 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
# this makes it simpler to get the args to -MF and -MT right
# and ensure we can simply include all the .d files.
#
# However suffix rules do not work with something like .o.d so we
# don't even try to handle 'make depend' gracefully.
# dep.mk will handle that itself.
#
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
# this what bmake > 20100401 will look for
.MAKE.DEPENDFILE ?= .depend
# set this to -MMD to ignore /usr/include
# actually it ignores <> so may not be a great idea
CFLAGS_MD ?= -MD
# -MF etc not available on all gcc versions.
CFLAGS_MF ?= -MF ${.TARGET:T}.d -MT ${.TARGET:T}
CFLAGS += ${CFLAGS_MD} ${CFLAGS_MF}
CXXFLAGS += ${CFLAGS_MD} ${CFLAGS_MF}
CLEANFILES += .depend ${.MAKE.DEPENDFILE} *.d
.if ${MAKE_VERSION} < 20160218
# skip generating dependfile for misc targets
.if ${.TARGETS:Uall:M*all} != ""
.END: ${.MAKE.DEPENDFILE}
.endif
# doing 'make depend' isn't a big win with this model
.if !target(depend)
depend: ${.MAKE.DEPENDFILE}
.endif
# this is trivial
${.MAKE.DEPENDFILE}: ${OBJS} ${POBJS} ${SOBJS}
-@for f in ${.ALLSRC:M*o:T:O:u:%=%.d}; do \
echo ".-include \"$$f\""; \
done > $@
.else
# we have .dinclude
.if empty(_SKIP_BUILD)
_all_objs = ${OBJS} ${POBJS} ${SOBJS}
.for d in ${_all_objs:M*o:T:O:u:%=%.d}
.dinclude <$d>
.endfor
.endif
.endif
.endif

View File

@ -0,0 +1,76 @@
# $Id: auto.obj.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2004, 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
#
ECHO_TRACE ?= echo
.ifndef Mkdirs
# A race condition in some versions of mkdir, means that it can bail
# if another process made a dir that mkdir expected to.
# We repeat the mkdir -p a number of times to try and work around this.
# We stop looping as soon as the dir exists.
# If we get to the end of the loop, a plain mkdir will issue an error.
Mkdirs= Mkdirs() { \
for d in $$*; do \
for i in 1 2 3 4 5 6; do \
mkdir -p $$d; \
test -d $$d && return 0; \
done > /dev/null 2>&1; \
mkdir $$d || exit $$?; \
done; }
.endif
# 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.
.if !empty(MAKEOBJDIRPREFIX)
.if ${.CURDIR:M${MAKEOBJDIRPREFIX}/*} != ""
# we are already in obj tree!
__objdir?= ${.CURDIR}
.endif
__objdir?= ${MAKEOBJDIRPREFIX}${.CURDIR}
.endif
__objdir?= ${MAKEOBJDIR:Uobj}
__objdir:= ${__objdir}
.if ${.OBJDIR:tA} != ${__objdir:tA}
# We need to chdir, make the directory if needed
.if !exists(${__objdir}/) && \
(${.TARGETS} == "" || ${.TARGETS:Nclean*:N*clean:Ndestroy*} != "")
# This will actually make it...
__objdir_made != echo ${__objdir}/; umask ${OBJDIR_UMASK:U002}; \
${ECHO_TRACE} "[Creating objdir ${__objdir}...]" >&2; \
${Mkdirs}; Mkdirs ${__objdir}
.endif
# This causes make to use the specified directory as .OBJDIR
.OBJDIR: ${__objdir}
.if ${.OBJDIR:tA} != ${__objdir:tA}
# we did not get what we want - do we care?
.if ${__objdir_made:Uno:M${__objdir}/*} != ""
# watch out for __objdir being relative path
.if !(${__objdir:M/*} == "" && ${.OBJDIR:tA} == ${${.CURDIR}/${__objdir}:L:tA})
.error could not use ${__objdir}: .OBJDIR=${.OBJDIR}
.endif
.endif
# apparently we can live with it
# make sure we know what we have
.OBJDIR: ${.CURDIR}
.endif
.endif
.endif

View File

@ -0,0 +1,80 @@
# $Id: autoconf.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 1996-2009, 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
#
.NOPATH: config.h config.status
CONFIGURE_DEPS += ${.CURDIR}/config.h.in ${.CURDIR}/configure
.if !target(config.h)
config.h: ${CONFIGURE_DEPS} config.status
./config.status
.endif
.if !target(config.status)
# avoid the targets behaving differently
.if exists(${.OBJDIR}/config.status)
config.status: config.recheck
.else
config.status: config.gen
.endif
config.recheck: ${CONFIGURE_DEPS}
./config.status --recheck
@touch $@
config.gen: ${CONFIGURE_DEPS}
CC="${CC} ${CCMODE}" ${.CURDIR}/configure --no-create ${CONFIGURE_ARGS}
@touch $@ config.recheck
CLEANFILES+= config.recheck config.gen config.status *.meta
.endif
# avoid things blowing up if these are not here...
# this is not quite per the autoconf manual,
# and is extremely convoluted - but all utterly necessary!
.if make(autoconf-in) || make(configure) || make(config.h.in) || ${AUTO_AUTOCONF:Uno:tl} == "yes"
AUTOCONF ?= autoconf
AUTOHEADER ?= autoheader
# expand it to a full path
AUTOCONF := ${AUTOCONF:${M_whence}}
.if exists(${AUTOCONF})
.PRECIOUS: configure config.h.in config.status
ACLOCAL =
ACCONFIG =
.if exists(${.CURDIR}/aclocal.m4)
ACLOCAL += aclocal.m4
.endif
# use of acconfig.h is deprecated!
.if exists(${.CURDIR}/acconfig.h)
ACCONFIG += acconfig.h
.endif
config.h.in: ${.CURDIR}/configure.in ${ACCONFIG}
(cd ${.CURDIR} && ${AUTOHEADER})
configure: ${.CURDIR}/configure.in ${ACLOCAL}
(cd ${.CURDIR} && ${AUTOCONF})
AUTOCONF_INPUTS += configure
autoconf-input: ${AUTOCONF_INPUTS}
.endif
.endif

View File

@ -0,0 +1,219 @@
#
# RCSid:
# $Id: autodep.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 1999-2010, 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 module provides automagic dependency generation along the
# lines suggested in the GNU make.info
# The depend target is mainly for backwards compatibility,
# dependencies are normally updated as part of compilation.
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
DEPENDFILE?= .depend
.for d in ${DEPENDFILE:N.depend}
# bmake only groks .depend
.if ${MAKE_VERSION} < 20160218
.-include <$d>
.else
.dinclude <$d>
.endif
.endfor
# it does nothing if SRCS is not defined or is empty
.if defined(SRCS) && !empty(SRCS)
DEPSRCS?=${SRCS}
__depsrcs=${DEPSRCS:M*.c}
__depsrcs+=${DEPSRCS:M*.y}
__depsrcs+=${DEPSRCS:M*.l}
__depsrcs+=${DEPSRCS:M*.s}
__depsrcs+=${DEPSRCS:M*.S}
__depsrcs+=${DEPSRCS:M*.cc}
__depsrcs+=${DEPSRCS:M*.cpp}
__depsrcs+=${DEPSRCS:M*.C}
__depsrcs+=${DEPSRCS:M*.cxx}
__depsrcs+=${DEPSRCS:M*.pc}
.for s in ${__depsrcs}
${s:T:R}.d: $s
.endfor
__depsrcs:=${__depsrcs:T:R:S/$/.d/g}
# we also need to handle makefiles where the .d's from __depsrcs
# don't match those from OBJS
# we avoid using := here, since the modifier applied to OBJS
# can cause trouble if there are any undefined vars in OBJS.
__dependsrcsx?= ${__depsrcs} ${OBJS:S/.o/.d/}
__dependsrcs= ${__dependsrcsx:O:u}
# clean up any .c files we may have generated
#__gensrcs:= ${DEPSRCS:M*.y} ${DEPSRCS:M*.l}
#CLEANFILES+= ${__gensrcs:T:R:S/$/.c/g}
# set this to -MMD to ignore /usr/include
# actually it ignores <> so may not be a great idea
CFLAGS_MD?=-MD
# -MF etc not available on all gcc versions.
# we "fix" the .o later
CFLAGS_MF?=-MF ${.TARGET:T:R}.d -MT ${.TARGET:T:R}.o
CFLAGS+= ${CFLAGS_MD} ${CFLAGS_MF}
RM?= rm
MAKE_SHELL?= sh
# watch out for people who don't use CPPFLAGS
CPPFLAGS_MD=${CFLAGS:M-[IUD]*} ${CPPFLAGS}
CXXFLAGS_MD=${CXXFLAGS:M-[IUD]*} ${CPPFLAGS}
# just in case these need to be different
CC_MD?=${CC}
CXX_MD?=${CXX}
# should have been set by sys.mk
CXX_SUFFIXES?= .cc .cpp .cxx .C
# so we can do an explicit make depend, but not otherwise
.if make(depend)
.SUFFIXES: .d
.if empty(CFLAGS_MD)
.y.d:
@echo updating dependencies for $<
@${YACC} ${YFLAGS} $<
@${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} y.tab.c | sed '/:/s/^/$@ /' > $@" || { ${RM} -f y.tab.c $@; false; }
@${RM} -f y.tab.c
.l.d:
@echo updating dependencies for $<
${LEX} ${LFLAGS} $<
@${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} lex.yy.c | sed '/:/s/^/$@ /' > $@" || { ${RM} -f lex.yy.c $@; false; }
@${RM} -f lex.yy.c
.c.d:
@echo updating dependencies for $<
@${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; }
.s.d .S.d:
@echo updating dependencies for $<
@${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} ${AINC} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; }
${CXX_SUFFIXES:%=%.d}:
@echo updating dependencies for $<
@${MAKE_SHELL} -ec "${CXX_MD} -M ${CXXFLAGS_MD} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; }
.else
.y.d:
${YACC} ${YFLAGS} $<
${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} y.tab.c > $@ || { ${RM} -f y.tab.c $@; false; }
${RM} -f y.tab.c
.l.d:
${LEX} ${LFLAGS} $<
${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} lex.yy.c > $@ || { ${RM} -f lex.yy.c $@; false; }
${RM} -f lex.yy.c
.c.d:
${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} $< > $@ || { ${RM} -f $@; false; }
.s.d .S.d:
${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} ${AINC} $< > $@ || { ${RM} -f $@; false; }
${CXX_SUFFIXES:%=%.d}:
${CXX_MD} ${CFLAGS_MD:S/D//} ${CXXFLAGS_MD} $< > $@ || { ${RM} -f $@; false; }
.endif
.if !target(depend)
depend: beforedepend ${DEPENDFILE} afterdepend _SUBDIRUSE
${DEPENDFILE}: ${DEPSRCS} ${__dependsrcs}
.NOPATH: ${__dependsrcs}
.OPTIONAL: ${__dependsrcs}
.endif
.endif # make(depend)
.if empty(CFLAGS_MD)
# make sure the .d's are generated/updated
${PROG} ${_LIBS}: ${DEPENDFILE}
.endif
.ORDER: beforedepend ${DEPENDFILE} afterdepend
.if ${.OBJDIR} != ${.CURDIR}
__depfiles= *.d
.else
__depfiles= ${__dependsrcs}
.endif
DEPCLEANFILES= ${DEPENDFILE} ${__depfiles} y.tab.d *.tmp.d
cleandir: cleanautodepend
cleanautodepend:
${RM} -f ${DEPCLEANFILES}
CLEANFILES+= ${DEPCLEANFILES}
.if defined(__dependsrcs) && !empty(__dependsrcs)
.if make(depend) || !(make(clean*) || make(destroy*) || make(obj) || make(*install) || make(install-*))
# this ensures we do the right thing if only building a shared or
# profiled lib
OBJ_EXTENSIONS?=.o .po .so .So
MDLIB_SED= -e '/:/s,^\([^\.:]*\)\.[psS]*o,${OBJ_EXTENSIONS:S,^,\1,},'
.ifdef NOMD_SED
.ifdef LIB
MD_SED=sed ${MDLIB_SED}
.else
MD_SED=cat
.endif
.else
# arrange to put some variable names into ${DEPENDFILE}
.ifdef LIB
MD_SED=sed ${MDLIB_SED}
.else
MD_SED=sed
.endif
SUBST_DEPVARS+= SB TOP BACKING SRC SRCDIR BASE BASEDIR
.for v in ${SUBST_DEPVARS}
.if defined(${v}) && !empty(${v})
MD_SED+= -e 's,${$v},$${$v},'
.endif
.endfor
.endif
.if (${MD_SED} == "sed")
MD_SED=cat
.endif
# this will be done whenever make finishes successfully
.if ${MAKE_VERSION:U0:[1]:C/.*-//} < 20050530
.END:
.else
.END: ${DEPENDFILE}
# we do not want to trigger building .d's just use them if they exist
${DEPENDFILE}: ${__dependsrcs:@d@${exists($d):?$d:}@}
.endif
-@${MD_SED} ${__depfiles} > ${DEPENDFILE}.new 2> /dev/null && \
test -s ${DEPENDFILE}.new && mv ${DEPENDFILE}.new ${DEPENDFILE}; \
${RM} -f ${DEPENDFILE}.new
.endif
.endif
.else
depend: beforedepend afterdepend _SUBDIRUSE
.endif
.if !target(beforedepend)
beforedepend:
.endif
.if !target(afterdepend)
afterdepend:
.endif
.endif

View File

@ -0,0 +1,43 @@
# $Id: compiler.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2019, 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 !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
.if ${MACHINE} == "common"
COMPILER_TYPE = none
COMPILER_VERSION = 0
.endif
.if empty(COMPILER_TYPE) || empty(COMPILER_VERSION)
# gcc does not always say gcc
_v != ${CC} --version 2> /dev/null | \
egrep -i 'clang|cc|[1-9]\.[0-9]|Free Software Foundation'
.if empty(COMPILER_TYPE)
.if ${_v:Mclang} != ""
COMPILER_TYPE = clang
.elif ${_v:M[Gg][Cc][Cc]} != "" || ${_v:MFoundation*} != ""
COMPILER_TYPE = gcc
.endif
.endif
.if empty(COMPILER_VERSION)
COMPILER_VERSION != echo "${_v:M[1-9].[0-9]*}:[1]" | \
awk -F. '{print $$1 * 10000 + $$2 * 100 + $$3;}'
.endif
.undef _v
.endif
# just in case we don't recognize compiler
COMPILER_TYPE ?= unknown
COMPILER_VERSION ?= 0
.endif

View File

@ -0,0 +1,101 @@
# RCSid:
# $Id: cython.mk,v 1.1.1.1 2020/05/24 05:35:53 nia 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
#
# 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,\..*,,}
CFLAGS+= -I${PYTHON_H:H}
# 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
COMPILE.c?= ${CC} -c ${CFLAGS}
PICO?= .pico
.SUFFIXES: ${PICO} .c
.c${PICO}:
${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}
# this is what we build
.if !empty(CYTHON_MODULE_NAME)
CYTHON_MODULE = ${CYTHON_MODULE_NAME}${CYTHON_PYVERSION}.so
CYTHON_SRCS?= ${CYTHON_MODULE_NAME}.pyx
# this is where we save generated src
CYTHON_SAVEGENDIR?= ${.CURDIR}/gen
# set this empty if you don't want to handle multiple versions
.if !defined(CYTHON_PYVERSION)
CYTHON_PYVERSION:= ${PYVERSION}
.endif
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
${CYTHON_MODULE}: ${SRCS:S,.c,${PICO},}
${CC} ${CC_SHARED:U-shared} -o ${.TARGET} ${.ALLSRC:M*${PICO}} ${LDADD}
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+= *${PICO} ${CYTHON_MODULE}
.endif

127
devel/bmake/files/mk/dep.mk Normal file
View File

@ -0,0 +1,127 @@
# $Id: dep.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
# handle Proc*C as well...
.if defined(SRCS)
.if !empty(SRCS:M*.pc)
.include <proc.mk>
.endif
# it would be nice to be able to query .SUFFIXES
OBJ_EXTENSIONS+= .o .po .lo .So
# explicit dependencies help short-circuit .SUFFIX searches
SRCS_DEP_FILTER+= N*.[hly]
.for s in ${SRCS:${SRCS_DEP_FILTER:O:u:ts:}}
.for e in ${OBJ_EXTENSIONS:O:u}
.if !target(${s:T:R}$e)
${s:T:R}$e: $s
.endif
.endfor
.endfor
.endif
.if exists(/usr/bin/mkdep)
MKDEP_CMD?= mkdep
.elif exists(/usr/local/share/bin/mkdeps.sh)
MKDEP_CMD?= /usr/local/share/bin/mkdeps.sh -N
.endif
MKDEP_CMD?= mkdep
MKDEP ?= ${MKDEP_CMD}
.NOPATH: .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
MKDEP_MK ?= autodep.mk
.include <${MKDEP_MK}>
.else
MKDEP_ENV_VARS += CC CXX
.for v in ${MKDEP_ENV_VARS:O:u}
.if !empty($v)
MKDEP_ENV += $v='${$v}'
.endif
.endfor
_MKDEP = ${MKDEP_ENV} ${MKDEP}
# some of the rules involve .h sources, so remove them from mkdep line
.if !target(depend)
depend: beforedepend .depend _SUBDIRUSE afterdepend
.if defined(SRCS)
# libs can have too many SRCS for a single command line
# so do them one at a time.
.depend: ${SRCS} ${.PARSEDIR}/${.PASEFILE}
@rm -f .depend
.ifdef LIB
@files="${.ALLSRC:M*.[sS]}"; \
set -x; for f in $$files; do ${_MKDEP} -a ${MKDEPFLAGS} \
${CFLAGS:M-[ID]*} ${CPPFLAGS} ${AINC} $$f; done
@files="${.ALLSRC:M*.c} ${.ALLSRC:M*.pc:T:.pc=.c}"; \
set -x; for f in $$files; do ${_MKDEP} -a ${MKDEPFLAGS} \
${CFLAGS:M-[ID]*} ${CPPFLAGS} $$f; done
@files="${.ALLSRC:M*.cc} ${.ALLSRC:M*.C} ${.ALLSRC:M*.cxx}"; \
set -x; for f in $$files; do ${_MKDEP} -a ${MKDEPFLAGS} \
${CXXFLAGS:M-[ID]*} ${CPPFLAGS} $$f; done
.else
@files="${.ALLSRC:M*.[Ss]}"; \
case "$$files" in *.[Ss]*) \
echo ${_MKDEP} -a ${MKDEPFLAGS} \
${CFLAGS:M-[ID]*} ${CPPFLAGS} ${AINC} $$files; \
${_MKDEP} -a ${MKDEPFLAGS} \
${CFLAGS:M-[ID]*} ${CPPFLAGS} ${AINC} $$files;; \
esac
@files="${.ALLSRC:M*.c} ${.ALLSRC:M*.pc:T:.pc=.c}"; \
case "$$files" in *.c*) \
echo ${_MKDEP} -a ${MKDEPFLAGS} \
${CFLAGS:M-[ID]*} ${CPPFLAGS} $$files; \
${_MKDEP} -a ${MKDEPFLAGS} \
${CFLAGS:M-[ID]*} ${CPPFLAGS} $$files;; \
esac
@files="${.ALLSRC:M*.cc} ${.ALLSRC:M*.C} ${.ALLSRC:M*.cxx}"; \
case "$$files" in *.[Cc]*) \
echo ${_MKDEP} -a ${MKDEPFLAGS} \
${CXXFLAGS:M-[ID]*} ${CPPFLAGS} $$files; \
${_MKDEP} -a ${MKDEPFLAGS} \
${CXXFLAGS:M-[ID]*} ${CPPFLAGS} $$files;; \
esac
.endif
.else
.depend:
.endif
.if !target(beforedepend)
beforedepend:
.endif
.if !target(afterdepend)
afterdepend:
.endif
.endif
.endif
.if !target(tags)
.if defined(SRCS)
tags: ${SRCS} _SUBDIRUSE
-cd ${.CURDIR}; ctags -f /dev/stdout ${.ALLSRC:N*.h} | \
sed "s;\${.CURDIR}/;;" > tags
.else
tags:
.endif
.endif
.if defined(SRCS)
cleandir: cleandepend
.if !target(cleandepend)
cleandepend:
rm -f .depend ${.CURDIR}/tags
.endif
.endif
.endif

View File

@ -0,0 +1,73 @@
# $Id: dirdeps-options.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2018, 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 makefile is used to deal with optional DIRDEPS.
#
# It is to be included by Makefile.depend.options in a
# directory which has DIRDEPS affected by optional features.
# Makefile.depend.options should set DIRDEPS_OPTIONS and
# may also set specific DIRDEPS.* for those options.
#
# If a Makefile.depend.options file exists, it will be included by
# dirdeps.mk and meta.autodep.mk
#
# We include local.dirdeps-options.mk which may also define DIRDEPS.*
# for options.
#
# Thus a directory, that is affected by an option FOO would have
# a Makefile.depend.options that sets
# DIRDEPS_OPTIONS= FOO
# It can also set either/both of
# DIRDEPS.FOO.yes
# DIRDEPS.FOO.no
# to whatever applies for that dir, or it can rely on globals
# set in local.dirdeps-options.mk
# Either way, we will .undef DIRDEPS.* when done.
# This should have been set by Makefile.depend.options
# before including us
DIRDEPS_OPTIONS ?=
# pickup any DIRDEPS.* we need
.-include <local.dirdeps-options.mk>
.if ${.MAKE.LEVEL} == 0
# :U below avoids potential errors when we :=
.for o in ${DIRDEPS_OPTIONS:tu}
DIRDEPS += ${DIRDEPS.$o.${MK_$o:U}:U}
.endfor
DIRDEPS := ${DIRDEPS:O:u}
# avoid cross contamination
.for o in ${DIRDEPS_OPTIONS:tu}
.undef DIRDEPS.$o.yes
.undef DIRDEPS.$o.no
.endfor
.else
# whether options are enabled or not,
# we want to filter out the relevant DIRDEPS.*
# we should only be included by meta.autodep.mk
# if dependencies are to be updated
.for o in ${DIRDEPS_OPTIONS:tu}
.for d in ${DIRDEPS.$o.yes} ${DIRDEPS.$o.no}
.if exists(${SRCTOP}/$d)
GENDIRDEPS_FILTER += N$d*
.elif exists(${SRCTOP}/${d:R})
GENDIRDEPS_FILTER += N${d:R}*
.endif
.endfor
.endfor
.endif

View File

@ -0,0 +1,133 @@
# RCSid:
# $Id: dirdeps-targets.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2019 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 makefile is used to set initial DIRDEPS for top-level build
# targets.
#
# The basic idea is that we have a list of directories in
# DIRDEPS_TARGETS_DIRS which are relative to SRCTOP.
# When asked to make 'foo' we look for any directory named 'foo'
# under DIRDEPS_TARGETS_DIRS.
# We then search those dirs for any Makefile.depend*
# Finally we select any that match conditions like REQUESTED_MACHINE
# or TARGET_SPEC and initialize DIRDEPS accordingly.
#
.if ${.MAKE.LEVEL} == 0
# pickup customizations
.-include <local.dirdeps-targets.mk>
# for DIRDEPS_BUILD this is how we prime the pump
DIRDEPS_TARGETS_DIRS ?= targets targets/pseudo
# these prefixes can modify how we behave
# they need to be stripped when looking for target dirs
DIRDEPS_TARGETS_PREFIX_LIST ?= pkg- build-
# matching target dirs if any
tdirs := ${.TARGETS:Nall:${DIRDEPS_TARGETS_PREFIX_LIST:@p@S,^$p,,@:ts:}:@t@${DIRDEPS_TARGETS_DIRS:@d@$d/$t@}@:@d@${exists(${SRCTOP}/$d):?$d:}@}
.if !empty(DEBUG_DIRDEPS_TARGETS)
.info tdirs=${tdirs}
.endif
.if !empty(tdirs)
# some things we know we want to ignore
DIRDEPS_TARGETS_SKIP_LIST += \
*~ \
*.bak \
*.inc \
*.old \
*.options \
*.orig \
*.rej \
# the list of MACHINEs we consider
DIRDEPS_TARGETS_MACHINE_LIST += \
${ALL_MACHINE_LIST:U} \
${PSEUDO_MACHINE_LIST:Ucommon host host32} \
${TARGET_MACHINE_LIST}
DIRDEPS_TARGETS_MACHINE_LIST := ${DIRDEPS_TARGETS_MACHINE_LIST:O:u}
# raw Makefile.depend* list
tdeps != 'cd' ${SRCTOP} && 'ls' -1 ${tdirs:O:u:@d@$d/${.MAKE.DEPENDFILE_PREFIX}*@} 2> /dev/null; echo
.if ${DEBUG_DIRDEPS_TARGETS:U:Mdep*} != ""
.info tdeps=${tdeps}
.endif
# remove things we know we don't want
tdeps := ${tdeps:${DIRDEPS_TARGETS_SKIP_LIST:${M_ListToSkip}}}
.if ${DEBUG_DIRDEPS_TARGETS:U:Mdep*} != ""
.info tdeps=${tdeps}
.endif
# plain entries (no qualifiers) these apply to any TARGET_SPEC
ptdeps := ${tdeps:M*${.MAKE.DEPENDFILE_PREFIX}:S,/${.MAKE.DEPENDFILE_PREFIX},,}
# MACHINE qualified entries
mqtdeps := ${DIRDEPS_TARGETS_MACHINE_LIST:@m@${tdeps:M*.$m}@:S,/${.MAKE.DEPENDFILE_PREFIX},,}
tqtdeps =
.if ${TARGET_SPEC_VARS:[#]} > 1
# TARGET_SPEC qualified entries
.if !empty(TARGET_SPEC_LIST)
# we have a list of valid TARGET_SPECS; use it
tqtdeps := ${TARGET_SPEC_LIST:U:O:u:@t@${tdeps:M*.$t}@:S,/${.MAKE.DEPENDFILE_PREFIX},,}
.else
# do we have a list of valid tuple members for at least
# the last tupple element? if so match on that
TARGET_SPEC_LAST_LIST ?= ${${TARGET_SPEC_VARS:[-1]}_LIST}
.if !empty(TARGET_SPEC_LAST_LIST)
tqtdeps := ${TARGET_SPEC_LAST_LIST:U:O:u:@t@${tdeps:M*,$t}@:S,/${.MAKE.DEPENDFILE_PREFIX},,}
.else
# this is sub-optimal match MACHINE,
tqtdeps := ${DIRDEPS_TARGETS_MACHINE_LIST:@m@${tdeps:M*.$m,*}@:S,/${.MAKE.DEPENDFILE_PREFIX},,}
.endif
.endif
.endif
# now work out what we want in DIRDEPS
.if empty(REQUESTED_MACHINE)
# we want them all just as found
DIRDEPS = ${ptdeps} ${mqtdeps} ${tqtdeps}
.else
# we only want those that match REQUESTED_MACHINE/REQUESTED_TARGET_SPEC
# or REQUESTED_TARGET_SPEC (TARGET_SPEC)
DIRDEPS = \
${ptdeps:@d@$d.${REQUESTED_TARGET_SPEC:U${TARGET_SPEC:U${REQUESTED_MACHINE}}}@} \
${mqtdeps:M*.${REQUESTED_MACHINE}} \
${tqtdeps:M*.${REQUESTED_TARGET_SPEC:U${TARGET_SPEC}}}
.endif
# clean up
DIRDEPS := ${DIRDEPS:O:u}
.if !empty(DEBUG_DIRDEPS_TARGETS)
.for x in tdeps ptdeps mqtdeps tqtdeps DIRDEPS
.info $x=${$x}
.endfor
.endif
.endif
# if we got DIRDEPS get to work
.if !empty(DIRDEPS)
.include <dirdeps.mk>
DIRDEPS_TARGETS_SKIP += all clean* destroy*
.for t in ${.TARGETS:${DIRDEPS_TARGETS_SKIP:${M_ListToSkip}}}
$t: dirdeps
.endfor
.endif
.endif

View File

@ -0,0 +1,834 @@
# $Id: dirdeps.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# Copyright (c) 2010-2020, Simon J. Gerraty
# Copyright (c) 2010-2018, Juniper Networks, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Much of the complexity here is for supporting cross-building.
# If a tree does not support that, simply using plain Makefile.depend
# should provide sufficient clue.
# Otherwise the recommendation is to use Makefile.depend.${MACHINE}
# as expected below.
# Note: this file gets multiply included.
# This is what we do with DIRDEPS
# DIRDEPS:
# This is a list of directories - relative to SRCTOP, it is
# normally only of interest to .MAKE.LEVEL 0.
# In some cases the entry may be qualified with a .<machine>
# or .<target_spec> suffix (see TARGET_SPEC_VARS below),
# for example to force building something for the pseudo
# machines "host" or "common" regardless of current ${MACHINE}.
#
# All unqualified entries end up being qualified with .${TARGET_SPEC}
# and partially qualified (if TARGET_SPEC_VARS has multiple
# entries) are also expanded to a full .<target_spec>.
# The _DIRDEP_USE target uses the suffix to set TARGET_SPEC
# correctly when visiting each entry.
#
# The fully qualified directory entries are used to construct a
# dependency graph that will drive the build later.
#
# Also, for each fully qualified directory target, we will search
# using ${.MAKE.DEPENDFILE_PREFERENCE} to find additional
# dependencies. We use Makefile.depend (default value for
# .MAKE.DEPENDFILE_PREFIX) to refer to these makefiles to
# distinguish them from others.
#
# Before each Makefile.depend file is read, we set
# DEP_RELDIR to be the RELDIR (path relative to SRCTOP) for
# its directory, and DEP_MACHINE etc according to the .<target_spec>
# represented by the suffix of the corresponding target.
#
# Since each Makefile.depend file includes dirdeps.mk, this
# processing is recursive and results in .MAKE.LEVEL 0 learning the
# dependencies of the tree wrt the initial directory (_DEP_RELDIR).
#
# BUILD_AT_LEVEL0
# Indicates whether .MAKE.LEVEL 0 builds anything:
# if "no" sub-makes are used to build everything,
# if "yes" sub-makes are only used to build for other machines.
# It is best to use "no", but this can require fixing some
# makefiles to not do anything at .MAKE.LEVEL 0.
#
# TARGET_SPEC_VARS
# The default value is just MACHINE, and for most environments
# this is sufficient. The _DIRDEP_USE target actually sets
# both MACHINE and TARGET_SPEC to the suffix of the current
# target so that in the general case TARGET_SPEC can be ignored.
#
# If more than MACHINE is needed then sys.mk needs to decompose
# TARGET_SPEC and set the relevant variables accordingly.
# It is important that MACHINE be included in and actually be
# the first member of TARGET_SPEC_VARS. This allows other
# variables to be considered optional, and some of the treatment
# below relies on MACHINE being the first entry.
# Note: TARGET_SPEC cannot contain any '.'s so the target
# triple used by compiler folk won't work (directly anyway).
#
# For example:
#
# # Always list MACHINE first,
# # other variables might be optional.
# TARGET_SPEC_VARS = MACHINE TARGET_OS
# .if ${TARGET_SPEC:Uno:M*,*} != ""
# _tspec := ${TARGET_SPEC:S/,/ /g}
# MACHINE := ${_tspec:[1]}
# TARGET_OS := ${_tspec:[2]}
# # etc.
# # We need to stop that TARGET_SPEC affecting any submakes
# # and deal with MACHINE=${TARGET_SPEC} in the environment.
# TARGET_SPEC =
# # export but do not track
# .export-env TARGET_SPEC
# .export ${TARGET_SPEC_VARS}
# .for v in ${TARGET_SPEC_VARS:O:u}
# .if empty($v)
# .undef $v
# .endif
# .endfor
# .endif
# # make sure we know what TARGET_SPEC is
# # as we may need it to find Makefile.depend*
# TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
#
# The following variables can influence the initial DIRDEPS
# computation with regard to the TARGET_SPECs that will be
# built.
# Most should also be considered by init.mk
#
# ONLY_TARGET_SPEC_LIST
# Defines a list of TARGET_SPECs for which the current
# directory can be built.
# If ALL_MACHINES is defined, we build for all the
# TARGET_SPECs listed.
#
# ONLY_MACHINE_LIST
# As for ONLY_TARGET_SPEC_LIST but only specifies
# MACHINEs.
#
# NOT_TARGET_SPEC_LIST
# A list of TARGET_SPECs for which the current
# directory should not be built.
#
# NOT_MACHINE_LIST
# A list of MACHINEs the current directory should not be
# built for.
#
.if !target(bootstrap) && (make(bootstrap) || \
make(bootstrap-this) || \
make(bootstrap-recurse) || \
make(bootstrap-empty))
# disable most of below
.MAKE.LEVEL = 1
.endif
# touch this at your peril
_DIRDEP_USE_LEVEL?= 0
.if ${.MAKE.LEVEL} == ${_DIRDEP_USE_LEVEL}
# only the first instance is interested in all this
.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
.if ${MAKEFILE:T} == ${.PARSEFILE} && empty(DIRDEPS) && ${.TARGETS:Uall:M*/*} != ""
# This little trick let's us do
#
# mk -f dirdeps.mk some/dir.${TARGET_SPEC}
#
all:
${.TARGETS:Nall}: all
DIRDEPS := ${.TARGETS:M*[/.]*}
# so that -DNO_DIRDEPS works
DEP_RELDIR := ${DIRDEPS:[1]:R}
# this will become DEP_MACHINE below
TARGET_MACHINE := ${DIRDEPS:[1]:E:C/,.*//}
.if ${TARGET_MACHINE:N*/*} == ""
TARGET_MACHINE := ${MACHINE}
.endif
# disable DIRDEPS_CACHE as it does not like this trick
MK_DIRDEPS_CACHE = no
.endif
# make sure we get the behavior we expect
.MAKE.SAVE_DOLLARS = no
# make sure these are empty to start with
_DEP_TARGET_SPEC =
# If TARGET_SPEC_VARS is other than just MACHINE
# it should be set by sys.mk or similar by now.
# TARGET_SPEC must not contain any '.'s.
TARGET_SPEC_VARS ?= MACHINE
# this is what we started with
TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
# this is what we mostly use below
DEP_TARGET_SPEC = ${TARGET_SPEC_VARS:S,^,DEP_,:@v@${$v:U}@:ts,}
# make sure we have defaults
.for v in ${TARGET_SPEC_VARS}
DEP_$v ?= ${$v}
.endfor
.if ${TARGET_SPEC_VARS:[#]} > 1
# Ok, this gets more complex (putting it mildly).
# In order to stay sane, we need to ensure that all the build_dirs
# we compute below are fully qualified wrt DEP_TARGET_SPEC.
# The makefiles may only partially specify (eg. MACHINE only),
# so we need to construct a set of modifiers to fill in the gaps.
.if ${MAKE_VERSION} >= 20170130
_tspec_x := ${TARGET_SPEC_VARS:range}
.elif ${TARGET_SPEC_VARS:[#]} > 10
# seriously? better have jot(1) or equivalent to produce suitable sequence
_tspec_x := ${${JOT:Ujot} ${TARGET_SPEC_VARS:[#]}:L:sh}
.else
# we can provide the sequence ourselves
_tspec_x := ${1 2 3 4 5 6 7 8 9 10:L:[1..${TARGET_SPEC_VARS:[#]}]}
.endif
# this handles unqualified entries
M_dep_qual_fixes = C;(/[^/.,]+)$$;\1.$${DEP_TARGET_SPEC};
# there needs to be at least one item missing for these to make sense
.for i in ${_tspec_x:[2..-1]}
_tspec_m$i := ${TARGET_SPEC_VARS:[2..$i]:@w@[^,]+@:ts,}
_tspec_a$i := ,${TARGET_SPEC_VARS:[$i..-1]:@v@$$$${DEP_$v}@:ts,}
M_dep_qual_fixes += C;(\.${_tspec_m$i})$$;\1${_tspec_a$i};
.endfor
.else
# A harmless? default.
M_dep_qual_fixes = U
.endif
.if !defined(.MAKE.DEPENDFILE_PREFERENCE)
# .MAKE.DEPENDFILE_PREFERENCE makes the logic below neater?
# you really want this set by sys.mk or similar
.MAKE.DEPENDFILE_PREFERENCE = ${_CURDIR}/${.MAKE.DEPENDFILE:T}
.if ${.MAKE.DEPENDFILE:E} == "${TARGET_SPEC}"
.if ${TARGET_SPEC} != ${MACHINE}
.MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R}.$${MACHINE}
.endif
.MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R}
.endif
.endif
_default_dependfile := ${.MAKE.DEPENDFILE_PREFERENCE:[1]:T}
_machine_dependfiles := ${.MAKE.DEPENDFILE_PREFERENCE:T:M*${MACHINE}*}
# for machine specific dependfiles we require ${MACHINE} to be at the end
# also for the sake of sanity we require a common prefix
.if !defined(.MAKE.DEPENDFILE_PREFIX)
# knowing .MAKE.DEPENDFILE_PREFIX helps
.if !empty(_machine_dependfiles)
.MAKE.DEPENDFILE_PREFIX := ${_machine_dependfiles:[1]:T:R}
.else
.MAKE.DEPENDFILE_PREFIX := ${_default_dependfile:T}
.endif
.endif
# this is how we identify non-machine specific dependfiles
N_notmachine := ${.MAKE.DEPENDFILE_PREFERENCE:E:N*${MACHINE}*:${M_ListToSkip}}
.endif # !target(_DIRDEP_USE)
# First off, we want to know what ${MACHINE} to build for.
# This can be complicated if we are using a mixture of ${MACHINE} specific
# and non-specific Makefile.depend*
# if we were included recursively _DEP_TARGET_SPEC should be valid.
.if empty(_DEP_TARGET_SPEC)
# we may or may not have included a dependfile yet
.if defined(.INCLUDEDFROMFILE)
_last_dependfile := ${.INCLUDEDFROMFILE:M${.MAKE.DEPENDFILE_PREFIX}*}
.else
_last_dependfile := ${.MAKE.MAKEFILES:M*/${.MAKE.DEPENDFILE_PREFIX}*:[-1]}
.endif
.if ${_debug_reldir:U0}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _last_dependfile='${_last_dependfile}'
.endif
.if empty(_last_dependfile) || ${_last_dependfile:E:${N_notmachine}} == ""
# this is all we have to work with
DEP_MACHINE = ${TARGET_MACHINE:U${MACHINE}}
_DEP_TARGET_SPEC := ${DEP_TARGET_SPEC}
.else
_DEP_TARGET_SPEC = ${_last_dependfile:${M_dep_qual_fixes:ts:}:E}
.endif
.if !empty(_last_dependfile)
# record that we've read dependfile for this
_dirdeps_checked.${_CURDIR}.${TARGET_SPEC}:
.endif
.endif
# by now _DEP_TARGET_SPEC should be set, parse it.
.if ${TARGET_SPEC_VARS:[#]} > 1
# we need to parse DEP_MACHINE may or may not contain more info
_tspec := ${_DEP_TARGET_SPEC:S/,/ /g}
.for i in ${_tspec_x}
DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]}
.endfor
.for v in ${TARGET_SPEC_VARS:O:u}
.if empty(DEP_$v)
.undef DEP_$v
.endif
.endfor
.else
DEP_MACHINE := ${_DEP_TARGET_SPEC}
.endif
# reset each time through
_build_all_dirs =
# the first time we are included the _DIRDEP_USE target will not be defined
# we can use this as a clue to do initialization and other one time things.
.if !target(_DIRDEP_USE)
# make sure this target exists
dirdeps: beforedirdeps .WAIT
beforedirdeps:
# We normally expect to be included by Makefile.depend.*
# which sets the DEP_* macros below.
DEP_RELDIR ?= ${RELDIR}
# this can cause lots of output!
# set to a set of glob expressions that might match RELDIR
DEBUG_DIRDEPS ?= no
# remember the initial value of DEP_RELDIR - we test for it below.
_DEP_RELDIR := ${DEP_RELDIR}
.endif
# DIRDEPS_CACHE can be very handy for debugging.
# Also 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 ${MK_DIRDEPS_CACHE} == "yes"
# this is where we will cache all our work
DIRDEPS_CACHE ?= ${_OBJDIR:tA}/dirdeps.cache${.TARGETS:Nall:O:u:ts-:S,/,_,g:S,^,.,:N.}
.endif
.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
# pickup customizations
# as below you can use !target(_DIRDEP_USE) to protect things
# which should only be done once.
.-include <local.dirdeps.mk>
.if !target(_DIRDEP_USE)
# things we skip for host tools
SKIP_HOSTDIR ?=
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.
SKIP_DIR += .host *.WAIT ${SKIP_DIRDEPS}
SKIP_DIR.host += ${SKIP_HOSTDIR}
DEP_SKIP_DIR = ${SKIP_DIR} \
${SKIP_DIR.${DEP_TARGET_SPEC}:U} \
${TARGET_SPEC_VARS:@v@${SKIP_DIR.${DEP_$v}:U}@} \
${SKIP_DIRDEPS.${DEP_TARGET_SPEC}:U} \
${TARGET_SPEC_VARS:@v@${SKIP_DIRDEPS.${DEP_$v}:U}@}
NSkipDir = ${DEP_SKIP_DIR:${M_ListToSkip}}
.if defined(NODIRDEPS) || defined(WITHOUT_DIRDEPS)
NO_DIRDEPS =
.elif defined(WITHOUT_DIRDEPS_BELOW)
NO_DIRDEPS_BELOW =
.endif
.if defined(NO_DIRDEPS)
# confine ourselves to the original dir and below.
DIRDEPS_FILTER += M${_DEP_RELDIR}*
.elif defined(NO_DIRDEPS_BELOW)
DIRDEPS_FILTER += M${_DEP_RELDIR}
.endif
# this is what we run below
DIRDEP_MAKE ?= ${.MAKE}
DIRDEP_DIR ?= ${.TARGET:R}
# we suppress SUBDIR when visiting the leaves
# we assume sys.mk will set MACHINE_ARCH
# you can add extras to DIRDEP_USE_ENV
# if there is no makefile in the target directory, we skip it.
_DIRDEP_USE: .USE .MAKE
@for m in ${.MAKE.MAKEFILE_PREFERENCE}; do \
test -s ${.TARGET:R}/$$m || continue; \
echo "${TRACER}Checking ${.TARGET:R} for ${.TARGET:E} ..."; \
${DIRDEP_USE_PRELUDE} \
MACHINE_ARCH= NO_SUBDIR=1 ${DIRDEP_USE_ENV} \
TARGET_SPEC=${.TARGET:E} \
MACHINE=${.TARGET:E} \
${DIRDEP_MAKE} -C ${DIRDEP_DIR} || exit 1; \
break; \
done
.ifdef ALL_MACHINES
# this is how you limit it to only the machines we have been built for
# previously.
.if empty(ONLY_TARGET_SPEC_LIST) && empty(ONLY_MACHINE_LIST)
.if !empty(ALL_MACHINE_LIST)
# ALL_MACHINE_LIST is the list of all legal machines - ignore anything else
_machine_list != cd ${_CURDIR} && 'ls' -1 ${ALL_MACHINE_LIST:O:u:@m@${.MAKE.DEPENDFILE:T:R}.$m@} 2> /dev/null; echo
.else
_machine_list != 'ls' -1 ${_CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.* 2> /dev/null; echo
.endif
_only_machines := ${_machine_list:${NIgnoreFiles:UN*.bak}:E:O:u}
.else
_only_machines := ${ONLY_TARGET_SPEC_LIST:U} ${ONLY_MACHINE_LIST:U}
.endif
.if empty(_only_machines)
# we must be boot-strapping
_only_machines := ${TARGET_MACHINE:U${ALL_MACHINE_LIST:U${DEP_MACHINE}}}
.endif
.else # ! ALL_MACHINES
# if ONLY_TARGET_SPEC_LIST or ONLY_MACHINE_LIST is set, we are limited to that.
# Note that ONLY_TARGET_SPEC_LIST should be fully qualified.
# if TARGET_MACHINE is set - it is really the same as ONLY_MACHINE_LIST
# otherwise DEP_MACHINE is it - so DEP_MACHINE will match.
_only_machines := ${ONLY_TARGET_SPEC_LIST:U:M${DEP_MACHINE},*}
.if empty(_only_machines)
_only_machines := ${ONLY_MACHINE_LIST:U${TARGET_MACHINE:U${DEP_MACHINE}}:M${DEP_MACHINE}}
.endif
.endif
.if !empty(NOT_MACHINE_LIST)
_only_machines := ${_only_machines:${NOT_MACHINE_LIST:${M_ListToSkip}}}
.endif
.if !empty(NOT_TARGET_SPEC_LIST)
# we must first qualify
_dm := ${DEP_MACHINE}
_only_machines := ${_only_machines:M*,*} ${_only_machines:N*,*:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:${M_dep_qual_fixes:ts:}:O:u:S,^.,,}
DEP_MACHINE := ${_dm}
_only_machines := ${_only_machines:${NOT_TARGET_SPEC_LIST:${M_ListToSkip}}}
.endif
# clean up
_only_machines := ${_only_machines:O:u}
# make sure we have a starting place?
DIRDEPS ?= ${RELDIR}
.endif # target
.if !defined(NO_DIRDEPS) && !defined(NO_DIRDEPS_BELOW)
.if ${MK_DIRDEPS_CACHE} == "yes"
# 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
# ignore anything but these
.MAKE.META.IGNORE_FILTER = M*/${.MAKE.DEPENDFILE_PREFIX}*
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 <dirdeps.mk>'; echo; \
} > ${.TARGET}.new
+@MAKELEVEL=${.MAKE.LEVEL} DIRDEPS_CACHE=${DIRDEPS_CACHE} \
DIRDEPS="${DIRDEPS}" \
TARGET_SPEC=${TARGET_SPEC} \
MAKEFLAGS= ${.MAKE} -C ${_CURDIR} -f ${BUILD_DIRDEPS_MAKEFILE} \
${BUILD_DIRDEPS_TARGETS} BUILD_DIRDEPS_CACHE=yes \
.MAKE.DEPENDFILE=.none \
${.MAKEFLAGS:tW:S,-D ,-D,g:tw:M*WITH*} \
${.MAKEFLAGS:tW:S,-d ,-d,g:tw:M-d*} \
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
.elif !make(dirdeps) && !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
.endif
.if ${BUILD_DIRDEPS} == "yes"
# the rest is done repeatedly for every Makefile.depend we read.
# if we are anything but the original dir we care only about the
# machine type we were included for..
.if ${DEP_RELDIR} == "."
_this_dir := ${SRCTOP}
.else
_this_dir := ${SRCTOP}/${DEP_RELDIR}
.endif
# on rare occasions, there can be a need for extra help
_dep_hack := ${_this_dir}/${.MAKE.DEPENDFILE_PREFIX}.inc
.-include <${_dep_hack}>
.-include <${_dep_hack:R}.options>
.if ${DEP_RELDIR} != ${_DEP_RELDIR} || ${DEP_TARGET_SPEC} != ${TARGET_SPEC}
# this should be all
_machines := ${DEP_MACHINE}
.else
# this is the machine list we actually use below
_machines := ${_only_machines}
.if defined(HOSTPROG) || ${DEP_MACHINE:Nhost*} == ""
# we need to build this guy's dependencies for host as well.
.if ${DEP_MACHINE:Nhost*} == ""
_machines += ${DEP_MACHINE}
.else
_machines += host
.endif
.endif
_machines := ${_machines:O:u}
.endif
.if ${TARGET_SPEC_VARS:[#]} > 1
# we need to tweak _machines
_dm := ${DEP_MACHINE}
# apply the same filtering that we do when qualifying DIRDEPS.
# M_dep_qual_fixes expects .${MACHINE}* so add (and remove) '.'
# Again we expect that any already qualified machines are fully qualified.
_machines := ${_machines:M*,*} ${_machines:N*,*:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:${M_dep_qual_fixes:ts:}:O:u:S,^.,,}
DEP_MACHINE := ${_dm}
_machines := ${_machines:O:u}
.endif
# reset each time through
_build_dirs =
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# pickup other machines for this dir if necessary
.if ${BUILD_AT_LEVEL0:Uyes} == "no"
_build_dirs += ${_machines:@m@${_CURDIR}.$m@}
.else
_build_dirs += ${_machines:N${DEP_TARGET_SPEC}:@m@${_CURDIR}.$m@}
.if ${DEP_TARGET_SPEC} == ${TARGET_SPEC}
# pickup local dependencies now
.if ${MAKE_VERSION} < 20160220
.-include <.depend>
.else
.dinclude <.depend>
.endif
.endif
.endif
.endif
.if ${_debug_reldir}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: DIRDEPS='${DIRDEPS}'
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _machines='${_machines}'
.endif
.if !empty(DIRDEPS)
# these we reset each time through as they can depend on DEP_MACHINE
DEP_DIRDEPS_FILTER = \
${DIRDEPS_FILTER.${DEP_TARGET_SPEC}:U} \
${TARGET_SPEC_VARS:@v@${DIRDEPS_FILTER.${DEP_$v}:U}@} \
${DIRDEPS_FILTER:U}
.if empty(DEP_DIRDEPS_FILTER)
# something harmless
DEP_DIRDEPS_FILTER = U
.endif
# this is what we start with
__depdirs := ${DIRDEPS:${NSkipDir}:${DEP_DIRDEPS_FILTER:ts:}:C,//+,/,g:O:u:@d@${SRCTOP}/$d@}
# some entries may be qualified with .<machine>
# the :M*/*/*.* just tries to limit the dirs we check to likely ones.
# the ${d:E:M*/*} ensures we don't consider junos/usr.sbin/mgd
__qual_depdirs := ${__depdirs:M*/*/*.*:@d@${exists($d):?:${"${d:E:M*/*}":?:${exists(${d:R}):?$d:}}}@}
__unqual_depdirs := ${__depdirs:${__qual_depdirs:Uno:${M_ListToSkip}}}
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# if it was called out - we likely need it.
__hostdpadd := ${DPADD:U.:M${HOST_OBJTOP}/*:S,${HOST_OBJTOP}/,,:H:${NSkipDir}:${DIRDEPS_FILTER:ts:}:S,$,.host,:N.*:@d@${SRCTOP}/$d@} \
${DPADD:U.:M${HOST_OBJTOP32:Uno}/*:S,${HOST_OBJTOP32:Uno}/,,:H:${NSkipDir}:${DIRDEPS_FILTER:ts:}:S,$,.host32,:N.*:@d@${SRCTOP}/$d@}
__qual_depdirs += ${__hostdpadd}
.endif
.if ${_debug_reldir}
.info depdirs=${__depdirs}
.info qualified=${__qual_depdirs}
.info unqualified=${__unqual_depdirs}
.endif
# _build_dirs is what we will feed to _DIRDEP_USE
_build_dirs += \
${__qual_depdirs:M*.host:${NSkipHostDir}:N.host} \
${__qual_depdirs:N*.host} \
${_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}
.endif # empty DIRDEPS
_build_all_dirs += ${_build_dirs}
_build_all_dirs := ${_build_all_dirs:O:u}
# Normally if doing make -V something,
# we do not want to waste time chasing DIRDEPS
# but if we want to count the number of Makefile.depend* read, we do.
.if ${.MAKEFLAGS:M-V${_V_READ_DIRDEPS}} == ""
.if !empty(_build_all_dirs)
.if ${BUILD_DIRDEPS_CACHE} == "yes"
# guard against _build_all_dirs being too big for a single command line
# first get list of dirs that need _DIRDEP_USE
# then export that and _build_all_dirs
_new_dirdeps := ${_build_all_dirs:@x@${target($x):?:$x}@}
.export _new_dirdeps _build_all_dirs
x!= echo; { echo '\# ${DEP_RELDIR}.${DEP_TARGET_SPEC}'; \
echo "dirdeps: \\"; \
for x in $$_build_all_dirs; do echo " $$x \\"; done; echo; \
for x in $$_new_dirdeps; do echo "$$x: _DIRDEP_USE"; done; echo; } >&3
.if !empty(DEP_EXPORT_VARS)
# Discouraged, but there are always exceptions.
# Handle it here rather than explain how.
x!= { echo; ${DEP_EXPORT_VARS:@v@echo '$v=${$v}';@} echo '.export ${DEP_EXPORT_VARS}'; echo; } >&3; echo
.endif
.else
# this makes it all happen
dirdeps: ${_build_all_dirs}
.endif
${_build_all_dirs}: _DIRDEP_USE
.if ${_debug_reldir}
.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs}
.endif
.if !empty(DEP_EXPORT_VARS)
.export ${DEP_EXPORT_VARS}
DEP_EXPORT_VARS=
.endif
# this builds the dependency graph
.for m in ${_machines}
# 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 ${_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"
_cache_deps := ${_build_dirs:M*.$q}
.export _cache_deps
x!= echo; { echo "${_this_dir}.$m: \\"; \
for x in $$_cache_deps; do echo " $$x \\"; done; echo; } >&3
.else
${_this_dir}.$m: ${_build_dirs:M*.$q}
.endif
.endfor
.endif
.if ${_debug_reldir}
.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m}
.endif
.if ${BUILD_DIRDEPS_CACHE} == "yes"
_cache_deps := ${_build_dirs:M*.$m:N${_this_dir}.$m}
.export _cache_deps
x!= echo; { echo "${_this_dir}.$m: \\"; \
for x in $$_cache_deps; do echo " $$x \\"; done; echo; } >&3
.else
${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
.endif
.endfor
.endif
# Now find more dependencies - and recurse.
.for d in ${_build_all_dirs}
.if !target(_dirdeps_checked.$d)
# once only
_dirdeps_checked.$d:
.if ${_debug_search}
.info checking $d
.endif
# Note: _build_all_dirs is fully qualifed so d:R is always the directory
.if exists(${d:R})
# 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/,.*//}
# set these too in case Makefile.depend* uses them
.if ${TARGET_SPEC_VARS:[#]} > 1
_dtspec := ${_DEP_TARGET_SPEC:S/,/ /g}
.for i in ${_tspec_x}
DEP_${TARGET_SPEC_VARS:[$i]} := ${_dtspec:[$i]}
.endfor
.else
DEP_MACHINE := ${_DEP_MACHINE}
.endif
# Warning: there is an assumption here that MACHINE is always
# the first entry in TARGET_SPEC_VARS.
# If TARGET_SPEC and MACHINE are insufficient, you have a problem.
_m := ${.MAKE.DEPENDFILE_PREFERENCE:T:S;${TARGET_SPEC}$;${d:E};:S;${MACHINE};${d:E:C/,.*//};:@m@${exists(${d:R}/$m):?${d:R}/$m:}@:[1]}
.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 ${_debug_search}
.info Looking for ${_qm}
.endif
# set this "just in case"
# we can skip :tA since we computed the path above
DEP_RELDIR := ${_m:H:S,${SRCTOP}/,,}
# and reset this
DIRDEPS =
.if ${_debug_reldir} && ${_qm} != ${_m}
.info loading ${_m} for ${d:E}
.endif
.include <${_m}>
.else
.-include <local.dirdeps-missing.mk>
.endif
.endif
.endif
.endfor
.endif # -V
.endif # BUILD_DIRDEPS
.elif ${.MAKE.LEVEL} > 42
.error You should have stopped recursing by now.
.else
# we are building something
DEP_RELDIR := ${RELDIR}
_DEP_RELDIR := ${RELDIR}
# Since we are/should be included by .MAKE.DEPENDFILE
# This is a final opportunity to add/hook global rules.
.-include <local.dirdeps-build.mk>
# pickup local dependencies
.if ${MAKE_VERSION} < 20160220
.-include <.depend>
.else
.dinclude <.depend>
.endif
.endif
# bootstrapping new dependencies made easy?
.if !target(bootstrap) && (make(bootstrap) || \
make(bootstrap-this) || \
make(bootstrap-recurse) || \
make(bootstrap-empty))
# if we are bootstrapping create the default
_want = ${.CURDIR}/${.MAKE.DEPENDFILE_DEFAULT:T}
.if exists(${_want})
# stop here
${.TARGETS:Mboot*}:
.elif !make(bootstrap-empty)
# 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}${.newline}Use: bootstrap-empty
.endif
_src?= ${.MAKE.DEPENDFILE}
.MAKE.DEPENDFILE_BOOTSTRAP_SED+= -e 's/${_src:E:C/,.*//}/${MACHINE}/g'
# just create Makefile.depend* for this dir
bootstrap-this: .NOTMAIN
@echo Bootstrapping ${RELDIR}/${_want:T} from ${_src:T}; \
echo You need to build ${RELDIR} to correctly populate it.
.if ${_src:T} != ${.MAKE.DEPENDFILE_PREFIX:T}
(cd ${.CURDIR} && sed ${.MAKE.DEPENDFILE_BOOTSTRAP_SED} ${_src} > ${_want:T})
.else
cp ${.CURDIR}/${_src:T} ${_want}
.endif
# create Makefile.depend* for this dir and its dependencies
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
# create an empty Makefile.depend* to get the ball rolling.
bootstrap-empty: .NOTMAIN .NOMETA
@echo Creating empty ${RELDIR}/${_want:T}; \
echo You need to build ${RELDIR} to correctly populate it.
@{ echo DIRDEPS=; echo ".include <dirdeps.mk>"; } > ${_want}
.endif

View File

@ -0,0 +1,64 @@
# $Id: doc.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
.include <init.mk>
BIB?= bib
EQN?= eqn
GREMLIN?= grn
GRIND?= vgrind -f
INDXBIB?= indxbib
PIC?= pic
REFER?= refer
ROFF?= groff -M/usr/share/tmac ${MACROS} ${PAGES}
SOELIM?= soelim
TBL?= tbl
.PATH: ${.CURDIR}
.if !defined(_SKIP_BUILD)
realbuild: paper.ps
.endif
.if !target(paper.ps)
paper.ps: ${SRCS}
${ROFF} ${SRCS} > ${.TARGET}
.endif
.if !target(print)
print: paper.ps
lpr -P${PRINTER} paper.ps
.endif
.if !target(manpages)
manpages:
.endif
.if !target(obj)
obj:
.endif
clean cleandir:
rm -f paper.* [eE]rrs mklog ${CLEANFILES}
.if ${MK_DOC} == "no"
install:
.else
FILES?= ${SRCS}
install:
test -d ${DESTDIR}${DOCDIR}/${DIR} || \
${INSTALL} -d ${DOC_INSTALL_OWN} -m ${DIRMODE} ${DESTDIR}${DOCDIR}/${DIR}
${INSTALL} ${COPY} ${DOC_INSTALL_OWN} -m ${DOCMODE} \
Makefile ${FILES} ${EXTRA} ${DESTDIR}${DOCDIR}/${DIR}
.endif
spell: ${SRCS}
spell ${SRCS} | sort | comm -23 - spell.ok > paper.spell
.if !empty(DOCOWN)
DOC_INSTALL_OWN?= -o ${DOCOWN} -g ${DOCGRP}
.endif
.endif

View File

@ -0,0 +1,339 @@
# $Id: dpadd.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2004, 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
#
##
# DESCRIPTION:
# This makefile manages a number of variables that simplify
# dealing with libs in a build.
#
# Primary inputs are DPLIBS, DPADD and SRC_LIBS:
#
# DPLIBS
# List of LIB* that we will actually link with
# should be in correct link order.
# DPLIBS is a short-cut to ensure that DPADD and LDADD are
# kept in sync.
#
# DPADD List of LIB* that should already be built.
#
# SRC_LIBS
# List of LIB* that we want headers from, we do *not*
# require that such libs have been built.
#
# The above all get added to DPMAGIC_LIBS which is what we
# process.
#
# We expect LIB* to be set to absolute path of a library -
# suitable for putting in DPADD.
# eg.
#
# LIBC ?= ${OBJTOP}/lib/libc/libc.a
#
# From such a path we can derrive a number of other variables
# for which we can supply sensible default values.
# We name all these variables for the basename of the library
# (libc in our example above -- ${__lib:T:R} in below):
#
# LDADD_${__lib:T:R}:
# What should be added to LDADD (eg -lc)
#
# OBJ_${__lib:T:R}:
# This is trivial - just the dirname of the built library.
#
# SRC_${__lib:T:R}:
# Where the src for ${__lib} is, if LIB* is set as above
# we can simply substitute ${SRCTOP} for ${OBJTOP} in
# the dirname.
#
# INCLUDES_${__lib:T:R}:
# What should be added to CFLAGS
#
# If the directory ${SRC_${__lib:T:R}}/h exists we will
# only add -I${SRC_${__lib:T:R}}/h on the basis that
# this is where the public api is kept.
#
# Otherwise default will be -I${OBJ_${__lib:T:R}}
# -I${SRC_${__lib:T:R}}
#
# Note much of the above is skipped for staged libs
# eg.
# LIBC ?= ${STAGE_OBJTOP}/usr/lib/libc.a
#
# Since we can safely assume that -I${STAGE_OBJTOP}/usr/include
# and -L${STAGE_OBJTOP}/usr/lib are sufficient, and we should
# have no need of anything else.
#
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
# sometimes we play games with .CURDIR etc
# _* hold the original values of .*
_OBJDIR?= ${.OBJDIR}
_CURDIR?= ${.CURDIR}
.if ${_CURDIR} == ${SRCTOP}
RELDIR=.
RELTOP=.
.else
RELDIR?= ${_CURDIR:S,${SRCTOP}/,,}
.if ${RELDIR} == ${_CURDIR}
RELDIR?= ${_OBJDIR:S,${OBJTOP}/,,}
.endif
RELTOP?= ${RELDIR:C,[^/]+,..,g}
.endif
RELOBJTOP?= ${OBJTOP}
RELSRCTOP?= ${SRCTOP}
# we get included just about everywhere so this is handy...
# C*DEBUG_XTRA are for defining on cmd line etc
# so do not use in makefiles.
.ifdef CFLAGS_DEBUG_XTRA
CFLAGS_LAST += ${CFLAGS_DEBUG_XTRA}
.endif
.ifdef CXXFLAGS_DEBUG_XTRA
CXXFLAGS_LAST += ${CXXFLAGS_DEBUG_XTRA}
.endif
.-include <local.dpadd.mk>
# DPLIBS helps us ensure we keep DPADD and LDADD in sync
DPLIBS+= ${DPLIBS_LAST}
DPADD+= ${DPLIBS:N-*}
.for __lib in ${DPLIBS}
.if "${__lib:M-*}" != ""
LDADD += ${__lib}
.else
LDADD += ${LDADD_${__lib:T:R}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}}
.endif
.endfor
# DPADD can contain things other than libs
__dpadd_libs := ${DPADD:M*/lib*}
.if defined(PROG) && ${MK_PROG_LDORDER_MK:Uno} != "no"
# some libs have dependencies...
# DPLIBS_* allows bsd.libnames.mk to flag libs which must be included
# in DPADD for a given library.
# Gather all such dependencies into __ldadd_all_xtras
# dups will be dealt with later.
# Note: libfoo_pic uses DPLIBS_libfoo
__ldadd_all_xtras=
.for __lib in ${__dpadd_libs:@d@${DPLIBS_${d:T:R:S,_pic,,}}@}
__ldadd_all_xtras+= ${LDADD_${__lib}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}}
.if "${DPADD:M${__lib}}" == ""
DPADD+= ${__lib}
.endif
.endfor
.endif
# Last of all... for libc and libgcc
DPADD+= ${DPADD_LAST}
# de-dupuplicate __ldadd_all_xtras into __ldadd_xtras
# in reverse order so that libs end up listed after all that needed them.
__ldadd_xtras=
.for __lib in ${__ldadd_all_xtras:[-1..1]}
.if "${__ldadd_xtras:M${__lib}}" == "" || ${NEED_IMPLICIT_LDADD:tl:Uno} != "no"
__ldadd_xtras+= ${__lib}
.endif
.endfor
.if !empty(__ldadd_xtras)
# now back to the original order
__ldadd_xtras:= ${__ldadd_xtras:[-1..1]}
LDADD+= ${__ldadd_xtras}
.endif
# Convert DPADD into -I and -L options and add them to CPPFLAGS and LDADD
# For the -I's convert the path to a relative one. For separate objdirs
# the DPADD paths will be to the obj tree so we need to subst anyway.
# update this
__dpadd_libs := ${DPADD:M*/lib*}
# Order -L's to search ours first.
# Avoids picking up old versions already installed.
__dpadd_libdirs := ${__dpadd_libs:R:H:S/^/-L/g:O:u:N-L}
LDADD += ${__dpadd_libdirs:M-L${OBJTOP}/*}
LDADD += ${__dpadd_libdirs:N-L${OBJTOP}/*:N-L${HOST_LIBDIR:U/usr/lib}}
.if defined(HOST_LIBDIR) && ${HOST_LIBDIR} != "/usr/lib"
LDADD+= -L${HOST_LIBDIR}
.endif
.if !make(dpadd)
.ifdef LIB
# Each lib is its own src_lib, we want to include it in SRC_LIBS
# so that the correct INCLUDES_* will be picked up automatically.
SRC_LIBS+= ${_OBJDIR}/lib${LIB}.a
.endif
.endif
#
# This little bit of magic, assumes that SRC_libfoo will be
# set if it cannot be correctly derrived from ${LIBFOO}
# Note that SRC_libfoo and INCLUDES_libfoo should be named for the
# actual library name not the variable name that might refer to it.
# 99% of the time the two are the same, but the DPADD logic
# only has the library name available, so stick to that.
#
SRC_LIBS?=
# magic_libs includes those we want to link with
# as well as those we might look at
__dpadd_magic_libs += ${__dpadd_libs} ${SRC_LIBS}
DPMAGIC_LIBS += ${__dpadd_magic_libs} \
${__dpadd_magic_libs:@d@${DPMAGIC_LIBS_${d:T:R}}@}
# we skip this for staged libs
.for __lib in ${DPMAGIC_LIBS:O:u:N${STAGE_OBJTOP:Unot}*/lib/*}
#
# if SRC_libfoo is not set, then we assume that the srcdir corresponding
# to where we found the library is correct.
#
SRC_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELSRCTOP},}
#
# This is a no-brainer but just to be complete...
#
OBJ_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELOBJTOP},}
#
# If INCLUDES_libfoo is not set, then we'll use ${SRC_libfoo}/h if it exists,
# else just ${SRC_libfoo}.
#
INCLUDES_${__lib:T:R}?= -I${exists(${SRC_${__lib:T:R}}/h):?${SRC_${__lib:T:R}}/h:${SRC_${__lib:T:R}}}
.endfor
# even for staged libs we sometimes
# need to allow direct -I to avoid cicular dependencies
.for __lib in ${DPMAGIC_LIBS:O:u:T:R}
.if !empty(SRC_${__lib}) && empty(INCLUDES_${__lib})
# must be a staged lib
.if exists(${SRC_${__lib}}/h)
INCLUDES_${__lib} = -I${SRC_${__lib}}/h
.else
INCLUDES_${__lib} = -I${SRC_${__lib}}
.endif
.endif
.endfor
# when linking a shared lib, avoid non pic libs
SHLDADD+= ${LDADD:N-[lL]*}
.for __lib in ${__dpadd_libs:u}
.if defined(SHLIB_NAME) && ${LDADD:M-l${__lib:T:R:S,lib,,}} != ""
.if ${__lib:T:N*_pic.a:N*.so} == "" || exists(${__lib:R}.so)
SHLDADD+= -l${__lib:T:R:S,lib,,}
.elif exists(${__lib:R}_pic.a)
SHLDADD+= -l${__lib:T:R:S,lib,,}_pic
.else
.warning ${RELDIR}.${TARGET_SPEC} needs ${__lib:T:R}_pic.a
SHLDADD+= -l${__lib:T:R:S,lib,,}
.endif
SHLDADD+= -L${__lib:H}
.endif
.endfor
# Now for the bits we actually need
__dpadd_incs=
.for __lib in ${__dpadd_libs:u}
.if (make(${PROG}_p) || defined(NEED_GPROF)) && exists(${__lib:R}_p.a)
__ldadd=-l${__lib:T:R:S,lib,,}
LDADD := ${LDADD:S,^${__ldadd}$,${__ldadd}_p,g}
.endif
.endfor
#
# We take care of duplicate suppression later.
# don't apply :T:R too early
__dpadd_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_${x:T:R}}@}
__dpadd_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_${x:T:R}}@}
__dpadd_last_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_LAST_${x:T:R}}@}
__dpadd_last_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_LAST_${x:T:R}}@}
.if defined(HOSTPROG) || ${MACHINE:Nhost*} == ""
# we want any -I/usr/* last
__dpadd_last_incs := \
${__dpadd_last_incs:N-I/usr/*} \
${__dpadd_incs:M-I/usr/*} \
${__dpadd_last_incs:M-I/usr/*}
__dpadd_incs := ${__dpadd_incs:N-I/usr/*}
.endif
#
# eliminate any duplicates - but don't mess with the order
# force evaluation now - to avoid giving make a headache
#
.for t in CFLAGS CXXFLAGS
# avoid duplicates
__$t_incs:=${$t:M-I*:O:u}
.for i in ${__dpadd_incs}
.if "${__$t_incs:M$i}" == ""
$t+= $i
__$t_incs+= $i
.endif
.endfor
.endfor
.for t in CFLAGS_LAST CXXFLAGS_LAST
# avoid duplicates
__$t_incs:=${$t:M-I*:u}
.for i in ${__dpadd_last_incs}
.if "${__$t_incs:M$i}" == ""
$t+= $i
__$t_incs+= $i
.endif
.endfor
.endfor
# This target is used to gather a list of
# dir: ${DPADD}
# entries
.if make(*dpadd*)
.if !target(dpadd)
dpadd: .NOTMAIN
.if defined(DPADD) && ${DPADD} != ""
@echo "${RELDIR}: ${DPADD:S,${OBJTOP}/,,}"
.endif
.endif
.endif
.ifdef SRC_PATHADD
# We don't want to assume that we need to .PATH every element of
# SRC_LIBS, but the Makefile cannot do
# .PATH: ${SRC_libfoo}
# since the value of SRC_libfoo must be available at the time .PATH:
# is read - and we only just worked it out.
# Further, they can't wait until after include of {lib,prog}.mk as
# the .PATH is needed before then.
# So we let the Makefile do
# SRC_PATHADD+= ${SRC_libfoo}
# and we defer the .PATH: until now so that SRC_libfoo will be available.
.PATH: ${SRC_PATHADD}
.endif
# after all that, if doing -n we don't care
.if ${.MAKEFLAGS:Ux:M-n} != ""
DPADD =
.elif ${.MAKE.MODE:Mmeta*} != "" && exists(${.MAKE.DEPENDFILE})
DPADD_CLEAR_DPADD ?= yes
.if ${DPADD_CLEAR_DPADD} == "yes"
# save this
__dpadd_libs := ${__dpadd_libs}
# we have made what use of it we can of DPADD
DPADD =
.endif
.endif
.endif

View File

@ -0,0 +1,83 @@
# $Id: files.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2017, 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
#
.include <init.mk>
FILES_INSTALL_OWN ?= -o ${SHAREOWN} -g ${SHAREGRP}
FILESMODE ?= ${SHAREMODE}
FILES_COPY ?= -C
FILESGROUPS ?= FILES
FILESGROUPS := ${FILESGROUPS:O:u}
.if !target(buildfiles)
.for group in ${FILESGROUPS}
buildfiles: ${${group}}
.endfor
.endif
buildfiles:
realbuild: buildfiles
# there is no default FILESDIR so
# ignore group if ${group}DIR is not defined
.for group in ${FILESGROUPS}
.if !empty(${group}) && defined(${group}DIR)
.if ${group} != "FILES"
${group}_INSTALL_OWN ?= ${FILES_INSTALL_OWN}
.endif
# incase we are staging
STAGE_DIR.${group} ?= ${STAGE_OBJTOP}${${group}DIR}
.for file in ${${group}:O:u}
${group}_INSTALL_OWN.${file:T} ?= ${${group}_INSTALL_OWN}
${group}DIR.${file:T} ?= ${${group}DIR}
file_mkdir_list += ${${group}DIR.${file:T}}
.if defined(${group}NAME.${file:T})
STAGE_AS_SETS += ${group}
STAGE_AS_${file} = ${${group}NAME.${file:T}}
stage_as.${group}: ${file}
installfiles: installfiles.${group}.${file:T}
installfiles.${group}.${file:T}: ${file} file_mkdirs
${INSTALL} ${FILES_COPY} ${${group}_INSTALL_OWN.${file:T}} \
-m ${FILESMODE} ${.ALLSRC:Nfile_mkdirs} ${DESTDIR}${${group}DIR}/${${group}NAME.${file:T}}
.else
STAGE_SETS += ${group}
stage_files.${group}: ${file}
installfiles.${group}: ${file}
installfiles: installfiles.${group}
.endif
.endfor # file
installfiles.${group}: file_mkdirs
${INSTALL} ${FILES_COPY} ${${group}_INSTALL_OWN} -m ${FILESMODE} \
${.ALLSRC:Nfile_mkdirs:O:u} ${DESTDIR}${${group}DIR}
.endif # !empty
.endfor # group
file_mkdirs:
@for d in ${file_mkdir_list:O:u}; do \
test -d ${DESTDIR}$$d || \
${INSTALL} -d ${FILES_INSTALL_OWN} -m 775 ${DESTDIR}$$d; \
done
beforeinstall:
installfiles:
realinstall: installfiles
.ORDER: beforeinstall installfiles

View File

@ -0,0 +1,22 @@
# $Id: final.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
# provide a hook for folk who want to do scary stuff
.-include <${.CURDIR:H}/Makefile-final.inc>
.-include <local.final.mk>
.if ${MK_STAGING} == "yes"
.include <meta.stage.mk>
.elif !empty(STAGE)
.-include <stage.mk>
.endif
.if empty(_SKIP_BUILD)
install: realinstall
.endif
realinstall:
.endif

View File

@ -0,0 +1,383 @@
# $Id: gendirdeps.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# Copyright (c) 2011-2020, Simon J. Gerraty
# Copyright (c) 2010-2018, Juniper Networks, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This makefile [re]generates ${.MAKE.DEPENDFILE}
#
.include <install-new.mk>
# Assumptions:
# RELDIR is the relative path from ${SRCTOP} to ${_CURDIR}
# (SRCTOP is ${SB}/src)
# _CURDIR is the absolute version of ${.CURDIR}
# _OBJDIR is the absolute version of ${.OBJDIR}
# _objroot is realpath of ${_OBJTOP} without ${MACHINE}
# this may be different from _OBJROOT if $SB/obj is a
# symlink to another filesystem.
# _objroot must be a prefix match for _objtop
.MAIN: all
# keep this simple
.MAKE.MODE = compat
all:
_CURDIR ?= ${.CURDIR}
_OBJDIR ?= ${.OBJDIR}
_OBJTOP ?= ${OBJTOP}
_OBJROOT ?= ${OBJROOT:U${_OBJTOP}}
.if ${_OBJROOT:M*/}
_slash=/
.else
_slash=
.endif
_objroot ?= ${_OBJROOT:tA}${_slash}
_this = ${.PARSEDIR}/${.PARSEFILE}
# remember what to make
_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T}
# We do _not_ want to read our own output!
.MAKE.DEPENDFILE = /dev/null
# caller should have set this
META_FILES ?= ${.MAKE.META.FILES}
.if !empty(META_FILES)
.if ${.MAKE.LEVEL} > 0 && !empty(GENDIRDEPS_FILTER)
# so we can compare below
.-include <${_DEPENDFILE}>
# yes, I mean :U with no value
_DIRDEPS := ${DIRDEPS:U:O:u}
.endif
META_FILES := ${META_FILES:T:O:u}
# pickup customizations
.-include <local.gendirdeps.mk>
# these are actually prefixes that we'll skip
# they should all be absolute paths
SKIP_GENDIRDEPS ?=
.if !empty(SKIP_GENDIRDEPS)
_skip_gendirdeps = egrep -v '^(${SKIP_GENDIRDEPS:O:u:ts|})' |
.else
_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
META2DEPS := ${META2DEPS}
.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != "" && ${DEBUG_GENDIRDEPS:Uno:Mmeta2d*} != ""
_time = time
_sh_x = sh -x
_py_d = -ddd
.else
_time =
_sh_x =
_py_d =
.endif
.if ${META2DEPS:E} == "py"
# we can afford to do this all the time.
DPDEPS ?= no
META2DEPS_CMD = ${_time} ${PYTHON} ${META2DEPS} ${_py_d}
.if ${DPDEPS:tl} != "no"
META2DEPS_CMD += -D ${DPDEPS}
.endif
META2DEPS_FILTER = sed 's,^src:,${SRCTOP}/,;s,^\([^/]\),${OBJTOP}/\1,' |
.elif ${META2DEPS:E} == "sh"
META2DEPS_CMD = ${_time} ${_sh_x} ${META2DEPS} OBJTOP=${_OBJTOP}
.else
META2DEPS_CMD ?= ${META2DEPS}
.endif
.if ${TARGET_OBJ_SPEC:U${MACHINE}} != ${MACHINE}
META2DEPS_CMD += -T ${TARGET_OBJ_SPEC}
.endif
META2DEPS_CMD += \
-R ${RELDIR} -H ${HOST_TARGET} \
${M2D_OBJROOTS:O:u:@o@-O $o@} \
${M2D_EXCLUDES:O:u:@o@-X $o@} \
M2D_OBJROOTS += ${OBJTOP} ${_OBJROOT} ${_objroot}
.if defined(SB_OBJROOT)
M2D_OBJROOTS += ${SB_OBJROOT}
.endif
.if defined(STAGE_ROOT)
M2D_OBJROOTS += ${STAGE_ROOT}
.endif
.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} == ""
# meta2deps.py only groks objroot
# so we need to give it what it expects
# and tell it not to add machine qualifiers
META2DEPS_ARGS += MACHINE=none
.endif
.if defined(SB_BACKING_SB)
META2DEPS_CMD += -S ${SB_BACKING_SB}/src
M2D_OBJROOTS += ${SB_BACKING_SB}/${SB_OBJPREFIX}
.endif
GENDIRDEPS_SEDCMDS += \
-e 's,//*$$,,;s,\.${HOST_TARGET:Uhost}$$,.host,' \
-e 's,\.${HOST_TARGET32:Uhost32}$$,.host32,' \
-e 's,\.${MACHINE}$$,,' \
-e 's:\.${TARGET_SPEC:U${MACHINE}}$$::'
# we are only interested in the dirs
# specifically those we read something from.
# we canonicalize them to keep things simple
# if we are using a split-fs sandbox, it gets a little messier.
_objtop := ${_OBJTOP:tA}
# some people put *.meta in META_XTRAS to make sure we get here
_meta_files := ${META_FILES:N\*.meta:O:u}
# assume a big list
_meta_files_arg= @meta.list
.if empty(_meta_files) && ${META_FILES:M\*.meta} != ""
# XXX this should be considered a bad idea,
# since we cannot ignore stale .meta
x != cd ${_OBJDIR} && find . -name '*.meta' -print -o \( -type d ! -name . -prune \) | sed 's,^./,,' > meta.list; echo
.elif ${_meta_files:[#]} > 500
.export _meta_files
x != echo; for m in $$_meta_files; do echo $$m; done > meta.list
# _meta_files is consuming a lot of env space
# that can impact command line length,
# and we do not need it any more
.undef _meta_files
.unexport _meta_files
.else
_meta_files_arg:= ${_meta_files}
.endif
dir_list != cd ${_OBJDIR} && \
${META2DEPS_CMD} MACHINE=${MACHINE} \
SRCTOP=${SRCTOP} RELDIR=${RELDIR} CURDIR=${_CURDIR} \
${META2DEPS_ARGS} \
${_meta_files_arg} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \
sed ${GENDIRDEPS_SEDCMDS}
.if ${dir_list:M*ERROR\:*} != ""
.warning ${dir_list:tW:C,.*(ERROR),\1,}
.warning Skipping ${_DEPENDFILE:S,${SRCTOP}/,,}
# we are not going to update anything
.else
dpadd_dir_list=
.if !empty(DPADD)
_nonlibs := ${DPADD:T:Nlib*:N*include}
.if !empty(_nonlibs)
ddep_list =
.for f in ${_nonlibs:@x@${DPADD:M*/$x}@}
.if exists($f.dirdep)
ddep_list += $f.dirdep
.elif exists(${f:H}.dirdep)
ddep_list += ${f:H}.dirdep
.else
dir_list += ${f:H:tA}
dpadd_dir_list += ${f:H:tA}
.endif
.endfor
.if !empty(ddep_list)
ddeps != cat ${ddep_list:O:u} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \
sed ${GENDIRDEPS_SEDCMDS}
.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != ""
.info ${RELDIR}: raw_dir_list='${dir_list}'
.info ${RELDIR}: ddeps='${ddeps}'
.endif
dir_list += ${ddeps}
.endif
.endif
.endif
# DIRDEPS represent things that had to have been built first
# so they should all be undir OBJTOP.
# Note that ${_OBJTOP}/bsd/include/machine will get reported
# to us as $SRCTOP/bsd/sys/$MACHINE_ARCH/include meaning we
# will want to visit bsd/include
# so we add
# ${"${dir_list:M*bsd/sys/${MACHINE_ARCH}/include}":?bsd/include:}
# to GENDIRDEPS_DIR_LIST_XTRAS
_objtops = ${OBJTOP} ${_OBJTOP} ${_objtop}
_objtops := ${_objtops:O:u}
dirdep_list = \
${_objtops:@o@${dir_list:M$o*/*:C,$o[^/]*/,,}@} \
${GENDIRDEPS_DIR_LIST_XTRAS}
# sort longest first
M2D_OBJROOTS := ${M2D_OBJROOTS:O:u:[-1..1]}
# anything we use from an object dir other than ours
# needs to be qualified with its .<machine> suffix
# (we used the pseudo machine "host" for the HOST_TARGET).
skip_ql= ${SRCTOP}* ${_objtops:@o@$o*@}
.for o in ${M2D_OBJROOTS:${skip_ql:${M_ListToSkip}}}
# we need := so only skip_ql to this point applies
ql.$o := ${dir_list:${skip_ql:${M_ListToSkip}}:M$o*/*/*:C,$o([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,}
qualdir_list += ${ql.$o}
.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != ""
.info ${RELDIR}: o=$o ${ql.$o qualdir_list:L:@v@$v=${$v}@}
.endif
skip_ql+= $o*
.endfor
dirdep_list := ${dirdep_list:O:u}
qualdir_list := ${qualdir_list:N*.${MACHINE}:O:u}
DIRDEPS = \
${dirdep_list:N${RELDIR}:N${RELDIR}/*} \
${qualdir_list:N${RELDIR}.*:N${RELDIR}/*}
# We only consider things below $RELDIR/ if they have a makefile.
# This is the same test that _DIRDEP_USE applies.
# We have do a double test with dirdep_list as it _may_ contain
# qualified dirs - if we got anything from a stage dir.
# qualdir_list we know are all qualified.
# It would be nice do peform this check for all of DIRDEPS,
# but we cannot assume that all of the tree is present,
# in fact we can only assume that RELDIR is.
DIRDEPS += \
${dirdep_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/$d/$m):?$d:${exists(${SRCTOP}/${d:R}/$m):?$d:}}@}@} \
${qualdir_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/${d:R}/$m):?$d:}@}@}
# what modifiers do we allow in GENDIRDEPS_FILTER
GENDIRDEPS_FILTER_MASK += @CMNS
DIRDEPS := ${DIRDEPS:${GENDIRDEPS_FILTER:UNno:M[${GENDIRDEPS_FILTER_MASK:O:u:ts}]*:ts:}:C,//+,/,g:O:u}
.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != ""
.info ${RELDIR}: M2D_OBJROOTS=${M2D_OBJROOTS}
.info ${RELDIR}: M2D_EXCLUDES=${M2D_EXCLUDES}
.info ${RELDIR}: dir_list='${dir_list}'
.info ${RELDIR}: dpadd_dir_list='${dpadd_dir_list}'
.info ${RELDIR}: dirdep_list='${dirdep_list}'
.info ${RELDIR}: qualdir_list='${qualdir_list}'
.info ${RELDIR}: SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS}'
.info ${RELDIR}: GENDIRDEPS_FILTER='${GENDIRDEPS_FILTER}'
.info ${RELDIR}: FORCE_DPADD='${DPADD}'
.info ${RELDIR}: DIRDEPS='${DIRDEPS}'
.endif
# SRC_DIRDEPS is for checkout logic
src_dirdep_list = \
${dir_list:M${SRCTOP}/*:S,${SRCTOP}/,,}
SRC_DIRDEPS = \
${src_dirdep_list:N${RELDIR}:N${RELDIR}/*:C,(/h)/.*,,}
SRC_DIRDEPS := ${SRC_DIRDEPS:${GENDIRDEPS_SRC_FILTER:UN/*:ts:}:C,//+,/,g:O:u}
# if you want to capture SRC_DIRDEPS in .MAKE.DEPENDFILE put
# SRC_DIRDEPS_FILE = ${_DEPENDFILE}
# in local.gendirdeps.mk
.if ${SRC_DIRDEPS_FILE:Uno:tl} != "no"
ECHO_SRC_DIRDEPS = echo 'SRC_DIRDEPS = \'; echo '${SRC_DIRDEPS:@d@ $d \\${.newline}@}'; echo;
.if ${SRC_DIRDEPS_FILE:T} == ${_DEPENDFILE:T}
_include_src_dirdeps = ${ECHO_SRC_DIRDEPS}
.else
all: ${SRC_DIRDEPS_FILE}
.if !target(${SRC_DIRDEPS_FILE})
${SRC_DIRDEPS_FILE}: ${META_FILES} ${_this} ${META2DEPS}
@(${ECHO_SRC_DIRDEPS}) > $@
.endif
.endif
.endif
_include_src_dirdeps ?=
all: ${_DEPENDFILE}
# if this is going to exist it would be there by now
.if !exists(.depend)
CAT_DEPEND = /dev/null
.endif
CAT_DEPEND ?= .depend
.if !empty(_DIRDEPS) && ${DIRDEPS} != ${_DIRDEPS}
# we may have changed a filter
.PHONY: ${_DEPENDFILE}
.endif
# 'cat .depend' should suffice, but if we are mixing build modes
# .depend may contain things we don't want.
# The sed command at the end of the stream, allows for the filters
# to output _{VAR} tokens which we will turn into proper ${VAR} references.
${_DEPENDFILE}: .NOMETA ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS}
@(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \
echo 'DIRDEPS = \'; \
echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
${_include_src_dirdeps} \
echo '.include <dirdeps.mk>'; \
echo; \
echo '.if $${DEP_RELDIR} == $${_DEP_RELDIR}'; \
echo '# local dependencies - needed for -jN in clean tree'; \
[ -s ${CAT_DEPEND} ] && { grep : ${CAT_DEPEND} | grep -v '[/\\]'; }; \
echo '.endif' ) | sed 's,_\([{(]\),$$\1,g' > $@.new${.MAKE.PID}
@${InstallNew}; InstallNew -s $@.new${.MAKE.PID}
.endif # meta2deps failed
.elif !empty(SUBDIR)
DIRDEPS := ${SUBDIR:S,^,${RELDIR}/,:O:u}
all: ${_DEPENDFILE}
${_DEPENDFILE}: .NOMETA ${MAKEFILE} ${_this}
@(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \
echo 'DIRDEPS = \'; \
echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
echo '.include <dirdeps.mk>'; \
echo ) | sed 's,_\([{(]\),$$\1,g' > $@.new
@${InstallNew}; InstallNew $@.new
.else
# nothing to do
all ${_DEPENDFILE}:
.endif
${_DEPENDFILE}: .PRECIOUS
# don't waste time looking for ways to make .meta files
.SUFFIXES:

View File

@ -0,0 +1,44 @@
# RCSid:
# $Id: host-target.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# Host platform information; may be overridden
.if !defined(_HOST_OSNAME)
_HOST_OSNAME != uname -s
.export _HOST_OSNAME
.endif
.if !defined(_HOST_OSREL)
_HOST_OSREL != uname -r
.export _HOST_OSREL
.endif
.if !defined(_HOST_MACHINE)
_HOST_MACHINE != uname -m
.export _HOST_MACHINE
.endif
.if !defined(_HOST_ARCH)
# for NetBSD prefer $MACHINE (amd64 rather than x86_64)
.if ${_HOST_OSNAME:NNetBSD} == ""
_HOST_ARCH := ${_HOST_MACHINE}
.else
_HOST_ARCH != uname -p 2> /dev/null || uname -m
# uname -p may produce garbage on linux
.if ${_HOST_ARCH:[\#]} > 1 || ${_HOST_ARCH:Nunknown} == ""
_HOST_ARCH := ${_HOST_MACHINE}
.endif
.endif
.export _HOST_ARCH
.endif
.if !defined(HOST_MACHINE)
HOST_MACHINE := ${_HOST_MACHINE}
.export HOST_MACHINE
.endif
HOST_OSMAJOR := ${_HOST_OSREL:C/[^0-9].*//}
HOST_OSTYPE := ${_HOST_OSNAME:S,/,,g}-${_HOST_OSREL:C/\([^\)]*\)//}-${_HOST_ARCH}
HOST_OS := ${_HOST_OSNAME}
host_os := ${_HOST_OSNAME:tl}
HOST_TARGET := ${host_os:S,/,,g}${HOST_OSMAJOR}-${_HOST_ARCH}
# tr is insanely non-portable, accommodate the lowest common denominator
TR ?= tr
toLower = ${TR} 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'
toUpper = ${TR} 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

View File

@ -0,0 +1,29 @@
# $Id: host.libnames.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2007-2009, 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
#
DLIBEXT ?= .a
DSHLIBEXT ?= ${DLIBEXT}
HOST_LIBEXT ?= ${DSHLIBEXT}
HOST_LIBDIRS ?= /usr/lib /lib
HOST_LIBS ?=
.for x in ${HOST_LIBS:O:u}
.for d in ${HOST_LIBDIRS}
.if exists($d/lib$x${HOST_LIBEXT})
LIB${x:tu} ?= $d/lib$x${HOST_LIBEXT}
.endif
.endfor
.endfor

View File

@ -0,0 +1,89 @@
# $Id: inc.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2008, 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
#
.include <init.mk>
.if !empty(LIBOWN)
INC_INSTALL_OWN ?= -o ${LIBOWN} -g ${LIBGRP}
.endif
INCMODE ?= 444
INC_COPY ?= -C
INCSDIR ?= ${INCDIR}
STAGE_INCSDIR?= ${STAGE_OBJTOP}${INCSDIR}
# accommodate folk used to freebsd
INCGROUPS ?= ${INCSGROUPS:UINCS}
INCGROUPS := ${INCGROUPS:O:u}
.if !target(buildincludes)
.for group in ${INCGROUPS}
buildincludes: ${${group}}
.endfor
.endif
buildincludes:
includes: buildincludes
.if !target(incinstall)
.for group in ${INCGROUPS}
.if !empty(${group})
.if ${group} != "INC"
${group}_INSTALL_OWN ?= ${INC_INSTALL_OWN}
${group}DIR ?= ${INCDIR}
.endif
# incase we are staging
STAGE_DIR.${group} ?= ${STAGE_OBJTOP}${${group}DIR}
.for header in ${${group}:O:u}
${group}_INSTALL_OWN.${header:T} ?= ${${group}_INSTALL_OWN}
${group}DIR.${header:T} ?= ${${group}DIR}
inc_mkdir_list += ${${group}DIR.${header:T}}
.if defined(${group}NAME.${header:T})
STAGE_AS_SETS += ${group}
STAGE_AS_${header} = ${${group}NAME.${header:T}}
stage_as.${group}: ${header}
incinstall: incinstall.${group}.${header:T}
incinstall.${group}.${header:T}: ${header} inc_mkdirs
${INSTALL} ${INC_COPY} ${${group}_INSTALL_OWN.${header:T}} -m ${INCMODE} ${.ALLSRC:Ninc_mkdirs} ${DESTDIR}${${group}DIR}/${${group}NAME.${header:T}}
.else
STAGE_SETS += ${group}
stage_files.${group}: ${header}
incinstall.${group}: ${header}
incinstall: incinstall.${group}
.endif
.endfor # header
incinstall.${group}: inc_mkdirs
${INSTALL} ${INC_COPY} ${${group}_INSTALL_OWN} -m ${INCMODE} \
${.ALLSRC:Ninc_mkdirs:O:u} ${DESTDIR}${${group}DIR}
.endif # !empty
.endfor # group
inc_mkdirs:
@for d in ${inc_mkdir_list:O:u}; do \
test -d ${DESTDIR}$$d || \
${INSTALL} -d ${INC_INSTALL_OWN} -m 775 ${DESTDIR}$$d; \
done
.endif # !target(incinstall)
beforeinstall:
realinstall: incinstall
.ORDER: beforeinstall incinstall

View File

@ -0,0 +1,70 @@
# $Id: init.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2002, 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 !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
.if ${MAKE_VERSION:U0} > 20100408
_this_mk_dir := ${.PARSEDIR:tA}
.else
_this_mk_dir := ${.PARSEDIR}
.endif
.-include <local.init.mk>
.-include <${.CURDIR:H}/Makefile.inc>
.include <own.mk>
.include <compiler.mk>
.MAIN: all
# should have been set by sys.mk
CXX_SUFFIXES?= .cc .cpp .cxx .C
.if !empty(WARNINGS_SET) || !empty(WARNINGS_SET_${MACHINE_ARCH})
.include <warnings.mk>
.endif
.for x in COPTS CPPFLAGS CPUFLAGS LDFLAGS
$x += ${$x.${COMPILER_TYPE}:U} ${$x.${.IMPSRC:T}:U}
.endfor
CC_PG?= -pg
CXX_PG?= ${CC_PG}
CC_PIC?= -DPIC
CXX_PIC?= ${CC_PIC}
PROFFLAGS?= -DGPROF -DPROF
.if ${.MAKE.LEVEL:U1} == 0 && ${BUILD_AT_LEVEL0:Uyes:tl} == "no"
# this tells lib.mk and prog.mk to not actually build anything
_SKIP_BUILD = not building at level 0
.endif
.if !defined(.PARSEDIR)
# no-op is the best we can do if not bmake.
.WAIT:
.endif
# define this once for consistency
.if empty(_SKIP_BUILD)
# beforebuild is a hook for things that must be done early
all: beforebuild .WAIT realbuild
.else
all: .PHONY
.warning ${_SKIP_BUILD}
.endif
beforebuild:
realbuild:
.endif

View File

@ -0,0 +1,185 @@
:
# NAME:
# install-mk - install mk files
#
# SYNOPSIS:
# install-mk [options] [var=val] [dest]
#
# DESCRIPTION:
# This tool installs mk files in a semi-intelligent manner into
# "dest".
#
# Options:
#
# -n just say what we want to do, but don't touch anything.
#
# -f use -f when copying sys,mk.
#
# -v be verbose
#
# -q be quiet
#
# -m "mode"
# Use "mode" for installed files (444).
#
# -o "owner"
# Use "owner" for installed files.
#
# -g "group"
# Use "group" for installed files.
#
# var=val
# Set "var" to "val". See below.
#
# All our *.mk files are copied to "dest" with appropriate
# ownership and permissions.
#
# By default if a sys.mk can be found in a standard location
# (that bmake will find) then no sys.mk will be put in "dest".
#
# SKIP_SYS_MK:
# If set, we will avoid installing our 'sys.mk'
# This is probably a bad idea.
#
# SKIP_BSD_MK:
# If set, we will skip making bsd.*.mk links to *.mk
#
# sys.mk:
#
# By default (and provided we are not installing to the system
# mk dir - '/usr/share/mk') we install our own 'sys.mk' which
# includes a sys specific file, or a generic one.
#
#
# AUTHOR:
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
# $Id: install-mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 1994 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
#
MK_VERSION=20200515
OWNER=
GROUP=
MODE=444
BINMODE=555
ECHO=:
SKIP=
cp_f=-f
while :
do
case "$1" in
*=*) eval "$1"; shift;;
+f) cp_f=; shift;;
-f) cp_f=-f; shift;;
-m) MODE=$2; shift 2;;
-o) OWNER=$2; shift 2;;
-g) GROUP=$2; shift 2;;
-v) ECHO=echo; shift;;
-q) ECHO=:; shift;;
-n) ECHO=echo SKIP=:; shift;;
--) shift; break;;
*) break;;
esac
done
case $# in
0) echo "$0 [options] <destination> [<os>]"
echo "eg."
echo "$0 -o bin -g bin -m 444 /usr/local/share/mk"
exit 1
;;
esac
dest=$1
os=${2:-`uname`}
osrel=${3:-`uname -r`}
Do() {
$ECHO "$@"
$SKIP "$@"
}
Error() {
echo "ERROR: $@" >&2
exit 1
}
Warning() {
echo "WARNING: $@" >&2
}
[ "$FORCE_SYS_MK" ] && Warning "ignoring: FORCE_{BSD,SYS}_MK (no longer supported)"
SYS_MK_DIR=${SYS_MK_DIR:-/usr/share/mk}
SYS_MK=${SYS_MK:-$SYS_MK_DIR/sys.mk}
realpath() {
[ -d $1 ] && cd $1 && 'pwd' && return
echo $1
}
if [ -s $SYS_MK -a -d $dest ]; then
# if this is a BSD system we don't want to touch $SYS_MK
dest=`realpath $dest`
sys_mk_dir=`realpath $SYS_MK_DIR`
if [ $dest = $sys_mk_dir ]; then
case "$os" in
*BSD*) SKIP_SYS_MK=:
SKIP_BSD_MK=:
;;
*) # could be fake?
if [ ! -d $dest/sys -a ! -s $dest/Generic.sys.mk ]; then
SKIP_SYS_MK=: # play safe
SKIP_BSD_MK=:
fi
;;
esac
fi
fi
[ -d $dest/sys ] || Do mkdir -p $dest/sys
[ -d $dest/sys ] || Do mkdir $dest/sys || exit 1
[ -z "$SKIP" ] && dest=`realpath $dest`
cd `dirname $0`
mksrc=`'pwd'`
if [ $mksrc = $dest ]; then
SKIP_MKFILES=:
else
# we do not install the examples
mk_files=`grep '^[a-z].*\.mk' FILES | egrep -v '(examples/|^sys\.mk|sys/)'`
mk_scripts=`egrep '^[a-z].*\.(sh|py)' FILES | egrep -v '/'`
sys_mk_files=`grep 'sys/.*\.mk' FILES`
SKIP_MKFILES=
[ -z "$SKIP_SYS_MK" ] && mk_files="sys.mk $mk_files"
fi
$SKIP_MKFILES Do cp $cp_f $mk_files $dest
$SKIP_MKFILES Do cp $cp_f $sys_mk_files $dest/sys
$SKIP_MKFILES Do cp $cp_f $mk_scripts $dest
$SKIP cd $dest
$SKIP_MKFILES Do chmod $MODE $mk_files $sys_mk_files
$SKIP_MKFILES Do chmod $BINMODE $mk_scripts
[ "$GROUP" ] && $SKIP_MKFILES Do chgrp $GROUP $mk_files $sys_mk_files
[ "$OWNER" ] && $SKIP_MKFILES Do chown $OWNER $mk_files $sys_mk_files
# if this is a BSD system the bsd.*.mk should exist and be used.
if [ -z "$SKIP_BSD_MK" ]; then
for f in dep doc files inc init lib links man nls obj own prog subdir
do
b=bsd.$f.mk
[ -s $b ] || Do ln -s $f.mk $b
done
fi
exit 0

View File

@ -0,0 +1,53 @@
# $Id: install-new.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2009, 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 !defined(InstallNew)
# copy if src and target are different making a backup if desired
CmpCp= CmpCp() { \
src=$$1 target=$$2 _bak=$$3; \
if ! test -s $$target || ! cmp -s $$target $$src; then \
trap "" 1 2 3 15; \
if test -s $$target; then \
if test "x$$_bak" != x; then \
rm -f $$target$$_bak; \
mv $$target $$target$$_bak; \
else \
rm -f $$target; \
fi; \
fi; \
cp $$src $$target; \
fi; }
# If the .new file is different, we want it.
# Note: this function will work as is for *.new$RANDOM"
InstallNew= ${CmpCp}; InstallNew() { \
_t=-e; _bak=; \
while :; do \
case "$$1" in \
-?) _t=$$1; shift;; \
--bak) _bak=$$2; shift 2;; \
*) break;; \
esac; \
done; \
for new in "$$@"; do \
if test $$_t $$new; then \
target=`expr $$new : '\(.*\).new'`; \
CmpCp $$new $$target $$_bak; \
fi; \
rm -f $$new; \
done; :; }
.endif

View File

@ -0,0 +1,97 @@
#
# RCSid:
# $Id: java.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# @(#) Copyright (c) 1998-2001, 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 !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
.include <init.mk>
CLASSPATH?=.
.if defined(PROG)
SRCS?= ${PROG:.class=.java}
.endif
.if !defined(SRCS) || empty(SRCS)
SRCS!=cd ${.CURDIR} && echo *.java
.endif
.SUFFIXES: .class .java
CLEANFILES+= *.class
JAVAC?= javac
JAVADOC?= javadoc
.if !target(docs)
docs:
${JAVADOC} ${JAVADOC_FLAGS} ${SRCS}
.endif
.if defined(JAVADESTDIR) && !empty(JAVADESTDIR)
JAVASRCDIR?=${JAVADESTDIR:H}/src
__classdest:=${JAVADESTDIR}${.CURDIR:S,${JAVASRCDIR},,}/
CLASSPATH:=${CLASSPATH}:${JAVADESTDIR}
JAVAC_FLAGS+= -d ${JAVADESTDIR}
.else
__classdest=
.endif
JAVAC_FLAGS+= ${JAVAC_DBG}
.if defined(MAKE_VERSION) && !defined(NO_CLASSES_COOKIE)
# java works best by compiling a bunch of classes at once.
# this lot does that but needs a recent netbsd make or
# or its portable cousin bmake.
.for __s in ${SRCS}
__c:= ${__classdest}${__s:.java=.class}
.if !target(${__c})
# We need to do something to force __c's parent to be made.
${__c}: ${__s}
@rm -f ${.TARGET}
.endif
SRCS_${__c}=${__s}
__classes:= ${__classes} ${__c}
.endfor
__classes_cookie=${__classdest}.classes.done
CLEANFILES+= ${__classes} ${__classes_cookie}
${__classes_cookie}: ${__classes}
CLASSPATH=${CLASSPATH} ${JAVAC} ${JAVAC_FLAGS} ${.OODATE:@c@${SRCS_$c}@}
@touch ${.TARGET}
all: ${__classes_cookie}
.else
# this will work with other BSD make's
.for __s in ${SRCS}
__c:= ${__classdest}${__s:.java=.class}
${__c}: ${__s}
CLASSPATH=${CLASSPATH} ${JAVAC} ${JAVAC_FLAGS} ${.OODATE}
.endfor
all: ${SRCS:%.java=${__classdest}%.class}
.endif
.if !target(cleanjava)
cleanjava:
rm -f [Ee]rrs mklog core *.core ${PROG} ${CLEANFILES}
clean: cleanjava
cleandir: cleanjava
.endif
.endif

View File

@ -0,0 +1,156 @@
# $Id: ldorder.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2015, 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
#
# Try to compute optimal link order.
# When using only shared libs link order does not much matter,
# but archive libs are a different matter.
# We can construct a graph of .ldorder-lib${LIB*} dependencies
# and associate each with _LDORDER_USE to output the relevant
# ld flags.
# Due to the nature of make, the result will be in the reverse order
# that we want to feed to ld.
# So we need to reverse it before use.
.if !target(_LDORDER_USE)
# does caller want to use ldorder?
# yes for prog, normally no for lib
.if ${.ALLTARGETS:Mldorder} != ""
_ldorder_use:
.endif
# define this if we need a barrier between local and external libs
# see below
LDORDER_EXTERN_BARRIER ?= .ldorder-extern-barrier
.-include <local.ldorder.mk>
# convert /path/to/libfoo.a into _{LIBFOO}
LDORDER_INC_FILTER += S,+,PLUS,g S,.so$$,,g
LDORDER_LIBS_FILTER += O:u
LDORDER_INC ?= ldorder.inc
# for meta mode
REFERENCE_FILE ?= :
_LDORDER_USE: .ldorder-rm .USE .NOTMAIN
@echo depends: ${.ALLSRC:M.ldorder-lib*} > /dev/null
@echo ${LDADD_${.TARGET:T:S,.ldorder-,,}:U${.TARGET:T:S/.ldorder-lib/-l/}} >> .ldorder
@${META_COOKIE_TOUCH}
# we need to truncate our working file
.ldorder-rm: .NOTMAIN
@rm -f .ldorder ldorder-*
@${.ALLSRC:O:u:@f@${REFERENCE_FILE} < $f;@}
@${META_COOKIE_TOUCH}
# make sure this exists
.ldorder: .NOTMAIN
# and finally we need to reverse the order of content
ldorder: .ldorder .NOTMAIN
@{ test ! -s .ldorder || cat -n .ldorder | sort -rn | \
sed '/ldorder-/d;s,^[[:space:]0-9]*,,'; } > ${.TARGET}
# Initially we hook contents of DPLIBS and DPADD into our graph
LDORDER_LIBS ?= ${DPLIBS} ${DPADD:M*/lib*} ${__dpadd_libs}
# we need to remember this
_LDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}}
.if empty(_LDORDER_LIBS)
# don't use stale ldorder
LDADD_LDORDER =
.else
# this is how you use it
LDADD_LDORDER ?= `cat ldorder`
.endif
# for debug below
_ldorder = ${RELDIR}.${TARGET_SPEC}
# we make have some libs that exist outside of $SB
# and want to insert a barrier
.if target(${LDORDER_EXTERN_BARRIER})
# eg. in local.ldorder.mk
# ${LDORDER_EXTERN_BARRIER}:
# @test -z "${extern_ldorders}" || \
# echo -Wl,-Bdynamic >> .ldorder
#
# feel free to put more suitable version in local.ldorder.mk if needed
# we do *not* count host libs in extern_ldorders
extern_ldorders ?= ${__dpadd_libs:tA:N/lib*:N/usr/lib*:N${SB}/*:N${SB_OBJROOT:tA}*:T:${LDORDER_LIBS_FILTER:ts:}:R:C/\.so.*//:S,^,.ldorder-,:N.ldorder-}
sb_ldorders ?= ${.ALLTARGETS:M.ldorder-*:N${LDORDER_EXTERN_BARRIER}:N.ldorder-rm:${extern_ldorders:${M_ListToSkip}}:N.ldorder-}
# finally in Makefile after include of *.mk put
# .ldorder ${sb_ldorders}: ${LDORDER_EXTERN_BARRIER}
# ${LDORDER_EXTERN_BARRIER}: ${extern_ldorders}
.endif
.endif # !target(_LDORDER_USE)
.if !empty(LDORDER_LIBS) && target(_ldorder_use)
# canonicalize - these are just tokens anyway
LDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}:R:C/\.so.*//}
_ldorders := ${LDORDER_LIBS:T:Mlib*:S,^,.ldorder-,}
.for t in ${_ldorders}
.if !target($t)
$t: _LDORDER_USE
.endif
.endfor
# and this makes it all happen
.ldorder: ${_ldorders}
# this is how we get the dependencies
.if ${.INCLUDEDFROMFILE:M*.${LDORDER_INC}} != ""
_ldorder := .ldorder-${.INCLUDEDFROMFILE:S/.${LDORDER_INC}//}
${_ldorder}: ${_ldorders}
.ldorder-rm: ${.INCLUDEDFROMDIR}/${.INCLUDEDFROMFILE}
.endif
# set DEBUG_LDORDER to pattern[s] that match the dirs of interest
.if ${DEBUG_LDORDER:Uno:@x@${RELDIR:M$x}@} != ""
.info ${_ldorder}: ${_ldorders}
.endif
# now try to find more ...
# each *.${LDORDER_INC} should set LDORDER_LIBS to what it needs
# it can also add to CFLAGS etc.
.for __inc in ${LDORDER_LIBS:S,$,.${LDORDER_INC},}
.if !target(__${__inc}__)
__${__inc}__:
# make sure this is reset
LDORDER_LIBS =
_ldorders =
.-include <${__inc}>
.endif
.endfor
.endif # !empty(LDORDER_LIBS)
.ifdef LIB
# you can make this depend on files (must match *ldorder*)
# to add extra content - like CFLAGS
libLDORDER_INC = lib${LIB}.${LDORDER_INC}
.if !commands(${libLDORDER_INC})
.if target(ldorder-header)
${libLDORDER_INC}: ldorder-header
.endif
${libLDORDER_INC}:
@(cat /dev/null ${.ALLSRC:M*ldorder*}; \
echo 'LDORDER_LIBS= ${_LDORDER_LIBS:T:R:${LDORDER_INC_FILTER:ts:}:tu:C,.*,_{&},:N_{}}'; \
echo; echo '.include <ldorder.mk>' ) | sed 's,_{,$${,g' > ${.TARGET}
.endif
.endif

609
devel/bmake/files/mk/lib.mk Normal file
View File

@ -0,0 +1,609 @@
# $Id: lib.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
.include <init.mk>
.if ${OBJECT_FMT} == "ELF"
NEED_SOLINKS?= yes
.endif
SHLIB_VERSION_FILE?= ${.CURDIR}/shlib_version
.if !defined(SHLIB_MAJOR) && exists(${SHLIB_VERSION_FILE})
SHLIB_MAJOR != . ${SHLIB_VERSION_FILE} ; echo $$major
SHLIB_MINOR != . ${SHLIB_VERSION_FILE} ; echo $$minor
SHLIB_TEENY != . ${SHLIB_VERSION_FILE} ; echo $$teeny
.endif
.for x in major minor teeny
print-shlib-$x:
.if defined(SHLIB_${x:tu}) && ${MK_PIC} != "no"
@echo ${SHLIB_${x:tu}}
.else
@false
.endif
.endfor
SHLIB_FULLVERSION ?= ${${SHLIB_MAJOR} ${SHLIB_MINOR} ${SHLIB_TEENY}:L:ts.}
SHLIB_FULLVERSION := ${SHLIB_FULLVERSION}
# add additional suffixes not exported.
# .po is used for profiling object files.
# ${PICO} is used for PIC object files.
PICO?= .pico
.SUFFIXES: .out .a .ln ${PICO} .po .o .s .S .c .cc .C .m .F .f .r .y .l .cl .p .h
.SUFFIXES: .sh .m4 .m
CFLAGS+= ${COPTS}
META_NOECHO?= echo
# Originally derrived from NetBSD-1.6
# Set PICFLAGS to cc flags for producing position-independent code,
# if not already set. Includes -DPIC, if required.
# Data-driven table using make variables to control how shared libraries
# are built for different platforms and object formats.
# OBJECT_FMT: currently either "ELF" or "a.out", from <bsd.own.mk>
# SHLIB_SOVERSION: version number to be compiled into a shared library
# via -soname. Usually ${SHLIB_MAJOR} on ELF.
# NetBSD/pmax used to use ${SHLIB_MAJOR}[.${SHLIB_MINOR}
# [.${SHLIB_TEENY}]]
# SHLIB_SHFLAGS: Flags to tell ${LD} to emit shared library.
# with ELF, also set shared-lib version for ld.so.
# SHLIB_LDSTARTFILE: support .o file, call C++ file-level constructors
# SHLIB_LDENDFILE: support .o file, call C++ file-level destructors
# FPICFLAGS: flags for ${FC} to compile .[fF] files to ${PICO} objects.
# CPPICFLAGS: flags for ${CPP} to preprocess .[sS] files for ${AS}
# CPICFLAGS: flags for ${CC} to compile .[cC] files to ${PICO} objects.
# CAPICFLAGS flags for {$CC} to compiling .[Ss] files
# (usually just ${CPPPICFLAGS} ${CPICFLAGS})
# APICFLAGS: flags for ${AS} to assemble .[sS] to ${PICO} objects.
.if ${TARGET_OSNAME} == "NetBSD"
.if ${MACHINE_ARCH} == "alpha"
# Alpha-specific shared library flags
FPICFLAGS ?= -fPIC
CPICFLAGS ?= -fPIC -DPIC
CPPPICFLAGS?= -DPIC
CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS}
APICFLAGS ?=
.elif ${MACHINE_ARCH} == "mipsel" || ${MACHINE_ARCH} == "mipseb"
# mips-specific shared library flags
# On mips, all libs are compiled with ABIcalls, not just sharedlibs.
MKPICLIB= no
# so turn shlib PIC flags on for ${AS}.
AINC+=-DABICALLS
AFLAGS+= -fPIC
AS+= -KPIC
.elif ${MACHINE_ARCH} == "vax" && ${OBJECT_FMT} == "ELF"
# On the VAX, all object are PIC by default, not just sharedlibs.
MKPICLIB= no
.elif (${MACHINE_ARCH} == "sparc" || ${MACHINE_ARCH} == "sparc64") && \
${OBJECT_FMT} == "ELF"
# If you use -fPIC you need to define BIGPIC to turn on 32-bit
# relocations in asm code
FPICFLAGS ?= -fPIC
CPICFLAGS ?= -fPIC -DPIC
CPPPICFLAGS?= -DPIC -DBIGPIC
CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS}
APICFLAGS ?= -KPIC
.else
# Platform-independent flags for NetBSD a.out shared libraries
SHLIB_SOVERSION=${SHLIB_FULLVERSION}
SHLIB_SHFLAGS=
FPICFLAGS ?= -fPIC
CPICFLAGS?= -fPIC -DPIC
CPPPICFLAGS?= -DPIC
CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS}
APICFLAGS?= -k
.endif
# Platform-independent linker flags for ELF shared libraries
.if ${OBJECT_FMT} == "ELF"
SHLIB_SOVERSION= ${SHLIB_MAJOR}
SHLIB_SHFLAGS= -soname lib${LIB}.so.${SHLIB_SOVERSION}
SHLIB_LDSTARTFILE?= /usr/lib/crtbeginS.o
SHLIB_LDENDFILE?= /usr/lib/crtendS.o
.endif
# for compatibility with the following
CC_PIC?= ${CPICFLAGS}
LD_shared=${SHLIB_SHFLAGS}
.endif # NetBSD
.if ${TARGET_OSNAME} == "FreeBSD"
.if ${OBJECT_FMT} == "ELF"
SHLIB_SOVERSION= ${SHLIB_MAJOR}
SHLIB_SHFLAGS= -soname lib${LIB}.so.${SHLIB_SOVERSION}
.else
SHLIB_SHFLAGS= -assert pure-text
.endif
SHLIB_LDSTARTFILE=
SHLIB_LDENDFILE=
CC_PIC?= -fpic
LD_shared=${SHLIB_SHFLAGS}
.endif # FreeBSD
MKPICLIB?= yes
# sys.mk can override these
LD_X?=-X
LD_x?=-x
LD_r?=-r
# Non BSD machines will be using bmake.
.if ${TARGET_OSNAME} == "SunOS"
LD_shared=-assert pure-text
.if ${OBJECT_FMT} == "ELF" || ${MACHINE} == "solaris"
# Solaris
LD_shared=-h lib${LIB}.so.${SHLIB_MAJOR} -G
.endif
.elif ${TARGET_OSNAME} == "HP-UX"
LD_shared=-b
LD_so=sl
DLLIB=
# HPsUX lorder does not grok anything but .o
LD_sobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,${PICO},'`
LD_pobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,.po,'`
.elif ${TARGET_OSNAME} == "OSF1"
LD_shared= -msym -shared -expect_unresolved '*'
LD_solib= -all lib${LIB}_pic.a
DLLIB=
# lorder does not grok anything but .o
LD_sobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,${PICO},'`
LD_pobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,.po,'`
AR_cq= -cqs
.elif ${TARGET_OSNAME} == "FreeBSD"
LD_solib= lib${LIB}_pic.a
.elif ${TARGET_OSNAME} == "Linux"
SHLIB_LD = ${CC}
# this is ambiguous of course
LD_shared=-shared -Wl,"-soname lib${LIB}.so.${SHLIB_MAJOR}"
LD_solib= -Wl,--whole-archive lib${LIB}_pic.a -Wl,--no-whole-archive
.if ${COMPILER_TYPE} == "gcc"
# Linux uses GNU ld, which is a multi-pass linker
# so we don't need to use lorder or tsort
LD_objs = ${OBJS}
LD_pobjs = ${POBJS}
LD_sobjs = ${SOBJS}
.endif
.elif ${TARGET_OSNAME} == "Darwin"
SHLIB_LD = ${CC}
SHLIB_INSTALL_VERSION ?= ${SHLIB_MAJOR}
SHLIB_COMPATABILITY_VERSION ?= ${SHLIB_MAJOR}.${SHLIB_MINOR:U0}
SHLIB_COMPATABILITY ?= \
-compatibility_version ${SHLIB_COMPATABILITY_VERSION} \
-current_version ${SHLIB_FULLVERSION}
LD_shared = -dynamiclib \
-flat_namespace -undefined suppress \
-install_name ${LIBDIR}/lib${LIB}.${SHLIB_INSTALL_VERSION}.${LD_solink} \
${SHLIB_COMPATABILITY}
SHLIB_LINKS =
.for v in ${SHLIB_COMPATABILITY_VERSION} ${SHLIB_INSTALL_VERSION}
.if "$v" != "${SHLIB_FULLVERSION}"
SHLIB_LINKS += lib${LIB}.$v.${LD_solink}
.endif
.endfor
.if ${MK_LINKLIB} != "no"
SHLIB_LINKS += lib${LIB}.${LD_solink}
.endif
LD_so = ${SHLIB_FULLVERSION}.dylib
LD_sobjs = ${SOBJS:O:u}
LD_solib = ${LD_sobjs}
SOLIB = ${LD_sobjs}
LD_solink = dylib
.if ${MACHINE_ARCH} == "i386"
PICFLAG ?= -fPIC
.else
PICFLAG ?= -fPIC -fno-common
.endif
RANLIB = :
.endif
SHLIB_LD ?= ${LD}
.if !empty(SHLIB_MAJOR)
.if ${NEED_SOLINKS} && empty(SHLIB_LINKS)
.if ${MK_LINKLIB} != "no"
SHLIB_LINKS = lib${LIB}.${LD_solink}
.endif
.if "${SHLIB_FULLVERSION}" != "${SHLIB_MAJOR}"
SHLIB_LINKS += lib${LIB}.${LD_solink}.${SHLIB_MAJOR}
.endif
.endif
.endif
LIBTOOL?=libtool
LD_shared ?= -Bshareable -Bforcearchive
LD_so ?= so.${SHLIB_FULLVERSION}
LD_solink ?= so
.if empty(LORDER)
LD_objs ?= ${OBJS}
LD_pobjs ?= ${POBJS}
LD_sobjs ?= ${SOBJS}
.else
LD_objs ?= `${LORDER} ${OBJS} | ${TSORT}`
LD_sobjs ?= `${LORDER} ${SOBJS} | ${TSORT}`
LD_pobjs ?= `${LORDER} ${POBJS} | ${TSORT}`
.endif
LD_solib ?= ${LD_sobjs}
AR_cq ?= cq
.if exists(/netbsd) && exists(${DESTDIR}/usr/lib/libdl.so)
DLLIB ?= -ldl
.endif
# some libs have lots of objects, and scanning all .o, .po and ${PICO} meta files
# is a waste of time, this tells meta.autodep.mk to just pick one
# (typically ${PICO})
# yes, 42 is a random number.
.if ${MK_DIRDEPS_BUILD} == "yes" && ${SRCS:Uno:[\#]} > 42
OPTIMIZE_OBJECT_META_FILES ?= yes
.endif
.if ${MK_LIBTOOL} == "yes"
# because libtool is so fascist about naming the object files,
# we cannot (yet) build profiled libs
MK_PROFILE=no
_LIBS=lib${LIB}.a
.if exists(${.CURDIR}/shlib_version)
SHLIB_AGE != . ${.CURDIR}/shlib_version ; echo $$age
.endif
.else
# for the normal .a we do not want to strip symbols
.c.o:
${COMPILE.c} ${.IMPSRC}
# for the normal .a we do not want to strip symbols
${CXX_SUFFIXES:%=%.o}:
${COMPILE.cc} ${.IMPSRC}
.S.o .s.o:
${COMPILE.S} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC}
.if (${LD_X} == "")
.c.po:
${COMPILE.c} ${CC_PG} ${PROFFLAGS} ${.IMPSRC} -o ${.TARGET}
${CXX_SUFFIXES:%=%.po}:
${COMPILE.cc} -pg ${.IMPSRC} -o ${.TARGET}
.S${PICO} .s${PICO}:
${COMPILE.S} ${PICFLAG} ${CC_PIC} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}
.else
.c.po:
${COMPILE.c} ${CC_PG} ${PROFFLAGS} ${.IMPSRC} -o ${.TARGET}.o
@${LD} ${LD_X} ${LD_r} ${.TARGET}.o -o ${.TARGET}
@rm -f ${.TARGET}.o
${CXX_SUFFIXES:%=%.po}:
${COMPILE.cc} ${CXX_PG} ${.IMPSRC} -o ${.TARGET}.o
${LD} ${LD_X} ${LD_r} ${.TARGET}.o -o ${.TARGET}
@rm -f ${.TARGET}.o
.S${PICO} .s${PICO}:
${COMPILE.S} ${PICFLAG} ${CC_PIC} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}.o
${LD} ${LD_x} ${LD_r} ${.TARGET}.o -o ${.TARGET}
@rm -f ${.TARGET}.o
.endif
.if (${LD_x} == "")
.c${PICO}:
${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}
${CXX_SUFFIXES:%=%${PICO}}:
${COMPILE.cc} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}
.S.po .s.po:
${COMPILE.S} ${PROFFLAGS} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}
.else
.c${PICO}:
${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}.o
${LD} ${LD_x} ${LD_r} ${.TARGET}.o -o ${.TARGET}
@rm -f ${.TARGET}.o
${CXX_SUFFIXES:%=%${PICO}}:
${COMPILE.cc} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}.o
${LD} ${LD_x} ${LD_r} ${.TARGET}.o -o ${.TARGET}
@rm -f ${.TARGET}.o
.S.po .s.po:
${COMPILE.S} ${PROFFLAGS} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}.o
${LD} ${LD_X} ${LD_r} ${.TARGET}.o -o ${.TARGET}
@rm -f ${.TARGET}.o
.endif
.endif
.c.ln:
${LINT} ${LINTFLAGS} ${CFLAGS:M-[IDU]*} -i ${.IMPSRC}
.if ${MK_LIBTOOL} != "yes"
.if !defined(PICFLAG)
PICFLAG=-fpic
.endif
_LIBS=
.if ${MK_ARCHIVE} != "no"
_LIBS += lib${LIB}.a
.endif
.if ${MK_PROFILE} != "no"
_LIBS+=lib${LIB}_p.a
POBJS+=${OBJS:.o=.po}
.endif
.if ${MK_PIC} != "no"
.if ${MK_PICLIB} == "no"
SOLIB ?= lib${LIB}.a
.else
SOLIB=lib${LIB}_pic.a
_LIBS+=${SOLIB}
.endif
.if !empty(SHLIB_FULLVERSION)
_LIBS+=lib${LIB}.${LD_so}
.endif
.endif
.if ${MK_LINT} != "no"
_LIBS+=llib-l${LIB}.ln
.endif
# here is where you can define what LIB* are
.-include <libnames.mk>
.if ${MK_DPADD_MK} == "yes"
# lots of cool magic, but might not suit everyone.
.include <dpadd.mk>
.endif
.if empty(LIB)
_LIBS=
.elif ${MK_LDORDER_MK} != "no"
# Record any libs that we need to be linked with
_LIBS+= ${libLDORDER_INC}
.include <ldorder.mk>
.endif
.if !defined(_SKIP_BUILD)
realbuild: ${_LIBS}
.endif
all: _SUBDIRUSE
.for s in ${SRCS:N*.h:M*/*}
${.o ${PICO} .po .lo:L:@o@${s:T:R}$o@}: $s
.endfor
OBJS+= ${SRCS:T:N*.h:R:S/$/.o/g}
.NOPATH: ${OBJS}
.if ${MK_LIBTOOL} == "yes"
.if ${MK_PIC} == "no"
LT_STATIC=-static
.else
LT_STATIC=
.endif
SHLIB_AGE?=0
# .lo's are created as a side effect
.s.o .S.o .c.o:
${LIBTOOL} --mode=compile ${CC} ${LT_STATIC} ${CFLAGS} ${CPPFLAGS} ${IMPFLAGS} -c ${.IMPSRC}
# can't really do profiled libs with libtool - its too fascist about
# naming the output...
lib${LIB}.a: ${OBJS}
@rm -f ${.TARGET}
${LIBTOOL} --mode=link ${CC} ${LT_STATIC} -o ${.TARGET:.a=.la} ${OBJS:.o=.lo} -rpath ${SHLIBDIR}:/usr/lib -version-info ${SHLIB_MAJOR}:${SHLIB_MINOR}:${SHLIB_AGE}
@ln .libs/${.TARGET} .
lib${LIB}.${LD_so}: lib${LIB}.a
@[ -s ${.TARGET}.${SHLIB_AGE} ] || { ln -s .libs/lib${LIB}.${LD_so}* . 2>/dev/null; : }
@[ -s ${.TARGET} ] || ln -s ${.TARGET}.${SHLIB_AGE} ${.TARGET}
.else # MK_LIBTOOL=yes
lib${LIB}.a: ${OBJS}
@${META_NOECHO} building standard ${LIB} library
@rm -f ${.TARGET}
@${AR} ${AR_cq} ${.TARGET} ${LD_objs}
${RANLIB} ${.TARGET}
POBJS+= ${OBJS:.o=.po}
.NOPATH: ${POBJS}
lib${LIB}_p.a: ${POBJS}
@${META_NOECHO} building profiled ${LIB} library
@rm -f ${.TARGET}
@${AR} ${AR_cq} ${.TARGET} ${LD_pobjs}
${RANLIB} ${.TARGET}
SOBJS+= ${OBJS:.o=${PICO}}
.NOPATH: ${SOBJS}
lib${LIB}_pic.a: ${SOBJS}
@${META_NOECHO} building shared object ${LIB} library
@rm -f ${.TARGET}
@${AR} ${AR_cq} ${.TARGET} ${LD_sobjs}
${RANLIB} ${.TARGET}
#SHLIB_LDADD?= ${LDADD}
# bound to be non-portable...
# this is known to work for NetBSD 1.6 and FreeBSD 4.2
lib${LIB}.${LD_so}: ${SOLIB} ${DPADD}
@${META_NOECHO} building shared ${LIB} library \(version ${SHLIB_FULLVERSION}\)
@rm -f ${.TARGET}
.if ${TARGET_OSNAME} == "NetBSD" || ${TARGET_OSNAME} == "FreeBSD"
.if ${OBJECT_FMT} == "ELF"
${SHLIB_LD} -x -shared ${SHLIB_SHFLAGS} -o ${.TARGET} \
${SHLIB_LDSTARTFILE} \
--whole-archive ${SOLIB} --no-whole-archive ${SHLIB_LDADD} \
${SHLIB_LDENDFILE}
.else
${SHLIB_LD} ${LD_x} ${LD_shared} \
-o ${.TARGET} ${SOLIB} ${SHLIB_LDADD}
.endif
.else
${SHLIB_LD} -o ${.TARGET} ${LD_shared} ${LD_solib} ${DLLIB} ${SHLIB_LDADD}
.endif
.endif
.if !empty(SHLIB_LINKS)
rm -f ${SHLIB_LINKS}; ${SHLIB_LINKS:O:u:@x@ln -s ${.TARGET} $x;@}
.endif
LOBJS+= ${LSRCS:.c=.ln} ${SRCS:M*.c:.c=.ln}
.NOPATH: ${LOBJS}
LLIBS?= -lc
llib-l${LIB}.ln: ${LOBJS}
@${META_NOECHO} building llib-l${LIB}.ln
@rm -f llib-l${LIB}.ln
@${LINT} -C${LIB} ${LOBJS} ${LLIBS}
.if !target(clean)
cleanlib: .PHONY
rm -f a.out [Ee]rrs mklog core *.core ${CLEANFILES}
rm -f lib${LIB}.a ${OBJS}
rm -f lib${LIB}_p.a ${POBJS}
rm -f lib${LIB}_pic.a lib${LIB}.so.*.* ${SOBJS}
rm -f llib-l${LIB}.ln ${LOBJS}
.if !empty(SHLIB_LINKS)
rm -f ${SHLIB_LINKS}
.endif
clean: _SUBDIRUSE cleanlib
cleandir: _SUBDIRUSE cleanlib
.else
cleandir: _SUBDIRUSE clean
.endif
.if defined(SRCS) && (!defined(MKDEP) || ${MKDEP} != autodep)
afterdepend: .depend
@(TMP=/tmp/_depend$$$$; \
sed -e 's/^\([^\.]*\).o[ ]*:/\1.o \1.po \1${PICO} \1.ln:/' \
< .depend > $$TMP; \
mv $$TMP .depend)
.endif
.if !target(install)
.if !target(beforeinstall)
beforeinstall:
.endif
.if !empty(LIBOWN)
LIB_INSTALL_OWN ?= -o ${LIBOWN} -g ${LIBGRP}
.endif
.include <links.mk>
.if !target(libinstall) && !empty(LIB)
realinstall: libinstall
libinstall:
[ -d ${DESTDIR}/${LIBDIR} ] || \
${INSTALL} -d ${LIB_INSTALL_OWN} -m 775 ${DESTDIR}${LIBDIR}
.if ${MK_ARCHIVE} != "no"
${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 644 lib${LIB}.a \
${DESTDIR}${LIBDIR}
${RANLIB} ${DESTDIR}${LIBDIR}/lib${LIB}.a
chmod ${LIBMODE} ${DESTDIR}${LIBDIR}/lib${LIB}.a
.endif
.if ${MK_PROFILE} != "no"
${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 644 \
lib${LIB}_p.a ${DESTDIR}${LIBDIR}
${RANLIB} ${DESTDIR}${LIBDIR}/lib${LIB}_p.a
chmod ${LIBMODE} ${DESTDIR}${LIBDIR}/lib${LIB}_p.a
.endif
.if ${MK_LDORDER_MK} != "no"
${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 644 \
lib${LIB}.ldorder.inc ${DESTDIR}${LIBDIR}
.endif
.if ${MK_PIC} != "no"
.if ${MK_PICLIB} != "no"
${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 644 \
lib${LIB}_pic.a ${DESTDIR}${LIBDIR}
${RANLIB} ${DESTDIR}${LIBDIR}/lib${LIB}_pic.a
chmod ${LIBMODE} ${DESTDIR}${LIBDIR}/lib${LIB}_pic.a
.endif
.if !empty(SHLIB_MAJOR)
${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m ${LIBMODE} \
lib${LIB}.${LD_so} ${DESTDIR}${LIBDIR}
.if !empty(SHLIB_LINKS)
(cd ${DESTDIR}${LIBDIR} && { rm -f ${SHLIB_LINKS}; ${SHLIB_LINKS:O:u:@x@ln -s lib${LIB}.${LD_so} $x;@} })
.endif
.endif
.endif
.if ${MK_LINT} != "no" && ${MK_LINKLIB} != "no" && !empty(LOBJS)
${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m ${LIBMODE} \
llib-l${LIB}.ln ${DESTDIR}${LINTLIBDIR}
.endif
.if defined(LINKS) && !empty(LINKS)
@set ${LINKS}; ${_LINKS_SCRIPT}
.endif
.endif
.if ${MK_MAN} != "no"
install: maninstall _SUBDIRUSE
maninstall: afterinstall
.endif
afterinstall: realinstall
libinstall: beforeinstall
realinstall: beforeinstall
.endif
.if defined(FILES) || defined(FILESGROUPS)
.include <files.mk>
.endif
.if ${MK_MAN} != "no"
.include <man.mk>
.endif
.if ${MK_NLS} != "no"
.include <nls.mk>
.endif
.include <obj.mk>
.include <inc.mk>
.include <dep.mk>
.include <subdir.mk>
.endif
# during building we usually need/want to install libs somewhere central
# note that we do NOT ch{own,grp} as that would likely fail at this point.
# otherwise it is the same as realinstall
# Note that we don't need this when using dpadd.mk
.libinstall: ${_LIBS}
test -d ${DESTDIR}${LIBDIR} || ${INSTALL} -d -m775 ${DESTDIR}${LIBDIR}
.for _lib in ${_LIBS:M*.a}
${INSTALL} ${COPY} -m 644 ${_lib} ${DESTDIR}${LIBDIR}
${RANLIB} ${DESTDIR}${LIBDIR}/${_lib}
.endfor
.for _lib in ${_LIBS:M*.${LD_solink}*:O:u}
${INSTALL} ${COPY} -m ${LIBMODE} ${_lib} ${DESTDIR}${LIBDIR}
.if !empty(SHLIB_LINKS)
(cd ${DESTDIR}${LIBDIR} && { ${SHLIB_LINKS:O:u:@x@ln -sf ${_lib} $x;@}; })
.endif
.endfor
@touch ${.TARGET}
.if !empty(LIB)
STAGE_LIBDIR?= ${STAGE_OBJTOP}${LIBDIR}
stage_libs: ${_LIBS}
.endif
.include <final.mk>
.endif

View File

@ -0,0 +1,22 @@
# $Id: libnames.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2007-2009, 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
#
DLIBEXT ?= .a
DSHLIBEXT ?= .so
.-include <local.libnames.mk>
.-include <sjg.libnames.mk>
.-include <fwall.libnames.mk>
.-include <host.libnames.mk>

View File

@ -0,0 +1,93 @@
# $Id: libs.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2006, 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
#
.MAIN: all
.if defined(LIBS)
# In meta mode, we can capture dependenices for _one_ of the progs.
# if makefile doesn't nominate one, we use the first.
.ifndef UPDATE_DEPENDFILE_LIB
UPDATE_DEPENDFILE_LIB = ${LIBS:[1]}
.export UPDATE_DEPENDFILE_LIB
.endif
.ifndef LIB
# They may have asked us to build just one
.for t in ${LIBS:R:T:S,^lib,,}
.if make(lib$t)
LIB?= $t
lib$t: all
.endif
.endfor
.endif
.if defined(LIB)
# just one of many
LIB_VARS += \
LIBDIR \
CFLAGS \
COPTS \
CPPFLAGS \
CXXFLAGS \
DPADD \
DPLIBS \
LDADD \
LDFLAGS \
MAN \
SRCS
.for v in ${LIB_VARS:O:u}
.if defined(${v}.${LIB}) || defined(${v}_${LIB})
$v += ${${v}_${LIB}:U${${v}.${LIB}}}
.endif
.endfor
# for meta mode, there can be only one!
.if ${LIB} == ${UPDATE_DEPENDFILE_LIB:Uno}
UPDATE_DEPENDFILE ?= yes
.endif
UPDATE_DEPENDFILE ?= NO
# ensure that we don't clobber each other's dependencies
DEPENDFILE?= .depend.${LIB}
# lib.mk will do the rest
.else
all: ${LIBS:S,^lib,,:@t@lib$t.a@} .MAKE
# We cannot capture dependencies for meta mode here
UPDATE_DEPENDFILE = NO
# nor can we safely run in parallel.
.NOTPARALLEL:
.endif
.endif
# handle being called [bsd.]libs.mk
.include <${.PARSEFILE:S,libs,lib,}>
.ifndef LIB
# tell libs.mk we might want to install things
LIBS_TARGETS+= cleandepend cleandir cleanobj depend install
.for b in ${LIBS:R:T:S,^lib,,}
lib$b.a: ${SRCS} ${DPADD} ${SRCS_lib$b} ${DPADD_lib$b}
(cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} LIB=$b)
.for t in ${LIBS_TARGETS:O:u}
$b.$t: .PHONY .MAKE
(cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} LIB=$b ${@:E})
.endfor
.endfor
.endif

View File

@ -0,0 +1,80 @@
# $Id: links.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2005, 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
#
# some platforms need something special
LN?= ln
ECHO?= echo
LINKS?=
SYMLINKS?=
__SYMLINK_SCRIPT= \
${ECHO} "$$t -> $$l"; \
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"; \
mkdir -p `dirname $$t`; \
rm -f $$t; \
${LN} $$l $$t
_SYMLINKS_SCRIPT= \
while test $$\# -ge 2; do \
l=$$1; shift; \
t=${DESTDIR}$$1; shift; \
${__SYMLINK_SCRIPT}; \
done; :;
_LINKS_SCRIPT= \
while test $$\# -ge 2; do \
l=${DESTDIR}$$1; shift; \
t=${DESTDIR}$$1; shift; \
${__LINK_SCRIPT}; \
done; :;
_SYMLINKS_USE: .USE
@set ${$@_SYMLINKS:U${SYMLINKS}}; ${_SYMLINKS_SCRIPT}
_LINKS_USE: .USE
@set ${$@_LINKS:U${LINKS}}; ${_LINKS_SCRIPT}
# sometimes we want to ensure DESTDIR is ignored
_BUILD_SYMLINKS_SCRIPT= \
while test $$\# -ge 2; do \
l=$$1; shift; \
t=$$1; shift; \
${__SYMLINK_SCRIPT}; \
done; :;
_BUILD_LINKS_SCRIPT= \
while test $$\# -ge 2; do \
l=$$1; shift; \
t=$$1; shift; \
${__LINK_SCRIPT}; \
done; :;
_BUILD_SYMLINKS_USE: .USE
@set ${$@_SYMLINKS:U${SYMLINKS}}; ${_BUILD_SYMLINKS_SCRIPT}
_BUILD_LINKS_USE: .USE
@set ${$@_LINKS:U${LINKS}}; ${_BUILD_LINKS_SCRIPT}

137
devel/bmake/files/mk/man.mk Normal file
View File

@ -0,0 +1,137 @@
# $Id: man.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
.include <init.mk>
# unlike bsd.man.mk we handle 3 approaches
# 1. install unformated nroff (default)
# 2. install formatted pages
# 3. install formatted pages but with extension of .0
# sadly we cannot rely on a shell that supports ${foo#...} and ${foo%...}
# so we have to use sed(1).
# set MANTARGET=cat for formatted pages
MANTARGET?= man
# set this to .0 for same behavior as bsd.man.mk
MCATEXT?=
NROFF?= nroff
MANDIR?= /usr/share/man
MANDOC?= man
.SUFFIXES: .1 .2 .3 .4 .5 .6 .7 .8 .9 .cat1 .cat2 .cat3 .cat4 .cat5 .cat6 \
.cat7 .cat8 .cat9
.9.cat9 .8.cat8 .7.cat7 .6.cat6 .5.cat5 .4.cat4 .3.cat3 .2.cat2 .1.cat1:
@echo "${NROFF} -${MANDOC} ${.IMPSRC} > ${.TARGET:T}"
@${NROFF} -${MANDOC} ${.IMPSRC} > ${.TARGET:T} || ( rm -f ${.TARGET:T} ; false )
.if defined(MAN) && !empty(MAN)
# we use cmt2doc.pl to extract manpages from source
# this is triggered by the setting of EXTRACT_MAN or MAN being set but
# not existsing.
.if !exists(${MAN:[1]}) && !target(${MAN:[1]})
.if defined(EXTRACT_MAN) && ${EXTRACT_MAN} == "no"
MAN=
.else
.if exists(/usr/local/share/bin/cmt2doc.pl)
CMT2DOC?= cmt2doc.pl
CMT2DOC_OPTS?= ${CMT2DOC_ORGOPT} -pmS${.TARGET:E}
.endif
.ifdef CMT2DOC
.c.8 .c.5 .c.3 .c.4 .c.1 \
.cc.8 .cc.5 .cc.3 .cc.4 .cc.1 \
.h.8 .h.5 .h.3 .h.4 .h.1 \
.sh.8 .sh.5 .sh.3 .sh.4 .sh.1 \
.pl.8 .pl.5 .pl.3 .pl.4 .pl.1:
@echo "${CMT2DOC} ${.IMPSRC} > ${.TARGET:T}"
@${CMT2DOC} ${CMT2DOC_OPTS} ${.IMPSRC} > ${.TARGET:T} || ( rm -f ${.TARGET:T} ; false )
.else
MAN=
.endif
.endif
.endif
_mandir=${DESTDIR}${MANDIR}/${MANTARGET}`echo $$page | sed -e 's/.*\.cat/./' -e 's/.*\.//'`
.if ${MANTARGET} == "cat"
_mfromdir?=.
MANALL= ${MAN:S/.1$/.cat1/g:S/.2$/.cat2/g:S/.3$/.cat3/g:S/.4$/.cat4/g:S/.5$/.cat5/g:S/.6$/.cat6/g:S/.7$/.cat7/g:S/.8$/.cat8/g:S/.9$/.cat9/g}
.if ${MCATEXT} == ""
_minstpage=`echo $$page | sed 's/\.cat/./'`
.else
_minstpage=`echo $$page | sed 's/\.cat.*//'`${MCATEXT}
.endif
.endif
.if target(${MAN:[1]})
_mfromdir?=.
.endif
_mfromdir?=${.CURDIR}
MANALL?= ${MAN}
_minstpage?=$${page}
.endif
.if !empty(MANOWN)
MAN_INSTALL_OWN ?= -o ${MANOWN} -g ${MANGRP}
MAN_CHOWN ?= chown
.else
MAN_CHOWN = :
.endif
MINSTALL= ${INSTALL} ${COPY} ${MAN_INSTALL_OWN} -m ${MANMODE}
.if defined(MANZ)
# chown and chmod are done afterward automatically
MCOMPRESS= gzip -cf
MCOMPRESSSUFFIX= .gz
.endif
maninstall:
.if defined(MANALL) && !empty(MANALL)
@for page in ${MANALL:T}; do \
test -s ${_mfromdir}/$$page || continue; \
dir=${_mandir}; \
test -d $$dir || ${INSTALL} -d ${MAN_INSTALL_OWN} -m 775 $$dir; \
instpage=$${dir}${MANSUBDIR}/${_minstpage}${MCOMPRESSSUFFIX}; \
if [ X"${MCOMPRESS}" = X ]; then \
echo ${MINSTALL} ${_mfromdir}/$$page $$instpage; \
${MINSTALL} ${_mfromdir}/$$page $$instpage; \
else \
rm -f $$instpage; \
echo ${MCOMPRESS} ${_mfromdir}/$$page \> $$instpage; \
${MCOMPRESS} ${_mfromdir}/$$page > $$instpage; \
${MAN_CHOWN} ${MANOWN}:${MANGRP} $$instpage; \
chmod ${MANMODE} $$instpage; \
fi \
done
.if defined(MLINKS) && !empty(MLINKS)
@set ${MLINKS}; \
while test $$# -ge 2; do \
page=$$1; \
shift; \
dir=${_mandir}; \
l=${_minstpage}${MCOMPRESSSUFFIX}; \
page=$$1; \
shift; \
dir=${_mandir}; \
t=$${dir}${MANSUBDIR}/${_minstpage}${MCOMPRESSSUFFIX}; \
echo $$t -\> $$l; \
rm -f $$t; \
ln -s $$l $$t; \
done
.endif
.endif
.if defined(MANALL) && !empty(MANALL)
manall: ${MANALL}
all: manall
.endif
.if defined(CLEANMAN) && !empty(CLEANMAN)
cleandir: cleanman
cleanman:
rm -f ${CLEANMAN}
.endif
.endif

View File

@ -0,0 +1,66 @@
# $Id: manifest.mk,v 1.1.1.1 2020/05/24 05:35:53 nia 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}

View File

@ -0,0 +1,320 @@
# $Id: meta.autodep.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2010, 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 ?= ${.PARSEFILE}
.if !target(__${_this}__)
__${_this}__: .NOTMAIN
.-include <local.autodep.mk>
PICO?= .pico
.if defined(SRCS)
# it would be nice to be able to query .SUFFIXES
OBJ_EXTENSIONS+= .o .po .lo ${PICO}
# explicit dependencies help short-circuit .SUFFIX searches
SRCS_DEP_FILTER+= N*.[hly]
.for s in ${SRCS:${SRCS_DEP_FILTER:O:u:ts:}}
.for e in ${OBJ_EXTENSIONS:O:u}
.if !target(${s:T:R}$e)
${s:T:R}$e: $s
.endif
.endfor
.endfor
.endif
.if make(gendirdeps)
# you are supposed to know what you are doing!
UPDATE_DEPENDFILE = yes
.elif !empty(.TARGETS) && !make(all)
# do not update the *depend* files
# unless we are building the entire directory or the default target.
# NO means don't update .depend - or Makefile.depend*
# no means update .depend but not Makefile.depend*
UPDATE_DEPENDFILE = NO
.elif ${.MAKEFLAGS:M-k} != ""
# it is a bad idea to update anything
UPDATE_DEPENDFILE = NO
.endif
_CURDIR ?= ${.CURDIR}
_OBJDIR ?= ${.OBJDIR}
_OBJTOP ?= ${OBJTOP}
_OBJROOT ?= ${OBJROOT:U${_OBJTOP}}
_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T}
.if ${.MAKE.LEVEL} > 0 || ${BUILD_AT_LEVEL0:Uyes:tl} == "yes"
# do not allow auto update if we ever built this dir without filemon
NO_FILEMON_COOKIE = .nofilemon
CLEANFILES += ${NO_FILEMON_COOKIE}
.if ${.MAKE.MODE:Uno:Mnofilemon} != ""
UPDATE_DEPENDFILE = NO
all: ${NO_FILEMON_COOKIE}
${NO_FILEMON_COOKIE}: .NOMETA
@echo UPDATE_DEPENDFILE=NO > ${.TARGET}
.elif exists(${NO_FILEMON_COOKIE})
UPDATE_DEPENDFILE = NO
.warning ${RELDIR} built with nofilemon; UPDATE_DEPENDFILE=NO
.endif
.endif
.if ${.MAKE.LEVEL} == 0
.if ${BUILD_AT_LEVEL0:Uyes:tl} == "no"
UPDATE_DEPENDFILE = NO
.endif
.endif
.if !exists(${_DEPENDFILE})
_bootstrap_dirdeps = yes
.endif
_bootstrap_dirdeps ?= no
UPDATE_DEPENDFILE ?= yes
.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
.info ${_DEPENDFILE:S,${SRCTOP}/,,} update=${UPDATE_DEPENDFILE}
.endif
.if !empty(XMAKE_META_FILE)
.if exists(${.OBJDIR}/${XMAKE_META_FILE})
# we cannot get accurate dependencies from an update build
UPDATE_DEPENDFILE = NO
.else
META_XTRAS += ${XMAKE_META_FILE}
.endif
.endif
.if ${_bootstrap_dirdeps} == "yes" || exists(${_DEPENDFILE})
# if it isn't supposed to be touched by us the Makefile should have
# UPDATE_DEPENDFILE = no
WANT_UPDATE_DEPENDFILE ?= yes
.endif
.if ${WANT_UPDATE_DEPENDFILE:Uno:tl} != "no"
.if ${.MAKE.MODE:Uno:Mmeta*} == "" || ${.MAKE.MODE:Uno:M*read*} != ""
UPDATE_DEPENDFILE = no
.endif
.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
.info ${_DEPENDFILE:S,${SRCTOP}/,,} update=${UPDATE_DEPENDFILE}
.endif
.if ${UPDATE_DEPENDFILE:tl} == "yes"
# sometimes we want .meta files generated to aid debugging/error detection
# but do not want to consider them for dependencies
# for example the result of running configure
# just make sure this is not empty
META_FILE_FILTER ?= N.meta
# never consider these
META_FILE_FILTER += Ndirdeps.cache*
.if !empty(DPADD)
# if we have any non-libs in DPADD,
# they probably need to be paid attention to
.if !empty(DPLIBS)
FORCE_DPADD = ${DPADD:${DPLIBS:${M_ListToSkip}}:${DPADD_LAST:${M_ListToSkip}}}
.else
_nonlibs := ${DPADD:T:Nlib*:N*include}
.if !empty(_nonlibs)
FORCE_DPADD += ${_nonlibs:@x@${DPADD:M*/$x}@}
.endif
.endif
.endif
.if !make(gendirdeps)
.END: gendirdeps
.endif
# if we don't have OBJS, then .depend isn't useful
.if !target(.depend) && (!empty(OBJS) || ${.ALLTARGETS:M*.o} != "")
# some makefiles and/or targets contain
# circular dependencies if you dig too deep
# (as meta mode is apt to do)
# so we provide a means of suppressing them.
# the input to the loop below is target: dependency
# with just one dependency per line.
# Also some targets are not really local, or use random names.
# Use local.autodep.mk to provide local additions!
SUPPRESS_DEPEND += \
${SB:S,/,_,g}* \
*:y.tab.c \
*.c:*.c \
*.h:*.h
.NOPATH: .depend
# we use ${.MAKE.META.CREATED} to trigger an update but
# we process using ${.MAKE.META.FILES}
# the double $$ defers initial evaluation
# if necessary, we fake .po dependencies, just so the result
# in Makefile.depend* is stable
# The current objdir may be referred to in various ways
OBJDIR_REFS += ${.OBJDIR} ${.OBJDIR:tA} ${_OBJDIR} ${RELOBJTOP}/${RELDIR}
_depend = .depend
# it would be nice to be able to get .SUFFIXES as ${.SUFFIXES}
# we actually only care about the .SUFFIXES of files that might be
# generated by tools like yacc.
DEPEND_SUFFIXES += .c .h .cpp .hpp .cxx .hxx .cc .hh
.depend: .NOMETA $${.MAKE.META.CREATED} ${_this}
@echo "Updating $@: ${.OODATE:T:[1..8]}"
@egrep -i '^R .*\.(${DEPEND_SUFFIXES:tl:O:u:S,^.,,:ts|})$$' /dev/null ${.MAKE.META.FILES:T:O:u:${META_FILE_FILTER:ts:}:M*o.meta} | \
sed -e 's, \./, ,${OBJDIR_REFS:O:u:@d@;s, $d/, ,@};/\//d' \
-e 's,^\([^/][^/]*\).meta...[0-9]* ,\1: ,' | \
sort -u | \
while read t d; do \
case "$$d:" in $$t) continue;; esac; \
case "$$t$$d" in ${SUPPRESS_DEPEND:U.:O:u:ts|}) continue;; esac; \
echo $$t $$d; \
done > $@.${.MAKE.PID}
@case "${.MAKE.META.FILES:T:M*.po.*}" in \
*.po.*) mv $@.${.MAKE.PID} $@;; \
*) { cat $@.${.MAKE.PID}; \
sed 's,\${PICO}:,.o:,;s,\.o:,.po:,' $@.${.MAKE.PID}; } | sort -u > $@; \
rm -f $@.${.MAKE.PID};; \
esac
.else
# make sure this exists
.depend:
# do _not_ assume that .depend is in any fit state for us to use
CAT_DEPEND = /dev/null
.if ${.MAKE.LEVEL} > 0
.export CAT_DEPEND
.endif
_depend =
.endif
.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
.info ${_DEPENDFILE:S,${SRCTOP}/,,} _depend=${_depend}
.endif
.if ${UPDATE_DEPENDFILE} == "yes"
gendirdeps: ${_DEPENDFILE}
.endif
.if !target(${_DEPENDFILE})
.if ${_bootstrap_dirdeps} == "yes"
# We are boot-strapping a new directory
# Use DPADD to seed DIRDEPS
.if !empty(DPADD)
# anything which matches ${_OBJROOT}* but not ${_OBJTOP}*
# needs to be qualified in DIRDEPS
# The pseudo machine "host" is used for HOST_TARGET
DIRDEPS += \
${DPADD:M${_OBJTOP}*:H:C,${_OBJTOP}[^/]*/,,:N.:O:u} \
${DPADD:M${_OBJROOT}*:N${_OBJTOP}*:N${STAGE_ROOT:U${_OBJTOP}}/*:H:S,${_OBJROOT},,:C,^([^/]+)/(.*),\2.\1,:S,${HOST_TARGET}$,host,:N.*:O:u}
.endif
.endif
_gendirdeps_mutex =
.if defined(NEED_GENDIRDEPS_MUTEX)
# If a src dir gets built with multiple object dirs,
# we need a mutex. Obviously, this is best avoided.
# Note if .MAKE.DEPENDFILE is common for all ${MACHINE}
# you either need to mutex, or ensure only one machine builds at a time!
# lockf is an example of a suitable tool
LOCKF ?= /usr/bin/lockf
.if exists(${LOCKF})
GENDIRDEPS_MUTEXER ?= ${LOCKF} -k
.endif
.if empty(GENDIRDEPS_MUTEXER)
.error NEED_GENDIRDEPS_MUTEX defined, but GENDIRDEPS_MUTEXER not set
.else
_gendirdeps_mutex = ${GENDIRDEPS_MUTEXER} ${GENDIRDEPS_MUTEX:U${_CURDIR}/Makefile}
.endif
.endif
# If we have META_XTRAS we most likely did not create them
# but we need to behave as if we did.
# Avoid adding glob patterns to .MAKE.META.CREATED though.
.MAKE.META.CREATED += ${META_XTRAS:N*\**:O:u}
.if make(gendirdeps)
META_FILES = *.meta
.elif ${OPTIMIZE_OBJECT_META_FILES:Uno:tl} == "no"
META_FILES = ${.MAKE.META.FILES:T:N.depend*:O:u}
.else
# if we have 1000's of .o.meta, ${PICO}.meta etc we need only look at one set
# it is left as an exercise for the reader to work out what this does
META_FILES = ${.MAKE.META.FILES:T:N.depend*:N*o.meta:O:u} \
${.MAKE.META.FILES:T:M*.${.MAKE.META.FILES:M*o.meta:R:E:O:u:[1]}.meta:O:u}
.endif
.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
.info ${_DEPENDFILE:S,${SRCTOP}/,,}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} xtras=${META_XTRAS}
.endif
.if ${.MAKE.LEVEL} > 0
.if ${UPDATE_DEPENDFILE} == "yes"
.-include <${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.options>
.endif
.if !empty(GENDIRDEPS_FILTER)
.export GENDIRDEPS_FILTER
.endif
# export to avoid blowing command line limit
META_FILES := ${META_XTRAS:U:O:u} ${META_FILES:U:T:O:u:${META_FILE_FILTER:ts:}}
.export META_FILES
.endif
# we might have .../ in MAKESYSPATH
_makesyspath:= ${_PARSEDIR}
${_DEPENDFILE}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.META.CREATED}
@echo Checking $@: ${.OODATE:T:[1..8]}
@(cd . && ${GENDIRDEPS_ENV} \
SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS:O:u}' \
DPADD='${FORCE_DPADD:O:u}' ${_gendirdeps_mutex} \
MAKESYSPATH=${_makesyspath} \
${.MAKE} -f gendirdeps.mk RELDIR=${RELDIR} _DEPENDFILE=${_DEPENDFILE})
@test -s $@ && touch $@; :
.endif
.endif
.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 <dirdeps.mk>
.else
${_DEPENDFILE}: .PRECIOUS
.endif
CLEANFILES += *.meta filemon.* *.db
# these make it easy to gather some stats
now_utc = ${%s:L:gmtime}
start_utc := ${now_utc}
meta_stats= meta=${empty(.MAKE.META.FILES):?0:${.MAKE.META.FILES:[#]}} \
created=${empty(.MAKE.META.CREATED):?0:${.MAKE.META.CREATED:[#]}}
#.END: _reldir_finish
.if target(gendirdeps)
_reldir_finish: gendirdeps
.endif
_reldir_finish: .NOMETA
@echo "${TIME_STAMP} Finished ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}"
#.ERROR: _reldir_failed
_reldir_failed: .NOMETA
@echo "${TIME_STAMP} Failed ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}"
.if defined(WITH_META_STATS) && ${.MAKE.LEVEL} > 0
.END: _reldir_finish
.ERROR: _reldir_failed
.endif
.endif

View File

@ -0,0 +1,366 @@
# $Id: meta.stage.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2011-2017, 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
#
.ifndef NO_STAGING
.if !target(__${.PARSEFILE}__)
# the guard target is defined later
.-include <local.meta.stage.mk>
.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} != ""
# this is generally safer anyway
_dirdep ?= ${RELDIR}.${TARGET_SPEC:U${MACHINE}}
.else
_dirdep ?= ${RELDIR}
.endif
CLEANFILES+= .dirdep
# this allows us to trace dependencies back to their src dir
.dirdep: .NOPATH
@echo '${_dirdep}' > $@
.if defined(NO_POSIX_SHELL) || ${type printf:L:sh:Mbuiltin} == ""
_stage_file_basename = `basename $$f`
_stage_target_dirname = `dirname $$t`
.else
_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
# add each dir we stage to to _STAGED_DIRS
# and make sure we have absolute paths so that bmake
# will match against .MAKE.META.BAILIWICK
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:M${_objroot}*:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,}
LN_CP_SCRIPT = LnCp() { \
rm -f $$2 2> /dev/null; \
{ [ -z "$$mode" ] && ${LN:Uln} $$1 $$2 2> /dev/null; } || \
cp -p $$1 $$2; }
# a staging conflict should cause an error
# a warning is handy when bootstapping different options.
STAGE_CONFLICT?= ERROR
.if ${STAGE_CONFLICT:tl} == "error"
STAGE_CONFLICT_ACTION= exit 1
.else
STAGE_CONFLICT_ACTION=
.endif
# it is an error for more than one src dir to try and stage
# the same file
STAGE_DIRDEP_SCRIPT = ${LN_CP_SCRIPT}; StageDirdep() { \
t=$$1; \
if [ -s $$t.dirdep ]; then \
cmp -s .dirdep $$t.dirdep && return; \
x=`cat $$t.dirdep`; \
case "${RELDIR}:${_dirdep}" in $${x%.*}:$${x}*) ;; \
*) echo "${STAGE_CONFLICT}: $$t installed by $$x not ${_dirdep}" >&2; \
${STAGE_CONFLICT_ACTION} ;; esac; \
fi; \
LnCp .dirdep $$t.dirdep || exit 1; }
# common logic for staging files
# this all relies on RELDIR being set to a subdir of SRCTOP
# we use ln(1) if we can, else cp(1)
STAGE_FILE_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageFiles() { \
case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \
dest=$$1; shift; \
mkdir -p $$dest; \
[ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
for f in "$$@"; do \
case "$$f" in */*) t=$$dest/${_stage_file_basename};; *) t=$$dest/$$f;; esac; \
StageDirdep $$t; \
LnCp $$f $$t || exit 1; \
[ -z "$$mode" ] || chmod $$mode $$t; \
done; :; }
STAGE_LINKS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageLinks() { \
case "$$1" in "") return;; --) shift;; -*) ldest= lnf=$$1; shift;; /*) ldest=$$1/;; esac; \
dest=$$1; shift; \
mkdir -p $$dest; \
[ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
while test $$\# -ge 2; do \
l=$$ldest$$1; shift; \
t=$$dest/$$1; \
case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \
shift; \
StageDirdep $$t; \
rm -f $$t 2>/dev/null; \
ln $$lnf $$l $$t || exit 1; \
done; :; }
STAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \
case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \
dest=$$1; shift; \
mkdir -p $$dest; \
[ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
while test $$\# -ge 2; do \
s=$$1; shift; \
t=$$dest/$$1; \
case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \
shift; \
StageDirdep $$t; \
LnCp $$s $$t || exit 1; \
[ -z "$$mode" ] || chmod $$mode $$t; \
done; :; }
# this is simple, a list of the "staged" files depends on this,
_STAGE_BASENAME_USE: .USE .dirdep ${.TARGET:T}
@${STAGE_FILE_SCRIPT}; StageFiles ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T}
_STAGE_AS_BASENAME_USE: .USE .dirdep ${.TARGET:T}
@${STAGE_AS_SCRIPT}; StageAs ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} ${STAGE_AS_${.TARGET:T}:U${.TARGET:T}}
.endif # first time
.if !empty(STAGE_INCSDIR)
.if !empty(STAGE_INCS)
stage_incs: ${STAGE_INCS:N*\**}
.endif
.if target(stage_incs) || !empty(.ALLTARGETS:Mstage_includes)
STAGE_TARGETS += stage_incs
STAGE_INCS ?= ${.ALLSRC:N.dirdep:Nstage_*}
stage_includes: stage_incs
stage_incs: .dirdep
@${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_INCSDIR:${STAGE_DIR_FILTER}} ${STAGE_INCS}
@touch $@
.endif
.endif
.if !empty(STAGE_LIBDIR)
.if !empty(STAGE_LIBS)
stage_libs: ${STAGE_LIBS:N*\**}
.endif
.if target(stage_libs)
STAGE_TARGETS += stage_libs
STAGE_LIBS ?= ${.ALLSRC:N.dirdep:Nstage_*}
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}
.endif
.endif
@touch $@
.endif
.endif
.if !empty(STAGE_DIR)
STAGE_SETS += _default
STAGE_DIR._default = ${STAGE_DIR}
STAGE_LINKS_DIR._default = ${STAGE_LINKS_DIR:U${STAGE_OBJTOP}}
STAGE_SYMLINKS_DIR._default = ${STAGE_SYMLINKS_DIR:U${STAGE_OBJTOP}}
STAGE_FILES._default = ${STAGE_FILES}
STAGE_LINKS._default = ${STAGE_LINKS}
STAGE_SYMLINKS._default = ${STAGE_SYMLINKS}
.endif
.if !empty(STAGE_SETS)
CLEANFILES += ${STAGE_SETS:@s@stage*$s@}
# some makefiles need to populate multiple directories
.for s in ${STAGE_SETS:O:u}
.if !empty(STAGE_FILES.$s)
stage_files.$s: ${STAGE_FILES.$s:N*\**}
.endif
.if target(stage_files.$s) || target(stage_files${s:S,^,.,:N._default})
STAGE_TARGETS += stage_files
STAGE_FILES.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
.if !target(.stage_files.$s)
.stage_files.$s:
.if $s != "_default"
stage_files: stage_files.$s
stage_files.$s: .dirdep
.else
STAGE_FILES ?= ${.ALLSRC:N.dirdep:Nstage_*}
stage_files: .dirdep
.endif
@${STAGE_FILE_SCRIPT}; StageFiles ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_FILES.$s:O}
@touch $@
.endif
.endif
.if !empty(STAGE_LINKS.$s)
stage_links.$s:
.endif
.if target(stage_links.$s) || target(stage_links${s:S,^,.,:N._default})
STAGE_LINKS_DIR.$s ?= ${STAGE_OBJTOP}
STAGE_TARGETS += stage_links
.if !target(.stage_links.$s)
.stage_links.$s:
.if $s != "_default"
stage_links: stage_links.$s
stage_links.$s: .dirdep
.else
stage_links: .dirdep
.endif
@${STAGE_LINKS_SCRIPT}; StageLinks ${STAGE_LINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_LINKS.$s}
@touch $@
.endif
.endif
.if !empty(STAGE_SYMLINKS.$s)
stage_symlinks.$s:
.endif
.if target(stage_symlinks.$s) || target(stage_symlinks${s:S,^,.,:N._default})
STAGE_SYMLINKS_DIR.$s ?= ${STAGE_OBJTOP}
STAGE_TARGETS += stage_symlinks
.if !target(.stage_symlinks.$s)
.stage_symlinks.$s:
.if $s != "_default"
stage_symlinks: stage_symlinks.$s
stage_symlinks.$s: .dirdep
.else
stage_symlinks: .dirdep
.endif
@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_SYMLINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_SYMLINKS.$s}
@touch $@
.endif
.endif
.endfor
.endif
.if !empty(STAGE_AS_SETS)
CLEANFILES += ${STAGE_AS_SETS:@s@stage*$s@}
# sometimes things need to be renamed as they are staged
# each ${file} will be staged as ${STAGE_AS_${file:T}}
# one could achieve the same with SYMLINKS
# stage_as_and_symlink makes the original name a symlink to the new name
# it is the same as using stage_as and stage_symlinks but ensures
# both operations happen together
.for s in ${STAGE_AS_SETS:O:u}
.if !empty(STAGE_AS.$s)
stage_as.$s: ${STAGE_AS.$s:N*\**}
.endif
.if target(stage_as.$s)
STAGE_TARGETS += stage_as
STAGE_AS.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
.if !target(.stage_as.$s)
.stage_as.$s:
stage_as: stage_as.$s
stage_as.$s: .dirdep
@${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS.$s:O:@f@$f ${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}}@}
@touch $@
.endif
.endif
.if !empty(STAGE_AS_AND_SYMLINK.$s)
stage_as_and_symlink.$s: ${STAGE_AS_AND_SYMLINK.$s:N*\**}
.endif
.if target(stage_as_and_symlink.$s)
STAGE_TARGETS += stage_as_and_symlink
STAGE_AS_AND_SYMLINK.$s ?= ${.ALLSRC:N.dirdep:Nstage_*}
.if !target(.stage_as_and_symlink.$s)
.stage_as_and_symlink.$s:
stage_as_and_symlink: stage_as_and_symlink.$s
stage_as_and_symlink.$s: .dirdep
@${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS_AND_SYMLINK.$s:O:@f@$f ${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}}@}
@${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS_AND_SYMLINK.$s:O:@f@${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}} $f@}
@touch $@
.endif
.endif
.endfor
.endif
CLEANFILES += ${STAGE_TARGETS} stage_incs stage_includes
# this lot also only makes sense the first time...
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
# stage_*links usually needs to follow any others.
# for non-jobs mode the order here matters
staging: ${STAGE_TARGETS:N*_links} ${STAGE_TARGETS:M*_links}
.if ${.MAKE.JOBS:U0} > 0 && ${STAGE_TARGETS:U:M*_links} != ""
# the above isn't sufficient
.for t in ${STAGE_TARGETS:N*links:O:u}
.ORDER: $t stage_links
.endfor
.endif
# generally we want staging to wait until everything else is done
STAGING_WAIT ?= .WAIT
.if ${.MAKE.LEVEL} > 0
all: ${STAGING_WAIT} staging
.endif
.if exists(${.PARSEDIR}/stage-install.sh) && !defined(STAGE_INSTALL)
# this will run install(1) and then followup with .dirdep files.
STAGE_INSTALL := sh ${.PARSEDIR:tA}/stage-install.sh INSTALL="${INSTALL}" OBJDIR=${.OBJDIR:tA}
.endif
# if ${INSTALL} gets run during 'all' assume it is for staging?
.if ${.TARGETS:Nall} == "" && defined(STAGE_INSTALL)
INSTALL := ${STAGE_INSTALL}
.if target(beforeinstall)
beforeinstall: .dirdep
.endif
.endif
.NOPATH: ${STAGE_FILES}
.if !empty(STAGE_TARGETS)
# for backwards compat make sure they exist
${STAGE_TARGETS}:
.NOPATH: ${CLEANFILES}
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
.endif

View File

@ -0,0 +1,79 @@
# $Id: meta.subdir.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2010, 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 !defined(NO_SUBDIR) && !empty(SUBDIR)
.if make(destroy*) || make(clean*)
.MAKE.MODE = compat
.if !commands(destroy)
.-include <bsd.obj.mk>
.endif
.elif ${.MAKE.LEVEL} == 0
.MAIN: all
.if !exists(${.CURDIR}/${.MAKE.DEPENDFILE:T}) || make(gendirdeps)
# start with this
DIRDEPS = ${SUBDIR:N.WAIT:O:u:@d@${RELDIR}/$d@}
.if make(gendirdeps)
.include <meta.autodep.mk>
.else
# this is the cunning bit
# actually it is probably a bit risky
# since we may pickup subdirs which are not relevant
# the alternative is a walk through the tree though
# which is difficult without a sub-make.
.if defined(BOOTSTRAP_DEPENDFILES)
_find_name = ${.MAKE.MAKEFILE_PREFERENCE:@m@-o -name $m@:S,^-o,,1}
DIRDEPS = ${_subdeps:H:O:u:@d@${RELDIR}/$d@}
.elif ${.MAKE.DEPENDFILE:E} == ${MACHINE} && defined(ALL_MACHINES)
# we want to find Makefile.depend.* ie for all machines
# and turn the dirs into dir.<machine>
_find_name = -name '${.MAKE.DEPENDFILE:T:R}*'
DIRDEPS = ${_subdeps:O:u:${NIgnoreFiles}:@d@${RELDIR}/${d:H}.${d:E}@:S,.${MACHINE}$,,:S,.depend$,,}
.else
# much simpler
_find_name = -name ${.MAKE.DEPENDFILE:T}
.if ${.MAKE.DEPENDFILE:E} == ${MACHINE}
_find_name += -o -name ${.MAKE.DEPENDFILE:T:R}
.endif
DIRDEPS = ${_subdeps:H:O:u:@d@${RELDIR}/$d@}
.endif
_subdeps != cd ${.CURDIR} && \
find ${SUBDIR:N.WAIT} -type f \( ${_find_name} \) -print -o \
-name .svn -prune 2> /dev/null; echo
.if empty(_subdeps)
DIRDEPS =
.else
# clean up if needed
DIRDEPS := ${DIRDEPS:S,^./,,:S,/./,/,g:${SUBDIRDEPS_FILTER:Uu}}
.endif
# we just dealt with it, if we leave it defined,
# dirdeps.mk will compute some interesting combinations.
.undef ALL_MACHINES
DEP_RELDIR = ${RELDIR}
.include <dirdeps.mk>
.endif
.endif
.else
all: .PHONY
.endif
.endif

View File

@ -0,0 +1,173 @@
# $Id: meta.sys.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2010-2020, 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
#
# include this if you want to enable meta mode
# for maximum benefit, requires filemon(4) driver.
.if ${MAKE_VERSION:U0} > 20100901
.if !target(.ERROR)
.-include <local.meta.sys.mk>
# absolute path to what we are reading.
_PARSEDIR = ${.PARSEDIR:tA}
.if !defined(SYS_MK_DIR)
SYS_MK_DIR := ${_PARSEDIR}
.endif
META_MODE += meta verbose
.MAKE.MODE ?= ${META_MODE}
.if ${.MAKE.LEVEL} == 0
_make_mode := ${.MAKE.MODE} ${META_MODE}
.if ${_make_mode:M*read*} != "" || ${_make_mode:M*nofilemon*} != ""
# tell everyone we are not updating Makefile.depend*
UPDATE_DEPENDFILE = NO
.export UPDATE_DEPENDFILE
.endif
.if ${UPDATE_DEPENDFILE:Uyes:tl} == "no" && !exists(/dev/filemon)
# we should not get upset
META_MODE += nofilemon
.export META_MODE
.endif
.endif
.if !defined(NO_SILENT)
.if ${MAKE_VERSION} > 20110818
# only be silent when we have a .meta file
META_MODE += silent=yes
.else
.SILENT:
.endif
.endif
# we use the pseudo machine "host" for the build host.
# this should be taken care of before we get here
.if ${OBJTOP:Ua} == ${HOST_OBJTOP:Ub}
MACHINE = host
.endif
.if !defined(MACHINE0)
# it can be handy to know which MACHINE kicked off the build
# for example, if using Makefild.depend for multiple machines,
# allowing only MACHINE0 to update can keep things simple.
MACHINE0 := ${MACHINE}
.export MACHINE0
.endif
.if !defined(META2DEPS)
.if defined(PYTHON) && exists(${PYTHON})
# we prefer the python version of this - it is much faster
META2DEPS ?= ${.PARSEDIR}/meta2deps.py
.else
META2DEPS ?= ${.PARSEDIR}/meta2deps.sh
.endif
META2DEPS := ${META2DEPS}
.export META2DEPS
.endif
MAKE_PRINT_VAR_ON_ERROR += \
.ERROR_TARGET \
.ERROR_META_FILE \
.MAKE.LEVEL \
MAKEFILE \
.MAKE.MODE
.if !defined(SB) && defined(SRCTOP)
SB = ${SRCTOP:H}
.endif
ERROR_LOGDIR ?= ${SB}/error
meta_error_log = ${ERROR_LOGDIR}/meta-${.MAKE.PID}.log
# we are not interested in make telling us a failure happened elsewhere
.ERROR: _metaError
_metaError: .NOMETA .NOTMAIN
-@[ "${.ERROR_META_FILE}" ] && { \
grep -q 'failure has been detected in another branch' ${.ERROR_META_FILE} && exit 0; \
mkdir -p ${meta_error_log:H}; \
cp ${.ERROR_META_FILE} ${meta_error_log}; \
echo "ERROR: log ${meta_error_log}" >&2; }; :
.endif
# Are we, after all, in meta mode?
.if ${.MAKE.MODE:Uno:Mmeta*} != ""
MKDEP_MK = meta.autodep.mk
.if ${.MAKE.MAKEFILES:M*sys.dependfile.mk} == ""
# this does all the smarts of setting .MAKE.DEPENDFILE
.-include <sys.dependfile.mk>
# check if we got anything sane
.if ${.MAKE.DEPENDFILE} == ".depend"
.undef .MAKE.DEPENDFILE
.endif
.MAKE.DEPENDFILE ?= Makefile.depend
.endif
# we can afford to use cookies to prevent some targets
# re-running needlessly
META_COOKIE_TOUCH?= touch ${COOKIE.${.TARGET}:U${.OBJDIR}/${.TARGET:T}}
META_NOPHONY=
META_NOECHO= :
# some targets involve old pre-built targets
# ignore mtime of shell
# and mtime of makefiles does not matter in meta mode
.MAKE.META.IGNORE_PATHS += \
${MAKEFILE} \
${MAKE_SHELL} \
${SHELL} \
${SYS_MK_DIR} \
.if ${UPDATE_DEPENDFILE:Uyes:tl} != "no"
.if ${.MAKEFLAGS:Uno:M-k} != ""
# make this more obvious
.warning Setting UPDATE_DEPENDFILE=NO due to -k
UPDATE_DEPENDFILE= NO
.export UPDATE_DEPENDFILE
.elif !exists(/dev/filemon)
.error ${.newline}ERROR: The filemon module (/dev/filemon) is not loaded.
.endif
.endif
.if ${.MAKE.LEVEL} == 0
# make sure dirdeps target exists and do it first
all: dirdeps .WAIT
dirdeps:
.NOPATH: dirdeps
.if defined(ALL_MACHINES)
# the first .MAIN: is what counts
# by default dirdeps is all we want at level0
.MAIN: dirdeps
# tell dirdeps.mk what we want
BUILD_AT_LEVEL0 = no
.endif
.if ${.TARGETS:Nall} == ""
# it works best if we do everything via sub-makes
BUILD_AT_LEVEL0 ?= no
.endif
.endif
.else
META_COOKIE_TOUCH=
# some targets need to be .PHONY in non-meta mode
META_NOPHONY= .PHONY
META_NOECHO= echo
.endif
.endif

755
devel/bmake/files/mk/meta2deps.py Executable file
View File

@ -0,0 +1,755 @@
#!/usr/bin/env python
from __future__ import print_function
"""
This script parses each "meta" file and extracts the
information needed to deduce build and src dependencies.
It works much the same as the original shell script, but is
*much* more efficient.
The parsing work is handled by the class MetaFile.
We only pay attention to a subset of the information in the
"meta" files. Specifically:
'CWD' to initialize our notion.
'C' to track chdir(2) on a per process basis
'R' files read are what we really care about.
directories read, provide a clue to resolving
subsequent relative paths. That is if we cannot find
them relative to 'cwd', we check relative to the last
dir read.
'W' files opened for write or read-write,
for filemon V3 and earlier.
'E' files executed.
'L' files linked
'V' the filemon version, this record is used as a clue
that we have reached the interesting bit.
"""
"""
RCSid:
$Id: meta2deps.py,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
Copyright (c) 2011-2019, Simon J. Gerraty
Copyright (c) 2011-2017, Juniper Networks, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import os, re, sys
def getv(dict, key, d=None):
"""Lookup key in dict and return value or the supplied default."""
if key in dict:
return dict[key]
return d
def resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
"""
Return an absolute path, resolving via cwd or last_dir if needed.
"""
if path.endswith('/.'):
path = path[0:-2]
if len(path) > 0 and path[0] == '/':
return path
if path == '.':
return cwd
if path.startswith('./'):
return cwd + path[1:]
if last_dir == cwd:
last_dir = None
for d in [last_dir, cwd]:
if not d:
continue
if path == '..':
dw = d.split('/')
p = '/'.join(dw[:-1])
if not p:
p = '/'
return p
p = '/'.join([d,path])
if debug > 2:
print("looking for:", p, end=' ', file=debug_out)
if not os.path.exists(p):
if debug > 2:
print("nope", file=debug_out)
p = None
continue
if debug > 2:
print("found:", p, file=debug_out)
return p
return None
def cleanpath(path):
"""cleanup path without using realpath(3)"""
if path.startswith('/'):
r = '/'
else:
r = ''
p = []
w = path.split('/')
for d in w:
if not d or d == '.':
continue
if d == '..':
try:
p.pop()
continue
except:
break
p.append(d)
return r + '/'.join(p)
def abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
"""
Return an absolute path, resolving via cwd or last_dir if needed.
this gets called a lot, so we try to avoid calling realpath.
"""
rpath = resolve(path, cwd, last_dir, debug, debug_out)
if rpath:
path = rpath
if (path.find('/') < 0 or
path.find('./') > 0 or
path.endswith('/..')):
path = cleanpath(path)
return path
def sort_unique(list, cmp=None, key=None, reverse=False):
list.sort(cmp, key, reverse)
nl = []
le = None
for e in list:
if e == le:
continue
le = e
nl.append(e)
return nl
def add_trims(x):
return ['/' + x + '/',
'/' + x,
x + '/',
x]
class MetaFile:
"""class to parse meta files generated by bmake."""
conf = None
dirdep_re = None
host_target = None
srctops = []
objroots = []
excludes = []
seen = {}
obj_deps = []
src_deps = []
file_deps = []
def __init__(self, name, conf={}):
"""if name is set we will parse it now.
conf can have the follwing keys:
SRCTOPS list of tops of the src tree(s).
CURDIR the src directory 'bmake' was run from.
RELDIR the relative path from SRCTOP to CURDIR
MACHINE the machine we built for.
set to 'none' if we are not cross-building.
More specifically if machine cannot be deduced from objdirs.
TARGET_SPEC
Sometimes MACHINE isn't enough.
HOST_TARGET
when we build for the pseudo machine 'host'
the object tree uses HOST_TARGET rather than MACHINE.
OBJROOTS a list of the common prefix for all obj dirs it might
end in '/' or '-'.
DPDEPS names an optional file to which per file dependencies
will be appended.
For example if 'some/path/foo.h' is read from SRCTOP
then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output.
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)
"""
self.name = name
self.debug = getv(conf, 'debug', 0)
self.debug_out = getv(conf, 'debug_out', sys.stderr)
self.machine = getv(conf, 'MACHINE', '')
self.machine_arch = getv(conf, 'MACHINE_ARCH', '')
self.target_spec = getv(conf, 'TARGET_SPEC', '')
self.curdir = getv(conf, 'CURDIR')
self.reldir = getv(conf, 'RELDIR')
self.dpdeps = getv(conf, 'DPDEPS')
self.line = 0
if not self.conf:
# some of the steps below we want to do only once
self.conf = conf
self.host_target = getv(conf, 'HOST_TARGET')
for srctop in getv(conf, 'SRCTOPS', []):
if srctop[-1] != '/':
srctop += '/'
if not srctop in self.srctops:
self.srctops.append(srctop)
_srctop = os.path.realpath(srctop)
if _srctop[-1] != '/':
_srctop += '/'
if not _srctop in self.srctops:
self.srctops.append(_srctop)
trim_list = add_trims(self.machine)
if self.machine == 'host':
trim_list += add_trims(self.host_target)
if self.target_spec:
trim_list += add_trims(self.target_spec)
for objroot in getv(conf, 'OBJROOTS', []):
for e in trim_list:
if objroot.endswith(e):
# this is not what we want - fix it
objroot = objroot[0:-len(e)]
if objroot[-1] != '/':
objroot += '/'
if not objroot in self.objroots:
self.objroots.append(objroot)
_objroot = os.path.realpath(objroot)
if objroot[-1] == '/':
_objroot += '/'
if not _objroot in self.objroots:
self.objroots.append(_objroot)
# 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'([^/]+)/(.+)')
if self.dpdeps and not self.reldir:
if self.debug:
print("need reldir:", end=' ', file=self.debug_out)
if self.curdir:
srctop = self.find_top(self.curdir, self.srctops)
if srctop:
self.reldir = self.curdir.replace(srctop,'')
if self.debug:
print(self.reldir, file=self.debug_out)
if not self.reldir:
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()
def reset(self):
"""reset state if we are being passed meta files from multiple directories."""
self.seen = {}
self.obj_deps = []
self.src_deps = []
self.file_deps = []
def dirdeps(self, sep='\n'):
"""return DIRDEPS"""
return sep.strip() + sep.join(self.obj_deps)
def src_dirdeps(self, sep='\n'):
"""return SRC_DIRDEPS"""
return sep.strip() + sep.join(self.src_deps)
def file_depends(self, out=None):
"""Append DPDEPS_${file} += ${RELDIR}
for each file we saw, to the output file."""
if not self.reldir:
return None
for f in sort_unique(self.file_deps):
print('DPDEPS_%s += %s' % (f, self.reldir), file=out)
# these entries provide for reverse DIRDEPS lookup
for f in self.obj_deps:
print('DEPDIRS_%s += %s' % (f, self.reldir), file=out)
def seenit(self, dir):
"""rememer that we have seen dir."""
self.seen[dir] = 1
def add(self, list, data, clue=''):
"""add data to list if it isn't already there."""
if data not in list:
list.append(data)
if self.debug:
print("%s: %sAdd: %s" % (self.name, clue, data), file=self.debug_out)
def find_top(self, path, list):
"""the logical tree may be split across multiple trees"""
for top in list:
if path.startswith(top):
if self.debug > 2:
print("found in", top, file=self.debug_out)
return top
return None
def find_obj(self, objroot, dir, path, input):
"""return path within objroot, taking care of .dirdep files"""
ddep = None
for ddepf in [path + '.dirdep', dir + '/.dirdep']:
if not ddep and os.path.exists(ddepf):
ddep = open(ddepf, 'r').readline().strip('# \n')
if self.debug > 1:
print("found %s: %s\n" % (ddepf, ddep), file=self.debug_out)
if ddep.endswith(self.machine):
ddep = ddep[0:-(1+len(self.machine))]
elif self.target_spec and ddep.endswith(self.target_spec):
ddep = ddep[0:-(1+len(self.target_spec))]
if not ddep:
# no .dirdeps, so remember that we've seen the raw input
self.seenit(input)
self.seenit(dir)
if self.machine == 'none':
if dir.startswith(objroot):
return dir.replace(objroot,'')
return None
m = self.dirdep_re.match(dir.replace(objroot,''))
if m:
ddep = m.group(2)
dmachine = m.group(1)
if dmachine != self.machine:
if not (self.machine == 'host' and
dmachine == self.host_target):
if self.debug > 2:
print("adding .%s to %s" % (dmachine, ddep), file=self.debug_out)
ddep += '.' + dmachine
return ddep
def try_parse(self, name=None, file=None):
"""give file and line number causing exception"""
try:
self.parse(name, file)
except:
# give a useful clue
print('{}:{}: '.format(self.name, self.line), end=' ', file=sys.stderr)
raise
def parse(self, name=None, file=None):
"""A meta file looks like:
# Meta data file "path"
CMD "command-line"
CWD "cwd"
TARGET "target"
-- command output --
-- filemon acquired metadata --
# buildmon version 3
V 3
C "pid" "cwd"
E "pid" "path"
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.
"""
version = 0 # unknown
if name:
self.name = name;
if file:
f = file
cwd = self.last_dir = self.cwd
else:
f = open(self.name, 'r')
skip = True
pid_cwd = {}
pid_last_dir = {}
last_pid = 0
self.line = 0
if self.curdir:
self.seenit(self.curdir) # we ignore this
interesting = 'CEFLRV'
for line in f:
self.line += 1
# ignore anything we don't care about
if not line[0] in interesting:
continue
if self.debug > 2:
print("input:", line, end=' ', file=self.debug_out)
w = line.split()
if skip:
if w[0] == 'V':
skip = False
version = int(w[1])
"""
if version < 4:
# we cannot ignore 'W' records
# as they may be 'rw'
interesting += 'W'
"""
elif w[0] == 'CWD':
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)
continue
pid = int(w[1])
if pid != last_pid:
if last_pid:
pid_last_dir[last_pid] = self.last_dir
cwd = getv(pid_cwd, pid, self.cwd)
self.last_dir = getv(pid_last_dir, pid, self.cwd)
last_pid = pid
# process operations
if w[0] == 'F':
npid = int(w[2])
pid_cwd[npid] = cwd
pid_last_dir[npid] = cwd
last_pid = npid
continue
elif w[0] == 'C':
cwd = abspath(w[2], cwd, None, self.debug, self.debug_out)
if cwd.endswith('/.'):
cwd = cwd[0:-2]
self.last_dir = pid_last_dir[pid] = cwd
pid_cwd[pid] = cwd
if self.debug > 1:
print("cwd=", cwd, file=self.debug_out)
continue
if w[2] in self.seen:
if self.debug > 2:
print("seen:", w[2], file=self.debug_out)
continue
# file operations
if w[0] in 'ML':
# 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
elif w[0] in 'ERWS':
path = w[2]
self.parse_path(path, cwd, w[0], w)
if not file:
f.close()
def is_src(self, base, dir, rdir):
"""is base in srctop"""
for dir in [dir,rdir]:
if not dir:
continue
path = '/'.join([dir,base])
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(dir)
return True
return False
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("exclude:", p, path, file=self.debug_out)
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)
rdir = os.path.realpath(dir)
if rdir == dir:
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
if self.is_src(base, dir, rdir):
self.seenit(w[2])
if not rdir:
return
objroot = None
for dir in [dir,rdir]:
if not dir:
continue
objroot = self.find_top(dir, self.objroots)
if objroot:
break
if objroot:
ddep = self.find_obj(objroot, dir, path, w[2])
if ddep:
self.add(self.obj_deps, ddep, 'obj')
if self.dpdeps and objroot.endswith('/stage/'):
sp = '/'.join(path.replace(objroot,'').split('/')[1:])
self.add(self.file_deps, sp, 'file')
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" ...
Options and key=value pairs contribute to the
dictionary passed to MetaFile.
-S "SRCTOP"
add "SRCTOP" to the "SRCTOPS" list.
-C "CURDIR"
-O "OBJROOT"
add "OBJROOT" to the "OBJROOTS" list.
-m "MACHINE"
-a "MACHINE_ARCH"
-H "HOST_TARGET"
-D "DPDEPS"
-d bumps debug level
"""
import getopt
# import Psyco if we can
# it can speed things up quite a bit
have_psyco = 0
try:
import psyco
psyco.full()
have_psyco = 1
except:
pass
conf = {
'SRCTOPS': [],
'OBJROOTS': [],
'EXCLUDES': [],
}
try:
machine = os.environ['MACHINE']
if machine:
conf['MACHINE'] = machine
machine_arch = os.environ['MACHINE_ARCH']
if machine_arch:
conf['MACHINE_ARCH'] = machine_arch
srctop = os.environ['SB_SRC']
if srctop:
conf['SRCTOPS'].append(srctop)
objroot = os.environ['SB_OBJROOT']
if objroot:
conf['OBJROOTS'].append(objroot)
except:
pass
debug = 0
output = True
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
elif o == '-d':
debug += 1
elif o == '-q':
output = False
elif o == '-H':
conf['HOST_TARGET'] = a
elif o == '-S':
if a not in conf['SRCTOPS']:
conf['SRCTOPS'].append(a)
elif o == '-C':
conf['CURDIR'] = a
elif o == '-O':
if a not in conf['OBJROOTS']:
conf['OBJROOTS'].append(a)
elif o == '-R':
conf['RELDIR'] = a
elif o == '-D':
conf['DPDEPS'] = a
elif o == '-m':
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)
conf['debug'] = debug
# get any var=val assignments
eaten = []
for a in args:
if a.find('=') > 0:
k,v = a.split('=')
if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']:
if k == 'SRCTOP':
k = 'SRCTOPS'
elif k == 'OBJROOT':
k = 'OBJROOTS'
if v not in conf[k]:
conf[k].append(v)
else:
conf[k] = v
eaten.append(a)
continue
break
for a in eaten:
args.remove(a)
debug_out = getv(conf, 'debug_out', sys.stderr)
if debug:
print("config:", file=debug_out)
print("psyco=", have_psyco, file=debug_out)
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 and m:
print(m.dirdeps())
print(m.src_dirdeps('\nsrc:'))
dpdeps = getv(conf, 'DPDEPS')
if dpdeps:
m.file_depends(open(dpdeps, 'wb'))
return m
if __name__ == '__main__':
try:
main(sys.argv)
except:
# yes, this goes to stdout
print("ERROR: ", sys.exc_info()[1])
raise

405
devel/bmake/files/mk/meta2deps.sh Executable file
View File

@ -0,0 +1,405 @@
#!/bin/sh
# NAME:
# meta2deps.sh - extract useful info from .meta files
#
# SYNOPSIS:
# meta2deps.sh SB="SB" "meta" ...
#
# DESCRIPTION:
# This script looks each "meta" file and extracts the
# information needed to deduce build and src dependencies.
#
# To do this, we extract the 'CWD' record as well as all the
# syscall traces which describe 'R'ead, 'C'hdir and 'E'xec
# syscalls.
#
# The typical meta file looks like::
#.nf
#
# # Meta data file "path"
# CMD "command-line"
# CWD "cwd"
# TARGET "target"
# -- command output --
# -- filemon acquired metadata --
# # buildmon version 2
# V 2
# E "pid" "path"
# R "pid" "path"
# C "pid" "cwd"
# R "pid" "path"
# X "pid" "status"
#.fi
#
# The fact that all the syscall entry lines start with a single
# character make these files quite easy to process using sed(1).
#
# To simplify the logic the 'CWD' line is made to look like a
# normal 'C'hdir entry, and "cwd" is remembered so that it can
# be prefixed to any "path" which is not absolute.
#
# If the "path" being read ends in '.srcrel' it is the content
# of (actually the first line of) that file that we are
# interested in.
#
# Any "path" which lies outside of the sandbox "SB" is generally
# not of interest and is ignored.
#
# The output, is a set of absolute paths with "SB" like:
#.nf
#
# $SB/obj-i386/bsd/gnu/lib/csu
# $SB/obj-i386/bsd/gnu/lib/libgcc
# $SB/obj-i386/bsd/include
# $SB/obj-i386/bsd/lib/csu/i386-elf
# $SB/obj-i386/bsd/lib/libc
# $SB/src/bsd/include
# $SB/src/bsd/sys/i386/include
# $SB/src/bsd/sys/sys
# $SB/src/pan-release/rtsock
# $SB/src/pfe-shared/include/jnx
#.fi
#
# Which can then be further processed by 'gendirdeps.mk'
#
# If we are passed 'DPDEPS='"dpdeps", then for each src file
# outside of "CURDIR" we read, we output a line like:
#.nf
#
# DPDEPS_$path += $RELDIR
#.fi
#
# with "$path" geting turned into reldir's, so that we can end
# up with a list of all the directories which depend on each src
# file in another directory. This can allow for efficient yet
# complete testing of changes.
# RCSid:
# $Id: meta2deps.sh,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
meta2src() {
cat /dev/null "$@" |
sed -n '/^R .*\.[chyl]$/s,^..[0-9]* ,,p' |
sort -u
}
meta2dirs() {
cat /dev/null "$@" |
sed -n '/^R .*\/.*\.[a-z0-9][^\/]*$/s,^..[0-9]* \(.*\)/[^/]*$,\1,p' |
sort -u
}
add_list() {
sep=' '
suffix=
while :
do
case "$1" in
"|") sep="$1"; shift;;
-s) suffix="$2"; shift 2;;
*) break;;
esac
done
name=$1
shift
eval list="\$$name"
for top in "$@"
do
case "$sep$list$sep" in
*"$sep$top$suffix$sep"*) continue;;
esac
list="${list:+$list$sep}$top$suffix"
done
eval "$name=\"$list\""
}
_excludes_f() {
egrep -v "$EXCLUDES"
}
meta2deps() {
DPDEPS=
SRCTOPS=$SRCTOP
OBJROOTS=
EXCLUDES=
while :
do
case "$1" in
*=*) eval export "$1"; shift;;
-a) MACHINE_ARCH=$2; shift 2;;
-m) MACHINE=$2; shift 2;;
-C) CURDIR=$2; shift 2;;
-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;;
esac
done
_th= _o=
case "$MACHINE" in
host) _ht=$HOST_TARGET;;
esac
for o in $OBJROOTS
do
case "$MACHINE,/$o/" in
host,*$HOST_TARGET*) ;;
*$MACHINE*|*${TARGET_SPEC:-$MACHINE}*) ;;
*) add_list _o $o; continue;;
esac
for x in $_ht $TARGET_SPEC $MACHINE
do
case "$o" in
"") continue;;
*/$x/) add_list _o ${o%$x/}; o=;;
*/$x) add_list _o ${o%$x}; o=;;
*$x/) add_list _o ${o%$x/}; o=;;
*$x) add_list _o ${o%$x}; o=;;
esac
done
done
OBJROOTS="$_o"
case "$OBJTOP" in
"")
for o in $OBJROOTS
do
OBJTOP=$o${TARGET_SPEC:-$MACHINE}
break
done
;;
esac
src_re=
obj_re=
add_list '|' -s '/*' src_re $SRCTOPS
add_list '|' -s '*' obj_re $OBJROOTS
[ -z "$RELDIR" ] && unset DPDEPS
tf=/tmp/m2d$$-$USER
rm -f $tf.*
trap 'rm -f $tf.*; trap 0' 0
> $tf.dirdep
> $tf.qual
> $tf.srcdep
> $tf.srcrel
> $tf.dpdeps
seenit=
seensrc=
lpid=
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
# we track cwd and ldir (of interest) per pid
# CWD is bmake's cwd
case "$lpid,$pid" in
,C) CWD=$path cwd=$path ldir=$path
if [ -z "$SB" ]; then
SB=`echo $CWD | sed 's,/obj.*,,'`
fi
SRCTOP=${SRCTOP:-$SB/src}
continue
;;
$pid,$pid) ;;
*)
case "$lpid" in
"") ;;
*) eval ldir_$lpid=$ldir;;
esac
eval ldir=\${ldir_$pid:-$CWD} cwd=\${cwd_$pid:-$CWD}
lpid=$pid
;;
esac
case "$op,$path" in
W,*srcrel|*.dirdep) continue;;
C,*)
case "$path" in
/*) cwd=$path;;
*) cwd=`cd $cwd/$path 2> /dev/null && /bin/pwd`;;
esac
# watch out for temp dirs that no longer exist
test -d ${cwd:-/dev/null/no/such} || cwd=$CWD
eval cwd_$pid=$cwd
continue
;;
F,*) # $path is new pid
eval cwd_$path=$cwd ldir_$path=$ldir
continue
;;
*) dir=${path%/*}
case "$path" in
$src_re|$obj_re) ;;
/*/stage/*) ;;
/*) continue;;
*) for path in $ldir/$path $cwd/$path
do
test -e $path && break
done
dir=${path%/*}
;;
esac
;;
esac
# avoid repeating ourselves...
case "$DPDEPS,$seensrc," in
,*)
case ",$seenit," in
*,$dir,*) continue;;
esac
;;
*,$path,*) continue;;
esac
# canonicalize if needed
case "/$dir/" in
*/../*|*/./*)
rdir=$dir
dir=`cd $dir 2> /dev/null && /bin/pwd`
seen="$rdir,$dir"
;;
*) seen=$dir;;
esac
case "$dir" in
${CURDIR:-.}|"") continue;;
$src_re)
# avoid repeating ourselves...
case "$DPDEPS,$seensrc," in
,*)
case ",$seenit," in
*,$dir,*) continue;;
esac
;;
esac
;;
*)
case ",$seenit," in
*,$dir,*) continue;;
esac
;;
esac
if [ -d $path ]; then
case "$path" in
*/..) ldir=${dir%/*};;
*) ldir=$path;;
esac
continue
fi
[ -f $path ] || continue
case "$dir" in
$CWD) continue;; # ignore
$src_re)
seenit="$seenit,$seen"
echo $dir >> $tf.srcdep
case "$DPDEPS,$reldir,$seensrc," in
,*) ;;
*) seensrc="$seensrc,$path"
echo "DPDEPS_$dir/${path##*/} += $RELDIR" >> $tf.dpdeps
;;
esac
continue
;;
esac
# if there is a .dirdep we cannot skip
# just because we've seen the dir before.
if [ -s $path.dirdep ]; then
# this file contains:
# '# ${RELDIR}.<machine>'
echo $path.dirdep >> $tf.qual
continue
elif [ -s $dir.dirdep ]; then
echo $dir.dirdep >> $tf.qual
seenit="$seenit,$seen"
continue
fi
seenit="$seenit,$seen"
case "$dir" in
$obj_re)
echo $dir;;
esac
done > $tf.dirdep
_nl=echo
for f in $tf.dirdep $tf.qual $tf.srcdep
do
[ -s $f ] || continue
case $f in
*qual) # a list of .dirdep files
# we can prefix everything with $OBJTOP to
# tell gendirdeps.mk that these are
# DIRDEP entries, since they are already
# qualified with .<machine> as needed.
# We strip .$MACHINE though
xargs cat < $f | sort -u |
sed "s,^# ,,;s,^,$OBJTOP/,;s,\.${TARGET_SPEC:-$MACHINE}\$,,;s,\.$MACHINE\$,,"
;;
*) sort -u $f;;
esac
_nl=:
done
if [ -s $tf.dpdeps ]; then
case "$DPDEPS" in
*/*) ;;
*) echo > $DPDEPS;; # the echo is needed!
esac
sort -u $tf.dpdeps |
sed "s,${SRCTOP}/,,;s,${SB_BACKING_SB:-$SB}/src/,," >> $DPDEPS
fi
# ensure we produce _something_ else egrep -v gets upset
$_nl
}
case /$0 in
*/meta2dep*) meta2deps "$@";;
*/meta2dirs*) meta2dirs "$@";;
*/meta2src*) meta2src "$@";;
esac

View File

@ -0,0 +1,503 @@
mk-files
********
The term ``mk-files`` refers to a collection of ``*.mk`` files.
You need bmake_ or a *recent* NetBSD_ make.
If in doubt use bmake_.
Introduction
============
Many years ago, when building large software projects, I used GNU make
(or my own patched version of it), and had developed a set of macros
to simplify developing complex build trees.
Since the early 90's my main development machines, run BSD
(NetBSD_ to be precise), and the BSD source tree is good example of a
large software project. It quickly became clear that
``/usr/share/mk/*.mk`` were a great model, but were quite tightly
linked to building the BSD tree.
Much as I liked using NetBSD, my customers were more likely to be
using SunOS, HP-UX etc, so I started on bmake_ and a portable collection
of mk-files (mk.tar.gz_). NetBSD provided much of the original structure.
Since then I've added a lot of features to NetBSD's make and hence to
bmake which is kept closely in sync. The mk-files however have
diverged quite a bit, though ideas are still picked up from NetBSD
and FreeBSD.
Basics
------
The BSD build model is very simple. A directory produces one
component, which is generally either a library or a program.
Library makefiles include ``lib.mk`` and programs include ``prog.mk``
and they *do the right thing*.
A simple library makefile might look like::
LIB = sig
SRCS = \
sigaction.c \
sigcompat.c \
sighdl.c
.include <lib.mk>
a simple program makefile::
PROG = cat
SRCS = cat.c
.include <prog.mk>
in such cases even the ``SRCS`` line is unnecessary as ``prog.mk``
will default it to ``${PROG}.c``.
It is the sensible use of defaults and the plethora of macro modifiers
provided by bmake_ that allow simple makefiles such as the above
*just work* on many different systems.
mk-files
========
This section provides a brief description of some of the ``*.mk``
files.
sys.mk
------
When bmake starts, it looks for ``sys.mk`` and reads it before doing
anything else. Thus, this is the place to setup the environment for
everyone else.
In this distribution, sys.mk avoids doing anything platform dependent.
It is quite short, and includes a number of other files (which may or
may not exists)
sys.env.mk
If it exists, is expected to do things like conditioning the
environment. Since it will only be included by the initial
instance of bmake, it should ``.export`` anything that
sub-makes might need.
examples/sys.clean-env.mk
An example of how to clean the environment.
See the file for all the details::
.if ${MAKE_VERSION} >= 20100606 && ${.MAKE.LEVEL} == 0
# we save any env var that starts with these
MAKE_SAVE_ENV_PREFIX += SB MK MAKE MACHINE NEED_ CCACHE DISTCC USE_ SSH
MAKE_SAVE_ENV_VARS += \
PATH HOME USER LOGNAME \
SRCTOP OBJTOP OBJROOT \
${_env_vars}
_env_vars != env | egrep '^(${MAKE_SAVE_ENV_PREFIX:ts|})' | sed 's,=.*,,'; echo
_export_list =
.for v in ${MAKE_SAVE_ENV_VARS:O:u}
.if !empty($v)
_export_list += $v
$v := ${$v}
.endif
.endfor
# now clobber the environment
.unexport-env
# list of vars that we handle specially below
_tricky_env_vars = MAKEOBJDIR
# export our selection - sans tricky ones
.export ${_export_list:${_tricky_env_vars:${M_ListToSkip}}}
# this next bit may need tweaking
.if defined(MAKEOBJDIR)
srctop := ${SRCTOP:U${SB_SRC:U${SB}/src}}
objroot := ${OBJROOT:U${SB_OBJROOT:U${SB}/${SB_OBJPREFIX}}}
# we'll take care of MACHINE below
objtop := ${OBJTOP:U${objroot}${MACHINE}}
.if !empty(objtop)
# we would normally want something like (/bin/sh):
# MAKEOBJDIR="\${.CURDIR:S,${SRCTOP},${OBJROOT}\${MACHINE},}"
# the $$ below is how we achieve the same result here.
# since everything saved from the environment above
# has run through := we need to compensate for ${MACHINE}
MAKEOBJDIR = $${.CURDIR:S,${srctop},${objtop:S,${MACHINE},\${MACHINE},},}
# export these as-is, and do not track...
.export-env ${_tricky_env_vars}
# now evaluate for ourselves
.for v in ${_tricky_env_vars}
$v := ${$v}
.endfor
.endif
.endif
.endif
host-target.mk
Is used to set macros like ``HOST_TARGET``, ``HOST_OS`` and
``host_os`` which are used to find the next step.
sys/\*.mk
Platform specific additions, such as ``Darwin.mk`` or ``SunOS.mk``
set things like ``HOST_LIBEXT = .dylib`` for Darwin or
``SHLIB_FULLVERSION = ${SHLIB_MAJOR}`` for SunOS 5.
If there is no OS specific file, ``sys/Generic.mk`` is used.
local.sys.mk
Any ``local.*.mk`` file is not part of the distribution.
This provides a hook for sites to do extra setup without
having to edit the distributed files.
The above arrangement makes it easy for the mk files to be part of a
src tree on an NFS volume and to allow building on multiple platforms.
lib.mk
------
This file is used to build a number of different libraries from the
same SRCS.
lib${LIB}.a
An archive lib of ``.o`` files, this is the default
lib${LIB}_p.a
A profiled lib of ``.po`` files.
Still an archive lib, but all the objects are built with
profiling in mind - hence the different extension.
It is skipped if ``MKPROFILE`` is "no".
lib${LIB}_pic.a
An archive of ``.so`` objects compiled for relocation.
On NetBSD this is the input to ``lib${LIB}.${LD_so}``, it is
skipped if ``MKPICLIB`` is "no".
lib${LIB}.${LD_so}
A shared library. The value of ``LD_so`` is very platform
specific. For example::
# SunOS 5 and most other ELF systems
libsslfd.so.1
# Darwin
libsslfd.1.dylib
This library will only be built if ``SHLIB_MAJOR`` has
a value, and ``MKPIC`` is not set to "no".
There is a lot of platform specific tweaking in ``lib.mk``, largely the
result of the original distributions trying to avoid interfering with
the system's ``sys.mk``.
libnames.mk
-----------
This is included by both ``prog.mk`` and ``lib.mk`` and tries to
include ``*.libnames.mk`` of which:
local.libnames.mk
does not exist unless you create it. It is a handy way for you
to customize without touching the distributed files.
For example, on a test machine I needed to build openssl but
not install it, so put the following in ``local.libnames.mk``::
.if ${host_os} == "sunos"
LIBCRYPTO = ${OBJTOP}/openssl/lib/crypto/libcrypto${DLIBEXT}
LIBSSL = ${OBJTOP}/openssl/lib/ssl/libssl${DLIBEXT}
INCLUDES_libcrypto = -I${OBJ_libcrypto}
.endif
The makefile created an openssl dir in ``${OBJ_libcrypto}`` to
gather all the headers. dpadd.mk_ did the rest.
sjg.libnames.mk
not part of the mk-files distribution.
host.libnames.mk
contains logic to find any libs named in ``HOST_LIBS`` in
``HOST_LIBDIRS``.
Each file above gets an opportunity to define things like::
LIBSSLFD ?= ${OBJTOP}/ssl/lib/sslfd/libsslfd${DLIBEXT}
INCLUDES_libsslfd = -I${SRC_libsslfd}/h -I${OBJ_libslfd}
these are used by dpadd.mk_ and will be explained below.
dpadd.mk
--------
This file looks like line noise, and is best considered read-only.
However it provides some very useful functionality, which simplifies the build.
Makefiles can use the LIB* macros defined via libnames.mk_ or anywhere
else in various ways::
# indicate that we need to include headers from LIBCRYPTO
# this would result in ${INCLUDES_libcrypto} being added to CFLAGS.
SRC_LIBS += ${LIBCRYPTO}
# indicate that libsslfd must be built already.
# it also has the same effect as SRC_LIBS
DPADD += ${LIBSSLFD}
# indicate that not only must libsslfd be built,
# but that we need to link with it.
# this is almost exactly equivalent to
# DPADD += ${LIBSSLFD}
# LDADD += -L${LIBSSLFD:H} -lsslfd
# and mostly serves to ensure that DPADD and LDADD are in sync.
DPLIBS += ${LIBSSLFD}
Any library (referenced by its full path) in any of the above, is
added to ``DPMAGIC_LIBS`` with the following results, for each lib *foo*.
SRC_libfoo
Is set to indicate where the src for libfoo is.
By default it is derived from ``LIBFOO`` by replacing
``${OBJTOP}`` with ``${SRCTOP}``.
OBJ_libfoo
Not very exciting, is just the dir where libfoo lives.
INCLUDES_libfoo
What to add to ``CFLAGS`` to find the public headers.
The default varies. If ``${SRC_libfoo}/h`` exists, it is assumed
to be the home of all public headers and thus the default is
``-I${SRC_libfoo}/h``
Otherwise we make no assumptions and the default is
``-I${SRC_libfoo} -I${OBJ_libfoo}``
LDADD_libfoo
This only applies to libs reference via ``DPLIBS``.
The default is ``-lfoo``, ``LDADD_*`` provides a hook to
instantiate other linker flags at the appropriate point
without losing the benfits of ``DPLIBS``.
prog.mk
-------
Compiles the specified SRCS and links them and the nominated libraries
into a program. Prog makefiles usually need to list the libraries
that need to be linked. We prefer use of ``DPLIBS`` but the more
traditional ``DPADD`` and ``LDADD`` work just as well.
That is::
DPLIBS += ${LIBCRYPTO}
is equivalent to::
DPADD += ${LIBCRYPTO}
LDADD += -lcrypto
obj.mk
------
One of the cool aspects of BSD make, is its support for separating
object files from the src tree. This is also the source of much
confusion to some.
Traditionally one had to do a separate ``make obj`` pass through the
tree. If ``MKOBJDIRS`` is "auto", we include auto.obj.mk_.
auto.obj.mk
-----------
This leverages the ``.OBJDIR`` target introduced some years ago to
NetBSD make, to automatically create the desired object dir.
subdir.mk
---------
This is the traditional means of walking the tree. A makefile sets
``SUBDIR`` to the list of sub-dirs to visit.
If ``SUBDIR_MUST_EXIST`` is set, missing directories cause an error,
otherwise a warning is issued. If you don't even want the warning,
set ``MISSING_DIR=continue``.
Traditionally, ``subdir.mk`` prints clue as it visits each subdir::
===> ssl
===> ssl/lib
===> ssl/lib/sslfd
you can suppress that - or enhance it by setting ``ECHO_DIR``::
# suppress subdir noise
ECHO_DIR=:
# print time stamps
ECHO_DIR=echo @ `date "+%s [%Y-%m-%d %T] "`
links.mk
--------
Provides rules for processing lists of ``LINKS`` and ``SYMLINKS``.
Each is expected to be a list of ``link`` and ``target`` pairs
(``link`` -> ``target``).
The logic is generally in a ``_*_SCRIPT`` which is referenced in a
``_*_USE`` (``.USE``) target.
The ``_BUILD_*`` forms are identical, but do not use ``${DESTDIR}``
and so are useful for creating symlinks during the build phase.
For example::
SYMLINKS += ${.CURDIR}/${MACHINE_ARCH}/include machine
header_links: _BUILD_SYMLINKS_USE
md.o: header_links
would create a symlink called ``machine`` in ``${.OBJDIR}`` pointing to
``${.CURDIR}/${MACHINE_ARCH}/include`` before compiling ``md.o``
autoconf.mk
-----------
Deals with running (or generating) GNU autoconf ``configure`` scripts.
dep.mk
------
Deals with collecting dependencies. Another useful feature of BSD
make is the separation of this sort of information into a ``.depend``
file. ``MKDEP`` needs to point to a suitable tool (like mkdeps.sh_)
If ``USE_AUTODEP_MK`` is "yes" includes autodep.mk_
autodep.mk
----------
Leverages the ``-MD`` feature of recent GCC to collect dependency
information as a side effect of compilation. With this GCC puts
dependency info into a ``.d`` file.
Unfortunately GCC bases the name of the ``.d`` file on the name of the
input rather than the output file, which causes problems when the same
source is compiled different ways. The latest GCC supports ``-MF`` to
name the ``.d`` file and ``-MT`` to control the name to put as the
dependent.
Recent bmake allows dependencies for the ``.END`` target (run at the
end if everything was successful), and ``autodep.mk`` uses this to
post process the ``.d`` files into ``.depend``.
auto.dep.mk
-----------
A much simpler implementation than autodep.mk_ it uses
``-MF ${.TARGET:T}.d``
to avoid possible conflicts during parallel builds.
This precludes the use of suffix rules to drive ``make depend``, so
dep.mk_ handles that if specifically requested.
options.mk
----------
Inspired by FreeBSD's ``bsd.own.mk`` more flexible.
FreeBSD now have similar functionality in ``bsd.mkopt.mk``.
It allows users to express their intent with respect to options
``MK_*`` by setting ``WITH_*`` or ``WITHOUT_*``.
Note: ``WITHOUT_*`` wins if both are set, and makefiles can set
``NO_*`` to say they cannot handle that option, or even ``MK_*`` if
they really need to.
own.mk
------
Normally included by ``init.mk`` (included by ``lib.mk`` and
``prog.mk`` etc), sets macros for default ownership etc.
It includes ``${MAKECONF}`` if it is defined and exists.
ldorder.mk
----------
Leverages ``bmake`` to compute optimal link order for libraries.
This works nicely and makes refactoring a breeze - so long as you
have not (or few) cicular dependencies between libraries.
man.mk
------
Deals with man pages.
warnings.mk
-----------
This provides a means of fine grained control over warnings on a per
``${MACHINE}`` or even file basis.
A makefile sets ``WARNINGS_SET`` to name a list of warnings
and individual ``W_*`` macros can be used to tweak them.
For example::
WARNINGS_SET = HIGH
W_unused_sparc = -Wno-unused
would add all the warnings in ``${HIGH_WARNINGS}`` to CFLAGS, but
on sparc, ``-Wno-unused`` would replace ``-Wunused``.
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
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
=======
You can use the content of mk.tar.gz_ without installing at all.
The script ``install-mk`` takes care of copying ``*.mk`` into a
destination directory, and unless told not to, create ``bsd.*.mk`` links
for ``lib.mk`` etc.
If you just want to create the ``bsd.*.mk`` links in the directory
where you unpacked the tar file, you can::
./mk/install-mk ./mk
------
.. _bmake: bmake.htm
.. _NetBSD: http://www.netbsd.org/
.. _mkdeps.sh: http://www.crufty.net/ftp/pub/sjg/mkdeps.sh
.. _mk.tar.gz: http://www.crufty.net/ftp/pub/sjg/mk.tar.gz
:Author: sjg@crufty.net
:Revision: $Id: mk-files.txt,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
:Copyright: Crufty.NET

View File

@ -0,0 +1,103 @@
:
# $Id: mkopt.sh,v 1.1.1.1 2020/05/24 05:35:53 nia 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=:
_MKOPT_PREFIX=${_MKOPT_PREFIX:-MK_}
#
# _mk_opt default OPT
#
# 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=${_MKOPT_PREFIX}$2 _wo=WITHOUT_$2 _wi=WITH_$2
eval "_mov=\$$_mo _wov=\$$_wo _wiv=\$$_wi"
case "$_wiv" in
[Nn][Oo]) _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
*/*) # option is dirname default comes from basename
eval "_d=\$${_MKOPT_PREFIX}${_o#*/}"
_o=${_o%/*}
;;
yes|no) _d=$_o; continue;;
esac
_mk_opt $_d $_o
done
}
# handle either options.mk style OPTIONS_DEFAULT_*
# or FreeBSD's new bsd.mkopt.mk style __DEFAULT_*_OPTIONS
_mk_opts_defaults() {
_mk_opts no $OPTIONS_DEFAULT_NO $__DEFAULT_NO_OPTIONS \
yes $OPTIONS_DEFAULT_YES $__DEFAULT_YES_OPTIONS \
$OPTIONS_DEFAULT_DEPENDENT $__DEFAULT_DEPENDENT_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

View File

@ -0,0 +1,47 @@
# $NetBSD: nls.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
.if !target(.MAIN)
# init.mk not included
.-include <${.CURDIR:H}/Makefile.inc>
.MAIN: all
.endif
.SUFFIXES: .cat .msg
.msg.cat:
@rm -f ${.TARGET}
gencat ${.TARGET} ${.IMPSRC}
.if defined(NLS) && !empty(NLS)
NLSALL= ${NLS:.msg=.cat}
.NOPATH: ${NLSALL}
.endif
.if !defined(NLSNAME)
.if defined(PROG)
NLSNAME=${PROG}
.else
NLSNAME=lib${LIB}
.endif
.endif
nlsinstall:
.if defined(NLSALL)
@for msg in ${NLSALL}; do \
NLSLANG=`basename $$msg .cat`; \
dir=${DESTDIR}${NLSDIR}/$${NLSLANG}; \
${INSTALL} -d $$dir; \
${INSTALL} ${COPY} -o ${NLSOWN} -g ${NLSGRP} -m ${NLSMODE} $$msg $$dir/${NLSNAME}.cat; \
done
.endif
.if defined(NLSALL)
all: ${NLSALL}
install: nlsinstall
cleandir: cleannls
cleannls:
rm -f ${NLSALL}
.endif

113
devel/bmake/files/mk/obj.mk Normal file
View File

@ -0,0 +1,113 @@
# $Id: obj.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 1999-2010, 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 !target(__${.PARSEFILE:S,bsd.,,}__)
__${.PARSEFILE:S,bsd.,,}__:
.include <init.mk>
ECHO_TRACE ?= echo
.if ${MK_OBJDIRS} == "no"
obj:
objlink:
objwarn:
.else
# this has to match how make behaves
.if defined(MAKEOBJDIRPREFIX) || defined(MAKEOBJDIR)
.if defined(MAKEOBJDIRPREFIX)
__objdir:= ${MAKEOBJDIRPREFIX}${.CURDIR}
.else
__objdir:= ${MAKEOBJDIR}
.endif
.else
__objdir= ${__objlink}
.endif
.if defined(OBJMACHINE)
__objlink= obj.${MACHINE}
.else
__objlink= obj
.endif
.if ${MK_AUTO_OBJ} == "yes"
.-include "auto.obj.mk"
.endif
.NOPATH: ${__objdir}
.PHONY: obj
obj: _SUBDIRUSE
@if test ! -d ${__objdir}/.; then \
mkdir -p ${__objdir}; \
if test ! -d ${__objdir}; then \
mkdir ${__objdir}; exit 1; \
fi; \
${ECHO_TRACE} "[Creating objdir ${__objdir}...]" >&2; \
fi
.if !target(_SUBDIRUSE)
# this just allows us to be included by ourselves
_SUBDIRUSE:
.endif
# so we can interact with freebsd makefiles
.if !target(objwarn)
objwarn:
.if ${.OBJDIR} == ${.CURDIR}
@echo "Warning Object directory is ${.CURDIR}"
.elif ${.OBJDIR} != ${__objdir}
@echo "Warning Object directory is ${.OBJDIR} vs. ${__objdir}"
.endif
.endif
.if !target(objlink)
objlink:
.if ${__objdir:T} != ${__objlink}
@if test -d ${__objdir}/.; then \
${RM} -f ${.CURDIR}/${__objlink}; \
${LN} -s ${__objdir} ${.CURDIR}/${__objlink}; \
echo "${__objlink} -> ${__objdir}"; \
else \
echo "No ${__objdir} to link to - do a 'make obj'"; \
fi
.endif
.endif
.endif
_CURDIR?= ${.CURDIR}
_OBJDIR?= ${.OBJDIR}
.if !target(print-objdir)
print-objdir:
@echo ${_OBJDIR}
.endif
.if !target(whereobj)
whereobj:
@echo ${_OBJDIR}
.endif
.if !target(destroy)
.if ${.CURDIR} != ${.OBJDIR}
destroy:
(cd ${_CURDIR} && rm -rf ${_OBJDIR})
.else
destroy: clean
.endif
.endif
.endif

View File

@ -0,0 +1,80 @@
# $Id: options.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2012, 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
#
# Inspired by FreeBSD bsd.own.mk, but intentionally simpler and more flexible.
# Options are normally listed in either OPTIONS_DEFAULT_{YES,NO}
# We convert these to ${OPTION}/{yes,no} in OPTIONS_DEFAULT_VALUES.
# We add the OPTIONS_DEFAULT_NO first so they take precedence.
# This allows override of an OPTIONS_DEFAULT_YES by adding it to
# OPTIONS_DEFAULT_NO or adding ${OPTION}/no to OPTIONS_DEFAULT_VALUES.
# An OPTIONS_DEFAULT_NO option can only be overridden by putting
# ${OPTION}/yes in OPTIONS_DEFAULT_VALUES.
# A makefile may set NO_* (or NO*) to indicate it cannot do something.
# User sets WITH_* and WITHOUT_* to indicate what they want.
# We set ${OPTION_PREFIX:UMK_}* which is then all we need care about.
OPTIONS_DEFAULT_VALUES += \
${OPTIONS_DEFAULT_NO:O:u:S,$,/no,} \
${OPTIONS_DEFAULT_YES:O:u:S,$,/yes,}
OPTION_PREFIX ?= MK_
# NO_* takes precedence
# If both WITH_* and WITHOUT_* are defined, WITHOUT_ wins unless
# DOMINANT_* is set to "yes"
# Otherwise WITH_* and WITHOUT_* override the default.
.for o in ${OPTIONS_DEFAULT_VALUES:M*/*}
.if defined(NO_${o:H}) || defined(NO${o:H})
# we cannot do it
${OPTION_PREFIX}${o:H} ?= no
.elif defined(WITH_${o:H}) && defined(WITHOUT_${o:H})
# normally WITHOUT_ wins
DOMINANT_${o:H} ?= no
${OPTION_PREFIX}${o:H} ?= ${DOMINANT_${o:H}}
.elif ${o:T:tl} == "no"
.if defined(WITH_${o:H})
${OPTION_PREFIX}${o:H} ?= yes
.else
${OPTION_PREFIX}${o:H} ?= no
.endif
.else
.if defined(WITHOUT_${o:H})
${OPTION_PREFIX}${o:H} ?= no
.else
${OPTION_PREFIX}${o:H} ?= yes
.endif
.endif
.endfor
# OPTIONS_DEFAULT_DEPENDENT += FOO_UTILS/FOO
# If neither WITH[OUT]_FOO_UTILS is set, (see rules above)
# use the value of ${OPTION_PREFIX}FOO
.for o in ${OPTIONS_DEFAULT_DEPENDENT:M*/*:O:u}
.if defined(NO_${o:H}) || defined(NO${o:H})
# we cannot do it
${OPTION_PREFIX}${o:H} ?= no
.elif defined(WITH_${o:H}) && defined(WITHOUT_${o:H})
# normally WITHOUT_ wins
DOMINANT_${o:H} ?= no
${OPTION_PREFIX}${o:H} ?= ${DOMINANT_${o:H}}
.elif defined(WITH_${o:H})
${OPTION_PREFIX}${o:H} ?= yes
.elif defined(WITHOUT_${o:H})
${OPTION_PREFIX}${o:H} ?= no
.else
${OPTION_PREFIX}${o:H} ?= ${${OPTION_PREFIX}${o:T}}
.endif
.endfor
.undef OPTIONS_DEFAULT_VALUES OPTIONS_DEFAULT_NO OPTIONS_DEFAULT_YES

271
devel/bmake/files/mk/own.mk Normal file
View File

@ -0,0 +1,271 @@
# $Id: own.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
.if !target(__init.mk__)
.include "init.mk"
.endif
.if !defined(NOMAKECONF) && !defined(NO_MAKECONF)
MAKECONF?= /etc/mk.conf
.-include "${MAKECONF}"
.endif
.include <host-target.mk>
TARGET_OSNAME?= ${_HOST_OSNAME}
TARGET_OSREL?= ${_HOST_OSREL}
TARGET_OSTYPE?= ${HOST_OSTYPE}
TARGET_HOST?= ${HOST_TARGET}
# these may or may not exist
.-include <${TARGET_HOST}.mk>
.-include <config.mk>
RM?= rm
LN?= ln
INSTALL?= install
prefix?= /usr
.if exists(${prefix}/lib)
libprefix?= ${prefix}
.else
libprefix?= /usr
.endif
# FreeBSD at least does not set this
MACHINE_ARCH?= ${MACHINE}
# we need to make sure these are defined too in case sys.mk fails to.
COMPILE.s?= ${CC} ${AFLAGS} -c
LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp
LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
CXXFLAGS?= ${CFLAGS}
COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
COMPILE.f?= ${FC} ${FFLAGS} -c
LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
LEX.l?= ${LEX} ${LFLAGS}
COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
YACC.y?= ${YACC} ${YFLAGS}
# for suffix rules
IMPFLAGS?= ${COPTS.${.IMPSRC:T}} ${CPUFLAGS.${.IMPSRC:T}} ${CPPFLAGS.${.IMPSRC:T}}
.for s in .c .cc
COMPILE.$s += ${IMPFLAGS}
LINK.$s += ${IMPFLAGS}
.endfor
PRINT.VAR.MAKE = MAKESYSPATH=${MAKESYSPATH:U${.PARSEDIR}} ${.MAKE}
.if empty(.MAKEFLAGS:M-V*)
.if defined(MAKEOBJDIRPREFIX) || defined(MAKEOBJDIR)
PRINTOBJDIR= ${PRINT.VAR.MAKE} -r -V .OBJDIR -f /dev/null xxx
.else
PRINTOBJDIR= ${PRINT.VAR.MAKE} -V .OBJDIR
.endif
.else
PRINTOBJDIR= echo # prevent infinite recursion
.endif
# we really like to have SRCTOP and OBJTOP defined...
.if !defined(SRCTOP) || !defined(OBJTOP)
.-include <srctop.mk>
.endif
.if !defined(SRCTOP) || !defined(OBJTOP)
# dpadd.mk is rather pointless without these
OPTIONS_DEFAULT_NO+= DPADD_MK
.endif
# process options
OPTIONS_DEFAULT_NO+= \
INSTALL_AS_USER \
GPROF \
PROG_LDORDER_MK \
LIBTOOL \
LINT \
OPTIONS_DEFAULT_YES+= \
ARCHIVE \
AUTODEP \
CRYPTO \
DOC \
DPADD_MK \
GDB \
KERBEROS \
LINKLIB \
MAN \
NLS \
OBJ \
PIC \
SHARE \
SKEY \
YP \
OPTIONS_DEFAULT_DEPENDENT+= \
CATPAGES/MAN \
LDORDER_MK/PROG_LDORDER_MK \
OBJDIRS/OBJ \
PICINSTALL/LINKLIB \
PICLIB/PIC \
PROFILE/LINKLIB \
STAGING_PROG/STAGING \
.include <options.mk>
.if ${MK_INSTALL_AS_USER} == "yes"
# We ignore this if user is root.
_uid!= id -u
.if ${_uid} != 0
.if !defined(USERGRP)
USERGRP!= id -g
.export USERGRP
.endif
.for x in BIN CONF DOC INC INFO FILES KMOD LIB MAN NLS PROG SHARE
$xOWN= ${USER}
$xGRP= ${USERGRP}
$x_INSTALL_OWN=
.endfor
.endif
.endif
# override this in sys.mk
ROOT_GROUP?= wheel
BINGRP?= ${ROOT_GROUP}
BINOWN?= root
BINMODE?= 555
NONBINMODE?= 444
DIRMODE?= 755
INCLUDEDIR?= ${prefix}/include
INCDIR?= ${INCLUDEDIR}
# Define MANZ to have the man pages compressed (gzip)
#MANZ= 1
MANTARGET?= cat
MANDIR?= ${prefix}/share/man/${MANTARGET}
MANGRP?= ${BINGRP}
MANOWN?= ${BINOWN}
MANMODE?= ${NONBINMODE}
INCLUDEDIR?= ${libprefix}/include
LIBDIR?= ${libprefix}/lib
SHLIBDIR?= ${libprefix}/lib
.if ${USE_SHLIBDIR:Uno} == "yes"
_LIBSODIR?= ${SHLIBDIR}
.else
_LIBSODIR?= ${LIBDIR}
.endif
# this is where ld.*so lives
SHLINKDIR?= /usr/libexec
LINTLIBDIR?= ${libprefix}/libdata/lint
LIBGRP?= ${BINGRP}
LIBOWN?= ${BINOWN}
LIBMODE?= ${NONBINMODE}
DOCDIR?= ${prefix}/share/doc
DOCGRP?= ${BINGRP}
DOCOWN?= ${BINOWN}
DOCMODE?= ${NONBINMODE}
NLSDIR?= ${prefix}/share/nls
NLSGRP?= ${BINGRP}
NLSOWN?= ${BINOWN}
NLSMODE?= ${NONBINMODE}
KMODDIR?= ${prefix}/lkm
KMODGRP?= ${BINGRP}
KMODOWN?= ${BINOWN}
KMODMODE?= ${NONBINMODE}
SHAREGRP?= ${BINGRP}
SHAREOWN?= ${BINOWN}
SHAREMODE?= ${NONBINMODE}
COPY?= -c
STRIP_FLAG?= -s
.if ${TARGET_OSNAME} == "NetBSD"
.if exists(/usr/libexec/ld.elf_so)
OBJECT_FMT=ELF
.endif
OBJECT_FMT?=a.out
.endif
# sys.mk should set something appropriate if need be.
OBJECT_FMT?=ELF
.if (${_HOST_OSNAME} == "FreeBSD")
CFLAGS+= ${CPPFLAGS}
.endif
# allow for per target flags
# apply the :T:R first, so the more specific :T can override if needed
CPPFLAGS += ${CPPFLAGS_${.TARGET:T:R}} ${CPPFLAGS_${.TARGET:T}}
CFLAGS += ${CFLAGS_${.TARGET:T:R}} ${CFLAGS_${.TARGET:T}}
# Define SYS_INCLUDE to indicate whether you want symbolic links to the system
# source (``symlinks''), or a separate copy (``copies''); (latter useful
# in environments where it's not possible to keep /sys publicly readable)
#SYS_INCLUDE= symlinks
# don't try to generate PIC versions of libraries on machines
# which don't support PIC.
.if (${MACHINE_ARCH} == "vax") || \
((${MACHINE_ARCH} == "mips") && defined(STATIC_TOOLCHAIN)) || \
((${MACHINE_ARCH} == "alpha") && defined(ECOFF_TOOLCHAIN))
MK_PIC=no
.endif
# No lint, for now.
NOLINT=
.if ${MK_LINKLIB} == "no"
MK_PICINSTALL= no
MK_PROFILE= no
.endif
.if ${MK_MAN} == "no"
MK_CATPAGES= no
.endif
.if ${MK_OBJ} == "no"
MK_OBJDIRS= no
MK_AUTO_OBJ= no
.endif
.if ${MK_SHARE} == "no"
MK_CATPAGES= no
MK_DOC= no
MK_INFO= no
MK_MAN= no
MK_NLS= no
.endif
# :U incase not using our sys.mk
.if ${MK_META_MODE:Uno} == "yes"
# should all be set by sys.mk if not default
TARGET_SPEC_VARS ?= MACHINE
.if ${TARGET_SPEC_VARS:[#]} > 1
TARGET_SPEC_VARS_REV := ${TARGET_SPEC_VARS:[-1..1]}
.else
TARGET_SPEC_VARS_REV = ${TARGET_SPEC_VARS}
.endif
.if ${MK_STAGING} == "yes"
STAGE_ROOT?= ${OBJROOT}/stage
STAGE_OBJTOP?= ${STAGE_ROOT}/${TARGET_SPEC_VARS_REV:ts/}
.endif
.endif
.endif

View File

@ -0,0 +1,36 @@
# $Id: prlist.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2006, 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 !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
# this needs to be included after all the lists it will process
# are defined - which is why it is a separate file.
# Usage looks like:
# MAKEFLAGS= ${.MAKE} -f ${MAKEFILE} prlist.SOMETHING_HUGE | xargs whatever
#
.if make(prlist.*)
.for t in ${.TARGETS:Mprlist.*:E}
.if empty($t)
prlist.$t:
.else
prlist.$t: ${$t:O:u:S,^,prlist-,}
${$t:O:u:S,^,prlist-,}: .PHONY
@echo "${.TARGET:S,prlist-,,}"
.endif
.endfor
.endif
.endif

View File

@ -0,0 +1,251 @@
# $Id: prog.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
.include <init.mk>
# FreeBSD at least expects MAN8 etc.
.if defined(MAN) && !empty(MAN)
_sect:=${MAN:E}
MAN${_sect}=${MAN}
.endif
.SUFFIXES: .out .o .c .cc .C .y .l .s .8 .7 .6 .5 .4 .3 .2 .1 .0
CFLAGS+= ${COPTS}
.if ${TARGET_OSNAME} == "NetBSD"
.if ${MACHINE_ARCH} == "sparc64"
CFLAGS+= -mcmodel=medlow
.endif
# ELF platforms depend on crtbegin.o and crtend.o
.if ${OBJECT_FMT} == "ELF"
.ifndef LIBCRTBEGIN
LIBCRTBEGIN= ${DESTDIR}/usr/lib/crtbegin.o
.MADE: ${LIBCRTBEGIN}
.endif
.ifndef LIBCRTEND
LIBCRTEND= ${DESTDIR}/usr/lib/crtend.o
.MADE: ${LIBCRTEND}
.endif
_SHLINKER= ${SHLINKDIR}/ld.elf_so
.else
LIBCRTBEGIN?=
LIBCRTEND?=
_SHLINKER= ${SHLINKDIR}/ld.so
.endif
.ifndef LIBCRT0
LIBCRT0= ${DESTDIR}/usr/lib/crt0.o
.MADE: ${LIBCRT0}
.endif
.endif # NetBSD
# here is where you can define what LIB* are
.-include <libnames.mk>
.if ${MK_DPADD_MK} == "yes"
# lots of cool magic, but might not suit everyone.
.include <dpadd.mk>
.endif
.if ${MK_GPROF} == "yes"
CFLAGS+= ${CC_PG} ${PROFFLAGS}
LDADD+= ${CC_PG}
.if ${MK_DPADD_MK} == "no"
LDADD_LIBC_P?= -lc_p
LDADD_LAST+= ${LDADD_LIBC_P}
.endif
.endif
.if defined(SHAREDSTRINGS)
CLEANFILES+=strings
.c.o:
${CC} -E ${CFLAGS} ${.IMPSRC} | xstr -c -
@${CC} ${CFLAGS} -c x.c -o ${.TARGET}
@rm -f x.c
${CXX_SUFFIXES:%=%.o}:
${CXX} -E ${CXXFLAGS} ${.IMPSRC} | xstr -c -
@mv -f x.c x.cc
@${CXX} ${CXXFLAGS} -c x.cc -o ${.TARGET}
@rm -f x.cc
.endif
.if defined(PROG)
BINDIR ?= ${prefix}/bin
SRCS?= ${PROG}.c
.for s in ${SRCS:N*.h:N*.sh:M*/*}
${.o .po .lo:L:@o@${s:T:R}$o@}: $s
.endfor
.if !empty(SRCS:N*.h:N*.sh)
OBJS+= ${SRCS:T:N*.h:N*.sh:R:S/$/.o/g}
LOBJS+= ${LSRCS:.c=.ln} ${SRCS:M*.c:.c=.ln}
.endif
.if defined(OBJS) && !empty(OBJS)
.NOPATH: ${OBJS} ${PROG} ${SRCS:M*.[ly]:C/\..$/.c/} ${YHEADER:D${SRCS:M*.y:.y=.h}}
# this is known to work for NetBSD 1.6 and FreeBSD 4.2
.if ${TARGET_OSNAME} == "NetBSD" || ${TARGET_OSNAME} == "FreeBSD"
_PROGLDOPTS=
.if ${SHLINKDIR} != "/usr/libexec" # XXX: change or remove if ld.so moves
_PROGLDOPTS+= -Wl,-dynamic-linker=${_SHLINKER}
.endif
.if defined(LIBDIR) && ${SHLIBDIR} != ${LIBDIR}
_PROGLDOPTS+= -Wl,-rpath-link,${DESTDIR}${SHLIBDIR}:${DESTDIR}/usr/lib \
-L${DESTDIR}${SHLIBDIR}
.endif
_PROGLDOPTS+= -Wl,-rpath,${SHLIBDIR}:/usr/lib
.if defined(PROG_CXX)
_CCLINK= ${CXX}
_SUPCXX= -lstdc++ -lm
.endif
.endif # NetBSD
_CCLINK?= ${CC}
.if ${MK_PROG_LDORDER_MK} != "no"
${PROG}: ldorder
.include <ldorder.mk>
.endif
.if defined(DESTDIR) && exists(${LIBCRT0}) && ${LIBCRT0} != "/dev/null"
${PROG}: ${LIBCRT0} ${OBJS} ${LIBC} ${DPADD}
${_CCLINK} ${LDFLAGS} ${LDSTATIC} -o ${.TARGET} -nostdlib ${_PROGLDOPTS} -L${DESTDIR}/usr/lib ${LIBCRT0} ${LIBCRTBEGIN} ${OBJS} ${LDADD_LDORDER} ${LDADD} -L${DESTDIR}/usr/lib ${_SUPCXX} -lgcc -lc -lgcc ${LIBCRTEND}
.else
${PROG}: ${LIBCRT0} ${OBJS} ${LIBC} ${DPADD}
${_CCLINK} ${LDFLAGS} ${LDSTATIC} -o ${.TARGET} ${_PROGLDOPTS} ${OBJS} ${LDADD_LDORDER} ${LDADD}
.endif # defined(DESTDIR)
.endif # defined(OBJS) && !empty(OBJS)
.if !defined(MAN)
MAN= ${PROG}.1
.endif # !defined(MAN)
.endif # defined(PROG)
.if !defined(_SKIP_BUILD)
realbuild: ${PROG}
.endif
all: _SUBDIRUSE
.if !target(clean)
cleanprog:
rm -f a.out [Ee]rrs mklog core *.core \
${PROG} ${OBJS} ${LOBJS} ${CLEANFILES}
clean: _SUBDIRUSE cleanprog
cleandir: _SUBDIRUSE cleanprog
.else
cleandir: _SUBDIRUSE clean
.endif
.if defined(SRCS) && (!defined(MKDEP) || ${MKDEP} != autodep)
afterdepend: .depend
@(TMP=/tmp/_depend$$$$; \
sed -e 's/^\([^\.]*\).o[ ]*:/\1.o \1.ln:/' \
< .depend > $$TMP; \
mv $$TMP .depend)
.endif
.if !target(install)
.if !target(beforeinstall)
beforeinstall:
.endif
.if !target(afterinstall)
afterinstall:
.endif
.if !empty(BINOWN)
PROG_INSTALL_OWN ?= -o ${BINOWN} -g ${BINGRP}
.endif
.if !target(realinstall)
realinstall: proginstall
.endif
.if !target(proginstall)
proginstall:
.if defined(PROG)
[ -d ${DESTDIR}${BINDIR} ] || \
${INSTALL} -d ${PROG_INSTALL_OWN} -m 775 ${DESTDIR}${BINDIR}
${INSTALL} ${COPY} ${STRIP_FLAG} ${PROG_INSTALL_OWN} -m ${BINMODE} \
${PROG} ${DESTDIR}${BINDIR}/${PROG_NAME}
.endif
.if defined(HIDEGAME)
(cd ${DESTDIR}/usr/games; rm -f ${PROG}; ln -s dm ${PROG})
.endif
.endif
.include <links.mk>
install: maninstall install_links _SUBDIRUSE
install_links:
.if !empty(SYMLINKS)
@set ${SYMLINKS}; ${_SYMLINKS_SCRIPT}
.endif
.if !empty(LINKS)
@set ${LINKS}; ${_LINKS_SCRIPT}
.endif
maninstall: afterinstall
afterinstall: realinstall
install_links: realinstall
proginstall: beforeinstall
realinstall: beforeinstall
.endif
.if !target(lint)
lint: ${LOBJS}
.if defined(LOBJS) && !empty(LOBJS)
@${LINT} ${LINTFLAGS} ${LDFLAGS:M-L*} ${LOBJS} ${LDADD}
.endif
.endif
.NOPATH: ${PROG}
.if defined(OBJS) && !empty(OBJS)
.NOPATH: ${OBJS}
.endif
.if defined(FILES) || defined(FILESGROUPS)
.include <files.mk>
.endif
.if ${MK_MAN} != "no"
.include <man.mk>
.endif
.if ${MK_NLS} != "no"
.include <nls.mk>
.endif
.include <obj.mk>
.include <dep.mk>
.include <subdir.mk>
.if !empty(PROG) && ${MK_STAGING_PROG} == "yes"
STAGE_BINDIR ?= ${STAGE_OBJTOP}${BINDIR}
STAGE_DIR.prog ?= ${STAGE_BINDIR}
.if ${PROG_NAME:U${PROG}} != ${PROG}
STAGE_AS_SETS += prog
STAGE_AS_${PROG} = ${PROG_NAME}
stage_as.prog: ${PROG}
.else
STAGE_SETS += prog
stage_files.prog: ${PROG}
.endif
.endif
.include <final.mk>
.endif

View File

@ -0,0 +1,102 @@
# $Id: progs.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2006, 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
#
.MAIN: all
.if defined(PROGS)
# In meta mode, we can capture dependenices for _one_ of the progs.
# if makefile doesn't nominate one, we use the first.
.ifndef UPDATE_DEPENDFILE_PROG
UPDATE_DEPENDFILE_PROG = ${PROGS:[1]}
.export UPDATE_DEPENDFILE_PROG
.endif
.ifndef PROG
# They may have asked us to build just one
.for t in ${PROGS}
.if make($t)
PROG ?= $t
.endif
.endfor
.endif
.if defined(PROG)
# just one of many
PROG_VARS += \
BINDIR \
CFLAGS \
COPTS \
CPPFLAGS \
CXXFLAGS \
DPADD \
DPLIBS \
LDADD \
LDFLAGS \
MAN \
SRCS
.for v in ${PROG_VARS:O:u}
.if defined(${v}.${PROG}) || defined(${v}_${PROG})
$v += ${${v}_${PROG}:U${${v}.${PROG}}}
.endif
.endfor
# for meta mode, there can be only one!
.if ${PROG} == ${UPDATE_DEPENDFILE_PROG:Uno}
UPDATE_DEPENDFILE ?= yes
.endif
UPDATE_DEPENDFILE ?= NO
# ensure that we don't clobber each other's dependencies
DEPENDFILE?= .depend.${PROG}
# prog.mk will do the rest
.else
all: ${PROGS}
# We cannot capture dependencies for meta mode here
UPDATE_DEPENDFILE = NO
# nor can we safely run in parallel.
.NOTPARALLEL:
.endif
.endif
# handle being called [bsd.]progs.mk
.include <${.PARSEFILE:S,progs,prog,}>
.ifndef PROG
# tell progs.mk we might want to install things
PROGS_TARGETS+= cleandepend cleandir cleanobj depend install
.for p in ${PROGS}
.if defined(PROGS_CXX) && !empty(PROGS_CXX:M$p)
# bsd.prog.mk may need to know this
x.$p= PROG_CXX=$p
.endif
$p ${p}_p: .PHONY .MAKE
(cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} PROG=$p ${x.$p})
.for t in ${PROGS_TARGETS:O:u}
$p.$t: .PHONY .MAKE
(cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} PROG=$p ${x.$p} ${@:E})
.endfor
.endfor
.for t in ${PROGS_TARGETS:O:u}
$t: ${PROGS:%=%.$t}
.endfor
.endif

View File

@ -0,0 +1,53 @@
# $Id: rst2htm.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2009, 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
#
# convert reStructuredText to HTML, using rst2html.py from
# docutils - http://docutils.sourceforge.net/
.if empty(TXTSRCS)
TXTSRCS != 'ls' -1t ${.CURDIR}/*.txt ${.CURDIR}/*.rst 2>/dev/null; echo
.endif
RSTSRCS ?= ${TXTSRCS}
HTMFILES ?= ${RSTSRCS:R:T:O:u:%=%.htm}
RST2HTML ?= rst2html.py
RST2PDF ?= rst2pdf
RST2S5 ?= rst2s5.py
# the following will run RST2S5 if the target name contains the word 'slides'
# otherwise it uses RST2HTML
RST2HTM = ${"${.TARGET:T:M*slides*}":?${RST2S5}:${RST2HTML}}
RST2HTM_SLIDES_FLAGS ?= ${RST2S5_FLAGS}
RST2HTM_DOC_FLAGS ?= ${RST2HTML_FLAGS}
RST2HTM_FLAGS ?= ${"${.TARGET:T:M*slides*}":?${RST2HTM_SLIDES_FLAGS}:${RST2HTM_DOC_FLAGS}}
RST2PDF_FLAGS ?= ${"${.TARGET:T:M*slides*}":?${RST2PDF_SLIDES_FLAGS}:${RST2PDF_DOC_FLAGS}}
RST_SUFFIXES ?= .rst .txt
CLEANFILES += ${HTMFILES}
html: ${HTMFILES}
.SUFFIXES: ${RST_SUFFIXES} .htm .pdf
${RST_SUFFIXES:@s@$s.htm@}:
${RST2HTM} ${RST2HTM_FLAGS} ${FLAGS.${.TARGET}} ${.IMPSRC} ${.TARGET}
${RST_SUFFIXES:@s@$s.pdf@}:
${RST2PDF} ${RST2PDF_FLAGS} ${FLAGS.${.TARGET}} ${.IMPSRC} ${.TARGET}
.for s in ${RSTSRCS:O:u}
${s:R:T}.htm: $s
${s:R:T}.pdf: $s
.endfor

View File

@ -0,0 +1,91 @@
# $Id: scripts.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2006, 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
#
.include <init.mk>
SCRIPTSGROUPS ?= SCRIPTS
SCRIPTSGROUPS := ${SCRIPTSGROUPS:O:u}
SCRIPTSDIR?= ${BINDIR}
SCRIPTSOWN?= ${BINOWN}
SCRIPTSGRP?= ${BINGRP}
SCRIPTSMODE?= ${BINMODE}
SCRIPTS_INSTALL_OWN?= -o ${SCRIPTSOWN} -g ${SCRIPTSGRP}
SCRIPTS_COPY ?= -C
# how we get script name from src
SCRIPTSNAME_MOD?=T:R
.if !target(buildfiles)
.for group in ${SCRIPTSGROUPS}
buildfiles: ${${group}}
.endfor
.endif
buildfiles:
realbuild: buildfiles
.for group in ${SCRIPTSGROUPS}
.if !empty(${group}) && defined(${group}DIR)
.if ${group} != "SCRIPTS"
${group}_INSTALL_OWN ?= ${SCRIPTS_INSTALL_OWN}
.endif
# incase we are staging
STAGE_DIR.${group} ?= ${STAGE_OBJTOP}${${group}DIR}
.for script in ${${group}:O:u}
${group}_INSTALL_OWN.${script:T} ?= ${${group}_INSTALL_OWN}
${group}DIR.${script:T} ?= ${${group}DIR_${script:T}:U${${group}DIR}}
script_mkdir_list += ${${group}DIR.${script:T}}
${group}NAME.${script} ?= ${${group}NAME_${script:T}:U${script:${SCRIPTSNAME_MOD}}}
.if ${${group}NAME.${script}:T} != ${script:T}
STAGE_AS_SETS += ${group}
STAGE_AS_${script} = ${${group}NAME.${script:T}}
stage_as.${group}: ${script}
installscripts: installscripts.${group}.${script:T}
installscripts.${group}.${script:T}: ${script} script_mkdirs
${INSTALL} ${SCRIPTS_COPY} ${${group}_INSTALL_OWN.${script:T}} \
-m ${SCRIPTSMODE} ${.ALLSRC:Nscript_mkdirs} ${DESTDIR}${${group}DIR}/${${group}NAME.${script:T}}
.else
STAGE_SETS += ${group}
stage_files.${group}: ${script}
installscripts.${group}: ${script}
installscripts: installscripts.${group}
.endif
.endfor # script
installscripts.${group}: script_mkdirs
${INSTALL} ${SCRIPTS_COPY} ${${group}_INSTALL_OWN} -m ${SCRIPTSMODE} \
${.ALLSRC:Nscript_mkdirs:O:u} ${DESTDIR}${${group}DIR}
.endif # !empty
.endfor # group
script_mkdirs:
@for d in ${script_mkdir_list:O:u}; do \
test -d ${DESTDIR}$$d || \
${INSTALL} -d ${SCRIPTS_INSTALL_OWN} -m 775 ${DESTDIR}$$d; \
done
beforeinstall:
installscripts:
realinstall: installscripts
.ORDER: beforeinstall installscripts

View File

@ -0,0 +1,66 @@
# $Id: srctop.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2012, 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 !defined(SRCTOP)
# if using mk(1) SB will be set.
.ifdef SB
.if ${.CURDIR:S,${SB},,} != ${.CURDIR}
# we are actually within SB
.ifdef SB_SRC
SRCTOP:= ${SB_SRC}
.elif exists(${SB}/src)
SRCTOP:= ${SB}/src
.else
SRCTOP:= ${SB}
.endif
.endif
.endif
.if !defined(SRCTOP)
.for rd in share/mk build/mk mk
.if ${_this_mk_dir:M*${rd}} != ""
.if ${.CURDIR:S,${_this_mk_dir:${rd:C,[^/]+,H,g:S,/, ,g:ts:}},,} != ${.CURDIR}
SRCTOP:= ${_this_mk_dir:${rd:C,[^/]+,H,g:S,/, ,g:ts:}}
.endif
.endif
.endfor
.endif
.if !defined(SRCTOP)
_SRCTOP_TEST_?= [ -f ../.sandbox-env -o -d share/mk ]
# Linux at least has a bug where attempting to check an automounter
# directory will hang. So avoid looking above /a/b
SRCTOP!= cd ${.CURDIR}; while :; do \
here=`pwd`; \
${_SRCTOP_TEST_} && { echo $$here; break; }; \
case $$here in /*/*/*) cd ..;; *) echo ""; break;; esac; \
done
.endif
.if defined(SRCTOP) && exists(${SRCTOP}/.)
.export SRCTOP
.endif
.endif
.if !defined(OBJTOP) && !empty(SRCTOP)
.if defined(MAKEOBJDIRPREFIX) && exists(${MAKEOBJDIRPREFIX}${SRCTOP})
OBJTOP= ${MAKEOBJDIRPREFIX}${SRCTOP}
.elif (exists(${SRCTOP}/Makefile) || exists(${SRCTOP}/makefile))
OBJTOP!= cd ${SRCTOP} && ${PRINTOBJDIR}
.endif
.if empty(OBJTOP)
OBJTOP= ${SRCTOP}
.endif
.export OBJTOP
.endif

View File

@ -0,0 +1,98 @@
#!/bin/sh
# NAME:
# stage-install.sh - wrapper around install
#
# SYNOPSIS:
# stage-install.sh [variable="value"] "args" "dest"
#
# DESCRIPTION:
# This script is a wrapper around the normal install(1).
# Its role is to add '.dirdep' files to the destination.
# The variables we might use are:
#
# INSTALL
# Path to actual install(1), default is
# $REAL_INSTALL
#
# OBJDIR
# Path to the dir where '.dirdep' was generated,
# default is '.'
#
# _DIRDEP
# Path to actual '.dirdep' file, default is
# $OBJDIR/.dirdep
#
# The "args" and "dest" are passed as is to install(1), and if a
# '.dirdep' file exists it will be linked or copied to each
# "file".dirdep placed in "dest" or "dest".dirdep if it happed
# to be a file rather than a directory.
#
# SEE ALSO:
# meta.stage.mk
#
# RCSid:
# $Id: stage-install.sh,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2013, 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
#
INSTALL=${REAL_INSTALL:-install}
OBJDIR=.
while :
do
case "$1" in
*=*) eval "$1"; shift;;
*) break;;
esac
done
# if .dirdep doesn't exist, just run install and be done
_DIRDEP=${_DIRDEP:-$OBJDIR/.dirdep}
[ -s $_DIRDEP ] && EXEC= || EXEC=exec
$EXEC $INSTALL "$@" || exit 1
# from meta.stage.mk
LnCp() {
rm -f $2 2> /dev/null
ln $1 $2 2> /dev/null || cp -p $1 $2
}
StageDirdep() {
t=$1
if [ -s $t.dirdep ]; then
cmp -s $_DIRDEP $t.dirdep && return
echo "ERROR: $t installed by `cat $t.dirdep` not `cat $_DIRDEP`" >&2
exit 1
fi
LnCp $_DIRDEP $t.dirdep || exit 1
}
args="$@"
while [ $# -gt 8 ]
do
shift 8
done
eval dest=\$$#
if [ -f $dest ]; then
# a file, there can be only one .dirdep needed
StageDirdep $dest
elif [ -d $dest ]; then
for f in $args
do
test -f $f || continue
StageDirdep $dest/${f##*/}
done
fi

View File

@ -0,0 +1,102 @@
# $Id: subdir.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# skip missing directories...
# $NetBSD: subdir.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# @(#)bsd.subdir.mk 5.9 (Berkeley) 2/1/91
.if ${.MAKE.LEVEL} == 0 && ${.MAKE.MODE:Uno:Mmeta*} != ""
.include <meta.subdir.mk>
# keep everyone happy
_SUBDIRUSE:
.elif !commands(_SUBDIRUSE) && !defined(NO_SUBDIR) && !defined(NOSUBDIR)
.-include <${.CURDIR}/Makefile.inc>
.if !target(.MAIN)
.MAIN: all
.endif
ECHO_DIR ?= echo
.ifdef SUBDIR_MUST_EXIST
MISSING_DIR=echo "Missing ===> ${.CURDIR}/$${entry}"; exit 1
.else
MISSING_DIR=echo "Skipping ===> ${.CURDIR}/$${entry}"; continue
.endif
_SUBDIRUSE: .USE
.if defined(SUBDIR)
@Exists() { test -f $$1; }; \
for entry in ${SUBDIR}; do \
(set -e; \
if Exists ${.CURDIR}/$${entry}.${MACHINE}/[mM]akefile; then \
_newdir_="$${entry}.${MACHINE}"; \
elif Exists ${.CURDIR}/$${entry}/[mM]akefile; then \
_newdir_="$${entry}"; \
else \
${MISSING_DIR}; \
fi; \
if test X"${_THISDIR_}" = X""; then \
_nextdir_="$${_newdir_}"; \
else \
_nextdir_="$${_THISDIR_}/$${_newdir_}"; \
fi; \
${ECHO_DIR} "===> $${_nextdir_}"; \
cd ${.CURDIR}/$${_newdir_}; \
${.MAKE} _THISDIR_="$${_nextdir_}" \
${.TARGET:S/realinstall/install/:S/.depend/depend/}) || exit 1; \
done
${SUBDIR}::
@set -e; _r=${.CURDIR}/; \
if test -z "${.TARGET:M/*}"; then \
if test -d ${.CURDIR}/${.TARGET}.${MACHINE}; then \
_newdir_=${.TARGET}.${MACHINE}; \
else \
_newdir_=${.TARGET}; \
fi; \
else \
_r= _newdir_=${.TARGET}; \
fi; \
${ECHO_DIR} "===> $${_newdir_}"; \
cd $${_r}$${_newdir_}; \
${.MAKE} _THISDIR_="$${_newdir_}" all
.endif
.if !target(install)
.if !target(beforeinstall)
beforeinstall:
.endif
.if !target(afterinstall)
afterinstall:
.endif
install: maninstall
maninstall: afterinstall
afterinstall: realinstall
realinstall: beforeinstall _SUBDIRUSE
.endif
.if defined(SRCS)
etags: ${SRCS}
-cd ${.CURDIR}; etags `echo ${.ALLSRC:N*.h} | sed 's;${.CURDIR}/;;'`
.endif
SUBDIR_TARGETS += \
all \
clean \
cleandir \
includes \
depend \
lint \
obj \
tags \
etags
.for t in ${SUBDIR_TARGETS:O:u}
$t: _SUBDIRUSE
.endfor
.include <own.mk>
.if make(destroy*)
.include <obj.mk>
.endif
.endif
# make sure this exists
all:

View File

@ -0,0 +1,130 @@
# $Id: sys.clean-env.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2009, 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 makefile would normally be included by sys.env.mk
# The variables used by this makefile include:
#
# MAKE_ENV_SAVE_VAR_LIST
# The actuall list of variables from the environment that will be
# preserved.
# MAKE_ENV_SAVE_PREFIX_LIST
# A list of prefixes to match against the environment - the results
# are added to MAKE_ENV_SAVE_VAR_LIST after being filtered by...
# MAKE_ENV_SAVE_EXCLUDE_LIST
# A list of words or patterns which is turned into a list of :N
# modifiers.
.if ${.MAKE.LEVEL} == 0 && ${MAKE_VERSION} >= 20100606
# We save any env var that starts with the words in MAKE_ENV_SAVE_PREFIX_LIST.
# This gets expanded to an egrep expression like '^(A|B|C...)'
# and added to MAKE_ENV_SAVE_VAR_LIST below.
# If any of these end up being too greedy, MAKE_ENV_SAVE_EXCLUDE_LIST
# can be used to filter.
MAKE_ENV_SAVE_PREFIX_LIST += \
CCACHE \
CVS \
DEBUG \
DISTCC \
HOST \
MACHINE \
MAKE \
MK \
NEED_ \
SB_ \
SSH \
SVN \
USE_ \
WITH_ \
WITHOUT_ \
# This could be a list of vars or patterns to explicitly exclude.
MAKE_ENV_SAVE_EXCLUDE_LIST ?= _
# This is the actual list that we will save
# HOME is probably something worth clobbering eg.
# HOME=/var/empty
MAKE_ENV_SAVE_VAR_LIST += \
HOME \
LOGNAME \
OBJROOT \
OBJTOP \
PATH \
SB \
SRCTOP \
USER \
${_env_vars:${MAKE_ENV_SAVE_EXCLUDE_LIST:${M_ListToSkip}}}
_env_vars != env | egrep '^(${MAKE_ENV_SAVE_PREFIX_LIST:ts|})' | sed 's,=.*,,'; echo
_export_list =
.for v in ${MAKE_ENV_SAVE_VAR_LIST:O:u}
.if defined($v)
_export_list += $v
# Save current value
$v := ${$v}
.endif
.endfor
# Now, clobber the environment
.unexport-env
# This is a list of vars that we handle specially below
_tricky_env_vars = MAKEOBJDIR OBJTOP
# Export our selection - sans tricky ones
.export ${_export_list:${_tricky_env_vars:${M_ListToSkip}}}
# This next bit may need tweaking
# if you don't happen to like the way I set it.
.if defined(MAKEOBJDIR)
# We are going to set this to the equivalent of the shell's
# MAKEOBJDIR='${.CURDIR:S,${SRCTOP},${OBJTOP},}'
_srctop := ${SRCTOP:U${SB_SRC:U${SB}/src}}
_objroot := ${OBJROOT:U${SB_OBJROOT:U${SB}/${SB_OBJPREFIX}}}
.if ${MAKE_VERSION} < 20160218
_objtop := ${OBJTOP:U${_objroot}${MACHINE}}
# Take care of ${MACHINE}
.if ${MACHINE:Nhost*} == "" || ${OBJTOP} == ${HOST_OBJTOP:Uno}
OBJTOP = ${_objtop:S,${HOST_TARGET}$,\${MACHINE},}
.else
OBJTOP = ${_objtop:S,${MACHINE}$,\${MACHINE},}
.endif
# Export like this
MAKEOBJDIR = $${.CURDIR:S,${_srctop},$${OBJTOP},}
#.info ${MAKE_SAVE_ENV_VARS _srctop _objroot _objtop OBJTOP MAKEOBJDIR:L:@v@${.newline}$v=${$v}@}
# Export these as-is, and do not track...
# otherwise the environment will be ruined when we evaluate them below.
.export-env ${_tricky_env_vars}
# Now evaluate for ourselves
.for v in ${_tricky_env_vars}
$v := ${$v}
.endfor
.else
# we cannot use the '$$' trick, anymore
# but we can export a literal (unexpanded) value
SRCTOP := ${_srctop}
OBJROOT := ${_objroot}
OBJTOP = ${OBJROOT}${MACHINE}
MAKEOBJDIR = ${.CURDIR:S,${SRCTOP},${OBJTOP},}
.export-literal SRCTOP OBJROOT ${_tricky_env_vars}
.endif
#.info ${_tricky_env_vars:@v@${.newline}$v=${$v}@}
#showenv:
# @env | egrep 'OBJ|SRC'
.endif # MAKEOBJDIR
.endif # level 0

View File

@ -0,0 +1,33 @@
# $Id: sys.debug.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2009, 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
#
# Sometimes we want to turn on debugging in just one or two places
# if .CURDIR is matched by any entry in DEBUG_MAKE_SYS_DIRS we
# will apply DEBUG_MAKE_FLAGS now.
# if an entry in DEBUG_MAKE_DIRS matches, we at the end of sys.mk
# eg. DEBUG_MAKE_FLAGS=-dv DEBUG_MAKE_SYS_DIRS="*lib/sjg"
# use DEBUG_MAKE_FLAGS0 to apply only to .MAKE.LEVEL 0
#
.if ${.MAKE.LEVEL:U1} == 0
# we use indirection, to simplify the tests below, and incase
# DEBUG_* were given on our command line.
_DEBUG_MAKE_FLAGS = ${DEBUG_MAKE_FLAGS0}
_DEBUG_MAKE_SYS_DIRS = ${DEBUG_MAKE_SYS_DIRS0:U${DEBUG_MAKE_SYS_DIRS}}
_DEBUG_MAKE_DIRS = ${DEBUG_MAKE_DIRS0:U${DEBUG_MAKE_DIRS}}
.else
_DEBUG_MAKE_FLAGS = ${DEBUG_MAKE_FLAGS}
_DEBUG_MAKE_SYS_DIRS = ${DEBUG_MAKE_SYS_DIRS}
_DEBUG_MAKE_DIRS = ${DEBUG_MAKE_DIRS}
.endif

View File

@ -0,0 +1,59 @@
# $Id: sys.dependfile.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2012, 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 only makes sense in meta mode.
# This allows a mixture of auto generated as well as manually edited
# dependency files, which can be differentiated by their names.
# As per dirdeps.mk we only require:
# 1. a common prefix
# 2. that machine specific files end in .${MACHINE}
#
# The .MAKE.DEPENDFILE_PREFERENCE below is an example.
# 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 ?= \
${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.${MACHINE} \
${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}
# Normally the 1st entry is our default choice
# Another useful default is ${.MAKE.DEPENDFILE_PREFIX}
.MAKE.DEPENDFILE_DEFAULT ?= ${.MAKE.DEPENDFILE_PREFERENCE:[1]}
_e := ${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}
.if !empty(_e)
.MAKE.DEPENDFILE := ${_e:[1]}
.elif ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}} != "" && ${.MAKE.DEPENDFILE_DEFAULT:E} != ${MACHINE}
# MACHINE specific depend files are supported, but *not* default.
# If any already exist, we should follow suit.
_aml = ${ALL_MACHINE_LIST:Uarm amd64 i386 powerpc:N${MACHINE}} ${MACHINE}
# make sure we restore MACHINE
_m := ${MACHINE}
_e := ${_aml:@MACHINE@${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}@}
MACHINE := ${_m}
.if !empty(_e)
.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}:[1]}
.endif
.endif
.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_DEFAULT}

155
devel/bmake/files/mk/sys.mk Normal file
View File

@ -0,0 +1,155 @@
# $Id: sys.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2003-2009, 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
#
# Avoid putting anything platform specific in here.
# _DEBUG_MAKE_FLAGS etc.
.include <sys.debug.mk>
.if !empty(_DEBUG_MAKE_FLAGS)
.if ${_DEBUG_MAKE_SYS_DIRS:Uno:@x@${.CURDIR:M$x}@} != ""
.MAKEFLAGS: ${_DEBUG_MAKE_FLAGS}
.endif
.endif
# useful modifiers
.include <sys.vars.mk>
# we expect a recent bmake
.if !defined(_TARGETS)
# some things we do only once
_TARGETS := ${.TARGETS}
.-include <sys.env.mk>
.endif
# we need HOST_TARGET etc below.
.include <host-target.mk>
# early customizations
.-include <local.sys.env.mk>
# Popular suffixes for C++
CXX_SUFFIXES += .cc .cpp .cxx .C
CXX_SUFFIXES := ${CXX_SUFFIXES:O:u}
# find the OS specifics
.if defined(SYS_OS_MK)
.include <${SYS_OS_MK}>
.else
_sys_mk =
.for x in ${HOST_OSTYPE} ${HOST_TARGET} ${HOST_OS} ${MACHINE} Generic
.if empty(_sys_mk)
.-include <sys/$x.mk>
_sys_mk := ${.MAKE.MAKEFILES:M*/$x.mk}
.if !empty(_sys_mk)
_sys_mk := sys/${_sys_mk:T}
.endif
.endif
.if empty(_sys_mk)
# might be an old style
.-include <$x.sys.mk>
_sys_mk := ${.MAKE.MAKEFILES:M*/$x.sys.mk:T}
.endif
.endfor
SYS_OS_MK := ${_sys_mk}
.export SYS_OS_MK
.endif
# some options we need to know early
OPTIONS_DEFAULT_NO += \
DIRDEPS_BUILD \
DIRDEPS_CACHE
OPTIONS_DEFAULT_DEPENDENT += \
AUTO_OBJ/DIRDEPS_BUILD \
META_MODE/DIRDEPS_BUILD \
STAGING/DIRDEPS_BUILD \
.-include <options.mk>
.if ${MK_DIRDEPS_BUILD:Uno} == "yes"
MK_META_MODE = yes
.-include <meta.sys.mk>
.elif ${MK_META_MODE:Uno} == "yes"
.MAKE.MODE = meta verbose ${META_MODE}
.endif
# make sure we have a harmless value
.MAKE.MODE ?= normal
# if you want objdirs make them automatic
# and do it early before we compute .PATH
.if ${MK_AUTO_OBJ:Uno} == "yes" || ${MKOBJDIRS:Uno} == "auto"
.include <auto.obj.mk>
.endif
.if !empty(SRCTOP)
.if ${.CURDIR} == ${SRCTOP}
RELDIR = .
.elif ${.CURDIR:M${SRCTOP}/*}
RELDIR := ${.CURDIR:S,${SRCTOP}/,,}
.endif
.endif
MACHINE_ARCH.host ?= ${_HOST_ARCH}
MACHINE_ARCH.${MACHINE} ?= ${MACHINE}
.if empty(MACHINE_ARCH)
MACHINE_ARCH = ${MACHINE_ARCH.${MACHINE}}
.endif
.ifndef ROOT_GROUP
ROOT_GROUP != sed -n /:0:/s/:.*//p /etc/group
.export ROOT_GROUP
.endif
unix ?= We run ${_HOST_OSNAME}.
# We need a Bourne/POSIX shell
MAKE_SHELL ?= sh
SHELL ?= ${MAKE_SHELL}
# A race condition in mkdir, means that it can bail if another
# process made a dir that mkdir expected to.
# We repeat the mkdir -p a number of times to try and work around this.
# We stop looping as soon as the dir exists.
# If we get to the end of the loop, a plain mkdir will issue an error.
Mkdirs= Mkdirs() { \
for d in $$*; do \
for i in 1 2 3 4 5 6; do \
mkdir -p $$d; \
test -d $$d && return 0; \
done; \
mkdir $$d || exit $$?; \
done; }
# this often helps with debugging
.SUFFIXES: .cpp-out
.c.cpp-out:
@${COMPILE.c:N-c} -E ${.IMPSRC} | grep -v '^[ ]*$$'
${CXX_SUFFIXES:%=%.cpp-out}:
@${COMPILE.cc:N-c} -E ${.IMPSRC} | grep -v '^[ ]*$$'
# late customizations
.-include <local.sys.mk>
# if .CURDIR is matched by any entry in DEBUG_MAKE_DIRS we
# will apply DEBUG_MAKE_FLAGS, now.
.if !empty(_DEBUG_MAKE_FLAGS)
.if ${_DEBUG_MAKE_DIRS:Uno:@x@${.CURDIR:M$x}@} != ""
.MAKEFLAGS: ${_DEBUG_MAKE_FLAGS}
.endif
.endif

View File

@ -0,0 +1,85 @@
# $Id: sys.vars.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# @(#) Copyright (c) 2003-2009, 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
#
# We use the following paradigm for preventing multiple inclusion.
# It relies on the fact that conditionals and dependencies are resolved
# at the time they are read.
#
# _this ?= ${.PARSEFILE}
# .if !target(__${_this}__)
# __${_this}__:
#
.if ${MAKE_VERSION:U0} > 20100408
_this = ${.PARSEDIR:tA}/${.PARSEFILE}
.else
_this = ${.PARSEDIR}/${.PARSEFILE}
.endif
# if this is an ancient version of bmake
MAKE_VERSION ?= 0
.if ${MAKE_VERSION:M*make-*}
# turn it into what we want - just the date
MAKE_VERSION := ${MAKE_VERSION:[1]:C,.*-,,}
.endif
# some useful modifiers
# A useful trick for testing multiple :M's against something
# :L says to use the variable's name as its value - ie. literal
# got = ${clean* destroy:${M_ListToMatch:S,V,.TARGETS,}}
M_ListToMatch = L:@m@$${V:M$$m}@
# match against our initial targets (see above)
M_L_TARGETS = ${M_ListToMatch:S,V,_TARGETS,}
# turn a list into a set of :N modifiers
# NskipFoo = ${Foo:${M_ListToSkip}}
M_ListToSkip= O:u:S,^,N,:ts:
# type should be a builtin in any sh since about 1980,
# but sadly there are exceptions!
.if ${.MAKE.OS:Unknown:NBSD/OS} == ""
_type_sh = which
.endif
# AUTOCONF := ${autoconf:L:${M_whence}}
M_type = @x@(${_type_sh:Utype} $$x) 2> /dev/null; echo;@:sh:[0]:N* found*:[@]:C,[()],,g
M_whence = ${M_type}:M/*:[1]
# convert a path to a valid shell variable
M_P2V = tu:C,[./-],_,g
# convert path to absolute
.if ${MAKE_VERSION:U0} > 20100408
M_tA = tA
.else
M_tA = C,.*,('cd' & \&\& 'pwd') 2> /dev/null || echo &,:sh
.endif
.if ${MAKE_VERSION:U0} >= 20170130
# M_cmpv allows comparing dotted versions like 3.1.2
# ${3.1.2:L:${M_cmpv}} -> 3001002
# we use big jumps to handle 3 digits per dot:
# ${123.456.789:L:${M_cmpv}} -> 123456789
M_cmpv.units = 1 1000 1000000
M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh
.endif
# absoulte path to what we are reading.
_PARSEDIR = ${.PARSEDIR:${M_tA}}
# many projects use MAJOR MINOR PATCH versioning
# ${OPENSSL:${M_M.M.P_VERSION}} is equivalent to
# ${OPENSSL_MAJOR_VERSION}.${OPENSSL_MINOR_VERSION}.${OPENSSL_PATCH_VERSION}
M_M.M.P_VERSION = L:@v@$${MAJOR MINOR PATCH:L:@t@$${$$v_$$t_VERSION:U0}@}@:ts.

View File

@ -0,0 +1,184 @@
# $NetBSD: AIX.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# @(#)sys.mk 5.11 (Berkeley) 3/13/91
OS= AIX
unix= We run ${OS}.
ROOT_GROUP= system
# This needs a lot of work yet...
NOPIC=no # no shared libs?
.SUFFIXES: .out .a .ln .o .c ${CXX_SUFFIXES} .F .f .r .y .l .s .S .cl .p .h .sh .m4
.LIBS: .a
AR= ar
ARFLAGS= rl
RANLIB= ranlib
AS= as
AFLAGS=
COMPILE.s= ${AS} ${AFLAGS}
LINK.s= ${CC} ${AFLAGS} ${LDFLAGS}
COMPILE.S= ${CC} ${AFLAGS} ${CPPFLAGS} -c
LINK.S= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
.if exists(/usr/local/bin/gcc)
CC= gcc
DBG= -O -g
STATIC?= -static
.else
CC= cc
DBG= -g
STATIC=
.endif
CFLAGS= ${DBG}
COMPILE.c= ${CC} ${CFLAGS} ${CPPFLAGS} -c
LINK.c= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
CXX= g++
CXXFLAGS= ${CFLAGS}
COMPILE.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
LINK.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
CPP= cpp
.if defined(DESTDIR)
CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include
.endif
MK_DEP= mkdeps.sh -N
FC= f77
FFLAGS= -O
RFLAGS=
COMPILE.f= ${FC} ${FFLAGS} -c
LINK.f= ${FC} ${FFLAGS} ${LDFLAGS}
COMPILE.F= ${FC} ${FFLAGS} ${CPPFLAGS} -c
LINK.F= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
COMPILE.r= ${FC} ${FFLAGS} ${RFLAGS} -c
LINK.r= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
LEX= lex
LFLAGS=
LEX.l= ${LEX} ${LFLAGS}
LD= ld
LDFLAGS=
LINT= lint
LINTFLAGS= -chapbx
PC= pc
PFLAGS=
COMPILE.p= ${PC} ${PFLAGS} ${CPPFLAGS} -c
LINK.p= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
YACC= yacc
YFLAGS= -d
YACC.y= ${YACC} ${YFLAGS}
# C
.c:
${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.c.o:
${COMPILE.c} ${.IMPSRC}
.c.a:
${COMPILE.c} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# C++
${CXX_SUFFIXES}:
${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
${CXX_SUFFIXES:%=%.o}:
${COMPILE.cc} ${.IMPSRC}
${CXX_SUFFIXES:%=%.a}:
${COMPILE.cc} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Fortran/Ratfor
.f:
${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.f.o:
${COMPILE.f} ${.IMPSRC}
.f.a:
${COMPILE.f} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.F:
${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.F.o:
${COMPILE.F} ${.IMPSRC}
.F.a:
${COMPILE.F} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.r:
${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.r.o:
${COMPILE.r} ${.IMPSRC}
.r.a:
${COMPILE.r} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Pascal
.p:
${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.p.o:
${COMPILE.p} ${.IMPSRC}
.p.a:
${COMPILE.p} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Assembly
.s:
${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.s.o:
${COMPILE.s} -o ${.TARGET} ${.IMPSRC}
.s.a:
${COMPILE.s} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.S:
${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.S.o:
${COMPILE.S} ${.IMPSRC}
.S.a:
${COMPILE.S} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Lex
.l:
${LEX.l} ${.IMPSRC}
${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
rm -f lex.yy.c
.l.c:
${LEX.l} ${.IMPSRC}
mv lex.yy.c ${.TARGET}
.l.o:
${LEX.l} ${.IMPSRC}
${COMPILE.c} -o ${.TARGET} lex.yy.c
rm -f lex.yy.c
# Yacc
.y:
${YACC.y} ${.IMPSRC}
${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
rm -f y.tab.c
.y.c:
${YACC.y} ${.IMPSRC}
mv y.tab.c ${.TARGET}
.y.o:
${YACC.y} ${.IMPSRC}
${COMPILE.c} -o ${.TARGET} y.tab.c
rm -f y.tab.c
# Shell
.sh:
rm -f ${.TARGET}
cp ${.IMPSRC} ${.TARGET}

View File

@ -0,0 +1,222 @@
# $NetBSD: Darwin.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
# @(#)sys.mk 8.2 (Berkeley) 3/21/94
OS= Darwin
unix?= We run ${OS}.
.SUFFIXES: .out .a .ln .o .s .S .c .m ${CXX_SUFFIXES} .F .f .r .y .l .cl .p .h
.SUFFIXES: .sh .m4 .dylib
.LIBS: .a .dylib
SHLIBEXT = .dylib
HOST_LIBEXT = .dylib
DSHLIBEXT = .dylib
AR?= ar
ARFLAGS?= rl
RANLIB =
AS?= as
AFLAGS?=
COMPILE.s?= ${AS} ${AFLAGS}
LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c
LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
PIPE?= -pipe
.if exists(/usr/bin/clang)
CC?= cc ${PIPE}
CXX?= c++
.elif exists(/usr/bin/gcc)
CC?= gcc ${PIPE}
.else
CC?= cc ${PIPE}
.endif
DBG?= -O2
CFLAGS?= ${DBG}
COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
.if exists(/usr/bin/g++)
CXX?= g++
.else
CXX?= c++
.endif
CXXFLAGS?= ${CFLAGS}
COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
OBJC?= ${CC}
OBJCFLAGS?= ${CFLAGS}
COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
CPP?= cpp
NOLINT= 1
CPPFLAGS?=
MK_DEP?= mkdep
FC?= f77
FFLAGS?= -O
RFLAGS?=
COMPILE.f?= ${FC} ${FFLAGS} -c
LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
INSTALL?= install
LEX?= lex
LFLAGS?=
LEX.l?= ${LEX} ${LFLAGS}
LD?= ld
LDFLAGS?=
SHLIB_TEENY = 0
SHLIB_MINOR = 0
MKPICLIB = no
LIBEXT = .dylib
LINT?= lint
LINTFLAGS?= -chapbx
LORDER?= lorder
NM?= nm
PC?= pc
PFLAGS?=
COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
SIZE?= size
TSORT?= tsort -q
YACC?= bison -y
YFLAGS?= -d
YACC.y?= ${YACC} ${YFLAGS}
# C
.c:
${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.c.o:
${COMPILE.c} ${.IMPSRC}
.c.a:
${COMPILE.c} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# C++
${CXX_SUFFIXES}:
${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
${CXX_SUFFIXES:%=%.o}:
${COMPILE.cc} ${.IMPSRC}
${CXX_SUFFIXES:%=%.a}:
${COMPILE.cc} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Objective-C
.m:
${LINK.m} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.m.o:
${COMPILE.m} ${.IMPSRC}
.m.a:
${COMPILE.m} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Fortran/Ratfor
.f:
${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.f.o:
${COMPILE.f} ${.IMPSRC}
.f.a:
${COMPILE.f} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.F:
${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.F.o:
${COMPILE.F} ${.IMPSRC}
.F.a:
${COMPILE.F} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.r:
${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.r.o:
${COMPILE.r} ${.IMPSRC}
.r.a:
${COMPILE.r} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Pascal
.p:
${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.p.o:
${COMPILE.p} ${.IMPSRC}
.p.a:
${COMPILE.p} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Assembly
.s:
${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.s.o:
${COMPILE.s} -o ${.TARGET} ${.IMPSRC}
.s.a:
${COMPILE.s} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.S:
${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.S.o:
${COMPILE.S} ${.IMPSRC}
.S.a:
${COMPILE.S} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Lex
.l:
${LEX.l} ${.IMPSRC}
${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
rm -f lex.yy.c
.l.c:
${LEX.l} ${.IMPSRC}
mv lex.yy.c ${.TARGET}
.l.o:
${LEX.l} ${.IMPSRC}
${COMPILE.c} -o ${.TARGET} lex.yy.c
rm -f lex.yy.c
# Yacc
.y:
${YACC.y} ${.IMPSRC}
${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
rm -f y.tab.c
.y.c:
${YACC.y} ${.IMPSRC}
mv y.tab.c ${.TARGET}
.y.o:
${YACC.y} ${.IMPSRC}
${COMPILE.c} -o ${.TARGET} y.tab.c
rm -f y.tab.c
# Shell
.sh:
rm -f ${.TARGET}
cp ${.IMPSRC} ${.TARGET}

View File

@ -0,0 +1,204 @@
# $Id: Generic.mk,v 1.1.1.1 2020/05/24 05:35:53 nia Exp $
#
# some reasonable defaults
.SUFFIXES: .out .a .ln .o .s .S .c ${CXX_SUFFIXES} .F .f .r .y .l .cl .p .h
.SUFFIXES: .sh .m4
.LIBS: .a
tools = \
ar \
lorder \
ranlib \
tsort
.for t in ${tools}
${t:tu} := ${t:${M_whence}}
.endfor
# need to make sure this is set
MACHINE_ARCH.${MACHINE} ?= ${MACHINE}
.if empty(MACHINE_ARCH)
MACHINE_ARCH = ${MACHINE_ARCH.${MACHINE}}
.endif
.if !empty(TSORT)
TSORT += -q
.endif
ARFLAGS?= rl
AS?= as
AFLAGS?=
.if ${MACHINE_ARCH} == "sparc64"
AFLAGS+= -Wa,-Av9a
.endif
COMPILE.s?= ${CC} ${AFLAGS} -c
LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp
LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
CC?= cc
DBG?= -O2
CFLAGS?= ${DBG}
COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
CXX?= c++
CXXFLAGS?= ${CFLAGS}
COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
OBJC?= ${CC}
OBJCFLAGS?= ${CFLAGS}
COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
CPP?= cpp
CPPFLAGS?=
FC?= f77
FFLAGS?= -O
RFLAGS?=
COMPILE.f?= ${FC} ${FFLAGS} -c
LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
INSTALL?= install
LEX?= lex
LFLAGS?=
LEX.l?= ${LEX} ${LFLAGS}
LD?= ld
LDFLAGS?=
LINT?= lint
LINTFLAGS?= -chapbxzF
NM?= nm
PC?= pc
PFLAGS?=
COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
SIZE?= size
YACC?= yacc
YFLAGS?=
YACC.y?= ${YACC} ${YFLAGS}
# C
.c:
${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.c.o:
${COMPILE.c} ${.IMPSRC}
.c.a:
${COMPILE.c} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.c.ln:
${LINT} ${LINTFLAGS} ${CPPFLAGS:M-[IDU]*} -i ${.IMPSRC}
# C++
${CXX_SUFFIXES}:
${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
${CXX_SUFFIXES:%=%.o}:
${COMPILE.cc} ${.IMPSRC}
${CXX_SUFFIXES:%=%.a}:
${COMPILE.cc} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Fortran/Ratfor
.f:
${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.f.o:
${COMPILE.f} ${.IMPSRC}
.f.a:
${COMPILE.f} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.F:
${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.F.o:
${COMPILE.F} ${.IMPSRC}
.F.a:
${COMPILE.F} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.r:
${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.r.o:
${COMPILE.r} ${.IMPSRC}
.r.a:
${COMPILE.r} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Pascal
.p:
${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.p.o:
${COMPILE.p} ${.IMPSRC}
.p.a:
${COMPILE.p} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Assembly
.s:
${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.s.o:
${COMPILE.s} ${.IMPSRC}
.s.a:
${COMPILE.s} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
.S:
${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
.S.o:
${COMPILE.S} ${.IMPSRC}
.S.a:
${COMPILE.S} ${.IMPSRC}
${AR} ${ARFLAGS} $@ $*.o
rm -f $*.o
# Lex
.l:
${LEX.l} ${.IMPSRC}
${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
rm -f lex.yy.c
.l.c:
${LEX.l} ${.IMPSRC}
mv lex.yy.c ${.TARGET}
.l.o:
${LEX.l} ${.IMPSRC}
${COMPILE.c} -o ${.TARGET} lex.yy.c
rm -f lex.yy.c
# Yacc
.y:
${YACC.y} ${.IMPSRC}
${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
rm -f y.tab.c
.y.c:
${YACC.y} ${.IMPSRC}
mv y.tab.c ${.TARGET}
.y.o:
${YACC.y} ${.IMPSRC}
${COMPILE.c} -o ${.TARGET} y.tab.c
rm -f y.tab.c
# Shell
.sh:
rm -f ${.TARGET}
cp ${.IMPSRC} ${.TARGET}

Some files were not shown because too many files have changed in this diff Show More