diff --git a/android-stub/build.gradle b/android-stub/build.gradle index 874f5996e..9037248c9 100644 --- a/android-stub/build.gradle +++ b/android-stub/build.gradle @@ -1,3 +1,8 @@ +plugins { + id 'conventions.common' + id 'conventions.jvm' +} + description = 'Conscrypt: Android-Stub' dependencies { diff --git a/android/build.gradle b/android/build.gradle index 3b8439c01..0eac51ea2 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,8 @@ plugins { - alias(libs.plugins.android.library) + id 'conventions.common' + id 'conventions.versionprops' + id 'conventions.boringssl' + id 'conventions.android' } description = 'Conscrypt: Android' diff --git a/benchmark-android/build.gradle b/benchmark-android/build.gradle index 42d7913de..d938a1187 100644 --- a/benchmark-android/build.gradle +++ b/benchmark-android/build.gradle @@ -1,5 +1,6 @@ plugins { - alias(libs.plugins.android.library) + id 'conventions.common' + id 'conventions.android' } description = 'Conscrypt: Android Benchmarks' diff --git a/benchmark-base/build.gradle b/benchmark-base/build.gradle index 6c838b148..115216620 100644 --- a/benchmark-base/build.gradle +++ b/benchmark-base/build.gradle @@ -1,3 +1,8 @@ +plugins { + id 'conventions.common' + id 'conventions.jvm' +} + description = 'Conscrypt: Base library for benchmarks' dependencies { diff --git a/benchmark-graphs/build.gradle b/benchmark-graphs/build.gradle index 63ea482cc..a1cbdab77 100644 --- a/benchmark-graphs/build.gradle +++ b/benchmark-graphs/build.gradle @@ -1,3 +1,7 @@ +plugins { + id 'conventions.common' +} + apply plugin: 'application' dependencies { diff --git a/benchmark-jmh/build.gradle b/benchmark-jmh/build.gradle index 20393b2ee..6cbee2e64 100644 --- a/benchmark-jmh/build.gradle +++ b/benchmark-jmh/build.gradle @@ -1,4 +1,6 @@ plugins { + id 'conventions.common' + id 'conventions.jvm' alias libs.plugins.jmh } diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts new file mode 100644 index 000000000..666966894 --- /dev/null +++ b/build-logic/build.gradle.kts @@ -0,0 +1,24 @@ +plugins { + `kotlin-dsl` + `java-gradle-plugin` + id("groovy-gradle-plugin") +} + +repositories { + mavenCentral() + google() + gradlePluginPortal() +} + +// Annoyingly, build-logic is pre-built before the rest of the subprojects and so cannot +// make use of the version catalogue in libs.versions.toml. +dependencies { + // AGP + implementation("com.android.tools.build:gradle:7.4.2") + implementation("biz.aQute.bnd:biz.aQute.bnd.gradle:6.4.0") + implementation("com.google.gradle:osdetector-gradle-plugin:1.7.3") + implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.3.0") + implementation("org.ajoberstar.grgit:grgit-gradle:5.3.3") + implementation("com.dorongold.plugins:task-tree:3.0.0") + implementation(gradleApi()) +} diff --git a/build-logic/src/main/groovy/conventions.android.gradle b/build-logic/src/main/groovy/conventions.android.gradle new file mode 100644 index 000000000..35f42242c --- /dev/null +++ b/build-logic/src/main/groovy/conventions.android.gradle @@ -0,0 +1,12 @@ +plugins { + id "com.android.library" +} + +repositories { + google() +} + +ext { + // Needs to be binary compatible with androidMinSdkVersion + androidMinJavaVersion = JavaVersion.VERSION_1_8 +} \ No newline at end of file diff --git a/build-logic/src/main/groovy/conventions.boringssl.gradle b/build-logic/src/main/groovy/conventions.boringssl.gradle new file mode 100644 index 000000000..bbd1ee153 --- /dev/null +++ b/build-logic/src/main/groovy/conventions.boringssl.gradle @@ -0,0 +1,19 @@ +plugins { + id 'org.ajoberstar.grgit' +} + +def boringHome = (project.findProperty('boringsslHome') ?: System.getenv('BORINGSSL_HOME')) +if (!boringHome) { + throw new GradleException("boringsslHome not set. Provide -PboringsslHome or \$BORINGSSL_HOME.") +} + +def boringInclude = file("${boringHome}/include").absolutePath +if (!file(boringInclude).exists()) { + throw new GradleException("BoringSSL include dir not found: ${boringInclude}") +} + +ext { + boringsslHome = boringHome + boringsslIncludeDir = boringInclude + boringSslVersion = org.ajoberstar.grgit.Grgit.open(dir: boringHome).head().id +} diff --git a/build-logic/src/main/groovy/conventions.common.gradle b/build-logic/src/main/groovy/conventions.common.gradle new file mode 100644 index 000000000..b77e152b6 --- /dev/null +++ b/build-logic/src/main/groovy/conventions.common.gradle @@ -0,0 +1,26 @@ +plugins { + id 'jacoco' + id 'net.ltgt.errorprone' + id 'com.dorongold.task-tree' +} + +group = "org.conscrypt" + +repositories { + mavenCentral() +} + +jacoco { + toolVersion = libs.versions.jacoco +} + +configurations { + jacocoAnt + jacocoAgent +} + +dependencies { + jacocoAnt libs.jacoco.ant + jacocoAgent libs.jacoco.agent + errorprone libs.errorprone +} diff --git a/build-logic/src/main/groovy/conventions.cpp.gradle b/build-logic/src/main/groovy/conventions.cpp.gradle new file mode 100644 index 000000000..28d9eadce --- /dev/null +++ b/build-logic/src/main/groovy/conventions.cpp.gradle @@ -0,0 +1,31 @@ +plugins { + id 'cpp' +} + +model { + toolChains { + visualCpp(VisualCpp) + // Prefer Clang over Gcc (order here matters!) + clang(Clang) { + // Gradle 7.x still seems to get confused about toolchains on Mac + // so explicitly add -arch args. + target("osx_aarch64") { + cppCompiler.withArguments { args -> + args << "-arch" << "arm64" + } + linker.withArguments { args -> + args << "-arch" << "arm64" + } + } + target("osx_x86-64") { + cppCompiler.withArguments { args -> + args << "-arch" << "x86_64" + } + linker.withArguments { args -> + args << "-arch" << "x86_64" + } + } + } + gcc(Gcc) + } +} \ No newline at end of file diff --git a/build-logic/src/main/groovy/conventions.jvm.gradle b/build-logic/src/main/groovy/conventions.jvm.gradle new file mode 100644 index 000000000..70077feeb --- /dev/null +++ b/build-logic/src/main/groovy/conventions.jvm.gradle @@ -0,0 +1,69 @@ +plugins { + id 'com.google.osdetector' + id 'java-library' +} + + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(11) + } +} + +[tasks.named("compileJava"), tasks.named("compileTestJava")].forEach { t -> + t.configure { + options.compilerArgs += ["-Xlint:all", "-Xlint:-options", '-Xmaxwarns', '9999999'] + options.encoding = "UTF-8" + options.release = 8 + + if (rootProject.hasProperty('failOnWarnings') && rootProject.failOnWarnings.toBoolean()) { + options.compilerArgs += ["-Werror"] + } + } +} + +tasks.named("compileTestJava").configure { + // serialVersionUID is basically guaranteed to be useless in our tests + options.compilerArgs += ["-Xlint:-serial"] +} + +tasks.named("jar").configure { + manifest { + attributes('Implementation-Title': name, + 'Implementation-Version': archiveVersion, + 'Built-By': System.getProperty('user.name'), + 'Built-JDK': System.getProperty('java.version'), + 'Source-Compatibility': sourceCompatibility, + 'Target-Compatibility': targetCompatibility) + } +} + +javadoc.options { + encoding = 'UTF-8' + links 'https://docs.oracle.com/en/java/javase/21/docs/api/java.base/' +} + +tasks.register("javadocJar", Jar) { + archiveClassifier = 'javadoc' + from javadoc +} + +tasks.register("sourcesJar", Jar) { + archiveClassifier = 'sources' + from sourceSets.main.allSource +} + +// At a test failure, log the stack trace to the console so that we don't +// have to open the HTML in a browser. +test { + testLogging { + exceptionFormat = 'full' + showExceptions true + showCauses true + showStackTraces true + showStandardStreams = true + } + // Enable logging for all conscrypt classes while running tests. + systemProperty 'java.util.logging.config.file', "${rootDir}/test_logging.properties" + maxHeapSize = '1500m' +} diff --git a/build-logic/src/main/groovy/conventions.versionprops.gradle b/build-logic/src/main/groovy/conventions.versionprops.gradle new file mode 100644 index 000000000..5c575f3d7 --- /dev/null +++ b/build-logic/src/main/groovy/conventions.versionprops.gradle @@ -0,0 +1,12 @@ +import org.gradle.util.VersionNumber + +tasks.register("generateProperties", WriteProperties) { + ext { + parsedVersion = VersionNumber.parse(version) + } + property("org.conscrypt.version.major", parsedVersion.getMajor()) + property("org.conscrypt.version.minor", parsedVersion.getMinor()) + property("org.conscrypt.version.patch", parsedVersion.getMicro()) + property("org.conscrypt.boringssl.version", boringSslVersion) + outputFile "build/generated/resources/org/conscrypt/conscrypt.properties" +} diff --git a/build.gradle b/build.gradle index 5f8137917..202a96f4e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,196 +1,6 @@ -import org.ajoberstar.grgit.Grgit -import org.gradle.util.VersionNumber - -plugins { - alias libs.plugins.bnd apply false - alias libs.plugins.android.library apply false - alias libs.plugins.errorprone - alias libs.plugins.grgit - alias libs.plugins.osdetector - alias libs.plugins.task.tree -} +description = 'Conscrypt is an alternate Java Security Provider that uses BoringSSL' subprojects { - def androidProject = ((project.name == 'conscrypt-android') - || (project.name == 'conscrypt-android-platform') - || (project.name == 'conscrypt-benchmark-android') - || (project.name == 'conscrypt-benchmark-caliper')) - if (androidProject) { - repositories { - google() - } - } else { - apply plugin: 'java-library' - apply plugin: 'cpp' - - model { - toolChains { - visualCpp(VisualCpp) - // Prefer Clang over Gcc (order here matters!) - clang(Clang) { - // Gradle 7.x still seems to get confused about toolchains on Mac - // so explicitly add -arch args. - target("osx_aarch64") { - cppCompiler.withArguments { args -> - args << "-arch" << "arm64" - } - linker.withArguments { args -> - args << "-arch" << "arm64" - } - } - target("osx_x86-64") { - cppCompiler.withArguments { args -> - args << "-arch" << "x86_64" - } - linker.withArguments { args -> - args << "-arch" << "x86_64" - } - } - } - gcc(Gcc) - } - } - } - apply plugin: "jacoco" - apply plugin: libs.plugins.errorprone.get().pluginId - - group = "org.conscrypt" - description = 'Conscrypt is an alternate Java Security Provider that uses BoringSSL' + // Keep this in `subprojects` for scripts and ease of use. Migrate to properties later. version = "2.6-SNAPSHOT" - - ext { - // Needs to be binary compatible with androidMinSdkVersion - androidMinJavaVersion = JavaVersion.VERSION_1_8 - - if (project.hasProperty("boringsslHome")) { - boringsslHome = project.property("boringsslHome") - } else { - boringsslHome = "$System.env.BORINGSSL_HOME" - } - boringsslIncludeDir = normalizePath("$boringsslHome/include") - - // Ensure the environment is configured properly. - assert file("$boringsslIncludeDir").exists() - - // Get the commit hash for BoringSSL. - boringSslGit = Grgit.open(dir: boringsslHome) - boringSslVersion = boringSslGit.head().id - - signJar = { jarPath -> - if (rootProject.hasProperty('signingKeystore') && rootProject.hasProperty('signingPassword')) { - def command = 'jarsigner -keystore ' + rootProject.signingKeystore + - ' -storepass ' + rootProject.signingPassword + - ' ' + jarPath + ' signingcert' - def process = command.execute() - process.waitFor() - if (process.exitValue()) { - throw new RuntimeException('Jar signing failed for ' + jarPath + ': ' + process.text) - } - } - } - } - - repositories { - mavenCentral() - mavenLocal() - } - - jacoco { - toolVersion = libs.versions.jacoco - } - - configurations { - jacocoAnt - jacocoAgent - } - - dependencies { - jacocoAnt libs.jacoco.ant - jacocoAgent libs.jacoco.agent - } - - dependencies { - errorprone libs.errorprone - } - - tasks.register("generateProperties", WriteProperties) { - ext { - parsedVersion = VersionNumber.parse(version) - } - property("org.conscrypt.version.major", parsedVersion.getMajor()) - property("org.conscrypt.version.minor", parsedVersion.getMinor()) - property("org.conscrypt.version.patch", parsedVersion.getMicro()) - property("org.conscrypt.boringssl.version", boringSslVersion) - outputFile "build/generated/resources/org/conscrypt/conscrypt.properties" - } - - if (!androidProject) { - java { - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } - } - - [tasks.named("compileJava"), tasks.named("compileTestJava")].forEach { t -> - t.configure { - options.compilerArgs += ["-Xlint:all", "-Xlint:-options", '-Xmaxwarns', '9999999'] - options.encoding = "UTF-8" - options.release = 8 - - if (rootProject.hasProperty('failOnWarnings') && rootProject.failOnWarnings.toBoolean()) { - options.compilerArgs += ["-Werror"] - } - } - } - - tasks.named("compileTestJava").configure { - // serialVersionUID is basically guaranteed to be useless in our tests - options.compilerArgs += ["-Xlint:-serial"] - } - - tasks.named("jar").configure { - manifest { - attributes('Implementation-Title': name, - 'Implementation-Version': archiveVersion, - 'Built-By': System.getProperty('user.name'), - 'Built-JDK': System.getProperty('java.version'), - 'Source-Compatibility': sourceCompatibility, - 'Target-Compatibility': targetCompatibility) - } - } - - javadoc.options { - encoding = 'UTF-8' - links 'https://docs.oracle.com/en/java/javase/21/docs/api/java.base/' - } - - tasks.register("javadocJar", Jar) { - archiveClassifier = 'javadoc' - from javadoc - } - - tasks.register("sourcesJar", Jar) { - archiveClassifier = 'sources' - from sourceSets.main.allSource - } - - // At a test failure, log the stack trace to the console so that we don't - // have to open the HTML in a browser. - test { - testLogging { - exceptionFormat = 'full' - showExceptions true - showCauses true - showStackTraces true - showStandardStreams = true - } - // Enable logging for all conscrypt classes while running tests. - systemProperty 'java.util.logging.config.file', "${rootDir}/test_logging.properties" - maxHeapSize = '1500m' - } - } -} - -static String normalizePath(path) { - new File(path.toString()).absolutePath } diff --git a/constants/build.gradle b/constants/build.gradle index 8f6c4593f..5a7e54592 100644 --- a/constants/build.gradle +++ b/constants/build.gradle @@ -1,3 +1,11 @@ +plugins { + id 'conventions.common' + id 'conventions.boringssl' + id 'conventions.cpp' + // TODO(prb) generate the Java to a central location so we don't need JVM conventions + id 'conventions.jvm' +} + description = 'Conscrypt: Constants' ext { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 52240f445..e9687414e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,11 +1,8 @@ [versions] -agp = "7.4.2" bnd = "6.4.0" bouncycastle = "1.67" caliper = "1.0-beta-2" errorprone = "2.31.0" -errorprone-plugin = "4.0.0" -grgit = "5.2.2" jacoco = "0.8.12" jmh = "1.37" jmh-plugin = "0.7.2" @@ -13,19 +10,12 @@ junit = "4.13.2" mockito = "2.28.2" netty-handler = "4.1.24.Final" netty-tcnative = "2.0.26.Final" -osdetector = "1.7.3" shadow = "7.1.2" -task-tree = "3.0.0" [plugins] -android-library = { id = "com.android.library", version.ref = "agp" } bnd = { id = "biz.aQute.bnd.builder", version.ref = "bnd" } -errorprone = { id = "net.ltgt.errorprone", version.ref = "errorprone-plugin" } -grgit = { id = "org.ajoberstar.grgit", version.ref = "grgit" } jmh = { id = "me.champeau.jmh", version.ref = "jmh-plugin" } -osdetector = { id = "com.google.osdetector", version.ref = "osdetector" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } -task-tree = { id = "com.dorongold.task-tree", version.ref = "task-tree" } [libraries] # Android tooling diff --git a/gradle/publishing.gradle b/gradle/publishing.gradle index c9ece0531..cfe0ca267 100644 --- a/gradle/publishing.gradle +++ b/gradle/publishing.gradle @@ -75,3 +75,20 @@ signMavenPublication.doFirst { tasks.withType(Sign) { onlyIf { isReleaseVersion } } + +def signJar(String jarPath) { + if (rootProject.hasProperty('signingKeystore') && rootProject.hasProperty('signingPassword')) { + def command = 'jarsigner -keystore ' + rootProject.signingKeystore + + ' -storepass ' + rootProject.signingPassword + + ' ' + jarPath + ' signingcert' + def process = command.execute() + process.in.eachLine { line -> logger.info(line) } + process.err.eachLine { line -> logger.error(line) } + process.waitFor() + if (process.exitValue() != 0) { + throw new GradleException("jarsigner failed for " + jarPath + " (exit " + process.exitValue() + ")") + } + } else { + logger.lifecycle("Skipping jar signing for ${jarPath} (no signingKeystore/signingPassword)") + } +} diff --git a/libcore-stub/build.gradle b/libcore-stub/build.gradle index ca2ce4e29..9c37e77be 100644 --- a/libcore-stub/build.gradle +++ b/libcore-stub/build.gradle @@ -1,3 +1,8 @@ +plugins { + id 'conventions.common' + id 'conventions.jvm' +} + description = 'Conscrypt: libcore Stub' configurations { diff --git a/openjdk-uber/build.gradle b/openjdk-uber/build.gradle index 652afebce..beaff563d 100644 --- a/openjdk-uber/build.gradle +++ b/openjdk-uber/build.gradle @@ -1,3 +1,15 @@ +plugins { + id 'conventions.common' + id 'conventions.boringssl' + id 'conventions.jvm' +} + +repositories { + mavenCentral() + // TODO(prb): Gate this on a property to ensure that local testing can't contaminate releases. + mavenLocal() +} + description = 'Conscrypt: OpenJdk UberJAR' Directory buildTop = layout.buildDirectory.get() diff --git a/openjdk/build.gradle b/openjdk/build.gradle index b145b1793..b63b4c8de 100644 --- a/openjdk/build.gradle +++ b/openjdk/build.gradle @@ -1,4 +1,9 @@ plugins { + id 'conventions.common' + id 'conventions.versionprops' + id 'conventions.boringssl' + id 'conventions.jvm' + id 'conventions.cpp' alias libs.plugins.bnd alias libs.plugins.shadow } @@ -127,6 +132,10 @@ ext { preferredNativeFileDir = buildToTest.nativeResourcesDir() } +// Since we're not taking a direct dependency on the constants module, we need to add an +// explicit task dependency to make sure the code is generated. +evaluationDependsOn(':conscrypt-constants') + sourceSets { main { java { diff --git a/platform/build.gradle b/platform/build.gradle index bb8cf0ae8..bb5f22908 100644 --- a/platform/build.gradle +++ b/platform/build.gradle @@ -1,5 +1,7 @@ plugins { - alias(libs.plugins.android.library) + id 'conventions.common' + id 'conventions.boringssl' + id 'conventions.android' } description = 'Conscrypt: Android Platform' diff --git a/settings.gradle b/settings.gradle index 798dc5bfd..830dc8e7a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -47,3 +47,6 @@ project(':conscrypt-constants').projectDir = "$rootDir/constants" as File project(':conscrypt-openjdk').projectDir = "$rootDir/openjdk" as File project(':conscrypt-openjdk-uber').projectDir = "$rootDir/openjdk-uber" as File project(':conscrypt-testing').projectDir = "$rootDir/testing" as File + +// Include convention plugins +includeBuild 'build-logic' diff --git a/testing/build.gradle b/testing/build.gradle index bae4f8ee5..dda77e406 100644 --- a/testing/build.gradle +++ b/testing/build.gradle @@ -1,4 +1,6 @@ plugins { + id 'conventions.common' + id 'conventions.jvm' alias libs.plugins.shadow }