Home | History | Annotate | Download | only in openjdk
      1 description = 'Conscrypt: OpenJdk'
      2 
      3 ext {
      4     jniSourceDir = "$rootDir/common/src/jni"
      5     assert file("$jniSourceDir").exists()
      6 
      7     // Build the list of classifiers that will be used in the build.
      8     arch32Name = 'x86'
      9     arch64Name = 'x86_64'
     10     // Allow the java executable to be specified via env/property for each architecture.
     11     javaExecutable32 = properties['javaExecutable32'] ?: System.env.CONSCRYPT_JAVA_EXECUTABLE_32
     12     javaExecutable64 = properties['javaExecutable64'] ?: System.env.CONSCRYPT_JAVA_EXECUTABLE_64
     13     nativeClassifiers = []
     14     if (build64Bit) {
     15         // Add the 64-Bit classifier first, as the preferred classifier.
     16         nativeClassifiers += classifierFor(osName, arch64Name)
     17     }
     18     if (build32Bit) {
     19         nativeClassifiers += classifierFor(osName, arch32Name)
     20     }
     21 
     22     // Create a "preferred" configuration that can be used by other modules (e.g. tests/benchmarks)
     23     preferredNativeConfiguration = normalizeClassifier(nativeClassifiers[0])
     24 }
     25 
     26 sourceSets {
     27     main {
     28         java {
     29             srcDirs += "${rootDir}/common/src/main/java"
     30             srcDirs += project(':conscrypt-constants').sourceSets.main.java.srcDirs
     31         }
     32     }
     33 }
     34 
     35 configurations {
     36     publicApiDocs
     37 }
     38 
     39 // Append the BoringSSL-Version to the manifest.
     40 jar.manifest {
     41     attributes 'BoringSSL-Version' : boringSslVersion
     42 }
     43 
     44 dependencies {
     45     // This is used for the @hide annotation processing in JavaDoc
     46     publicApiDocs project(':conscrypt-api-doclet')
     47 
     48     compileOnly project(':conscrypt-constants')
     49 
     50     testCompile project(':conscrypt-constants'),
     51                 project(':conscrypt-testing'),
     52                 libraries.junit,
     53                 libraries.mockito
     54 }
     55 
     56 javadoc {
     57     options.doclet = "org.conscrypt.doclet.FilterDoclet"
     58     options.docletpath = configurations.publicApiDocs.files as List
     59 }
     60 
     61 /**
     62  * Create Jar and Test tasks for each native classifier.
     63  */
     64 nativeClassifiers.each { nativeClassifier ->
     65     // Create all native configurations
     66     addNativeSourceSet(nativeClassifier)
     67     addNativeSourceSet("${nativeClassifier}Test")
     68 
     69     // Create the JAR task and add it's output to the published archives for this project
     70     addNativeJar(nativeClassifier)
     71 
     72     // Create the test task and have it auto run whenever the test task runs.
     73     addNativeTest(nativeClassifier)
     74 }
     75 
     76 def nativeFileDir(nativeClassifier) {
     77     def normalizedClassifier = normalizeClassifier(nativeClassifier)
     78     "${buildDir}/${normalizedClassifier}/resources/main"
     79 }
     80 
     81 // Creates a source set (and resulting configurations) containing only the
     82 // native shared library.
     83 def addNativeSourceSet(nativeClassifier) {
     84     def normalizedClassifier = normalizeClassifier(nativeClassifier)
     85 
     86     // Create a configuration which will contain the artifact.
     87     configurations.create(normalizedClassifier)
     88 
     89     // Create a new source set. This will automatically create configurations for:
     90     // ${normalizedClassifier}Compile
     91     // ${normalizedClassifier}Runtime
     92     def sources = sourceSets.create(normalizedClassifier)
     93     sources.resources {
     94         srcDirs += files(nativeFileDir(nativeClassifier))
     95     }
     96 }
     97 
     98 // Adds a JAR task for the native library.
     99 def addNativeJar(nativeClassifier) {
    100     def normalizedClassifier = normalizeClassifier(nativeClassifier)
    101     // Create a JAR for this configuration and add it to the output archives.
    102     def jarTaskName = "create${normalizedClassifier}Jar"
    103     // The testRuntime configuration is created automatically when we created the source set.
    104     def testRuntimeConfigName = "${normalizedClassifier}TestRuntime"
    105     task "$jarTaskName"(type: Jar) {
    106         dependsOn classes
    107         dependsOn configurations[testRuntimeConfigName]
    108         from sourceSets.main.output + files(nativeFileDir(nativeClassifier))
    109         manifest = jar.manifest
    110         classifier = nativeClassifier
    111     }
    112     // Add it to the 'archives' configuration so that the artifact will be automatically built and
    113     // installed/deployed.
    114     artifacts.add('archives', tasks["$jarTaskName"])
    115 
    116     // Also add the artifact to its own configuration so that it can be referenced from other projects.
    117     artifacts.add(normalizedClassifier, tasks["$jarTaskName"])
    118 }
    119 
    120 // Optionally adds a test task for the given platform
    121 def addNativeTest(nativeClassifier) {
    122     def normalizedClassifier = normalizeClassifier(nativeClassifier)
    123     def testTaskName = "${normalizedClassifier}Test"
    124     def javaExecutable
    125     def javaArchFlag
    126     if (normalizedClassifier.endsWith(arch32Name)) {
    127         // 32-bit test
    128         javaExecutable = javaExecutable32 != null ? javaExecutable32 : test.executable
    129         javaArchFlag = '-d32'
    130     } else {
    131         // 64-bit test
    132         javaExecutable = javaExecutable64 != null ? javaExecutable64 : test.executable
    133         javaArchFlag = '-d64'
    134     }
    135 
    136     // Execute the java executable to see if it supports the architecture flag.
    137     def javaError = new ByteArrayOutputStream()
    138     exec {
    139         executable javaExecutable
    140         args = ["$javaArchFlag", '-version']
    141         ignoreExitValue true
    142         errorOutput = javaError
    143     }
    144 
    145     // Only add the test if the javaArchFlag is supported for the selected JVM
    146     def archSupported = !javaError.toString().toLowerCase().contains('error')
    147     if (archSupported) {
    148         task "$testTaskName"(type: Test) {
    149             testClassesDir = test.testClassesDir
    150             classpath = test.classpath + files(nativeFileDir(nativeClassifier))
    151             jvmArgs javaArchFlag
    152             executable = javaExecutable
    153         }
    154         test.dependsOn "$testTaskName"
    155     }
    156 }
    157 
    158 // Exclude all test classes from the default test suite.
    159 // We will test each available native artifact separately (see nativeClassifiers).
    160 test.exclude("**")
    161 
    162 model {
    163     platforms {
    164         x86 {
    165             architecture arch32Name
    166         }
    167         x86_64 {
    168             architecture arch64Name
    169         }
    170     }
    171 
    172     buildTypes {
    173         release
    174     }
    175 
    176     components {
    177         // Builds the JNI library.
    178         conscrypt_openjdk_jni(NativeLibrarySpec) {
    179             if (build32Bit) { targetPlatform arch32Name }
    180             if (build64Bit) { targetPlatform arch64Name }
    181 
    182             sources {
    183                 cpp {
    184                     source {
    185                         srcDirs "$jniSourceDir/main/cpp"
    186                         include "**/*.cpp"
    187                     }
    188                 }
    189             }
    190 
    191             binaries {
    192                 // Build the JNI lib as a shared library.
    193                 withType (SharedLibraryBinarySpec) {
    194                     cppCompiler.define "CONSCRYPT_OPENJDK"
    195 
    196                     // Set up 32-bit vs 64-bit build
    197                     def libPath
    198                     if (targetPlatform.getArchitecture().getName() == "x86") {
    199                         libPath = "$boringssl32BuildDir"
    200                     } else if (targetPlatform.getArchitecture().getName() == "x86-64") {
    201                         libPath = "$boringssl64BuildDir"
    202                     } else {
    203                         throw new GradleException("Unknown architecture: " +
    204                                 targetPlatform.getArchitecture().name)
    205                     }
    206 
    207                     if (toolChain in Clang || toolChain in Gcc) {
    208                         cppCompiler.args "-Wall",
    209                                 "-fPIC",
    210                                 "-O2",
    211                                 "-std=c++11",
    212                                 "-I$jniSourceDir/main/include",
    213                                 "-I$jniSourceDir/unbundled/include",
    214                                 "-I$boringsslIncludeDir",
    215                                 "-I$jdkIncludeDir",
    216                                 "-I$jdkIncludeDir/linux",
    217                                 "-I$jdkIncludeDir/darwin",
    218                                 "-I$jdkIncludeDir/win32"
    219 
    220                         // Static link to BoringSSL
    221                         linker.args "-O2",
    222                                 "-fvisibility=hidden",
    223                                 "-lstdc++",
    224                                 libPath + "/ssl/libssl.a",
    225                                 libPath + "/crypto/libcrypto.a"
    226                     } else if (toolChain in VisualCpp) {
    227                         cppCompiler.define "DLL_EXPORT"
    228                         cppCompiler.define "WIN32_LEAN_AND_MEAN"
    229                         cppCompiler.define "WIN64"
    230                         cppCompiler.define "_WINDOWS"
    231                         cppCompiler.define "UNICODE"
    232                         cppCompiler.define "_UNICODE"
    233                         cppCompiler.define "NDEBUG"
    234 
    235                         cppCompiler.args "/nologo",
    236                                 "/MT",
    237                                 "/WX-",
    238                                 "/Wall",
    239                                 "/O2",
    240                                 "/Oi",
    241                                 "/Ot",
    242                                 "/GL",
    243                                 "/GS",
    244                                 "/Gy",
    245                                 "/fp:precise",
    246                                 "-wd4514", // Unreferenced inline function removed
    247                                 "-wd4548", // Expression before comma has no effect
    248                                 "-wd4625", // Copy constructor was implicitly defined as deleted
    249                                 "-wd4626", // Assignment operator was implicitly defined as deleted
    250                                 "-wd4710", // function not inlined
    251                                 "-wd4711", // function inlined
    252                                 "-wd4820", // Extra padding added to struct
    253                                 "-wd4946", // reinterpret_cast used between related classes:
    254                                 "-wd4996", // Thread safety for strerror
    255                                 "-wd5027", // Move assignment operator was implicitly defined as deleted
    256                                 "-I$jniSourceDir/main/include",
    257                                 "-I$jniSourceDir/unbundled/include",
    258                                 "-I$boringsslIncludeDir",
    259                                 "-I$jdkIncludeDir",
    260                                 "-I$jdkIncludeDir/win32"
    261 
    262                         // Static link to BoringSSL
    263                         linker.args "-WX",
    264                                 "ws2_32.lib",
    265                                 "advapi32.lib",
    266                                 libPath + "\\ssl\\ssl.lib",
    267                                 libPath + "\\crypto\\crypto.lib"
    268                     }
    269                 }
    270 
    271                 // Never build a static library.
    272                 withType(StaticLibraryBinarySpec) {
    273                     buildable = false
    274                 }
    275             }
    276         }
    277     }
    278 
    279     tasks { t ->
    280         $.binaries.withType(SharedLibraryBinarySpec).each { binary ->
    281             // Build the native artifact classifier from the OS and architecture.
    282             def archName = binary.targetPlatform.architecture.name.replaceAll('-', '_')
    283             def classifier = classifierFor(osName, archName)
    284             def normalizedClassifier = normalizeClassifier("$classifier")
    285             def source = binary.sharedLibraryFile
    286 
    287             // Copies the native library to a resource location that will be included in the jar.
    288             def copyTaskName = "copyNativeLib${normalizedClassifier}"
    289             task "$copyTaskName"(type: Copy, dependsOn: binary.buildTask) {
    290                 from source
    291                 // Rename the artifact to include the generated classifier
    292                 rename '(.+)(\\.[^\\.]+)', "\$1-$classifier\$2"
    293                 // This location will automatically be included in the jar.
    294                 into "${buildDir}/${normalizedClassifier}/resources/main/META-INF/native"
    295             }
    296 
    297             // Make sure we build and copy the native library to the output directory.
    298             compileJava.dependsOn "$copyTaskName"
    299 
    300             // Now define a task to strip the release binary (linux only)
    301             def stripTask = binary.tasks.taskName("strip")
    302             t.create(stripTask) {
    303                 dependsOn binary.tasks.link
    304                 doFirst {
    305                     if (osName == 'linux') {
    306                         ["strip", binary.tasks.link.outputFile].execute().waitForOrKill(1000)
    307                     }
    308                 }
    309             }
    310             binary.tasks.build.dependsOn stripTask
    311         }
    312     }
    313 }
    314 
    315 static classifierFor(osName, archName) {
    316     return "${osName}-${archName}"
    317 }
    318 
    319 static normalizeClassifier(classifier) {
    320     return classifier.replaceAll("-", "_")
    321 }
    322 
    323 // Manually add the native library to help IntelliJ run tests.
    324 idea.module {
    325     scopes.PROVIDED.plus += [ configurations["$preferredNativeConfiguration"] ]
    326 }
    327