source: trunk/doc/guide/new/xml/portfiledev.xml @ 28467

Last change on this file since 28467 was 28467, checked in by markd@…, 12 years ago

Closes #12440. Use .orig instead of .org for the section on creating patchfiles.

File size: 22.8 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 TCL script that usually contains only the
14    simple keyword/value combinations and Tcl extensions as described in the
15    <link linkend="reference">Portfile Reference</link> chapter, though it may
16    also contain arbitrary TCL code. Every port has a corresponding Portfile,
17    but Portfiles do not completely define a port's installation behavior
18    since the MacPorts base has default port installation characteristics
19    coded within it. Therefore Portfiles need only specify required options
20    and, when required, non-default characteristics for a port.</para>
21
22    <para>A common way for Portfiles to augment or override MacPorts base
23    default installation phase characteristics is by using
24    <filename>Portfile</filename> phase declaration(s). If you use Portfile
25    phase declaration(s), you should know how to identify the "global" section
26    of a Portfile. Any statements not contained within a phase declaration, no
27    matter where they are located in a Portfile are said to be in the global
28    section of the Portfile, therefore the global section need not be
29    contiguous. Likewise, to remove statements from the global section they
30    must be placed within a phase declaration.</para>
31
32    <para>The main phases you need to be aware of when making a Portfile are
33    these:</para>
34
35    <itemizedlist>
36      <listitem>
37        <para>Fetch</para>
38      </listitem>
39
40      <listitem>
41        <para>Extract</para>
42      </listitem>
43
44      <listitem>
45        <para>Patch</para>
46      </listitem>
47
48      <listitem>
49        <para>Configure</para>
50      </listitem>
51
52      <listitem>
53        <para>Build</para>
54      </listitem>
55
56      <listitem>
57        <para>Destroot</para>
58      </listitem>
59    </itemizedlist>
60
61    <para>The default installation phase behavior performed by the MacPorts
62    base works fine for applications that use the standard
63    <command>configure</command>, <command>make</command>, and <command>make
64    install</command> steps, which conform to phases configure, build, and
65    destroot respectively. For applications that do not conform to this
66    standard behavior, any installation phase may be augmented using pre-
67    and/or post- phases, or even overridden or eliminated. See <link
68    linkend="development.examples">Example Portfiles</link> below.</para>
69
70    <note>
71      <para>For a detailed description of all port phases, see the <link
72      linkend="reference">Portfile Reference</link> chapter.</para>
73    </note>
74  </section>
75
76  <section id="development.local-repositories">
77    <title>Local Portfile Repositories</title>
78
79    <para>To create and test Portfiles that are not yet committed to
80    subversion, you may create a local Portfile repository as shown.</para>
81
82    <orderedlist>
83      <listitem>
84        <para>Open the <filename>sources.conf</filename> file in a text
85        editor.</para>
86
87        <programlisting><prompt>%%</prompt> <userinput>cd ${prefix}/etc/macports/</userinput>
88<prompt>%%</prompt> <userinput>pico sources.conf</userinput></programlisting>
89      </listitem>
90
91      <listitem>
92        <para>Insert a URL pointing to the local repository location before
93        the rsync URL as shown.</para>
94
95        <programlisting>file:///Users/julesverne/ports
96rsync://rsync.macports.org/release/ports
97</programlisting>
98
99        <note>
100          <para>The file URL should always appear before the rsync URL so that
101          local Portfiles can be tested that are duplicated in the MacPorts
102          tree, because the <command>port</command> command will always
103          operate on the first Portfile it encounters.</para>
104        </note>
105      </listitem>
106
107      <listitem>
108        <para>Place the Portfiles you create inside a directory whose name
109        matches the port, which should in turn be placed inside a directory
110        that reflect the port's primary category (the first category entry in
111        the Portfile).</para>
112
113        <programlisting><prompt>%%</prompt> <userinput>cd /Users/julesverne</userinput>
114<prompt>%%</prompt> <userinput>mkdir -p ports/games/bestevergame</userinput>
115<prompt>%%</prompt> <userinput>cd ports/games/bestevergame</userinput>
116<prompt>%%</prompt> <userinput>touch Portfile</userinput></programlisting>
117      </listitem>
118
119      <listitem>
120        <para>After a Portfile is created (see below), use the MacPorts
121        <command>portindex</command> command in the local repository's
122        directory to install it into the
123        <filename>Portindex</filename>.</para>
124
125        <programlisting>%% <userinput>cd /Users/julesverne/ports</userinput>
126%% <userinput>portindex</userinput></programlisting>
127
128        <screen>Creating software index in /Users/julesverne/ports
129Adding port games/bestevergame
130
131Total number of ports parsed:   1
132Ports successfully parsed:      1       
133Ports failed:                   0</screen>
134      </listitem>
135    </orderedlist>
136
137    <para>Once the local port is added to the <filename>Portindex</filename>,
138    it becomes available for searching or installation as with any other
139    Portfile in the MacPorts tree as shown.</para>
140
141    <programlisting><prompt>%%</prompt> <userinput>port search bestever</userinput></programlisting>
142
143    <screen>bestevergame   games/bestevergame 1.1   The Best Ever Game</screen>
144  </section>
145
146  <section id="development.creating-portfile">
147    <title>Creating a Portfile</title>
148
149    <para>Here we list the individual Portfile components for an application
150    that conforms to the the standard <command> configure</command>,
151    <command>make</command>, and <command>make install</command> steps of most
152    open source application installs.</para>
153
154    <orderedlist>
155      <listitem>
156        <para>Subversion ID tag line</para>
157
158        <para>The first line of a new Portfile must be set as shown. When a
159        port is committed to subversion, ID tags are expanded to include the
160        last person to commit and the commit time.</para>
161
162        <programlisting># $Id$</programlisting>
163      </listitem>
164
165      <listitem>
166        <para>PortSystem line</para>
167
168        <para>This statement is required for all ports.</para>
169
170        <programlisting>PortSystem        1.0</programlisting>
171      </listitem>
172
173      <listitem>
174        <para>Port name</para>
175
176        <programlisting>name              rrdtool</programlisting>
177      </listitem>
178
179      <listitem>
180        <para>Port version</para>
181
182        <programlisting>version           1.2.23</programlisting>
183      </listitem>
184
185      <listitem>
186        <para>Port categories</para>
187
188        <para>A port may belong to more than one category, but the first
189        (primary) category should match the directory name in the ports tree
190        where the Portfile is to reside.</para>
191
192        <programlisting>categories        net</programlisting>
193      </listitem>
194
195      <listitem>
196        <para>Port maintainers</para>
197
198        <para>A port's maintainer is a person or persons who take
199        responsibility for keeping the port up-to-date, and the maintainer
200        keyword lists maintainer email addresses(s). To hide these addresses
201        from spambots, see the more full explanation of the maintainer keyword
202        in the <link linkend="reference.keywords.global">Global
203        Keywords</link> section of the <link linkend="reference">Portfile
204        Reference</link> chapter.</para>
205
206        <programlisting>maintainers       julesverne@example.org</programlisting>
207
208        <note>
209          <para>The address <email>nomaintainer@macports.org</email>
210          designates a port that may be modified by any committer.</para>
211        </note>
212      </listitem>
213
214      <listitem>
215        <para>Port description</para>
216
217        <programlisting>description       Round Robin Database</programlisting>
218      </listitem>
219
220      <listitem>
221        <para>Port long_description</para>
222
223        <programlisting>long_description  RRDtool is a system to store and display time-series data</programlisting>
224      </listitem>
225
226      <listitem>
227        <para>A port's application homepage</para>
228
229        <programlisting>homepage          http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/</programlisting>
230      </listitem>
231
232      <listitem>
233        <para>Platform statement</para>
234
235        <programlisting>platforms         darwin</programlisting>
236      </listitem>
237
238      <listitem>
239        <para>A port's download URLs</para>
240
241        <programlisting>master_sites      http://oss.oetiker.ch/rrdtool/pub/ \
242                  ftp://ftp.pucpr.br/rrdtool/</programlisting>
243      </listitem>
244
245      <listitem>
246        <para>Port checksums</para>
247
248        <para>The checksums specified in a Portfile are checked with the
249        fetched tarball for security.</para>
250
251        <programlisting>checksums         md5 dafa161bc9c61e57636a6085c87c1fe8</programlisting>
252      </listitem>
253
254      <listitem>
255        <para>Port dependencies</para>
256
257        <para>A port's dependencies are ports that must be installed before
258        another port is installed.</para>
259
260        <programlisting>depends_lib       port:perl5.8 \
261                  port:tcl \
262                  port:zlib</programlisting>
263      </listitem>
264
265      <listitem>
266        <para>Port configure arguments (optional)</para>
267
268        <programlisting>configure.args    --prefix=${prefix} \
269                  --enable-perl-site-install \
270                  --mandir=${prefix}/share/man</programlisting>
271      </listitem>
272    </orderedlist>
273  </section>
274
275  <section id="development.examples">
276    <title>Example Portfiles</title>
277
278    <para>In this section we take a look at a complete simple Portfile, and
279    then pre- and post- phase definitions to augment and override the MacPorts
280    default phases.</para>
281
282    <section id="development.examples.basic">
283      <title>A Basic Portfile</title>
284
285      <programlisting># Id$
286PortSystem      1.0
287
288name                    rrdtool
289version                 1.2.23
290categories              net
291maintainers             julesverne
292description             Round Robin Database
293long_description        RRDtool is a system to store and display time-series data
294homepage                http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/
295platforms               darwin
296master_sites            http://oss.oetiker.ch/rrdtool/pub/ \
297                        ftp://ftp.pucpr.br/rrdtool/
298
299checksums               md5 dafa161bc9c61e57636a6085c87c1fe8
300
301depends_lib             port:perl5.8 \
302                        port:tcl \
303                        port:zlib
304
305configure.args          --prefix=${prefix} \
306                        --enable-perl-site-install \
307                        --mandir=${prefix}/share/man</programlisting>
308    </section>
309
310    <section id="development.examples.pre-post">
311      <title>Portfile Using Pre- / Post- Phases</title>
312
313      <para>To augment a port's installation phase, and not override it, you
314      may use pre- and post- installation phases as shown in this
315      example.</para>
316
317      <programlisting>post-destroot {
318# Install example files not installed by the Makefile
319        file mkdir ${destroot}${prefix}/share/doc/${name}/examples
320        file copy ${worksrcpath}/examples/ \
321             ${destroot}${prefix}/share/doc/${name}/examples
322}</programlisting>
323    </section>
324
325    <section id="development.examples.override">
326      <title>Portfile that Overrides Default Phases</title>
327
328      <para>To override the automatic MacPorts installation phase processing,
329      define your own installation phases as shown in this example.</para>
330
331      <programlisting>destroot {
332        xinstall -m 755 -d ${destroot}${prefix}/bin
333        xinstall -m 755 ${worksrcpath}/cdpr ${destroot}${prefix}/bin
334}</programlisting>
335    </section>
336
337    <section id="development.examples.startupitem">
338      <title>Portfile Using a StartupItem</title>
339
340      <para>Startupitems may be placed in the global section of a
341      Portfile.</para>
342
343      <programlisting>startupitem.create      yes
344startupitem.name        nmicmpd
345startupitem.executable  "${prefix}/bin/nmicmpd"</programlisting>
346
347      <para>Startupitems keywords may also be used within a variant definition
348      to make their installation conditional.</para>
349
350      <programlisting>variant server {
351    startupitem.create    yes
352    startupitem.start "${prefix}/share/${name}/vm-pop3d.init start"
353    startupitem.stop "${prefix}/share/${name}/vm-pop3d.init stop"
354}</programlisting>
355    </section>
356  </section>
357
358  <section id="development.variants">
359    <title>Port Variants</title>
360
361    <para>Variants are a way for port authors to provide options that may be
362    invoked at install time. They are declared in the global section of a
363    Portfile using the "variant" keyword and may provide a description.</para>
364
365    <section id="development.variants.options">
366      <title>Variants to Modify Options</title>
367
368      <para>The most common use for a variant is to add or remove
369      dependencies, configure arguments, and build arguments from the global
370      Portfile section. Here is an example of a port providing four variants
371      that add additional configure arguments to a port.</para>
372
373      <programlisting>variant pop     { configure.args-append --enable-pop }
374variant imap    { configure.args-append --enable-imap }
375variant ssl     { configure.args-append --with-ssl }
376variant debug   { configure.args-append --enable-debug }</programlisting>
377
378      <para>In the example variant declaration, the configure argument
379      <literal>--without-x</literal> is removed and a numner of others are
380      appended.</para>
381
382      <programlisting>variant x11 description {Builds port as an X11 program with Lucid widgets} {
383    configure.args-delete   --without-x
384    configure.args-append   --with-x-toolkit=lucid \
385                            --without-carbon \
386                            --with-xpm \
387                            --with-jpeg \
388                            --with-tiff \
389                            --with-gif \
390                            --with-png
391    depends_lib-append      lib:libX11:XFree86 \
392                            lib:libXpm:XFree86 \
393                            port:jpeg \
394                            port:tiff \
395                            port:libungif \
396                            port:libpng
397}</programlisting>
398    </section>
399
400    <section id="development.variants.phase">
401      <title>Variant Actions in a Phase</title>
402
403      <para>If a variant requires options in addition to those provided by
404      keywords using -append and/or -delete, in other words, any actions that
405      would normally take place within a port installation phase, do not try
406      to do this within the variant declaration. Rather, modify the behavior
407      of any affected phases when the variant is invoked using the
408      variant_isset keyword.</para>
409
410      <programlisting>post-destroot {
411    xinstall -m 755 -d ${destroot}${prefix}/etc/
412    xinstall ${worksrcpath}/examples/foo.conf \
413        ${destroot}${prefix}/etc/
414
415    if {[variant_isset] carbon]} {
416        delete ${destroot}${prefix}/bin/emacs
417        delete ${destroot}${prefix}/bin/emacs-${version}
418    }
419}</programlisting>
420    </section>
421
422    <section id="development.variants.default">
423      <title>Default Variants</title>
424
425      <para>Variants are used to specify actions that lie outside the core
426      functions of an application or port, but there may be some cases where
427      you wish to specify these non-core functions by default. For this
428      purpose you may use the keyword default_variants.</para>
429
430      <programlisting>default_variants +foo +bar</programlisting>
431
432      <note>
433        <para>The default_variant keyword may only be used in the global
434        Portfile section.</para>
435      </note>
436    </section>
437  </section>
438
439  <section id="development.patches">
440    <title>Patch Files</title>
441
442    <para>Patch files are files created with the Unix command
443    <command>diff</command> that are applied using the command
444    <command>patch</command> to modify text files to fix bugs or extend
445    functionality.</para>
446
447    <section id="development.patches.portfile">
448      <title>Creating Portfile Patches</title>
449
450      <para>If you wish to contribute modifications or fixes to a Portfile,
451      you should do so in the form of a patch.</para>
452
453      <orderedlist>
454        <listitem>
455          <para>Make a copy of the Portfile you wish to modify; both files
456          must be in the same directory, though it may be any
457          directory.</para>
458
459          <programlisting><prompt>%%</prompt> <userinput>cp Portfile Portfile.orig</userinput></programlisting>
460        </listitem>
461
462        <listitem>
463          <para>Edit the file to make it as you want it to be after it is
464          fetched.</para>
465        </listitem>
466
467        <listitem>
468          <para>Now use the Unix command <command>diff -u </command>to create
469          a "unified" diff patch file.</para>
470
471          <programlisting><prompt>%%</prompt> <userinput>diff -u Portfile.orig Portfile &gt; Portfile.diff</userinput></programlisting>
472        </listitem>
473
474        <listitem>
475          <para>A patch file that is a "unified" diff file is the easiest to
476          interpret by humans and this type should always be used for ports.
477          The Portfile patch below will change the version and checksums when
478          applied.</para>
479
480          <programlisting>--- Portfile.orig        2007-07-25 18:52:12.000000000 -0700
481+++ Portfile    2007-07-25 18:53:35.000000000 -0700
482@@ -2,7 +2,7 @@
483 PortSystem             1.0
484 
485 name                   nefu
486-version                        1.4.0
487+version                        1.3.0
488 categories             net
489 maintainers            nomaintainer@macports.org
490 description            A network monitoring daemon.
491@@ -13,9 +13,9 @@
492
493 homepage               http://rsug.itd.umich.edu/software/${name}
494
495 master_sites           ${homepage}/files/
496-checksums              md5 f0953b21cdb5eb327e40d4b215110b71 \
497+checksums              md5 01532e67a596bfff6a54aa36face26ae \
498 extract.suffix  .tgz
499 platforms              darwin
500</programlisting>
501        </listitem>
502      </orderedlist>
503
504      <para>Now you may attach the <filename>Portfile.diff</filename> to a
505      MacPorts Trac ticket for the port author to evaluate.</para>
506    </section>
507
508    <section id="development.patches.source">
509      <title>Creating Source Code Patches</title>
510
511      <para>Necessary or useful patches to application source code should be
512      sent to the application developer (not the port author) so the
513      modifications may be included in the next version, and the port patch
514      eventually removed.</para>
515
516      <orderedlist>
517        <listitem>
518          <para>Locate the file you wish to patch in its original location
519          within the unpacked source directory and make a duplicate of
520          it.</para>
521
522          <programlisting><prompt>%%</prompt> <userinput>cd foo-1.34/src</userinput>
523<prompt>%%</prompt> <userinput>cp Makefile.in Makefile.in.orig</userinput></programlisting>
524        </listitem>
525
526        <listitem>
527          <para>Edit the file to make it as you want it to be after it is
528          fetched.</para>
529        </listitem>
530
531        <listitem>
532          <para>Now use the Unix command <command>diff -u</command> to create
533          a "unified" diff patch file.</para>
534
535          <programlisting><prompt>%%</prompt> <userinput>cd foo-1.34</userinput>
536<prompt>%%</prompt> <userinput>diff -u Makefile.in.orig Makefile.in &gt; patch-Makefile.in</userinput></programlisting>
537
538          <note>
539            <para>You must execute the <command>diff</command> command in the
540            top-level of the unpacked source code. Otherwise the
541            <command>patch</command> command will look for the file to be
542            patched in the wrong place and fail.</para>
543          </note>
544        </listitem>
545
546        <listitem>
547          <para>A patch file that is a "unified" diff file is the easiest to
548          interpret by humans and this type should always be used for ports.
549          See the example below where a patch adds <varname>DESTDIR</varname>
550          support to a <filename>Makefile.in</filename> file.</para>
551
552          <programlisting>--- Makefile.in.orig   2007-06-01 16:30:47.000000000 -0700
553+++ Makefile.in       2007-06-20 10:10:59.000000000 -0700
554@@ -131,23 +131,23 @@
555        $(INSTALL_DATA)/gdata $(INSTALL_DATA)/perl
556
557 install-lib:
558-       -mkdir -p $(INSTALL_LIB)
559+       -mkdir -p $(DESTDIR)$(INSTALL_LIB)
560        $(PERL) tools/install_lib -s src -l $(INSTALL_LIB) $(LIBS)
561-       cp $(TEXT) $(INSTALL_LIB)/
562+       cp $(TEXT) $(DESTDIR)$(INSTALL_LIB)/</programlisting>
563        </listitem>
564
565        <listitem>
566          <para>Now you may place the patch
567          <filename>patch-Makefile.in</filename> in the path ${portpath}/files
568          of a local repository (or commit it to subversion) and use it in a
569          port using the patchfiles keyword.</para>
570
571          <programlisting>patchfiles              patch-Makefile.in</programlisting>
572        </listitem>
573      </orderedlist>
574    </section>
575
576    <section id="development.patches.applying">
577      <title>Manually Applying Patches</title>
578
579      <para>Though MacPorts applies patch files automatically, you may want to
580      know how to apply patch files manually if you want to apply uncommitted
581      Portfile patches or other similar uses.</para>
582
583      <orderedlist>
584        <listitem>
585          <para>Change to the directory containing the file to be patched. In
586          this example, we'll apply a Portfile patch to the postfix
587          port.</para>
588
589          <programlisting><prompt>%%</prompt> <userinput>cd /opt/local/var/macports/sources/rsync.macports.org/release/ports/mail/postfix</userinput></programlisting>
590        </listitem>
591
592        <listitem>
593          <para>Now apply the patch that is on the current user's desktop. The
594          patchfile knows the filename of the file to be patched.</para>
595
596          <programlisting><prompt>%%</prompt> <userinput>patch &lt; ~/Desktop/Portfile.diff</userinput></programlisting>
597
598          <screen>patching file Portfile</screen>
599        </listitem>
600      </orderedlist>
601    </section>
602  </section>
603
604  <section id="development.practices">
605    <title>Portfile Best Practices</title>
606
607    <para>This section contains practical guidelines for creating Portfiles
608    that install smoothly and provide consistency between ports.</para>
609
610    <section id="development.practices.dont-overwrite">
611      <title>Don't Overwrite Config Files</title>
612
613      <para></para>
614    </section>
615
616    <section id="development.practices.install-docs">
617      <title>Install Docs and Examples</title>
618
619      <para></para>
620    </section>
621
622    <section id="development.practices.provide-messages">
623      <title>Provide User Messages</title>
624
625      <para></para>
626    </section>
627  </section>
628</chapter>
Note: See TracBrowser for help on using the repository browser.