Skip to content

Commit

Permalink
Merge pull request #503 from ethereum/java_cmake_build
Browse files Browse the repository at this point in the history
Java CMake build
  • Loading branch information
chfast authored May 12, 2020
2 parents bb4329c + fb13cff commit 66f6428
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 77 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ include(CMakeDependentOption)
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

option(EVMC_JAVA "Enable building Java Native Interface (JNI) bindings" OFF)

option(EVMC_INSTALL "Enable EVMC installation (e.g. make install)" ON)

option(EVMC_TESTING "Build everything (libraries, tools, examples, internal tests)" OFF)
Expand Down Expand Up @@ -58,6 +60,10 @@ set(include_dir ${PROJECT_SOURCE_DIR}/include)

add_subdirectory(lib)

if(EVMC_JAVA)
add_subdirectory(bindings/java)
endif()

if(EVMC_TOOLS)
add_subdirectory(tools)
endif()
Expand Down
34 changes: 34 additions & 0 deletions bindings/java/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# EVMC: Ethereum Client-VM Connector API.
# Copyright 2020 The EVMC Authors.
# Licensed under the Apache License, Version 2.0.

include(UseJava)

find_package(Java REQUIRED COMPONENTS Development)
find_package(JNI REQUIRED)

add_jar(evmc-jar
OUTPUT_NAME evmc-java
VERSION ${PROJECT_VERSION}
SOURCES
java/src/main/java/org/ethereum/evmc/EvmcVm.java
java/src/main/java/org/ethereum/evmc/Host.java
java/src/main/java/org/ethereum/evmc/HostContext.java
GENERATE_NATIVE_HEADERS evmc-java-native-headers)

add_library(evmc-java SHARED)
target_sources(evmc-java PRIVATE
c/evmc-vm.c
c/host.c
c/host.h)
target_include_directories(evmc-java PRIVATE ${JNI_INCLUDE_DIRS})
target_link_libraries(evmc-java PRIVATE evmc-java-native-headers evmc::evmc evmc::loader ${JNI_LIBRARIES})

