1 # Building HAT
  2 [Back to Index ../](../index.md)
  3 
  4 We use `maven` and `cmake` to build HAT.
  5 
  6 Maven controls the build but delegates to cmake for native artifacts (such as ffi-backends), we also use cmake to provide jextract
  7 with location information needed to reference various include/lib paths. (See extractions/pom.xml)
  8 
  9 Use `sudo apt` on Linux or `brew install`.
 10 
 11 ```bash
 12 sudo apt install cmake maven
 13 ```
 14 
 15 ```bash
 16 brew install cmake
 17 brew install maven
 18 ```
 19 
 20 ## Setting environment variables JAVA_HOME and PATH
 21 To build HAT we need to ensure that `JAVA_HOME` points to our babylon jdk (the one we built [here](babylon.md))
 22 
 23 We also need to ensure that `${JAVA_HOME}/bin` is in our PATH (before any other JAVA location).
 24 
 25 We also need jextract for some maven targets.
 26 
 27 We can download and install jextract from [here](https://jdk.java.net/jextract/)
 28 
 29 The `env.bash` shell script can be sourced (dot included) in your shell to set JAVA_HOME and PATH
 30 ```bash
 31 cd hat
 32 . ./env.bash
 33 ```
 34 This should detect the arch type (AARCH64 or X86_46) and select the correct relative parent dir and inject that dir in your PATH if you are working with
 35 HAT in the original subdir of the babylon project.
 36 
 37 It will also check if jextract is in your PATH.  If it is not, you will need to add it (if you decide to use any of the jextract artifacts).
 38 ```bash
 39 cd hat
 40 . ./env.bash
 41 export PATH=${PATH}:/path/to/my/jextract/bin
 42 echo ${JAVA_HOME}
 43 /Users/ME/github/babylon/hat/../build/macosx-aarch64-server-release/jdk
 44 echo ${PATH}
 45 /Users/ME/github/babylon/hat/../build/macosx-aarch64-server-release/jdk/bin:/usr/local/bin:......
 46 ```
 47 ## Building
 48 Now we should be able to use maven to build, if successful maven will place all jars and libs in a newly created `build` dir in your top level hat dir.
 49 ```bash
 50 cd hat
 51 . ./env.bash
 52 mvn clean package
 53 ls build
 54 hat-core-1.0.jar                    hat-example-heal-1.0.jar
 55 hat-backend-ffi-cuda-1.0.jar        hat-example-mandel-1.0.jar
 56 hat-backend-ffi-mock-1.0.jar        hat-example-squares-1.0.jar
 57 hat-backend-ffi-opencl-1.0.jar      hat-example-view-1.0.jar
 58 hat-example-violajones-1.0.jar      hat-example-experiments-1.0.jar
 59 libopencl_backend.dylib
 60 ```
 61 
 62 ## Running an example
 63 To run we use some common java `opt` files.
 64 
 65 When executing with java we canplace common java params in files (say opts) then use `java @opts` to avoid typing all the opts each time.
 66 
 67 To declutter the hat dir, we prefix some useful `opt` files with `.`
 68 
 69 For example in the .ffi-opencl-example opt file we have
 70 ```bash
 71 cat .ffi-opencl-example
 72 --enable-preview --add-modules=jdk.incubator.code --enable-native-access=ALL-UNNAMED -Djava.library.path=build --class-path build/hat-ffi-opencl-examples-1.0.jar
 73 ```
 74 
 75 So you can run an example (say nbody)  using the opencl backend using
 76 ```bash
 77 java @.ffi-opencl-example nbody.Main
 78 ```
 79 
 80 Similarly we can run HAT's test suite.
 81 
 82 ```bash
 83 java @.ffi-opencl-test-suite
 84 ....
 85 ```
 86 
 87 To list available `@.` files
 88 ```bash
 89 ls .*
 90 ```
 91 
 92 ----
 93 ### HAT runtime environment variable.
 94 
 95 During ffi-backend development we added some useful flags to pass to native code to allow us to trace calls, inject logging, control options.
 96 
 97 These should be considered just development flags.
 98 
 99 At runtime the ffi-backends all communicate from the java side to the native side via a 32 bit 'config' int.
100 
101 The Java side class [hat.backend.ffi.Config](https://github.com/openjdk/babylon/blob/code-reflection/hat/backends/ffi/shared/src/main/java/hat/backend/ffi/Config.java)
102 
103 Is initialized from an environment variable `HAT` at runtime
104 
105 So for example when we launch
106 ```bash
107 java @hat/run ffi-opencl heal
108 ```
109 
110 We can pass config info to `HAT` via either `-DHAT=xxx` or via the `HAT` ENV variable.
111 
112 So for example to get HAT to dump the text form of the kernel code models.
113 
114 ```
115 HAT=INFO,SHOW_KERNEL_MODEL java @hat/run ffi-opencl heal
116 ```
117 
118 Or to show generated opencl or cuda code
119 ```
120 HAT=INFO,SHOW_CODE java @hat/run ffi-opencl heal
121 ```
122 
123 This is particularly useful for selecting PLATFORM + DEVICE if you have multiple GPU devices.
124 
125 Here we select DEVICE 0 on PLATFORM 0 (actually the default)
126 ```
127 HAT=INFO,PLATFORM:0,DEVICE:0,SHOW_CODE ...
128 ```
129 or for DEVICE 1 on PLATFORM 1
130 ```
131 HAT=INFO,PLATFORM:1,DEVICE:1,SHOW_CODE ...
132 ```
133 
134 Note the platform and device id's are 4 bits. This probably works for development, but we will need a more expressive way of capturing this via the accelerator selection.
135 
136 This just allows us to test without code changes.
137 
138 To keep he java code and the native code in sync.  The `main` method at the end of
139  [hat.backend.ffi.Config](https://github.com/openjdk/babylon/blob/code-reflection/hat/backends/ffi/shared/src/main/java/hat/backend/ffi/Config.java)
140 is actually used to create the C99 header for Cuda and OpenCL ffi-backends.
141 
142 So whenever we change the Java config class we should run the main method to generate the header.   This is not really robust, (but proved way better than trying to remember for all backends) but you need to know, if you add move config bits to the Java side.
143 
144 The Main method uses a variant of the code builders used for C99 style code (CUDA/OpenCL) to generate the config.h header.
145 
146 This is how we keep the ffi based backends in sync
147 
148 Some more useful `config bits`
149 
150 ```
151 HAT=PTX java @hat/run ffi-cuda ....
152 ```
153 Sends PTX generated by our prototype PTX generator to the backend (for CUDA) rather than C99 code.
154 
155 ```
156 HAT=INFO java @hat/run ....
157 ```
158 
159 Will dump all of the `config bits` from the native side.
160 
161 At present this yields
162 ```
163 native minimizeCopies 0
164 native trace 0
165 native profile 0
166 native showCode 0
167 native showKernelModel 0
168 native showComputeModel 0
169 native info 1
170 native traceCopies 0
171 native traceSkippedCopies 0
172 native traceEnqueues 0
173 native traceCalls 0
174 native showWhy 0
175 native showState 0
176 native ptx 0
177 native interpret 0
178 ```
179 Generally the flags all represent single bits (except PLATFORM:n and DEVICE:n) and are set using comma separated uppercase+underscore string forms.
180 
181 
182 So to experiment with `minimizeCopies` and to  `showCode` we set `HAT=MINIMIZE_COPIES,SHOW_CODE`