diff a/hat/bld b/hat/bld
--- /dev/null
+++ b/hat/bld
@@ -0,0 +1,274 @@
+/* vim: set ft=java:
+ *
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import static bldr.Bldr.*;
+
+void main(String[] args) {
+
+    /*
+     *  ./
+     *    +--build/                     All jars, native libs and executables
+     *    |    +--cmake-build-debug/    All intermediate cmake artifacts
+     *    |
+     *    +--stage/
+     *    |    +--repo/                 All downloaded maven assets
+     *    |    |
+     *    |    +--jextract/             All jextracted files
+     *    |    |    +--opencl
+     *    |    |    +--opengl
+     *    |    |    +--cuda
+     *    |
+     *    +--hat                        * Note maven style layout
+     *    |    +--src/main/java
+     *    |    |    +--hat/
+     *    |    |
+     *    |    +--src/main/test
+     *    |         +--hat/
+     *    |
+     *    +--backends
+     *    |    +--java
+     *    |    |    +--mt                    (*)
+     *    |    |    +--seq                   (*)
+     *    |    +--jextracted
+     *    |    |    +--opencl                (*)
+     *    |    +--ffi
+     *    |    |    +--opencl                (*)
+     *    |    |    +--ptx                   (*)
+     *    |    |    +--mock                  (*)
+     *    |    |    +--spirv                 (*)
+     *    |    |    +--cuda                  (*)
+     *    |    |    +--hip                   (*)
+     *    |
+     *    +--examples
+     *    |    +--mandel                (*)
+     *    |    +--squares               (*)
+     *    |    +--heal                  (*)
+     *    |    +--life                  (*)
+     *    |    +--violajones            (*)
+     *
+     */
+
+    var hatDir = DirEntry.current();
+  var hatCoreDir = hatDir.existingDir("hat");
+  var backends = hatDir.existingDir("backends");
+  var examples = hatDir.existingDir("examples");
+  var stageDir = hatDir.buildDir("stage").create();
+  var jextractDir = stageDir.buildDir("jextract").create();
+  var buildDir = BuildDir.of(hatDir.path("build")).create();
+  var cmakeBuildDir = buildDir.cMakeBuildDir("cmake-build-debug");
+
+  var extractedOpenCLJar = buildDir.jarFile("jextracted-opencl.jar");
+  var extractedOpenGLJar = buildDir.jarFile("jextracted-opengl.jar");
+
+  var opencl = Capabilities.OpenCL.of();
+  var opengl = Capabilities.OpenGL.of();
+  var cuda = Capabilities.CUDA.of();
+  var hip = Capabilities.HIP.of();
+  var jextract = Capabilities.JExtract.of();
+  var cmake = Capabilities.CMake.of();
+
+  Capabilities capabilities = Capabilities.of(opencl, opengl, cuda, hip, jextract, cmake);
+
+  if (cmake.available()) {
+    cmake.probe(buildDir, capabilities);
+  }
+  capabilities.capabilities().forEach(fw -> println((fw.available() ? "we have " : "no ") + fw.name));
+  var verbose = false;
+
+
+  if (jextract.available()) {
+    if (opencl.available()) {
+      if (!extractedOpenCLJar.exists()) {
+        var openclSource = jextractDir.sourceDir("opencl");
+        if (!openclSource.exists()) {
+          jextract(jextract.executable, $ -> {
+            $
+              .verbose(verbose)
+              .output(jextractDir)
+              .target_package(openclSource.fileName());
+            switch (os) {
+              case OS.Mac mac -> {
+                $
+                  .compile_flag("-F" + opencl.appLibFrameworks() + "/System/library/Frameworks")
+                  .library(mac.frameworkLibrary("OpenCL"))
+                  //.library(Path.of(opencl.lib()))
+                  .header(Path.of(opencl.includeDir()).resolve("Headers/opencl.h"));
+              }
+              case OS.Linux linux -> {
+              }
+              default -> throw new RuntimeException("Unsupported OS: " + os);
+            }
+          });
+        }
+        jar(jar -> {
+              jar
+                .jar(extractedOpenCLJar)
+                .javac(javac -> javac.source(24).source_path(openclSource));
+            }
+        );
+      }
+    } else {
+      println("This platform does not have OpenCL");
+    }
+
+    if (opengl.available()) {
+      if (!extractedOpenGLJar.exists()) {
+        var openglSource = jextractDir.sourceDir("opengl");
+        if (!openglSource.exists()) {
+          jextract(jextract.executable, $ -> { $
+              .verbose(verbose)
+              .output(jextractDir)
+              .target_package(openglSource.fileName());
+            switch (os) {
+              case OS.Mac mac -> { $
+                  .compile_flag("-F" + opengl.appLibFrameworks() + "/System/library/Frameworks")
+                  //.library(opengl.lib("GLUT"),opengl.lib("OpenGL"))
+                  .library(mac.frameworkLibrary("GLUT"), mac.frameworkLibrary("OpenGL"))
+                  .header(mac.frameworkHeader("GLUT", "glut.h"));
+              }
+              case OS.Linux linux -> {
+              }
+              default -> throw new RuntimeException("Unsupported OS: " + os);
+            }
+          });
+        }
+        jar(jar -> jar
+          .jar(extractedOpenGLJar)
+          .javac(javac -> javac.source(24).source_path(openglSource))
+        );
+      }
+    } else {
+      println("This platform does not have OpenGL");
+    }
+
+
+    if (cuda.available()) {
+
+    } else {
+      println("This platform does not have CUDA");
+    }
+  }
+  var hatJavacOpts = javacBuilder(javacBuilder -> {javacBuilder
+    .enable_preview()
+    .add_modules("jdk.incubator.code")
+    .add_exports(
+       "java.base",
+       List.of(
+          "jdk.internal",
+          "jdk.internal.vm.annotation"
+       ),
+       "ALL-UNNAMED"
+    )
+    .source(24);
+  });
+
+  var hatJarOptions = jarBuilder(jarBuilder -> jarBuilder
+    .verbose(verbose)
+  );
+  var hatJarFile = buildDir.jarFile("hat-1.0.jar");
+  jar(jar -> jar
+    .copy(hatJarOptions)
+    .jar(hatJarFile)
+    .maven_style_root(hatCoreDir)
+    .javac(javac -> javac.copy(hatJavacOpts))
+  );
+
+
+  // Here we create all backend jars.
+  var ffiBackends = backends.existingDir("ffi");
+  ffiBackends
+    .subDirs(backend -> !backend.matches("^.*(spirv|hip|shared|target|.idea)$"))
+    .forEach(backend -> {
+      var jarFile = buildDir.jarFile("hat-backend-ffi-" + backend.fileName() + "-1.0.jar");
+      println(jarFile.fileName());
+      jar(jar -> jar.copy(hatJarOptions)
+        .jar(jarFile)
+        .maven_style_root(backend)
+        .javac(javac -> javac.copy(hatJavacOpts).class_path(hatJarFile))
+      );
+    });
+
+  // Here we create all java backend jars.
+  var javaBackends = backends.existingDir("java");
+  javaBackends
+    .subDirs(backend -> !backend.matches("^.*(target|.idea)$"))
+    .forEach(backend -> {
+      var jarFile = buildDir.jarFile("hat-backend-java-" + backend.fileName() + "-1.0.jar");
+      println(jarFile.fileName());
+      jar(jar -> jar
+            .copy(hatJarOptions)
+            .jar(jarFile)
+            .dir_list(backend.dir("src/main/resources"))
+          //.maven_style_root(backend)
+      );
+    });
+
+
+  // here we create the example jars
+  examples
+    .subDirs(example -> !example.matches("^.*(experiments|nbody|target|.idea)$"))
+    .forEach(example -> {
+      var jarFile = buildDir.jarFile("hat-example-" + example.fileName() + "-1.0.jar");
+      println(jarFile.fileName());
+      jar(jar -> jar.copy(hatJarOptions)
+        .jar(jarFile)
+        .maven_style_root(example)
+        .javac(javac -> javac.copy(hatJavacOpts).class_path(hatJarFile))
+        .manifest(manifest -> manifest
+          .main_class(example.fileName() + ".Main")
+        )
+      );
+    });
+
+  if (jextract.available() && opencl.available() && opengl.available()) {
+    var example = examples.dir("nbody");
+    var jarFile = buildDir.jarFile("hat-example-" + example.fileName() + "-1.0.jar");
+    println(jarFile.fileName());
+    jar(jar -> jar.copy(hatJarOptions)
+      .jar(jarFile)
+      .maven_style_root(example)
+      .javac(javac -> javac.copy(hatJavacOpts).class_path(hatJarFile, extractedOpenCLJar, extractedOpenGLJar))
+    );
+  }
+
+  if (cmake.available()) {
+    if (!cmakeBuildDir.exists()) {
+      cmake($ -> $
+        .source_dir(ffiBackends)
+        .build_dir(cmakeBuildDir)
+        .copy_to(buildDir)
+      );
+    }
+    cmake($ -> $
+      .build(cmakeBuildDir)
+    );
+  } else {
+    println("No cmake available so we did not build ffi backend shared libs");
+  }
+
+
+}
+ 
