= Portfile Development = === MacPorts Guide === It's a good idea to start out with the [http://guide.macports.org/#development Portfile Development] section of the MacPorts Guide. There's a line-by-line explanation in [http://guide.macports.org/#development.creating-portfile Section 4.2] that will help you write a portfile from scratch. === Diamonds in the Rough === Unfortunately, there are useful things that end up buried in the Guide. For example, if you're developing against mysql5 (where multiple packages might create the mysql5 binary), you'd want to [http://guide.macports.org/#reference.dependencies.types depend on the binary] instead of a specific port. This is accomplished in [source:trunk/dports/www/php5/Portfile#L264 php5] through {{{depends_lib-append path:bin/mysql_config5:mysql5}}}. '''Note:''' The trailing mysql5 indicates which port to be installed if the binary cannot be found. Also hidden (to the point where I cannot find it) is how to write wrapper scripts; [source:trunk/dports/x11/wine/ wine] is considered the poster-portfile. Another example is [source:trunk/dports/math/pspp/ pspp]. The scripts should be included in the port's {{{files}}} directory and dynamically modified through the portfile by the [http://guide.macports.org/#reference.tcl-extensions tcl extensions], {{{xinstall}}} and {{{reinplace}}}. Also to be remembered: If at any point you need to see what MacPorts is actually doing with your portfile, use the {{{-d}}} flag. === Steps to Decide When to Use Patch Files === 1. Do nothing: MacPorts already puts{{{ --prefix=${prefix} }}}in {{{configure.pre_args}}} and most software uses configure scripts and most configure scripts understand that flag. 1. If there is another flag you need to use instead, overwrite {{{configure.pre_args}}}. 1. If there is no flag to do this, try an environment variable (e.g.,{{{ configure.env-append PREFIX=${prefix} }}}). 1. If no environment variable exists for this, then patch. === Do Not Hardcode /opt/local === Speaking of {{{reinplace}}}, '''do not''' hardcode {{{/opt/local}}} anywhere! Instead, use {{{reinplace}}} to replace things like {{{${prefix} }}}and {{{${x11prefix} }}}and other variables that can be different on users' systems. === Steps to Installing to Destroot === 1. Do nothing: MacPorts already puts{{{ DESTDIR=${destroot} }}}into {{{destroot.destdir}}} and most Makefiles support this. 1. If there is another variable you need to use, overwrite {{{destroot.destdir}}} (perhaps{{{ destroot.destdir INSTALL_ROOT=${destroot}${prefix} }}}or{{{ destroot.destdir PREFIX=${destroot}${prefix} }}}). 1. If the Makefile doesn't support {{{DESTDIR}}}, request from the author that they do. If they won't or you can't wait for their fix, patch the Makefile to support {{{DESTDIR}}}, or override the destroot phase entirely and {{{xinstall}}} the files into place in the portfile. 1. Sometimes in {{{post-destroot}}} you have to{{{ reinplace s|${destroot}|| somefiles }}}because the destroot path has gotten inserted into them. === Steps to Fixing Libs/Includes === 1. Do nothing: MacPorts already puts {{{-L${prefix}/lib}}} in {{{configure.ldflags}}} and {{{-I${prefix}/include}}} in {{{configure.cflags}}} so that most MacPorts software should be automatically found. 1. If not, look for a {{{--with-foo=path}}} configure option; for example{{{ configure.args-append --with-zlib=${prefix} }}}. 1. Sometimes software responds to specific environment variables, e.g. for [port:graphviz] you could {{{configure.env-append FONTCONFIG_CFLAGS=-I${prefix}/include FONTCONFIG_LIBS=-L${prefix}/lib}}}. 1. You could add nonstandard library paths to the {{{CPPFLAGS}}} and {{{LDFLAGS}}} globally with {{{configure.cppflags-append -I${prefix}/include/something}}} and {{{configure.ldflags-append -L${prefix}/include/something}}}. 1. If there's really no other way, patch. === Dealing with Incompatible Flags === Use a patchfile so that if upstream ever fixes their software to not use -lcrypt and your patch then breaks, you'll be able to tell why. {{{-lcrypt}}} specifically is a flag you find in some Linux software but which is incompatible with and unnecessary on Mac OS X. If software tries to use that flag on Mac OS X, you would write a patchfile to remove that option, but only apply the patchfile on platform darwin (MacPorts could be installed on a non-Mac operating system and you wouldn't want this particular patch to be applied there). Ideally you would report the problem to the author of the software and they would fix their configure script or whatever, so that Mac users who are not using MacPorts will also benefit from what we discovered and we can remove our patch with the next release. Sometimes software authors have no interest in making such changes to their software — That's their prerogative. In that case, we maintain the patchfile in MacPorts forever. === Details of Fetch Phase === Fetch runs{{{ ${master_sites}${distfiles} }}}(assuming {{{master_sites}}} and {{{distfiles}}} are both only a single item, as is likely the case) {{{${distfiles} }}}defaults to{{{ ${distname}${extract.suffix} }}} {{{${distname} }}}defaults to{{{ ${name}-${version} }}} {{{${extract.suffix} }}}defaults to {{{.tar.gz}}} = Portfile Testing = === Portindex === Once you've created your portfile, it's best to test it with your copy of MacPorts. The first step is to create a [http://guide.macports.org/#development.local-repositories local portfile repository] for testing. For this, I suggest creating the directory {{{~/ports}}}. Inside this new directory, you should run {{{portindex}}} which will create the repository index of everything following the {{{./group/port/Portfile}}} heirarchy. '''Note:''' This command should be run everytime you make changes as it will include the new index data for MacPorts. Also watch out for any errors it reports, which stop the portfile from showing up in MacPorts. === Port Info === Once you have a repository setup and indexed, you can then instruct MacPorts to include the repository's path in {{{${prefix}/etc/macports/sources.conf}}} — the order of this file's content is important as ports are loaded in a first-come-first-serve basis. To test if your port index is being included, run {{{port info portname}}} where ''portname'' is a port you've placed in your local repository. If everything works well, you'll notice information appearing from your local repository's portfile. '''Note:''' If you have a port named the same as an existing one, this will report that there are two copies found with the first encounter being displayed. This is why the order of repositories listed in {{{sources.conf}}} matters. === Port Lint === Now that your copy of MacPorts is able to interact with your portfile, run {{{port lint --nitpick portname}}} to do a maximum compliance check. If it reports 0 errors and 0 warnings then you're ready to submit your portfile to MacPorts. = Completion = === Submitting Ticket === See [http://guide.macports.org/#project.contributing Contributing to MacPorts] on how to create a ticket. === Disabling Your Local Repository === Once you're done with development, you can disable your local repository by commenting the line out of your {{{sources.conf}}} file. You can optionally delete your repository's directory, however I suggest keeping it as you can use it for reference when working on future portfiles, and it saves you from having to recreate the directory.