Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Jul 2010 23:06:33 +0100
From:      Christopher Key <cjk32@cam.ac.uk>
To:        freebsd-ports@freebsd.org
Subject:   [patch] Integration between portconf and port options
Message-ID:  <4C476F69.1060200@cam.ac.uk>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------010902020507020400060909
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

  At present, the interaction between portconf and port options is 
somewhat confusing.  Firstly, the output of make showconfig and the 
defaults displayed by make config are unaffected by anything set in 
ports.conf.  Secondly, its quite easy to unexpectedly end up having both 
WITH_XXX and WITHOUT_XXX defined.

Consider devel/binutils:

#v+
# cd /usr/ports/devel/binutils
# make rmconfig
# make showconfig
===> The following configuration options are available for 
binutils-2.20.1_3:
      NLS=off (default) "Enable National Language Support"
===> Use 'make config' to modify these settings
# make -V WITH_NLS

# make -V WITHOUT_NLS
true
#v-

i.e. one option defaulting to off.  We can switch it on with ports.conf:

#v+
# make -DWITH_NLS -VWITH_NLS
1
# make -DWITH_NLS -VWITHOUT_NLS

#v-

however, if options get set then things get confusing:

#v+
# make config
# make showconfig
===> The following configuration options are available for 
binutils-2.20.1_3:
      NLS=off "Enable National Language Support"
===> Use 'make config' to modify these settings
# make -V WITH_NLS

# make -V WITHOUT_NLS
true
# make -DWITH_NLS -VWITH_NLS
1
# make -DWITH_NLS -VWITHOUT_NLS
true
#v-

Just by accepting the defaults, we've suddenly got both WITH_NLS and 
WITHOUT_NLS defined.  In this case, the port checks for WITH_NLS, and 
the build will be unaffected.  In general, the port must check for 
WITH_XXX if the default option value is off (and for WITHOUT_XXX if the 
default value is on) in order to avoid the build changing as a result of 
accepting the default configuration presented by make config.  This 
seems rather fragile, and is clearly susceptible to problems should the 
default option values get changed.


The attached patch reworks the options framework slightly to try resolve 
these two problems.

When a port is being built, each option defined in OPTIONS can be on or 
off, and exactly one of WITH_XXX and WITHOUT_XXX will be defined after 
including bsd.port.options.mk.

There are three locations from which an option can take its value: (in 
decreasing order of priority)
1) /var/db/ports/*/options
2) ports.conf, make.conf and command line arguments - for now termed 
environment, although a more descriptive term is desired.
3) default values from OPTIONS

When make config is run, the values displayed will be the values of the 
options seen by the port when building.  Typically, this would means 
that when make config is first run, the values presented would be the 
defaults (but would reflect anything set in ports.conf too).  Subsequent 
runs would then show the values saved by the last invocation of make config.

When make showconfig, the options displayed will again be the values 
seen by the port when building.  It also displays the location from 
which the option value came from (i.e. config, environment or default).


As both /var/db/ports/*/options and ports.conf etc are stored as lists 
of WITH_XXX and WITHOUT_XXX variables, it is possible for both WITH_XXX 
and WITHOUT_XXX to be defined simultaneously in one location.  If both 
are defined in one location, then WITHOUT_XXX takes priority.  If both 
are defined, but only in different locations, the the first location on 
the list takes priority.

