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"] ] }