Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

building static libraries with shared library wrapper #105

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[submodule "external/monero-cpp"]
path = external/monero-cpp
url = https://github.com/woodser/monero-cpp
url = https://github.com/nsec1/monero-cpp.git
branch = buildStaticOption
Copy link
Owner

@woodser woodser Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this branch be removed? We can assume your PR to monero-cpp is applied during the build process (as all PRs will be accepted at once).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it can. It just makes tests easier. I will do this.

227 changes: 200 additions & 27 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ project(monero-java-jni)
#############

set(MONERO_CPP "${CMAKE_SOURCE_DIR}/external/monero-cpp")
message(STATUS MONERO_CPP : ${MONERO_CPP} : ${MONERO_CPP})
message(STATUS MONERO_CPP : ${MONERO_CPP})

set(MONERO_CPP_SRC "${MONERO_CPP}/src")
set(MONERO_PROJECT ${MONERO_CPP}/external/monero-project)
set(MONERO_PROJECT_SRC "${MONERO_PROJECT}/src")

list(APPEND CMAKE_MODULE_PATH "${MONERO_PROJECT}/cmake")
list(APPEND CMAKE_MODULE_PATH "${MONERO_CPP}/cmake")

# check JAVA_HOME
if(NOT DEFINED ENV{JAVA_HOME} OR "$ENV{JAVA_HOME}" STREQUAL "")
message(FATAL_ERROR "JAVA_HOME variable not set, for example: export JAVA_HOME=/path/to/jdk")
Expand Down Expand Up @@ -57,49 +60,193 @@ message(STATUS EXTRA_LIBRARIES: ${EXTRA_LIBRARIES})
set(Boost_NO_BOOST_CMAKE 1)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost 1.58 QUIET REQUIRED COMPONENTS chrono date_time filesystem program_options regex serialization wserialization system thread)
message(STATUS "Using Boost include dir at ${Boost_INCLUDE_DIR}")

if(Boost_FOUND)
message(STATUS "Using Boost include dir at ${Boost_INCLUDE_DIR}")
message(STATUS "Using Boost lib version: ${Boost_LIB_VERSION}")
message(STATUS "Using Boost libs: ${Boost_LIBRARIES}")
endif()

############
# OpenSSL
############

if (APPLE AND NOT IOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -std=c++14")
if (NOT OPENSSL_ROOT_DIR)
EXECUTE_PROCESS(COMMAND brew --prefix openssl
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "Using OpenSSL found at ${OPENSSL_ROOT_DIR}")
find_package(OpenSSL REQUIRED)

if (WIN32)
list(APPEND OPENSSL_LIBRARIES ws2_32 crypt32 bcrypt)
endif()

if(OPENSSL_FOUND)
message(STATUS "Using OpenSSL include dir at ${OPENSSL_INCLUDE_DIR}")
message(STATUS "Using OpenSSL libs: ${OPENSSL_LIBRARIES}")
endif()

############
# libsodium
############

find_library(SODIUM_LIBRARY sodium REQUIRED)
if(SODIUM_LIBRARY)
message(STATUS "Using libsodium library at ${SODIUM_LIBRARY}")
find_path(SODIUM_INCLUDE_PATH sodium/crypto_verify_32.h)
if (SODIUM_INCLUDE_PATH)
message(STATUS "SODIUM_INCLUDE_PATH: ${SODIUM_INCLUDE_PATH}")
else()
message(FATAL_ERROR "Could not find required sodium/crypto_verify_32.h")
endif()
endif()

find_package(OpenSSL REQUIRED)
message(STATUS "Using OpenSSL include dir at ${OPENSSL_INCLUDE_DIR}")
############
# HIDAPI
############

if(STATIC AND NOT IOS)
if(UNIX)
set(OPENSSL_LIBRARIES "${OPENSSL_LIBRARIES};${CMAKE_DL_LIBS};${CMAKE_THREAD_LIBS_INIT}")
option(USE_DEVICE_TREZOR "Trezor hardware wallet suport" ON)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get linker errors building with USE_DEVICE_TREZOR=OFF related to HIDAPI.

Can we remove this conditional and always find the package?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nsec1 any response?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@woodser other than this comment, is this PR ready to merge?

if (USE_DEVICE_TREZOR)
if(APPLE)
include_directories(SYSTEM /usr/include/malloc)
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif()
endif()

find_package(HIDAPI REQUIRED)
message(STATUS "Using HIDAPI include dir at ${HIDAPI_INCLUDE_DIR}")
add_definitions(-DHAVE_HIDAPI)
else()
message(STATUS "Trezor support disabled by USE_DEVICE_TREZOR")
endif()

if (WIN32)
list(APPEND OPENSSL_LIBRARIES ws2_32 crypt32 bcrypt)

#############
# Monero
#############

set(MONERO_PROJECT_BUILD "${MONERO_PROJECT}/build/release" CACHE STRING "Monero project build directory")
message(STATUS "Using monero-project build: " ${MONERO_PROJECT_BUILD})

list(APPEND CMAKE_MODULE_PATH "${MONERO_PROJECT}/cmake")

add_library(wallet STATIC IMPORTED)
set_target_properties(wallet PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/lib/libwallet.a)

# libwallet-crypto.a provides x86_64 asm for some wallet functions
if (EXISTS ${MONERO_PROJECT_BUILD}/src/crypto/wallet/libwallet-crypto.a)
add_library(wallet_crypto_lib STATIC IMPORTED)
set_target_properties(wallet_crypto_lib PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/crypto/wallet/libwallet-crypto.a)
set(wallet_crypto wallet_crypto_lib)
endif()

add_library(lmdb STATIC IMPORTED)
set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/external/db_drivers/liblmdb/liblmdb.a)

