source: trunk/doc-new/guide/xml/portfiledev.xml @ 105460

Last change on this file since 105460 was 105460, checked in by mk@…, 7 years ago

Guide: describe portgroup obsolete

File size: 42.0 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
3"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
4<chapter id="development">
5  <title>Portfile Development</title>
6
7  <para>This chapter covers a brief introduction to Portfiles, how to create a
8  local Portfile repository for development, and creating Portfiles.</para>
9
10  <section id="development.introduction">
11    <title>Portfile Introduction</title>
12
13    <para>A MacPorts Portfile is a <ulink
14    url="http://en.wikipedia.org/wiki/Tcl">TCL</ulink> script that usually
15    contains only the simple keyword/value combinations and Tcl extensions as
16    described in the <link linkend="reference">Portfile Reference</link>
17    chapter, though it may also contain arbitrary TCL code. Every port has a
18    corresponding Portfile, but Portfiles do not completely define a port's
19    installation behavior since MacPorts base has default port installation
20    characteristics coded within it. Therefore Portfiles need only specify
21    required options, though some ports may require non-default
22    options.</para>
23
24    <para>A common way for Portfiles to augment or override MacPorts base
25    default installation phase characteristics is by using
26    <filename>Portfile</filename> phase declaration(s). If you use Portfile
27    phase declaration(s), you should know how to identify the
28    <quote>global</quote> section of a Portfile. Any statements not contained
29    within a phase declaration, no matter where they are located in a Portfile,
30    are said to be in the global section of the Portfile; therefore the global
31    section need not be contiguous. Likewise, to remove statements from the
32    global section they must be placed within a phase declaration.</para>
33
34    <para>The main phases you need to be aware of when making a Portfile are
35    these:</para>
36
37    <itemizedlist>
38      <listitem>
39        <para>Fetch</para>
40      </listitem>
41
42      <listitem>
43        <para>Extract</para>
44      </listitem>
45
46      <listitem>
47        <para>Patch</para>
48      </listitem>
49
50      <listitem>
51        <para>Configure</para>
52      </listitem>
53
54      <listitem>
55        <para>Build</para>
56      </listitem>
57
58      <listitem>
59        <para>Destroot</para>
60      </listitem>
61    </itemizedlist>
62
63    <para>The default installation phase behavior performed by the MacPorts
64    base works fine for applications that use the standard
65    <command>configure</command>, <command>make</command>, and <command>make
66    install</command> steps, which conform to phases configure, build, and
67    destroot respectively. For applications that do not conform to this
68    standard behavior, any installation phase may be augmented using <link
69    linkend="development.examples.augment">pre- and/or post- phases</link>, or
70    even <link linkend="development.examples.override">overridden</link> or
71    <link linkend="development.examples.eliminate">eliminated</link>. See
72    <link linkend="development.examples">Example Portfiles</link>
73    below.</para>
74
75    <note>
76      <para>For a detailed description of all port phases, see the <link
77      linkend="reference.phases">Portfile Reference</link> chapter.</para>
78    </note>
79  </section>
80
81  <section id="development.creating-portfile">
82    <title>Creating a Portfile</title>
83
84    <para>Here we list the individual Portfile components for an application
85    that conforms to the standard <command>configure</command>,
86    <command>make</command>, and <command>make install</command> steps of most
87    open source application installs.</para>
88
89    <orderedlist>
90      <listitem>
91        <para>Modeline</para>
92
93        <para>This should be the first line of a Portfile. It sets the correct
94        editing options for vim and emacs. See <link
95        linkend="development.practices.portstyle">Port Style</link> for more
96        information. Its use is optional and up to the port maintainer.</para>
97
98        <programlisting># -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4</programlisting>
99      </listitem>
100
101      <listitem>
102        <para>Subversion ID tag line</para>
103
104        <para>This must be a Portfile's second line (or the first, if a
105        modeline is not used). When a port is committed to the repository, ID
106        tags are expanded to include the filename and the revision number,
107        date and time, and author of the last commit.</para>
108
109        <programlisting># $Id$</programlisting>
110      </listitem>
111
112      <listitem>
113        <para>PortSystem line</para>
114
115        <para>This statement is required for all ports.</para>
116
117        <programlisting>PortSystem          1.0</programlisting>
118      </listitem>
119
120      <listitem>
121        <para>Port name</para>
122
123        <programlisting>name                rrdtool</programlisting>
124      </listitem>
125
126      <listitem>
127        <para>Port version</para>
128
129        <programlisting>version             1.2.23</programlisting>
130      </listitem>
131
132      <listitem>
133        <para>Port categories</para>
134
135        <para>A port may belong to more than one category, but the first
136        (primary) category should match the directory name in the ports tree
137        where the Portfile is to reside.</para>
138
139        <programlisting>categories          net</programlisting>
140      </listitem>
141
142      <listitem>
143        <para>Platform statement</para>
144
145        <programlisting>platforms           darwin</programlisting>
146      </listitem>
147
148<!--
149      <listitem>
150          <para>Port license</para>
151
152        <para>A port's license indicates the class of license employed by the
153        owner. Setting this signals the main intentions of the license with
154        respect to binary and source distribution. It is presently only for
155        informational purposes and MacPorts does not distribute binaries.</para>
156
157        <itemizedlist>
158          <listitem>
159            <para><varname>GPL</varname> – signifies the requirements of GNU
160            General Public    License; the source be available in the same place
161            as the binary.</para>
162
163            <para><varname>LGPL</varname> – use this for the GNU Lesser General
164            Public License,    which mandates that    the source and binary are
165            available in the same place.</para>
166
167            <para><varname>BSD</varname> – covering the original and new BSD
168            license as well as MIT and Apache; these licenses allow for optional
169            inclusion of source code.</para>
170
171            <para><varname>Artistic</varname> – aptly named to indicate the
172            Artistic license and derivatives.</para>
173
174            <para><varname>Artistic-GPL</varname> – dual-licensed under the
175            Artistic and GPL licenses.</para>
176
177            <para><varname>/GFDL</varname> and <varname>/LDP</varname> – these
178            suffixes indicate that the documentation provided is under the GNU
179            Free Documentation License or the Linux Documentation Project</para>
180
181            <para><varname>RESTRICT</varname> – when the licenses are
182            restrictive.</para>
183
184            <para><varname>RESTRICT-EYESONLY</varname> – if the license does not
185            permit distribution.</para>
186
187            <para><varname>PUBLIC</varname> – the code is not copyrighted:
188            anyone can do anything</para>
189          </listitem>
190        </itemizedlist>
191      </listitem>
192-->
193      <listitem>
194        <para>Port maintainers</para>
195
196        <para>A port's maintainers are the people who have agreed to take
197        responsibility for keeping the port up-to-date. The
198        <literal>maintainers</literal> keyword lists the maintainers' email
199        addresses, preferrably in the obfuscated form which hides them
200        from spambots. For more, see the full explanation of the <link
201        linkend="reference.keywords.maintainers">maintainers keyword</link> in
202        the <link linkend="reference.keywords">Global Keywords</link> section
203        of the <link linkend="reference">Portfile Reference</link>
204        chapter.</para>
205
206        <programlisting>maintainers         jdoe \
207                    example.org:julesverne</programlisting>
208      </listitem>
209
210      <listitem>
211        <para>Port description</para>
212
213        <programlisting>description         Round Robin Database</programlisting>
214      </listitem>
215
216      <listitem>
217        <para>Port long_description</para>
218
219        <programlisting>long_description    RRDtool is a system to store and display time-series \
220                    data</programlisting>
221      </listitem>
222
223      <listitem>
224        <para>A port's application homepage</para>
225
226        <programlisting>homepage            http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/</programlisting>
227      </listitem>
228
229      <listitem>
230        <para>A port's download URLs</para>
231
232        <programlisting>master_sites        http://oss.oetiker.ch/rrdtool/pub/ \
233                    ftp://ftp.pucpr.br/rrdtool/</programlisting>
234      </listitem>
235
236      <listitem>
237        <para>Port checksums</para>
238
239        <para>The checksums specified in a Portfile are checked with the
240        fetched tarball for security. For the best security, use rmd160
241        and sha256 checksum types.</para>
242
243        <programlisting>checksums               rmd160  7bbfce4fecc2a8e1ca081169e70c1a298ab1b75a \
244                        sha256  2829fcb7393bac85925090b286b1f9c3cd3fbbf8e7f35796ef4131322509aa53</programlisting>
245
246        <para>To find the correct checksums for a port's distribution file,
247        follow this example:</para>
248
249        <programlisting><prompt>%%</prompt> <userinput>openssl rmd160 rrdtool-1.2.23.tar.gz</userinput>
250<prompt>%%</prompt> <userinput>openssl sha256 rrdtool-1.2.23.tar.gz</userinput></programlisting>
251
252        <screen>RIPEMD160( ... rrdtool-1.2.23.tar.gz)= 7bbfce4fecc2a8e1ca081169e70c1a298ab1b75a
253
254SHA256( ... rrdtool-1.2.23.tar.gz)= 2829fcb7393bac85925090b286b1f9c3cd3fbbf8e7f35796ef4131322509aa53</screen>
255      </listitem>
256
257      <listitem>
258        <para>Port dependencies</para>
259
260        <para>A port's dependencies are ports that must be installed before
261        another port is installed.</para>
262
263        <programlisting>depends_lib         port:perl5.8 \
264                    port:tcl \
265                    port:zlib</programlisting>
266      </listitem>
267
268      <listitem>
269        <para>Port configure arguments (optional)</para>
270
271        <programlisting>configure.args      --enable-perl-site-install \
272                    --mandir=${prefix}/share/man</programlisting>
273      </listitem>
274    </orderedlist>
275  </section>
276
277  <section id="development.examples">
278    <title>Example Portfiles</title>
279
280    <para>In this section we begin by taking a look at a complete simple
281    Portfile; then we see how to <link
282    linkend="development.examples.augment">augment default phases</link> by
283    defining pre- and post- phases, how to <link
284    linkend="development.examples.override">override default phases</link>,
285    and finally how to <link
286    linkend="development.examples.eliminate">eliminate port
287    phases</link>.</para>
288
289    <section id="development.examples.basic">
290      <title>A Basic Portfile</title>
291
292      <programlisting># $Id$
293
294PortSystem          1.0
295
296name                rrdtool
297version             1.2.23
298categories          net
299platforms           darwin
300license             GPL
301maintainers         julesverne
302description         Round Robin Database
303long_description    RRDtool is a system to store and display time-series data
304homepage            http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/
305master_sites        http://oss.oetiker.ch/rrdtool/pub/ \
306                    ftp://ftp.pucpr.br/rrdtool/
307
308checksums           rmd160  7bbfce4fecc2a8e1ca081169e70c1a298ab1b75a \
309                    sha256  2829fcb7393bac85925090b286b1f9c3cd3fbbf8e7f35796ef4131322509aa53
310
311depends_lib         path:bin/perl:perl5 \
312                    port:tcl \
313                    port:zlib
314
315configure.args      --enable-perl-site-install \
316                    --mandir=${prefix}/share/man</programlisting>
317    </section>
318
319    <section id="development.examples.augment">
320      <title>Augment Phases Using pre- / post-</title>
321
322      <para>To augment a port's installation phase, and not override it, you
323      may use pre- and post- installation phases as shown in this
324      example.</para>
325
326      <programlisting>post-destroot {
327    # Install example files not installed by the Makefile
328    file mkdir ${destroot}${prefix}/share/doc/${name}/examples
329    file copy ${worksrcpath}/examples/ \
330        ${destroot}${prefix}/share/doc/${name}/examples
331}</programlisting>
332    </section>
333
334    <section id="development.examples.override">
335      <title>Overriding Phases</title>
336
337      <para>To override the automatic MacPorts installation phase processing,
338      define your own installation phases as shown in this example.</para>
339
340      <programlisting>destroot {
341    xinstall -m 755 -d ${destroot}${prefix}/share/doc/${name}
342    xinstall -m 755 ${worksrcpath}/README ${destroot}${prefix}/share/doc/${name}
343}</programlisting>
344    </section>
345
346    <section id="development.examples.eliminate">
347      <title>Eliminating Phases</title>
348
349      <para>To eliminate a default phase, simply define a phase with no
350      contents as shown.</para>
351
352      <programlisting>build {}</programlisting>
353
354      <note>
355        <para>Because many software packages do not use
356        <option>configure</option>, a keyword is provided to eliminate the
357        <option>configure</option> phase. Another exception is the
358        <option>destroot</option> phase may not be eliminated. See the
359        chapter <link linkend="reference">Portfile Reference</link> for full
360        information.</para>
361      </note>
362    </section>
363
364    <section id="development.examples.startupitem">
365      <title>Creating a StartupItem</title>
366
367      <para>Startupitems may be placed in the global section of a
368      Portfile.</para>
369
370      <programlisting>startupitem.create      yes
371startupitem.name        nmicmpd
372startupitem.executable  "${prefix}/bin/nmicmpd"</programlisting>
373
374      <para>Startupitems keywords may also be used within a variant definition
375      to make their installation conditional.</para>
376
377      <programlisting>variant server {
378    startupitem.create  yes
379    startupitem.start   "${prefix}/share/${name}/vm-pop3d.init start"
380    startupitem.stop    "${prefix}/share/${name}/vm-pop3d.init stop"
381}</programlisting>
382    </section>
383  </section>
384
385  <section id="development.variants">
386    <title>Port Variants</title>
387
388    <para>Variants are a way for port authors to provide options that may be
389    invoked at install time. They are declared in the global section of a
390    Portfile using the <quote>variant</quote> keyword, and should include <link
391    linkend="reference.variants.descriptions">carefully chosen variant
392    descriptions</link>.</para>
393
394    <section id="development.variants.options">
395      <title>Example Variants</title>
396
397      <para>The most common actions for user-selected variants is to add or
398      remove dependencies, configure arguments, and build arguments according
399      to various options a port author wishes to provide. Here is an example
400      of several variants that modify depends_lib and configure arguments for
401      a port.</para>
402
403      <programlisting>variant fastcgi description {Add fastcgi binary} {
404    configure.args-append \
405            --enable-fastcgi \
406            --enable-force-cgi-redirect \
407            --enable-memory-limit
408}
409
410variant gmp description {Add GNU MP functions} {
411    depends_lib-append port:gmp
412    configure.args-append --with-gmp=${prefix}
413
414}
415
416variant sqlite description {Build sqlite support} {
417    depends_lib-append \
418        port:sqlite3
419    configure.args-delete \
420        --without-sqlite \
421        --without-pdo-sqlite
422    configure.args-append \
423        --with-sqlite \
424        --with-pdo-sqlite=${prefix} \
425        --enable-sqlite-utf8
426}</programlisting>
427
428      <note>
429        <para>Variant names may contain only the characters A-Z, a-z, and the
430        underscore character <quote>_</quote>. Therefore, take care to never
431        use hyphens in variant names.</para>
432      </note>
433
434      <para>In the example variant declaration below, the configure argument
435      <literal>--without-x</literal> is removed and a number of others are
436      appended.</para>
437
438      <programlisting>variant x11 description {Builds port as an X11 program with Lucid widgets} {
439    configure.args-delete   --without-x
440    configure.args-append   --with-x-toolkit=lucid \
441                            --without-carbon \
442                            --with-xpm \
443                            --with-jpeg \
444                            --with-tiff \
445                            --with-gif \
446                            --with-png
447    depends_lib-append      lib:libX11:XFree86 \
448                            lib:libXpm:XFree86 \
449                            port:jpeg \
450                            port:tiff \
451                            port:libungif \
452                            port:libpng
453}</programlisting>
454    </section>
455
456    <section id="development.variants.phase">
457      <title>Variant Actions in a Phase</title>
458
459      <para>If a variant requires options in addition to those provided by
460      keywords using -append and/or -delete, in other words, any actions that
461      would normally take place within a port installation phase, do not try
462      to do this within the variant declaration. Rather, modify the behavior
463      of any affected phases when the variant is invoked using the
464      variant_isset keyword.</para>
465
466      <programlisting>post-destroot {
467    xinstall -m 755 -d ${destroot}${prefix}/etc/
468    xinstall ${worksrcpath}/examples/foo.conf \
469        ${destroot}${prefix}/etc/
470
471    if {[variant_isset carbon]} {
472        delete ${destroot}${prefix}/bin/emacs
473        delete ${destroot}${prefix}/bin/emacs-${version}
474    }
475}</programlisting>
476    </section>
477
478    <section id="development.variants.default">
479      <title>Default Variants</title>
480
481      <para>Variants are used to specify actions that lie outside the core
482      functions of an application or port, but there may be some cases where
483      you wish to specify these non-core functions by default. For this
484      purpose you may use the keyword default_variants.</para>
485
486      <programlisting>default_variants    +foo +bar</programlisting>
487
488      <!-- TODO: add warning not to use default_variant at the moment -->
489
490      <note>
491        <para>The default_variant keyword may only be used in the global
492        Portfile section.</para>
493      </note>
494    </section>
495  </section>
496
497  <section id="development.patches">
498    <title>Patch Files</title>
499
500    <para>Patch files are files created with the Unix command
501    <command>diff</command> that are applied using the command
502    <command>patch</command> to modify text files to fix bugs or extend
503    functionality.</para>
504
505    <section id="development.patches.portfile">
506      <title>Creating Portfile Patches</title>
507
508      <para>If you wish to contribute modifications or fixes to a Portfile,
509      you should do so in the form of a patch. Follow the steps below to
510      create Portfile patch files</para>
511
512      <orderedlist>
513        <listitem>
514          <para>Make a copy of the Portfile you wish to modify; both files
515          must be in the same directory, though it may be any
516          directory.</para>
517
518          <programlisting><prompt>%%</prompt> <userinput>cp -p Portfile Portfile.orig</userinput></programlisting>
519        </listitem>
520
521        <listitem>
522          <para>Edit the file to make it as you want it to be after it is
523          fetched.</para>
524        </listitem>
525
526        <listitem>
527          <para>Now use the Unix command <command>diff -u </command>to create
528          a <quote>unified</quote> diff patch file. Put the name of the port in
529          the patchfile, for example, Portfile-rrdtool.diff.</para>
530
531          <programlisting><prompt>%%</prompt> <userinput>diff -u Portfile.orig Portfile &gt; Portfile-rrdtool.diff</userinput></programlisting>
532        </listitem>
533
534        <listitem>
535          <para>A patch file that is a <quote>unified</quote> diff file is the
536          easiest to interpret by humans and this type should always be used
537          for ports. The Portfile patch below will change the version and
538          checksums when applied.</para>
539
540          <programlisting>--- Portfile.orig        2011-07-25 18:52:12.000000000 -0700
541+++ Portfile    2011-07-25 18:53:35.000000000 -0700
542@@ -2,7 +2,7 @@
543 PortSystem          1.0
544 name                foo
545 
546-version             1.3.0
547+version             1.4.0
548 categories          net
549 maintainers         nomaintainer
550 description         A network monitoring daemon.
551@@ -13,9 +13,9 @@
552 
553 homepage            http://rsug.itd.umich.edu/software/${name}
554 
555 master_sites        ${homepage}/files/
556-checksums           rmd160 f0953b21cdb5eb327e40d4b215110b71
557+checksums           rmd160 01532e67a596bfff6a54aa36face26ae
558 extract.suffix      .tgz
559 platforms           darwin
560</programlisting>
561        </listitem>
562      </orderedlist>
563
564      <para>Now you may attach the patch file to a MacPorts Trac ticket for
565      the port author to evaluate.</para>
566    </section>
567
568    <section id="development.patches.source">
569      <title>Creating Source Code Patches</title>
570
571      <para>Necessary or useful patches to application source code should
572      generally be sent to the application developer rather than the port
573      author so the modifications may be included in the next version of the
574      application.</para>
575
576      <para>Generally speaking, you should create one patch file for each file
577      to be patched. Patchfile filenames should uniquely distinguish the file
578      and generally be of the form
579      <filename>patch-</filename><replaceable>&lt;directory&gt;</replaceable>-<replaceable>&lt;filename&gt;.diff</replaceable>,
580      as shown in this example:
581      <filename>patch-src-Makefile.in.diff</filename>.</para>
582
583      <para>You may use patch files that patch multiple files under these
584      conditions:</para>
585
586      <itemizedlist>
587        <listitem>
588          <para>You find existing patch files that do so.</para>
589        </listitem>
590
591        <listitem>
592          <para>If fixing a particular problem or bug requires changes in
593          multiple files -in those cases the patch filename should reference
594          the problem or bug, for example:
595          <filename>patch-</filename><replaceable>&lt;destroot_variable_fix&gt;.diff</replaceable></para>
596        </listitem>
597      </itemizedlist>
598
599      <para>To create a patch to modify a single file, follow the steps
600      below.</para>
601
602      <orderedlist>
603        <listitem>
604          <para>Locate the file you wish to patch in its original location
605          within the unpacked source directory and make a duplicate of
606          it.</para>
607
608          <programlisting><prompt>%%</prompt> <userinput>cd ~/Downloads/foo-1.34/src</userinput>
609<prompt>%%</prompt> <userinput>cp -p Makefile.in Makefile.in.orig</userinput></programlisting>
610        </listitem>
611
612        <listitem>
613          <para>Edit the file and modify the text to reflect your
614          corrections.</para>
615        </listitem>
616
617        <listitem>
618          <para>Now <command>cd</command> to the top-level directory of the
619          unpacked source, and use the Unix command <command>diff -u</command>
620          to create a <quote>unified</quote> diff patch file.</para>
621
622          <programlisting><prompt>%%</prompt> <userinput>cd ~/Downloads/foo-1.34</userinput>
623<prompt>%%</prompt> <userinput>diff -u src/Makefile.in.orig src/Makefile.in &gt; patch-src-Makefile.in.diff</userinput></programlisting>
624
625          <para>You should execute the <command>diff</command> command from
626          the top-level directory of the unpacked source code, because during
627          the patch phase MacPorts by default uses the patch argument
628          <option>-p0</option>, which does not strip prefixes with any leading
629          slashes from file names found in the patch file (as opposed to
630          <option>-p1</option> that strips one, etc), and any path not
631          relative to the top-level directory of the unpacked source will fail
632          during the patch phase.</para>
633
634          <note>
635            <para>If you find an existing source file patch you wish to use
636            that contains leading path information (diff was executed from a
637            directory higher than the top-level source directory), you will
638            need to use the <link linkend="reference.phases.patch">patch phase
639            keyword</link> <code>patch.pre_args</code> to specify a
640            <option>-px</option> value for how many prefixes with leading
641            slashes are to be stripped off.</para>
642          </note>
643        </listitem>
644
645        <listitem>
646          <para>A patch file that is a <quote>unified</quote> diff file is the
647          easiest to interpret by humans and this type should always be used
648          for ports. See the example below where a patch adds
649          <varname>DESTDIR</varname> support to a
650          <filename>Makefile.in</filename> file.</para>
651
652          <programlisting>--- src/Makefile.in.orig   2007-06-01 16:30:47.000000000 -0700
653+++ src/Makefile.in       2007-06-20 10:10:59.000000000 -0700
654@@ -131,23 +131,23 @@
655        $(INSTALL_DATA)/gdata $(INSTALL_DATA)/perl
656
657 install-lib:
658-       -mkdir -p $(INSTALL_LIB)
659+       -mkdir -p $(DESTDIR)$(INSTALL_LIB)
660        $(PERL) tools/install_lib -s src -l $(INSTALL_LIB) $(LIBS)
661-       cp $(TEXT) $(INSTALL_LIB)/
662+       cp $(TEXT) $(DESTDIR)$(INSTALL_LIB)/</programlisting>
663        </listitem>
664
665        <listitem>
666          <para>Place the patch
667          <filename>patch-src-Makefile.in.diff</filename> in the directory
668          <filename>${portpath}/files</filename> and use it in a port using
669          the <code>patchfiles</code> keyword. <varname>${portpath}</varname>
670          may be in a local Portfile repository during development, or
671          <filename>files/</filename> may be in a port's
672          <varname>${portpath}</varname> in the global MacPorts
673          repository.</para>
674
675          <programlisting>patchfiles          patch-src-Makefile.in.diff</programlisting>
676        </listitem>
677      </orderedlist>
678    </section>
679
680    <section id="development.patches.applying">
681      <title>Manually Applying Patches</title>
682
683      <para>MacPorts applies patch files automatically, but you may want to
684      know how to apply patch files manually if you want to test patch files
685      you have created or you wish to apply uncommitted Portfile
686      patches.</para>
687
688      <orderedlist>
689        <listitem>
690          <para>Change to the directory containing the file to be patched. In
691          this example, we'll apply a Portfile patch to the postfix
692          port.</para>
693
694          <programlisting><prompt>%%</prompt> <userinput>cd $(port dir postfix)</userinput></programlisting>
695        </listitem>
696
697        <listitem>
698          <para>Now apply the patch from your Downloads folder, or wherever you
699          put it. The patchfile knows the name of the file to be patched.</para>
700
701          <programlisting><prompt>%%</prompt> <userinput>patch -p0 &lt; ~/Downloads/Portfile-postfix.diff</userinput></programlisting>
702
703          <screen>patching file Portfile</screen>
704        </listitem>
705      </orderedlist>
706    </section>
707  </section>
708
709  <section id="development.local-repositories">
710    <title>Local Portfile Repositories</title>
711
712    <para>To create and test Portfiles that are not yet committed to
713    Subversion, you may create a local Portfile repository as shown. Replace
714    the hypothetical user <filename>julesverne</filename> with your username
715    in the example below.</para>
716
717    <orderedlist>
718      <listitem>
719        <para>Open the <filename>sources.conf</filename> file in a text
720        editor. For example, to open it into TextEdit:</para>
721
722        <programlisting><prompt>%%</prompt> <userinput>open -e ${prefix}/etc/macports/sources.conf</userinput></programlisting>
723      </listitem>
724
725      <listitem>
726        <para>Insert a URL pointing to your local repository location before
727        the rsync URL as shown.</para>
728
729        <programlisting>file:///Users/julesverne/ports
730rsync://rsync.macports.org/release/ports [default]
731</programlisting>
732
733        <note>
734          <para>The file URL should always appear before the rsync URL so that
735          local Portfiles can be tested that are duplicated in the MacPorts
736          tree, because the <command>port</command> command will always
737          operate on the first Portfile it encounters.</para>
738        </note>
739      </listitem>
740
741      <listitem>
742        <para>Place the Portfiles you create inside a directory whose name
743        matches the port, which should in turn be placed inside a directory
744        that reflects the port's primary category (the first category entry in
745        the Portfile). For example, to create the directory for a hypothetical
746        port <quote>bestevergame</quote> and to begin editing its Portfile in
747        TextEdit, you can use these commands:</para>
748
749        <programlisting><prompt>%%</prompt> <userinput>mkdir -p ~/ports/games/bestevergame</userinput>
750<prompt>%%</prompt> <userinput>cd ~/ports/games/bestevergame</userinput>
751<prompt>%%</prompt> <userinput>touch Portfile</userinput>
752<prompt>%%</prompt> <userinput>open -e Portfile</userinput></programlisting>
753
754        <para>See other sections in the Guide for help writing Portfiles. If
755        you've already written the Portfile elsewhere, you can instead copy
756        the Portfile into this directory.</para>
757      </listitem>
758
759      <listitem>
760        <para>If your Portfile needs to apply any patches to the port's source
761        files, create a <filename>files</filename> directory and place the
762        patchfiles in it, and reference the patchfiles in your Portfile, as
763        explained in
764        <link linkend="development.patches.source">Creating Source Code Patches</link>.</para>
765      </listitem>
766
767      <listitem>
768        <para>After you create or update your Portfile, use the MacPorts
769        <command>portindex</command> command in the local repository's
770        directory to create or update the index of the ports in your local
771        repository.</para>
772
773        <programlisting>%% <userinput>cd ~/ports</userinput>
774%% <userinput>portindex</userinput></programlisting>
775
776        <screen>Creating software index in /Users/julesverne/ports
777Adding port games/bestevergame
778
779Total number of ports parsed:   1
780Ports successfully parsed:      1
781Ports failed:                   0</screen>
782      </listitem>
783    </orderedlist>
784
785    <para>Once the local port is added to the <filename>PortIndex</filename>,
786    it becomes available for searching or installation as with any other
787    Portfile in the MacPorts tree:</para>
788
789    <programlisting><prompt>%%</prompt> <userinput>port search bestever</userinput></programlisting>
790
791    <screen>bestevergame @1.1 (games)
792    The Best Ever Game</screen>
793  </section>
794
795  <section id="development.practices">
796    <title>Portfile Best Practices</title>
797
798    <para>This section contains practical guidelines for creating Portfiles
799    that install smoothly and provide consistency between ports. The following
800    sections are on the TODO list.</para>
801
802    <section id="development.practices.portstyle">
803      <title>Port Style</title>
804
805      <para>Portfiles may be thought of as a table of keys and values in two
806      columns separated by spaces (not tabs), so you should set your editor to
807      use soft tabs, which are tabs emulated by spaces. By default, the top
808      line of all Portfiles should use a modeline that defines soft tabs for
809      the vim and emacs editors as shown.</para>
810
811      <programlisting># -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4</programlisting>
812
813      <para>The left column should consist of single words, and will be
814      separated from the more complex right side by spaces in multiples of
815      four. Variable assignments and variant declarations are exceptions, and
816      may be considered a single word on the left side, with a single space
817      between words.</para>
818
819      <programlisting>set libver "8.5"
820
821
822variant mysql5 { ... }</programlisting>
823
824      <para>Frequently multiple items are necessary in the second column. For
825      example, to set multiple source download locations, multiple
826      <code>master_sites</code> must be defined. Unless the second column
827      items are few and short you should place each additional item on a new
828      line and separate lines with a backslash. Indent the lines after the
829      first line to make it clear the items are second column values and also
830      to emphasize the unity of the block.</para>
831
832      <programlisting>destroot.keepdirs    ${destroot}${prefix}/var/run \
833                     ${destroot}${prefix}/var/log \
834                     ${destroot}${prefix}/var/cache/mrtg</programlisting>
835    </section>
836
837    <section id="development.practices.dont-overwrite">
838      <title>Don't Overwrite Config Files</title>
839
840      <para>TODO:</para>
841    </section>
842
843    <section id="development.practices.install-docs">
844      <title>Install Docs and Examples</title>
845
846      <para>TODO:</para>
847    </section>
848
849    <section id="development.practices.provide-messages">
850      <title>Provide User Messages</title>
851
852      <para>TODO:</para>
853    </section>
854
855    <section id="development.practices.use-variables">
856      <title>Use Variables</title>
857
858      <para>TODO: Set variables so changing paths may be done in one place;
859      use them anytime it makes updates simpler: distname
860      ${name}-src-${version}</para>
861    </section>
862
863
864    <section id="development.practices.rename-replace-port">
865      <title>Renaming or replacing a port</title>
866
867      <para>If there is the need to replace a port with another port or a
868      renaming is necessary for some reason, the port should be marked as
869      <code>replaced_by</code>.</para>
870     
871      <para>As an illustration of a typical workflow the port
872      <quote>skrooge-devel</quote> shall be taken. This port had been used for
873      testing new versions of skrooge, but it turned out to have become
874      unnecessary due to the fact that skrooge's developers currently prefer a
875      distribution via port <quote>skrooge</quote> instead. </para>
876     
877      <para>At the end of this section the use of the obsolete PortGroup is suggested
878      as an even shorter approach to the below described workflow.</para>
879
880      <section id="development.replaced_by">
881      <title>The long way</title>
882
883      <para>Skrooge's original devel port file looked like this:</para>
884
885<programlisting># -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; truncate-lines: t -*- vim:fenc=utf-8:et:sw=4:ts=4:sts=4
886# $Id$
887
888PortSystem          1.0
889PortGroup           kde4    1.1
890
891fetch.type          svn
892svn.url             svn://anonsvn.kde.org/home/kde/trunk/extragear/office/skrooge
893svn.revision        1215845
894
895name                skrooge-devel
896version             0.8.0-${svn.revision}
897
898categories          kde finance
899maintainers         mk pixilla openmaintainer
900description         Skrooge
901long_description    Personal finance management tool for KDE4, with the aim of being highly intuitive, while \
902                    providing powerful functions such as reporting (including graphics), persistent \
903                    Undo/Redo, encryption, and much more...
904
905conflicts           skrooge
906
907platforms           darwin
908license             GPL-3
909
910homepage            http://skrooge.org
911master_sites        http://skrooge.org/files/
912
913livecheck.type      none
914
915distname            skrooge
916
917depends_lib-append  port:kdelibs4 \
918                    port:libofx \
919                    port:qca-ossl \
920                    port:kdebase4-runtime \
921                    port:oxygen-icons</programlisting>
922
923        <para>The following steps have to be taken to ensure a smooth transition
924        for a MacPorts user updating his local installation using
925        <userinput>sudo port upgrade</userinput>:</para>
926
927    <orderedlist>
928      <listitem>
929        <para> add the line <code>replaced_by foo</code> where foo is the
930        port this one is replaced by; when a user upgrades this port,
931        MacPorts will instead install the replacement port</para>
932                <programlisting>replaced_by         skrooge</programlisting>
933      </listitem>
934
935      <listitem>
936        <para> increase the version, revision, or epoch, so that users who
937        have this port installed will get notice in <code>port
938        outdated</code> that they should upgrade it and trigger the above
939        process</para>
940                <programlisting>revision            1</programlisting>
941      </listitem>
942
943      <listitem>
944        <para> clear distfiles (have a line reading only
945        <code>distfiles</code>) so that no distfile is downloaded for this
946        stub port</para>
947                <programlisting>distfiles</programlisting>
948      </listitem>
949
950      <listitem>
951        <para> delete master_sites since there aren't any distfiles to
952        download</para>
953      </listitem>
954
955      <listitem>
956        <para> disable livecheck</para>
957        <programlisting>livecheck.type      none</programlisting>
958      </listitem>
959
960      <listitem>
961        <para> add a pre-configure block with a <code>ui_error</code> and
962        <code>return -code error</code> explaining to users who try to
963        install this port that the port has been replaced</para>
964                <programlisting>pre-configure {
965    ui_error "Please do not install this port since it has been replaced by 'skrooge'."
966    return -code error
967}</programlisting>
968      </listitem>
969    </orderedlist>
970
971        <para>With above modifications the port file eventually looks like
972        this:</para>
973
974<programlisting># -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; truncate-lines: t -*- vim:fenc=utf-8:et:sw=4:ts=4:sts=4
975# $Id$
976
977PortSystem          1.0
978
979name                skrooge-devel
980svn.revision        1215845
981version             0.8.0-${svn.revision}
982revision            1
983
984replaced_by         skrooge
985
986categories          kde finance
987maintainers         mk pixilla openmaintainer
988description         Skrooge
989long_description    Personal finance management tool for KDE4, with the aim of being highly intuitive, while \
990                    providing powerful functions such as reporting (including graphics), persistent \
991                    Undo/Redo, encryption, and much more...
992
993platforms           darwin
994license             GPL-3
995
996homepage            http://skrooge.org
997
998livecheck.type      none
999
1000pre-configure {
1001    ui_error "Please do not install this port since it has been replaced by 'skrooge'."
1002    return -code error
1003}
1004
1005distfiles</programlisting>
1006
1007        <para>A user upgrading ports will experience the following for port
1008  <quote>skrooge-devel</quote>:</para>
1009        <programlisting><prompt>%%</prompt> <userinput>sudo port upgrade skrooge-devel</userinput></programlisting>
1010        <screen>--->  skrooge-devel is replaced by skrooge
1011--->  Computing dependencies for skrooge
1012--->  Fetching skrooge
1013--->  Verifying checksum(s) for skrooge
1014--->  Extracting skrooge
1015--->  Configuring skrooge
1016--->  Building skrooge
1017--->  Staging skrooge into destroot
1018--->  Deactivating skrooge-devel @0.8.0-1215845_0
1019--->  Cleaning skrooge-devel
1020--->  Computing dependencies for skrooge
1021--->  Installing skrooge @0.8.0.6_0
1022--->  Activating skrooge @0.8.0.6_0
1023##########################################################
1024# Don't forget that dbus needs to be started as the local
1025# user (not with sudo) before any KDE programs will launch
1026# To start it run the following command:                 
1027# launchctl load /Library/LaunchAgents/org.freedesktop.dbus-session.plist
1028##########################################################
1029 
1030######################################################
1031#  Programs will not start until you run the command
1032#  'sudo chown -R $USER ~/Library/Preferences/KDE' 
1033#  replacing $USER with your username.             
1034######################################################
1035--->  Cleaning skrooge</screen>
1036
1037        <para>In case a user actually tries to install the obsolete port
1038        <quote>skrooge-devel</quote> it would be pointed out by an error message that
1039  this is impossible now:</para>
1040        <programlisting><prompt>%%</prompt> <userinput>sudo port install skrooge-devel</userinput></programlisting>
1041        <screen>--->  Fetching skrooge-devel
1042--->  Verifying checksum(s) for skrooge-devel
1043--->  Extracting skrooge-devel
1044--->  Configuring skrooge-devel
1045Error: Please do not install this port since it has been replaced by 'skrooge'.
1046Error: Target org.macports.configure returned:
1047Log for skrooge-devel is at: /opt/local/var/macports/logs/_opt_local_var_macports_sources_rsync.macports.org_release_ports_kde_skrooge-devel/main.log
1048Error: Status 1 encountered during processing.
1049To report a bug, see &lt;http://guide.macports.org/#project.tickets&gt;</screen>
1050
1051        </section>
1052
1053    <section id="development.obsolete-portgroup">
1054    <title>The shortcut: PortGroup obsolete</title>
1055
1056        <para>Using the PortGroup obsolete makes the task described in the previous subsection
1057        much easier:</para>
1058
1059        <programlisting>
1060# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; truncate-lines: t -*- vim:fenc=utf-8:et:sw=4:ts=4:sts=4
1061# $Id$
1062PortSystem          1.0
1063replaced_by         skrooge
1064PortGroup           obsolete 1.0
1065name                skrooge-devel
1066svn.revision        1215845
1067version             0.8.0-${svn.revision}
1068revision            2</programlisting>
1069
1070        <para>The PortGroup defines a number of reasonable defaults for a port that is only
1071        there to inform users that they should uninstall it and install something else
1072        instead. You might want to override some of the defaults though. For details have
1073        a look at the PortGroup's source code in
1074        <filename>${prefix}/var/macports/sources/rsync.macports.org/release/ports/_resources/port1.0/group/obsolete-1.0.tcl</filename>.</para>
1075
1076    </section>
1077
1078    </section>
1079   
1080   
1081    <section id="development.practices.removing-port">
1082      <title>Removing a port</title>
1083
1084      <para>If a port has to be removed from MacPorts one should consider
1085      the hints concerning replacing it by some alternative port given
1086      <link linkend="development.practices.rename-replace-port">above</link>.
1087      If there is no replacement for it, insert a pre-configure
1088      block as described there to alert the user about why the port is not
1089      allowed for installation anymore.</para>
1090
1091      <para>It is recommended to wait about a year before the port directory
1092      is actually being removed from MacPorts' Subversion repository.</para>
1093 
1094        </section>
1095   
1096  </section>
1097</chapter>
Note: See TracBrowser for help on using the repository browser.