Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Standard.Tableau to native-image #12204

Merged
merged 18 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 40 additions & 10 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3421,7 +3421,6 @@ lazy val `runtime-compiler-dump` =
.enablePlugins(JPMSPlugin)
.settings(
frgaalJavaCompilerSetting,
javaModuleName := "org.enso.runtime.compiler.dump",
Compile / internalModuleDependencies := {
val transitiveDeps =
(`runtime-parser` / Compile / internalModuleDependencies).value
Expand Down Expand Up @@ -3792,6 +3791,9 @@ lazy val `engine-runner` = project
.listFiles("*.jar")
.map(_.getAbsolutePath()) ++
`std-snowflake-polyglot-root`
.listFiles("*.jar")
.map(_.getAbsolutePath()) ++
`std-tableau-polyglot-root`
.listFiles("*.jar")
.map(_.getAbsolutePath())

Expand Down Expand Up @@ -3918,12 +3920,15 @@ lazy val `engine-runner` = project
"org.enso.image",
"org.enso.table",
"org.enso.database",
"org.enso.tableau",
"org.eclipse.jgit",
"com.amazonaws",
"com.google",
"io.grpc",
"io.opencensus",
"net.snowflake.client"
"net.snowflake.client",
"com.sun.jna",
"com.tableau.hyperapi"
)
)
}
Expand Down Expand Up @@ -4693,6 +4698,8 @@ val `std-microsoft-polyglot-root` =
stdLibComponentRoot("Microsoft") / "polyglot" / "java"
val `std-tableau-polyglot-root` =
stdLibComponentRoot("Tableau") / "polyglot" / "java"
val `std-tableau-native-libs` =
stdLibComponentRoot("Tableau") / "polyglot" / "lib"

