1 # Building HAT
  2 
  3 ----
  4 
  5 * [Contents](hat-00.md)
  6 * House Keeping
  7     * [Project Layout](hat-01-01-project-layout.md)
  8     * [Building Babylon](hat-01-02-building-babylon.md)
  9     * [Building HAT](hat-01-03-building-hat.md)
 10 * Programming Model
 11     * [Programming Model](hat-03-programming-model.md)
 12 * Interface Mapping
 13     * [Interface Mapping Overview](hat-04-01-interface-mapping.md)
 14     * [Cascade Interface Mapping](hat-04-02-cascade-interface-mapping.md)
 15 * Implementation Detail
 16     * [Walkthrough Of Accelerator.compute()](hat-accelerator-compute.md)
 17 
 18 ---
 19 
 20 # Building HAT with Bldr
 21 
 22 We initially used maven and cmake to build hat.  If you feel more comfortable
 23 with maven consider [building with maven and cmake](hat-01-03-building-hat-with-maven.md)
 24 but it is possible that maven support will be removed if the `Bldr` approach takes off.
 25 
 26 We might even have `Bldr` create the maven artifacts....
 27 
 28 ## Setting environment variables JAVA_HOME and PATH
 29 
 30 To build HAT we need to ensure that `JAVA_HOME` is set
 31 to point to our babylon jdk (the one we built [here](hat-01-02-building-babylon.md))
 32 
 33 It will simplify our tasks going forward if we
 34 add `${JAVA_HOME}/bin` to our PATH (before any other JAVA installs).
 35 
 36 The top level `env.bash` shell script can be sourced (dot included)
 37 into your shell to both set `JAVA_HOME` and update your `PATH`
 38 
 39 It should detect the arch type (AARCH64 or X86_46) and
 40 select the correct relative parent dir and inject that dir in your PATH.
 41 
 42 ```bash
 43 cd hat
 44 . ./env.bash
 45 echo ${JAVA_HOME}
 46 /Users/ME/github/babylon/hat/../build/macosx-aarch64-server-release/jdk
 47 echo ${PATH}
 48 /Users/ME/github/babylon/hat/../build/macosx-aarch64-server-release/jdk/bin:/usr/local/bin:......
 49 ```
 50 
 51 # Introducing Bldr
 52 `Bldr` is a minimal java build system which has all the capabilities needed so far
 53 to build existing HAT as well as it's examples and backends. It is just a set of
 54 static methods and helper classes wrapping javac/jar tooling.
 55 
 56 `Bldr` itself is a java class in
 57 ```
 58 bldr
 59   └── src
 60       └── main
 61           └── java
 62               └── bldr
 63                   └── Bldr.java
 64 ```
 65 
 66 We do need to compile this one class using javac one time, then we can use this in `bld` scripts to actually bld.
 67 
 68 Assuming we have our babylon JDK build in our path (via `. env.bash`) we should do this every time we 'pull' HAT.
 69 
 70 ```shell
 71 mkdir bldr/classes
 72 javac --enable-preview -source 24 -d bldr/classes bldr/src/main/java/bldr/Bldr.java
 73 ```
 74 
 75 Now the `bldr/classes` dir contains all we need to create build scripts
 76 
 77 In HAT's root dir is a `#!` (Hash Bang) java launcher style script called `bld`
 78 which uses tools exposed by the precompiled `Bldr` to compile, create jars, run jextract, download dependencies, tar/untar etc.
 79 
 80 As git does not allow us to check in scripts with execute permission, we need to `chmod +x` this `bld` file.
 81 
 82 ```bash
 83 chmod +x bld
 84 ```
 85 
 86 A simple example of `bld` script which just compiles core HAT source to `build/hat-1.0.jar` is shown.
 87 
 88 ```java
 89 #!/usr/bin/env java --enable-preview --source 24 --class-path bldr/classes
 90 import module java.compiler;
 91 import static bldr.Bldr.*;
 92 void main(String[] args) throws IOException, InterruptedException {
 93     var hatDir = Path.of(System.getProperty("user.dir"));
 94     var target = path(hatDir, "build");// mkdir(rmdir(path(hatDir, "build")));
 95 
 96     var hatJarResult = javacjar($ -> $
 97             .opts(  "--source", "24",
 98                     "--enable-preview",
 99                     "--add-exports=java.base/jdk.internal=ALL-UNNAMED",
100                     "--add-exports=java.base/jdk.internal.vm.annotation=ALL-UNNAMED")
101             .jar(path(target, "hat-1.0.jar"))
102             .source_path(path(hatDir, "hat/src/main/java"))
103     );
104 }
105 ```
106 Note that the first line has the `#!` magic to allow this java code to be executed as if it
107 were a script.  Whilst `bld` is indeed real java code,  we do not need to compile it. Instead we just execute using
108 
109 ```bash
110 ./bld
111 ```
112 
113 The real `bld` is more complicated, but not much more. It will will build hat-1.0.jar, along with all the backend jars hat-backend-?-1.0.jar,
114 all the example jars hat-example-?-1.0.jar and will try to build all native artifacts (.so/.dylib) it can.
115 So if cmake finds OpenCL libs/headers, you will see libopencl_backend (.so or .dylib)
116 
117 On a CUDA machine you will see libcuda_backend(.so or .dylib)
118 
119 `bld` will also sanity check .java/.cpp/.h files to make sure we don't have any tabs, lines that with whitespace
120 or files without appropriate licence headers
121 
122 ```bash
123 cd hat
124 . ./env.bash
125 ./bld
126 ls build
127 hat-1.0.jar                     hat-example-heal-1.0.jar        libptx_backend.dylib
128 hat-backend-cuda-1.0.jar        hat-example-mandel-1.0.jar      libspirv_backend.dylib
129 hat-backend-mock-1.0.jar        hat-example-squares-1.0.jar     mock_info
130 hat-backend-opencl-1.0.jar      hat-example-view-1.0.jar        opencl_info
131 hat-backend-ptx-1.0.jar         hat-example-violajones-1.0.jar  ptx_info
132 hat-backend-spirv-1.0.jar       libmock_backend.dylib           spirv_info
133 hat-example-experiments-1.0.jar libopencl_backend.dylib
134 ```
135 
136 ## Running an example
137 
138 To run a HAT example we can run from the artifacts in `build` dir
139 
140 ```bash
141 ${JAVA_HOME}/bin/java \
142    --enable-preview --enable-native-access=ALL-UNNAMED \
143    --class-path build/hat-1.0.jar:build/hat-example-mandel-1.0.jar:build/hat-backend-opencl-1.0.jar \
144    --add-exports=java.base/jdk.internal=ALL-UNNAMED \
145    -Djava.library.path=build\
146    mandel.Main
147 ```
148 
149 The provided `hatrun.bash` script simplifies this somewhat, we just need to pass the backend
150 name `opencl` and the package name `mandel`
151 (all examples are assumed to be in `packagename/Main.java`
152 
153 ```bash
154 bash hatrun.bash opencl mandel
155 ```