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>
224 To ensure correct handling of <filename>.class</filename>
225 dependencies in all cases, you need to tell &SCons; which Java
226 version is being used. This is needed because Java 1.5 changed
227 the <filename>.class</filename> file names for nested anonymous
228 inner classes. Use the <varname>JAVAVERSION</varname> construction
229 variable to specify the version in use. With Java 1.6, the
230 one-liner example can then be defined like this:
235 Java('classes', 'src', JAVAVERSION='1.6')
239 See <varname>JAVAVERSION</varname> in the man page for more information.
245 <title>Building Java Archive (<filename>.jar</filename>) Files: the &b-Jar; Builder</title>
249 After building the class files,
250 it's common to collect them into
251 a Java archive (<filename>.jar</filename>) file,
252 which you do by calling the &b-link-Jar; Builder method.
253 If you want to just collect all of the
254 class files within a subdirectory,
255 you can just specify that subdirectory
256 as the &b-Jar; source:
260 <scons_example name="jar1">
261 <file name="SConstruct" printme="1">
262 Java(target = 'classes', source = 'src')
263 Jar(target = 'test.jar', source = 'classes')
265 <file name="src/Example1.java">
266 public class Example1
268 public static void main(String[] args)
270 System.out.println("Hello Java world!\n");
274 <file name="src/Example2.java">
275 public class Example2
277 public static void main(String[] args)
279 System.out.println("Hello Java world!\n");
283 <file name="src/Example3.java">
284 public class Example3
286 public static void main(String[] args)
288 System.out.println("Hello Java world!\n");
296 &SCons; will then pass that directory
297 to the &jar; command,
298 which will collect all of the underlying
299 <filename>.class</filename> files:
303 <scons_output example="jar1">
304 <scons_output_command>scons -Q</scons_output_command>
309 If you want to keep all of the
310 <filename>.class</filename> files
311 for multiple programs in one location,
312 and only archive some of them in
313 each <filename>.jar</filename> file,
314 you can pass the &b-Jar; builder a
315 list of files as its source.
316 It's extremely simple to create multiple
317 <filename>.jar</filename> files this way,
318 using the lists of target class files created
319 by calls to the &b-link-Java; builder
320 as sources to the various &b-Jar; calls:
324 <scons_example name="jar2">
325 <file name="SConstruct" printme="1">
326 prog1_class_files = Java(target = 'classes', source = 'prog1')
327 prog2_class_files = Java(target = 'classes', source = 'prog2')
328 Jar(target = 'prog1.jar', source = prog1_class_files)
329 Jar(target = 'prog2.jar', source = prog2_class_files)
331 <file name="prog1/Example1.java">
332 public class Example1
334 public static void main(String[] args)
336 System.out.println("Hello Java world!\n");
340 <file name="prog1/Example2.java">
341 public class Example2
343 public static void main(String[] args)
345 System.out.println("Hello Java world!\n");
349 <file name="prog2/Example3.java">
350 public class Example3
352 public static void main(String[] args)
354 System.out.println("Hello Java world!\n");
358 <file name="prog2/Example4.java">
359 public class Example4
361 public static void main(String[] args)
363 System.out.println("Hello Java world!\n");
371 This will then create
372 <filename>prog1.jar</filename>
373 and <filename>prog2.jar</filename>
374 next to the subdirectories
375 that contain their <filename>.java</filename> files:
379 <scons_output example="jar2">
380 <scons_output_command>scons -Q</scons_output_command>
386 <title>Building C Header and Stub Files: the &b-JavaH; Builder</title>
390 You can generate C header and source files
391 for implementing native methods,
392 by using the &b-link-JavaH; Builder.
393 There are several ways of using the &JavaH Builder.
394 One typical invocation might look like:
398 <scons_example name="javah">
399 <file name="SConstruct" printme="1">
400 classes = Java(target = 'classes', source = 'src/pkg/sub')
401 JavaH(target = 'native', source = classes)
403 <file name="src/pkg/sub/Example1.java">
405 public class Example1
407 public static void main(String[] args)
412 <file name="src/pkg/sub/Example2.java">
414 public class Example2
416 public static void main(String[] args)
421 <file name="src/pkg/sub/Example3.java">
423 public class Example3
425 public static void main(String[] args)
434 The source is a list of class files generated by the
435 call to the &b-link-Java; Builder,
436 and the target is the output directory in
437 which we want the C header files placed.
439 gets converted into the <option>-d</option>
440 when &SCons; runs &javah;:
444 <scons_output example="javah">
445 <scons_output_command>scons -Q</scons_output_command>
452 will generate the header files
453 <filename>native/pkg_sub_Example1.h</filename>,
454 <filename>native/pkg_sub_Example2.h</filename>
456 <filename>native/pkg_sub_Example3.h</filename>.
457 Notice that &SCons; remembered that the class
458 files were generated with a target directory of
459 <filename>classes</filename>,
460 and that it then specified that target directory
461 as the <option>-classpath</option> option
462 to the call to &javah;.
468 Although it's more convenient to use
469 the list of class files returned by
471 as the source of a call to the &b-JavaH; Builder,
472 you <emphasis>can</emphasis>
473 specify the list of class files
474 by hand, if you prefer.
477 &cv-link-JAVACLASSDIR; construction variable
478 when calling &b-JavaH;:
482 <scons_example name="JAVACLASSDIR">
483 <file name="SConstruct" printme="1">
484 Java(target = 'classes', source = 'src/pkg/sub')
485 class_file_list = ['classes/pkg/sub/Example1.class',
486 'classes/pkg/sub/Example2.class',
487 'classes/pkg/sub/Example3.class']
488 JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes')
490 <file name="src/pkg/sub/Example1.java">
492 public class Example1
494 public static void main(String[] args)
499 <file name="src/pkg/sub/Example2.java">
501 public class Example2
503 public static void main(String[] args)
508 <file name="src/pkg/sub/Example3.java">
510 public class Example3
512 public static void main(String[] args)
521 The &cv-JAVACLASSDIR; value then
522 gets converted into the <option>-classpath</option>
523 when &SCons; runs &javah;:
527 <scons_output example="JAVACLASSDIR">
528 <scons_output_command>scons -Q</scons_output_command>
533 Lastly, if you don't want a separate header file
534 generated for each source file,
535 you can specify an explicit File Node
536 as the target of the &b-JavaH; Builder:
540 <scons_example name="javah_file">
541 <file name="SConstruct" printme="1">
542 classes = Java(target = 'classes', source = 'src/pkg/sub')
543 JavaH(target = File('native.h'), source = classes)
545 <file name="src/pkg/sub/Example1.java">
547 public class Example1
549 public static void main(String[] args)
554 <file name="src/pkg/sub/Example2.java">
556 public class Example2
558 public static void main(String[] args)
563 <file name="src/pkg/sub/Example3.java">
565 public class Example3
567 public static void main(String[] args)
576 Because &SCons; assumes by default
577 that the target of the &b-JavaH; builder is a directory,
578 you need to use the &File; function
579 to make sure that &SCons; doesn't
580 create a directory named <filename>native.h</filename>.
581 When a file is used, though,
582 &SCons; correctly converts the file name
583 into the &javah; <option>-o</option> option:
587 <scons_output example="javah_file">
588 <scons_output_command>scons -Q</scons_output_command>
594 <title>Building RMI Stub and Skeleton Class Files: the &b-RMIC; Builder</title>
598 You can generate Remote Method Invocation stubs
599 by using the &b-link-RMIC; Builder.
600 The source is a list of directories,
601 typically returned by a call to the &b-link-Java; Builder,
602 and the target is an output directory
603 where the <filename>_Stub.class</filename>
604 and <filename>_Skel.class</filename> files will
609 <scons_example name="RMIC">
610 <file name="SConstruct" printme="1">
611 classes = Java(target = 'classes', source = 'src/pkg/sub')
612 RMIC(target = 'outdir', source = classes)
614 <file name="src/pkg/sub/Example1.java">
616 public class Example1
618 public static void main(String[] args)
623 <file name="src/pkg/sub/Example2.java">
625 public class Example2
627 public static void main(String[] args)
636 As it did with the &b-link-JavaH; Builder,
637 &SCons; remembers the class directory
638 and passes it as the <option>-classpath</option> option
643 <scons_output example="RMIC">
644 <scons_output_command>scons -Q</scons_output_command>
649 This example would generate the files
650 <filename>outdir/pkg/sub/Example1_Skel.class</filename>,
651 <filename>outdir/pkg/sub/Example1_Stub.class</filename>,
652 <filename>outdir/pkg/sub/Example2_Skel.class</filename> and
653 <filename>outdir/pkg/sub/Example2_Stub.class</filename>.