Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Sep 2000 05:22:26 -0500
From:      Will Andrews <will@physics.purdue.edu>
To:        FreeBSD Ports <ports@FreeBSD.org>
Subject:   Ports Options Paper
Message-ID:  <20000903052226.E1205@radon.gryphonsoft.com>

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

--ReaqsoxgOBHFXBhH
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi all,

This is the fruit of my brain's unused cycles, several nights of
sleepless thought, and several weeks of pondering.

Please note that any egotistical statements (i.e. this proposal will
solve everybody's problems etc.) are hereby retracted if serious flaws
are found with this proposal.  :-P

Failing that, I think there's plenty of room for improvement, and my
goal is to have an implementation written by October 3, 2000, and tested
by October 15, 2000.

But I do think I've thought this out quite well.. and now that I've
finally offloaded most of my ideas (maybe there's something I missed
that I thought up previously), I'm hoping we can finally get the ports
collection to become the world's best package management system.

I think I'm going to get some sleep now.  Finally.

Till next time,
-- 
Will Andrews <will@physics.purdue.edu> <will@FreeBSD.org>
GCS/E/S @d- s+:+ a--- C++ UB++++$ P+ L- E--- W+ N-- !o ?K w---
O- M+ V- PS+ PE++ Y+ PGP+>+++ t++ 5 X+ R+ tv+ b++ DI+++ D+ 
G++ e>++++ h! r- y?

--ReaqsoxgOBHFXBhH
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=ports-options

program PORTS-OPTIONS

begin

			Paper on "Ports Options"

Author:	Will Andrews <will@FreeBSD.org>
Date:	Thu 29 June 2000
Last:	Sun 3 September 2000

				PROBLEM

	The current ports system has many problems that make it
difficult to extend, upgrade, etc.  For example, there is no command
that will upgrade all installed ports for you.  There is no way for
one port to find out whether another port has support for a certain
feature.  There is no way to ensure library/binary compatibility.
There is no way to build more than one package (i.e. with or without
fonts, w/ or w/o GTK support, w/ or w/o GNOME support, w/ or w/o
LDAP support, w/ or w/o debugging code, and so forth).  There is no
easy UI for enabling or disabling "options" in the ports that have
them.  There is no consistent interface to add "options".

				PROPOSAL

N.B.:
	This paper now takes into account advantages given to the
ports system by the PORTREVISION/PORTEPOCH system recently proposed
by Kris Kennaway <kris@FreeBSD.org>, which allows for flawless version
upgrade mechanism.  Original ideas by Maxim Sobolev <sobomax@FreeBSD.org>
and Neil-Blakey Milner <nbm@FreeBSD.org>.

The Story:

	Some time ago, Neil-Blakey Milner <nbm@FreeBSD.org> proposed
a method allowing users to configure their ports without having to
read the Makefile to figure out what options were available.  This
idea was a good one, but its implementation was a little too difficult:
it required XML files in addition to each port.  Since porters are a
little more used to Makefile syntax, it seems it would be easier to
set up something in this manner, to solve a large variety of problems
with the current ports system.  XML parsers are not easy to write and
do not come with the system.  (Read: it's not easy to integrate XML
files so they can work with the base system, and thus this sort of
thing would be too proprietary)  [ no offense, Neil ;) ]

	Let's take an example of astro/xplanet...:

.if (!defined(WITH_TK80) && !defined(WITH_TK81) && !defined(WITH_TK82) && !defined(WITH_TK83))
.if exists(${LOCALBASE}/bin/wish8.3)
WITH_TK83=      yes
.elif exists(${LOCALBASE}/bin/wish8.2)
WITH_TK82=	yes
.elif exists(${LOCALBASE}/bin/wish8.1)
WITH_TK81=      yes
.else
WITH_TK80=	yes
.endif
.endif

.if defined(WITH_TK80)
RUN_DEPENDS=	wish8.0:${PORTSDIR}/x11-toolkits/tk80
WISH=		${LOCALBASE}/bin/wish8.0
TKVERMSG=	"Using Tk 8.0"
.endif

.if defined(WITH_TK81)
RUN_DEPENDS=	wish8.1:${PORTSDIR}/x11-toolkits/tk81
WISH=		${LOCALBASE}/bin/wish8.1
TKVERMSG=	"Using Tk 8.1"
.endif

.if defined(WITH_TK82)
RUN_DEPENDS=	wish8.2:${PORTSDIR}/x11-toolkits/tk82
WISH=		${LOCALBASE}/bin/wish8.2
TKVERMSG=	"Using Tk 8.2"
.endif

