Skip to content
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
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ endif()
include(GNUInstallDirs)

option(LIBCDOC_WITH_DOCS "Generate documentation with Doxygen" ON)
option(SKIP_JAVA_TESTS "Skip Java tests (useful when cross-compiling)" OFF)

find_package(OpenSSL 3.0.0 REQUIRED)
find_package(ZLIB REQUIRED)
Expand Down Expand Up @@ -69,6 +70,13 @@ if(LIBCDOC_WITH_DOCS)
endif()

add_subdirectory(cdoc)
# Binary dir of the cdoc sub-build; used by examples/CMakeLists.txt to locate
# the SWIG-generated Java bindings. Correct also when libcdoc is included as
# a subproject of a larger build.
set(CDOC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/cdoc)
if(NOT SKIP_JAVA_TESTS)
add_subdirectory(examples)
endif()

find_package(Boost COMPONENTS unit_test_framework QUIET)
if (TARGET Boost::unit_test_framework)
Expand Down
3 changes: 2 additions & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@
"cacheVariables": {
"CMAKE_SYSTEM_NAME": "Android",
"CMAKE_SYSTEM_VERSION": "30",
"BUILD_SHARED_LIBS": "NO"
"BUILD_SHARED_LIBS": "NO",
"SKIP_JAVA_TESTS": "YES"
}
},
{
Expand Down
6 changes: 4 additions & 2 deletions cdoc/CDocCipher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,9 @@ int CDocCipher::writer_push(CDocWriter& writer, const vector<Recipient>& rcpts,
int64_t result = writer.beginEncryption();
if (result != libcdoc::OK) return result;
for (const std::string& file : files) {
std::filesystem::path path(file);
// The string is UTF-8; construct the path from u8string so that
// Windows interprets it as UTF-8 rather than the active code page.
std::filesystem::path path(std::u8string(reinterpret_cast<const char8_t*>(file.data()), file.size()));
if (!std::filesystem::exists(path)) {
LOG_ERROR("File does not exist: {}", file);
return 1;
Expand Down Expand Up @@ -519,7 +521,7 @@ int CDocCipher::Decrypt(const unique_ptr<CDocReader>& rdr, unsigned int lock_idx
LOG_ERROR("Error on extracting FMK: {} {}", result, rdr->getLastErrorStr());
return 1;
}
filesystem::path base_path(base_pathname);
filesystem::path base_path(std::u8string(reinterpret_cast<const char8_t*>(base_pathname.data()), base_pathname.size()));

/* Do pull */
result = rdr->beginDecryption(fmk);
Expand Down
74 changes: 74 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Java example (CDocTool) built with the Gradle wrapper in examples/java.
#
# The example compiles against the SWIG-generated Java bindings produced by
# the cdoc_java target. It is added to the default build only when:
# * SWIG was found and the cdoc_java target exists, and
# * a Java Development Kit was found (Java_Development_FOUND), and
# * the Gradle wrapper script is present in the source tree, and
# * LIBCDOC_BUILD_JAVA_EXAMPLE is ON (default).
#
# The Gradle invocation is given absolute paths to the SWIG Java sources and
# the JNI library of the current build, so no manual configuration is needed.

set(JAVA_EXAMPLE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/java)

if(WIN32)
set(GRADLE_WRAPPER ${JAVA_EXAMPLE_DIR}/gradlew.bat)
else()
set(GRADLE_WRAPPER ${JAVA_EXAMPLE_DIR}/gradlew)
endif()

if(NOT EXISTS ${GRADLE_WRAPPER})
message(STATUS "Gradle wrapper not found in ${JAVA_EXAMPLE_DIR} - skipping Java example")
return()
endif()

if(NOT TARGET cdoc_java)
message(STATUS "cdoc_java target not available - skipping Java example")
return()
endif()

if(NOT Java_Development_FOUND)
message(STATUS "Java Development Kit not found - skipping Java example")
return()
endif()

option(LIBCDOC_BUILD_JAVA_EXAMPLE "Build the Java CDocTool example with Gradle" ON)
if(NOT LIBCDOC_BUILD_JAVA_EXAMPLE)
return()
endif()

# Directory containing the SWIG-generated .java files (OUTPUT_DIR of
# swig_add_library in cdoc/CMakeLists.txt). CDOC_BINARY_DIR is set by the
# parent CMakeLists.txt right after add_subdirectory(cdoc); fall back to the
# conventional location if this file is used standalone.
if(NOT CDOC_BINARY_DIR)
set(CDOC_BINARY_DIR ${CMAKE_BINARY_DIR}/cdoc)
endif()
set(JAVA_EXAMPLE_SWIG_DIR ${CDOC_BINARY_DIR}/java)
set(JAVA_EXAMPLE_JAR ${JAVA_EXAMPLE_DIR}/build/libs/CDocTool.jar)

# When cross-compiling (e.g. Android), the JNI library targets a different
# architecture than the build host, so Java tests cannot load it. Build the
# example jar but skip the tests.
if(SKIP_JAVA_TESTS)
set(GRADLE_SKIP_TESTS -x test)
endif()

add_custom_command(
OUTPUT ${JAVA_EXAMPLE_JAR}
COMMENT "Building Java example (CDocTool.jar) with Gradle"
COMMAND ${GRADLE_WRAPPER}
--info
--no-daemon
-PswigJavaDir=${JAVA_EXAMPLE_SWIG_DIR}
-PjniLibDir=$<TARGET_FILE_DIR:cdoc_java>
build ${GRADLE_SKIP_TESTS}
WORKING_DIRECTORY ${JAVA_EXAMPLE_DIR}
DEPENDS cdoc_java
VERBATIM
)

add_custom_target(cdoc_java_example ALL
DEPENDS ${JAVA_EXAMPLE_JAR}
)
57 changes: 55 additions & 2 deletions examples/java/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,62 @@
# Build instructions for Java

## Build
The Java example (`CDocTool`) compiles against the SWIG-generated Java
bindings produced by the libcdoc CMake build.

## Automatic build (recommended)

When the libcdoc project is configured with SWIG and a JDK available, the
example is built automatically as part of the default CMake build:

cmake --preset macos
cmake --build build/macos

This produces `examples/java/build/libs/CDocTool.jar`. Set
`-DLIBCDOC_BUILD_JAVA_EXAMPLE=OFF` to disable it.

## Manual build

First build the main CMake project so that the SWIG Java bindings and the
JNI library exist, then run the Gradle wrapper:

./gradlew jar

`build.gradle` locates the SWIG-generated sources automatically by scanning
the well-known CMake build directories (`build/<preset>/cdoc/java`). If your
build tree lives elsewhere, point the build at it explicitly:

./gradlew jar -PswigJavaDir=/path/to/build/cdoc/java -PjniLibDir=/path/to/build/cdoc

or with environment variables:

LIBCDOC_SWIG_JAVA_DIR=/path/to/build/cdoc/java LIBCDOC_JNI_LIB_DIR=/path/to/build/cdoc ./gradlew jar

## Test

The example has JUnit 5 tests (in `src/test/java`) that run against the
compiled JNI library:

./gradlew test

The CMake-driven build runs the tests automatically (it invokes
`gradlew build`, which includes the `test` task).

## Run

java -Djava.library.path=/some/path/lib -jar build/libs/CDocTool.jar
./gradlew run

or directly:

java -jar build/libs/CDocTool.jar

The JNI library built by the CMake project is located automatically. The
resolution order is:

1. `--library <file>` command line argument
2. `-Dcdoc.library=<file>` system property
3. `ee/ria/cdoc/jni.properties` baked into the jar by Gradle (records the
JNI library directory at build time)
4. Well-known CMake build directories (`build/<preset>/cdoc`) relative to
the working directory
5. `java.library.path` (set by `./gradlew run`, or pass
`-Djava.library.path=/path/to/build/cdoc` to `java`)
Loading
Loading