source: trunk/www/en/portfileHOWTO.php @ 1327

Last change on this file since 1327 was 1327, checked in by michaelm, 18 years ago

made more explicit when to include contents in the portfile, patch by fkr

  • Property svn:eol-style set to native
File size: 14.1 KB
Line 
1<?
2
3//
4// File     : portfileHOWTO.php
5// Version  : $Id: portfileHOWTO.php,v 1.9 2002/12/06 07:15:40 michaelm Exp $
6// Location : /projects/darwinports/portfileHOWTO.php
7//
8
9        include_once("$DOCUMENT_ROOT/includes/od_lib.inc.php");
10        od_print_header("How to Write a DarwinPorts Portfile", "en", "iso-8859-1", "", 0);
11?>
12
13<h2>
14How to Write a DarwinPorts Portfile
15</h2>
16<pre><tt>
17Kevin Van Vechten | <a href="mailto:kevin@opendarwin.org">kevin@opendarwin.org</a>
188-Oct-2002
19</tt></pre>
20<h3>
21Abstract
22</h3>
23<p>
24DarwinPorts automates the common tasks needed to port software to Darwin.  Portfiles provide the information necessary for building and installing a particular software title correctly on Darwin.  The goal of DarwinPorts is to keep Portfile syntax as simple as possible, while still supporting all the special cases that many software titles require to build and install successfully.
25</p>
26<p>
27This article describes the construction of a simple Portfile, and explores a few of DarwinPorts' most common features.
28</p>
29<h3>
30Getting Started
31</h3>
32<p>
33In order to work with DarwinPorts, you'll need to download and install it on your system.  The DarwinPorts project <a href="http://opendarwin.org/projects/darwinports/">homepage</a> describes how to get and install it.
34</p>
35<p>
36Since you're interested in writing a Portfile, let's change some configuration options that will help in debugging as we go.  Edit the file <tt>/etc/ports/ports.conf</tt> to contain the following (you'll likely have to use <tt>sudo</tt> to edit this file):
37</p>
38<pre><tt>
39ports_debug     yes
40ports_verbose   yes
41</tt></pre>
42<p>
43This will display useful debugging messages that are usually suppressed while running DarwinPorts.
44</p>
45<p>
46DarwinPorts performs several basic predefined tasks, these are:
47</p>
48<a name="basictoc"></a><h4>Basic Topics</h4>
49<ul>
50<li><a href="#fetch">Fetching the Sources</a></li>
51<li><a href="#checksum">Verifying the Downloaded File</a></li>
52<li><a href="#extract">Extracting the Sources into a Working Directory</a></li>
53<li><a href="#configure">Running a Configure Script</a></li>
54<li><a href="#build">Building the Sources</a></li>
55<li><a href="#install">Installing the Finished Product on the System</a></li>
56</ul>
57<a name="advancedtoc"></a><h4>Advanced Topics</h4>
58<ul>
59<li><a href="#targets">Overriding Targets</a></li>
60<li><a href="#variants">Portfile Variants</a></li>
61</ul>
62<a name="appendixtoc"></a><h4>Appendix</h4>
63<ul>
64<li><a href="#portfilelist">Portfile Listing</a></li>
65<li><a href="#contentslist">Contents Listing</a></li>
66</ul>
67
68<h3>
69<a name="fetch"></a>Fetching the Sources
70</h3>
71<p>
72The first step is to choose a piece of software to bring to port.  For this example, we'll be porting ircII, a popular internet relay chat client.  We can start with a simple Portfile describing the basic attributes of ircII such as its name, version, and the site where we can download the sources.  Create a working directory named <tt>ircii</tt> and inside it create a file named <tt>Portfile</tt> with the following contents:
73</p>
74<pre><tt>
75PortSystem 1.0
76name            ircii
77version         20020912
78categories      irc
79maintainers     kevin@opendarwin.org
80master_sites    ftp://ircftp.au.eterna.com.au/pub/ircII/
81</tt></pre>
82<p>
83A Portfile consists of key/value pairs.  The <tt>name</tt> and <tt>version</tt> key describe the name and version of the software.  The <tt>categories</tt> key is a list of the logical categories to which the software belongs; this is used for organizational purposes.  The first entry in <tt>categories</tt> should match the directory in which the port's directory resides in the port tree.  The <tt>maintainers</tt> key should contain your email address, and the <tt>master_sites</tt> key should contain a list of sites where the distribution sources may be downloaded.  DarwinPorts uses the terms 'keys' and 'options' interchangeably since most keys are used as options of a particular task in the porting process.
84</p>
85<p>
86At this point, the Portfile is complete enough to download ircII.  By default, DarwinPorts will append the <tt>version</tt> to the <tt>name</tt> and assume sources are in <tt>.tar.gz</tt> format.  From your working directory, execute the following command:
87</p>
88<pre><tt>
89% port checksum
90</tt></pre>
91<p>
92The <tt>port</tt> command operates on the <tt>Portfile</tt> in the current working directory.  You should see the following output:
93</p>
94<!--
95.........|.........|.........|.........|.........|.........|.........|.........|
96-->
97<pre><tt>
98DEBUG: Executing com.apple.main (ircii)
99DEBUG: Executing com.apple.fetch (ircii)
100--->  ircii-20020912.tar.gz doesn't seem to exist in /opt/local/var/db/dports/
101distfiles
102--->  Attempting to fetch ircii-20020912.tar.gz from ftp://
103ircftp.au.eterna.com.au/pub/ircII/
104DEBUG: Executing com.apple.checksum (ircii)
105Error: No checksums statement in Portfile.  File checksums are:
106ircii-20020912.tar.gz md5 2ae68c015698f58763a113e9bc6852cc
107Error: Target error: com.apple.checksum returned: No checksums statement in
108Portfile.
109</tt></pre>
110
111<h3>
112<a name="checksum"></a>Verifying the Downloaded File
113</h3>
114<p>
115Notice that DarwinPorts first checks for a local copy of <tt>ircii-20020912.tar.gz</tt> and doesn't find it, so it then downloads from the remote site.  The port doesn't finish because of an error:  "No checksums statement in Portfile."  Portfiles must contain an md5 checksum of all distribution files--this allows DarwinPorts to verify the accuracy and authenticity of the sources.  For convenience, an md5 checksum of the downladed files is printed when the <tt>checksums</tt> argument is not specified.  Go back and add the following to your Portfile:
116</p>
117<pre><tt>
118checksums       md5 2ae68c015698f58763a113e9bc6852cc
119</tt></pre>
120
121<h3>
122<a name="extract"></a>Extracting the Sources into a Working Directory
123</h3>
124<p>
125Now that we have a checksum and can verify our sources, we can proceed to extracting the sources into our working directory.  Execute the following:
126</p>
127<pre><tt>
128% port extract
129</tt></pre>
130<p>
131Which should display the following output:
132</p>
133<!--
134.........|.........|.........|.........|.........|.........|.........|.........|
135-->
136<pre><tt>
137DEBUG: Skipping completed com.apple.main (ircii)
138DEBUG: Skipping completed com.apple.fetch (ircii)
139DEBUG: Executing com.apple.checksum (ircii)
140--->  Checksum OK for ircii-20020912.tar.gz
141DEBUG: Executing com.apple.extract (ircii)
142--->  Extracting for ircii-20020912
143--->  Extracting ircii-20020912.tar.gz ... DEBUG: Assembled command: 'cd /Users/
144kevin/opendarwin/proj/darwinports/dports/irc/ircii/work &amp;&amp; gzip -dc /opt/local/
145var/db/dports/distfiles/ircii-20020912.tar.gz | tar -xf -'
146Done
147</tt></pre>
148<h3>
149<a name="configure"></a>Running a Configure Script
150</h3>
151<p>
152Now that the sources have been extracted into a <tt>work</tt> directory in the current working directory, we can configure the sources to compile with the desired options.  By default DarwinPorts assumes the software you're porting uses an autoconf configure script, also by default, DarwinPorts will pass the <tt>--prefix=${prefix}</tt> argument to configure, specifying that the software should be installed in the directory tree used by DarwinPorts.
153</p>
154<p>
155ircII's standard set of options looks fine for a base install on Darwin, so we'll move on to the build phase. 
156</p>
157
158<h3>
159<a name="build"></a>Building the Sources
160</h3>
161<p>
162To build, type the following:
163</p>
164<pre><tt>
165% port build
166</tt></pre>
167<p>
168By default, the build phase executes the system's make(1) utility.  (This can be changed with the <tt>build.type</tt> option which accepts an argument of <tt>bsd</tt>, <tt>gnu</tt>, or <tt>pbx</tt>.  Alternatively, the <tt>build.cmd</tt> option may be used to specify an arbitrary build command.)  The above step has starting compiling the sources, when it finishes we'll be ready to install the software. 
169</p>
170
171<h3>
172<a name="install"></a>Installing the Finished Product on the System
173</h3>
174<p>
175Portfiles are required to have a <tt>contents</tt> option which specifies which files are installed.  DarwinPorts uses this information to catalog what files belong to which piece of software so they may be later uninstalled.  Each parameter to <tt>contents</tt> is a path to a file.  All paths are relative to the <tt>${prefix}</tt> variable.  As a convenient way to determine exactly what files are installed as part of ircII, let's use the find command to compose a manifest of the files in the <tt>${prefix}</tt> tree.  After installing we'll re-run the find command, and use the differences to generate our contents list.
176</p>
177<p>
178Using the unidiff format, we'll compare the list of existing files with the new list of files, only paying attention to the lines that were added.  Since the contents paths are supposed to be relative to <tt>${prefix}</tt>, we'll pipe through <tt>sed</tt> and delete the prefix (<tt>/opt/local/</tt>), storing the result in a file named <tt>contents</tt> in our port directory.  We can do this with the following commands:
179</p>
180<!--
181.........|.........|.........|.........|.........|.........|.........|.........|
182-->
183<pre><tt>
184% find /opt/local > /tmp/existing.files
185% sudo port install
186% find /opt/local > /tmp/more.files
187% diff -u /tmp/existing.files /tmp/more.files | grep ^\+\/ | \
188  sed -e 's|^\+/opt/local/*||g' > contents
189</tt></pre>
190<p>
191Now that we have a contents file in our port directory, we should edit it to begin with <tt>contents {</tt> and end with a closing <tt>}</tt>.  (It is important to note that any other process using the <tt>${prefix}</tt> tree may interfere with the accuracy of the <tt>find</tt> command.  You should audit the resulting <tt>contents</tt> file to look for any files that appear out of place, specifically some DarwinPorts temporary files such as <tt>/var/db/dports/receipts/ircii-20020912.tmp</tt>.)
192It's also important to review the contents file and make sure directories are listed <i>after</i> the files they contain for the uninstall process to work correctly.
193Next we should edit the Portfile to include our contents file:
194</p>
195<pre><tt>
196include contents
197</tt></pre>
198<p>
199If the list of files installed by the port does not extends beyond one page of an 80x24 terminal, the <tt>contents</tt> option should be included in the Portfile.
200Instead of <tt>include contents</tt>, one would use:
201</p>
202<pre><tt>
203contents    bin/irc \
204            bin/irc-20020912 \
205            man/man1/irc.1 \
206            man/man1/ircbug.1 \
207            man/man1/ircII.1 \
208            man/man1
209</pre></tt>
210<p>
211Now we have a complete portfile.  Re-run the installation step to add your port to your own registry:
212</p>
213<pre><tt>
214% sudo port install
215</tt></pre>
216Which will output the following:
217<pre><tt>
218DEBUG: Skipping completed com.apple.main (ircii)
219DEBUG: Skipping completed com.apple.fetch (ircii)
220DEBUG: Skipping completed com.apple.checksum (ircii)
221DEBUG: Skipping completed com.apple.extract (ircii)
222DEBUG: Skipping completed com.apple.patch (ircii)
223DEBUG: Skipping completed com.apple.configure (ircii)
224DEBUG: Skipping completed com.apple.build (ircii)
225DEBUG: Skipping completed com.apple.install (ircii)
226DEBUG: Executing com.apple.registry (ircii)
227--->  Adding ircii to registry, this may take a moment...
228</tt></pre>
229
230<h2>
231Advanced Topics
232</h2>
233
234<h3>
235<a name="targets"></a>Overriding Targets
236</h3>
237<p>
238It's possible to override the functionality of any build target with Tcl code.  A common example is the following, which might be useful for a script without an autoconf configure script:
239</p>
240<pre><tt>
241configure {}
242</tt></pre>
243<p>
244In the Portfile, this will replace the functionality of the configure target, thus skipping that step.  It is also possible to execute Tcl code immediately before or after any of the standard targets.  This can be accomplished in the following manner:
245</p>
246<!--
247.........|.........|.........|.........|.........|.........|.........|.........|
248-->
249<pre><tt>
250post-configure {
251    reinplace "s|change.this.to.a.server|irc.openprojects.net|g" \
252        "${workdir}/${worksrcdir}/config.h"
253}
254</tt></pre>
255<p>
256This example replaces the occurrence of <tt>change.this.to.a.server</tt> with <tt>irc.openprojects.net</tt> in the config.h file that was generated during the preceding <tt>configure</tt> phase.  Note this is a somewhat contrived example, since the same could have been accomplished by specifying <tt>--with-default-server=irc.openprojects.net</tt> in <tt>configure.args</tt>, but the approach is generally useful when such configure arguments aren't present.
257</p>
258
259<h3>
260<a name="variants"></a>Portfile Variants
261</h3>
262<p>
263Since Darwin 6.0 has ipv6, it would be possible to configure with the <tt>--with-ipv6</tt> option.  This can be done by adding the following option to the Portfile:
264</p>
265<pre><tt>
266configure.args      --disable-ipv6
267
268variant ipv6 {
269    configure.args-append  --enable-ipv6
270}
271</tt></pre>
272<p>
273Now the default build will not include ipv6 support, but if the ipv6 variant is requested, ircII will have it.  Options by themselves should be thought of as an assignment operator.  Since variants may be used in combination with one another, it's good practice to only append to options instead of overwrite them.  All options may be suffixed with <tt>-append</tt> or <tt>-delete</tt> to append or delete one term from the list.  You can specify building with the ipv6 variant in the following way:
274</p>
275<pre><tt>
276% port build +ipv6
277</tt></pre>
278
279<h2>
280Appendix
281</h2>
282
283<h3>
284<a name="portfilelist"></a>Portfile Listing
285</h3>
286<p>
287The following is a complete listing of the ircII Portfile:
288</p>
289<pre><tt>
290PortSystem 1.0
291name            ircii
292version         20020912
293categories      irc
294maintainers     kevin@opendarwin.org
295master_sites    ftp://ircftp.au.eterna.com.au/pub/ircII/
296checksums       md5 2ae68c015698f58763a113e9bc6852cc
297configure.args  --disable-ipv6
298include         contents
299
300post-configure {
301        reinplace "s|change.this.to.a.server|irc.openprojects.net|g" \
302                  "${workdir}/${worksrcdir}/config.h"
303}
304
305variant ipv6 {
306        configure.args-append --enable-ipv6
307}
308</tt></pre>
309
310<h3>
311<a name="contentslist"></a>Contents Listing
312</h3>
313<p>
314The following is a partial listing of the ircII contents file:
315</p>
316<pre><tt>
317contents {
318bin/irc
319bin/irc-20020912
320... omitted ...
321man/man1/irc.1
322man/man1/ircbug.1
323man/man1/ircII.1
324man/man1
325man
326... omitted ...
327}
328</tt></pre>
329
330
331<? 
332        od_print_footer("en"); 
333?>
Note: See TracBrowser for help on using the repository browser.