Skip to content

Commit

Permalink
Linux RiscV support
Browse files Browse the repository at this point in the history
  • Loading branch information
modmuss50 committed Aug 4, 2024
1 parent 5f09e18 commit 74f1f00
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.LegacyASMLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.LoomNativeSupportLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.ObjcBridgeUpgradeLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.RiscVNativesLibraryProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.RuntimeLog4jLibraryProcessor;
import net.fabricmc.loom.util.Platform;

public class LibraryProcessorManager {
public static final List<LibraryProcessorFactory> DEFAULT_LIBRARY_PROCESSORS = List.of(
ArmNativesLibraryProcessor::new,
RiscVNativesLibraryProcessor::new,
LegacyASMLibraryProcessor::new,
LoomNativeSupportLibraryProcessor::new,
LWJGL2MavenLibraryProcessor::new,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@

public class LWJGL3UpgradeLibraryProcessor extends LibraryProcessor {
private static final String LWJGL_GROUP = "org.lwjgl";
// Version used to support ARM64 macOS, or Java 19 on all platforms
private static final String LWJGL_VERSION = "3.3.2";
// Version used to support RiscV Linux
private static final String LWJGL_VERSION_RISCV = "3.3.4";

public LWJGL3UpgradeLibraryProcessor(Platform platform, LibraryContext context) {
super(platform, context);
Expand All @@ -60,6 +63,16 @@ public ApplicationResult getApplicationResult() {
return ApplicationResult.MUST_APPLY;
}

if (upgradeLinuxRiscV()) {
if (!context.hasClasspathNatives()) {
// Don't support upgrading versions not using classpath natives to support RiscV
return ApplicationResult.DONT_APPLY;
}

// Update LWJGL when RiscV Linux is not supported
return ApplicationResult.MUST_APPLY;
}

// If the developer requests we can still upgrade LWJGL on this platform
return ApplicationResult.CAN_APPLY;
}
Expand All @@ -70,7 +83,8 @@ public Predicate<Library> apply(Consumer<Library> dependencyConsumer) {
if (library.is(LWJGL_GROUP) && library.name().startsWith("lwjgl")) {
// Replace the natives with the new version, none natives become runtime only
final Library.Target target = library.target() == Library.Target.NATIVES ? Library.Target.NATIVES : Library.Target.RUNTIME;
final Library upgradedLibrary = library.withVersion(LWJGL_VERSION).withTarget(target);
final String upgradedVersion = upgradeLinuxRiscV() ? LWJGL_VERSION_RISCV : LWJGL_VERSION;
final Library upgradedLibrary = library.withVersion(upgradedVersion).withTarget(target);
dependencyConsumer.accept(upgradedLibrary);
}

Expand All @@ -85,6 +99,16 @@ public void applyRepositories(RepositoryHandler repositories) {

// Add support for macOS
private boolean upgradeMacOSArm() {
return platform.getOperatingSystem().isMacOS() && platform.getArchitecture().isArm() && !context.supportsArm64(Platform.OperatingSystem.MAC_OS) && !context.hasClasspathNatives();
return platform.getOperatingSystem().isMacOS()
&& platform.getArchitecture().isArm()
&& !context.supportsArm64(Platform.OperatingSystem.MAC_OS)
&& !context.hasClasspathNatives();
}

// Add support for Linux RiscV
private boolean upgradeLinuxRiscV() {
return platform.getOperatingSystem().isLinux()
&& platform.getArchitecture().isRiscV()
&& platform.getArchitecture().is64Bit();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2024 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package net.fabricmc.loom.configuration.providers.minecraft.library.processors;

import java.util.function.Consumer;
import java.util.function.Predicate;

import org.gradle.api.artifacts.dsl.RepositoryHandler;

import net.fabricmc.loom.LoomRepositoryPlugin;
import net.fabricmc.loom.configuration.providers.minecraft.library.Library;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryContext;
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor;
import net.fabricmc.loom.util.Platform;

/**
* A processor to add support for RiscV.
*/
public class RiscVNativesLibraryProcessor extends LibraryProcessor {
private static final String LWJGL_GROUP = "org.lwjgl";

public RiscVNativesLibraryProcessor(Platform platform, LibraryContext context) {
super(platform, context);
}

@Override
public ApplicationResult getApplicationResult() {
if (!context.usesLWJGL3()) {
// Only supports LWJGL 3
return ApplicationResult.DONT_APPLY;
}

if (!platform.getArchitecture().isRiscV() || !platform.getArchitecture().is64Bit()) {
// Not an RiscV platform, can never apply this.
return ApplicationResult.DONT_APPLY;
}

if (!platform.getOperatingSystem().isLinux()) {
// Only linux supports RiscV
return ApplicationResult.DONT_APPLY;
}

if (!context.hasClasspathNatives()) {
// Only upgrade versions using classpath natives
return ApplicationResult.DONT_APPLY;
}

return ApplicationResult.MUST_APPLY;
}

@Override
public Predicate<Library> apply(Consumer<Library> dependencyConsumer) {
return library -> {
// Add additional riscv64 natives for LWJGL, alongside the existing x64 linux natives.
if (library.is(LWJGL_GROUP) && library.target() == Library.Target.NATIVES && (library.classifier() != null && library.classifier().equals("natives-linux"))) {
// Add the riscv64 natives.
dependencyConsumer.accept(library.withClassifier(library.classifier() + "-riscv64"));
}

return true;
};
}

@Override
public void applyRepositories(RepositoryHandler repositories) {
LoomRepositoryPlugin.forceLWJGLFromMavenCentral(repositories);
}
}
6 changes: 6 additions & 0 deletions src/main/java/net/fabricmc/loom/util/CurrentPlatform.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ private static Architecture getCurrentArchitecture() {
final String arch = System.getProperty("os.arch");
final boolean is64Bit = arch.contains("64") || arch.startsWith("armv8");
final boolean isArm = arch.startsWith("arm") || arch.startsWith("aarch64");
final boolean isRiscV = arch.startsWith("riscv");

return new Architecture() {
@Override
Expand All @@ -76,6 +77,11 @@ public boolean is64Bit() {
public boolean isArm() {
return isArm;
}

@Override
public boolean isRiscV() {
return isRiscV;
}
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/net/fabricmc/loom/util/Platform.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ interface Architecture {
boolean is64Bit();

boolean isArm();

boolean isRiscV();
}

Architecture getArchitecture();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,29 @@ class LibraryProcessorManagerTest extends LibraryProcessorTest {
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.classifier() == "natives-macos"
}

// A test to ensure that we can add linux ARM64 support on an unsupported version
def "Linux riscv"() {
when:
def platform = PlatformTestUtils.LINUX_RISCV
def (original, context) = getLibs("1.21", platform)
def processed = new LibraryProcessorManager(platform, GradleTestUtil.mockRepositoryHandler()).processLibraries(original, context)

then:
// Test to make sure that we compile against the original version
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.3.3"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.3.3"
// And at runtime we have the new version.
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.RUNTIME }.version() == "3.3.4"

// Test to make sure that the natives were upgraded.
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.3.3"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.3.4"

// Test to make sure that the natives were added.
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.classifier() == "natives-linux"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.classifier() == "natives-linux-riscv64"
}

def "runtime log4j"() {
when:
def platform = PlatformTestUtils.WINDOWS_X64
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class ArmNativesLibraryProcessorTest extends LibraryProcessorTest {
"1.17.1" | PlatformTestUtils.MAC_OS_X64
"1.16.5" | PlatformTestUtils.MAC_OS_X64
"1.15.2" | PlatformTestUtils.LINUX_X64
"1.20" | PlatformTestUtils.LINUX_RISCV
"1.14.4" | PlatformTestUtils.MAC_OS_X64
"1.12.2" | PlatformTestUtils.WINDOWS_X64
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,23 @@ class LWJGL3UpgradeLibraryProcessorTest extends LibraryProcessorTest {
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}

def "Apply when adding linux riscv support"() {
when:
def (_, context) = getLibs(id, PlatformTestUtils.LINUX_RISCV)
def processor = new LWJGL3UpgradeLibraryProcessor(PlatformTestUtils.LINUX_RISCV, context)
then:
processor.applicationResult == result

where:
id || result
"1.21" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.19.4" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.18.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not using classpath natives.
"1.16.5" || LibraryProcessor.ApplicationResult.DONT_APPLY
"1.14.4" || LibraryProcessor.ApplicationResult.DONT_APPLY
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}

def "Upgrade LWJGL classpath natives"() {
when:
def (original, context) = getLibs("1.19.4", PlatformTestUtils.MAC_OS_X64, JavaVersion.VERSION_20)
Expand Down Expand Up @@ -133,4 +150,22 @@ class LWJGL3UpgradeLibraryProcessorTest extends LibraryProcessorTest {
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.2.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.3.2"
}

def "Upgrade LWJGL classpath natives Linux riscv"() {
when:
def (original, context) = getLibs("1.19.4", PlatformTestUtils.LINUX_RISCV, JavaVersion.VERSION_20)
def processor = new LWJGL3UpgradeLibraryProcessor(PlatformTestUtils.LINUX_RISCV, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)

then:
// Test to make sure that we compile against the original version
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.3.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.COMPILE }.version() == "3.3.1"
// And at runtime we have the new version.
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.RUNTIME }.version() == "3.3.4"

// Test to make sure that the natives were replaced.
original.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.3.1"
processed.find { it.is("org.lwjgl:lwjgl-glfw") && it.target() == Library.Target.NATIVES }.version() == "3.3.4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2024 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package net.fabricmc.loom.test.unit.library.processors

import net.fabricmc.loom.configuration.providers.minecraft.library.Library
import net.fabricmc.loom.configuration.providers.minecraft.library.LibraryProcessor
import net.fabricmc.loom.configuration.providers.minecraft.library.processors.RiscVNativesLibraryProcessor
import net.fabricmc.loom.test.util.PlatformTestUtils

class RiscVNativesLibraryProcessorTest extends LibraryProcessorTest {
def "Apply when adding linux riscv support"() {
when:
def (_, context) = getLibs(id, PlatformTestUtils.LINUX_RISCV)
def processor = new RiscVNativesLibraryProcessor(PlatformTestUtils.LINUX_RISCV, context)
then:
processor.applicationResult == result

where:
id || result
"1.21" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.20.1" || LibraryProcessor.ApplicationResult.MUST_APPLY
"1.14.4" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not using classpath natives
"1.12.2" || LibraryProcessor.ApplicationResult.DONT_APPLY // Not LWJGL 3
}

def "Never apply on none riscv platforms"() {
when:
def (_, context) = getLibs(id, platform)
def processor = new RiscVNativesLibraryProcessor(platform, context)
then:
processor.applicationResult == LibraryProcessor.ApplicationResult.DONT_APPLY

where:
id | platform
"1.21" | PlatformTestUtils.LINUX_ARM64
"1.21" | PlatformTestUtils.LINUX_X64
"1.19.4" | PlatformTestUtils.MAC_OS_X64
"1.18.2" | PlatformTestUtils.WINDOWS_X64
"1.17.1" | PlatformTestUtils.MAC_OS_X64
"1.16.5" | PlatformTestUtils.MAC_OS_X64
"1.15.2" | PlatformTestUtils.LINUX_X64
"1.14.4" | PlatformTestUtils.MAC_OS_X64
"1.12.2" | PlatformTestUtils.WINDOWS_X64
}

def "Add linux riscv natives"() {
when:
def (original, context) = getLibs("1.21", PlatformTestUtils.LINUX_RISCV)
def processor = new RiscVNativesLibraryProcessor(PlatformTestUtils.LINUX_RISCV, context)
def processed = mockLibraryProcessorManager().processLibraries([processor], original)

then:
// Test that the riscv64 natives are added alongside the existing ones
def originalNatives = original.findAll { it.is("org.lwjgl") && it.target() == Library.Target.NATIVES }
originalNatives.count { it.classifier() == "natives-linux-riscv64" } == 0
originalNatives.count { it.classifier() == "natives-linux" } > 0

def processedNatives = processed.findAll { it.is("org.lwjgl") && it.target() == Library.Target.NATIVES }
processedNatives.count { it.classifier() == "natives-linux-riscv64" } > 0
processedNatives.count { it.classifier() == "natives-linux" } > 0
}
}
Loading

0 comments on commit 74f1f00

Please sign in to comment.