add_library(epee STATIC IMPORTED)
set_target_properties(epee PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/contrib/epee/src/libepee.a)

add_library(rpc_base STATIC IMPORTED)
set_target_properties(rpc_base PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/rpc/librpc_base.a)

add_library(net STATIC IMPORTED)
set_target_properties(net PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/net/libnet.a)

add_library(hardforks STATIC IMPORTED)
set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/hardforks/libhardforks.a)

add_library(easylogging STATIC IMPORTED)
set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/external/easylogging++/libeasylogging.a)

add_library(cryptonote_core STATIC IMPORTED)
set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/cryptonote_core/libcryptonote_core.a)

add_library(cryptonote_basic STATIC IMPORTED)
set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/cryptonote_basic/libcryptonote_basic.a)

add_library(cryptonote_format_utils_basic STATIC IMPORTED)
set_target_properties(cryptonote_format_utils_basic PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/cryptonote_basic/libcryptonote_format_utils_basic.a)

add_library(mnemonics STATIC IMPORTED)
set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/mnemonics/libmnemonics.a)

add_library(common STATIC IMPORTED)
set_target_properties(common PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/common/libcommon.a)

add_library(cncrypto STATIC IMPORTED)
set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/crypto/libcncrypto.a)

add_library(ringct STATIC IMPORTED)
set_target_properties(ringct PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/ringct/libringct.a)

add_library(ringct_basic STATIC IMPORTED)
set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/ringct/libringct_basic.a)

add_library(blockchain_db STATIC IMPORTED)
set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/blockchain_db/libblockchain_db.a)

add_library(blocks STATIC IMPORTED)
set_target_properties(blocks PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/blocks/libblocks.a)

add_library(checkpoints STATIC IMPORTED)
set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/checkpoints/libcheckpoints.a)

add_library(device STATIC IMPORTED)
set_target_properties(device PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/device/libdevice.a)

add_library(device_trezor STATIC IMPORTED)
set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/device_trezor/libdevice_trezor.a)

add_library(multisig STATIC IMPORTED)
set_target_properties(multisig PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/multisig/libmultisig.a)

add_library(version STATIC IMPORTED)
set_target_properties(version PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/src/libversion.a)

add_library(randomx STATIC IMPORTED)
set_target_properties(randomx PROPERTIES IMPORTED_LOCATION
${MONERO_PROJECT_BUILD}/external/randomx/librandomx.a)

############
# Unbound
############

find_library(UNBOUND_LIBRARIES libunbound.a) # LD_LIBRARY_PATH
if(UNBOUND_LIBRARIES)
message(STATUS "Found libunbound library: ${UNBOUND_LIBRARIES}")
endif()

######################
# monero-cpp
######################

add_library(monero-cpp SHARED IMPORTED)
add_library(monero-cpp STATIC IMPORTED)

# import shared c++ library
if (APPLE)
set_target_properties(monero-cpp PROPERTIES IMPORTED_LOCATION ./libmonero-cpp.dylib)
elseif (WIN32)
set_target_properties(monero-cpp PROPERTIES IMPORTED_LOCATION ./libmonero-cpp.dll)
set_target_properties(monero-cpp PROPERTIES IMPORTED_IMPLIB ./libmonero-cpp.dll.a)
# import static c++ library
if (WIN32)
set_target_properties(monero-cpp PROPERTIES IMPORTED_LOCATION ./libmonero-cpp.lib)
else()
set_target_properties(monero-cpp PROPERTIES IMPORTED_LOCATION ./libmonero-cpp.so)
set_target_properties(monero-cpp PROPERTIES IMPORTED_LOCATION ./libmonero-cpp.a)
endif()

###############################################
Expand All @@ -115,20 +262,19 @@ add_library(monero-java SHARED ${MONERO_JNI_SRC_FILES})
target_include_directories(monero-java PUBLIC
"$ENV{JAVA_HOME}"
"$ENV{JAVA_HOME}/include"
"${MONERO_CPP}/external/libsodium/include/sodium"
"${MONERO_CPP}/external/openssl-sdk/include"
"${MONERO_CPP_SRC}/"
"${MONERO_PROJECT}/contrib/epee/include"
"${MONERO_PROJECT}/external/"
"${MONERO_PROJECT}/external/easylogging++"
"${MONERO_PROJECT}/external/rapidjson/include"
"${MONERO_PROJECT_SRC}/"
"${MONERO_PROJECT_SRC}/crypto"
"${MONERO_PROJECT_SRC}/crypto/crypto_ops_builder/include/"
"${MONERO_PROJECT_SRC}/wallet"
"${MONERO_PROJECT_SRC}/wallet/api"
${SODIUM_INCLUDE_PATH}
${Boost_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIR}
${HIDAPI_INCLUDE_DIR}
)

