3 Copyright (c) 2001, 2002, 2003 Steven Knight
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:
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
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.
30 Cons is Perl-based. That is, Cons scripts F<Conscript> and F<Construct>
31 files, the equivalent to F<Makefile> or F<makefile> are all written in
32 Perl. This provides an immediate benefit: the language for writing scripts
33 is a familiar one. Even if you don't happen to be a Perl programmer, it
34 helps to know that Perl is basically just a simple declarative language,
35 with a well-defined flow of control, and familiar semantics. It has
36 variables that behave basically the way you would expect them to,
37 subroutines, flow of control, and so on. There is no special syntax
38 introduced for Cons. The use of Perl as a scripting language simplifies
39 the task of expressing the appropriate solution to the often complex
40 requirements of a build.
46 Here's how to build the famous "Hello, World!" example using &SCons;.
54 printf("Hello, world!\n");
60 Enter the following into a file name &SConstruct;:
66 env.Program('hello.c')
71 That's it. Now run the &scons; command to build the program.
72 On a POSIX-compliant system like Linux or UNIX,
73 you'll see something like:
78 % <userinput>scons</userinput>
79 cc -c hello.c -o hello.o
85 On a Windows system with the Microsoft Visual C++ compiler,
86 you'll see something like:
91 C:\><userinput>scons</userinput>
92 cl /Fohello.obj hello.c
93 link /Fohello.exe hello.obj
98 First, notice that you only need
99 to specify the name of the source file,
100 and that &SCons; deduces the names of
101 the object and executable files
102 correctly from the source file.
108 Second, notice that the same input &SConstruct; file,
110 generates the correct output file names on both systems:
111 <filename>hello.o</filename> and <filename>hello</filename>
113 <filename>hello.obj</filename> and <filename>hello.exe</filename>
115 This is a simple example of how easy it is to
116 use &SCons; to write portable software builds.
122 (Note that we won't provide duplicate side-by-side
123 POSIX and Windows output for the
124 rest of the examples in this guide;
125 just keep in mind that, unless otherwise specified,
126 any of the examples should work equally well on both types of systems.)
131 <title>The &SConstruct; File</title>
135 If you're used to build systems like &Make;
136 you've already figured out that the &SConstruct; file
137 is the &SCons; equivalent of a &Makefile;.
138 That is, the &SConstruct; file is the input file
139 that &SCons; reads to control the build.
145 What may not be obvious, though, is that
146 there's an important difference between
147 an &SConstruct; file and a &Makefile:
148 the &SConstruct; file is actually a Python script.
149 If you're not already familiar with Python, don't worry;
150 Python is very easy to learn,
151 and this User's Guide will introduce you step-by-step
152 to the relatively small amount of Python you'll
153 need to know to be able to use &SCons; effectively.
159 One aspect of using Python as the
160 scripting language is that you can put comments
161 in your &SConstruct; file using Python's commenting convention;
162 that is, everything between a '#' and the end of the line
168 env = Environment() # Create an environment.
169 # Arrange to build the "hello" program.
170 env.Program('hello.c')
175 You'll see throughout the remainder of this Guide
176 that being able to use the power of a
177 real scripting language
178 can greatly simplify the solutions
179 to complex requirements of real-world builds.
186 <title>Compiling Multiple Source Files</title>
190 It's more common, of course,
191 that you'll need to build a program from
192 not just one, but many input source files.
193 To do this, you need to put the
194 source files in a Python list
195 (enclosed in square brackets),
196 and slide that list over to to the right
197 to make room for the output program file name.
204 env.Program('program', ['main.c', 'file1.c', 'file2.'])
209 (&SCons; puts the output file name to the left
210 of the source file names
211 so that the order mimics that of an
212 assignment statement: "program = source files".)
218 A build of the above example would look:
223 % <userinput>scons</userinput>
224 cc -c file1.c -o file1.o
225 cc -c file2.c -o file2.o
226 cc -c main.c -o main.o
227 cc -o program main.o file1.o file2.o
232 XXX DO WE NEED WINDOWS EXAMPLE OUTPUT HERE?
241 C:\><userinput>scons</userinput>
242 cl /Fofile1.obj file1.c
243 cl /Fofile2.obj file2.c
244 cl /Fomain.obj main.c
245 link /Foprogram.exe main.obj file1.obj file2.obj
253 <title>Keeping &SConstruct; Files Easy to Read</title>
257 One drawback to the use of a Python list
258 for source files is that
259 each file name must be enclosed in quotes
260 (either single quotes or double quotes).
261 This can get cumbersome and difficult to read
262 when the list of file names is long.
263 Fortunately, there are a number of things
264 we can do to make sure that
265 the &SConstruct; file stays easy to read.
271 To make long lists of file names
272 easier to deal with, &SCons; provides a
274 that takes a quoted list of file names,
275 with the names separated by spaces or other white-space characters,
276 and turns it into a list of separate file names.
277 Using the &Split; function turns the
278 previous example into:
284 env.Program('program', Split('main.c file1.c file2.'))
289 Putting the call to the &Split; function
290 inside the <function>env.Program</function> call
291 can also be a little unwieldy.
292 A more readable alternative is to
293 assign the output from the &Split; call
295 and then use the variable when calling the
296 <function>env.Program</function> function:
302 list = Split('main.c file1.c file2.')
303 env.Program('program', list)
308 Lastly, the &Split; function
309 doesn't care how much white space separates
310 the file names in the quoted string.
311 This allows you to create lists of file
312 names that span multiple lines,
313 which often makes for easier editing:
322 env.Program('program', list)
328 <title>Keyword Arguments</title>
332 &SCons; also allows you to identify
333 the output file and input source files
334 by Python keyword arguments.
335 The output file is known as the
336 <emphasis>target</emphasis>,
337 and the source file(s) are known (logically enough) as the
338 <emphasis>source</emphasis>.
339 The Python syntax for this is:
345 list = Split('main.c file1.c file2.')
346 env.Program(target = 'program', source = list)
351 Whether or not you choose to use keyword arguments
352 to identify the target and source files
353 is purely a personal choice.
360 <title>Compiling Multiple Programs</title>
364 In order to compile multiple programs
365 within the same &SConstruct; file,
366 simply call <function>env.Program</function>
368 once for each program you need to build:
375 env.Program('bar', ['bar1.c', 'bar2.c'])
380 &SCons; would then build the programs as follows:
385 % <userinput>scons</userinput>
386 cc -c bar1.c -o bar1.o
387 cc -c bar2.c -o bar2.o
388 cc -o bar bar1.o bar2.o
396 <title>Sharing Source Files Between Multiple Programs</title>
405 common = ['common1.c', 'common2.c']
407 env.Program(['foo.c'] + common)
408 env.Program('bar', ['bar1.c', 'bar2.c'] + common)
412 % <userinput>scons</userinput>
413 cc -c bar1.c -o bar1.o
414 cc -c bar2.c -o bar2.o
415 cc -c common1.c -o common1.o
416 cc -c common2.c -o common2.o
417 cc -o bar bar1.o bar2.o common1.o common2.o
419 cc -o foo foo.o common1.o common2.o