For example, if /var/db/port/*/options had WITH_XXX set and ports.conf 
had WITHOUT_XXX set, then the option would be on (and only WITH_XXX 
would be defined after bsd.port.options.mk), because .../options takes 
priority.  However, if nothing was set in .../options, and ports.conf 
set both WITH_XXX and WITHOUT_XXX then the option would be off (and only 
WITHOUT_XXX would be defined after bsd.port.option.mk) because 
WITHOUT_XXX takes priority.


Feedback would be very much appreciated.


Kind regards,

Christopher Key


--------------010902020507020400060909
Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0";
	name="rework-options.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="rework-options.patch"

Index: Mk/bsd.port.mk
===================================================================
RCS file: /home/ncvs/ports/Mk/bsd.port.mk,v
retrieving revision 1.643
diff -u -r1.643 bsd.port.mk
--- Mk/bsd.port.mk	15 Jul 2010 14:48:50 -0000	1.643
+++ Mk/bsd.port.mk	21 Jul 2010 20:31:25 -0000
@@ -1291,43 +1291,88 @@
 .endif
 OPTIONSFILE?=	${PORT_DBDIR}/${UNIQUENAME}/options
 .if defined(OPTIONS)
-# include OPTIONSFILE first if exists
+
+_OPTIONS_LIST=${OPTIONS:C/".*"//g:S/on//:S/off//}
+
+# Firstly, get an on/off value for each option defined by make.conf, ports.conf, -D...
+# Also undef the corresponding WITH_XXX, WITHOUT_XXX so that we can see what we read in 
+# from our config file.  We'll restore them later.
+.	for OPT in ${_OPTIONS_LIST}
+.	if defined(WITH_${OPT}) || defined(WITHOUT_${OPT}) 
+.	if defined(WITHOUT_${OPT}) # always check WITHOUT_XXX before WITH_XXX to give WITHOUT_XXX priority
+_OPTION_VAL_${OPT}=	off
+.	else
+_OPTION_VAL_${OPT}=	on
+.	endif
+_OPTION_SRC_${OPT}?=	environment
+.	undef WITH_${OPT}
+.	undef WITHOUT_${OPT}
+.   endif
+.   endfor
+
+# Include OPTIONSFILE if exists
 .	if exists(${OPTIONSFILE}) && !make(rmconfig)
 .	include "${OPTIONSFILE}"
 .	endif
 .	if exists(${OPTIONSFILE}.local)
 .	include "${OPTIONSFILE}.local"
 .	endif
-WITHOUT:=
-WITH:=
-.	if defined(OPTIONS)
-REALOPTIONS=${OPTIONS:C/".*"//g}
-.	for O in ${REALOPTIONS}
+
+# Update our list of option values based on what we read from our config file.  Again, unset
+# WITH_XXX and WITHOUT_XXX.  We'll restore them later, ensuring that WITH_XXX and WITHOUT_XXX
+# are mutually exclusive.
+.	for OPT in ${_OPTIONS_LIST}
+.	if defined(WITH_${OPT}) || defined(WITHOUT_${OPT}) 
+.	if defined(WITHOUT_${OPT}) # always check WITHOUT_XXX before WITH_XXX to give WITHOUT_XXX priority
+_OPTION_VAL_${OPT}=	off
+.	else
+_OPTION_VAL_${OPT}=	on
+.	endif
+_OPTION_SRC_${OPT}=	config
+.	undef WITH_${OPT}
+.	undef WITHOUT_${OPT}
+.   endif
+.   endfor
+
+# Set default value for remaining options
+.	for O in ${OPTIONS:C/".*"//g}
 RO:=${O}
-.	if ${RO:L} == off
-WITHOUT:=	${WITHOUT} ${OPT}
+.	if ${RO:L} == on || ${RO:L} == off
+.	if !defined(_OPTION_VAL_${OPT})
+_OPTION_VAL_${OPT}:=	${RO:L}
+_OPTION_SRC_${OPT}:=	default
 .	endif
-.	if ${RO:L} == on
-WITH:=		${WITH} ${OPT}
+.	else
+OPT:=	${RO}
+.endif
+.endfor
+.undef RO
+.undef OPT
+
+# restore WITH_XXX, WITHOUT_XXX appropriately
+.	for OPT in ${_OPTIONS_LIST}
+.	if ${_OPTION_VAL_${OPT}} == on
+WITH_${OPT}=	true
+.	else
+WITHOUT_${OPT}=	true
 .	endif
-OPT:=${RO}
 .	endfor
-.	endif
-# define only if NO WITH/WITHOUT_${W} is defined
-.	for W in ${WITH}
-.   if !defined(WITH_${W}) && !defined(WITHOUT_${W})
-WITH_${W}:=	true
-.   endif
+
+# shell script to set variables for current option values
+_OPTIONS_SET_SH:=
+.	for OPT in ${_OPTIONS_LIST}
+_OPTIONS_SET_SH:=	${_OPTIONS_SET_SH} \
+					OPTION_SRC_${OPT}=${_OPTION_SRC_${OPT}}; \
+					OPTION_VAL_${OPT}=${_OPTION_VAL_${OPT}};
 .	endfor
-.	for W in ${WITHOUT}
-.   if !defined(WITH_${W}) && !defined(WITHOUT_${W})
-WITHOUT_${W}:=	true
-.   endif
+
+# clean up
+.	for OPT in ${_OPTIONS_LIST}
+.	undef _OPTION_VAL_${OPT}
+.	undef _OPTION_SRC_${OPT}
 .	endfor
-.	undef WITH
-.	undef WITHOUT
-.	undef RO
-.	undef REALOPTIONS
+.	undef _OPTIONS_LIST
+
 .endif
 
 .endif
@@ -6102,24 +6147,11 @@
 	${MKDIR} $${optionsdir} 2> /dev/null) || \
 		(${ECHO_MSG} "===> Cannot create $${optionsdir}, check permissions"; exit 1)
 .endif
-	-@if [ -e ${OPTIONSFILE} ]; then \
-		. ${OPTIONSFILE}; \
-	fi; \
+	-@${_OPTIONS_SET_SH} \
 	set -- ${OPTIONS} XXX; \
 	while [ $$# -gt 3 ]; do \
 		OPTIONSLIST="$${OPTIONSLIST} $$1"; \
-		defaultval=$$3; \
-		withvar=WITH_$$1; \
-		withoutvar=WITHOUT_$$1; \
-		withval=$$(eval ${ECHO_CMD} $$\{$${withvar}\}); \
-		withoutval=$$(eval ${ECHO_CMD} $$\{$${withoutvar}\}); \
-		if [ ! -z "$${withval}" ]; then \
-			val=on; \
-		elif [ ! -z "$${withoutval}" ]; then \
-			val=off; \
-		else \
-			val=$$3; \
-		fi; \
+		val=$$(eval ${ECHO_CMD} $$\{OPTION_VAL_$${1}\}); \
 		DEFOPTIONS="$${DEFOPTIONS} $$1 \"$$2\" $${val}"; \
 		shift 3; \
 	done; \
@@ -6176,21 +6208,11 @@
 .if defined(OPTIONS)
 .if exists(${OPTIONSFILE})
 # scan saved options and invalidate them, if the set of options does not match
-	@. ${OPTIONSFILE}; \
+	@${_OPTIONS_SET_SH} \
 	set ${OPTIONS} XXX; \
 	while [ $$# -gt 3 ]; do \
-		withvar=WITH_$$1; \
-		withoutvar=WITHOUT_$$1; \
-		withval=$$(eval ${ECHO_CMD} $$\{$${withvar}\}); \
-		withoutval=$$(eval ${ECHO_CMD} $$\{$${withoutvar}\}); \
-		if [ ! -z "$${withval}" ]; then \
-			val=on; \
-		elif [ ! -z "$${withoutval}" ]; then \
-			val=off; \
-		else \
-			val=missing; \
-		fi; \
-		if [ "$${val}" = "missing" ]; then \
+		src=$$(eval ${ECHO_CMD} $$\{OPTION_SRC_$${1}\}); \
+		if [ "$${src}" != "config" ]; then \
 			OPTIONS_INVALID=yes; \
 		fi; \
 		shift 3; \
@@ -6206,26 +6228,16 @@
 
 .if !target(showconfig)
 showconfig:
-.if defined(OPTIONS)
+.if !defined(OPTIONS)
+	@${ECHO_MSG} "===> No options to configure"
+.else
 	@${ECHO_MSG} "===> The following configuration options are available for ${PKGNAME}:"
-	-@if [ -e ${OPTIONSFILE} ]; then \
-		. ${OPTIONSFILE}; \
-	fi; \
+	@${_OPTIONS_SET_SH} \
 	set -- ${OPTIONS} XXX; \
 	while [ $$# -gt 3 ]; do \
-		defaultval=$$3; \
-		withvar=WITH_$$1; \
-		withoutvar=WITHOUT_$$1; \
-		withval=$$(eval ${ECHO_CMD} $$\{$${withvar}\}); \
-		withoutval=$$(eval ${ECHO_CMD} $$\{$${withoutvar}\}); \
-		if [ ! -z "$${withval}" ]; then \
-			val=on; \
-		elif [ ! -z "$${withoutval}" ]; then \
-			val=off; \
-		else \
-			val="$$3 (default)"; \
-		fi; \
-		${ECHO_MSG} "     $$1=$${val} \"$$2\""; \
+		val=$$(eval ${ECHO_CMD} $$\{OPTION_VAL_$${1}\}); \
+		src=$$(eval ${ECHO_CMD} $$\{OPTION_SRC_$${1}\}); \
+		${ECHO_MSG} "     $$1=$${val} ($${src}) \"$$2\""; \
 		shift 3; \
 	done
 	@${ECHO_MSG} "===> Use 'make config' to modify these settings"

--------------010902020507020400060909--



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