Dev build fixes

This commit is contained in:
crschnick
2025-04-23 16:24:34 +00:00
parent 1cc21e12c0
commit 928585200a
4 changed files with 63 additions and 85 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ sdk install java 24-graalce
sdk default java 24-graalce
```
.
On Windows, you have to manually install a JDK, e.g. from [Adoptium](https://adoptium.net/temurin/releases/?version=21).
On Windows, you have to manually install a JDK, e.g. from [Adoptium](https://adoptium.net/temurin/releases/?version=24).
You can configure a few development options in the file `app/dev.properties` which will be automatically generated when gradle is first run.
@@ -5,6 +5,7 @@ import io.xpipe.app.ext.ProcessControlProvider;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.resources.AppResources;
import io.xpipe.app.util.ModuleAccess;
import io.xpipe.core.process.OsType;
import io.xpipe.core.util.ModuleLayerLoader;
import io.xpipe.core.util.XPipeInstallation;
@@ -25,7 +26,7 @@ import java.util.stream.Stream;
public class AppExtensionManager {
private static AppExtensionManager INSTANCE;
private final List<Extension> loadedExtensions = new ArrayList<>();
private final List<Module> loadedModules = new ArrayList<>();
private final List<ModuleLayer> leafModuleLayers = new ArrayList<>();
private final List<Path> extensionBaseDirectories = new ArrayList<>();
private ModuleLayer baseLayer = ModuleLayer.boot();
@@ -66,18 +67,11 @@ public class AppExtensionManager {
throw ExtensionException.corrupt("Missing base module");
}
baseLayer = baseModule.get().getModule().getLayer();
loadedExtensions.add(baseModule.get());
baseLayer = baseModule.get().getLayer();
loadedModules.add(baseModule.get());
}
private void determineExtensionDirectories() throws Exception {
if (!AppProperties.get().isImage()) {
extensionBaseDirectories.add(Path.of(System.getProperty("user.dir"))
.resolve("app")
.resolve("build")
.resolve("ext_dev"));
}
if (!AppProperties.get().isFullVersion()) {
var localInstallation = XPipeInstallation.getLocalDefaultInstallationBasePath(
AppProperties.get().isStaging() || AppProperties.get().isLocatePtb());
@@ -104,13 +98,6 @@ public class AppExtensionManager {
var extensions = XPipeInstallation.getLocalExtensionsDirectory(p);
extensionBaseDirectories.add(extensions);
}
var userDir = AppProperties.get().getDataDir().resolve("extensions");
extensionBaseDirectories.add(userDir);
var currentInstallation = XPipeInstallation.getCurrentInstallationBasePath();
var productionRoot = XPipeInstallation.getLocalExtensionsDirectory(currentInstallation);
extensionBaseDirectories.add(productionRoot);
}
private static String getLocalInstallVersion() throws Exception {
@@ -126,16 +113,16 @@ public class AppExtensionManager {
public Set<Module> getContentModules() {
return Stream.concat(
Stream.of(ModuleLayer.boot().findModule("io.xpipe.app").orElseThrow()),
loadedExtensions.stream().map(extension -> extension.module))
loadedModules.stream())
.collect(Collectors.toSet());
}
private void loadAllExtensions() {
private void loadAllExtensions() throws Exception {
for (var ext : List.of("system", "proc", "uacc")) {
var extension = findAndParseExtension(ext, baseLayer)
.orElseThrow(() -> ExtensionException.corrupt("Missing module " + ext));
loadedExtensions.add(extension);
leafModuleLayers.add(extension.getModule().getLayer());
loadedModules.add(extension);
leafModuleLayers.add(extension.getLayer());
}
var scl = ClassLoader.getSystemClassLoader();
@@ -144,13 +131,24 @@ public class AppExtensionManager {
var cf = Configuration.resolve(finder, cfs, finder, List.of());
extendedLayer = ModuleLayer.defineModulesWithOneLoader(cf, leafModuleLayers, scl)
.layer();
if (!AppProperties.get().isFullVersion()) {
ModuleAccess.exportAndOpen(
ModuleLayer.boot().findModule("java.base").orElseThrow(),
"java.io",
extendedLayer.findModule("io.xpipe.ext.proc").orElseThrow());
ModuleAccess.exportAndOpen(ModuleLayer.boot().findModule("org.apache.commons.io").orElseThrow(),
"org.apache.commons.io.input",
extendedLayer.findModule("io.xpipe.ext.proc").orElseThrow());
}
}
private Optional<Extension> findAndParseExtension(String name, ModuleLayer parent) {
private Optional<Module> findAndParseExtension(String name, ModuleLayer parent) {
var inModulePath = ModuleLayer.boot().findModule("io.xpipe.ext." + name);
if (inModulePath.isPresent()) {
TrackEvent.info("Loaded extension " + name + " from boot module path");
return Optional.of(new Extension(null, inModulePath.get().getName(), name, inModulePath.get(), 0));
return inModulePath;
}
for (Path extensionBaseDirectory : extensionBaseDirectories) {
@@ -166,20 +164,12 @@ public class AppExtensionManager {
return Optional.empty();
}
private Optional<Extension> parseExtensionDirectory(Path dir, ModuleLayer parent) {
private Optional<Module> parseExtensionDirectory(Path dir, ModuleLayer parent) {
if (!Files.exists(dir) || !Files.isDirectory(dir)) {
return Optional.empty();
}
if (loadedExtensions.stream().anyMatch(extension -> dir.equals(extension.dir))
|| loadedExtensions.stream()
.anyMatch(extension ->
extension.id.equals(dir.getFileName().toString()))) {
return Optional.empty();
}
TrackEvent.trace(String.format("Scanning directory %s for extensions", dir));
try {
ModuleFinder finder = ModuleFinder.of(dir);
var found = finder.findAll();
@@ -196,26 +186,8 @@ public class AppExtensionManager {
ClassLoader scl = ClassLoader.getSystemClassLoader();
var layer = ModuleLayer.defineModulesWithOneLoader(cf, List.of(parent), scl)
.layer();
var ext = getExtensionFromDir(layer, dir);
if (ext.isEmpty()) {
if (AppProperties.get().isFullVersion()) {
throw ExtensionException.corrupt("Unable to load extension from directory " + dir);
}
} else {
if (loadedExtensions.stream()
.anyMatch(extension -> extension.getName().equals(ext.get().name))) {
return Optional.empty();
}
TrackEvent.withInfo("Loaded extension module")
.tag("name", ext.get().getName())
.tag("dir", dir.toString())
.tag("dependencies", ext.get().getDependencies())
.handle();
return ext;
}
var mod = layer.modules().iterator().next();
return Optional.of(mod);
}
} catch (Throwable t) {
ErrorEvent.fromThrowable(t)
@@ -224,34 +196,4 @@ public class AppExtensionManager {
}
return Optional.empty();
}
private Optional<Extension> getExtensionFromDir(ModuleLayer l, Path dir) {
return l.modules().stream()
.map(m -> {
AtomicReference<Extension> ext = new AtomicReference<>();
AppResources.withResourceInLayer(m.getName(), "extension.properties", l, path -> {
if (Files.exists(path)) {
var props = new Properties();
try (var in = Files.newInputStream(path)) {
props.load(in);
}
var name = props.get("name").toString();
var deps = l.modules().size() - 1;
ext.set(new Extension(dir, dir.getFileName().toString(), name, m, deps));
}
});
return Optional.ofNullable(ext.get());
})
.flatMap(Optional::stream)
.findFirst();
}
@Value
private static class Extension {
Path dir;
String id;
String name;
Module module;
int dependencies;
}
}
@@ -0,0 +1,30 @@
package io.xpipe.app.util;
import lombok.SneakyThrows;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ModuleAccess {
public static void exportAndOpen(Module source, String pkg, Module target) throws Exception {
if (source.isExported(pkg, target) && source.isOpen(pkg, target)) {
return;
}
Method getDeclaredFields0 = Class.class.getDeclaredMethod("getDeclaredMethods0", boolean.class);
getDeclaredFields0.setAccessible(true);
Method[] fields = (Method[]) getDeclaredFields0.invoke(Module.class, false);
Method modifiers = null;
for (Method each : fields) {
if ("implAddExportsOrOpens".equals(each.getName())) {
modifiers = each;
break;
}
}
modifiers.setAccessible(true);
modifiers.invoke(source, pkg, target, false, true);
modifiers.invoke(source, pkg, target, true, true);
}
}
+8 -2
View File
@@ -144,8 +144,7 @@ project.ext {
// Module access fixes
jvmRunArgs += [
"--add-opens", "java.base/java.io=io.xpipe.ext.proc",
"--add-opens", "org.apache.commons.io/org.apache.commons.io.input=io.xpipe.ext.proc",
"--add-opens", "java.base/java.lang=io.xpipe.app",
"--add-opens", "net.synedra.validatorfx/net.synedra.validatorfx=io.xpipe.app",
"--add-opens", "java.base/java.nio.file=io.xpipe.app",
"--add-opens", "java.base/java.lang=io.xpipe.app",
@@ -157,6 +156,13 @@ project.ext {
"--add-opens", "javafx.graphics/com.sun.javafx.tk.quantum=io.xpipe.app"
]
if (fullVersion) {
jvmRunArgs += [
"--add-opens", "java.base/java.io=io.xpipe.ext.proc",
"--add-opens", "org.apache.commons.io/org.apache.commons.io.input=io.xpipe.ext.proc",
]
}
// Use project liliput
jvmRunArgs += ['-XX:+UnlockExperimentalVMOptions', '-XX:+UseCompactObjectHeaders']