An enterprise-grade Java-based, Apache 2.0 licensed Ethereum client https://wiki.hyperledger.org/display/besu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
besu/build.gradle

522 lines
16 KiB

/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
import net.ltgt.gradle.errorprone.CheckSeverity
plugins {
id 'com.diffplug.gradle.spotless' version '3.17.0'
id 'com.jfrog.bintray' version '1.8.4'
id 'com.github.ben-manes.versions' version '0.20.0'
id 'com.github.hierynomus.license' version '0.15.0'
id 'io.spring.dependency-management' version '1.0.6.RELEASE'
id 'me.champeau.gradle.jmh' version '0.4.8' apply false
id 'net.ltgt.errorprone' version '0.6.1'
id 'net.researchgate.release' version '2.7.0'
}
group = 'tech.pegasys.pantheon'
defaultTasks 'build', 'checkLicenses', 'javadoc'
def buildAliases = ['dev': [
'spotlessApply',
'build',
'checkLicenses',
'javadoc'
]]
def expandedTaskList = []
gradle.startParameter.taskNames.each {
expandedTaskList << (buildAliases[it] ? buildAliases[it] : it)
}
gradle.startParameter.taskNames = expandedTaskList.flatten()
// Gets a integer command argument, passed with -Pname=x, or the defaut if not provided.
def _intCmdArg(name, defaultValue) {
return project.hasProperty(name) ? project.property(name) as int : defaultValue
}
def _intCmdArg(name) {
return _intCmdArg(name, null)
}
def _strListCmdArg(name, defaultValue) {
if (!project.hasProperty(name))
return defaultValue
return ((String)project.property(name)).tokenize(',')
}
def _strListCmdArg(name) {
return _strListCmdArg(name, null)
}
allprojects {
apply plugin: 'java-library'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'jacoco'
apply plugin: 'net.ltgt.errorprone'
apply from: "${rootDir}/gradle/versions.gradle"
apply from: "${rootDir}/gradle/check-licenses.gradle"
version = rootProject.version
jacoco {
toolVersion = '0.8.2'
if (project.tasks.findByName('referenceTests')) {
applyTo referenceTests
}
}
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
repositories {
if ("$System.env.JENKINS_URL" == 'https://jenkins.pegasys.tech/') {
maven { url "https://nexus.int.pegasys.tech/repository/consensys-pegasys/" }
maven { url "https://nexus.int.pegasys.tech/repository/jcenter/" }
} else {
jcenter()
mavenCentral()
maven { url "https://consensys.bintray.com/pegasys-repo" }
}
}
dependencies {
errorprone("com.google.errorprone:error_prone_core")
if (JavaVersion.current().isJava8()) {
errorproneJavac("com.google.errorprone:javac")
}
}
apply plugin: 'com.diffplug.gradle.spotless'
spotless {
java {
// This path needs to be relative to each project
target fileTree('.') {
include '**/*.java'
exclude '**/generalstate/GeneralStateReferenceTest*.java'
exclude '**/generalstate/GeneralStateRegressionReferenceTest*.java'
exclude '**/blockchain/BlockchainReferenceTest*.java'
exclude '**/pantheon/PantheonInfo.java'
exclude '**/.gradle/**'
}
removeUnusedImports()
googleJavaFormat('1.7')
importOrder 'tech.pegasys', 'java', ''
trimTrailingWhitespace()
endWithNewline()
licenseHeaderFile "${rootDir}/gradle/spotless.java.license"
}
groovyGradle {
target '*.gradle'
greclipse().configFile(rootProject.file('gradle/formatter.properties'))
endWithNewline()
}
// Below this line are currently only license header tasks
format 'groovy', {
target '**/*.groovy'
licenseHeaderFile "${rootDir}/gradle/spotless.java.license", 'import'
}
// Currently disabled due to referencetest issues
// format 'bash', {
// target fileTree('.') {
// include '**/*.sh'
// exclude '**/ansible/**'
// }
// licenseHeaderFile "${rootDir}/gradle/spotless.bash.license", '#!/bin'
// }
// format 'sol', {
// target fileTree('.') { include '**/*.sol' }
// licenseHeaderFile "${rootDir}/gradle/spotless.java.license", '^(pragma|contract)'
// }
}
tasks.withType(JavaCompile) {
options.compilerArgs += [
'-Xlint:unchecked',
'-Xlint:cast',
'-Xlint:rawtypes',
'-Xlint:overloads',
'-Xlint:divzero',
'-Xlint:finally',
'-Xlint:static',
'-Werror',
]
options.errorprone {
excludedPaths '.*/(generated/*.*|.*ReferenceTest_.*)'
// Our equals need to be symmetric, this checker doesn't respect that.
check('EqualsGetClass', CheckSeverity.OFF)
// We like to use futures with no return values.
check('FutureReturnValueIgnored', CheckSeverity.OFF)
// We use the JSR-305 annotations instead of the Google annotations.
check('ImmutableEnumChecker', CheckSeverity.OFF)
// This is a style check instead of an error-prone pattern.
check('UnnecessaryParentheses', CheckSeverity.OFF)
// Lazy impl causes excess CPU usage O(n) of non-final fiield when it should be O(1).
check('FieldCanBeFinal', CheckSeverity.OFF)
check('InsecureCryptoUsage', CheckSeverity.WARN)
check('WildcardImport', CheckSeverity.WARN)
}
options.encoding = 'UTF-8'
}
/*
* Pass some system properties provided on the gradle command line to test executions for
* convenience.
*
* The properties passed are:
* - 'test.ethereum.include': allows to run a single Ethereum reference tests. For instance,
* running a single general state test can be done with:
* ./gradlew :ethereum:tech.pegasys.pantheon.ethereum.vm:test -Dtest.single=GeneralStateTest -Dtest.ethereum.include=callcodecallcallcode_101-Frontier
* The meaning being that will be run only the tests for which the value passed as "include"
* (which can be a java pattern) matches parts of the test name. Knowing that tests names for
* reference tests are of the form:
* <name>(-<milestone>([<variant>])?)?
* where <name> is the test name as defined in the json file (usually the name of the json file
* as well), <milestone> is the Ethereum milestone tested (not all test use it) and <variant>
* is only use in some general state tests where for the same json file and same milestone,
* multiple variant of that test are run. The variant is a simple number.
* - 'test.ethereum.state.eip': for general state tests, allows to only run tests for the
* milestone specified by this value. So for instance,
* ./gradlew :ethereum:tech.pegasys.pantheon.ethereum.vm:test -Dtest.single=GeneralStateTest -Dtest.ethereum.state.eip=Frontier
* only run general state tests for Frontier. Note that this behavior could be achieved as well
* with the 'include' option above since it is a pattern, but this is a slightly more convenient
* option.
* - 'root.log.level' and 'evm.log.level': allow to control the log level used during the tests.
*/
test {
jvmArgs = [
'-Xmx4g',
'-XX:-UseGCOverheadLimit'
]
Set toImport = [
'test.ethereum.include',
'test.ethereum.state.eip',
'root.log.level',
'evm.log.level'
]
for (String name : toImport) {
if (System.getProperty(name) != null) {
systemProperty name, System.getProperty(name)
}
}
}
// Normalise Xdoclint behaviour across JDKs (OpenJDK 8 is more lenient than Oracle JDK by default).
javadoc {
options.addStringOption('Xdoclint:all', '-quiet')
if (JavaVersion.current() == JavaVersion.VERSION_1_8) {
options.addStringOption('Xwerror', '-quiet')
} else {
options.addStringOption('Xwerror', '-html5')
}
options.encoding = 'UTF-8'
}
}
task deploy() {}
subprojects {
tasks.withType(Test) {
// If GRADLE_MAX_TEST_FORKS is not set, use half the available processors
maxParallelForks = (System.getenv('GRADLE_MAX_TEST_FORKS') ?: (Runtime.runtime.availableProcessors().intdiv(2) ?: 1)).toInteger()
}
tasks.withType(JavaCompile) {
options.fork = true
options.incremental = true
}
apply plugin: 'maven-publish'
sourceSets {
// test-support can be consumed as a library by other projects in their tests
testSupport {
java {
compileClasspath += main.output
runtimeClasspath += main.output
srcDir file('src/test-support/java')
}
resources.srcDir file('src/test-support/resources')
}
integrationTest {
java {
compileClasspath += main.output
runtimeClasspath += main.output
srcDir file('src/integration-test/java')
}
resources.srcDir file('src/integration-test/resources')
}
}
configurations {
testSupportImplementation.extendsFrom implementation
integrationTestImplementation.extendsFrom implementation
testSupportArtifacts
}
task testSupportJar (type: Jar) {
baseName = "${project.name}-support-test"
from sourceSets.testSupport.output
}
dependencies {
testImplementation sourceSets.testSupport.output
integrationTestImplementation sourceSets.testSupport.output
}
task integrationTest(type: Test, dependsOn:["compileTestJava"]){
group = "verification"
description = "Runs the Pantheon integration tests"
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
outputs.upToDateWhen { false }
}
if (file('src/jmh').directory) {
apply plugin: 'me.champeau.gradle.jmh'
jmh {
// Allows to control JMH execution directly from the command line. I typical execution may look
// like:
// gradle jmh -Pf=2 -Pwi=3 -Pi=5 -Pinclude=MyBench
// which will run 2 forks with 3 warmup iterations and 5 normal ones for each, and will only
// run the benchmark matching 'MyBench' (a regexp).
warmupForks = _intCmdArg('wf')
warmupIterations = _intCmdArg('wi')
fork = _intCmdArg('f')
iterations = _intCmdArg('i')
benchmarkMode = _strListCmdArg('bm')
include = _strListCmdArg('include', [''])
humanOutputFile = project.file("${project.buildDir}/reports/jmh/results.txt")
resultFormat = 'JSON'
}
dependencies { jmh 'org.apache.logging.log4j:log4j-api' }
}
}
jar { enabled = false }
apply plugin: 'application'
mainClassName = "tech.pegasys.pantheon.Pantheon"
applicationDefaultJvmArgs = [
"-Dvertx.disableFileCPResolving=true",
"-Dpantheon.home=PANTHEON_HOME",
// We shutdown log4j ourselves, as otherwise his shutdown hook runs before our own and whatever
// happens during shutdown is not logged.
"-Dlog4j.shutdownHookEnabled=false"
]
run {
args project.hasProperty("pantheon.run.args") ? project.property("pantheon.run.args").toString().split("\\s+") : []
doFirst {
applicationDefaultJvmArgs = applicationDefaultJvmArgs.collect{it.replace('PANTHEON_HOME', "$buildDir/pantheon")}
}
}
startScripts {
def shortenWindowsClasspath = { line ->
line = line.replaceAll(/^set CLASSPATH=.*$/, "set CLASSPATH=%APP_HOME%/lib/*")
}
doLast {
unixScript.text = unixScript.text.replace('PANTHEON_HOME', '\$APP_HOME')
windowsScript.text = windowsScript.text.replace('PANTHEON_HOME', '%~dp0..')
// Prevent the error originating from the 8191 chars limit on Windows
windowsScript.text =
windowsScript
.readLines()
.collect(shortenWindowsClasspath)
.join('\r\n')
}
}
dependencies {
compile project(':pantheon')
errorprone 'com.google.errorprone:error_prone_core'
}
distributions {
main {
contents {
from("./LICENSE") { into "." }
from("build/reports/license/license-dependency.html") { into "." }
from("./docs/GettingStartedBinaries.md") { into "." }
from("./docs/DocsArchive0.8.0.html") { into "." }
}
}
}
installDist { dependsOn checkLicenses }
distTar {
dependsOn checkLicenses
doFirst {
delete fileTree(dir: 'build/distributions', include: '*.tar.gz')
}
compression = Compression.GZIP
extension = 'tar.gz'
}
distZip {
dependsOn checkLicenses
doFirst {
delete fileTree(dir: 'build/distributions', include: '*.zip')
}
}
task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
additionalSourceDirs.from files(subprojects.sourceSets.main.allSource.srcDirs)
sourceDirectories.from files(subprojects.sourceSets.main.allSource.srcDirs)
classDirectories.from files(subprojects.sourceSets.main.output)
executionData.from fileTree(dir: '.', includes: ['**/jacoco/*.exec'])
reports {
xml.enabled true
csv.enabled true
html.destination file("build/reports/jacocoHtml")
}
onlyIf = { true }
}
configurations { annotationProcessor }
// Prevent errorprone-checks being dependent upon errorprone-checks!
// However, ensure all subprojects comply with the custom rules.
configure(subprojects.findAll {it.name != 'errorprone-checks'}) {
dependencies { annotationProcessor project(":errorprone-checks") }
tasks.withType(JavaCompile) {
options.annotationProcessorPath = configurations.annotationProcessor
}
}
// Takes the version, and if -SNAPSHOT is part of it replaces SNAPSHOT
// with the git commit version.
def calculateVersion() {
String version = rootProject.version
if (version.endsWith("-SNAPSHOT")) {
version = version.replace("-SNAPSHOT", "-dev-" + getCheckedOutGitCommitHash())
}
return version
}
def getCheckedOutGitCommitHash() {
def gitFolder = "$projectDir/.git/"
if (!file(gitFolder).isDirectory()) {
// We are in a submodule. The file's contents are `gitdir: <gitFolder>\n`.
// Read the file, cut off the front, and trim the whitespace.
gitFolder = file(gitFolder).text.substring(8).trim() + "/"
}
def takeFromHash = 8
/*
* '.git/HEAD' contains either
* in case of detached head: the currently checked out commit hash
* otherwise: a reference to a file containing the current commit hash
*/
def head = new File(gitFolder + "HEAD").text.split(":") // .git/HEAD
def isCommit = head.length == 1 // e5a7c79edabbf7dd39888442df081b1c9d8e88fd
if(isCommit) return head[0].trim().take(takeFromHash) // e5a7c79edabb
def refHead = new File(gitFolder + head[1].trim()) // .git/refs/heads/master
refHead.text.trim().take takeFromHash
}
apply plugin: 'net.researchgate.release'
task releaseIntegrationTest(type: Test){
for(TaskContainer taskList : subprojects.tasks){
def subProjectIntegrationTask = taskList.findByName('integrationTest')
if (subProjectIntegrationTask != null) {
dependsOn subProjectIntegrationTask
}
}
}
task releaseReferenceTest(type: Test, dependsOn : [
':ethereum:core:referenceTests',
':ethereum:rlp:referenceTests',
':ethereum:trie:referenceTests'
]){
}
task releaseAcceptanceTest(type: Test, dependsOn : ':acceptance-tests:acceptanceTest') {}
release {
preTagCommitMessage = '[Gradle Release Plugin] - pre tag commit: '
tagCommitMessage = '[Gradle Release Plugin] - creating tag: '
newVersionCommitMessage = '[Gradle Release Plugin] - new version commit: '
buildTasks = [
'build',
'releaseIntegrationTest',
'releaseAcceptanceTest',
'releaseReferenceTest',
'checkLicenses',
'javadoc'
]
git {
requireBranch = project.hasProperty('release.branch') ? project.property('release.branch') : 'master'
}
}
apply plugin: 'com.jfrog.bintray'
bintray {
user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER')
key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_KEY')
filesSpec {
from distTar.destinationDir.path
from distZip.destinationDir.path
into '.'
}
publish = true
pkg {
repo = 'pegasys-repo'
name = 'pantheon'
userOrg = 'consensys'
licenses = ['Apache-2.0']
websiteUrl = 'https://github.com/PegaSysEng/pantheon'
issueTrackerUrl = 'https://github.com/PegaSysEng/pantheon/issues'
vcsUrl = 'https://github.com/PegaSysEng/pantheon.git'
version {
name = project.version
released = new Date()
}
}
}
afterReleaseBuild.dependsOn bintrayUpload
bintrayUpload.mustRunAfter(distTar)
bintrayUpload.mustRunAfter(distZip)