Eliminate / replace remaining cPickle references in test scripts.
[scons.git] / doc / user / java.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   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.
37
38   </para>
39
40   <section>
41   <title>Building Java Class Files:  the &b-Java; Builder</title>
42
43     <para>
44
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:
57
58     </para>
59
60     <scons_example name="java">
61       <file name="SConstruct" printme="1">
62       Java('classes', 'src')
63       </file>
64       <file name="src/Example1.java">
65       public class Example1
66       {
67         public static void main(String[] args)
68         {
69           System.out.println("Hello Java world!\n");
70         }
71       }
72       </file>
73       <file name="src/Example2.java">
74       public class Example2
75       {
76         public static void main(String[] args)
77         {
78           System.out.println("Hello Java world!\n");
79         }
80       }
81       </file>
82       <file name="src/Example3.java">
83       public class Example3
84       {
85         public static void main(String[] args)
86         {
87           System.out.println("Hello Java world!\n");
88         }
89       }
90       </file>
91     </scons_example>
92
93     <para>
94
95     If the <filename>src</filename> directory contains
96     three <filename>.java</filename> source files,
97     then running &SCons; might look like this:
98
99     </para>
100
101     <scons_output example="java">
102       <scons_output_command>scons -Q</scons_output_command>
103     </scons_output>
104
105     <para>
106
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.
112
113     </para>
114
115   </section>
116
117   <section>
118   <title>How &SCons; Handles Java Dependencies</title>
119
120     <para>
121
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:
132
133     </para>
134
135     <scons_example name="java-classes">
136       <file name="SConstruct" printme="1">
137       Java('classes', 'src')
138       </file>
139       <file name="src/Example1.java">
140       public class Example1
141       {
142         public static void main(String[] args)
143         {
144           System.out.println("Hello Java world!\n");
145         }
146       }
147       public class AdditionalClass1
148       {
149         public static void main(String[] args)
150         {
151           System.out.println("Hello Java world!\n");
152         }
153       }
154       </file>
155       <file name="src/Example2.java">
156       public class Example2
157       {
158         class Inner2 {
159           public static void main(String[] args)
160           {
161             System.out.println("Hello Java world!\n");
162           }
163         }
164       }
165       </file>
166       <file name="src/Example3.java">
167       public class Example3
168       {
169         public static void main(String[] args)
170         {
171           System.out.println("Hello Java world!\n");
172         }
173       }
174       public class AdditionalClass3
175       {
176         public static void main(String[] args)
177         {
178           System.out.println("Hello Java world!\n");
179         }
180       }
181       </file>
182     </scons_example>
183
184     <para>
185
186     Will not only tell you reliably
187     that the <filename>.class</filename> files
188     in the <filename>classes</filename> subdirectory 
189     are up-to-date:
190
191     </para>
192
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>
196     </scons_output>
197
198     <para>
199
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.
204     For example, if our
205     <filename>Example1.java</filename>
206     and
207     <filename>Example3.java</filename>
208     files both define additional classes,
209     and the class defined in <filename>Example2.java</filename>
210     has an inner class,
211     running <userinput>scons -c</userinput>
212     will clean up all of those <filename>.class</filename> files
213     as well:
214
215     </para>
216
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>
220     </scons_output>
221
222     <para>
223
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:
231
232     </para> 
233
234     <sconstruct>
235       Java('classes', 'src', JAVAVERSION='1.6')
236     </sconstruct>
237
238     <para>
239     See <varname>JAVAVERSION</varname> in the man page for more information.
240     </para>
241
242   </section>
243
244   <section>
245   <title>Building Java Archive (<filename>.jar</filename>) Files:  the &b-Jar; Builder</title>
246
247     <para>
248
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:
257
258     </para>
259
260     <scons_example name="jar1">
261       <file name="SConstruct" printme="1">
262       Java(target = 'classes', source = 'src')
263       Jar(target = 'test.jar', source = 'classes')
264       </file>
265       <file name="src/Example1.java">
266       public class Example1
267       {
268         public static void main(String[] args)
269         {
270           System.out.println("Hello Java world!\n");
271         }
272       }
273       </file>
274       <file name="src/Example2.java">
275       public class Example2
276       {
277         public static void main(String[] args)
278         {
279           System.out.println("Hello Java world!\n");
280         }
281       }
282       </file>
283       <file name="src/Example3.java">
284       public class Example3
285       {
286         public static void main(String[] args)
287         {
288           System.out.println("Hello Java world!\n");
289         }
290       }
291       </file>
292     </scons_example>
293
294     <para>
295
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:
300
301     </para>
302
303     <scons_output example="jar1">
304       <scons_output_command>scons -Q</scons_output_command>
305     </scons_output>
306
307     <para>
308
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:
321
322     </para>
323
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)
330       </file>
331       <file name="prog1/Example1.java">
332       public class Example1
333       {
334         public static void main(String[] args)
335         {
336           System.out.println("Hello Java world!\n");
337         }
338       }
339       </file>
340       <file name="prog1/Example2.java">
341       public class Example2
342       {
343         public static void main(String[] args)
344         {
345           System.out.println("Hello Java world!\n");
346         }
347       }
348       </file>
349       <file name="prog2/Example3.java">
350       public class Example3
351       {
352         public static void main(String[] args)
353         {
354           System.out.println("Hello Java world!\n");
355         }
356       }
357       </file>
358       <file name="prog2/Example4.java">
359       public class Example4
360       {
361         public static void main(String[] args)
362         {
363           System.out.println("Hello Java world!\n");
364         }
365       }
366       </file>
367     </scons_example>
368
369     <para>
370
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:
376
377     </para>
378
379     <scons_output example="jar2">
380       <scons_output_command>scons -Q</scons_output_command>
381     </scons_output>
382
383   </section>
384
385   <section>
386   <title>Building C Header and Stub Files:  the &b-JavaH; Builder</title>
387
388     <para>
389
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:
395
396     </para>
397
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)
402       </file>
403       <file name="src/pkg/sub/Example1.java">
404       package pkg.sub;
405       public class Example1
406       {
407         public static void main(String[] args)
408         {
409         }
410       }
411       </file>
412       <file name="src/pkg/sub/Example2.java">
413       package pkg.sub;
414       public class Example2
415       {
416         public static void main(String[] args)
417         {
418         }
419       }
420       </file>
421       <file name="src/pkg/sub/Example3.java">
422       package pkg.sub;
423       public class Example3
424       {
425         public static void main(String[] args)
426         {
427         }
428       }
429       </file>
430     </scons_example>
431
432     <para>
433
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.
438     The target
439     gets converted into the <option>-d</option>
440     when &SCons; runs &javah;:
441
442     </para>
443
444     <scons_output example="javah">
445       <scons_output_command>scons -Q</scons_output_command>
446     </scons_output>
447
448     <para>
449
450     In this case,
451     the call to &javah;
452     will generate the header files
453     <filename>native/pkg_sub_Example1.h</filename>,
454     <filename>native/pkg_sub_Example2.h</filename>
455     and
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;.
463
464     </para>
465
466     <para>
467
468     Although it's more convenient to use
469     the list of class files returned by
470     the &b-Java; Builder
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.
475     If you do,
476     you need to set the
477     &cv-link-JAVACLASSDIR; construction variable
478     when calling &b-JavaH;:
479
480     </para>
481
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')
489       </file>
490       <file name="src/pkg/sub/Example1.java">
491       package pkg.sub;
492       public class Example1
493       {
494         public static void main(String[] args)
495         {
496         }
497       }
498       </file>
499       <file name="src/pkg/sub/Example2.java">
500       package pkg.sub;
501       public class Example2
502       {
503         public static void main(String[] args)
504         {
505         }
506       }
507       </file>
508       <file name="src/pkg/sub/Example3.java">
509       package pkg.sub;
510       public class Example3
511       {
512         public static void main(String[] args)
513         {
514         }
515       }
516       </file>
517     </scons_example>
518
519     <para>
520
521     The &cv-JAVACLASSDIR; value then
522     gets converted into the <option>-classpath</option>
523     when &SCons; runs &javah;:
524
525     </para>
526
527     <scons_output example="JAVACLASSDIR">
528       <scons_output_command>scons -Q</scons_output_command>
529     </scons_output>
530
531     <para>
532
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:
537
538     </para>
539
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)
544       </file>
545       <file name="src/pkg/sub/Example1.java">
546       package pkg.sub;
547       public class Example1
548       {
549         public static void main(String[] args)
550         {
551         }
552       }
553       </file>
554       <file name="src/pkg/sub/Example2.java">
555       package pkg.sub;
556       public class Example2
557       {
558         public static void main(String[] args)
559         {
560         }
561       }
562       </file>
563       <file name="src/pkg/sub/Example3.java">
564       package pkg.sub;
565       public class Example3
566       {
567         public static void main(String[] args)
568         {
569         }
570       }
571       </file>
572     </scons_example>
573
574     <para>
575
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:
584
585     </para>
586
587     <scons_output example="javah_file">
588       <scons_output_command>scons -Q</scons_output_command>
589     </scons_output>
590
591   </section>
592
593   <section>
594   <title>Building RMI Stub and Skeleton Class Files:  the &b-RMIC; Builder</title>
595
596     <para>
597
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
605     be placed:
606
607     </para>
608
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)
613       </file>
614       <file name="src/pkg/sub/Example1.java">
615       package pkg.sub;
616       public class Example1
617       {
618         public static void main(String[] args)
619         {
620         }
621       }
622       </file>
623       <file name="src/pkg/sub/Example2.java">
624       package pkg.sub;
625       public class Example2
626       {
627         public static void main(String[] args)
628         {
629         }
630       }
631       </file>
632     </scons_example>
633
634     <para>
635
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
639     to &rmic:
640
641     </para>
642
643     <scons_output example="RMIC">
644       <scons_output_command>scons -Q</scons_output_command>
645     </scons_output>
646
647     <para>
648
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>.
654
655     </para>
656
657   </section>