[87310] trunk/dports/_resources/port1.0/group/php5pear-1.0.tcl

Ryan Schmidt ryandesign at macports.org
Wed Nov 16 18:55:17 PST 2011


On Nov 16, 2011, at 20:02, Bradley Giesbrecht wrote:

> On Nov 16, 2011, at 5:49 PM, Ryan Schmidt wrote:
> 
>> [1] Granted, this is also confusing: the second argument of php5extension.setup is assigned to the local variable "version", which is different from the MacPorts global option of the same name. That's why later you see the otherwise odd-looking:
>> 
>>   version                     ${version}
>> 
>> It would be clearer if I used a different local variable name in the proc declaration, one which does not conflict with existing options / globals.
> 
> Thanks for the explantations. I did use your php5extensions PortGroup as a starting point, so I guess you are the root of some of my confusion. I'm so kidding :)

True though. The job of a portgroup is to simplify things for portfile authors, but in the process of doing that, the portgroup itself can get a bit complicated.


> So is declaring an "option" something like a shorthand so you don't have to use "set" to set or change a var value?

options are like global variables you don't have to use "set" to set, but they're more than that. For example, they get -append and -delete procs added to them. configure.args, depends_lib, etc. are all options. So just like you have configure.args-append, by declaring e.g. php5pear.channel as an option, you now have the procedures php5pear.channel-append and php5pear.channel-delete available. These procs might not make sense for every one of your options, but they're there nonetheless if you want them.

The most important difference between variables and options though is that options are evaluated lazily. This means an option's default is not evaluated when it's declared; it's evaluated when it's first used. You're already familiar with this behavior from many of the options in MacPorts base. Consider these MacPorts options and their default values:

default distname {${name}-${version}}
default worksrcdir {$distname}

This code executes the moment the parser hits the line "PortSystem 1.0" at the top of a portfile. name and version haven't been defined yet, but that's fine; MacPorts has just set up distname so that, the first time something tries to use its value, it'll figure out what name and version are then. Same with worksrcdir: it's set up so that the first time it's read, it'll take the current value of distname. In many ports, you'll change distname, and then expect worksrcdir to have changed along with it. And this works, because you hadn't tried to read worksrcdir until after you set distname.

Example from the php5extension portgroup:

options php5extension.extension_dir
default php5extension.extension_dir {[exec ${prefix}/bin/php-config --extension-dir 2>/dev/null]}

If that [exec] were evaluated the instant the parser reached the "PortGroup php5extension 1.0" line in the portfile, that would cause an error if the user hadn't installed the php5 port yet, which provides the php-config executable. Instead, that [exec] is not run until ${php5extension.extension_dir} is first read (which, looking further into the portgroup, is in a pre-configure block, which won't run until after the php5 port is already installed).

That's what the extra set of curly braces surrounding the default are, by the way. If those weren't there, it would be evaluated immediately.


> Now I think I know how to accomplish this, where I want to change a var to non-default if the Portfile passed in an arg:
> option php5pear.channel
> option php5pear.packagexml
> proc php5pear.setup {package.name package.version {package.channel "pear.php.net"} {package.packagexml "package.xml"}}
> php5pear.channel			${package.channel}
> php5pear.packagexml		${package.packagexml}

First, remember it's "options", not "option". Then, I assume you meant those assignments to be inside the proc:

options php5pear.channel
options php5pear.packagexml
proc php5pear.setup {package.name package.version {package.channel "pear.php.net"} {package.packagexml "package.xml"}} {
    php5pear.channel			${package.channel}
    php5pear.packagexml		${package.packagexml}
    ....
}

Yes, you could do that. The only problem is you've decided that not only does the namespace "php5pear" belong to your portgroup, but also "package". Yes they're in fact local variables in this proc.... but I don't think we've used variables whose names contain a dot in this manner before. They've always been top-level global entities, and the part before the dot is there to create a pseudo-namespace, to ensure there's no ambiguity. Long story short, I'd just use "normal" variable names for proc arguments. Using an underscore instead of a dot would be fine for example.

proc php5pear.setup {package_name package_version {package_channel "pear.php.net"} {package_packagexml "package.xml"}} {
    ....
}

In the setup proc, I'd only put the most essential parameters. name, version, channel is probably necessary. What about package.xml? None of the 500+ pear ports you added so far use it, unless I did my grep wrong. If the odd port here or there needs to override the package.xml, I'd just let that port set that option directly, as in:

PortSystem 1.0
PortGroup php5pear 1.0

php5pear.setup foo 1.2.3 channel.example.com
php5pear.packagexml otherpackage.xml

....

And the portgroup would define the default value, as in:

options php5pear.packagexml
default php5pear.packagexml package.xml




More information about the macports-dev mailing list