Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Sep 2012 23:01:09 -0700
From:      Garrett Cooper <yanegomi@gmail.com>
To:        freebsd-hackers@freebsd.org
Cc:        "freebsd-arch@FreeBSD.org Arch" <freebsd-arch@freebsd.org>
Subject:   [CFT/RFC]: refactor bsd.prog.mk to understand multiple programs instead of a singular program
Message-ID:  <CAGH67wRkOmy7rWLkxXnT2155PuSQpwOMyu7dTAKeO1WW2dju7g@mail.gmail.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hello,
    I've been a bit busy working on porting over ATF from NetBSD, and
one of the pieces that's currently not available in FreeBSD that's
available in NetBSD is the ability to understand and compile multiple
programs. In order to do this I had to refactor bsd.prog.mk (a lot).
The attached patch is the end result so far, and I was wondering if
anyone could please review it and/or test it (outside of me doing so).
I wrote over 40 tests, but it's not exercising everything, and I would
like for someone to please review/test this out who has an interest in
NLS support (ala bsd.nls.mk) in particular. AFAICT this is the only
gap that I couldn't resolve right away (there isn't a ton of recent
documentation on how to use bsd.nls.mk).
    I'll run a micro benchmark and buildworld a few times (in
progress) with and without the change to measure the performance
effect.
    Any assistance would be much appreciated.
Thanks!
-Garrett