.if defined(WITH_TK83)
RUN_DEPENDS=	wish8.3:${PORTSDIR}/x11-toolkits/tk83
WISH=		${LOCALBASE}/bin/wish8.3
TKVERMSG=	"Using Tk 8.3"
.endif

Basically, we would replace these lines with:

option WITH_TK80
DESCR=		"Tk 8.0 support"
RUN_DEPENDS=	tk-8.0:${PORTSDIR}/x11-toolkits/tk80
WISH=		${LOCALBASE}/bin/wish8.0
end WITH_TK80

option WITH_TK81
DESCR=		"Tk 8.1 support"
RUN_DEPENDS=	tk-8.1:${PORTSDIR}/x11-toolkits/tk81
WISH=		${LOCALBASE}/bin/wish8.1
TKVERMSG=	"Using Tk 8.1"
end WITH_TK81
[...]

in ${FILESDIR}/options.  Additionally, we could have a
bsd.options.mk that will store these variables with preset
defaults.  This bsd.options.mk could also contain the magic
involved into turning ${FILESDIR}/options into a useful
Makefile-type thing.

The reasons for putting such things in a separate file is to
simplify parsing for GUI-style programs like gportconf (which
nbm proposed using with his XML format) or dialog(1), which
would be the default user-friendly interface.  It would also
reduce clutter in port Makefiles somewhat.

The *_DEPENDS can also be moved to ${FILESDIR}/options:

LIB_DEPENDS=	kdecore.4:${PORTSDIR}/x11/kdelibs2
RUN_DEPENDS=	konqueror:${PORTSDIR}/x11/kdebase2 \
		kjumpingcube:${PORTSDIR}/games/kdegames2 \
		kdf:${PORTSDIR}/misc/kdeutils2 \
		kword:${PORTSDIR}/editors/koffice \
		kppp:${PORTSDIR}/net/kdenetwork2

to

# defined in bsd.options.mk - capitalized so parser doesn't try
# to look for an `end' point.
REQUIRE WITH_KDELIBS

require WITH_KDEBASE
RUN_DEPENDS=	kdebase-2.0:${PORTSDIR}/x11/kdebase2
end WITH_KDEBASE

require WITH_KDEGAMES
RUN_DEPENDS=	kdegames-2.0:${PORTSDIR}/x11/kdegames2
end WITH_KDEGAMES
[...]

Returning to the idea of interfaces and that of storing info
about a port's options: If a user selects a particular option,
the package generator will note it in the ${PKG_DBDIR}/${PKGNAME}/+OPTS
file.  I.e., if GTK support is optional but not required and the
user selects it, the package generator will put it in the +OPTS
file as "WITH_GTK".  If, say, a port supports Qt, GTK, and GNOMELIBS
interfaces, it could hold "WITH_GTK,WITH_QT,WITH_GNOMELIBS".

Now let us address the fact that some configure scripts like to assume
that if you have something installed and it finds it, it should use it
while linking programs etc.  This skews our package dependency system
in a number of subtle ways.  Thus, we should have a make.conf variable,
USE_GRATUITOUS_DEPENDS, which we can check to see if it is allowed or
not.  Then, we can add something like this to a port that allows buidling
with GTK but doesn't require it:

option WITH_GTK
LIB_DEPENDS=	gtk-1.2.8:${PORTSDIR}/x11-toolkits/gtk12
option GRATUITOUS
SOME_VAR_TO_DEFINE_HERE=	blah
CONFIGURE_ARGS=		--blah3 --blah6
end GRATUITOUS
option NO_GRATUITOUS
GRATUITOUS_PATCHES=	patch-aa patch-ac patch-zb3
CONFIGURE_ARGS=		--blah --blah2
end NO_GRATUITOUS
end WITH_GTK

