普通文本  |  327行  |  12.4 KB

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