14c10b7c07196b066131e1dd7aeabab27ae906a7
[scons.git] / doc / user / sconf.in
1 <!--
2
3   __COPYRIGHT__
4
5   Permission is hereby granted, free of charge, to any person obtaining
6   a copy of this software and associated documentation files (the
7   "Software"), to deal in the Software without restriction, including
8   without limitation the rights to use, copy, modify, merge, publish,
9   distribute, sublicense, and/or sell copies of the Software, and to
10   permit persons to whom the Software is furnished to do so, subject to
11   the following conditions:
12
13   The above copyright notice and this permission notice shall be included
14   in all copies or substantial portions of the Software.
15
16   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17   KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18   WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 -->
25
26   <para>
27
28   &SCons; has integrated support for multi-platform build configuration
29   similar to that offered by GNU &Autoconf;,
30   such as
31   figuring out what libraries or header files
32   are available on the local system.
33   This section describes how to use
34   this &SCons feature.
35
36   </para>
37
38   <note>
39   <para>
40   This chapter is still under development,
41   so not everything is explained as well as it should be.
42   See the &SCons; man page for additional information.
43   </para>
44   </note>
45
46   <section>
47   <title>&Configure_Contexts;</title>
48
49     <para>
50
51     The basic framework for multi-platform build configuration
52     in &SCons; is to attach a &configure_context; to a
53     construction environment by calling the &Configure; function,
54     perform a number of checks for
55     libraries, functions, header files, etc.,
56     and to then call the configure context's &Finish; method
57     to finish off the configuration:
58
59     </para>
60
61     <sconstruct>
62     env = Environment()
63     conf = Configure(env)
64     # Checks for libraries, header files, etc. go here!
65     env = conf.Finish()
66     </sconstruct>
67
68     <para>
69
70     &SCons; provides a number of basic checks,
71     as well as a mechanism for adding your own custom checks.
72
73     </para>
74
75     <para>
76
77     Note that &SCons; uses its own dependency
78     mechanism to determine when a check
79     needs to be run--that is,
80     &SCons; does not run the checks
81     every time it is invoked,
82     but caches the values returned by previous checks
83     and uses the cached values unless something has changed.
84     This saves a tremendous amount
85     of developer time while working on
86     cross-platform build issues.
87
88     </para>
89
90     <para>
91
92     The next sections describe
93     the basic checks that &SCons; supports,
94     as well as how to add your own custom checks.
95
96     </para>
97
98   </section>
99
100   <section>
101   <title>Checking for the Existence of Header Files</title>
102
103     <para>
104
105     Testing the existence of a header file
106     requires knowing what language the header file is.
107     A configure context has a &CheckCHeader; method
108     that checks for the existence of a C header file:
109
110     </para>
111
112     <sconstruct>
113     env = Environment()
114     conf = Configure(env)
115     if not conf.CheckCHeader('math.h'):
116         print 'Math.h must be installed!'
117         Exit(1)
118     if conf.CheckCHeader('foo.h'):
119         conf.env.Append('-DHAS_FOO_H')
120     env = conf.Finish()
121     </sconstruct>
122
123     <para>
124
125     Note that you can choose to terminate
126     the build if a given header file doesn't exist,
127     or you can modify the contstruction environment
128     based on the existence of a header file.
129
130     </para>
131
132     <para>
133
134     If you need to check for the existence
135     a C++ header file,
136     use the &CheckCXXHeader; method:
137
138     </para>
139
140     <sconstruct>
141     env = Environment()
142     conf = Configure(env)
143     if not conf.CheckCXXHeader('vector.h'):
144         print 'vector.h must be installed!'
145         Exit(1)
146     env = conf.Finish()
147     </sconstruct>
148
149   </section>
150
151   <section>
152   <title>Checking for the Availability of a Function</title>
153
154     <para>
155
156     Check for the availability of a specific function
157     using the &CheckFunc; method:
158
159     </para>
160
161     <sconstruct>
162     env = Environment()
163     conf = Configure(env)
164     if not conf.CheckFunc('strcpy'):
165         print 'Did not find strcpy(), using local version'
166         conf.env.Append('-Dstrcpy=my_local_strcpy')
167     env = conf.Finish()
168     </sconstruct>
169
170   </section>
171
172   <section>
173   <title>Checking for the Availability of a Library</title>
174
175     <para>
176
177     Check for the availability of a library
178     using the &CheckLib; method.
179     You only specify the basename of the library,
180     you don't need to add a <literal>lib</literal>
181     prefix or a <literal>.a</literal> or <literal>.lib</literal> suffix:
182
183     </para>
184
185     <sconstruct>
186     env = Environment()
187     conf = Configure(env)
188     if not conf.CheckLib('m'):
189         print 'Did not find libm.a or m.lib, exiting!'
190         Exit(1)
191     env = conf.Finish()
192     </sconstruct>
193
194     <para>
195
196     Because the ability to use a library successfully
197     often depends on having access to a header file
198     that describes the library's interface,
199     you can check for a library
200     <emphasis>and</emphasis> a header file
201     at the same time by using the
202     &CheckLibWithHeader; method:
203
204     </para>
205
206     <sconstruct>
207     env = Environment()
208     conf = Configure(env)
209     if not conf.CheckLibWithHeader('m', 'math.h'):
210         print 'Did not find libm.a or m.lib, exiting!'
211         Exit(1)
212     env = conf.Finish()
213     </sconstruct>
214
215     <para>
216
217     This is essentially shorthand for
218     separate calls to the &CheckHeader; and &CheckLib;
219     functions.
220
221     </para>
222
223   </section>
224
225   <section>
226   <title>Checking for the Availability of a &typedef;</title>
227
228     <para>
229
230     Check for the availability of a &typedef;
231     by using the &CheckType; method:
232
233     </para>
234
235     <sconstruct>
236     env = Environment()
237     conf = Configure(env)
238     if not conf.CheckType('off_t'):
239         print 'Did not find off_t typedef, assuming int'
240         conf.env.Append(CCFLAGS = '-Doff_t=int')
241     env = conf.Finish()
242     </sconstruct>
243
244     <para>
245
246     You can also add a string that will be
247     placed at the beginning of the test file
248     that will be used to check for the &typedef;.
249     This provide a way to specify
250     files that must be included to find the &typedef;:
251
252     </para>
253
254     <sconstruct>
255     env = Environment()
256     conf = Configure(env)
257     if not conf.CheckType('off_t', '#include &amp;lt;sys/types.h&amp;gt;\n'):
258         print 'Did not find off_t typedef, assuming int'
259         conf.env.Append(CCFLAGS = '-Doff_t=int')
260     env = conf.Finish()
261     </sconstruct>
262
263   </section>
264
265   <section>
266   <title>Adding Your Own Custom Checks</title>
267
268     <para>
269
270     A custom check is a Python function
271     that checks for a certain condition to exist
272     on the running system,
273     usually using methods that &SCons;
274     supplies to take care of the details
275     of checking whether a compilation succeeds,
276     a link succeeds,
277     a program is runnable,
278     etc.
279     A simple custom check for the existence of
280     a specific library might look as follows:
281
282     </para>
283
284     <sconstruct>
285     mylib_test_source_file = """
286     #include &amp;lt;mylib.h&amp;gt;
287     int main(int argc, char **argv)
288     {
289         MyLibrary mylib(argc, argv);
290         return 0;
291     }
292     """
293
294     def CheckMyLibrary(context):
295         context.Message('Checking for MyLibrary...')
296         result = context.TryLink(mylib_test_source_file, '.c')
297         context.Result(result)
298         return result
299     </sconstruct>
300
301     <para>
302
303     The &Message; and &Result; methods
304     should typically begin and end a custom check to
305     let the user know what's going on:
306     the &Message; call prints the
307     specified message (with no trailing newline)
308     and the &Result; call prints
309     <literal>ok</literal> if the check succeeds and
310     <literal>failed</literal> if it doesn't.
311     The &TryLink; method
312     actually tests for whether the
313     specified program text
314     will successfully link.
315
316     </para>
317
318     <para>
319
320     (Note that a custom check can modify
321     its check based on any arguments you
322     choose to pass it,
323     or by using or modifying the configure context environment
324     in the <literal>context.env</literal> attribute.)
325
326     </para>
327
328     <para>
329
330     This custom check function is
331     then attached to the &configure_context;
332     by passing a dictionary
333     to the &Configure; call
334     that maps a name of the check
335     to the underlying function:
336
337     </para>
338
339     <sconstruct>
340     env = Environment()
341     conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
342     </sconstruct>
343
344     <para>
345
346     You'll typically want to make
347     the check and the function name the same,
348     as we've done here,
349     to avoid potential confusion.
350
351     </para>
352
353     <para>
354
355     We can then put these pieces together
356     and actually call the <literal>CheckMyLibrary</literal> check
357     as follows:
358
359     </para>
360
361     <sconstruct>
362     mylib_test_source_file = """
363     #include &amp;lt;mylib.h&amp;gt;
364     int main(int argc, char **argv)
365     {
366         MyLibrary mylib(argc, argv);
367         return 0;
368     }
369     """
370
371     def CheckMyLibrary(context):
372         context.Message('Checking for MyLibrary... ')
373         result = context.TryLink(mylib_test_source_file, '.c')
374         context.Result(result)
375         return result
376
377     env = Environment()
378     conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
379     if not conf.CheckMyLibrary():
380         print 'MyLibrary is not installed!'
381         Exit(1)
382     env = conf.Finish()
383
384     # We would then add actual calls like Program() to build
385     # something using the "env" construction environment.
386     </sconstruct>
387
388     <para>
389
390     If MyLibrary is not installed on the system,
391     the output will look like:
392
393     </para>
394
395     <screen>
396     % <userinput>scons</userinput>
397     scons: Reading SConscript file ...
398     Checking for MyLibrary... failed
399     MyLibrary is not installed!
400     </screen>
401
402     <para>
403
404     If MyLibrary is installed,
405     the output will look like:
406
407     </para>
408
409     <screen>
410     % <userinput>scons</userinput>
411     scons: Reading SConscript file ...
412     Checking for MyLibrary... failed
413     scons: done reading SConscript
414     scons: Building targets ...
415         .
416         .
417         .
418     </screen>
419
420   </section>
421
422   <section>
423   <title>Not Configuring When Cleaning Targets</title>
424
425     <para>
426
427     Using multi-platform configuration
428     as described in the previous sections
429     will run the configuration commands
430     even when invoking
431     <userinput>scons -c</userinput>
432     to clean targets:
433
434     </para>
435
436     <screen>
437     % <userinput>scons -Q -c</userinput>
438     Checking for MyLibrary... ok
439     Removed foo.o
440     Removed foo
441     </screen>
442
443     <para>
444
445     Although running the platform checks
446     when removing targets doesn't hurt anything,
447     it's usually unnecessary.
448     You can avoid this by using the
449     &GetOption(); method to
450     check whether the <option>-c</option> (clean)
451     option has been invoked on the command line:
452
453     </para>
454
455     <sconstruct>
456     env = Environment()
457     if not env.GetOption('clean'):
458         conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
459         if not conf.CheckMyLibrary():
460             print 'MyLibrary is not installed!'
461             Exit(1)
462         env = conf.Finish()
463     </sconstruct>
464
465     <screen>
466     % <userinput>scons -Q -c</userinput>
467     Removed foo.o
468     Removed foo
469     </screen>
470
471   </section>