blob: 56a2ea8b309642fedaa8f702154178fe30d1b8cd [file] [log] [blame]
plugins {
id 'com.github.johnrengelman.shadow' version '6.0.0'
}
import aQute.bnd.gradle.BundleTaskConvention
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.codehaus.groovy.runtime.InvokerHelper
apply plugin: 'biz.aQute.bnd.builder'
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'
nativeClassifiers = []
nativeClassifier64Bit = null
nativeClassifier32Bit = null
preferredClassifier = null
preferredSourceSet = null
preferredNativeFileDir = null
if (build64Bit) {
// Add the 64-Bit classifier first, as the preferred classifier.
nativeClassifier64Bit = classifierFor(osName, arch64Name)
nativeClassifiers += nativeClassifier64Bit
preferredClassifier = nativeClassifier64Bit
preferredSourceSet = sourceSetName(preferredClassifier)
preferredNativeFileDir = nativeResourcesDir(preferredClassifier)
}
if (build32Bit) {
nativeClassifier32Bit = classifierFor(osName, arch32Name)
nativeClassifiers += nativeClassifier32Bit
if (preferredClassifier == null) {
preferredClassifier = nativeClassifier32Bit
preferredSourceSet = sourceSetName(preferredClassifier)
preferredNativeFileDir = nativeResourcesDir(preferredClassifier)
}
}
}
sourceSets {
main {
java {
srcDirs += "${rootDir}/common/src/main/java"
srcDirs += project(':conscrypt-constants').sourceSets.main.java.srcDirs
}
resources {
srcDirs += "build/generated/resources"
}
}
platform {
java {
srcDirs = [ "src/main/java" ]
includes = [ "org/conscrypt/Platform.java" ]
}
}
test {
java {
srcDirs += "${rootDir}/common/src/test/java"
}
resources {
srcDirs += "${rootDir}/common/src/test/resources"
// This shouldn't be needed but seems to help IntelliJ locate the native artifact.
srcDirs += preferredNativeFileDir
}
}
// Add the source sets for each of the native build
nativeClassifiers.each { nativeClassifier ->
def sourceSetName = sourceSetName(nativeClassifier)
// Main sources for the native build
"$sourceSetName" {
output.dir(nativeResourcesDir(nativeClassifier), builtBy: "copyNativeLib${sourceSetName}")
}
}
}
compileJava {
dependsOn generateProperties
}
tasks.register("platformJar", Jar) {
from sourceSets.platform.output
}
tasks.register("testJar", ShadowJar) {
classifier = 'tests'
configurations = [project.configurations.testRuntime]
from sourceSets.test.output
}
if (isExecutableOnPath('cpplint')) {
def cpplint = tasks.register("cpplint", Exec) {
executable = 'cpplint'
// TODO(nmittler): Is there a better way of getting the JNI sources?
def pattern = ['**/*.cc', '**/*.h']
def sourceFiles = fileTree(dir: jniSourceDir, includes: pattern).asPath.tokenize(':')
// Adding roots so that class #ifdefs don't require full path from the project root.
args = sourceFiles
// Capture stderr from the process
errorOutput = new ByteArrayOutputStream();
// Need to ignore exit value so that doLast will execute.
ignoreExitValue = true
doLast {
// Create the report file.
def reportDir = file("${buildDir}/cpplint")
reportDir.mkdirs();
def reportFile = new File(reportDir, "report.txt")
def reportStream = new FileOutputStream(reportFile)
try {
// Check for failure
if (execResult != null) {
execResult.assertNormalExitValue()
}
} catch (Exception e) {
// The process failed - get the error report from the stderr.
String report = errorOutput.toString();
// Write the report to the console.
System.err.println(report)
// Also write the report file.
reportStream.write(report.bytes);
// Extension method cpplint.output() can be used to obtain the report
ext.output = {
return report
}
// Rethrow the exception to terminate the build.
throw e;
} finally {
reportStream.close();
}
}
}
check.dependsOn cpplint
}
configurations {
publicApiDocs
platform
}
artifacts {
platform platformJar
}
apply from: "$rootDir/gradle/publishing.gradle"
publishing.publications.maven {
artifact sourcesJar
artifact javadocJar
}
jar.manifest {
attributes ('BoringSSL-Version' : boringSslVersion,
'Automatic-Module-Name' : 'org.conscrypt',
'Bundle-SymbolicName': 'org.conscrypt',
'-exportcontents': 'org.conscrypt.*')
}
dependencies {
// This is used for the @Internal annotation processing in JavaDoc
publicApiDocs project(':conscrypt-api-doclet')
// This is listed as compile-only, but we absorb its contents.
compileOnly project(':conscrypt-constants')
testCompile project(':conscrypt-constants'),
project(path: ':conscrypt-testing', configuration: 'runtime'),
libraries.junit,
libraries.mockito
testRuntimeClasspath sourceSets["$preferredSourceSet"].output
platformCompileOnly sourceSets.main.output
}
nativeClassifiers.each { nativeClassifier ->
// Create the JAR task and add it's output to the published archives for this project
addNativeJar(nativeClassifier)
// Build the classes as part of the standard build.
classes.dependsOn sourceSet(nativeClassifier).classesTaskName
}
// Adds a JAR task for the native library.
def addNativeJar(nativeClassifier) {
// Create a JAR for this configuration and add it to the output archives.
SourceSet sourceSet = sourceSet(nativeClassifier)
def jarTask = tasks.register(sourceSet.jarTaskName, Jar) { Jar t ->
// Depend on the regular classes task
dependsOn classes
manifest = jar.manifest
classifier = nativeClassifier
from sourceSet.output + sourceSets.main.output
// add OSGI headers
t.convention.plugins.bundle = new BundleTaskConvention(t)
t.doLast {
t.buildBundle()
}
}
// Add the jar task to the standard build.
jar.dependsOn jarTask
// Add it to the publishing archives list.
publishing.publications.maven.artifact jarTask.get()
}
// Check which version
def javaError = new ByteArrayOutputStream()
exec {
executable test.executable
System.out.println("Running tests with java executable: " + test.executable + ".")
args = ['-version']
ignoreExitValue true
errorOutput = javaError
}
def suiteClass = (javaError.toString() =~ /"1[.]7[.].*"/) ?
"org/conscrypt/ConscryptJava7Suite.class" : "org/conscrypt/ConscryptSuite.class";
test {
include suiteClass, "org/conscrypt/ConscryptOpenJdkSuite.class"
}
def testFdSocket = tasks.register("testFdSocket", Test) {
include suiteClass, "org/conscrypt/ConscryptOpenJdkSuite.class"
InvokerHelper.setProperties(testLogging, test.testLogging.properties)
systemProperties = test.systemProperties
systemProperty "org.conscrypt.useEngineSocketByDefault", false
}
check.dependsOn testFdSocket
// Tests that involve interoperation with the OpenJDK TLS provider (generally to
// test renegotiation, since we don't support initiating renegotiation but do
// support peer-initiated renegotiation). The JDK TLS provider doesn't work
// if Conscrypt is installed as the default provider, so these need to live in
// a different task than the other tests, most of which need Conscrypt to be
// installed to function.
def testInterop = tasks.register("testInterop", Test) {
include "org/conscrypt/ConscryptEngineTest.class"
include "org/conscrypt/RenegotiationTest.class"
}
check.dependsOn testInterop
jacocoTestReport {
additionalSourceDirs.from files("$rootDir/openjdk/src/test/java", "$rootDir/common/src/main/java")
executionData tasks.withType(Test)
}
javadoc {
dependsOn(configurations.publicApiDocs)
options.doclet = "org.conscrypt.doclet.FilterDoclet"
options.docletpath = configurations.publicApiDocs.files as List
}
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 "**/*.cc"
}
}
}
binaries {
// Build the JNI lib as a shared library.
withType (SharedLibraryBinarySpec) {
cppCompiler.define "CONSCRYPT_OPENJDK"
// Set up 32-bit vs 64-bit build
def building64Bit = false
def libPath
if (targetPlatform.getArchitecture().getName() == "x86") {
libPath = "$boringssl32BuildDir"
} else if (targetPlatform.getArchitecture().getName() == "x86-64") {
libPath = "$boringssl64BuildDir"
building64Bit = true
} else {
throw new GradleException("Unknown architecture: " +
targetPlatform.getArchitecture().name)
}
if (toolChain in Clang || toolChain in Gcc) {
cppCompiler.args "-Wall",
"-fPIC",
"-O3",
"-std=c++11",
"-I$jniSourceDir/main/include",
"-I$jniSourceDir/unbundled/include",
"-I$boringsslIncludeDir",
"-I$jdkIncludeDir",
"-I$jdkIncludeDir/linux",
"-I$jdkIncludeDir/darwin",
"-I$jdkIncludeDir/win32"
if (rootProject.hasProperty('checkErrorQueue')) {
System.out.println("Compiling with error queue checking enabled")
cppCompiler.define "CONSCRYPT_CHECK_ERROR_QUEUE"
}
// Static link to BoringSSL
linker.args "-O3",
"-fvisibility=hidden",
"-lpthread",
libPath + "/ssl/libssl.a",
libPath + "/crypto/libcrypto.a"
if (targetPlatform.operatingSystem.isLinux()) {
// Static link libstdc++ and libgcc because
// they are not available in some restrictive Linux
// environments.
linker.args "-static-libstdc++",
"-static-libgcc"
} else {
linker.args "-lstdc++"
}
} else if (toolChain in VisualCpp) {
cppCompiler.define "DLL_EXPORT"
cppCompiler.define "WIN32_LEAN_AND_MEAN"
cppCompiler.define "NOMINMAX"
if (building64Bit) {
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 sourceSetName = sourceSetName("$classifier")
def source = binary.sharedLibraryFile
// Copies the native library to a resource location that will be included in the jar.
def copyTask = project.tasks.register("copyNativeLib${sourceSetName}", Copy) {
dependsOn binary.tasks.link
from source
// Rename the artifact to include the generated classifier
rename '(.+)(\\.[^\\.]+)', "\$1-$classifier\$2"
// Everything under will be included in the native jar.
into nativeResourcesDir(classifier) + '/META-INF/native'
}
// Now define a task to strip the release binary (linux only)
if (osName == 'linux' && (!rootProject.hasProperty('nostrip') ||
!rootProject.nostrip.toBoolean())) {
def stripTask = binary.tasks.taskName("strip")
project.tasks.register(stripTask as String, Exec) {
dependsOn binary.tasks.link
executable "strip"
args binary.tasks.link.linkedFile.asFile.get()
}
copyTask.configure {
dependsOn stripTask
}
}
}
}
}
boolean isExecutableOnPath(executable) {
FilenameFilter filter = new FilenameFilter() {
@Override
boolean accept(File dir, String name) {
return executable.equals(name);
}
}
for(String folder : System.getenv('PATH').split("" + File.pathSeparatorChar)) {
File[] files = file(folder).listFiles(filter)
if (files != null && files.size() > 0) {
return true;
}
}
return false;
}
String nativeResourcesDir(nativeClassifier) {
def sourceSetName = sourceSetName(nativeClassifier)
"${buildDir}/${sourceSetName}/native-resources"
}
SourceSet sourceSet(classifier) {
sourceSets[sourceSetName(classifier)]
}
static String classifierFor(osName, archName) {
"${osName}-${archName}"
}
static String sourceSetName(classifier) {
classifier.replaceAll("-", "_")
}