1 /* vim: set ft=java:
  2  *
  3  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.  Oracle designates this
  9  * particular file as subject to the "Classpath" exception as provided
 10  * by Oracle in the LICENSE file that accompanied this code.
 11  *
 12  * This code is distributed in the hope that it will be useful, but WITHOUT
 13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 15  * version 2 for more details (a copy is included in the LICENSE file that
 16  * accompanied this code).
 17  *
 18  * You should have received a copy of the GNU General Public License version
 19  * 2 along with this work; if not, write to the Free Software Foundation,
 20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 21  *
 22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 23  * or visit www.oracle.com if you need additional information or have any
 24  * questions.
 25  */
 26 
 27 import static bldr.Bldr.*;
 28 import static java.lang.System.*;
 29 
 30 void main(String[] args) {
 31 
 32     /*
 33      *  ./
 34      *    +--build/                     All jars, native libs and executables
 35      *    |    +--cmake-build-debug/    All intermediate cmake artifacts
 36      *    |
 37      *    +--stage/
 38      *    |    +--repo/                 All downloaded maven assets
 39      *    |    |
 40      *    |    +--jextract/             All jextracted files
 41      *    |    |    +--opencl
 42      *    |    |    +--opengl
 43      *    |    |    +--cuda
 44      *    |
 45      *    +--hat-core                        * Note maven style layout
 46      *    |    +--src/main/java
 47      *    |    |    +--hat/
 48      *    |    |
 49      *    |    +--src/main/test
 50      *    |         +--hat/
 51      *    |
 52      *    +--backends
 53      *    |    +--java
 54      *    |    |    +--mt                    (*)
 55      *    |    |    +--seq                   (*)
 56      *    |    +--jextracted
 57      *    |    |    +--opencl                (*)
 58      *    |    +--ffi
 59      *    |    |    +--opencl                (*)
 60      *    |    |    +--ptx                   (*)
 61      *    |    |    +--mock                  (*)
 62      *    |    |    +--spirv                 (*)
 63      *    |    |    +--cuda                  (*)
 64      *    |    |    +--hip                   (*)
 65      *    |
 66      *    +--examples
 67      *    |    +--mandel                (*)
 68      *    |    +--squares               (*)
 69      *    |    +--heal                  (*)
 70      *    |    +--life                  (*)
 71      *    |    +--violajones            (*)
 72      *
 73      */
 74 
 75     var dir = DirEntry.current();
 76     var hatCoreDir = dir.existingDir("hat-core");
 77     var backends = dir.existingDir("backends");
 78     var examples = dir.existingDir("examples");
 79     var wrapsDir = dir.existingDir("wrap");
 80     var stageDir = dir.buildDir("stage").create();
 81     var buildDir = BuildDir.of(dir.path("build")).create();
 82     var cmakeBuildDir = buildDir.cMakeBuildDir("cmake-build-debug");
 83 
 84     var openclCapability = Capabilities.OpenCL.of();
 85     var openglCapability = Capabilities.OpenGL.of();
 86     var cudaCapability = Capabilities.CUDA.of();
 87     var hipCapability = Capabilities.HIP.of();
 88     var jextractCapability = Capabilities.JExtract.of();// or Capability.JExtract.of(Path.of("/my/jextract-22/bin/jextract"));
 89     var cmakeCapability = Capabilities.CMake.of();
 90 
 91     Capabilities capabilities = Capabilities.of(openclCapability, openglCapability, cudaCapability, hipCapability, jextractCapability, cmakeCapability);
 92 
 93     if (cmakeCapability.available()) {
 94         cmakeCapability.probe(buildDir, capabilities);
 95     }
 96 
 97     capabilities.capabilities().forEach(fw -> out.print( "["+fw.name + (fw.available() ? "\u2714" : "\u2715") +"]"));
 98     out.println();
 99 
100     var verbose = false;
101     var wrapJar= buildDir.jarFile("hat-wrap-1.0.jar");
102     var clWrapJar= buildDir.jarFile("hat-clwrap-1.0.jar");
103     var glWrapJar= buildDir.jarFile("hat-glwrap-1.0.jar");
104     var cuWrapJar= buildDir.jarFile("hat-cuwrap-1.0.jar");
105     var hatJar = buildDir.jarFile("hat-core-1.0.jar");
106 
107  var hatJavacOpts = javacBuilder($ -> $
108             .enable_preview()
109             .add_modules("jdk.incubator.code")
110             .add_exports_to_all_unnamed("java.base", "jdk.internal", "jdk.internal.vm.annotation")
111             .current_source()
112     );
113 
114     var hatJarOptions = jarBuilder($ -> $
115             .verbose(verbose)
116     );
117     jar(hatJarOptions, jar -> jar
118             .jarFile(hatJar)
119             .maven_style_root(hatCoreDir)
120             .javac(hatJavacOpts, javac -> {
121             })
122     );
123 
124     jar(jar -> jar
125          .jarFile(wrapJar)
126          .maven_style_root(wrapsDir.dir("wrap"))
127          .javac(javac -> javac.current_source())
128     );
129 
130     if (jextractCapability.available()) {
131         if (openclCapability.available()) {
132             if (!openclCapability.jarFile(buildDir).exists()) {
133                 if (!openclCapability.stage(stageDir).exists()) {
134                     jextract(jextractCapability.executable, $ -> $ .verbose(verbose) .capability(openclCapability,stageDir));
135                 }else{
136                     out.println("Using previously extracted  "+openclCapability.stage(buildDir).fileName());
137                 }
138                 jar(jar -> jar
139                     .jarFile(openclCapability.jarFile(buildDir))
140                     .javac(javac -> javac.current_source().source_path(SourceDir.of(openclCapability.stage(stageDir).path())))
141 
142                 );
143             }else{
144                 out.println("Using existing extracted "+openclCapability.jarFile(buildDir).fileName());
145             }
146             jar(jar -> jar
147                .jarFile(clWrapJar)
148                .maven_style_root(wrapsDir.dir("clwrap"))
149                .javac(javac -> javac.current_source().class_path(wrapJar,hatJar, openclCapability.jarFile(buildDir)))
150             );
151         } else {
152             out.println("This platform does not have OpenCL");
153         }
154 
155         if (openglCapability.available()) {
156             if (!openglCapability.jarFile(buildDir).exists()) {
157                 if (!openglCapability.stage(stageDir).exists()) {
158                     jextract(jextractCapability, $ -> $ .verbose(verbose) .capability(openglCapability, stageDir));
159                 }else{
160                     out.println("Using previously extracted  "+openglCapability.stage(buildDir).fileName());
161                 }
162                 jar(jar -> jar
163                         .jarFile(openglCapability.jarFile(buildDir))
164                         .javac(javac -> javac.current_source().source_path(SourceDir.of(openglCapability.stage(stageDir).path())))
165                 );
166             }else{
167                 out.println("Using existing extracted "+openglCapability.jarFile(buildDir).fileName());
168             }
169             jar(jar -> jar
170                .jarFile(glWrapJar)
171                .maven_style_root(wrapsDir.dir("glwrap"))
172                .javac(javac -> javac
173                   .current_source()
174                   .exclude(javaSrc -> javaSrc.matches("^.*/wrap/glwrap/GLCallbackEventHandler\\.java$"))
175                   //.exclude(javaSrc -> javaSrc.matches("^.*/wrap/glwrap/GLFuncEventHandler\\.java$"))
176                   .class_path(wrapJar, openglCapability.jarFile(buildDir))
177                )
178             );
179         } else {
180             out.println("This platform does not have OpenGL");
181         }
182 
183 
184         if (cudaCapability.available()) {
185 
186         } else {
187             out.println("This platform does not have CUDA");
188         }
189     }
190 
191     var backendJars = new ArrayList<bldr.Bldr.JarFile>();
192    
193 
194     // Here we create all ffi-backend jars.
195     var ffiBackends = backends.existingDir("ffi");
196     ffiBackends.subDirs()
197             .filter(backend -> backend.failsToMatch("^.*(spirv|hip|shared|target|.idea)$"))
198             .forEach(backend -> {
199                 var ffiBackendJarFile = buildDir.jarFile("hat-backend-ffi-" + backend.fileName() + "-1.0.jar");
200                 backendJars.add(ffiBackendJarFile);
201                 out.println(ffiBackendJarFile.fileName());
202                 jar(hatJarOptions, jar -> jar
203                         .jarFile(ffiBackendJarFile)
204                         .maven_style_root(backend)
205                         .javac(hatJavacOpts, javac -> javac.class_path(hatJar))
206                 );
207             });
208 
209     // Here we create jextracted-backend jars.
210     var jextractedBackends = backends.existingDir("jextracted");
211     var jextractedBackendSharedDir = jextractedBackends.dir("shared");
212     out.println("Shared jextracted "+jextractedBackendSharedDir.path());
213     var jextractedSharedBackendJar=buildDir.jarFile("hat-backend-jextracted-shared-1.0.jar");
214     backendJars.add(jextractedSharedBackendJar);
215     var jextractedBackendSharedResult = jar(hatJarOptions, jar -> jar
216           .jarFile(jextractedSharedBackendJar)
217           .maven_style_root(jextractedBackendSharedDir)
218           .javac(hatJavacOpts, javac -> javac.verbose(verbose)
219               .class_path(hatJar)
220           )
221     ); 
222 
223     if (openclCapability.available()){
224        var jextractedBackendOpenCLDir = jextractedBackends.dir("opencl");
225        out.println("OpenCL jextracted "+jextractedBackendOpenCLDir.path());
226        var jextractedOpenCLBackendJar = buildDir.jarFile("hat-backend-jextracted-opencl-1.0.jar");
227        backendJars.add(jextractedOpenCLBackendJar);
228        jar(hatJarOptions, jar -> jar
229           .jarFile(jextractedOpenCLBackendJar)
230           .maven_style_root(jextractedBackendOpenCLDir)
231           .javac(hatJavacOpts, javac -> javac.verbose(verbose)
232               .class_path(hatJar, openclCapability.jarFile(buildDir), jextractedBackendSharedResult )
233           )
234        );
235    }
236 
237 
238     // Here we create all java backend jars.
239     backends.existingDir("java")
240             .subDirs()
241             .filter(backend -> backend.failsToMatch("^.*(target|.idea)$"))
242             .forEach(backend -> {
243                 var backendJavaJar = buildDir.jarFile("hat-backend-java-" + backend.fileName() + "-1.0.jar");
244                 out.println(backendJavaJar.fileName());
245                 backendJars.add(backendJavaJar);
246                 jar(hatJarOptions, jar -> jar
247                         .jarFile(backendJavaJar)
248                         .dir_list(backend.dir("src/main/resources"))
249                 );
250             });
251 
252     backendJars.forEach(j->out.println(" backend "+j.path()));
253 
254 
255     // here we create the example jars
256     examples.subDirs()
257             .filter(example -> example.failsToMatch("^.*(experiments|nbody|life|target|.idea)$"))
258             .forEach(example -> {
259                 var exampleJarFile = buildDir.jarFile("hat-example-" + example.fileName() + "-1.0.jar");
260                 out.println(exampleJarFile.fileName());
261                 jar(hatJarOptions, jar -> jar
262                         .jarFile(exampleJarFile)
263                         .maven_style_root(example)
264                         .javac(hatJavacOpts, javac -> javac.class_path(hatJar))
265                         .manifest(manifest -> manifest .main_class(example.fileName() + ".Main"))
266                 );
267             });
268 
269     
270     if (jextractCapability.available() && openclCapability.available()) {
271         var example = examples.dir("life");
272         var exampleJarFile = buildDir.jarFile("hat-example-" + example.fileName() + "-1.0.jar");
273         out.println(exampleJarFile.fileName());
274         jar(hatJarOptions, jar -> jar
275                 .jarFile(exampleJarFile)
276                 .maven_style_root(example)
277                 .javac(hatJavacOpts, javac -> javac
278                    .class_path(hatJar, wrapJar, clWrapJar, openclCapability.jarFile(buildDir), buildDir.jarFile("hat-backend-ffi-opencl-1.0.jar"))
279                 )
280         );
281     }
282 
283 
284     if (jextractCapability.available() && openclCapability.available() && openglCapability.available()) {
285         var example = examples.dir("nbody");
286         var exampleJarFile = buildDir.jarFile("hat-example-" + example.fileName() + "-1.0.jar");
287         out.println(exampleJarFile.fileName());
288         jar(hatJarOptions, jar -> jar
289                 .jarFile(exampleJarFile)
290                 .maven_style_root(example)
291                 .javac(hatJavacOpts, javac -> javac
292                     .class_path( hatJar, wrapJar, clWrapJar, glWrapJar, openclCapability.jarFile(buildDir), openglCapability.jarFile(buildDir),buildDir.jarFile("hat-backend-ffi-opencl-1.0.jar"))
293                 )
294         );
295     }
296 
297     if (cmakeCapability.available()) {
298         if (!cmakeBuildDir.exists()) {
299             cmake($ -> $
300                     .verbose(verbose)
301                     .source_dir(ffiBackends)
302                     .build_dir(cmakeBuildDir)
303                     .copy_to(buildDir)
304             );
305         }
306         cmake($ -> $
307                 .build(cmakeBuildDir)
308         );
309     } else {
310         out.println("No cmake available so we did not build ffi backend shared libs");
311     }
312 
313 }
314