clarify package directory vs. work directory
[ikiwiki.git] / docs / howtos / howtoporttodragonfly / index.mdwn
1 # How to port to DragonFly
2
3 [[!toc levels=4 ]]
4
5 This page is intended to provide some useful information to help you port applications to your DragonFly operating system. This system uses the NetBSD Packages Collection (pkgsrc) to manage application ports. A basic knowledge of this collection, of GNU developer tools, and possibly of imake, is required to successfully complete this task. For more information, references to these tools are available in the References section below.
6
7 This paper will focus on applications made for the pkgsrc collection. But many information will also be useful to those who simply wants to port applications to DragonFly without specific context.
8
9 ## Preparing the workspace
10
11 To port software with pkgsrc, two approaches are possible:
12
13 * Add new packages in pkgsrc.
14 * Modify an existing package.
15
16 In both cases, the source code of the package must be extracted into a work directory before starting the porting work. When a source file of the original application is modified, its original will be stored with the extension “. orig”. The utility mkpatches, that we'll see later in this document, will use the original files as a basis to create patches. Please note that *the version with the extension .orig must always be that of the original distribution package*.
17
18 ### Add a new package
19
20 The page [Creating a new pkgsrc package from scratch](http://www.netbsd.org/docs/pkgsrc/creating.html)
21  gives the main steps required to add a new application to the pkgsrc collection.This tutorial is very well done and summarizes the main steps required to create a new package.
22
23 ### Modify an existing package
24
25 Suppose you would want to modify the application foo/bar from the pkgsrc collection. You then start by visiting its dedicated directory in pkgsrc, and by running the following command:
26
27         cd /usr/pkgsrc/foo/bar
28         bmake patch
29
30 This will restore the changes previously made, which will be a good starting point for the porting. The bmake command could also be used without options to attempt an immediate first compilation. But you might have to change some files first, like the GNU scripts for example.
31
32 Suppose that the foo application of the collection is version 1.0. Let's go into the newly extracted source directory located right here<a name="AEN1" href="#FTN.AEN1">[1]</a>:
33
34         cd /var/obj/pkgsrc/foo/bar/work/foo-1.0
35
36 Voilà, your ready! The porting of the source code can now begin.
37
38 ## Working with GNU developper tools
39
40 If the application to port uses GNU tools like autoconf, GNU scripts shall be the first thing to look at. We'll first make a brief introduction to these tools. Then we will cover some modifications required to adapt their scripts to DragonFly. 
41
42 ### Introduction to GNU tools
43
44 GNU provides a series of very popular tools which aims at helping C and C++ cross-platform application development. These tools are Autoconf, Automake and Libtool. They can operate independently, but they can also be highly integrated.
45
46 Their use in common might not be necessarily easy to master. The GNU Autobook (see the References section), available online for free, can help you find your way with it.
47
48 Briefly, the following files are defined by the developers:
49
50 * Makefile.am and config.h (automake), to generate the Makefile.in files.
51 * configure.ac (autoconf), to generate the configure script.
52
53 The aclocal tool generates the file aclocal.m4, which contains dependencies for the configure script. It is usually run before other tools. The autoconf generated configure script will in turn generate the makefiles from other generated files, like Makefile.in. So, there are several levels of file generation. 
54
55 The first level generation is called bootstrapping (see the Bootstrap section). This process generates a set of files and directories right in the current build directory. For example, in DragonFly 2.8, the files generated by default are:
56
57         autom4te.cache/
58         .deps/
59         configure
60         missing
61         Makefile.in
62         install-sh
63         depcomp
64         config.sub
65         config.guess
66         aclocal.m4
67
68 When porting an application, it is usually not necessary to regenerate these files and directories. You simply need to adjust the Makefile and configure files. But occasionally, you'll have no other choice. The following sections attempt to give you some leads to follow.
69
70 ### Editing configure, config.guess and config.sub
71
72 When the script configure is run, it creates settings suitable for the host platform. In cases where DragonFly is not on the list of supported systems, we'll need to add it. 
73
74 By default, the command uname -m is used to detect the host platform. In our case, it will return the DragonFly label. The host_os variable will be defined after this value and will take the form “dragonflyX” (where X is the version of the host system, ex. 2.8). The configure script then uses this information to define OSARCH. A good place to start the port would be to add the following definition:
75
76         case "${host_os}" in
77              […]
78              dragonfly*)
79              OSARCH=DragonFly
80              ;;
81
82 The host_os variable is normally generated by running config.guess. It can also be explicitly defined by using the “build” option of the configure script.
83
84 Then you can continue by searching through the script to locate:
85
86 * Other occurrences of case "${host_os}".
87 * Occurrences of the “BSD” string.
88 * Changes made to other BSD systems, like NetBSD for example. If the software has already been brought to one of these systems, and it will often be the case, this will allow you to quickly find many of the modifications required for DragonFly. Of course this is not to take for granted.
89
90 Ideally, you would have to review the entire configure script to make sure that all necessary changes were made. Some will prefer to go by trial and error, by first changing what's obvious and then actively testing the results.
91
92 The config.guess file may also need to be reviewed. But the latest versions of this script already include DragonFly in its supported systems. Running it on DragonFly 2.8, for example, returns *i386-unknown-dragonfly2.8*.
93
94 The config.sub file contains a set of subroutines used by the configure script. If this file is not a symlink, it may also need to be changed. But the DragonFly system is already included by default in it, but possibly lightly implemented.
95
96 One special thing to consider in the review of GNU scripts for DragonFly is that some configuration scripts tries to collect all BSD like systems like this:
97
98         case "$uname" in
99                 *BSD*)
100         […]
101         esac
102
103 In our case, uname will contain the string DragonFly, without the “BSD” suffix. This pattern should be searched to explicitly add DragonFly after the sequence:
104
105         case "$uname" in
106                 *BSD*|DragonFly)
107         […]
108         esac
109
110 You might want to solve this problem by forcing variables like host_os and OSARCH to “DragonflyBSD”. But it may be more difficult than simply searching for occurrences of *BSD and applying the necessary changes.
111
112 ### Regenerate GNU scripts
113
114 There may be cases where you would want to regenerate the GNU scripts rather than just port them. Some basic knowledge are required to perform this task. For those who do not have this knowledge, the GNU Autobook is an excellent reference for it. We'll briefly cover the topic here, by giving some basic information and clarifying some difficulties.
115
116 #### Autoconf compatibility
117
118 As mentioned before, autoconf is used to regenerate the configure script. Operating systems are not bundled with the same version of it. We must therefore see to use the correct version of GNU tools if we want to regenerate completelly an application's build scripts.
119
120 #### The makefile.am file
121
122 This file contains macros needed to generate the Makefile.in files, which in turn generates the makefiles. The automake tool defines a syntax of its own. It can generate complex and portable makefiles from a small makefile.am script.
123
124 #### The configure.ac or configure.in file
125
126 This file contains macros necessary to generate the configure script. These are m4 macros, which generates a shell script when you run autoconf. Required changes to this file are similar to those proposed for the configure script itself.
127
128 #### Bootstrap
129
130 The procedure aiming at regenerating all the GNU build files is called *bootstrap*. Some ports are bundled with a script of this name. It runs all the required tools in the correct order. The typical case will define the following sequence:
131
132         aclocal \
133         && automake --gnu --add-missing \
134         && autoconf
135
136 ### Compiling with FreeBSD as build target
137
138 As DragonFly is a FreeBSD fork, many are building it's ports by using the FreeBSD build target. Although it sometimes works well, like for PostgreSQL, this is risky because compile compatibility with FreeBSD is not among DragonFly's goals. You must therefore expect that this shortcut is less and less usable over time, or can possibly generate badly optimized binaries.
139
140 In cases where this method still works, they may still be some changes required in GNU scripts. As mentioned earlier, scripts sometime tries to catch all the BSD variants by using the “*BSD” string. In these cases, without minimal changes, the final results might not entirely be what was anticipated for FreeBSD.
141
142 ## Working with imake and xmkmf
143
144 Arguably, imake and xmkmf could be seen as the old building tools for those wishing to develop portable applications. These tools were designed for the venerable X Window System and its applications, themselves brought to many operating systems, including UNIX®, the BSD family, GNU/Linux, AIX®, Solaris® and Windows®. This section will cover briefly these build tools, because they have been gradually discarded in favor of the GNU build tools.
145
146 X Window normally comes with a lib/X11/config directory, which contains macro files dedicated to xmkmf. This directory contains files with extensions *.cf, *.tmpl and *.rules.
147
148 * *.cf files contains settings specific to it's hosts. X Window comes normally with a DragonFly.cf file.
149 * *. rules files defines macros that implement the rules that can be used in Imakefile files.
150 * *. tmpl files contains templates that defines compile options.
151
152 As for GNU automake, these macros are used to generate makefiles for the operating system that hosts the X Window System. The normal xmkmf's procedure is to define Imakefile files, then to build the makefiles by running xmkmf. This tool will in turn call imake, which is a C preprocessor interface for the make tool. The tool xmkmf will invoke imake with the appropriate arguments for DragonFly.
153
154 When xmkmf is executed with the -a option, it automatically runs make Makefiles, make includes and make depends.
155
156 Here's a simple Imakefile example:
157
158         BINDIR = /usr/local/bin
159         
160         .SUFFIXES: cpp
161         
162         CXXEXTRA_INCLUDES = -I. -I.. -I/usr/pkg/include
163         LOCAL_LIBRARIES = -L/usr/pkg/lib
164         EXTRA_LIBRARIES = $(XMLIB) $(XTOOLLIB) $(XLIB) $(XMULIB) $(XPMLIB)
165         CXXDEBUGFLAGS = -O2 -g
166         
167         HEADERS = bar.h
168         SRCS = bar.cpp
169         OBJS = bar.o
170         
171         ComplexCplusplusProgramTarget(bar)
172
173 Note the similarity of Imakefile with makefiles. You can see the Imakefile as makefiles with macros.
174
175 In the example above, the ComplexCplusplusProgramTarget macro defines a rule to generate the C++ "bar" binary, according to the parameters that precedes it. Notably, the parameter .SUFFIXES indicates that the source files will have the extension “.cpp”.
176
177 In DragonFly, imake and xmkmf are available by installing the package devel/imake. For more information, links are given in the References section.
178
179 ## Editing the code
180
181 To tailor a program to DragonFly, you can either use the definition used to identify the DragonFly system or use the definitions generated by the GNU tools.
182
183 ### The DragonFly definition
184
185 Idealy, an application's code would be reviewed in full to ensure that it uses the right functions and algorithms for DragonFly.
186
187 In fact, the method mostly used is probably to try to compile, to correct the code when it does not, and to test the final results. When the code is adapted to DragonFly, it may look like this: 
188
189         #if defined(__DragonFly__)
190                 /* code specific to DragonFly */
191         #elif
192                 /* code for other systems */
193         #endif
194
195 An initial change might be to scan the definitions for the other BSD variants, as FreeBSD or NetBSD. We often see this kind of syntax in the code tree:
196
197         #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__) || defined(__DragonFly__)
198         #include <fcntl.h>
199         #include <net/route.h>
200         #endif
201
202 ### GNU Tools definition
203
204 Porting code can focus on identifying available functions rather than on identifying host systems. A typical case would be the bcopy function, normally used instead of strcpy on BSD derivatives. Rather than referring to the host system, the code might look like this (from the GNU Autobook<a name="AEN2" href="#FTN.AEN2">[2]</a>):
205
206         #if !HAVE_STRCPY
207         #  if HAVE_BCOPY
208         #    define strcpy(dest, src)   bcopy (src, dest, 1 + strlen (src))
209         #  else /* !HAVE_BCOPY */
210              error no strcpy or bcopy
211         #  endif /* HAVE_BCOPY */
212         #endif /* HAVE_STRCPY */
213
214 This guarantees a form of compatibility between systems at the code level. Unfortunately, this approach is moderately used, which generates more work for porters.
215
216 ### The BSD4.4 Heritage
217
218 Many developers are unaware that a BSD definition was created for BSD4.4 and it's derivatives, as DragonFly, FreeBSD and NetBSD. This definition is used like this (from pkgsrc developer's guide<a name="AEN3" href="#FTN.AEN3">[3]</a>):
219
220         #include <sys/param.h>
221         #if (defined(BSD) && BSD >= 199306)
222         /* BSD-specific code goes here */
223         #else
224         /* non-BSD-specific code goes here */
225         #endif
226
227 The NetBSD group, which maintains pkgsrc, recommends the use of this definition. In fact, it is rarely used. In the specific case of DragonFly, this definition no longer exists. Therefore it must not be used.
228
229 ## Patching for pkgsrc
230
231 Ideally, a port to DragonFly shall always be at the project level. But realistically, it is faster and easier to modify applications at the pkgsrc level.
232
233 pkgsrc contains the patches and some basic information needed to build a package in the *package directory* (by default `/usr/pkgsrc/<category>/<package>`).
234
235 The `pkgtools/pkgdiff` suite of tools helps with creating and updating patches to a package. Extract the source code into the *work directory* (by default `/usr/pkgobj/bootstrap/work/pkgsrc/<category>/<package>/work/`) by invoking
236
237         bmake patch
238
239 from the package directory. This fetches the source code if necessary, extracts it and applies any existing pkgsrc patch, saving the unpatched files with a `.orig` extension in the work directory.
240
241 To create a new patch, save a copy of the original file with that same `.orig` extension. If it exists, just keep it – do not overwrite or change `.orig` files or your patches will not apply later on! You may choose to use `pkgvi` from the `pkgdiff` suite to automate this.
242
243 You can preview the patches using `pkgdiff <file>`. To generate all patches invoke
244
245         mkpatches
246
247 from the package directory (not the work directory!) The new patches will be saved in the `patches/` directory along with backups of the previous patchset. When you are content with the generated patches commit them and update the patch checksums:
248
249         mkpatches -c
250         bmake makepatchsum
251
252 You may also revert to the old patches by calling `mkpatches -r`.
253
254 Now clean up and try to rebuild your package:
255
256         bmake clean
257         bmake
258
259 If you have any other changes to add, you can remove the package again and repeat these steps.
260
261 ## Submitting a package in pkgsrc
262
263 If you plan to port a program to DragonFly and wish to share your work, pkgsrc is ideal for you. The first thing to do is to inquire whether the application is already in the collection. If not, you're free to add your work and be registered as a port maintainer.
264
265 This section will attempt to give you some minimal guidance on submitting changes in the pkgsrc collection. This information is incomplete, please consult the page [Submitting and Commiting](http://www.netbsd.org/docs/pkgsrc/submit.html) carefully before submitting anything for real.
266
267 A source code package can be submitted with the gtk-send-pr package (pr=Problem Report), or by visiting the page [NetBSD Problem Report](http://www.netbsd.org/support/send-pr.html). The indications given by the pkgsrc developer's guide in connection with this tool are summarized here:
268
269 “In the form of the problem report, the category should be “pkg”, the synopsis should include the package name and version number, and the description field should contain a short description of your package (contents of the COMMENT variable or DESCR file are OK). The uuencoded package data should go into the “fix” field.” ̶  http://www.netbsd.org/docs/pkgsrc/submit.html#submitting-your-package
270
271 It is also possible to import new packages in pkgsrc-wip. See [http://pkgsrc-wip.sourceforge.net/](http://pkgsrc-wip.sourceforge.net/) for more information.
272
273 ## References
274
275 [The pkgsrc guide](http://www.netbsd.org/docs/pkgsrc/)
276
277 [The pkgsrc developer's guide](http://www.netbsd.org/docs/pkgsrc/developers-guide.html)
278
279 [[pkgsrc on DragonFly|/docs/howtos/HowToPkgsrc/]]
280
281 [GNU autoconf](http://www.gnu.org/software/autoconf/)
282
283 [GNU automake](http://www.gnu.org/software/automake/)
284
285 [GNU libtool](http://www.gnu.org/software/libtool/)
286
287 [GNU “autobook”, or “GNU AUTOCONF, AUTOMAKE, AND LIBTOOLS”, from Gary V. Vaughan](http://sources.redhat.com/autobook/)
288
289 [imake](http://www.x.org/archive/X11R6.7.0/doc/imake.1.html)
290
291 [xmkmf](http://www.x.org/archive/X11R6.7.0/doc/xmkmf.1.html)
292
293 ## Notes
294
295 <table border="0">
296
297   <tr>
298       <td align="LEFT" valign="TOP" width="5%">
299         <a name="FTN.AEN1" 
300             href="#AEN1">[1]
301         </a>
302       </td>
303       <td align="LEFT" valign="TOP">
304         <p>
305           Previously, the work directory was created directly in the directory dedicated to the ported application, under the pkgsrc directory. But to preserve the integrity of these directories and to be able to compile on another volume, the working files have been moved under /usr/obj. The source code located in /usr/src followed the same path.
306         </p>
307       </td>
308   </tr>
309
310   <tr>
311       <td align="LEFT" valign="TOP" width="5%">
312         <a name="FTN.AEN2" 
313             href="#AEN2">[2]
314         </a>
315       </td>
316       <td align="LEFT" valign="TOP">
317         <p>
318           Source: <a href="http://sources.redhat.com/autobook/autobook/autobook_50.html#SEC50">http://sources.redhat.com/autobook/autobook/autobook_50.html#SEC50</a>. “Copyright (C) 2000, 2006 Gary V. Vaughan. Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.”
319         </p>
320       </td>
321   </tr>
322
323   <tr>
324       <td align="LEFT" valign="TOP" width="5%">
325         <a name="FTN.AEN3" 
326             href="#AEN3">[3]
327         </a>
328       </td>
329       <td align="LEFT" valign="TOP">
330         <p>
331           Source: <a href="http://www.netbsd.org/docs/pkgsrc/fixes.html#fixes.build.cpp">http://www.netbsd.org/docs/pkgsrc/fixes.html#fixes.build.cpp</a>. Copyright © 1994-2007 The NetBSD Foundation, Inc.
332         </p>
333       </td>
334   </tr>
335
336 </table>