= Portfile Recipes = [[PageOutline(2-3,Table of Contents,inline)]] == Branch and major versions == #branch Often times, when a port's version is x.y.z, you want to be able to refer to just the x.y part, for a download URL or for other reasons. The de facto standard way to do this is {{{ set branch [join [lrange [split ${version} .] 0 1] .] }}} This splits the version string into an array, takes the first two elements of the array, and glues them back together again. This example is from [browser:trunk/dports/devel/glib2 glib2]. If you need to refer just to the x part (the major version) you can similarly do: {{{ set major [lindex [split ${version} .] 0] }}} This splits the version string into an array and returns just the first element. This example is from [browser:trunk/dports/lang/php5 php5]. == Using glob results in "Cannot stat: " == #glob glob returns a list which is not handled by some commands (eg, xinstall); instead, wrap the command in an eval. Instead of {{{ xinstall -m 644 [glob ${worksrcpath}/docs/*.html] ${destroot}${prefix}/share/doc/${name} }}} which fails with the "Cannot stat..." error, instead use {{{ eval xinstall -m 644 [glob ${worksrcpath}/docs/*.html] ${destroot}${prefix}/share/doc/${name} }}} == variant_isset doesn't work when variant is set == #variant_isset Make sure you have the variant defined, even if it is empty, in the Portfile. If all you need is to do something when the variant is set and not dedicate an entire variant section to it, variant_isset can work but you must still define the variant (or platform for things like darwin, darwin_9, etc). So just add {{{ variant myvariant { } }}} or {{{ platform darwin 9 { } }}} Then port will set the variant when selected and variant_isset should work. == Preferred use of default_variants == #default_variants Currently negating a variant (through {{{-variant}}}) is not remembered which means a {{{port upgrade}}} will not keep that negation around. This causes issues with default_variants which must be kept in mind (ticket #2377). The preferred technique is to only select a default variant when one of a set is actually needed; eg, from [browser:trunk/dports/graphics/ImageMagick ImageMagick], when selecting the pixel quantum: {{{ if {![variant_isset q8] && ![variant_isset q32]} { default_variants +q16 } }}} This also leads to preferring negative-based variants (like {{{no_x11}}}) as using {{{+no_x11}}} is remembered, whereas if you had {{{x11}}} as a variant and set it in default_variants, {{{-x11}}} would not be remembered. == cvs/svn/git tag for consistency == #checkout_tag When using one of the checkout-based fetch types (cvs, svn, git, etc) it is best to also use the accompanying tag or date to make sure everyone gets the same checkout as you originally did when creating the port. For example, [browser:trunk/dports/lang/slime slime] does the following for cvs: {{{ cvs.date ${version} }}} [browser:trunk/dports/irc/irssi-devel irssi-devel] does the following for svn: {{{ svn.tag ${version} }}} (note that it instead uses svn.revision as svn.tag will be deprecated in favor of svn.revision when MacPorts 1.8 is released). == Don't hardcode /opt/local == #hardcode_opt_local Make sure to never hardcode /opt/local anywhere as that is the default prefix for MacPorts, but other ones can be used. Many ports will either use a simple reinplace like {{{ reinplace "s|/usr/local|${prefix}|g" ${worksrcpath}/Makefile }}} to replace instances of /usr/local with the right MacPorts prefix when a Makefile simply assumes /usr/local (see for example [browser:trunk/dports/audio/id3v2 id3v2]). Others, when a patch being applied needs to reference the prefix, will use a template for the prefix like @@PREFIX@@, then a similar reinplace: {{{ reinplace "s|@@PREFIX@@|${prefix}|g" ${worksrcpath}/configure }}} that is then run in post-patch (see for example [browser:trunk/dports/devel/glib2 glib2]). == Xcode version checking == #xcode_version MacPorts [ticket:12794 does not check the version of Xcode] being used at runtime, but many ports will fail to build if the version of Xcode is too old. If you discover that your port requires a particular minimum version of Xcode, add this code to the port to print an error if the user's Xcode is too old: {{{ pre-extract { if {"darwin" == ${os.platform} && 9 == ${os.major}} { set minimum_xcodeversion 3.1 set current_xcodeversion [exec defaults read /Developer/Applications/Xcode.app/Contents/Info CFBundleShortVersionString] if {[rpm-vercomp ${current_xcodeversion} ${minimum_xcodeversion}] < 0} { ui_error "On Mac OS X ${macosx_version}, ${name} ${version} requires Xcode ${minimum_xcodeversion} or later but you have Xcode ${current_xcodeversion}." return -code error "incompatible Xcode version" } } } }}} This example is from [browser:trunk/dports/multimedia/x264 x264]. Note that the check [http://lists.macosforge.org/pipermail/macports-dev/2009-April/008112.html is done at pre-extract time]. You can change the "9" in the os.major check to "8" if you're checking Tiger (Xcode 2.x) or "7" for Panther (Xcode 1.x) and update the minimum_xcodeversion accordingly. If you don't know what minimum version of Xcode would work, it's ok to just put whatever version you found that the port worked with. For example, libpixman is known to work with Xcode 1.5 but fail with 1.1, so [changeset:45892 libpixman now requires Xcode 1.5] on Panther, even though compatibility with Xcode 1.2 was not tested. It is better to make a user upgrade to a newer Xcode than for a port maintainer to spend time testing old versions. == Dealing with stealth updates == #stealth-updates Some software may update their distfile with new changes without changing the version number (eg, it stays example-1.2.tar.gz); another case where this happens is when the distfile is unversioned (eg, example.tar.gz). The safest way to deal with this is to keep the port's version unchanged (eg, stays at 1.2) while increasing the revision. This however causes upgrade issues for those with it already as the update will include different checksums, but those who've already downloaded the distfile now have incorrect checksums. To work around this, set dist_subdir so that it includes the version and revision: {{{ dist_subdir ${name}/${version}_${revision} }}} See for example the [browser:trunk/dports/lang/sicp/Portfile sicp Portfile].