Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c37a5c370 | |||
| b495ac4799 |
@@ -29,7 +29,6 @@ buildAllJars/
|
|||||||
relocate_natives/.venv/
|
relocate_natives/.venv/
|
||||||
relocate_natives/__pycache__/
|
relocate_natives/__pycache__/
|
||||||
relocate_natives/apple-codesign/
|
relocate_natives/apple-codesign/
|
||||||
relocate_natives/cache/
|
|
||||||
|
|
||||||
# file from notepad++
|
# file from notepad++
|
||||||
*.bak
|
*.bak
|
||||||
|
|||||||
@@ -17,9 +17,6 @@ variables:
|
|||||||
# These can be extended so code is a bit less duplicated
|
# These can be extended so code is a bit less duplicated
|
||||||
.build_java:
|
.build_java:
|
||||||
#image: eclipse-temurin:17
|
#image: eclipse-temurin:17
|
||||||
before_script:
|
|
||||||
- apt-get update
|
|
||||||
- apt-get install python3 python3-pip python-is-python3 python3-venv -y --no-install-recommends
|
|
||||||
cache:
|
cache:
|
||||||
key: "gradleCache_$CI_JOB_NAME_SLUG"
|
key: "gradleCache_$CI_JOB_NAME_SLUG"
|
||||||
policy: pull-push
|
policy: pull-push
|
||||||
|
|||||||
+3
-25
@@ -106,24 +106,12 @@ forgix {
|
|||||||
|
|
||||||
|
|
||||||
class NativeTransformer implements Transformer {
|
class NativeTransformer implements Transformer {
|
||||||
private boolean enabled = false
|
|
||||||
private final HashMap<String, String> replacements = new HashMap()
|
private final HashMap<String, String> replacements = new HashMap()
|
||||||
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
||||||
private var nativeRelocator
|
private var nativeRelocator
|
||||||
|
|
||||||
public File rootDir
|
public File rootDir
|
||||||
|
|
||||||
NativeTransformer() {
|
|
||||||
try {
|
|
||||||
int exitCode = Runtime.getRuntime().exec(new String[]{"python", "--version"}).waitFor()
|
|
||||||
if (exitCode == 0) {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
println(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void relocateNative(String target, String replacement) {
|
void relocateNative(String target, String replacement) {
|
||||||
if (replacement.length() > target.length()) {
|
if (replacement.length() > target.length()) {
|
||||||
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
||||||
@@ -132,22 +120,15 @@ class NativeTransformer implements Transformer {
|
|||||||
replacements.put(target, replacement)
|
replacements.put(target, replacement)
|
||||||
}
|
}
|
||||||
|
|
||||||
void before(Closure closure) {
|
|
||||||
if (enabled)
|
|
||||||
closure.run()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
||||||
return enabled && replacements.keySet().stream().anyMatch {
|
return replacements.keySet().stream().anyMatch {
|
||||||
element.name.startsWith(it as String)
|
element.name.startsWith(it as String)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void transform(@Nonnull TransformerContext context) {
|
void transform(@Nonnull TransformerContext context) {
|
||||||
println("Transforming $context.path...")
|
|
||||||
byte[] content = context.is.readAllBytes()
|
byte[] content = context.is.readAllBytes()
|
||||||
|
|
||||||
if (nativeRelocator == null) {
|
if (nativeRelocator == null) {
|
||||||
@@ -395,16 +376,13 @@ subprojects { p ->
|
|||||||
// Sqlite Database
|
// Sqlite Database
|
||||||
// librariesLocation isn't used because it's too long for replacing paths in native libraries
|
// librariesLocation isn't used because it's too long for replacing paths in native libraries
|
||||||
// Allowing strings larger than the original string would require shifting the entire binary's contents
|
// Allowing strings larger than the original string would require shifting the entire binary's contents
|
||||||
transform(NativeTransformer) {
|
|
||||||
rootDir = project.rootDir
|
|
||||||
|
|
||||||
before {
|
|
||||||
relocate "org.sqlite", "dh_sqlite", {
|
relocate "org.sqlite", "dh_sqlite", {
|
||||||
exclude "org/sqlite/native/**"
|
exclude "org/sqlite/native/**"
|
||||||
}
|
}
|
||||||
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
|
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
|
||||||
}
|
|
||||||
|
|
||||||
|
transform(NativeTransformer) {
|
||||||
|
rootDir = project.rootDir
|
||||||
relocateNative "org/sqlite", "dh_sqlite"
|
relocateNative "org/sqlite", "dh_sqlite"
|
||||||
relocateNative "org_sqlite", "dh_1sqlite"
|
relocateNative "org_sqlite", "dh_1sqlite"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,15 @@ class NativeRelocator
|
|||||||
/**
|
/**
|
||||||
* Initializes the NativeRelocator by preparing the environment if necessary.
|
* Initializes the NativeRelocator by preparing the environment if necessary.
|
||||||
* Executes the appropriate preparation script based on the OS.
|
* Executes the appropriate preparation script based on the OS.
|
||||||
*
|
|
||||||
* @throws Exception if the preparation script fails or an unsupported OS is detected.
|
|
||||||
*/
|
*/
|
||||||
NativeRelocator(Path rootDirectory) throws Exception
|
NativeRelocator(Path rootDirectory)
|
||||||
{
|
{
|
||||||
this.rootDirectory = rootDirectory;
|
this.rootDirectory = rootDirectory;
|
||||||
this.cacheRoot = this.rootDirectory.resolve("cache");
|
this.cacheRoot = this.rootDirectory.resolve("cache");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepare() throws Exception
|
||||||
|
{
|
||||||
if (this.rootDirectory.resolve(".venv").toFile().exists())
|
if (this.rootDirectory.resolve(".venv").toFile().exists())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -196,6 +197,9 @@ class NativeRelocator
|
|||||||
return Files.readAllBytes(outputFilePath);
|
return Files.readAllBytes(outputFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("Relocating to " + outputPath + "...");
|
||||||
|
this.prepare();
|
||||||
|
|
||||||
for (Map.Entry<String, String> replacement : replacements.entrySet())
|
for (Map.Entry<String, String> replacement : replacements.entrySet())
|
||||||
{
|
{
|
||||||
this.replaceInNullTerminatedStrings(content, replacement.getKey(), replacement.getValue());
|
this.replaceInNullTerminatedStrings(content, replacement.getKey(), replacement.getValue());
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ manifold_version=2024.1.37
|
|||||||
nightconfig_version=3.6.6
|
nightconfig_version=3.6.6
|
||||||
lz4_version=1.8.0
|
lz4_version=1.8.0
|
||||||
xz_version=1.9
|
xz_version=1.9
|
||||||
|
# Before updating, read relocate_natives/README.md
|
||||||
sqlite_jdbc_version=3.47.2.0
|
sqlite_jdbc_version=3.47.2.0
|
||||||
# 8.2.1 is the newest version we can use since that's the version MC 1.16.5 uses
|
# 8.2.1 is the newest version we can use since that's the version MC 1.16.5 uses
|
||||||
fastutil_version=8.2.1
|
fastutil_version=8.2.1
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
This directory contains the native files of libraries that were modified for relocation. They will be copied from here during the normal build steps.
|
||||||
|
|
||||||
|
Before adding/updating a library, make sure you have Python 3.8+ installed and check the instructions below.
|
||||||
|
|
||||||
|
How to add a library's natives:
|
||||||
|
|
||||||
|
1. In `build.gradle`:
|
||||||
|
|
||||||
|
- Make sure the target package is the same length or shorter (untested) than the source package. Underscores in native methods will take 2 characters so account for that as well.
|
||||||
|
- Exclude the native files and add them as `relocateNative` (see example).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
relocate "org.sqlite", "dh_sqlite", {
|
||||||
|
exclude "org/sqlite/native/**"
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(NativeTransformer) {
|
||||||
|
// NativeTransformer configuration
|
||||||
|
rootDir = project.rootDir
|
||||||
|
|
||||||
|
// Replace native strings, e.g. used in calls back to Java
|
||||||
|
relocateNative "org/sqlite", "dh_sqlite"
|
||||||
|
// Rename native methods used when calling from Java
|
||||||
|
relocateNative "org_sqlite", "dh_1sqlite"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
How to update a library's natives:
|
||||||
|
|
||||||
|
1. Delete the library's folder in cache/.
|
||||||
|
2. It will repopulate during the next build.
|
||||||
|
|
||||||
|
Why does this step exist?
|
||||||
|
|
||||||
|
- Native files are not handled by the shadow plugin correctly.
|
||||||
|
- I preferred it as a more streamlined approach, although a bit hacky.
|
||||||
|
- Possible alternatives:
|
||||||
|
- Use edited libraries' source code: although more straightforward, it requires maintaining and updating the repositories for the libraries being added
|
||||||
|
- Interfacing with the necessary libraries directly: an absolute mess for technical reasons
|
||||||
|
|
||||||
|
What are libraries used?
|
||||||
|
|
||||||
|
- LIEF: for fixing binaries after replacing strings
|
||||||
|
- apple-codesign: for re-signing Mac binaries, since their signatures get invalidated after previous steps
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user