1buildscript {
2    ext.android_tools = 'com.android.tools.build:gradle:3.1.3'
3    repositories {
4        google()
5        jcenter()
6    }
7    dependencies {
8        // This must be applied in the root project otherwise each subproject will
9        // have it in a different ClassLoader.
10        classpath android_tools
11    }
12}
13
14plugins {
15  // Add dependency for build script so we can access Git from our
16  // build script.
17  id 'org.ajoberstar.grgit' version '2.2.1'
18  id 'net.ltgt.errorprone' version '0.0.11'
19}
20
21subprojects {
22    def androidProject = ((project.name == 'conscrypt-android')
23            || (project.name == 'conscrypt-android-platform')
24            || (project.name == 'conscrypt-benchmark-android')
25            || (project.name == 'conscrypt-benchmark-caliper'))
26    if (androidProject) {
27        repositories {
28            google()
29        }
30    } else {
31        apply plugin: 'java-library'
32        apply plugin: 'cpp'
33
34        model {
35            toolChains {
36                visualCpp(VisualCpp)
37                // Prefer Clang over Gcc (order here matters!)
38                clang(Clang)
39                gcc(Gcc)
40            }
41        }
42    }
43    apply plugin: "maven"
44    apply plugin: "signing"
45    apply plugin: "idea"
46    apply plugin: "jacoco"
47    apply plugin: "net.ltgt.errorprone"
48
49    group = "org.conscrypt"
50    description = 'Conscrypt is an alternate Java Security Provider that uses BoringSSL'
51    version = "2.1.0-SNAPSHOT"
52
53    ext {
54        os = org.gradle.internal.os.OperatingSystem.current();
55        if (os.isLinux()) {
56            osName = "linux"
57        } else if (os.isMacOsX()) {
58            osName = "osx"
59        } else if (os.isWindows()) {
60            osName = "windows"
61        } else {
62            throw new GradleException("Unsupported os: " + os.name)
63        }
64
65        if (project.hasProperty("boringsslHome")) {
66            boringsslHome = project.property("boringsslHome")
67        } else {
68            boringsslHome = "$System.env.BORINGSSL_HOME"
69        }
70
71        boringsslIncludeDir = normalizePath("$boringsslHome/include")
72        boringssl32BuildDir = normalizePath("$boringsslHome/build32")
73        boringssl64BuildDir = normalizePath("$boringsslHome/build64")
74
75        if (project.hasProperty("jdkHome")) {
76            jdkHome = project.property("jdkHome")
77        } else {
78            jdkHome = "$System.env.JAVA_HOME"
79        }
80        jdkIncludeDir = normalizePath("$jdkHome/include")
81        // Needs to be binary compatible with androidMinSdkVersion
82        androidMinJavaVersion = JavaVersion.VERSION_1_7
83
84        build32Bit = file("$boringssl32BuildDir").exists()
85        build64Bit = file("$boringssl64BuildDir").exists()
86
87        // Ensure the environment is configured properly.
88        assert file("$boringsslHome").exists()
89        assert file("$boringsslIncludeDir").exists()
90        assert build32Bit || build64Bit
91        assert file("$jdkHome").exists()
92        assert file("$jdkIncludeDir").exists()
93
94        // Get the commit hash for BoringSSL.
95        boringSslGit = org.ajoberstar.grgit.Grgit.open(dir: boringsslHome)
96        boringSslVersion = boringSslGit.head().id
97
98        // Allow the java executable to be specified via env/property for each architecture.
99        javaExecutable32 = System.getProperty('javaExecutable32', System.env.CONSCRYPT_JAVA_EXECUTABLE_32)
100        javaExecutable64 = System.getProperty('javaExecutable64', System.env.CONSCRYPT_JAVA_EXECUTABLE_64)
101
102        jmhVersion = '1.19'
103        libraries = [
104                android_tools: android_tools,
105                roboelectric: 'org.robolectric:android-all:7.1.0_r7-robolectric-0',
106
107                // Test dependencies.
108                bouncycastle_apis: 'org.bouncycastle:bcpkix-jdk15on:1.56',
109                bouncycastle_provider: 'org.bouncycastle:bcprov-jdk15on:1.56',
110                junit  : 'junit:junit:4.12',
111                mockito: 'org.mockito:mockito-core:1.9.5',
112                truth  : 'com.google.truth:truth:0.28',
113
114                // Benchmark dependencies
115                jmh_core: "org.openjdk.jmh:jmh-core:${jmhVersion}",
116                jmh_generator_annprocess: "org.openjdk.jmh:jmh-generator-annprocess:${jmhVersion}",
117                jmh_generator_asm: "org.openjdk.jmh:jmh-generator-asm:${jmhVersion}",
118                jmh_generator_bytecode: "org.openjdk.jmh:jmh-generator-bytecode:${jmhVersion}",
119                jmh_generator_reflection: "org.openjdk.jmh:jmh-generator-reflection:${jmhVersion}",
120                netty_handler: 'io.netty:netty-handler:4.1.8.Final',
121                netty_tcnative: 'io.netty:netty-tcnative-boringssl-static:1.1.33.Fork26',
122        ]
123
124        signJar = { jarPath ->
125            if (rootProject.hasProperty('signingKeystore') && rootProject.hasProperty('signingPassword')) {
126                def command = 'jarsigner -keystore ' + rootProject.signingKeystore +
127                        ' -storepass ' + rootProject.signingPassword +
128                        ' ' + jarPath + ' signingcert'
129                def process = command.execute()
130                process.waitFor()
131                if (process.exitValue()) {
132                    throw new GradleException('Jar signing failed for ' + jarPath + ': ' + process.text)
133                }
134            }
135        }
136    }
137
138    repositories {
139        mavenCentral()
140        mavenLocal()
141        jcenter()
142    }
143
144    signing {
145        required false
146        sign configurations.archives
147    }
148
149    signArchives.doFirst {
150        configurations.archives.allArtifacts.each {
151            if (it.type == 'jar' && it.classifier != 'sources' && it.classifier != 'javadoc') {
152                signJar(it.file.absolutePath)
153            }
154        }
155    }
156
157    task generateProperties(type: WriteProperties) {
158        ext {
159            parsedVersion = VersionNumber.parse(version)
160        }
161        property("org.conscrypt.version.major", parsedVersion.getMajor())
162        property("org.conscrypt.version.minor", parsedVersion.getMinor())
163        property("org.conscrypt.version.patch", parsedVersion.getMicro())
164        property("org.conscrypt.boringssl.version", boringSslVersion)
165        outputFile "build/generated/resources/org/conscrypt/conscrypt.properties"
166    }
167
168    if (!androidProject) {
169        sourceCompatibility = JavaVersion.VERSION_1_7
170        targetCompatibility = JavaVersion.VERSION_1_7
171
172        [compileJava, compileTestJava].each() {
173            it.options.compilerArgs += ["-Xlint:all", "-Xlint:-options", '-Xmaxwarns', '9999999']
174            it.options.encoding = "UTF-8"
175            if (rootProject.hasProperty('failOnWarnings') && rootProject.failOnWarnings.toBoolean()) {
176                it.options.compilerArgs += ["-Werror"]
177            }
178        }
179
180        compileTestJava {
181            // serialVersionUID is basically guaranteed to be useless in our tests
182            options.compilerArgs += ["-Xlint:-serial"]
183        }
184
185        jar.manifest {
186            attributes('Implementation-Title': name,
187                    'Implementation-Version': version,
188                    'Built-By': System.getProperty('user.name'),
189                    'Built-JDK': System.getProperty('java.version'),
190                    'Source-Compatibility': sourceCompatibility,
191                    'Target-Compatibility': targetCompatibility)
192        }
193
194        javadoc.options {
195            encoding = 'UTF-8'
196            links 'https://docs.oracle.com/javase/8/docs/api/'
197        }
198
199        // Disable JavaDoc doclint on Java 8. It's annoying.
200        if (JavaVersion.current().isJava8Compatible()) {
201            allprojects {
202                tasks.withType(Javadoc) {
203                    options.addStringOption('Xdoclint:none', '-quiet')
204                }
205            }
206        }
207
208        task javadocJar(type: Jar) {
209            classifier = 'javadoc'
210            from javadoc
211        }
212
213        task sourcesJar(type: Jar) {
214            classifier = 'sources'
215            from sourceSets.main.allSource
216        }
217
218        artifacts {
219            archives sourcesJar
220            archives javadocJar
221        }
222
223        uploadArchives.repositories.mavenDeployer {
224            beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
225            String stagingUrl
226            if (rootProject.hasProperty('repositoryId')) {
227                stagingUrl = 'https://oss.sonatype.org/service/local/staging/deployByRepositoryId/' +
228                        rootProject.repositoryId
229            } else {
230                stagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
231            }
232            def configureAuth = {
233                if (rootProject.hasProperty('ossrhUsername') && rootProject.hasProperty('ossrhPassword')) {
234                    authentication(userName: rootProject.ossrhUsername, password: rootProject.ossrhPassword)
235                }
236            }
237            repository(url: stagingUrl, configureAuth)
238            snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/', configureAuth)
239        }
240
241        [
242                install.repositories.mavenInstaller,
243                uploadArchives.repositories.mavenDeployer,
244        ]*.pom*.whenConfigured { pom ->
245            pom.project {
246                name "$project.group:$project.name"
247                description project.description
248                url 'https://conscrypt.org/'
249
250                scm {
251                    connection 'scm:git:https://github.com/google/conscrypt.git'
252                    developerConnection 'scm:git:git@github.com:google/conscrypt.git'
253                    url 'https://github.com/google/conscrypt'
254                }
255
256                licenses {
257                    license {
258                        name 'Apache 2'
259                        url 'https://www.apache.org/licenses/LICENSE-2.0'
260                    }
261                }
262
263                developers {
264                    developer {
265                        id "conscrypt"
266                        name "Conscrypt Contributors"
267                        email "conscrypt@googlegroups.com"
268                        url "https://conscrypt.org/"
269                        organization = "Google, Inc."
270                        organizationUrl "https://www.google.com"
271                    }
272                }
273            }
274        }
275
276        // At a test failure, log the stack trace to the console so that we don't
277        // have to open the HTML in a browser.
278        test {
279            testLogging {
280                exceptionFormat = 'full'
281                showExceptions true
282                showCauses true
283                showStackTraces true
284                showStandardStreams = true
285            }
286            // Enable logging for all conscrypt classes while running tests.
287            systemProperty 'java.util.logging.config.file', "${rootDir}/test_logging.properties"
288            maxHeapSize = '1500m'
289
290            // Override the default executable if manually specified
291            if (build64Bit && javaExecutable64 != null) {
292                executable javaExecutable64
293            } else if (build32Bit && javaExecutable32 != null) {
294                executable javaExecutable32
295            }
296        }
297    }
298}
299
300static String normalizePath(path) {
301    new File(path.toString()).absolutePath
302}
303