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