Index: head/CHANGES =================================================================== --- head/CHANGES +++ head/CHANGES @@ -10,6 +10,33 @@ All ports committers are allowed to commit to this file. +20171130: +AUTHOR: mat@FreeBSD.org + + Flavors are a way to have multiple variations of a port. The port is built + multiple times, with the variations. To declare flavors, set the FLAVORS + variable to the flavors you want defined. The first flavor will be the + default: + + FLAVORS= flavor1 flavor2 + + The flavors MUST be lowercase, and can contain [[:lower:][:digit:]_]. + + Then, when building the port, pass the FLAVOR as an argument after make to + select the flavor. + + $ make install FLAVOR=flavor2 + + In the port, you can then change the behavior depending on the value of the + FLAVOR variable. Note that the different flavors MUST have different + PKGNAMEs. Be sure to guard against an empty FLAVOR variable by using + ${FLAVOR:U}: + + .if ${FLAVOR:U} == flavor2 + PKGNAMESUFFIX= -foo + OPTIONS_DEFAULT+= FOO + .endif + 20171020: AUTHOR: ak@FreeBSD.org Index: head/Mk/Scripts/qa.sh =================================================================== --- head/Mk/Scripts/qa.sh +++ head/Mk/Scripts/qa.sh @@ -841,9 +841,26 @@ return $rc } +flavors() +{ + local rc pkgnames uniques + rc=0 + if [ -n "${FLAVOR}" ]; then + pkgnames=$(make -C "${CURDIR}" flavors-package-names|sort) + uniques=$(echo "${pkgnames}"|uniq) + if [ "$pkgnames" != "${uniques}" ]; then + err "Package names are not uniques with flavors:" + make -C "${CURDIR}" pretty-flavors-package-names >&2 + err "maybe use _PKGNAMEPREFIX/SUFFIX". + rc=1 + fi + fi + return ${rc} +} + checks="shebang symlinks paths stripped desktopfileutils sharedmimeinfo" checks="$checks suidfiles libtool libperl prefixvar baselibs terminfo" -checks="$checks proxydeps sonames perlcore no_arch gemdeps" +checks="$checks proxydeps sonames perlcore no_arch gemdeps flavors" ret=0 cd ${STAGEDIR} Index: head/Mk/bsd.port.mk =================================================================== --- head/Mk/bsd.port.mk +++ head/Mk/bsd.port.mk @@ -1065,8 +1065,7 @@ .if !defined(_FLAVOR) _FLAVOR:= ${FLAVOR} .endif -# XXX: We have no real FLAVORS support in ports or tools yet. -#PORTS_FEATURES+= FLAVORS +PORTS_FEATURES+= FLAVORS MINIMAL_PKG_VERSION= 1.6.0 _PORTS_DIRECTORIES+= ${PKG_DBDIR} ${PREFIX} ${WRKDIR} ${EXTRACT_WRKDIR} \ @@ -1082,18 +1081,6 @@ .include "${PORTSDIR}/Mk/bsd.commands.mk" -.if !empty(FLAVOR) -. if empty(FLAVORS) -IGNORE= FLAVOR is defined while this port does not have FLAVORS. -. elif ! ${FLAVORS:M${FLAVOR}} -IGNORE= Unknown flavor '${FLAVOR}', possible flavors: ${FLAVORS}. -. endif -.endif - -.if !empty(FLAVORS) && empty(FLAVOR) -FLAVOR= ${FLAVORS:[1]} -.endif - # Do not leak flavors to childs make .MAKEOVERRIDES:= ${MAKEOVERRIDES:NFLAVOR=*} @@ -1470,6 +1457,32 @@ .include "${USESDIR}/${f:C/\:.*//}.mk" .endfor +.if !empty(FLAVORS) +. if ${FLAVORS:Mall} +DEV_ERROR+= "FLAVORS cannot contain 'all', it is a reserved value" +. endif +. for f in ${FLAVORS} +. if ${f:C/[[:lower:][:digit:]_]//g} +_BAD_FLAVOR_NAMES+= ${f} +. endif +. endfor +. if !empty(_BAD_FLAVOR_NAMES) +DEV_ERROR+= "FLAVORS contains flavors that are not all [a-z0-9_]: ${_BAD_FLAVOR_NAMES}" +. endif +.endif + +.if !empty(FLAVOR) +. if empty(FLAVORS) +IGNORE= FLAVOR is defined (to ${FLAVOR}) while this port does not have FLAVORS. +. elif ! ${FLAVORS:M${FLAVOR}} +IGNORE= Unknown flavor '${FLAVOR}', possible flavors: ${FLAVORS}. +. endif +.endif + +.if !empty(FLAVORS) && empty(FLAVOR) +FLAVOR= ${FLAVORS:[1]} +.endif + EXTRACT_SUFX?= .tar.gz .if defined(USE_LINUX_PREFIX) @@ -1562,6 +1575,9 @@ LOCALBASE=${LOCALBASE} \ "STRIP=${STRIP}" \ TMPPLIST=${TMPPLIST} \ + CURDIR='${.CURDIR}' \ + FLAVOR=${FLAVOR} \ + FLAVORS='${FLAVORS}' \ BUNDLE_LIBS=${BUNDLE_LIBS} \ LDCONFIG_DIR="${LDCONFIG_DIR}" \ PKGORIGIN=${PKGORIGIN} \ @@ -4025,11 +4041,17 @@ fetch-specials: @${ECHO_MSG} "===> Fetching all distfiles required by ${PKGNAME} for building" @for dir in ${_DEPEND_SPECIALS}; do \ + case $${dir} in \ + *@*) \ + flavor=$${dir#*@}; \ + dir=$${dir%@*}; \ + ;; \ + esac; \ case $$dir in \ /*) ;; \ *) dir=${PORTSDIR}/$$dir ;; \ esac; \ - (cd $$dir; ${MAKE} fetch); \ + (cd $$dir; ${MAKE} FLAVOR=$${flavor} fetch); \ done .endif @@ -4323,6 +4345,7 @@ INDEX_OUT=/dev/stdout . endif +. if empty(FLAVORS) || defined(_DESCRIBE_WITH_FLAVOR) describe: @(${ECHO_CMD} -n "${PKGNAME}|${.CURDIR}|${PREFIX}|"; \ ${ECHO_CMD} -n ${COMMENT:Q}; \ @@ -4337,6 +4360,13 @@ ;; \ esac; \ done < ${DESCR}; ${ECHO_CMD}) >>${INDEX_OUT} +. else # empty(FLAVORS) +describe: ${FLAVORS:S/^/describe-/} +. for f in ${FLAVORS} +describe-${f}: + @cd ${.CURDIR} && ${MAKE} -B FLAVOR=${f} -D_DESCRIBE_WITH_FLAVOR describe +. endfor +. endif # empty(FLAVORS) . endif www-site: @@ -4616,6 +4646,25 @@ .if !defined(DEVELOPER) @${ECHO_MSG} "/!\\ To run stage-qa automatically add DEVELOPER=yes to your environment /!\\" .endif +.endif + +pretty-flavors-package-names: .PHONY +.if empty(FLAVORS) + @${ECHO_CMD} "no flavor: ${PKGNAME}" +.else +.for f in ${FLAVORS} + @${ECHO_CMD} -n "${f}: " + @cd ${.CURDIR} && ${MAKE} -B FLAVOR=${f} -V PKGNAME +.endfor +.endif + +flavors-package-names: .PHONY +.if empty(FLAVORS) + @${ECHO_CMD} "${PKGNAME}" +.else +.for f in ${FLAVORS} + @cd ${.CURDIR} && ${MAKE} -B FLAVOR=${f} -V PKGNAME +.endfor .endif # Fake installation of package so that user can pkg delete it later. Index: head/Tools/scripts/MOVEDlint.awk =================================================================== --- head/Tools/scripts/MOVEDlint.awk +++ head/Tools/scripts/MOVEDlint.awk @@ -80,15 +80,44 @@ } lastdate = $3 + from_flavor="" + if ($1 ~ "@") { + from_flavor=$1 + sub("@.*", "", $1) + sub(".*@", "", from_flavor) + } + if (system("test -f " portsdir "/" $1 "/Makefile")) { delete missing[$1] } else { - printf "%5d: %s must be marked as resurrected\n", NR, $1 | sort + if (from_flavor != "") { + if (!system("test \"" from_flavor "\" = \"`make -C " portsdir "/" $1 " -VFLAVORS:M" from_flavor "`\"")) { + printf "%5d: %s still has the %s flavor\n", NR, $1, from_flavor | sort + } + # No else because the port is there but does not have the flavor, + # so it should be ok. + } else { + printf "%5d: %s must be marked as resurrected\n", NR, $1 | sort + } } if ($2) { + to_flavor="" + if ($2 ~ "@") { + to_flavor=$2 + sub("@.*", "", $2) + sub(".*@", "", to_flavor) + } + if (system("test -f " portsdir "/" $2 "/Makefile")) missing[$2] = NR + else + if (to_flavor != "") { + if (system("test \"" to_flavor "\" = \"`make -C " portsdir "/" $2 " -VFLAVORS:M" to_flavor "`\"")) { + printf "%5d: %s does not have the %s flavor\n", NR, $2, to_flavor | sort + error[NR] = 1 + } + } } # Produces too many false positives