[-- Attachment #2 --]
--- share/mk/bsd.prog.mk	2012-09-01 14:30:15.921795554 -0700
+++ share/mk/bsd.prog.mk	2012-09-02 22:31:59.915743268 -0700
@@ -5,195 +5,277 @@
 
 .SUFFIXES: .out .o .c .cc .cpp .cxx .C .m .y .l .ln .s .S .asm
 
-# XXX The use of COPTS in modern makefiles is discouraged.
-.if defined(COPTS)
-CFLAGS+=${COPTS}
-.endif
+# Legacy knobs
+.if defined(PROG) || defined(PROG_CXX)
+. if defined(PROG)
+PROGS=		${PROG}
+. endif
+. if defined(PROG_CXX)
+PROGS=		${PROG_CXX}
+PROGS_CXX=	${PROG_CXX}
+. endif
+# Loop once to keep pattern and avoid namespace pollution
+. for _P in ${PROGS}
+.  if !defined(MAN)
+.   for sect in 1 1aout 2 3 4 5 6 7 8 9
+.    if defined(MAN${sect})
+MAN.${_P}=	${MAN${sect}}
+.    endif
+.   endfor
+.  endif # !defined(MAN)
+MAN.${_P}?=	${_P}.1
+.  if defined(NLSNAME) && !empty(NLSNAME)
+NLSNAME.${P}:=	${NLSNAME}
+.  endif
+.  if defined(PRECIOUSPROG)
+PRECIOUSPROG.${_P}=
+.  endif
+.  if defined(PROGNAME)
+PROGNAME.${_P}=	${PROGNAME}
+.  endif
+.  if defined(SRCS)
+SRCS.${_P}:=	${SRCS}
+.  endif
+. endfor
+.else # !defined(PROG) && !defined(PROG_CXX)
+. if defined(PROGS_CXX) && !empty(PROGS_CXX)
+PROGS+=		${PROGS_CXX}
+. endif
+.endif # defined(PROG) || defined(PROG_CXX)
+
+.if defined(PROGS_CXX) && !empty(PROGS_CXX)
+. for _P in ${PROGS_CXX}
+PROG_CXX.${_P}=
+. endfor
+.endif
+
+# Avoid recursive variables. It shouldn't be used this way with ${PROGS} either
+.undef NLSNAME
+
+# Setup global CFLAGS, CXXFLAGS, and LDFLAGS
+CFLAGS?=
+CXXFLAGS?=
+DPADD?=
+LDADD?=
+LDFLAGS?=
 
-.if ${MK_ASSERT_DEBUG} == "no"
-CFLAGS+= -DNDEBUG
-NO_WERROR=
+.if defined(COPTS)
+CFLAGS+=	${COPTS}
 .endif
 
 .if defined(DEBUG_FLAGS)
-CFLAGS+=${DEBUG_FLAGS}
-CXXFLAGS+=${DEBUG_FLAGS}
-
-.if ${MK_CTF} != "no" && ${DEBUG_FLAGS:M-g} != ""
-CTFFLAGS+= -g
-.endif
+. if ${MK_CTF} != "no" && ${DEBUG_FLAGS:M-g} != ""
+CTFFLAGS+=	-g
+. endif
+CFLAGS+=	-DNDEBUG
+CFLAGS+=	${DEBUG_FLAGS}
+CXXFLAGS+=	${DEBUG_FLAGS}
 .endif
 
-.if defined(CRUNCH_CFLAGS)
-CFLAGS+=${CRUNCH_CFLAGS}
-.endif
+STRIP?=		-s
 
-.if !defined(DEBUG_FLAGS)
-STRIP?=	-s
-.endif
-
-.if defined(NO_SHARED) && (${NO_SHARED} != "no" && ${NO_SHARED} != "NO")
-LDFLAGS+= -static
-.endif
-
-.if defined(PROG_CXX)
-PROG=	${PROG_CXX}
-.endif
-
-.if defined(PROG)
-.if defined(SRCS)
-
-OBJS+=  ${SRCS:N*.h:R:S/$/.o/g}
-
-.if target(beforelinking)
-${PROG}: ${OBJS} beforelinking
-.else
-${PROG}: ${OBJS}
-.endif
-.if defined(PROG_CXX)
-	${CXX} ${CXXFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LDADD}
-.else
-	${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LDADD}
-.endif
-.if ${MK_CTF} != "no"
-	${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${OBJS}
+.if ${MK_ASSERT_DEBUG} == "no"
+CFLAGS+=	-DNDEBUG
+NO_WERROR=
 .endif
 
-.else	# !defined(SRCS)
+.for _P in ${PROGS}
 
-.if !target(${PROG})
-.if defined(PROG_CXX)
-SRCS=	${PROG}.cc
-.else
-SRCS=	${PROG}.c
-.endif
+CFLAGS.${_P}	?=
+CXXFLAGS.${_P}	?=
+LDFLAGS.${_P}	?=
+. if !defined(NLSDIR.${_P})
+NLSDIR.${_P}:=	${NLSDIR}
+. endif
+. undef NLSDIR
+
+. if (defined(NO_SHARED) && ${NO_SHARED} != "no") || (defined(NO_SHARED.${_P}) && ${NO_SHARED.${_P}} != "no")
+LDFLAGS.${_P}+= -static
+. endif
+
+. if defined(SRCS.${_P})
+
+OBJS.${_P}=	${SRCS.${_P}:N*.h:R:S/$/.o/g}
+
+.  if target(beforelinking)
+${_P}: ${OBJS.${_P}} beforelinking
+.  else
+${_P}: ${OBJS.${_P}}
+.  endif
+.  if defined(PROG_CXX.${_P})
+	${CXX} ${CXXFLAGS} ${CXXFLAGS.${_P}} ${LDFLAGS} ${LDFLAGS.${_P}} -o ${.TARGET} ${OBJS.${_P}} ${LDADD} ${LDADD.${_P}}
+.  else
+	${CC} ${CFLAGS} ${CFLAGS.${_P}} ${LDFLAGS} ${LDFLAGS.${_P}} -o ${.TARGET} ${OBJS.${_P}} ${LDADD} ${LDADD.${_P}}
+.  endif
+.  if ${MK_CTF} != "no"
+	${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${OBJS.${_P}}
+.  endif
+
+. else # !defined(SRCS.${_P})
+
+.  if !target(${_P})
+.   if defined(PROG_CXX.${_P})
+SRCS.${_P}?=	${_P}.cc
+.   else
+SRCS.${_P}?=	${_P}.c
+.   endif
 
 # Always make an intermediate object file because:
 # - it saves time rebuilding when only the library has changed
 # - the name of the object gets put into the executable symbol table instead of
 #   the name of a variable temporary object.
 # - it's useful to keep objects around for crunching.
-OBJS=	${PROG}.o
+OBJS.${_P}=	${_P}.o
 
-.if target(beforelinking)
-${PROG}: ${OBJS} beforelinking
-.else
-${PROG}: ${OBJS}
-.endif
-.if defined(PROG_CXX)
-	${CXX} ${CXXFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LDADD}
-.else
-	${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LDADD}
-.endif
-.if ${MK_CTF} != "no"
-	${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${OBJS}
-.endif
-.endif
+.   if target(beforelinking)
+${_P}: ${OBJS.${_P}} beforelinking
+.   else
+${_P}: ${OBJS.${_P}}
+.   endif # target(beforelinking)
+.   if defined(PROG_CXX.${_P})
+	${CXX} ${CXXFLAGS} ${CXXFLAGS.${_P}} ${LDFLAGS} ${LDFLAGS.${_P}} -o ${.TARGET} ${OBJS.${_P}} ${LDADD} ${LDADD.${_P}}
+.   else
+	${CC} ${CFLAGS} ${CFLAGS.${_P}} ${LDFLAGS} ${LDFLAGS.${_P}} -o ${.TARGET} ${OBJS.${_P}} ${LDADD} ${LDADD.${_P}}
+.   endif
+.   if ${MK_CTF} != "no"
+	${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${OBJS.${_P}}
+.   endif
+
+.  endif # !target(${_P})
+
+. endif # defined(SRCS.${_P})
+
+# Needed in bsd.dep.mk .
+. if !empty(SRCS.${_P})
+SRCS+=	${SRCS.${_P}}
+. endif
 
-.endif
+CLEANFILES+= 	${OBJS.${_P}}
 
-.if	${MK_MAN} != "no" && !defined(MAN) && \
-	!defined(MAN1) && !defined(MAN2) && !defined(MAN3) && \
-	!defined(MAN4) && !defined(MAN5) && !defined(MAN6) && \
-	!defined(MAN7) && !defined(MAN8) && !defined(MAN9) && \
-	!defined(MAN1aout)
-MAN=	${PROG}.1
-MAN1=	${MAN}
-.endif
-.endif
+.endfor # for _P in ${PROGS}
+
+all: objwarn ${PROGS} ${SCRIPTS}
 
-all: objwarn ${PROG} ${SCRIPTS}
 .if ${MK_MAN} != "no"
+. for _P in ${PROGS}
+.  if defined(MAN.${_P})
+MAN+=	${MAN.${_P}}
+.  endif
+. endfor
 all: _manpages
 .endif
 
-.if defined(PROG)
-CLEANFILES+= ${PROG}
-.endif
-
-.if defined(OBJS)
-CLEANFILES+= ${OBJS}
-.endif
+CLEANFILES+= ${PROGS}
 
 .include <bsd.libnames.mk>
 
-.if defined(PROG)
 _EXTRADEPEND:
-.if defined(LDFLAGS) && !empty(LDFLAGS:M-nostdlib)
-.if defined(DPADD) && !empty(DPADD)
-	echo ${PROG}: ${DPADD} >> ${DEPENDFILE}
-.endif
-.else
-	echo ${PROG}: ${LIBC} ${DPADD} >> ${DEPENDFILE}
-.if defined(PROG_CXX)
-.if !empty(CXXFLAGS:M-stdlib=libc++)
-	echo ${PROG}: ${LIBCPLUSPLUS} >> ${DEPENDFILE}
-.else
-	echo ${PROG}: ${LIBSTDCPLUSPLUS} >> ${DEPENDFILE}
-.endif
-.endif
-.endif
-.endif
+.for _P in ${PROGS}
+. if !empty(LDFLAGS:M-nostdlib) || (defined(LDFLAGS.${_P}) && !empty(LDFLAGS.${_P}:M-nostdlib))
+	echo ${_P}: ${DPADD} ${DPADD.${_P}} >> ${DEPENDFILE}
+. else
+	echo ${_P}: ${LIBC} ${DPADD} ${DPADD.${_P}} >> ${DEPENDFILE}
+.  if defined(PROG_CXX.${_P})
+.   if !empty(CXXFLAGS:M-stdlib=libc++) || !empty(CXXFLAGS.${_P}:M-stdlib=libc++)
+	echo ${_P}: ${LIBCPLUSPLUS} >> ${DEPENDFILE}
+.   else
+	echo ${_P}: ${LIBSTDCPLUSPLUS} >> ${DEPENDFILE}
+.   endif
+.  endif
+. endif
+.endfor
 
-.if !target(install)
+.for _P in ${PROGS}
+INSTALLFLAGS.${_P}?= ${INSTALLFLAGS}
 
-.if defined(PRECIOUSPROG)
-.if !defined(NO_FSCHG)
-INSTALLFLAGS+= -fschg
-.endif
-INSTALLFLAGS+= -S
-.endif
+. if !target(install)
+.  if defined(PRECIOUSPROG.${_P})
+.   if !defined(NO_FSCHG) && !defined(NO_FSCHG.${_P})
+INSTALLFLAGS.${_P}+= -fschg
+.   endif
+INSTALLFLAGS.${_P}+= -S
+.  endif
+. endif
+
+BINDIR.${_P}?=		${BINDIR}
+BINGRP.${_P}?=		${BINGRP}
+BINMODE.${_P}?=		${BINMODE}
+BINOWN.${_P}?=		${BINOWN}
 
-_INSTALLFLAGS:=	${INSTALLFLAGS}
-.for ie in ${INSTALLFLAGS_EDIT}
-_INSTALLFLAGS:=	${_INSTALLFLAGS${ie}}
 .endfor
 
-.if !target(realinstall) && !defined(INTERNALPROG)
-realinstall: _proginstall
-.ORDER: beforeinstall _proginstall
-_proginstall:
-.if defined(PROG)
-.if defined(PROGNAME)
-	${INSTALL} ${STRIP} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
-	    ${_INSTALLFLAGS} ${PROG} ${DESTDIR}${BINDIR}/${PROGNAME}
-.else
-	${INSTALL} ${STRIP} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
-	    ${_INSTALLFLAGS} ${PROG} ${DESTDIR}${BINDIR}
-.endif
-.endif
-.endif	# !target(realinstall)
-
-.if defined(SCRIPTS) && !empty(SCRIPTS)
-realinstall: _scriptsinstall
-.ORDER: beforeinstall _scriptsinstall
-
-SCRIPTSDIR?=	${BINDIR}
-SCRIPTSOWN?=	${BINOWN}
-SCRIPTSGRP?=	${BINGRP}
-SCRIPTSMODE?=	${BINMODE}
-
-.for script in ${SCRIPTS}
-.if defined(SCRIPTSNAME)
-SCRIPTSNAME_${script:T}?=	${SCRIPTSNAME}
-.else
-SCRIPTSNAME_${script:T}?=	${script:T:R}
-.endif
-SCRIPTSDIR_${script:T}?=	${SCRIPTSDIR}
-SCRIPTSOWN_${script:T}?=	${SCRIPTSOWN}
-SCRIPTSGRP_${script:T}?=	${SCRIPTSGRP}
-SCRIPTSMODE_${script:T}?=	${SCRIPTSMODE}
-_scriptsinstall: _SCRIPTSINS_${script:T}
-_SCRIPTSINS_${script:T}: ${script}
+.if !target(install)
+
+. for _P in ${PROGS}
+
+.  if !defined(INTERNALPROG.${_P})
+
+.ORDER: beforeinstall _proginstall.${_P}
+_proginstall.${_P}:
+.   if defined(PROGNAME.${_P})
+	${INSTALL} ${STRIP} -o ${BINOWN.${_P}} -g ${BINGRP.${_P}} \
+	    -m ${BINMODE.${_P}} ${INSTALLFLAGS.${_P}} ${_P} \
+	    ${DESTDIR}${BINDIR.${_P}}/${PROGNAME.${_P}}
+.   else
+	${INSTALL} ${STRIP} -o ${BINOWN.${_P}} -g ${BINGRP.${_P}} \
+	    -m ${BINMODE.${_P}} ${INSTALLFLAGS.${_P}} ${_P} \
+	    ${DESTDIR}${BINDIR.${_P}}
+.   endif 
+
+realinstall: _proginstall.${_P}
+
+.  endif # !defined(INTERNALPROG.${_P})
+
+. endfor # for _P in ${PROGS}
+
+. if defined(SCRIPTS) && !empty(SCRIPTS)
+SCRIPTSDIR?=		${BINDIR}
+SCRIPTSOWN?=		${BINOWN}
+SCRIPTSGRP?=		${BINGRP}
+SCRIPTSMODE?=		${BINMODE}
+
+__scriptsinstall: .USE
 	${INSTALL} -o ${SCRIPTSOWN_${.ALLSRC:T}} \
-	    -g ${SCRIPTSGRP_${.ALLSRC:T}} -m ${SCRIPTSMODE_${.ALLSRC:T}} \
+	    -g ${SCRIPTSGRP_${.ALLSRC:T}} \
+	    -m ${SCRIPTSMODE_${.ALLSRC:T}} \
 	    ${.ALLSRC} \
-	    ${DESTDIR}${SCRIPTSDIR_${.ALLSRC:T}}/${SCRIPTSNAME_${.ALLSRC:T}}
-.endfor
-.endif
+	    ${.TARGET}
+
+.  for S in ${SCRIPTS}
+
+realinstall: scriptsinstall
+.ORDER: beforeinstall scriptsinstall
 
-NLSNAME?=	${PROG}
+.   if defined(SCRIPTSNAME)
+SCRIPTSNAME_${S}?=	${SCRIPTSNAME}
+.   else
+SCRIPTSNAME_${S}?=	${S:T:R}
+.   endif
+
+SCRIPTSDIR_${S}?=	${SCRIPTSDIR}
+SCRIPTSOWN_${S}?=	${SCRIPTSOWN}
+SCRIPTSGRP_${S}?=	${SCRIPTSGRP}
+SCRIPTSMODE_${S}?=	${SCRIPTSMODE}
+
+scriptsinstall: ${DESTDIR}${SCRIPTSDIR_${S}}/${SCRIPTSNAME_${S}}
+
+${DESTDIR}${SCRIPTSDIR_${S}}/${SCRIPTSNAME_${S}}: __scriptsinstall ${S}
+
+.  endfor # for S in ${SCRIPTS}
+
+. endif # defined(SCRIPTS) && !empty(SCRIPTS)
+
+.endif # !target(install)
+
+# Wrap bsd.nls.mk because I can't force that Makefile snippet to work only with
+# ${PROGS}.
+.for _P in ${PROGS}
+NLSNAME.${_P}?=	${_P}
+NLS:=		${NLS.${_P}}
+NLSDIR:=	${NLSDIR.${_P}}
+NLSNAME:=	${NLSNAME.${_P}}
 .include <bsd.nls.mk>
+.endfor
 
 .include <bsd.files.mk>
 .include <bsd.incs.mk>
@@ -202,25 +284,32 @@
 .if ${MK_MAN} != "no"
 realinstall: _maninstall
 .ORDER: beforeinstall _maninstall
-.endif
 
+.include <bsd.man.mk>
 .endif
 
 .if !target(lint)
-lint: ${SRCS:M*.c}
-.if defined(PROG)
-	${LINT} ${LINTFLAGS} ${CFLAGS:M-[DIU]*} ${.ALLSRC}
-.endif
-.endif
+. for _P in ${PROGS}
+.  if !target(lint.${_P})
+.   if defined(PROG_CXX.${_P})
+lint.${_P}:
+.   else
+lint.${_P}: ${SRCS.${_P}:M*.c}
+	${LINT} ${LINTFLAGS} ${CFLAGS:M-[DIU]*} ${CFLAGS.${_P}:M-[DIU]*} ${.ALLSRC}
+.   endif
+.  endif
 
-.if ${MK_MAN} != "no"
-.include <bsd.man.mk>
-.endif
+lint: lint.${_P}
+
+. endfor
+.endif # !target(lint)
 
 .include <bsd.dep.mk>
 
-.if defined(PROG) && !exists(${.OBJDIR}/${DEPENDFILE})
-${OBJS}: ${SRCS:M*.h}
+.if !exists(${.OBJDIR}/${DEPENDFILE})
+. for _P in ${PROGS}
+${OBJS.${_P}}: ${SRCS.${_P}:M*.h}
+. endfor
 .endif
 
 .include <bsd.obj.mk>
--- /usr/src/share/mk/bsd.README	2012-05-20 15:37:40.893092501 -0700
+++ share/mk/bsd.README	2012-09-02 22:25:48.410745161 -0700
@@ -1,5 +1,5 @@
 #	@(#)bsd.README	8.2 (Berkeley) 4/2/94
-# $FreeBSD: stable/9/share/mk/bsd.README 235534 2012-05-17 07:59:15Z jlh $
+# $FreeBSD: src/share/mk/bsd.README,v 1.37 2012/05/24 20:00:58 marcel Exp $
 
 This is the README file for the "include" files for the FreeBSD
 source tree.  The files are installed in /usr/share/mk, and are by
@@ -207,98 +207,157 @@
 
 It sets/uses the following variables:
 
-BINGRP		Binary group.
+Variables global to all programs:
 
-BINOWN		Binary owner.
+CLEANFILES		Additional files to remove and
+CLEANDIRS		additional directories to remove during clean and cleandir
+			targets.  "rm -f" and "rm -rf" used respectively.
+
+DEBUG_FLAGS		debugging specific CFLAGS/LDFLAGS; if set any binaries
+ 			produced will not be stripped.  See also: WITH_CTF
+
+FILES			A list of non-executable files.
+			The installation is controlled by the FILESNAME, FILESOWN,
+			FILESGRP, FILESMODE, FILESDIR variables that can be
+			further specialized by FILES<VAR>_<file>.
+
+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:
 
-BINMODE		Binary mode.
+			LINKS=	${DESTDIR}/bin/test ${DESTDIR}/bin/[
 
-CLEANFILES	Additional files to remove and
-CLEANDIRS	additional directories to remove during clean and cleandir
-		targets.  "rm -f" and "rm -rf" used respectively.
+PROG			The name of the program to build.  If not supplied,
+			nothing is built.
 
-CFLAGS		Flags to the compiler when creating C objects.
+PROG_CXX		If defined, the name of the C++ program to build.  Also
+			causes <bsd.prog.mk> to link the program with the
+			standard C++ library.  PROG_CXX overrides the value
+			of PROG if PROG is also set.
 
-FILES		A list of non-executable files.
-		The installation is controlled by the FILESNAME, FILESOWN,
-		FILESGRP, FILESMODE, FILESDIR variables that can be
-		further specialized by FILES<VAR>_<file>.
+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.
 
-LDADD		Additional loader objects.  Usually used for libraries.
-		For example, to load with the compatibility and utility
-		libraries, use:
+SUBDIR			A list of subdirectories that should be built as well.
+			Each of the targets will execute the same target in the
+			subdirectories.
 
-			LDFILES=-lutil -lcompat
+The following variables can be tuned for specific program use (you will need
+to suffix variable declarations with .${PROG}, e.g. PROG= foo -> SRCS.foo):
 
-LDFLAGS		Additional loader flags.
+BINDIR			Binary directory.
 
-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:
+BINGRP			Binary group.
 
-			LINKS=	${DESTDIR}/bin/test ${DESTDIR}/bin/[
+BINOWN			Binary owner.
+
+BINMODE			Binary mode.
+
+CFLAGS			Flags to the compiler when creating C objects.
+
+DPADD			Additional dependencies for the program.  Usually used
+			for libraries.  For example, to depend on the
+			compatibility and utility libraries use:
+
+				DPADD=${LIBCOMPAT} ${LIBUTIL}
+
+			There is a predefined identifier for each
+			(non-profiled, non-shared) library and object.  Library
+			file names are transformed to identifiers by removing
+			the extension and converting to upper case.
+
+			There are no special identifiers for profiled or shared
+			libraries or objects.  The identifiers for the standard
+			libraries are used in DPADD.  This works correctly iff
+			all the libraries are built at the same time.
+			Unfortunately, it causes unnecessary relinks to shared
+			libraries when only the static libraries have changed.
+			Dependencies on shared libraries should be only on the
+			library version numbers.
+
+INSTALLFLAGS		install(1) flags.
+
+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.
+
+MAN			Manual pages (should end in .1 - .9).  If no MAN
+			variable is defined, "MAN=<PROG>.1" is assumed.
+
+NO_FSCHG		Do not call install(1) with -f schg.
+
+PRECIOUSPROG		Install with -S (safe copy) and handle NO_FSCHG
+			variable case as well.
+
+PROG_CXX		C++ application name(s); the sources for the
+			application(s) are compiled via ${CXX}
+
+PROGNAME		The name that the above program will be installed, if
+			different from <PROG>.
+
+SRCS			List of source files to build the program.  If SRCS is
+			not defined, it's assumed to be ${PROG}.c or, if
+			PROG_CXX is defined, ${PROG_CXX}.cc.
+
+SCRIPTS			A list of interpreter scripts [file.{sh,csh,pl,awk,...}].
+			The installation is controlled by the SCRIPTSNAME, SCRIPTSOWN,
+			SCRIPTSGRP, SCRIPTSMODE, SCRIPTSDIR variables that can be
+			further specialized by SCRIPTS<VAR>_<script>.
+
+The following variables can be tuned for specific scripts; you will need
+to suffix variable declarations with _<SCRIPT>, e.g.
+SCRIPT -> foo, -> SCRIPTDIR_foo.  In all cases, the per-script variables
+default to the equivalent global SCRIPT* variable and fallback to the
+BIN* equivalents, e.g. SCRIPTDIR_foo falls back to SCRIPTDIR if SCRIPTDIR_foo
+is not defined, then BINDIR if SCRIPTDIR is not defined:
+
+SCRIPTSDIR		Directory to install a script to.
+
+SCRIPTGRP		Group to set for a script.
+
+SCRIPTMODE		Mode to apply to a script.
 
-MAN		Manual pages (should end in .1 - .9).  If no MAN variable
-		is defined, "MAN=${PROG}.1" is assumed.
+SCRIPTOWN		Owner to set for a script.
 
-PROG		The name of the program to build.  If not supplied, nothing
-		is built.
+Legacy variables are as follows:
 
-PROG_CXX	If defined, the name of the program to build.  Also
-		causes <bsd.prog.mk> to link the program with the
-		standard C++ library.  PROG_CXX overrides the value
-		of PROG if PROG is also set.
-
-PROGNAME	The name that the above program will be installed as, if
-		different from ${PROG}.
-
-SRCS		List of source files to build the program.  If SRCS is not
-		defined, it's assumed to be ${PROG}.c or, if PROG_CXX is
-		defined, ${PROG_CXX}.cc.
-
-DPADD		Additional dependencies for the program.  Usually used for
-		libraries.  For example, to depend on the compatibility and
-		utility libraries use:
-
-			SRCLIB=${LIBCOMPAT} ${LIBUTIL}
-
-		There is a predefined identifier for each (non-profiled,
-		non-shared) library and object.  Library file names are
-		transformed to identifiers by removing the extension and
-		converting to upper case.
-
-		There are no special identifiers for profiled or shared
-		libraries or objects.  The identifiers for the standard
-		libraries are used in DPADD.  This works correctly iff all
-		the libraries are built at the same time.  Unfortunately,
-		it causes unnecessary relinks to shared libraries when
-		only the static libraries have changed.  Dependencies on
-		shared libraries should be only on the library version
-		numbers.
-
-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 nob.
-
-SUBDIR		A list of subdirectories that should be built as well.
-		Each of the targets will execute the same target in the
-		subdirectories.
-
-SCRIPTS		A list of interpreter scripts [file.{sh,csh,pl,awk,...}].
-		The installation is controlled by the SCRIPTSNAME, SCRIPTSOWN,
-		SCRIPTSGRP, SCRIPTSMODE, SCRIPTSDIR variables that can be
-		further specialized by SCRIPTS<VAR>_<script>.
+COPTS			Optimization flags appended to CFLAGS; highly
+ 			discouraged in modern Makefiles.
+
+PROG			Legacy form of `PROGS`
+
+PROG_CXX		Legacy form of `PROGS_CXX`
+
+The following variables are wrapped to be made `PROGS aware`:
+
+NLS			See bsd.nls.mk description for more details.
+NLSDIR
+NLSNAME
+
+Developer convenience variables:
+
+WITH_ASSERT_DEBUG	Compile with CFLAGS+=-DNDEBUG
 
 The include file <bsd.prog.mk> includes the file named "../Makefile.inc"
-if it exists, as well as the include file <bsd.man.mk>.
+if it exists, as well as the include file <bsd.man.mk>.  Furthermore, if
+WITH_NLS is defined and NLS.<PROG> is also defined, then bsd.nls.mk is
+included as well.
 
 Some simple examples:
 
+1. Single C Program:
+
 To build foo from foo.c with a manual page foo.1, use:
 
-	PROG=	foo
+	PROGS=	foo
 
 	.include <bsd.prog.mk>
 
@@ -314,6 +373,34 @@
 
 	SRCS=	a.c b.c c.c d.c
 
+2. Single C++ Program:
+
+To build bar with bar.cc with a manpage page bar.1, use:
+
+	PROGS_CXX=	bar
+
+	.include <bsd.prog.mk>
+
+All other constructs are the same as in the Single C Program case.
+
+3. Multiple C programs:
+
+To build foo from foo.c and bar with bar.c, use:
+
+	PROGS=	foo bar
+
+	.include <bsd.prog.mk>
+
+To build foo from bar.c and bar with foo.c, use:
+
+	PROGS=	foo bar
+
+	SRCS.foo= bar.c
+
+	SRCS.bar= foo.c
+
+	.include <bsd.prog.mk>
+
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
 The include file <bsd.subdir.mk> contains the default targets for building

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAGH67wRkOmy7rWLkxXnT2155PuSQpwOMyu7dTAKeO1WW2dju7g>