-
Notifications
You must be signed in to change notification settings - Fork 64
Description
We worked through moving from netty-tcnative
to ACCP; it wasn't a smooth path, and still has a few rough edges.
For Netty TcNative we had pulled in the native dependencies via build.gradle.kts as:
val nettyTcnativeClassifiers = setOf("osx-aarch_64", "osx-x86_64","linux-aarch_64", "linux-x86_64", "windows-x86_64")
nettyTcnativeClassifiers.forEach { tcNativeClassifier ->
runtimeOnly("io.netty:netty-tcnative-boringssl-static") { artifact { classifier = tcNativeClassifier } }
}
Key points:
- the classifiers is the set of all deployment and development classifiers;
- the scope is
runtimeOnly
as the native libraries only need to be pulled in at runtime; - the dependency version is resolved via Netty BOM (in this case, via Spring Boot), preventing version mismatch between native dependencies and their Java peers;
Netty has collaborating components - code in Netty itself and these optional dependencies - making it smart enough to attempt to load the (optional) native library for the current platform. For example, libnetty_tcnative_osx_aarch_64.jnilib
is included in the osx-aarch_64
classifier. Note that the library name includes the platform information.
We played with a few options for ACCP:
- Create an Uber JAR (combining the JARs for different classifiers that are identical other than their included native library). This had challenges:
- breaks the JAR signing (only for Oracle JDK, not material for us);
- collisions in native library names as they don't include platform information, e.g.
libamazonCorrettoCryptoProvider.dylib
is the same name for x86_64 and aarch64 variants;
That was a non-starter.
- Put logic in
build.gradle.kts
to account for development and deployment requirements:
// we currently deploy on AMD64 architecture
val accpDeploymentClassifier = "linux-x86_64"
val accpClassifier =
when {
System.getenv("CI") == "true" -> accpDeploymentClassifier
// accp does not have a windows artifact; use the deployment classifier so we don't have
// resolution / compilation issues, but don't initialize in code
osdetector.os == "windows" -> accpDeploymentClassifier
// run locally (likely MacOS)
else -> osdetector.classifier
}
implementation(libs.amazonCorrettoCryptoProvider) { artifact { classifier = accpClassifier } }
This works but isn't equivalent to what we had with Netty:
- its considerably more verbose;
- it hard-codes the deployment target architecture (no where else do we have that), as only a single ACCP library can be included; this precludes using the same build in different deployment targets;
- ACCP needs to be a compile-time dependency (due to the intialization steps), however there is no ACCP library for Windows, so we hack around that;
- it requires the OS Detector plugin (that we otherwise have never needed to use)
Ideally ACCP would support something like:
// BOM to keep versions aligned
implementation(platform("software.amazon.cryptools:AmazonCorrettoCryptoProvider-bom:2.4.1"))
// the Java classes
implementation("software.amazon.cryptools:AmazonCorrettoCryptoProvider-core")
// all native dependencies (a JAR that depends on all the individual native jars to pull them all in)
runtimeOnly("software.amazon.cryptools:AmazonCorrettoCryptoProvider-native-all")
// or, for those that wish to selectively pull in platform dependencies
runtimeOnly("software.amazon.cryptools:AmazonCorrettoCryptoProvider-native") { artifact { classifier = "linux-x86_64" } }
Aware that ACCP can be deployed out-of-band (into the class path, or installed in the JDK) but that poses additional complexities:
- its uncommon to drop libs in the class path at deployment time (we have no other apps that do this, and frown on the practice) - why would this lib require that?
- the challenges in versioning / resolving / managing deployment outside of the regular build process are problematic;
Perhaps similar to #366, with more color.