• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1description = 'Conscrypt: OpenJdk'
2
3ext {
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
26sourceSets {
27    main {
28        java {
29            srcDirs += "${rootDir}/common/src/main/java"
30            srcDirs += project(':conscrypt-constants').sourceSets.main.java.srcDirs
31        }
32    }
33}
34
35configurations {
36    publicApiDocs
37}
38
39// Append the BoringSSL-Version to the manifest.
40jar.manifest {
41    attributes 'BoringSSL-Version' : boringSslVersion
42}
43
44dependencies {
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
56javadoc {
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 */
64nativeClassifiers.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
76def 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.
83def 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.
99def 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
121def 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).
160test.exclude("**")
161
162model {
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
315static classifierFor(osName, archName) {
316    return "${osName}-${archName}"
317}
318
319static normalizeClassifier(classifier) {
320    return classifier.replaceAll("-", "_")
321}
322
323// Manually add the native library to help IntelliJ run tests.
324idea.module {
325    scopes.PROVIDED.plus += [ configurations["$preferredNativeConfiguration"] ]
326}
327