Where GRATUITOUS_PATCHES will be a string containing the names of the
patches to be applied if USE_GRATUITOUS_DEPENDS is not defined (i.e. if
it is necessary to apply patches etc.  NOTE: I'm not real solid on any
of these ideas, but this issue needs to be addressed in a satisfactory
manner, to prevent package dependency breakage.  The above method seems
to be good enough to take care of 99.99% of gratuitous pkg dependencies.
My major concern would be regarding conflicting patch files.  Perhaps
patchfiles for GRATUITOUS stuff should be denoted in a different manner.

OK.  Now, let us consider the case where someone wants to install a
port that REQUIRES an option in a dependency, either through one of its
own options or requirements.  But WAIT!  The port is already installed,
and it doesn't have the optional code installed!  Okay, then.  If we are
in BATCH mode, force deinstall and reinstall with option.  If we are in
OPTIONS mode (i.e. user selected the `options' target in bsd.port.mk on
the original make command), warn the user and ask about reinstalling X
version of the port that's in the tree with the required options PLUS
whatever other options the port originally contained selected by default.
Then, check another make.conf var FORCE_DEPENDS (or similar) as a last
chance check to see if we have permission to override current port.  Else
we fail the install of the original port with an appropriate error message.
This sort of thing would be implemented something like:

option WITH_DEBUG
REQUIREDEP gtk-1.2.8 WITH_DEBUG
end WITH_DEBUG

Now, to move on to the age-old question: How can we properly support the
``make upgrade'' target?  Now that we have PORTREVISION/PORTEPOCH, we can
ensure that new versions of packages will always have a PKGNAME greater
than previous ones.  Hence, we can simply deinstall and install the new
ports.  If the user runs this target from /usr/ports, it checks the PKG_DB
for currently installed ports, selects the options that are default, and
reinstall them in this manner with the options as available.  Warnings
will be given if an option is no longer available, and fail if a make.conf
or other variable is specified.  Obviously, if ``upgrade'' is run in a
category or specific port Makefile, the upgrade will be as specific in
scope as possible, and will only traverse outside its domain to install
dependencies, and this can be disabled with another make.conf variable.

Another issue that I've stumbled across over time has been the inability
of a single port to create multiple packages.  Hence, I'd like to reintroduce
this issue by exploiting the flexibility of ports-options.  Let us observe
how we can modify easily (or rather, easily enough) the GTK 1.2.8 port to
build a debugging version:

option WITH_DEBUG
PKGNAME=	${PKGNAME}-debug
CFLAGS+=	-g
end WITH_DEBUG

and so forth.  This sort of thing will allow us to replace all sorts of hacks
currently in the ports tree, such as ports that exist only to provide
localized versions of another port (i.e. chinese/mutt and mail/mutt), and
all of the various Netscape ports can be crunched into *ONE* Netscape port.
Gratuitous extra ports, i.e. kde11 vs kde2, can now be crunched into *ONE*
kde port, eliminating vagueness.  And this will also allow us to crunch all
the various +ipv6 and -ssl ports into their master ports, and still generate
the extra packages as needed.  Packages can also be generated for the various
options, i.e. debugging, gtk support, and so forth, from *ONE* port!  The
major advantages to this includes not only the significant reduction of
inodes required by an average ports installation, but also increased
maintainability.  This is not to say that this method would become REQUIRED;
that is, people can still do it the old hackish way, but it WOULD require a
good reason - i.e. too much hacking needs to be done that would not be made
available through the ports-options mechanism.

Some people may wonder about the effects on the current ports system.  Well,
one thing is for sure.  People are going to have to reinstall *ALL* of their
current packages (assuming nobody comes up with a good way to upgrade all of
the PKG_DBDIRs to account for the changes).  But the standard ``make install''
semantics will not change.  It will do whatever is the normal method for
installing (i.e. the required [LIB,BUILD,RUN]_DEPENDS and so forth) and nothing
more.  People can avoid the dialog(1) etc. interfaces by simply mentioning
in an environment variable OPTIONS which options they desire.  The options
target can also print out in standard textual format the various options
available for a particular port to stdout, which the users can then use to
specify the options in said environment variable.


			SUMMARY & CONCLUSION

The term "ports-options" comes from the name of the file that the options
would be written in (${FILESDIR}/options).  It is designed to solve many of
the problems with the current ports tree as it is.  The project involved in
writing an actual ports-options implementation would probably consist of
creating a new bsd.options.mk to contain options code and common options
(although these may be placed in separate files instead as per Akinori's
recent proposal).  A separate file containing a parser for these files
(written in Perl or some other language in the base system) will be used
to generate a Makefile.options as needed.  It will provide the actual
functionality to the makefile system.  Reiterating, the reasons for putting
things in a separate file are to keep cruft out of the main port Makefile,
and to provide an easier way for fancier interfaces to the options method,
like a GTK/QT/GNOME/dialog(1)/text interface.  Also reiterating, ports-options
is not just to provide an easier interface to the options available in a
port, but also to solve many of the package dependency problems that currently
exist in ports.

The power and flexibiltiy of ports-options has been so shockingly
unbelievable that I'm sure other people will think up additional methods
to exploit its usefulness.  I'd particularly like to thank Neil-Blakey
Milner <nbm@FreeBSD.org> for the inspiration!  I believe that the project
involving writing the code to support ports-options will be most enlightening
(and time-consuming!) as well as vastly enjoyable, because it will result
in an ultimately more powerful ports collection than ever before.


						Greetings,

							Will
end

--ReaqsoxgOBHFXBhH--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message




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