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.
28 So far, we've been using examples of
29 building C and C++ programs
30 to demonstrate the features of &SCons;.
31 &SCons; also supports building Java programs,
32 but Java builds are handled slightly differently,
33 which reflects the ways in which
34 the Java compiler and tools
35 build programs differently than
36 other languages' tool chains.
41 <title>Building Java Class Files: the &b-Java; Builder</title>
45 The basic activity when programming in Java,
46 of course, is to take one or more <filename>.java</filename> files
47 containing Java source code
48 and to call the Java compiler
49 to turn them into one or more
50 <filename>.class</filename> files.
51 In &SCons;, you do this
52 by giving the &b-link-Java; Builder
53 a target directory in which
54 to put the <filename>.class</filename> files,
55 and a source directory that contains
56 the <filename>.java</filename> files:
60 <scons_example name="java">
61 <file name="SConstruct" printme="1">
62 Java('classes', 'src')
64 <file name="src/Example1.java">
67 public static void main(String[] args)
69 System.out.println("Hello Java world!\n");
73 <file name="src/Example2.java">
76 public static void main(String[] args)
78 System.out.println("Hello Java world!\n");
82 <file name="src/Example3.java">
85 public static void main(String[] args)
87 System.out.println("Hello Java world!\n");
95 If the <filename>src</filename> directory contains
96 three <filename>.java</filename> source files,
97 then running &SCons; might look like this:
101 <scons_output example="java">
102 <scons_output_command>scons -Q</scons_output_command>
107 &SCons; will actually search the <filename>src</filename>
108 directory tree for all of the <filename>.java</filename> files.
109 The Java compiler will then create the
110 necessary class files in the <filename>classes</filename> subdirectory,
111 based on the class names found in the <filename>.java</filename> files.
118 <title>How &SCons; Handles Java Dependencies</title>
122 In addition to searching the source directory for
123 <filename>.java</filename> files,
124 &SCons; actually runs the <filename>.java</filename> files
125 through a stripped-down Java parser that figures out
126 what classes are defined.
127 In other words, &SCons; knows,
128 without you having to tell it,
129 what <filename>.class</filename> files
130 will be produced by the &javac; call.
131 So our one-liner example from the preceding section:
135 <scons_example name="java-classes">
136 <file name="SConstruct" printme="1">
137 Java('classes', 'src')
139 <file name="src/Example1.java">
140 public class Example1
142 public static void main(String[] args)
144 System.out.println("Hello Java world!\n");
147 public class AdditionalClass1
149 public static void main(String[] args)
151 System.out.println("Hello Java world!\n");
155 <file name="src/Example2.java">
156 public class Example2
159 public static void main(String[] args)
161 System.out.println("Hello Java world!\n");
166 <file name="src/Example3.java">
167 public class Example3
169 public static void main(String[] args)
171 System.out.println("Hello Java world!\n");
174 public class AdditionalClass3
176 public static void main(String[] args)
178 System.out.println("Hello Java world!\n");
186 Will not only tell you reliably
187 that the <filename>.class</filename> files
188 in the <filename>classes</filename> subdirectory
193 <scons_output example="java-classes">
194 <scons_output_command>scons -Q</scons_output_command>
195 <scons_output_command>scons -Q classes</scons_output_command>
200 But it will also remove all of the generated
201 <filename>.class</filename> files,
202 even for inner classes,
203 without you having to specify them manually.
205 <filename>Example1.java</filename>
207 <filename>Example3.java</filename>
208 files both define additional classes,
209 and the class defined in <filename>Example2.java</filename>
211 running <userinput>scons -c</userinput>
212 will clean up all of those <filename>.class</filename> files
217 <scons_output example="java-classes">
218 <scons_output_command>scons -Q</scons_output_command>
219 <scons_output_command>scons -Q -c classes</scons_output_command>
225 <title>Building Java Archive (<filename>.jar</filename>) Files: the &b-Jar; Builder</title>
229 After building the class files,
230 it's common to collect them into
231 a Java archive (<filename>.jar</filename>) file,
232 which you do by calling the &b-link-Jar; Builder method.
233 If you want to just collect all of the
234 class files within a subdirectory,
235 you can just specify that subdirectory
236 as the &b-Jar; source:
240 <scons_example name="jar1">
241 <file name="SConstruct" printme="1">
242 Java(target = 'classes', source = 'src')
243 Jar(target = 'test.jar', source = 'classes')
245 <file name="src/Example1.java">
246 public class Example1
248 public static void main(String[] args)
250 System.out.println("Hello Java world!\n");
254 <file name="src/Example2.java">
255 public class Example2
257 public static void main(String[] args)
259 System.out.println("Hello Java world!\n");
263 <file name="src/Example3.java">
264 public class Example3
266 public static void main(String[] args)
268 System.out.println("Hello Java world!\n");
276 &SCons; will then pass that directory
277 to the &jar; command,
278 which will collect all of the underlying
279 <filename>.class</filename> files:
283 <scons_output example="jar1">
284 <scons_output_command>scons -Q</scons_output_command>
289 If you want to keep all of the
290 <filename>.class</filename> files
291 for multiple programs in one location,
292 and only archive some of them in
293 each <filename>.jar</filename> file,
294 you can pass the &b-Jar; builder a
295 list of files as its source.
296 It's extremely simple to create multiple
297 <filename>.jar</filename> files this way,
298 using the lists of target class files created
299 by calls to the &b-link-Java; builder
300 as sources to the various &b-Jar; calls:
304 <scons_example name="jar2">
305 <file name="SConstruct" printme="1">
306 prog1_class_files = Java(target = 'classes', source = 'prog1')
307 prog2_class_files = Java(target = 'classes', source = 'prog2')
308 Jar(target = 'prog1.jar', source = prog1_class_files)
309 Jar(target = 'prog2.jar', source = prog2_class_files)
311 <file name="prog1/Example1.java">
312 public class Example1
314 public static void main(String[] args)
316 System.out.println("Hello Java world!\n");
320 <file name="prog1/Example2.java">
321 public class Example2
323 public static void main(String[] args)
325 System.out.println("Hello Java world!\n");
329 <file name="prog2/Example3.java">
330 public class Example3
332 public static void main(String[] args)
334 System.out.println("Hello Java world!\n");
338 <file name="prog2/Example4.java">
339 public class Example4
341 public static void main(String[] args)
343 System.out.println("Hello Java world!\n");
351 This will then create
352 <filename>prog1.jar</filename>
353 and <filename>prog2.jar</filename>
354 next to the subdirectories
355 that contain their <filename>.java</filename> files:
359 <scons_output example="jar2">
360 <scons_output_command>scons -Q</scons_output_command>
366 <title>Building C Header and Stub Files: the &b-JavaH; Builder</title>
370 You can generate C header and source files
371 for implementing native methods,
372 by using the &b-link-JavaH; Builder.
373 There are several ways of using the &JavaH Builder.
374 One typical invocation might look like:
378 <scons_example name="javah">
379 <file name="SConstruct" printme="1">
380 classes = Java(target = 'classes', source = 'src/pkg/sub')
381 JavaH(target = 'native', source = classes)
383 <file name="src/pkg/sub/Example1.java">
385 public class Example1
387 public static void main(String[] args)
392 <file name="src/pkg/sub/Example2.java">
394 public class Example2
396 public static void main(String[] args)
401 <file name="src/pkg/sub/Example3.java">
403 public class Example3
405 public static void main(String[] args)
414 The source is a list of class files generated by the
415 call to the &b-link-Java; Builder,
416 and the target is the output directory in
417 which we want the C header files placed.
419 gets converted into the <option>-d</option>
420 when &SCons; runs &javah;:
424 <scons_output example="javah">
425 <scons_output_command>scons -Q</scons_output_command>
432 will generate the header files
433 <filename>native/pkg_sub_Example1.h</filename>,
434 <filename>native/pkg_sub_Example2.h</filename>
436 <filename>native/pkg_sub_Example3.h</filename>.
437 Notice that &SCons; remembered that the class
438 files were generated with a target directory of
439 <filename>classes</filename>,
440 and that it then specified that target directory
441 as the <option>-classpath</option> option
442 to the call to &javah;.
448 Although it's more convenient to use
449 the list of class files returned by
451 as the source of a call to the &b-JavaH; Builder,
452 you <emphasis>can</emphasis>
453 specify the list of class files
454 by hand, if you prefer.
457 &cv-link-JAVACLASSDIR; construction variable
458 when calling &b-JavaH;:
462 <scons_example name="JAVACLASSDIR">
463 <file name="SConstruct" printme="1">
464 Java(target = 'classes', source = 'src/pkg/sub')
465 class_file_list = ['classes/pkg/sub/Example1.class',
466 'classes/pkg/sub/Example2.class',
467 'classes/pkg/sub/Example3.class']
468 JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes')
470 <file name="src/pkg/sub/Example1.java">
472 public class Example1
474 public static void main(String[] args)
479 <file name="src/pkg/sub/Example2.java">
481 public class Example2
483 public static void main(String[] args)
488 <file name="src/pkg/sub/Example3.java">
490 public class Example3
492 public static void main(String[] args)
501 The &cv-JAVACLASSDIR; value then
502 gets converted into the <option>-classpath</option>
503 when &SCons; runs &javah;:
507 <scons_output example="JAVACLASSDIR">
508 <scons_output_command>scons -Q</scons_output_command>
513 Lastly, if you don't want a separate header file
514 generated for each source file,
515 you can specify an explicit File Node
516 as the target of the &b-JavaH; Builder:
520 <scons_example name="javah_file">
521 <file name="SConstruct" printme="1">
522 classes = Java(target = 'classes', source = 'src/pkg/sub')
523 JavaH(target = File('native.h'), source = classes)
525 <file name="src/pkg/sub/Example1.java">
527 public class Example1
529 public static void main(String[] args)
534 <file name="src/pkg/sub/Example2.java">
536 public class Example2
538 public static void main(String[] args)
543 <file name="src/pkg/sub/Example3.java">
545 public class Example3
547 public static void main(String[] args)
556 Because &SCons; assumes by default
557 that the target of the &b-JavaH; builder is a directory,
558 you need to use the &File; function
559 to make sure that &SCons; doesn't
560 create a directory named <filename>native.h</filename>.
561 When a file is used, though,
562 &SCons; correctly converts the file name
563 into the &javah; <option>-o</option> option:
567 <scons_output example="javah_file">
568 <scons_output_command>scons -Q</scons_output_command>
574 <title>Building RMI Stub and Skeleton Class Files: the &b-RMIC; Builder</title>
578 You can generate Remote Method Invocation stubs
579 by using the &b-link-RMIC; Builder.
580 The source is a list of directories,
581 typically returned by a call to the &b-link-Java; Builder,
582 and the target is an output directory
583 where the <filename>_Stub.class</filename>
584 and <filename>_Skel.class</filename> files will
589 <scons_example name="RMIC">
590 <file name="SConstruct" printme="1">
591 classes = Java(target = 'classes', source = 'src/pkg/sub')
592 RMIC(target = 'outdir', source = classes)
594 <file name="src/pkg/sub/Example1.java">
596 public class Example1
598 public static void main(String[] args)
603 <file name="src/pkg/sub/Example2.java">
605 public class Example2
607 public static void main(String[] args)
616 As it did with the &b-link-JavaH; Builder,
617 &SCons; remembers the class directory
618 and passes it as the <option>-classpath</option> option
623 <scons_output example="RMIC">
624 <scons_output_command>scons -Q</scons_output_command>
629 This example would generate the files
630 <filename>outdir/pkg/sub/Example1_Skel.class</filename>,
631 <filename>outdir/pkg/sub/Example1_Stub.class</filename>,
632 <filename>outdir/pkg/sub/Example2_Skel.class</filename> and
633 <filename>outdir/pkg/sub/Example2_Stub.class</filename>.