Gentoo Archives: gentoo-doc-cvs

From: Lukasz Damentko <rane@×××××××××××.org>
To: gentoo-doc-cvs@l.g.o
Subject: [gentoo-doc-cvs] cvs commit: autotools-practices.xml
Date: Fri, 16 Dec 2005 15:04:09
Message-Id: 200512161504.jBGF40vP018901@robin.gentoo.org
1 rane 05/12/16 15:03:59
2
3 Added: xml/htdocs/doc/en/articles autotools-practices.xml
4 Log:
5 #115757, new article about autotools, written by flameeyes for linux.com
6
7 Revision Changes Path
8 1.1 xml/htdocs/doc/en/articles/autotools-practices.xml
9
10 file : http://www.gentoo.org/cgi-bin/viewcvs.cgi/xml/htdocs/doc/en/articles/autotools-practices.xml?rev=1.1&content-type=text/x-cvsweb-markup&cvsroot=gentoo
11 plain: http://www.gentoo.org/cgi-bin/viewcvs.cgi/xml/htdocs/doc/en/articles/autotools-practices.xml?rev=1.1&content-type=text/plain&cvsroot=gentoo
12
13 Index: autotools-practices.xml
14 ===================================================================
15 <?xml version='1.0' encoding="UTF-8"?>
16 <!DOCTYPE guide SYSTEM "/dtd/guide.dtd">
17 <!-- $Header: /var/cvsroot/gentoo/xml/htdocs/doc/en/articles/autotools-practices.xml,v 1.1 2005/12/16 15:03:59 rane Exp $ -->
18
19 <guide link="/doc/en/articles/autotools-practices.xml">
20 <title>Best practices with autotools</title>
21
22 <author title="Author">
23 <mail link="flameeyes@g.o">Diego Pettenò</mail>
24 </author>
25
26 <abstract>
27 This article covers some of the most common errors people make when using
28 autotools and ways to achieve better results.
29 </abstract>
30
31 <!-- The content of this document is licensed under the CC-BY-SA license -->
32 <!-- See http://creativecommons.org/licenses/by-sa/2.5 -->
33 <license/>
34
35 <version>1.0</version>
36 <date>2005-12-16</date>
37
38 <chapter>
39 <title>Best practices with autotools</title>
40 <section>
41 <body>
42
43 <p>
44 The core of GNU's compile chain -- the set of tools used to build GNU software
45 packages -- is the so-called "autotools," a term that refers to the autoconf
46 and automake programs, as well as libtool, autoheader, pkg-config, and
47 sometimes gettext. These tools let you compile GNU software on a wide variety
48 of platforms and Unix and Unix-like operating systems, providing developers a
49 framework to check for the presence of the libraries, functions, and tools that
50 they want to use. While autotools are great in the hands of an experienced
51 developer, they can be quite a handful for the first-time user, and it's not so
52 rare that packages are shipped with working-but-broken autotools support. This
53 article will cover some of the most common errors people make when using
54 autotools and ways to achieve better results.
55 </p>
56
57 <p>
58 Regardless of anyone's opinion about them, we currently have no valid
59 alternative for autotools. Projects such as Scons are not as portable as
60 autotools, and they don't embody enough knowledge to be useful yet. We have
61 tons of automatic checks with autotools, and a lot of libraries come with an m4
62 library with macros to check for their presence.
63 </p>
64
65 <p>
66 The basic structure of an autotooled project is simple. Autoconf takes help of
67 an <path>aclocal.m4</path> file (created by aclocal using the m4 libraries on
68 its search path and <path>acinclude.m4</path> file) to parse the
69 <path>configure.ac</path> file (formerly <path>configure.in</path>) and
70 transform it into a "configure" script. For every directory there should exist
71 an <path>Makefile.am</path>, which automake uses to create Makefile.in
72 templates. The Makefile.in templates are then processed and transformed by the
73 <path>configure</path> script into real Makefiles. You can avoid avoid using
74 automake and just write your own Makefile.in files, but this is quite complex,
75 and you lose a few features of autotools.
76 </p>
77
78 <p>
79 In a <path>configure.ac</path> file you can use macros you define yourself, the
80 default ones provided by autoconf and aclocal, or external macros provided, for
81 instance, by other packages. In such a case aclocal will create the
82 <path>aclocal.m4</path> file adding the library files it finds on the system's
83 library with the defined macros; this is a critical step to have a working
84 autotooled project, as we'll see in a moment.
85 </p>
86
87 <p>
88 A <path>Makefile.am</path> is mainly a declaration of intents: you can fill
89 some targets variables with the name of the targets you want to build. These
90 variables are structured in a format like placetoinstall_TYPEOFTARGET. The
91 place is the location in a hierarchical Unix filesystem (bin, lib, include,
92 ...), a non-used keyword that can be defined with an arbitrary path (using the
93 keyworddir variable), or the special keyword noinst that marks the targets that
94 need not to be installed (for example private headers, or static libraries used
95 during build). After naming the target, you can use the name (replacing dots
96 with underscores) as the prefix for the variables that affects its build. In
97 this way you can provide special CFLAGS, LDFLAGS, and LDADD variables used
98 during the build of a single target, instead of changing them for all the
99 targets. You can also use variables collected during configure phase, if you
100 passed them to the AC_SUBST macro in <path>configure.ac</path>, so that they
101 are replaced inside makefiles. Also, though defining CFLAGS and LDFLAGS on a
102 per-target basis seems useful, adding static flags in Makefile.am is a bad
103 thing for portability, as you can't tell if the compiler you're using supports
104 them, or if you really need them (-ldl put in LDFLAGS is a good example of a
105 flag needed on Linux but not on FreeBSD); in such cases you should use
106 <path>configure.ac</path> to add these flags.
107 </p>
108
109 <p>
110 The most commonly used macros in configure.ac are AC_CHECK_HEADERS,
111 AC_CHECK_FUNCTS, and AC_CHECK_LIB, which test for the presence of,
112 respectively, some header files, some library functions, and a given library
113 (with a specific function in it). They are important for portability as they
114 provides a way to check which headers are present and which are not (for
115 example system headers that have different locations in different operating
116 systems), and to check whether a function is present in the system library
117 (asprintf() is missing in OpenBSD for example, while it's present on GNU C
118 library and FreeBSD), and finally to check for the presence of some third-party
119 library or to see if a specific link to a library is needed to get some
120 functions (for example dlopen() function is in libdl library on GNU systems,
121 while it's provided by the system's C library on FreeBSD).
122 </p>
123
124 <p>
125 Along with testing for the presence or absence of functions or headers (and
126 sometimes libraries) you usually need to change the code's path (for example to
127 avoid the use of missing functions, or to define a drop-in replacement for
128 them). Autoconf is commonly coupled with another tool, autoheader, which
129 creates a <path>config.h.in</path> template, used by configure script to create
130 a <path>config.h</path> header in which are defined a few preprocessor macros
131 in form of HAVE_givenfunction or HAVE_givenheader_H which can be tested with
132 #ifdef/#ifndef directives inside a C or C++ source file to change the code
133 according to the features present.
134 </p>
135
136 <p>
137 Here are some practices to keep in mind to help you use autotools to create the
138 most portable code possible.
139 </p>
140
141 <p>
142 <b>The config.h header file should be considered to be an internal header
143 file</b>, so it should be used just by the single package in which it's
144 created. You should avoid editing the <path>config.h.in</path> template to add
145 your own code there, as this requires you to manually update it according to
146 the <path>configure.ac</path> you're writing.
147 </p>
148
149 <p>
150 Unfortunately a few projects, such as Net-SNMP, export this header file with
151 other libraries' headers, which requires any projects that use their libraries
152 to include them (or provide their own copy of the internal Net-SNMP
153 structures). This is a bad thing, as the autotools structure of a library
154 project should be invisible to software using it (which might not use autotools
155 at all). Also, changes in autotools behavior are anything but rare, so you can
156 have two identical checks with different results due to changes in the way they
157 are executed. If you need to define your own wrappers or replacements in case
158 something is not in the environment you're compiling for, you should do that in
159 private headers that do not get installed (declared as noinst_HEADERS in
160 <path>Makefile.am</path> files).
161 </p>
162
163 <p>
164 <b>Always provide the m4 files you used</b>. As autotools have been in use for
165 years, many packages (for example libraries) that can be reused by other
166 programs provide an m4 library file in <path>/usr/share/aclocal</path> that
167 makes it possible to check for their presence (for example using the -config
168 scripts) with a simple macro call. These files are used by aclocal to create
169 the <path>aclocal.m4</path> file, and they usually are present on the
170 developers' systems where aclocal is executed to create the release, but when
171 they are for optional dependencies, they can be missing on users' systems.
172 While this is usually not a problem, because users rarely executes aclocal,
173 it's a problem for source distributions, such as Gentoo, where sometimes you
174 need to patch a Makefile.am or the <path>configure.ac</path> and then re-run
175 autoconf without having all the optional dependencies installed (or having
176 different versions, which can be incompatible or bugged, of the same m4 file).
177 </p>
178
179 <p>
180 To avoid this problem, you should create an m4 subdirectory in your package's
181 directory and then put there the m4 library files you are using. You must then
182 call aclocal with aclocal -I m4 options to search in that directory before the
183 system library. You can then choose whether to put that directory under
184 revision control (CVS, SVN, or whatever else you are using) or just create it
185 for the releases. The latter case is the bare minimum requirement for a
186 package. It minimizes the amount of revision-controlled code and ensures that
187 you're always using the latest m4 version, but has the drawback that anyone who
188 checks out your repository won't be able to execute autoconf without having to
189 look on a release tarball to take the m4 from (and that might not work, as you
190 can have updated the configure.ac to suit a newer macro or added more
191 dependencies). On the other hand, putting the m4 directory under revision
192 control sometimes tempts the developers to change the macros to suit their
193 needs. Although this seems logical, as the m4 files are under your revision
194 control, it will upset many package maintainers, as sometimes new versions of
195 m4 files fix bugs or support newer options and installation paths (for example
196 multilib setups), and having the m4 files modified makes it impossible to just
197 replace them with updated versions. It also mean that when you're going to
198 update an m4 file you must redo the modification against the original.
199 </p>
200
201 <p>
202 m4 files are always a problem to work with. They must replicate almost the same
203 code from library to library (depending on the way you need to provide
204 CFLAGS/LDFLAGS: with tests or with a -config script). To avoid this problem,
205 the GNOME and FreeDesktop projects developed a tool called pkg-config, which
206 provides both an executable binary and an m4 file to include in configure.ac
207 files, and lets developers check for the presence of a given library (and/or
208 package), provided that the package itself installed a pkg-config .pc data
209 file. This approach simplifies the work of maintaining configure.ac scripts,
210 and requires a lot less time to be processed during execution of configure
211 script, as it uses the information provided by the installed package itself
212 instead of just trying if it's present. On the other hand, this approach means
213 that an error the developers make concerning a dependency can break the user
214 program, as they just hardcode the compiler and linker flags in the data file
215 and the configure script doesn't actually check whether the library works.
216 Fortunately, this doesn't happen too often.
217 </p>
218
219 <p>
220 To create the configure file, you need PKG_CHECK_MODULES, contained in the
221 <path>pkg.m4</path> library. You should add that file to your m4 directory. If
222 pkg-config dependency is mandatory (as the tool is run by the configure script)
223 you can't be sure that the m4 file you are using is the same as one on users'
224 systems, nor you can be sure that it does not include extra bugs, as it can be
225 older than yours.
226 </p>
227
228 <p>
229 <b>Always check for the libraries you're going to link to</b>, if you have them
230 as mandatory dependencies. Usually autoconf macros or pkg-config data files
231 define prerequisite libraries that you need to successfully link to your
232 library. Also, some functions that are in extra libraries in some systems
233 (like dlopen() in libdl on Linux and Mac OS X) can be in the libc of another
234 system (the same function is in libc on FreeBSD). In these cases you need to
235 check whether the function can be found without linking to anything, or if you
236 need to use a specific library (for example to avoid linking to a non-existent
237 libdl that would fail where it's not needed).
238 </p>
239
240 <p>
241 <b>Be careful with GNU extensions</b>. One of the things that makes portability
242 a big pain is the use of extension functions, which are provided by GNU libc
243 but aren't present on other C libraries like BSD's or uClibc. When you use such
244 functions, you should always provide a "drop-in replacement," a function that
245 can provide the same functionality as the library function, maybe with less
246 performance or security, which can be used when the extension function is not
247 present on system's C library. Those functions must be protected by a #ifdef
248 HAVE_function ... #endif block, so that they don't get duplicated when they are
249 already present. Make sure that these functions are not exported by the library
250 to the external users; they should be declared inside an internal header, to
251 avoid breaking other libraries that may be doing similar tricks.
252 </p>
253
254 <p>
255 <b>Avoid compiling OS-specific code when not needed</b>. When a program
256 optionally supports specific libraries or specific operating systems, it's not
257 rare to have entire source files that are specific to that code path. To avoid
258 compiling them when they're not needed, use the AM_CONDITIONAL macro inside a
259 configure.ac file. This automake macro (usable only if you're using automake to
260 build the project) allows you to define if .. endif blocks inside a Makefile.am
261 file, inside which you can set special variables. You can, for example, add a
262 "platformsrcs" variable that you set to the right source file for the platform
263 to build for, then use in a _SOURCES variable.
264 </p>
265
266 <p>
267 However, there are two common errors developers make when using AM_CONDITIONAL.
268 The first is the use of AM_CONDITIONAL in an already conditional branch (for
269 example under an info or in a case switch), which leads to automake complaining
270 about a conditional defined only conditionally (AM_CONDITIONAL must be called
271 on global scope, out of every if block, so you must define a variable to
272 contain the status of the conditions and then test against when calling the
273 AM_CONDITIONAL). The other one is that you can't change the targets' variables
274 directly, and you must define "commodity" variables, whose results empty out of
275 the conditional, to add or remove source files and targets.
276 </p>
277
278 <p>
279 Many projects, to avoid compiling code for specific code paths, add the entire
280 files in #ifdef ... #endif preprocessor conditionals. While this usually works,
281 it makes the code ugly and error-prone, as a single statement out of the
282 conditional block can be compiled where the source file is not needed. It also
283 misleads users sometimes, as the source files seem to be compiled in situations
284 where they don't make sense.
285 </p>
286
287 <p>
288 <b>Be smart in looking for operating system or hardware platform</b>. Sometimes
289 you need to search for a specific operating system or hardware platform. The
290 right way to do this depends on where you need to know this. If you must know
291 it to enable extra tests on configure, or you must add extra targets on
292 makefiles, you must do the check in configure.ac. On the other hand, if the
293 difference must be known in a source file, for example to enable an optional
294 asm-coded function, you should rely directly on the compiler/preprocessor, so
295 you should use #ifdef directives with the default macros enabled on the target
296 platform (for example __linux__, __i386__, _ARC_PPC, __sparc__, _FreeBSD_ and
297 __APPLE__).
298 </p>
299
300 <p>
301 <b>Don't run commands in configure.ac</b>. If you need to check for hardware or
302 operating system in a configure.ac, you should avoid using the uname command,
303 despite this being one of the most common way to do such a test. This is
304 actually an error, as this breaks crosscompilation. Autotools supports
305 crosscompile projects from one machine to another using hosts definitions:
306 strings in the form "hardware-vendor-os" (actually, "hardware-vendor-os-libc"
307 when GNU libc is used), such as i686-pc-linux-gnu and
308 x86_64-unknown-freebsd5.4. CHOST is the host definition for the system you're
309 compiling the software for, CBUILD is the host definition for the system you're
310 compiling on; when CHOST and CBUILD differ, you're crosscompiling.
311 </p>
312
313 <p>
314 In the examples above, the first host definition shows an x86-like system, with
315 a pentium2-equivalent (or later) processor, running a Linux kernel with a GNU
316 libc (usually this refers to a GNU/Linux system). The second refers to an AMD64
317 system with a FreeBSD 5.4 operating system. (For a GNU/kFreeBSD system, which
318 uses FreeBSD kernel and GNU libc, the host definition is
319 hw-unknown-freebsd-gnu, while for a Gentoo/FreeBSD, using FreeBSD's kernel and
320 libc, but with Gentoo framework, the host definition is hw-gentoo-freebsd5.4.)
321 By using $host and $build variables inside a configure.ac script you can enable
322 or disable specific features based on the operating system or on the hardware
323 platform you're compiling to or on.
324 </p>
325
326 <p>
327 <b>Don't abuse "automagic" dependencies</b>. One of the most useful features of
328 autotools are the automatic checks for the presence of a library, which are
329 often used to automatically enable support for extra dependencies and such.
330 However, abusing this feature makes the build of a package a bit of a problem.
331 While this is quite useful for first-time users, and although most of the
332 projects having complex dependencies (such as multimedia programs like xine and
333 VLC) use a plugin-based framework that allows them to avoid most of the
334 breakages, "automagic" dependencies are a great pain for packagers, especially
335 ones working on source-based distributions such as Gentoo and ports-like
336 frameworks. When you build something with automagical dependencies you enable
337 the functions supported by the libraries found on the system on which the
338 configure script is run. This means that the output binaries might not work on
339 a system that shares the same base packages but misses one extra library, for
340 example. Also, you can't tell the exact dependencies of a package, as some
341 might be optional and not be built when the libraries are not present.
342 </p>
343
344 <p>
345 To avoid this, autoconf allows you to add --enable/--disable and
346 --with/--without options to configure scripts. With such options you can
347 forcefully enable or disable a specific option (such as the support for an
348 extra library or for a specific feature), and leave the default to automatic
349 tests.
350 </p>
351
352 <p>
353 Unfortunately, many developers misunderstand the meaning of the two parameters
354 of the functions used to add those options (AC_ARG_ENABLE and AC_ARG_WITH).
355 They represent the code to execute when a parameter is passed and when one is
356 not. Many developers mistakenly think that the two parameters define the code
357 to execute when the feature is enabled and when is disabled. While this usually
358 works when you pass a parameter just to change the default behavior, many
359 source-based distributions pass parameters also to confirm the default
360 behavior, which leads to errors (features explicitly requested missing). Being
361 able to disable optional features if they don't add dependencies (think of OSS
362 audio support on Linux) is always a good thing for users, who can avoid
363 building extra code if they don't plan to use it, and prevents maintainers from
364 doing dirty caching tricks to enable or disable features as their users
365 request.
366 </p>
367
368 <p>
369 While autotools were a big problem for both developers and maintainers because
370 there are different incompatible versions that do not get along well together
371 (since they install in the same places, with the same names) and which are used
372 in different combinations, the use of autotools saves maintainers from doing
373 all sorts of dirty tricks to compile software. If you look at ebuild from
374 Gentoo's portage, the few that do not use autotools are the more complex ones,
375 as they need to check variables on very different setups (we can or not have
376 NPTL support; we can be on Linux, FreeBSD, or Mac OS X; we can be using GLIBC
377 or another libc; and so on), while autotools usually take care of that on their
378 own. It's also true that many patches applied by maintainers are to fix broken
379 autotools script in upstream sources, but this is just a little problem
380 compared to the chaos of using special build systems that don't work at all
381 with little environmental changes.
382 </p>
383
384 <p>
385 Autotools can be quite tricky for newcomers, but when you start using them on a
386 daily basis you find it's a lot easier than having to deal with manual
387 makefiles or other strange build tools such as imake or qmake, or even worse,
388 special autotools-like build scripts that try to recognize the system they are
389 building on. Autotools makes it simple to support new OSes and new hardware
390 platforms, and saves maintainers and porters from having to learn how to
391 custom-build a system to fix compilation. By carefully writing a script,
392 developers can support new platforms without any changes at all.
393 </p>
394
395 </body>
396 </section>
397 </chapter>
398 </guide>
399
400
401
402 --
403 gentoo-doc-cvs@g.o mailing list