Skip to content
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ test-mockup-os-release

# generated dependency packages
*.tar.*

local.properties
26 changes: 26 additions & 0 deletions Build_new.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Setup for J2V8 Native Library Building

## Install Android NDK

**Install NDK via SDK Manager**
- Open Android Studio
- Go to Tools > SDK Manager
- Click "SDK Tools" tab
- Check NDK and click apply

**Set environment variable**
```bash
# Add to ~/.zshrc or ~/.bash_profile
export ANDROID_NDK_HOME=~/Library/Android/sdk/ndk-bundle

# Reload shell
source ~/.zshrc
```

## Run the build script

```bash
./rebuild_native.sh
```
This will compile new .so libraries from V8 sources and place them in `src/main/jniLibs/` replacing the existing ones.
It will also run `./gradlew assembleRelease` and build the .aar artifact.
55 changes: 32 additions & 23 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,48 @@ ext."signing.keyId" = System.getenv("KEY_ID")

buildscript {
repositories {
jcenter()
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.android.tools.build:gradle:8.7.3'
classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.2'
}
}

apply plugin: 'spoon'

repositories {
jcenter()
google()
mavenCentral()
}

dependencies {
testCompile 'junit:junit:4.12'
//testCompile 'org.mockito:mockito-all:2.6.3'
testCompile 'org.mockito:mockito-core:2.6.3'

androidTestCompile 'junit:junit:4.12'
androidTestCompile 'org.mockito:mockito-android:2.6.3' // https://jeroenmols.com/blog/2017/01/17/mockitoandroid/
androidTestCompile 'com.android.support:support-annotations:24.0.0'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
testImplementation 'junit:junit:4.13.2'
//testImplementation 'org.mockito:mockito-all:2.6.3'
testImplementation 'org.mockito:mockito-core:4.11.0'

androidTestImplementation 'junit:junit:4.13.2'
androidTestImplementation 'org.mockito:mockito-android:4.11.0' // https://jeroenmols.com/blog/2017/01/17/mockitoandroid/
androidTestImplementation 'androidx.annotation:annotation:1.9.1'
androidTestImplementation 'androidx.test:runner:1.6.2'
androidTestImplementation 'androidx.test:rules:1.6.1'
}