if(EVMC_INSTALL)
install(TARGETS evmc-java EXPORT evmcTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

install_jar(evmc-jar DESTINATION ${CMAKE_INSTALL_DATADIR}/java)
endif()
43 changes: 13 additions & 30 deletions bindings/java/Makefile
Original file line number Diff line number Diff line change
@@ -1,42 +1,25 @@
OS:=$(shell uname -s | tr '[:upper:]' '[:lower:]')
ifeq ($(OS), linux)
EXT:=so
OS_LFLAGS:=
JAVA_HOME:=$(shell java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home' | sed 's/\s*java.home = //' | sed 's/\/jre//')
else ifeq ($(OS), darwin)
EXT:=so
OS_LFLAGS:=-mmacosx-version-min=$(shell defaults read loginwindow SystemVersionStampAsString) -framework CoreFoundation -framework Security
JAVA_HOME:=$(shell java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home' | sed 's/\s*java.home = //' | sed 's/\/jre//')
endif
JAVA_HOME:=$(shell java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home' | sed 's/\s*java.home = //' | sed 's/\/jre//')

INCLUDES = -I../../include
JAVA_INCLUDES = -I$(JAVA_HOME)/include/$(OS) -I$(JAVA_HOME)/include
JAVA_LIBS = -L$(JAVA_HOME)/lib/server -ljvm
CFLAGS = -O2 -fPIC
LFLAGS = -shared
OUT_DIR = ./c/build
SOURCE_DIR = $(realpath $(CURDIR)/../..)
OUT_DIR = $(CURDIR)/c/build
BUILD_DIR = $(OUT_DIR)/_cmake_build

gradlew:
gradle --no-daemon setup

build: gradlew
mkdir -p $(OUT_DIR)
javac ./java/src/main/java/org/ethereum/evmc/EvmcVm.java -h ./c --class-path ./java/src/main/java -s ./java/build
mv c/org_ethereum_evmc_EvmcVm.h c/evmc-vm.h
gcc $(DEBUG_FLAG) $(CFLAGS) -c $(INCLUDES) -o $(OUT_DIR)/loader.o ../../lib/loader/loader.c
gcc $(DEBUG_FLAG) $(CFLAGS) -c $(INCLUDES) $(JAVA_INCLUDES) -o $(OUT_DIR)/host.o ./c/host.c
gcc $(DEBUG_FLAG) $(CFLAGS) ./c/evmc-vm.c $(INCLUDES) $(JAVA_INCLUDES) $(JAVA_LIBS) $(CFLAGS) $(LFLAGS) -o $(OUT_DIR)/evmc.$(EXT) $(OUT_DIR)/host.o $(OUT_DIR)/loader.o
gcc $(DEBUG_FLAG) -shared ../../examples/example_vm/example_vm.c $(INCLUDES) -o $(OUT_DIR)/example_vm.$(EXT)
build: gradlew $(OUT_DIR)/lib/libevmc-java.so
mkdir -p ./java/build
./gradlew --no-daemon clean spotlessApply build

test: build
./gradlew --no-daemon test

format:
clang-format -i c/evmc-vm.c c/host.c c/host.h
gradlew:
gradle --no-daemon setup

$(OUT_DIR)/lib/libevmc-java.so:
mkdir -p $(BUILD_DIR)
(cd $(BUILD_DIR) && cmake $(SOURCE_DIR) -DCMAKE_INSTALL_PREFIX=$(OUT_DIR) -DEVMC_JAVA=ON -DJAVA_HOME=$(JAVA_HOME) -DEVMC_EXAMPLES=ON)
cmake --build $(OUT_DIR)/_cmake_build --target install

clean:
rm -rf $(OUT_DIR)
rm -rf build
rm -rf ./java/build/
rm -rf ./c/build/
10 changes: 5 additions & 5 deletions bindings/java/c/evmc-vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
* Licensed under the Apache License, Version 2.0.
*/

#include "host.h"
#include "org_ethereum_evmc_EvmcVm.h"
#include <evmc/helpers.h>
#include <evmc/loader.h>

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>

#include "evmc-vm.h"
#include "evmc/helpers.h"
#include "evmc/loader.h"
#include "host.h"

static void throw_java_assert(JNIEnv* jenv, const char* msg)
{
jclass jcls = (*jenv)->FindClass(jenv, "java/lang/AssertionError");
Expand Down
26 changes: 0 additions & 26 deletions bindings/java/java/README.md

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static EvmcVm create(String filename) {
if (!EvmcVm.isEvmcLibraryLoaded) {
try {
// load so containing the jni bindings to evmc
System.load(System.getProperty("user.dir") + "/../c/build/evmc.so");
System.load(System.getProperty("user.dir") + "/../c/build/lib/libevmc-java.so");
EvmcVm.isEvmcLibraryLoaded = true;
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load.\n" + e);
Expand Down
28 changes: 15 additions & 13 deletions bindings/java/java/src/test/java/org/ethereum/evmc/EvmcTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,28 @@
import org.junit.jupiter.api.Test;

final class EvmcTest {
private static final String exampleVmPath =
System.getProperty("user.dir") + "/../c/build/lib/libexample-vm.so";

@Test
void testInitCloseDestroy() throws Exception {
Assertions.assertDoesNotThrow(
() -> {
try (EvmcVm vm =
EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {}
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {}
});
}

@Test
void testAbiVersion() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
int abiVersion = vm.abi_version();
assert (abiVersion > 0);
}
}

@Test
void testName() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
String name = vm.name();
assert (name.length() > 0);
assert (name.equals("example_vm"));
Expand All @@ -34,7 +36,7 @@ void testName() throws Exception {

@Test
void testVersion() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
String version = vm.version();
assert (version.length() > 0);
assert (version.equals("0.0.0"));
Expand All @@ -43,7 +45,7 @@ void testVersion() throws Exception {

@Test
void testExecute_returnAddress() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
HostContext context = new TestHostContext();
int BYZANTIUM = 4;
int EVMC_CALL = 0;
Expand Down Expand Up @@ -73,7 +75,7 @@ void testExecute_returnAddress() throws Exception {
/** Tests callbacks: get_storage_fn & set_storage_fn */
@Test
void testExecute_counter() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
HostContext context = new TestHostContext();
int BYZANTIUM = 4;
int EVMC_CALL = 0;
Expand Down Expand Up @@ -103,7 +105,7 @@ void testExecute_counter() throws Exception {
/** Tests callbacks: get_tx_context_fn */
@Test
void testExecute_returnBlockNumber() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
HostContext context = new TestHostContext();
int BYZANTIUM = 4;
int EVMC_CALL = 0;
Expand Down Expand Up @@ -133,7 +135,7 @@ void testExecute_returnBlockNumber() throws Exception {
/** Tests callbacks: get_tx_context_fn & set_storage_fn */
@Test
void testExecute_saveReturnBlockNumber() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
HostContext context = new TestHostContext();
int BYZANTIUM = 4;
int EVMC_CALL = 0;
Expand Down Expand Up @@ -165,7 +167,7 @@ void testExecute_saveReturnBlockNumber() throws Exception {
/** Tests callbacks: call_fn */
@Test
void testExecute_makeCall() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
HostContext context = new TestHostContext();
int BYZANTIUM = 4;
int EVMC_CALL = 0;
Expand Down Expand Up @@ -203,7 +205,7 @@ void testExecute_makeCall() throws Exception {

@Test
void testExecute_EVMC_CREATE() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
HostContext context = new TestHostContext();
int BYZANTIUM = 4;
int EVMC_CREATE = 3;
Expand Down Expand Up @@ -231,15 +233,15 @@ void testExecute_EVMC_CREATE() throws Exception {

@Test
void testGetCapabilities() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
int capabilities = vm.get_capabilities();
assert (capabilities > 0);
}
}

@Test
void testSetOption() throws Exception {
try (EvmcVm vm = EvmcVm.create(System.getProperty("user.dir") + "/../c/build/example_vm.so")) {
try (EvmcVm vm = EvmcVm.create(exampleVmPath)) {
int result = vm.set_option("verbose", "1");
assert (result == 0);
}
Expand Down
11 changes: 9 additions & 2 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,6 @@ jobs:
build-cmake-min:
docker:
- image: circleci/buildpack-deps:bionic
environment:
CMAKE_OPTIONS: -DHUNTER_RUN_UPLOAD=NO
steps:
- run:
name: "Install default CMake"
Expand Down Expand Up @@ -270,8 +268,17 @@ jobs:
bindings-java:
docker:
- image: circleci/openjdk:13-buster
environment:
CMAKE_OPTIONS: -DEVMC_JAVA=ON
steps:
- run:
name: "Install CMake"
command: |
sudo apt -qq update
sudo apt -yq install cmake
- checkout
- build
- test
- run:
name: "Java Build"
command: |
Expand Down

0 comments on commit 66f6428

Please sign in to comment.