description = 'Conscrypt: OpenJdk'
ext {
jniSourceDir = "$rootDir/common/src/jni"
assert file("$jniSourceDir").exists()
// Build the list of classifiers that will be used in the build.
arch32Name = 'x86'
arch64Name = 'x86_64'
// Allow the java executable to be specified via env/property for each architecture.
javaExecutable32 = properties['javaExecutable32'] ?: System.env.CONSCRYPT_JAVA_EXECUTABLE_32
javaExecutable64 = properties['javaExecutable64'] ?: System.env.CONSCRYPT_JAVA_EXECUTABLE_64
nativeClassifiers = []
if (build64Bit) {
// Add the 64-Bit classifier first, as the preferred classifier.
nativeClassifiers += classifierFor(osName, arch64Name)
}
if (build32Bit) {
nativeClassifiers += classifierFor(osName, arch32Name)
}
// Create a "preferred" configuration that can be used by other modules (e.g. tests/benchmarks)
preferredNativeConfiguration = normalizeClassifier(nativeClassifiers[0])
}
sourceSets {
main {
java {
srcDirs += "${rootDir}/common/src/main/java"
srcDirs += project(':conscrypt-constants').sourceSets.main.java.srcDirs
}
}
}
configurations {
publicApiDocs
}
// Append the BoringSSL-Version to the manifest.
jar.manifest {
attributes 'BoringSSL-Version' : boringSslVersion
}
dependencies {
// This is used for the @hide annotation processing in JavaDoc
publicApiDocs project(':conscrypt-api-doclet')
compileOnly project(':conscrypt-constants')
testCompile project(':conscrypt-constants'),
project(':conscrypt-testing'),
libraries.junit,
libraries.mockito
}
javadoc {
options.doclet = "org.conscrypt.doclet.FilterDoclet"
options.docletpath = configurations.publicApiDocs.files as List
}
/**
* Create Jar and Test tasks for each native classifier.
*/
nativeClassifiers.each { nativeClassifier ->
// Create all native configurations
addNativeSourceSet(nativeClassifier)
addNativeSourceSet("${nativeClassifier}Test")
// Create the JAR task and add it's output to the published archives for this project
addNativeJar(nativeClassifier)
// Create the test task and have it auto run whenever the test task runs.
addNativeTest(nativeClassifier)
}
def nativeFileDir(nativeClassifier) {
def normalizedClassifier = normalizeClassifier(nativeClassifier)
"${buildDir}/${normalizedClassifier}/resources/main"
}
// Creates a source set (and resulting configurations) containing only the
// native shared library.
def addNativeSourceSet(nativeClassifier) {
def normalizedClassifier = normalizeClassifier(nativeClassifier)
// Create a configuration which will contain the artifact.
configurations.create(normalizedClassifier)
// Create a new source set. This will automatically create configurations for:
// ${normalizedClassifier}Compile
// ${normalizedClassifier}Runtime
def sources = sourceSets.create(normalizedClassifier)
sources.resources {
srcDirs += files(nativeFileDir(nativeClassifier))
}
}
// Adds a JAR task for the native library.
def addNativeJar(nativeClassifier) {
def normalizedClassifier = normalizeClassifier(nativeClassifier)
// Create a JAR for this configuration and add it to the output archives.
def jarTaskName = "create${normalizedClassifier}Jar"
// The testRuntime configuration is created automatically when we created the source set.
def testRuntimeConfigName = "${normalizedClassifier}TestRuntime"
task "$jarTaskName"(type: Jar) {
dependsOn classes
dependsOn configurations[testRuntimeConfigName]
from sourceSets.main.output + files(nativeFileDir(nativeClassifier))
manifest = jar.manifest
classifier = nativeClassifier
}
// Add it to the 'archives' configuration so that the artifact will be automatically built and
// installed/deployed.
artifacts.add('archives', tasks["$jarTaskName"])
// Also add the artifact to its own configuration so that it can be referenced from other projects.
artifacts.add(normalizedClassifier, tasks["$jarTaskName"])
}
// Optionally adds a test task for the given platform
def addNativeTest(nativeClassifier) {
def normalizedClassifier = normalizeClassifier(nativeClassifier)
def testTaskName = "${normalizedClassifier}Test"
def javaExecutable
def javaArchFlag
if (normalizedClassifier.endsWith(arch32Name)) {
// 32-bit test
javaExecutable = javaExecutable32 != null ? javaExecutable32 : test.executable
javaArchFlag = '-d32'
} else {
// 64-bit test
javaExecutable = javaExecutable64 != null ? javaExecutable64 : test.executable
javaArchFlag = '-d64'
}
// Execute the java executable to see if it supports the architecture flag.
def javaError = new ByteArrayOutputStream()
exec {
executable javaExecutable
args = ["$javaArchFlag", '-version']
ignoreExitValue true
errorOutput = javaError
}
// Only add the test if the javaArchFlag is supported for the selected JVM
def archSupported = !javaError.toString().toLowerCase().contains('error')
if (archSupported) {
task "$testTaskName"(type: Test) {
testClassesDir = test.testClassesDir
classpath = test.classpath + files(nativeFileDir(nativeClassifier))
jvmArgs javaArchFlag
executable = javaExecutable
}
test.dependsOn "$testTaskName"
}
}
// Exclude all test classes from the default test suite.
// We will test each available native artifact separately (see nativeClassifiers).
test.exclude("**")
model {
platforms {
x86 {
architecture arch32Name
}
x86_64 {
architecture arch64Name
}
}
buildTypes {
release
}
components {
// Builds the JNI library.
conscrypt_openjdk_jni(NativeLibrarySpec) {
if (build32Bit) { targetPlatform arch32Name }
if (build64Bit) { targetPlatform arch64Name }
sources {
cpp {
source {
srcDirs "$jniSourceDir/main/cpp"
include "**/*.cpp"
}
}
}
binaries {
// Build the JNI lib as a shared library.
withType (SharedLibraryBinarySpec) {
cppCompiler.define "CONSCRYPT_OPENJDK"
// Set up 32-bit vs 64-bit build
def libPath
if (targetPlatform.getArchitecture().getName() == "x86") {
libPath = "$boringssl32BuildDir"
} else if (targetPlatform.getArchitecture().getName() == "x86-64") {
libPath = "$boringssl64BuildDir"
} else {
throw new GradleException("Unknown architecture: " +
targetPlatform.getArchitecture().name)
}
if (toolChain in Clang || toolChain in Gcc) {
cppCompiler.args "-Wall",
"-fPIC",
"-O2",
"-std=c++11",
"-I$jniSourceDir/main/include",
"-I$jniSourceDir/unbundled/include",
"-I$boringsslIncludeDir",
"-I$jdkIncludeDir",
"-I$jdkIncludeDir/linux",
"-I$jdkIncludeDir/darwin",
"-I$jdkIncludeDir/win32"
// Static link to BoringSSL
linker.args "-O2",
"-fvisibility=hidden",
"-lstdc++",
libPath + "/ssl/libssl.a",
libPath + "/crypto/libcrypto.a"
} else if (toolChain in VisualCpp) {
cppCompiler.define "DLL_EXPORT"
cppCompiler.define "WIN32_LEAN_AND_MEAN"
cppCompiler.define "WIN64"
cppCompiler.define "_WINDOWS"
cppCompiler.define "UNICODE"
cppCompiler.define "_UNICODE"
cppCompiler.define "NDEBUG"
cppCompiler.args "/nologo",
"/MT",
"/WX-",
"/Wall",
"/O2",
"/Oi",
"/Ot",
"/GL",
"/GS",
"/Gy",
"/fp:precise",
"-wd4514", // Unreferenced inline function removed
"-wd4548", // Expression before comma has no effect
"-wd4625", // Copy constructor was implicitly defined as deleted
"-wd4626", // Assignment operator was implicitly defined as deleted
"-wd4710", // function not inlined
"-wd4711", // function inlined
"-wd4820", // Extra padding added to struct
"-wd4946", // reinterpret_cast used between related classes:
"-wd4996", // Thread safety for strerror
"-wd5027", // Move assignment operator was implicitly defined as deleted
"-I$jniSourceDir/main/include",
"-I$jniSourceDir/unbundled/include",
"-I$boringsslIncludeDir",
"-I$jdkIncludeDir",
"-I$jdkIncludeDir/win32"
// Static link to BoringSSL
linker.args "-WX",
"ws2_32.lib",
"advapi32.lib",
libPath + "\\ssl\\ssl.lib",
libPath + "\\crypto\\crypto.lib"
}
}
// Never build a static library.
withType(StaticLibraryBinarySpec) {
buildable = false
}
}
}
}
tasks { t ->
$.binaries.withType(SharedLibraryBinarySpec).each { binary ->
// Build the native artifact classifier from the OS and architecture.
def archName = binary.targetPlatform.architecture.name.replaceAll('-', '_')
def classifier = classifierFor(osName, archName)
def normalizedClassifier = normalizeClassifier("$classifier")
def source = binary.sharedLibraryFile
// Copies the native library to a resource location that will be included in the jar.
def copyTaskName = "copyNativeLib${normalizedClassifier}"
task "$copyTaskName"(type: Copy, dependsOn: binary.buildTask) {
from source
// Rename the artifact to include the generated classifier
rename '(.+)(\\.[^\\.]+)', "\$1-$classifier\$2"
// This location will automatically be included in the jar.
into "${buildDir}/${normalizedClassifier}/resources/main/META-INF/native"
}
// Make sure we build and copy the native library to the output directory.
compileJava.dependsOn "$copyTaskName"
// Now define a task to strip the release binary (linux only)
def stripTask = binary.tasks.taskName("strip")
t.create(stripTask) {
dependsOn binary.tasks.link
doFirst {
if (osName == 'linux') {
["strip", binary.tasks.link.outputFile].execute().waitForOrKill(1000)
}
}
}
binary.tasks.build.dependsOn stripTask
}
}
}
static classifierFor(osName, archName) {
return "${osName}-${archName}"
}
static normalizeClassifier(classifier) {
return classifier.replaceAll("-", "_")
}
// Manually add the native library to help IntelliJ run tests.
idea.module {
scopes.PROVIDED.plus += [ configurations["$preferredNativeConfiguration"] ]
}