ANTHony
- A C-compatible API for loading and running a Maven/Gradle-based Java/Kotlin project, capturing stdout/stderr and the exit code, with support for environment variables, JVM args, Gradle options, and an optional per-run timeout.
- Two backends:
- Gradle Tooling API (default) — embeds a JVM in-process and drives the
build through the official
org.gradle:gradle-tooling-api, wrapper-aware and version-independent. gradlewsubprocess — a fallback used automatically when the Tooling API is unavailable (no JDK, no bridge jar) but agradlewwrapper exists.
- Gradle Tooling API (default) — embeds a JVM in-process and drives the
build through the official
The public API lives in headers/ANTHony/GradleRunner.h. It exposes an opaque
GradleRunner handle plus the following functions:
gradle_runner_create/gradle_runner_destroygradle_runner_run_task(task, extra args, timeout, stdout/stderr/exit code)gradle_runner_set_env,gradle_runner_add_jvm_arg,gradle_runner_add_gradle_optgradle_runner_set_java_home,gradle_runner_set_bridge_jar,gradle_runner_cancelgradle_runner_set_android_sdk,gradle_runner_set_signing_config,gradle_runner_find_apk,gradle_runner_find_aabgradle_runner_free_string,gradle_runner_error_string
A minimal C++ usage example:
#include "ANTHony/GradleRunner.h"
GradleRunner *runner = gradle_runner_create("/path/to/project");
gradle_runner_set_bridge_jar(runner, "/path/to/gradle-runner-bridge.jar");
char *out = nullptr;
char *err = nullptr;
int exitCode = 0;
GradleRunnerError rc = gradle_runner_run_task(
runner, "build", nullptr, 0, 0, &out, &err, &exitCode);
if (rc == GRADLE_RUNNER_OK) {
// use out / err / exitCode
}
gradle_runner_free_string(out);
gradle_runner_free_string(err);
gradle_runner_destroy(runner);See examples/simple/main.cpp for a complete runnable example.
The library can build Android projects programmatically. Android builds are
ordinary Gradle builds driven by the Android Gradle Plugin, so any task
(assembleDebug, assembleRelease, bundleRelease, test, ...) works through
gradle_runner_run_task. Build variants and flavors are selected by task name
(e.g. assemble<Flavor><BuildType>).
GradleRunner *runner = gradle_runner_create("/path/to/android/project");
gradle_runner_set_bridge_jar(runner, "/path/to/gradle-runner-bridge.jar");
gradle_runner_set_android_sdk(runner, "/path/to/Android/sdk");
char *out = nullptr, *err = nullptr;
int exitCode = 0;
GradleRunnerError rc = gradle_runner_run_task(
runner, "assembleDebug", nullptr, 0, 0, &out, &err, &exitCode);
char *apk = nullptr;
gradle_runner_find_apk(runner, &apk); // newest *.apk under build outputs
gradle_runner_find_aab(runner, &aab); // newest *.aab under build outputs
gradle_runner_free_string(apk);
gradle_runner_free_string(out);
gradle_runner_free_string(err);
gradle_runner_destroy(runner);gradle_runner_set_android_sdksetsANDROID_HOME/ANDROID_SDK_ROOT(the non-invasive alternative tolocal.properties).gradle_runner_set_signing_configinjects the AGPandroid.injected.signing.*properties for release signing without editing the project's build files.gradle_runner_find_apk/gradle_runner_find_aabreturn the newest build artifact by modification time.
See examples/android/main.cpp for a complete runnable example.
The Tooling API backend needs a small Java bridge packaged as a fat jar. The
bridge is a Gradle project (generated with gradle init) under java/, with a
committed gradlew wrapper. Build it with:
cd java
./gradlew fatJar
# produces java/lib/build/libs/gradle-runner-bridge.jarThe C++ library locates the bridge jar via gradle_runner_set_bridge_jar(), or
by searching gradle-runner-bridge.jar,
java/lib/build/libs/gradle-runner-bridge.jar, and
../java/lib/build/libs/gradle-runner-bridge.jar relative to the working
directory. A CMake convenience target is also available:
cmake --build build --target gradle_runner_bridgeThe embedded JVM is located from, in order: gradle_runner_set_java_home(),
the JAVA_HOME environment variable, /usr/libexec/java_home (macOS), then
java on PATH. The Gradle daemon forked by the Tooling API must run on a
Java version supported by the target Gradle version (e.g. Java 17–24 for Gradle
9.x).
ANTHony is a library; it is consumed by an application (such as XIDER) that provides a platform implementation. A minimal setup selects one backend and one platform:
cmake -S . -B build
cmake --build build- CMake 3.10+
- A C++20 compiler
- A JDK (for the Tooling API backend;
-DANTHONY_USE_TOOLING_API=OFFto build without it) - Doxygen + Graphviz (only for
-DBUILD_DOCS=ON)
Select exactly one backend and one platform:
cmake -S . -B build \
-DBUILD_TESTING=ON
cmake --build build
ctest --test-dir build --output-on-failureOptional options:
-DBUILD_TESTING=ON— build and run the test suite.-DBUILD_DOCS=ON— build Doxygen documentation.-DBUILD_BENCHMARKS=ON— build the benchmark harness.-DANTHONY_USE_TOOLING_API=OFF— disable the JNI/Tooling API backend and use only thegradlewsubprocess fallback.
Once installed, downstream projects can use find_package(anthony):
cmake --install build --prefix /path/to/prefixfind_package(anthony REQUIRED)
target_link_libraries(my_app PRIVATE anthony::anthony)- How ANTHony Works
- Architecture
- Getting Started
- Versioning & Support
- Technical Choices
- Code Conventions
- Commit Conventions
We welcome contributions from the community! If you're interested in contributing to ANTHony, please check out our Contributing Guidelines for more information on how to get involved.
ANTHony is released under the MIT License. See CODE_OF_CONDUCT.md for our community standards and SECURITY.md for reporting vulnerabilities.