android {
compileSdkVersion 10
buildToolsVersion '24.0.3'

namespace 'com.eclipsesource.v8'
compileSdk 35
defaultConfig {
minSdkVersion 10
targetSdkVersion 10
minSdkVersion 21
targetSdkVersion 35

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

lintOptions {
Expand Down Expand Up @@ -79,10 +86,12 @@ spoon {
}
}

publishing {
publications {
maven(MavenPublication) {
artifact("$buildDir/outputs/aar/j2v8-release.aar")
afterEvaluate {
publishing {
publications {
maven(MavenPublication) {
artifact bundleReleaseAar
}
}
}
}
}
114 changes: 114 additions & 0 deletions check_elf_alignment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/bin/bash
progname="${0##*/}"
progname="${progname%.sh}"

# Usage: check_elf_alignment.sh [path to *.so files|path to *.apk]
# Copied from https://developer.android.com/guide/practices/page-sizes

cleanup_trap() {
if [ -n "${tmp}" -a -d "${tmp}" ]; then
rm -rf ${tmp}
fi
exit $1
}

usage() {
echo "Host side script to check the ELF alignment of shared libraries."
echo "Shared libraries are reported ALIGNED when their ELF regions are"
echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED."
echo
echo "Usage: ${progname} [input-path|input-APK|input-APEX]"
}

if [ ${#} -ne 1 ]; then
usage
exit
fi

case ${1} in
--help | -h | -\?)
usage
exit
;;

*)
dir="${1}"
;;
esac

if ! [ -f "${dir}" -o -d "${dir}" ]; then
echo "Invalid file: ${dir}" >&2
exit 1
fi

if [[ "${dir}" == *.apk ]]; then
trap 'cleanup_trap' EXIT

echo
echo "Recursively analyzing $dir"
echo

if { zipalign --help 2>&1 | grep -q "\-P <pagesize_kb>"; }; then
echo "=== APK zip-alignment ==="
zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification'
echo "========================="
else
echo "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher."
echo " You can install the latest build-tools by running the below command"
echo " and updating your \$PATH:"
echo
echo " sdkmanager \"build-tools;35.0.0-rc3\""
fi

dir_filename=$(basename "${dir}")
tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX")
unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1
dir="${tmp}"
fi

if [[ "${dir}" == *.apex ]]; then
trap 'cleanup_trap' EXIT

echo
echo "Recursively analyzing $dir"
echo

dir_filename=$(basename "${dir}")
tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX")
deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; }
dir="${tmp}"
fi

RED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"

unaligned_libs=()

echo
echo "=== ELF alignment ==="

matches="$(find "${dir}" -type f)"
IFS=$'\n'
for match in $matches; do
# We could recursively call this script or rewrite it to though.
[[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}"
[[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}"

[[ $(file "${match}") == *"ELF"* ]] || continue

res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)"
if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then
echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
else
echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"
unaligned_libs+=("${match}")
fi
done

if [ ${#unaligned_libs[@]} -gt 0 ]; then
echo -e "${RED}Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}"
elif [ -n "${dir_filename}" ]; then
echo -e "ELF Verification Successful"
fi
echo "====================="
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#increase jvm heap space available for gradle
#(allows to run dex in the same process as gradle)
org.gradle.jvmargs=-Xmx4608M
android.useAndroidX=true
12 changes: 6 additions & 6 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Mon Dec 15 11:54:06 CET 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
#Thu Jun 05 09:06:59 CEST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
2 changes: 2 additions & 0 deletions jni/com_eclipsesource_v8_V8Impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@

#define TAG "J2V8_V8Impl"

#ifdef _WIN32
#pragma comment(lib, "userenv.lib")
#pragma comment(lib, "IPHLPAPI.lib")
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "WINMM.lib")
#pragma comment( lib, "psapi.lib" )
#endif

using namespace std;
using namespace v8;
Expand Down
127 changes: 127 additions & 0 deletions rebuild_native.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/bin/bash

# A script to rebuild J2V8 native libraries for Android

set -e

echo "J2V8 Native Library Rebuild Script"
echo "=================================="
echo "✅ Builds 16KB-aligned .so libraries for Google Play compliance"

# Check if Android NDK is available
if [ -z "$ANDROID_NDK_HOME" ]; then
echo "ERROR: ANDROID_NDK_HOME environment variable not set"
echo "Please install Android NDK and set ANDROID_NDK_HOME"
exit 1
fi

# Create output directories (replace existing libraries in src/main/jniLibs)
mkdir -p src/main/jniLibs/arm64-v8a
mkdir -p src/main/jniLibs/armeabi-v7a
mkdir -p src/main/jniLibs/x86
mkdir -p src/main/jniLibs/x86_64
mkdir -p build_native/android

if [ -d "v8.out" ]; then
echo "✅ V8 libraries found:"
find v8.out -name "*.a" | sort
else
# Taken from https://download.eclipsesource.com/j2v8/v8/libv8_9.3.345.11_monolith.zip
# Added to VCS in case the link breaks
unzip v8_monolith/libv8_9.3.345.11_monolith.zip -d v8.out
fi

API_LEVEL=21

# Function to build for a specific architecture
build_arch() {
local android_abi=$1
local v8_arch=$2
local ndk_arch=$3

echo ""
echo "Building for $android_abi ($v8_arch)..."

# Set up compiler paths
local TOOLCHAIN="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64"
if [ ! -d "$TOOLCHAIN" ]; then
# Try linux toolchain
TOOLCHAIN="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64"
fi

if [ ! -d "$TOOLCHAIN" ]; then
echo "ERROR: Could not find Android NDK toolchain"
return 1
fi

local CC="$TOOLCHAIN/bin/${ndk_arch}${API_LEVEL}-clang"
local CXX="$TOOLCHAIN/bin/${ndk_arch}${API_LEVEL}-clang++"

if [ ! -f "$CC" ]; then
echo "ERROR: Compiler not found: $CC"
return 1
fi

echo "Using compiler: $CC"

# Generate JNI header if needed
if [ ! -f "jni/com_eclipsesource_v8_V8Impl.h" ]; then
echo "Generating JNI headers..."
if [ -d "build/intermediates/javac/release/classes" ]; then
javah -cp build/intermediates/javac/release/classes -o jni com.eclipsesource.v8.V8Impl || echo "Warning: Could not generate JNI headers"
else
echo "Warning: Java classes not found, using existing JNI headers"
fi
fi

# Compile flags with release optimizations
local CPPFLAGS="-I$ANDROID_NDK_HOME/sysroot/usr/include"
CPPFLAGS="$CPPFLAGS -I$ANDROID_NDK_HOME/sysroot/usr/include/$ndk_arch"
CPPFLAGS="$CPPFLAGS -Iv8.out/include"
CPPFLAGS="$CPPFLAGS -Ijni"
CPPFLAGS="$CPPFLAGS -fPIC -std=c++17 -O3 -DNDEBUG"

# Link flags with 16KB alignment for Google Play compliance and symbol stripping
local LDFLAGS="-shared -llog -s"
LDFLAGS="$LDFLAGS -Wl,-z,max-page-size=16384"
LDFLAGS="$LDFLAGS -Wl,-z,common-page-size=16384"

# Output directly to src/main/jniLibs (replace existing files under version control)
local OUTPUT="src/main/jniLibs/$android_abi/libj2v8.so"

echo "Compiling libj2v8 for $android_abi..."

# Compile the JNI implementation
if ! $CXX $CPPFLAGS -c jni/com_eclipsesource_v8_V8Impl.cpp -o "build_native/android/v8impl_$android_abi.o"; then
echo "ERROR: Compilation failed for $android_abi"
return 1
fi

echo "Linking libj2v8 for $android_abi..."

# Link with V8 and output directly to jniLibs
if ! $CXX $LDFLAGS -o "$OUTPUT" "build_native/android/v8impl_$android_abi.o" "$v8_lib"; then
echo "ERROR: Linking failed for $android_abi"
return 1
fi

echo "✅ Built: $OUTPUT"
ls -lh "$OUTPUT"
}

# Build for each architecture
echo "Building for all Android architectures..."

build_arch "arm64-v8a" "android.arm64" "aarch64-linux-android"
build_arch "armeabi-v7a" "android.arm" "armv7a-linux-androideabi"
build_arch "x86" "android.x86" "i686-linux-android"
build_arch "x86_64" "android.x64" "x86_64-linux-android"

echo ""
echo "Native library rebuild complete!"
echo "Libraries compiled and replaced in src/main/jniLibs:"
ls -la src/main/jniLibs/*/libj2v8.so 2>/dev/null || echo "No libraries found in src/main/jniLibs/"
echo ""
./check_elf_alignment.sh src/main/jniLibs
echo "Running './gradlew assembleRelease' to build the AAR with the new native libraries"
./gradlew assembleRelease
Binary file modified src/main/jniLibs/arm64-v8a/libj2v8.so
100644 → 100755
Binary file not shown.
Binary file modified src/main/jniLibs/armeabi-v7a/libj2v8.so
100644 → 100755
Binary file not shown.
Binary file modified src/main/jniLibs/x86/libj2v8.so
100644 → 100755
Binary file not shown.
Binary file modified src/main/jniLibs/x86_64/libj2v8.so
100644 → 100755
Binary file not shown.
Binary file added v8_monolith/libv8_9.3.345.11_monolith.zip
Binary file not shown.
Loading