util: Embed the JNI library (.so) in the jar file for the gem5 ops.
authorGabe Black <gabe.black@gmail.com>
Fri, 23 Oct 2020 03:01:06 +0000 (20:01 -0700)
committerGabe Black <gabe.black@gmail.com>
Mon, 21 Dec 2020 23:47:36 +0000 (23:47 +0000)
This makes it easier to manage the java wrapper since there's only one
file. This change also splits up the command builder which builds the
java jar since we need to run one step which produces the .h, then a
second step to build the library, and then finally the step that
produces the jar. The first step is left as a command builder since the
scons Java builder still doesn't know about the -h option, but the
second step now uses the Jar builder.

Change-Id: I76e2e5e86bb3153f2ba69a75ad94cd4e065cd33d
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/28183
Reviewed-by: Gabe Black <gabe.black@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
util/m5/SConstruct
util/m5/src/SConscript
util/m5/src/java/gem5/Ops.java

index 242bbe7c3f98cc1905cc53a704e454e32e9a36cd..6552bfb9fa62b71c990fcd1b28901224c3eaad18 100644 (file)
@@ -79,6 +79,7 @@ if not GetOption('verbose'):
     main['ASPPCOMSTR'] = ComStr('ASPP')
     main['ARCOMSTR'] = ComStr('AR')
     main['RANLIBCOMSTR'] = ComStr('RANLIB')
+    main['JARCOMSTR'] = ComStr('JAR')
 
     def MakeAction(action, string, *args, **kwargs):
         def func(target, source, env, executor):
index b3e057c7f8dc4bb9294066ebea06e9fbda5c970d..1105b60379ba8de010b9c3409427c11d19e62c65 100644 (file)
@@ -105,16 +105,24 @@ if env['HAVE_JAVA']:
     # that the javah tool exists. Java has dropped that tool in favor of a -h
     # option on javac which the Java builder doesn't know how to use. To get
     # around this, we set up our own builder which does the "right thing" here.
-    java_env.Command([ Dir('java').File('gem5_Ops.h'),
-                       Dir('out').Dir('java').File('gem5Ops.jar') ],
-                     srcs,
-                     MakeAction([
-                         '${JAVAC} ${JAVACFLAGS} -d ${OUT} '
-                         '${SOURCES} -h ${JAVA_DIR}',
-                         '${JAR} cvf ${TARGETS[1]} ${CLS_DIR}/*.class' ],
-                        'JAVA'),
-                     CLS_DIR=Dir('out').Dir('java').Dir('gem5'),
-                     OUT=Dir('out').Dir('java'), JAVA_DIR=Dir('java'))
+    jni_header = Dir('java').File('gem5_Ops.h')
+
+    java_files = []
+    class_files = []
+    def check_for_java(arg, dirname, fnames):
+        for filename in fnames:
+            base, extension = os.path.splitext(filename)
+            if extension == '.java':
+                java_files.append(dirname.File(filename))
+                class_files.append(dirname.File(base + '.class'))
+
+    Dir('java').walk(check_for_java, None)
+
+    java_env.Command([ jni_header ] + class_files, java_files,
+                     MakeAction('${JAVAC} ${JAVACFLAGS} -d ${JAVA_DIR} '
+                                '${SOURCES} -h ${JAVA_DIR}',
+                                'JAVA'), JAVA_DIR=Dir('java'))
+
     # Set include paths to the C headers from the JDK which scons found for us.
     java_env.Append(CPPPATH='${JAVAINCLUDES}')
     for ct in all_call_types:
@@ -122,9 +130,11 @@ if env['HAVE_JAVA']:
             java_env.Append(CXXFLAGS=[ '-DCALL_TYPE_DEFAULT=%s' % ct.name ])
         java_env.Append(CXXFLAGS=[ '-DCALL_TYPE_%s_ENABLED=%s' %
                                    (ct.name, '1' if ct.enabled else '0') ])
-    java_env.SharedLibrary('out/java/gem5Ops',
-                           [ jni ] + m5op_shared + m5_mmap_shared)
+    jni_lib = java_env.SharedLibrary(
+            'java/gem5Ops', [ jni ] + m5op_shared + m5_mmap_shared)
 
+    java_env.Jar(Dir('out').File('gem5Ops.jar'),
+                 jni_lib + class_files, JARCHDIR=Dir('java'))
 
 if env['HAVE_LUA51']:
     #
index 44afad9765d96e0f634a1afd17b80e84dfd3b8ad..f6ab178dbe95489223f763253d3a886a7ca451da 100644 (file)
@@ -37,6 +37,7 @@
 
 package gem5;
 
+import java.io.*;
 import java.util.*;
 
 /**
@@ -53,7 +54,21 @@ public class Ops {
     public static final Map<String, Ops> callTypes;
 
     static {
-        System.loadLibrary("gem5Ops");
+        try {
+            File temp_lib = File.createTempFile("gem5Ops", ".so");
+            temp_lib.deleteOnExit();
+
+            InputStream in = Ops.class.getResourceAsStream("/libgem5Ops.so");
+            byte[] buffer = new byte[in.available()];
+            in.read(buffer);
+            OutputStream out = new FileOutputStream(temp_lib);
+            out.write(buffer);
+
+            System.load(temp_lib.getAbsolutePath());
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage());
+        }
+
         setupCallTypes();
         callTypes = Collections.unmodifiableMap(_callTypes);
     }