if (APPLE)
Expand All @@ -141,8 +287,35 @@ endif()

target_link_libraries(monero-java
monero-cpp
wallet
rpc_base
net
lmdb
easylogging
cryptonote_core
cryptonote_basic
cryptonote_format_utils_basic
mnemonics
ringct
ringct_basic
common
cncrypto
blockchain_db
blocks
checkpoints
device
device_trezor
multisig
version
randomx
epee
hardforks
${wallet_crypto}
${UNBOUND_LIBRARIES}
${Boost_LIBRARIES}
${OPENSSL_LIBRARIES}
${SODIUM_LIBRARY}
${HIDAPI_LIBRARIES}
${EXTRA_LIBRARIES}
)

Expand Down
28 changes: 17 additions & 11 deletions bin/build_libmonero_java.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@

#EMCC_DEBUG=1

HOST_NCORES=$(nproc 2>/dev/null || shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1)
export HOST_NCORES=${HOST_NCORES-$(nproc 2>/dev/null || shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1)}
BUILD_DIR="$(pwd)/build"
export CMAKE_PREFIX_PATH="$(pwd)/external/monero-cpp/build/install"${CMAKE_PREFIX_PATH+:$CMAKE_PREFIX_PATH}
export USE_DEVICE_TREZOR=OFF
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove this or does it cause a problem on your system?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

echo "HOST_NCORES=$HOST_NCORES in $0"
echo "CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH in $0"
echo "USE_DEVICE_TREZOR=$USE_DEVICE_TREZOR in $0"

# build libmonero-cpp shared library
cd ./external/monero-cpp/ &&
./bin/build_libmonero_cpp.sh &&
[ -d $BUILD_DIR ] || mkdir -p $BUILD_DIR

# copy libmonero-cpp shared library to ./build
cd ../../ &&
mkdir -p ./build &&
cp ./external/monero-cpp/build/libmonero-cpp.* ./build &&
# build libmonero-cpp static library
(cd ./external/monero-cpp/ && \
./bin/build_libmonero_cpp.sh -DSTATIC=ON) && \

# copy libmonero-cpp static library to ./build
cp ./external/monero-cpp/build/libmonero-cpp.* $BUILD_DIR && \

# build libmonero-java shared library to ./build
cd build &&
cmake .. &&
cd $BUILD_DIR && \
cmake -D USE_DEVICE_TREZOR=$USE_DEVICE_TREZOR .. && \
cmake --build . -j$HOST_NCORES &&
make .
make -j$HOST_NCORES .
11 changes: 3 additions & 8 deletions src/main/java/monero/common/MoneroUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,18 @@ public static void loadNativeLibrary() {

// get library file names and paths
String libraryPath = "/";
String libraryCppFile = null;
String libraryJavaFile = null;
if (osName.contains("windows")) {
libraryPath += "windows/";
libraryFiles = new String[] { "libmonero-cpp.dll", "libmonero-cpp.dll.a", "libmonero-java.dll", "libmonero-java.dll.a" };
libraryCppFile = "libmonero-cpp.dll";
libraryFiles = new String[] { "libmonero-java.dll", "libmonero-java.dll.a" };
libraryJavaFile = "libmonero-java.dll";
} else if (osName.contains("linux")) {
libraryPath += osArch.contains("aarch64") ? "linux-arm64/" : "linux-x86_64/";
libraryFiles = new String[] { "libmonero-cpp.so", "libmonero-java.so" };
libraryCppFile = "libmonero-cpp.so";
libraryFiles = new String[] { "libmonero-java.so" };
libraryJavaFile = "libmonero-java.so";
} else if (osName.contains("mac")) {
libraryPath += osArch.contains("aarch64") ? "mac-arm64/" : "mac-x86_64/";
libraryFiles = new String[] { "libmonero-cpp.dylib", "libmonero-java.dylib" };
libraryCppFile = "libmonero-cpp.dylib";
libraryFiles = new String[] { "libmonero-java.dylib" };
libraryJavaFile = "libmonero-java.dylib";
} else {
throw new MoneroError("Unsupported operating system: " + osName);
Expand All @@ -111,7 +107,6 @@ public static void loadNativeLibrary() {
}

// load native libraries
System.load(tempDir.resolve(libraryCppFile).toString());
System.load(tempDir.resolve(libraryJavaFile).toString());
} catch (Exception | UnsatisfiedLinkError e) {
throw new MoneroError(e);
Expand Down