lazy val `std-base` = project
.in(file("std-bits") / "base")
Expand Down Expand Up @@ -4882,7 +4889,16 @@ lazy val `std-image` = project
},
Compile / packageBin := Def.task {
val result = (Compile / packageBin).value
val _ = extractNativeLibs.value
// Ensure dependencies are first copied.
StdBits
.copyDependencies(
`image-polyglot-root`,
Seq("std-image.jar", "opencv.jar"),
ignoreScalaLibrary = true,
ignoreDependency = Some("org.openpnp" % "opencv" % opencvVersion)
)
.value
extractNativeLibs.value
result
}.value
)
Expand Down Expand Up @@ -5133,11 +5149,10 @@ lazy val `std-tableau` = project
Seq[Attributed[File]]()
}
},
Compile / unmanagedClasspath := Def.task {
val additionalFiles: Seq[Attributed[File]] = fetchZipToUnmanaged.value
val result = (Compile / unmanagedClasspath).value
result ++ additionalFiles
}.value,
Compile / unmanagedClasspath :=
(Compile / unmanagedClasspath)
.dependsOn(fetchZipToUnmanaged)
.value,
Compile / unmanagedJars := (Compile / unmanagedJars)
.dependsOn(fetchZipToUnmanaged)
.value,
Expand All @@ -5147,15 +5162,30 @@ lazy val `std-tableau` = project
"org.netbeans.api" % "org-openide-util-lookup" % netbeansApiVersion % "provided",
"net.java.dev.jna" % "jna-platform" % jnaVersion
),
// Extract native libraries from tableau's jar, and put them under
// Standard/Tableau/polyglot/lib directory.
extractNativeLibs := {
StdBits
.extractNativeLibsFromTableau(
`std-tableau-polyglot-root`,
`std-tableau-native-libs`,
tableauVersion,
jnaVersion
)
.value
},
Compile / packageBin := Def.task {
val result = (Compile / packageBin).value
val _ = StdBits
StdBits
.copyDependencies(
`std-tableau-polyglot-root`,
Seq("std-tableau.jar"),
ignoreScalaLibrary = true
ignoreScalaLibrary = true,
ignoreUnmanagedDependency =
Some(!_.getName.endsWith("tableauhyperapi.jar"))
)
.value
extractNativeLibs.value
result
}.value
)
Expand Down
7 changes: 7 additions & 0 deletions build_tools/build/src/engine/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,12 @@ pub async fn runner_sanity_test(
.run_ok()
.await;

let test_tableau = Command::new(&enso)
.args(["--run", repo_root.test.join("Tableau_Tests").as_str()])
.set_env(ENSO_DATA_DIRECTORY, engine_package)?
.run_ok()
.await;

let test_geo = Command::new(&enso)
.args(["--run", repo_root.test.join("Geo_Tests").as_str()])
.set_env(ENSO_DATA_DIRECTORY, engine_package)?
Expand All @@ -663,6 +669,7 @@ pub async fn runner_sanity_test(
.and(test_aws)
.and(test_microsoft)
.and(test_snowflake)
.and(test_tableau)
.and(test_geo)
.and(test_image);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public static class TopScope {
public static final String REGISTER_MODULE = "register_module";
public static final String UNREGISTER_MODULE = "unregister_module";
public static final String COMPILE = "compile";
public static final String FIND_NATIVE_LIBRARY = "find_native_library";
}

public static class Module {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package org.enso.interpreter.test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import com.oracle.truffle.api.TruffleFile;
import java.io.IOException;
Expand All @@ -12,6 +15,9 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import org.enso.cli.OS;
import org.enso.common.LanguageInfo;
import org.enso.common.MethodNames;
import org.enso.editions.LibraryName;
import org.enso.interpreter.runtime.util.TruffleFileSystem;
import org.enso.pkg.NativeLibraryFinder;
Expand All @@ -27,6 +33,7 @@ public class NativeLibraryFinderTest {

@Rule public final TestRule printContextRule = new PrintSystemInfoRule();
private Package<TruffleFile> stdImgPkg;
private Package<TruffleFile> stdTableauPkg;

@Test
public void standardImageShouldHaveNativeLib() {
Expand All @@ -51,6 +58,67 @@ public void standardImageShouldHaveNativeLib() {
}
}

@Test
public void standardTableauShouldHaveNativeLib() {
try (var ctx = ContextUtils.createDefaultContext()) {
// Evaluate dummy sources to force loading Standard.Tableau
ContextUtils.evalModule(
ctx, """
from Standard.Tableau import all
main = 42
""");
var ensoCtx = ContextUtils.leakContext(ctx);
var stdTableau =
ensoCtx
.getPackageRepository()
.getPackageForLibraryJava(LibraryName.apply("Standard", "Tableau"));
assertThat(stdTableau.isPresent(), is(true));
this.stdTableauPkg = stdTableau.get();
var nativeLibs =
NativeLibraryFinder.listAllNativeLibraries(stdTableau.get(), TruffleFileSystem.INSTANCE);
// Tableau has Tableau's native lib AND jni
assertThat("There should be two native libs for Standard.Tableau", nativeLibs.size(), is(2));
}
}

@Test
public void findTableauNativeLibrary() {
try (var ctx = ContextUtils.createDefaultContext()) {
// Evaluate dummy sources to force loading Standard.Tableau
ContextUtils.evalModule(
ctx,
"""
from Standard.Base import all
from Standard.Tableau import all
main = 42
""");
var nativeLib =
ctx.getBindings(LanguageInfo.ID)
.invokeMember(MethodNames.TopScope.FIND_NATIVE_LIBRARY, "tableauhyperapi");
assertNotNull(nativeLib);
var expectedLibName = OS.isWindows() ? "tableauhyperapi" : "libtableauhyperapi";
assertThat(nativeLib.asString(), containsString(expectedLibName));
}
}

@Test
public void failToFindNativeLibrary() {
try (var ctx = ContextUtils.createDefaultContext()) {
// Evaluate dummy sources to force loading of some packages
ContextUtils.evalModule(
ctx,
"""
from Standard.Base import all
from Standard.Table import all
main = 42
""");
var nativeLib =
ctx.getBindings(LanguageInfo.ID)
.invokeMember(MethodNames.TopScope.FIND_NATIVE_LIBRARY, "iDontExist");
assertTrue(nativeLib.isNull());
}
}

public final class PrintSystemInfoRule implements TestRule {
@Override
public Statement apply(Statement base, Description description) {
Expand All @@ -70,7 +138,10 @@ public void evaluate() {
.append(System.lineSeparator());
var mappedLibName = System.mapLibraryName("opencv_java470");
sb.append(" Mapped library name: ")
.append(mappedLibName)
.append(System.lineSeparator())
.append(" " + System.mapLibraryName("opencv_java470"))
.append(System.lineSeparator())
.append(" " + System.mapLibraryName("tableauhyperapi"))
.append(System.lineSeparator());
if (stdImgPkg != null) {
sb.append(" Contents of Standard.Image native library dir:")
Expand All @@ -81,6 +152,15 @@ public void evaluate() {
contents.forEach(
path -> sb.append(" ").append(path).append(System.lineSeparator()));
}
if (stdTableauPkg != null) {
sb.append(" Contents of Standard.Tableau native library dir:")
.append(System.lineSeparator());
var nativeLibDir = stdTableauPkg.nativeLibraryDir();
var nativeLibPath = Path.of(nativeLibDir.getAbsoluteFile().getPath());
var contents = contentsOfDir(nativeLibPath);
contents.forEach(
path -> sb.append(" ").append(path).append(System.lineSeparator()));
}
throw new AssertionError(sb.toString(), e);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers;
import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.type.Types;
import org.enso.interpreter.runtime.util.TruffleFileSystem;
import org.enso.pkg.NativeLibraryFinder;
import org.enso.pkg.Package;
import org.enso.pkg.QualifiedName;
import org.enso.scala.wrapper.ScalaConversions;
Expand Down Expand Up @@ -172,6 +174,19 @@ private static Module registerModule(
return module;
}

@CompilerDirectives.TruffleBoundary
private static Object findNativeLibrary(Object[] arguments, EnsoContext context) {
var libname = arguments[0].toString();
var pkgRepo = context.getPackageRepository();
for (var pkg : pkgRepo.getLoadedPackagesJava()) {
var libPath = NativeLibraryFinder.findNativeLibrary(libname, pkg, TruffleFileSystem.INSTANCE);
if (libPath != null) {
return libPath;
}
}
return context.getNothing();
}

@CompilerDirectives.TruffleBoundary
private static Object unregisterModule(
TopLevelScope scope, Object[] arguments, EnsoContext context)
Expand Down Expand Up @@ -238,6 +253,8 @@ static Object doInvoke(
return leakContext(ctx);
case MethodNames.TopScope.COMPILE:
return compile(arguments, ctx);
case MethodNames.TopScope.FIND_NATIVE_LIBRARY:
return findNativeLibrary(arguments, ctx);
default:
throw UnknownIdentifierException.create(member);
}
Expand All @@ -257,7 +274,8 @@ boolean isMemberInvocable(String member) {
|| member.equals(MethodNames.TopScope.REGISTER_MODULE)
|| member.equals(MethodNames.TopScope.UNREGISTER_MODULE)
|| member.equals(MethodNames.TopScope.LEAK_CONTEXT)
|| member.equals(MethodNames.TopScope.COMPILE);
|| member.equals(MethodNames.TopScope.COMPILE)
|| member.equals(MethodNames.TopScope.FIND_NATIVE_LIBRARY);
}

/**
Expand Down
Loading
Loading