Deprecated options (option_deprecate) in variants and other standard code blocks
Ryan Schmidt
ryandesign at macports.org
Sat May 18 02:49:15 PDT 2013
I'm hoping some other developers who have a good understanding of MacPorts base can help me. I'm trying to understand some strange behavior of the "option_deprecate" procedure which I think is a bug.
First, some background for those who may not be as familiar with MacPorts base. An "option" in MacPorts—such as "depends_lib" or "configure.args"—is a variable that can be set or overwritten without using the "set" command, that can behave as a list, that can have items appended or deleted or replaced using the special -append, -delete or -replace modifiers, and that supports lazy/late evaluation. And options can have variable traces attached to them using "option_proc" so that a particular procedure runs whenever an option is accessed or changed or deleted.
Options are also automatically global within standard portfile code blocks, like "build {}" or "pre-destroot {}" or "variant {}", meaning that you can just use any option without having to first indicate that it's a global variable. This magic occurs because standard code blocks get run through "makeuserproc" when they're created, which automatically runs "global" on all available globals at the beginning of each such code block:
https://trac.macports.org/browser/trunk/base/src/port1.0/portutil.tcl?rev=105002#L1247
However in your own non-standard code blocks, i.e. procedures defined directly using "proc", you do have to first use "global" for any options you want to use, and we see this in procedures in MacPorts base too.
"option_deprecate" is not used in MacPorts right at this very moment, but it has been used before at times when we've renamed options. For example, "livecheck.type" used to be called "livecheck.check", so for awhile, MacPorts base used "option_deprecate livecheck.check livecheck.type" so that any ports using "livecheck.check" would still work until maintainers got around to updating their ports. "option_deprecate" works by creating an option with the old name and attaching a variable trace to it using "option_proc" so that whenever the old option is read from or written to, that action is intercepted and redirected to the new option:
https://trac.macports.org/browser/trunk/base/src/port1.0/portutil.tcl?rev=105002#L260
But this doesn't appear to work right when a deprecated option is used inside a code block.
Here's a sample portfile that works—it correctly shows that both "livecheck.type" and "livecheck.check" have the value "default":
PortSystem 1.0
name test1
version 1.0
option_deprecate livecheck.check livecheck.type
ui_msg "livecheck.type=${livecheck.type}"
ui_msg "livecheck.check=${livecheck.check}"
But this next sample portfile doesn't work—after printing "livecheck.type=default", it says "can't read 'livecheck.check': no such variable":
PortSystem 1.0
name test2
version 1.0
option_deprecate livecheck.check livecheck.type
variant foo {
ui_msg "livecheck.type=${livecheck.type}"
ui_msg "livecheck.check=${livecheck.check}"
}
default_variants +foo
Obviously you wouldn't actually use "option_deprecate" inside a portfile; these samples are just to illustrate that if an option is deprecated, then it doesn't work right inside a code block.
It works if I add "global livecheck.check" inside the code block:
PortSystem 1.0
name test3
version 1.0
option_deprecate livecheck.check livecheck.type
variant foo {
global livecheck.check
ui_msg "livecheck.type=${livecheck.type}"
ui_msg "livecheck.check=${livecheck.check}"
}
default_variants +foo
But this shouldn't be necessary because options are supposed to be automatically global, so I'm trying to understand how to fix this. I would like deprecated options to behave identically to supported options.
More information about the macports-dev
mailing list