24.4. Building C Header and Stub Files: the `JavaH` Builder
Prev | Chapter 24. Java Builds | Next

## 24.4. Building C Header and Stub Files: the `JavaH` Builder

You can generate C header and source files for implementing native methods, by using the `JavaH` Builder. There are several ways of using the `JavaH` Builder. One typical invocation might look like:

    classes = Java(target='classes', source='src/pkg/sub')
    JavaH(target='native', source=classes)

The source is a list of class files generated by the call to the `Java` Builder, and the target is the output directory in which we want the C header files placed. The target gets converted into the `-d` when SCons runs javah:

    % scons -Q
    javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java
    javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3

In this case, the call to javah will generate the header files `native/pkg_sub_Example1.h`, `native/pkg_sub_Example2.h` and `native/pkg_sub_Example3.h`. Notice that SCons remembered that the class files were generated with a target directory of `classes`, and that it then specified that target directory as the `-classpath` option to the call to javah.

Although it's more convenient to use the list of class files returned by the `Java` Builder as the source of a call to the `JavaH` Builder, you can specify the list of class files by hand, if you prefer. If you do, you need to set the `$JAVACLASSDIR` construction variable when calling `JavaH`:

    Java(target='classes', source='src/pkg/sub')
    class_file_list = [
        'classes/pkg/sub/Example1.class',
        'classes/pkg/sub/Example2.class',
        'classes/pkg/sub/Example3.class',
    ]
    JavaH(target='native', source=class_file_list, JAVACLASSDIR='classes')

The `$JAVACLASSDIR` value then gets converted into the `-classpath` when SCons runs javah:

    % scons -Q
    javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java
    javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3

Lastly, if you don't want a separate header file generated for each source file, you can specify an explicit File Node as the target of the `JavaH` Builder:

    classes = Java(target='classes', source='src/pkg/sub')
    JavaH(target=File('native.h'), source=classes)

Because SCons assumes by default that the target of the `JavaH` builder is a directory, you need to use the `File` function to make sure that SCons doesn't create a directory named `native.h`. When a file is used, though, SCons correctly converts the file name into the javah `-o` option:

    % scons -Q
    javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java
    javah -o native.h -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3

Note that the javah command was removed from the JDK as of JDK 10, and the approved method (available since JDK 8) is to use javac to generate native headers at the same time as the Java source code is compiled. As such the `JavaH` builder is of limited utility in later Java versions.

Prev | Up | Next
24.3. Building Java Archive (`.jar`) Files: the `Jar` Builder | Home | 24.5. Building RMI Stub and Skeleton Class Files: the `RMIC` Builder