source: trunk/doc/guide/xml/quick.xml @ 3070

Last change on this file since 3070 was 3070, checked in by fkr, 17 years ago

Bug: #705
Submitted by: wb@… (Will Barton)
Reviewed by:
Approved by:
Obtained from:

documentation of the new mirror_sites api for the guide.

  • Property svn:eol-style set to native
File size: 26.5 KB
Line 
1<?xml version="1.0" encoding="UTF-8" ?>
2<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
3                "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
4<chapter id="quickstart">
5  <chapterinfo>
6    <keywordset>
7      <keyword>
8        portfile
9      </keyword>
10   
11      <keyword>
12        introduction
13      </keyword>
14     
15      <keyword>
16        maintainer
17      </keyword>
18    </keywordset>
19  </chapterinfo>
20 
21  <title>Quick Start</title> 
22
23  <sect1 id="getting_started">
24    <title>Getting Stated With DarwinPorts</title>
25
26    <para>This document will provide a short guide to the basics of a
27      DarwinPorts <filename>Portfile</filename>.  A
28      <filename>Portfile</filename> is actually a Tcl script run by the
29      <command>port</command> system.  Despite this, the
30      <filename>Portfile</filename> syntax is very
31      straightforward.</para>
32   
33    <para>In order to work with DarwinPorts, you will need to download and
34      install it on your system.  The <link linkend='getting_dports'> 
35      Obtaining</link> and <link linkend='install_dports'>Installing 
36      DarwinPorts</link> sections of this guide describes the process in
37      detail. </para>
38
39    <para>Since you're interested in writing a
40      <filename>Portfile</filename>, you should invoke the
41      <command>port</command> with the <option>-v</option> (verbose
42      output) and the <option>-d</option> (debugging option) switches.
43      This will display useful messages that are usually suppressed
44      while running DarwinPorts.</para>
45  </sect1>
46
47  <sect1 id="basics">
48    <title>Basic Topics and Examples</title>
49
50    <sect2 id="fetching_sources">
51      <title>Fetching the Sources</title>
52
53      <para>The first step is to choose a piece of software to port. 
54      For this example, we'll be porting ircII, a popular Internet relay
55      chat client.</para>
56
57      <para>We can start with a simple <filename>Portfile</filename>
58        describing the basic attributes of ircII, such as its name,
59        version, and the site where we can download the sources.  </para>
60        <para>Create a working directory named <filename>ircII</filename> 
61        and inside it create a file named <filename>Portfile</filename> 
62        with the following contents:</para>
63
64      <example id="ircii">
65        <title>ircII <filename>Portfile</filename></title> 
66         
67        <programlisting># &#x0024;Id: &#x0024;
68PortSystem        1.0
69name              ircii
70version           20020912
71categories        irc
72maintainers       kevin@opendarwin.org
73description       an IRC and ICB client
74long_description  The ircII program is a full screen, termcap based \
75                  interface to Internet Relay Chat. It gives full access \
76                  to all of the normal IRC functions, plus a variety of \
77                  additional options.
78homepage          http://www.eterna.com.au/ircii/
79master_sites      ftp://ircftp.au.eterna.com.au/pub/ircII/</programlisting>
80      </example>
81
82      <para>A <filename>Portfile</filename> consists of key/value pairs.
83        This example uses the following keys:</para>
84 
85      <variablelist>
86        <varlistentry>
87          <term><varname># &#x0024;Id: &#x0024;</varname></term>
88         
89          <listitem>
90            <para>Every <filename>Portfile</filename> starts with
91              <varname>#&#x0024;Id: &#x0024;</varname>. This is a RCS
92              <varname>Id</varname> tag (commented out with the '#' character
93              so that DarwinPorts is not confused by the tag). </para>
94          </listitem>
95        </varlistentry>
96
97        <varlistentry>
98          <term><varname>PortSystem</varname></term>
99
100          <listitem>
101            <para>Following the RCS <varname>Id</varname> tag comes the
102              <varname>PortSystem</varname> version declaration.  Currently the
103              only valid version declaration is <varname>PortSystem
104                1.0</varname>.</para>
105          </listitem>
106        </varlistentry>
107
108        <varlistentry>
109          <term><varname>name</varname> and
110            <varname>version</varname></term>
111
112          <listitem>
113            <para>The <varname>name</varname> and
114              <varname>version</varname> keys describe the name and
115              version of the software.</para>
116          </listitem>
117        </varlistentry>
118       
119        <varlistentry>
120          <term><varname>categories</varname></term>
121         
122          <listitem>
123            <para>The <varname>categories</varname> key is a list of the
124              logical categories to which the software belongs; this is
125              used for organizational purposes.  The first entry in
126              <varname>categories</varname> should match the directory
127              in which the port's directory resides in the ports
128              tree.</para>
129          </listitem>
130        </varlistentry>
131
132        <varlistentry>
133          <term><varname>maintainers</varname></term>
134
135          <listitem>
136            <para>The <varname>maintainers</varname> key should contain
137              the email address of the person or persons maintaining the port.</para>
138          </listitem>
139        </varlistentry>
140
141        <varlistentry>
142          <term><varname>description</varname> and
143            <varname>long_description</varname></term>
144
145          <listitem>
146            <para><varname>description</varname> provides a short (one line)
147              description of the port, while
148              <varname>long_description</varname> holds a more detailed
149              description of the software.</para>
150          </listitem>
151        </varlistentry>
152
153        <varlistentry>
154          <term><varname>homepage</varname></term>
155
156          <listitem>
157            <para>To refer to the main web site of the software, the
158              <varname>homepage</varname> key is used.</para>
159          </listitem>
160        </varlistentry>
161
162        <varlistentry>
163          <term><varname>master_sites</varname></term>
164         
165          <listitem>
166            <para>The <varname>master_sites</varname> key should contain
167              a list of sites where the distribution sources may be
168              downloaded by the port system. </para>
169          </listitem>
170        </varlistentry>
171      </variablelist>
172     
173      <para>DarwinPorts uses the terms 'keys' and 'options'
174        interchangeably since most keys are used as options of a
175        particular task in the porting process.</para>
176     
177      <para>At this point, the <filename>Portfile</filename> is complete
178        enough to download ircII.  By default, DarwinPorts will append
179        the <varname>version</varname> to <varname>name</varname> and
180        assume sources are in a gzipped tar archive with the
181        <filename>.tar.gz</filename> suffix. </para>
182        <para>From your working directory, execute the following command:</para>
183     
184      <para><userinput>port -d -v checksum</userinput></para>
185
186      <para>The <command>port</command> command (when used without an explicit
187      port name operates on the <filename>Portfile</filename> in the current
188      working directory. You should see the following output:</para>
189
190      <para><computeroutput><literallayout>DEBUG: Executing com.apple.main (ircii)
191DEBUG: Executing com.apple.fetch (ircii)
192--->  ircii-20020912.tar.gz doesn't seem to exist in /opt/local/var/db/dports/distfiles
193--->  Attempting to fetch ircii-20020912.tar.gz from ftp://ircftp.au.eterna.com.au/pub/ircII/
194DEBUG: Executing com.apple.checksum (ircii)
195Error: No checksums statement in Portfile.  File checksums are:
196ircii-20020912.tar.gz md5 2ae68c015698f58763a113e9bc6852cc
197Error: Target error: com.apple.checksum returned: No checksums statement in Portfile.
198</literallayout></computeroutput></para>
199    </sect2>
200
201    <sect2 id="checksums">
202      <title>Verifying the Downloaded File</title>
203
204      <para>Notice that DarwinPorts first checks for a local copy of
205        <filename>ircii-20020912.tar.gz</filename> and doesn't find it,
206        so it then downloads from the remove site.  The port doesn't
207        finish because of an error: <computeroutput>No checksums
208          statement in Portfile.</computeroutput>
209        Portfiles must contain an md5 checksum of all distribution
210        files--this allows DarwinPorts to verify the accuracy and
211        authenticity of the sources.  For convenience, an md5 checksum
212        of the downloaded files is printed when the
213        <varname>checksums</varname> argument is not specified.  Go back
214        and add the following to your
215        <filename>Portfile</filename>:</para>
216
217      <programlisting>checksums    md5 2ae68c015698f58763a113e9bc6852cc</programlisting>
218
219      <para>If you have more than one file being fetched you should
220        specify the checksum for each in the form:</para>
221
222      <programlisting>checksums    foo md5 ... \
223             bar md5 ...</programlisting>
224     
225    </sect2>
226
227    <sect2 id="extract">
228      <title>Extracting the Sources into a Working Directory</title>
229
230      <para>Now that we have a checksum and can verify our sources, we
231        can proceed to extracting the sources into our working
232        directory.  Execute the following:</para>
233
234      <para><userinput>port -d -v extract</userinput></para>
235
236      <para>Which should display the following output:</para>
237
238      <para><computeroutput><literallayout>DEBUG: Skipping completed com.apple.main (ircii)
239DEBUG: Skipping completed com.apple.fetch (ircii)
240DEBUG: Executing com.apple.checksum (ircii)
241--->  Checksum OK for ircii-20020912.tar.gz
242DEBUG: Executing com.apple.extract (ircii)
243--->  Extracting for ircii-20020912
244--->  Extracting ircii-20020912.tar.gz ... DEBUG: Assembled command: 'cd
245/Users/kevin/opendarwin/proj/darwinports/dports/irc/ircii/work &amp;&amp; gzip -dc /opt/local/var/db/dports/distfiles/ircii-20020912.tar.gz | tar -xf -'
246Done</literallayout></computeroutput></para>
247    </sect2>
248
249    <sect2 id="running_configure">
250      <title>Running a <filename>configure</filename> Script</title>
251
252      <para>Now that the sources have been extracted into a
253        <filename>work</filename> directory in the Portfile
254        directory, we can configure the sources to compile with the
255        desired options.  By default DarwinPorts assumes the software
256        you're porting uses an autoconf <filename>configure</filename>
257        script and  will pass the <option>--prefix=${prefix}</option> 
258        argument to <filename>configure</filename>, specifying that the
259        software should be installed in the directory tree used by
260        DarwinPorts.</para>
261
262      <para>ircII's standard set of options is fine for a base
263        install on Darwin, so we won't add anything to the
264        <varname>configure</varname> phase and instead just
265        move on to the build phase.  Please look at the
266        later chapters in this Guide for more information about
267        the <link linkend='configure'>Configuration</link> phase.</para>
268    </sect2>
269
270    <sect2 id="building_sources">
271      <title>Building the Sources</title>
272
273      <para>To build, type the following:</para>
274     
275      <para><userinput>port build -v -d</userinput></para>
276
277      <para>By default, the build phase executes the system's
278        <command>make</command>(1) utility.  (This can be changed with
279        the <varname>build.type</varname> option which accepts an
280        argument of <varname>bsd</varname>, <varname>gnu</varname>, or
281        <varname>pbx</varname>.  Alternatively, the
282        <varname>build.cmd</varname> option may be used to specify an
283        arbitrary build command.)  The above step has started
284        compiling the sources, when it finishes we'll be ready to
285        install the software.</para>
286    </sect2>
287
288    <sect2 id="installing">
289      <title>Installing the Finished Product on the System</title>
290
291      <para>The former method of including a
292        <varname>contents</varname> list has been made obsolete by the
293        <varname>destroot</varname> mechanism.  With
294        <varname>destroot</varname> the software is installed into a
295        directory tree below in the <filename>work</filename>
296        directory.  While some software (like ircII) does not require
297        any special tweaks to be installed into the destroot, others
298        (like ncftp) need the <varname>install.destroot</varname>
299        option in order to correctly install into the
300        <varname>destroot</varname>.</para>
301
302      <programlisting>install.destroot     mandir=${destroot}${prefix}/man prefix=${destroot}${prefix}</programlisting>
303
304      <para>Take a look at some of our ports to see more examples on
305        how to use the <varname>install.destroot</varname>
306        option.</para>
307
308      <para>Now we have a complete <filename>Portfile</filename>.
309        Run the installation step to add your port to your own
310        registry. </para>
311     
312      <para><userinput>sudo port -d -v install</userinput></para>
313
314      <para>Which should finish with the output:</para>
315
316      <para><computeroutput><literallayout>
317--->  Adding ircii to registry, this may take a moment...</literallayout></computeroutput></para>
318    </sect2>
319  </sect1>
320
321  <sect1 id="advanced">
322    <title>Advanced Topics</title>
323
324    <sect2 id="overriding_targets">
325      <title>Overriding Targets</title>
326
327      <para>It's possible to override the functionality of any build
328        target with Tcl code.  A common example is the following which
329        might be useful for a script without a configure script.
330        <filename>configure</filename> script:</para>
331
332      <programlisting>configure    {}</programlisting>
333
334      <para>In the <filename>Portfile</filename>, this will replace
335        the functionality of the <varname>configure</varname> target,
336        thus skipping that step.  It is also possible to execute Tcl
337        code immediately before or after any of the standard targets.
338        This can be accomplished using pre--&lt;target&gt; or
339        post-&lt;target&gt; in the following manner:</para>
340
341      <programlisting>post-configure {
342    reinplace "s|change.this.to.a.server|irc.openprojects.net|g" \
343              "${workdir}/${worksrcdir}/config.h"
344}</programlisting>
345
346      <para>This example replaces the occurrence of
347        <varname>change.this.to.a.server</varname> with
348        <varname>irc.freenode.net</varname> in the
349        <filename>config.h</filename> file that was generated during
350        the preceding <varname>configure</varname> phase.  Note this
351        is a somewhat contrived example, since the same could have
352        been accomplished by specifying
353        <varname>--with-default-server=irc.freenode.net</varname>
354        in <varname>configure.args</varname>, but the approach is
355        generally useful when such configure arguments aren't
356        present.</para>
357    </sect2>
358
359    <sect2 id="variants">
360      <title>Portfile Variants</title>
361
362      <para>Since Darwin 6.0 has ipv6, it would be possible to
363        configure with the <varname>--with-ipv6</varname> option.
364        This can be done by adding the following option to the
365        <filename>Portfile</filename>:</para>
366
367      <programlisting>configure.args      --disable-ipv6
368
369variant ipv6 {
370    configure.args-append  --enable-ipv6
371}</programlisting>
372
373      <para>Now the default build will not include ipv6 support, but
374        if the ipv6 variant is requested, ircII will have it.  Options
375        by themselves should be thought of as an assignment operator.
376        Since variants may be used in combination with one another,
377        it's good practice to only append to options instead of
378        overwriting them.  All options may be suffixed with
379        <varname>-append</varname> or <varname>-delete</varname> to
380        append or delete one term from the list.  You can specify
381        building with the ipv6 variant in the following way:</para>
382
383      <para><userinput>port build +ipv6</userinput></para>
384    </sect2>
385     
386    <sect2 id="mirror_sites">
387      <title>Mirror Site Lists</title>
388
389      <para>It is possible to use predefined lists of mirror sites in
390        your <filename>Portfile</filename>, such as SourceForge or GNU
391        mirrors.  A full list of mirror site types is available in
392        Chapter 3, 'Fetch phase'.  The straight-forward usage is:</para>
393
394      <programlisting>master_sites                sourceforge http://distfiles.opendarwin.org/
395master_sites.mirror_subdir  ${name}</programlisting>
396
397      <para>This will search all of the mirror sites for SourceForge and
398        then http://distfiles.opendarwin.org, appending
399        <varname>${name}</varname> to the end of each SoureForge mirror
400        site in the list, for example:</para>
401
402      <programlisting>http://us.dl.sourceforge.net/${name}
403ftp://us.dl.sourceforge.net/pub/sourceforge/${name}</programlisting>
404
405      <para>You can also use the mirror site lists in
406        <varname>patch_sites</varname> and use
407        <varname>patch_sites.mirror_subdir</varname> to specify the
408        subdirectory.  For more information and advanced usage of mirror
409        site lists (i.e. distfile tags, multiple lists with different
410        subdirectories), please see Chapter 3, 'Fetch Phase'.</para>
411    </sect2>
412
413    <sect2 id="additional options">
414      <title>Additional Options</title>
415
416      <para>There are additional options that are commonly used in
417        <filename>Portfile</filename>s.  The following are commonly
418        used options that may be useful:</para>
419
420      <variablelist>
421        <varlistentry>
422          <term><varname>distfile</varname></term>
423
424          <listitem>
425            <para><varname>distfile</varname> is the name and version
426              combined with the <varname>extract_sufx</varname> (by
427              default <filename>${name}-${version}.tar.gz</filename>)
428              by default, and is used by DarwinPorts to fetch the
429              distribution file.  If the name of the file on the server
430              is not the same as <filename>${name}-${version}.tar.gz
431              </filename> you can use this option to override the default
432              <varname>distfile</varname> name. </para>
433          </listitem>
434        </varlistentry>
435       
436        <varlistentry>
437          <term><varname>depends_lib</varname></term>
438
439          <listitem>
440            <para><varname>depends_lib</varname> is used if the port
441              needs other libraries or binaries to be installed in order
442              to <varname>configure</varname> and run.  It takes three
443              terms, separated by colons.  The first term is
444              <varname>bin</varname> or <varname>lib</varname>.  This
445              defines the search path the port system will look for the
446              dependency in.  If <varname>bin</varname> is specified,
447              <varname>$PATH</varname> is searched for the dependency.
448              If <varname>lib</varname> is specified, the library path
449              is searched instead.  The second term is a regular
450              expression that is used to search the search path for the
451              dependency.  Usually the name of the library is good
452              enough.  The port system will append
453              <filename>.dylib</filename> to the reg-ex so only dynamic
454              libraries will be matched.  The third term is the name of
455              the port that can provide the dependency if it is not
456              satisfied by something already installed on the
457              system.</para>
458          </listitem>
459        </varlistentry>
460
461        <varlistentry>
462          <term><varname>patchfiles</varname></term>
463
464          <listitem>
465            <para><varname>patchfiles</varname> is a list of patches to
466              be applied to the port (needed for the software to
467              compile/run or install correctly).  Patches are usually
468              provided in a <filename>files/</filename> directory in the
469              same directory as the
470              <filename>Portfile</filename>.</para>
471          </listitem>
472        </varlistentry>
473      </variablelist>
474
475      <para>Please take a look at the other chapters in this
476        Guide for more detailed information about these and other
477        options.</para>
478    </sect2>
479  </sect1>
480
481  <sect1 id="common_mistakes">
482    <title>Common Mistakes</title>
483
484    <sect2 id="dont_wrap_brackets">
485     <title>Don't quote or wrap items in '{}'.</title> 
486       
487      <para> Frequently people submit ports with the description or
488        configure arguments quoted, or wrapped in curly brackets. In
489        general this is not correct.  </para>
490    </sect2>
491  </sect1>
492
493  <sect1 id="testing_hints">
494    <title>Testing <filename>Portfiles</filename>: Tips and Hints</title>
495
496    <sect2 id="debug_verbose_msgs">
497      <title>Debugging and Verbose Messages</title>
498
499      <para>You should use the <option>-d</option> and
500        <option>-v</option> switches to <command>port</command> to
501        enable debugging and verbose messages, respectively.</para>
502    </sect2>
503
504    <sect2 id="local_repository">
505      <title>Use a Local Portfile Repository</title>
506
507      <para> Enable a second local source
508        (<filename>Portfile</filename>) repository for your
509        uncommitted ports.  Edit
510        <filename>/etc/ports/sources.conf</filename> and
511        add:<userinput>file:///User/foo/dports-dev</userinput> (or
512        wherever your local dport tree is).</para>
513
514      <para> Create an index file from the local source repository
515        root. This will also perform a simple syntax check Portfiles
516        contained.</para>
517       
518      <para><userinput>portindex</userinput></para>
519    </sect2>
520
521    <sect2 id="testing_destroot">
522      <title>Testing Destroot</title>
523     
524      <para>First run port install without root privileges, this is a
525        good way to check that the port installs into the destroot and
526        not directly into the main prefix directory, or elsewhere in
527        the system.  This should succeed up to the point darwinports
528        attempts to copy the port from the destroot into the
529        darwinports prefix. Once you are confident the port is
530        correctly destrooted install the port into the darwinports
531        prefix using root privileges. </para>
532     
533      <para><userinput>sudo port install foo</userinput></para>
534
535      <para> Ensure the Port installs into the destroot and does not
536        install anything onto the system directly, most software that
537        uses autoconf should behave correctly automatically as
538        darwinports sets DESTDIR by default. If files are directly
539        installed to the system they will not be registered and
540        packaging will fail. </para>
541    </sect2>
542
543    <sect2 id="test_uninstall">
544      <title>Test Uninstall</title>
545
546      <para> Uninstall the port </para>
547       
548      <para><userinput>sudo port uninstall foo</userinput></para>
549    </sect2>
550
551    <sect2 id="try_clean_machine">
552      <title>Try the Port on a Clean Machine</title>
553
554      <para> Make sure the port builds, installs and uninstalls on
555      a &quot;clean machine&quot;. A clean machine should have a
556      clean install of the OS, to avoid missing dependencies. 
557      Using a chrooted version of the OS to install and test ports
558      makes this much easier, see the chroot
559      <ulink url="http://darwinports.gene-hacker.net/docs/howto/chroot_10.2/index.html">
560      HOWTO</ulink> for more details on how to set up the chroot. </para>
561    </sect2>
562       
563
564    <sect2 id="clean_workdir">
565      <title>Clean the Working Directory after an Error</title>
566
567      <para> Clean the working source directory for a port. This will
568        allow a clean reinstall if an error was encountered earlier in
569        the build process.</para>
570     
571      <para> <userinput> port clean foo </userinput> </para>
572    </sect2>
573       
574  </sect1>
575   
576  <sect1 id="advice">
577    <title>Where can I ask for advice?</title> 
578
579    <para>Either on the <email>darwinports@opendarwin.org</email>
580      mailing list, or on the #opendarwin channel on irc.freenode.net.
581      Don't be afraid to ask questions! You should also look at the
582      later sections of the <link linkend="details">guide</link>and the
583      <filename>portfile</filename>(7) and
584      <filename>portstyle</filename>(7) manpages for more information.</para>
585
586  </sect1>
587
588  <sect1 id="submit_ports">
589    <title>How do I submit my Ports</title>
590     
591    <para>See the <link linkend="submission">submission chapter</link> for
592    all the information on how to submit a port properly.</para>
593  </sect1>
594
595  <sect1 id="more_examples">
596    <title>More Example <filename>Portfile</filename>s</title>
597
598    <example id="expat">
599      <title>Expat <filename>Portfile</filename></title>
600      <programlisting><![CDATA[########################### libxslt Portfile ##################################
601# $Id: quick.xml,v 1.13 2003/07/20 17:00:53 fkr Exp $
602
603PortSystem      1.0
604
605name            libxslt
606version         1.0.21
607homepage        http://www.xmlsoft.org/
608description     gnome xslt library and xsltproc
609categories      textproc
610platforms       darwin
611maintainers     mike+libxslt@gene-hacker.net
612master_sites    ftp://xmlsoft.org/ \
613                ftp://ftp.gnome.org/pub/GNOME/sources/libxslt/1.0/
614
615checksums       md5 9cc0491e2584788748eb7069ea1d5277
616depends_lib     lib:libxml2:libxml2
617patchfiles      patch-aclocal.m4 patch-configure patch-ltmain.sh
618
619long_description Gnome library for applying XSL stylesheet transformations to \
620 xml files, comes with several useful binaries.
621
622###########################################################################]]></programlisting>
623    </example>
624
625    <example id="neon">
626      <title>Neon <filename>Portfile</filename></title>
627
628<programlisting><![CDATA[###########################neon Portfile####################################
629# $Id: quick.xml,v 1.13 2003/07/20 17:00:53 fkr Exp $
630         
631PortSystem 1.0
632name            neon
633version         0.23.4
634                         
635categories      www
636maintainers     rooneg@electricjellyfish.net
637description     An HTTP and WebDAV client library with a C interface
638                         
639master_sites    http://www.webdav.org/neon/
640checksums       md5 56b380a7352c68d425b1d3d3d610f994
641
642depends_lib     lib:libexpat.0.4:expat
643configure.env   LDFLAGS='-L"${prefix}/lib"' CPPFLAGS='-I"${prefix}/include"'
644
645configure.args  --with-ssl \
646                --with-force-ssl \
647                --enable-xml \
648                --enable-shared \
649                --with-expat
650
651############################################################################]]></programlisting>
652    </example>
653
654    <para>For more examples, you can browse the directory tree of
655      DarwinPorts' <filename>dports</filename> directory and have a look
656      at the <filename>Portfile</filename>s of your favorite
657      ports.</para>
658   
659    <para>For more information about some options used in these
660      <filename>Portfile</filename> examples that were not covered in
661      this chapter, please take a look at the following chapters of this
662      Guide.</para>
663  </sect1>
664</chapter>
Note: See TracBrowser for help on using the repository browser.