1// ASM: a very small and fast Java bytecode manipulation framework 2// Copyright (c) 2000-2011 INRIA, France Telecom 3// All rights reserved. 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions 7// are met: 8// 1. Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// 2. Redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution. 13// 3. Neither the name of the copyright holders nor the names of its 14// contributors may be used to endorse or promote products derived from 15// this software without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27// THE POSSIBILITY OF SUCH DAMAGE. 28 29buildscript { 30 repositories { mavenCentral() } 31 dependencies { classpath 'org.netbeans.tools:sigtest-maven-plugin:1.5' } 32} 33 34plugins { id 'com.github.sherter.google-java-format' version '0.9' apply false } 35plugins { id 'me.champeau.jmh' version '0.6.8' apply false } 36plugins { id 'org.sonarqube' version '3.5.0.2730' apply false } 37 38description = 'ASM, a very small and fast Java bytecode manipulation framework' 39 40apply plugin: 'java-platform' 41dependencies { 42 constraints { 43 api project(':asm'), project(':asm-tree'), project(':asm-analysis') 44 api project(':asm-util'), project(':asm-commons') 45 } 46} 47 48allprojects { 49 group = 'org.ow2.asm' 50 version = '9.5' + (rootProject.hasProperty('release') ? '' : '-SNAPSHOT') 51} 52 53subprojects { 54 repositories { mavenCentral() } 55 apply plugin: 'java-library' 56 apply plugin: 'jacoco' 57 sourceCompatibility = '1.8' 58 targetCompatibility = '1.8' 59 test { useJUnitPlatform() } 60 ext.provides = [] // The provided java packages, e.g. ['org.objectweb.asm'] 61 ext.requires = [] // The required Gradle projects, e.g. [':asm-test'] 62 ext.transitiveRequires = { -> 63 return requires.collect{project(it)} 64 .collect{it.transitiveRequires().plus(it.provides[0])}.flatten() as Set 65 } 66 ext.transitiveImports = { -> 67 return requires.collect{project(it)} 68 .collect{it.transitiveImports().plus(it.provides)}.flatten() as Set 69 } 70 ext.depends = [] // The external dependencies, e.g. ['junit:junit:4.12'] 71 // Some external dependencies (such as Jacoco) depend transitively on ASM, and 72 // without this rule Gradle can mix ASM jars of different versions (e.g. 73 // asm-6.0.jar with the asm-tree.jar built locally). 74 configurations.all { resolutionStrategy { preferProjectModules() } } 75} 76 77// ----------------------------------------------------------------------------- 78// Project descriptions 79// ----------------------------------------------------------------------------- 80 81project(':asm') { 82 description = parent.description 83 provides = ['org.objectweb.asm', 'org.objectweb.asm.signature'] 84} 85 86project(':asm-analysis') { 87 description = "Static code analysis API of ${parent.description}" 88 provides = ['org.objectweb.asm.tree.analysis'] 89 requires = [':asm-tree'] 90} 91 92project(':asm-commons') { 93 description = "Usefull class adapters based on ${parent.description}" 94 provides = ['org.objectweb.asm.commons'] 95 requires = [':asm', ':asm-tree'] 96 dependencies { testImplementation project(':asm-util') } 97} 98 99project(':asm-test') { 100 description = "Utilities for testing ${parent.description}" 101 provides = ['org.objectweb.asm.test'] 102 depends = ['org.junit.jupiter:junit-jupiter-api:5.9.1', 103 'org.junit.jupiter:junit-jupiter-params:5.9.1'] 104} 105 106project(':asm-tree') { 107 description = "Tree API of ${parent.description}" 108 provides = ['org.objectweb.asm.tree'] 109 requires = [':asm'] 110} 111 112project(':asm-util') { 113 description = "Utilities for ${parent.description}" 114 provides = ['org.objectweb.asm.util'] 115 requires = [':asm', ':asm-tree', ':asm-analysis'] 116 dependencies { testImplementation 'org.codehaus.janino:janino:3.1.9' } 117} 118 119// Use "gradle benchmarks:jmh [-PjmhInclude='<regex>']" to run the benchmarks. 120project(':benchmarks') { 121 description = "Benchmarks for ${rootProject.description}" 122 apply plugin: 'me.champeau.jmh' 123 dependencies { 124 implementation files('libs/csg-bytecode-1.0.0.jar', 'libs/jclasslib.jar') 125 jmh project(':asm'), project(':asm-tree') 126 } 127 depends = [ 128 'kawa:kawa:1.7', 129 'net.sf.jiapi:jiapi-reflect:0.5.2', 130 'net.sourceforge.serp:serp:1.15.1', 131 'org.apache.bcel:bcel:6.0', 132 'org.aspectj:aspectjweaver:1.8.10', 133 'org.cojen:cojen:2.2.5', 134 'org.javassist:javassist:3.21.0-GA', 135 'org.mozilla:rhino:1.7.7.1' 136 ] 137 ['4.0', '5.0.1', '6.0', '7.0', '8.0.1', '9.0'].each { version -> 138 configurations.create("asm${version}") 139 dependencies.add("asm${version}", "org.ow2.asm:asm:${version}@jar") 140 dependencies.add("asm${version}", "org.ow2.asm:asm-tree:${version}@jar") 141 task "asm${version}"(type: Copy) { 142 from configurations."asm${version}".collect{zipTree(it)} 143 into "${buildDir}/asm${version}" 144 duplicatesStrategy = DuplicatesStrategy.INCLUDE // module-info.class 145 } 146 classes.dependsOn "asm${version}" 147 } 148 configurations.create('input-classes-java8') 149 dependencies.add('input-classes-java8', 'io.vavr:vavr:0.10.0@jar') 150 task copyInputClasses(type: Copy) { 151 from configurations.'input-classes-java8'.collect{zipTree(it)} 152 into "${buildDir}/input-classes-java8" 153 } 154 classes.dependsOn copyInputClasses 155 jmh { 156 jvmArgsAppend = ["-Duser.dir=${rootDir}"] 157 resultFormat = 'CSV' 158 profilers = ['org.objectweb.asm.benchmarks.MemoryProfiler'] 159 if (rootProject.hasProperty('jmhInclude')) { 160 includes = [jmhInclude] 161 } 162 } 163} 164 165project(':tools') { 166 description = "Tools used to build ${parent.description}" 167} 168 169project(':tools:retrofitter') { 170 description = "JDK 1.5 class retrofitter based on ${rootProject.description}" 171 sourceCompatibility = '1.9' 172 targetCompatibility = '1.9' 173 // TODO: this compiles asm twice (here and in :asm). 174 sourceSets.main.java.srcDirs += project(':asm').sourceSets.main.java.srcDirs 175} 176 177// ----------------------------------------------------------------------------- 178// Project tasks creation and configuration 179// ----------------------------------------------------------------------------- 180 181// All projects are checked with googleJavaFormat, Checkstyle and PMD, 182// and tested with :asm-test and JUnit. 183subprojects { 184 apply plugin: 'com.github.sherter.google-java-format' 185 googleJavaFormat.toolVersion = '1.15.0' 186 googleJavaFormat.exclude 'src/resources/java/**/*' 187 188 // Check the coding style with Checkstyle. Fail in case of error or warning. 189 apply plugin: 'checkstyle' 190 checkstyle.configFile = file("${rootDir}/tools/checkstyle.xml") 191 checkstyle.maxErrors = 0 192 checkstyle.maxWarnings = 0 193 194 // Check the code with PMD. 195 apply plugin: 'pmd' 196 pmd.ruleSets = [] 197 pmd.ruleSetFiles = files("${rootDir}/tools/pmd.xml") 198 pmd.consoleOutput = true 199 200 dependencies { 201 requires.each { projectName -> api project(projectName) } 202 depends.each { artifactName -> api artifactName } 203 testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.1', 204 'org.junit.jupiter:junit-jupiter-params:5.9.1' 205 testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.1' 206 testImplementation project(':asm-test') 207 } 208 209 // Produce byte-for-byte reproducible archives. 210 tasks.withType(AbstractArchiveTask).configureEach { 211 preserveFileTimestamps = false 212 reproducibleFileOrder = true 213 dirMode = 0775 214 fileMode = 0664 215 } 216} 217 218// Configure the projects with a non-empty 'provides' property. They must be 219// checked for code coverage and backward compatibility, retrofited to Java 1.5, 220// and packaged with generated module-info classes. 221configure(subprojects.findAll{it.provides}) { 222 // Code coverage configuration. 223 jacoco.toolVersion = '0.8.8' 224 jacocoTestReport { 225 reports { xml.required = true } 226 classDirectories.setFrom(sourceSets.main.output.classesDirs) 227 } 228 jacocoTestCoverageVerification { 229 classDirectories.setFrom(sourceSets.main.output.classesDirs) 230 violationRules.rule { limit { minimum = 0.95; counter = 'INSTRUCTION' } } 231 } 232 check.dependsOn jacocoTestCoverageVerification 233 234 // Retrofit the code in-place to Java 1.5 and generate a module-info class 235 // from the code content, in compileJava.doLast. 236 if (name != 'asm-test') { 237 compileJava.dependsOn ':tools:retrofitter:classes' 238 compileJava.doLast { 239 def path = project(':tools:retrofitter').sourceSets.main.runtimeClasspath 240 def loader = new URLClassLoader(path.collect {f -> f.toURL()} as URL[]) 241 def retrofitter = 242 loader.loadClass('org.objectweb.asm.tools.Retrofitter').newInstance() 243 def classes = sourceSets.main.output.classesDirs.singleFile 244 def requires = transitiveRequires() as List 245 retrofitter.retrofit(classes, "${version}") 246 retrofitter.verify(classes, "${version}", provides, requires) 247 } 248 } 249 250 // Create one backward compatibility checking task for each 'sigtest-*' file 251 // in test/resources, and make the 'check' task depend on all these tasks. 252 if (file('src/test/resources/').exists()) { 253 file('src/test/resources/').eachFileMatch(~/sigtest-.*/) { f -> 254 task "${f.name}"(dependsOn: 'classes') { 255 inputs.files(f, sourceSets.main.java) 256 outputs.file("${buildDir}/${f.name}") 257 doLast { 258 def sigtest = new com.sun.tdk.signaturetest.SignatureTest() 259 def args = ['-ApiVersion', version, '-Backward', '-Static', 260 '-Mode', 'bin', '-FileName', f, '-Classpath', 261 project(':tools').file('jdk8-api.jar').path + File.pathSeparator + 262 sourceSets.main.output.classesDirs.asPath, '-Package'] + provides 263 outputs.getFiles()[0].withPrintWriter { printWriter -> 264 sigtest.run(args as String[], printWriter, null) 265 } 266 if (!sigtest.isPassed()) throw new GradleException() 267 } 268 } 269 check.dependsOn f.name 270 } 271 // Define a task to create a sigtest file for the current version. 272 task "buildSigtest"(dependsOn: 'classes') { 273 inputs.files(sourceSets.main.java) 274 outputs.file("src/test/resources/sigtest-${version}.txt") 275 doLast { 276 def setup = new com.sun.tdk.signaturetest.Setup() 277 def args = ['-ApiVersion', version, '-FileName', outputs.getFiles()[0], 278 '-Classpath', project(':tools').file('jdk8-api.jar').path + 279 File.pathSeparator + sourceSets.main.output.classesDirs.asPath + 280 File.pathSeparator + sourceSets.main.compileClasspath.asPath, 281 '-Package'] + provides 282 setup.run(args as String[], new PrintWriter(System.err, true), null) 283 if (!setup.isPassed()) throw new GradleException() 284 } 285 } 286 } 287 288 jar.manifest.attributes( 289 'Implementation-Title': project.description, 290 'Implementation-Version': "${version}") 291 // Package the project as an OSGi bundle. Exclude the asm-test project (the 292 // DefaultPackage class prevents it from being a proper bundle). 293 if (name != 'asm-test') { 294 def imports = transitiveImports() 295 jar.manifest.attributes( 296 'Bundle-DocURL': 'http://asm.ow2.org', 297 'Bundle-License': 'BSD-3-Clause;link=https://asm.ow2.io/LICENSE.txt', 298 'Bundle-ManifestVersion': 2, 299 'Bundle-Name': provides[0], 300 'Bundle-RequiredExecutionEnvironment': 'J2SE-1.5', 301 'Bundle-SymbolicName': provides[0], 302 'Bundle-Version': "${version}", 303 'Export-Package': 304 provides.collect{"${it};version=\"${version}\""}.join(',') + 305 (imports ? ";uses:=\"${imports.join(',')}\"" : "")) 306 if (imports) { 307 jar.manifest.attributes( 308 'Import-Package': 309 imports.collect{"${it};version=\"${version}\""}.join(','), 310 'Module-Requires': 311 transitiveRequires().collect{"${it};transitive=true"}.join(',')) 312 } 313 } 314 315 // Apply the SonarQube plugin to monitor the code quality of the project. 316 // Use with 'gradlew sonarqube -Dsonar.host.url=https://sonarqube.ow2.org'. 317 apply plugin: 'org.sonarqube' 318 sonarqube { 319 properties { property 'sonar.projectKey', "ASM:${project.name}" } 320 } 321 322 // Add a task to generate a private javadoc and add it as a dependency of the 323 // 'check' task. 324 task privateJavadoc(type: Javadoc) { 325 source = sourceSets.main.allJava 326 classpath = configurations.compileClasspath 327 destinationDir = file("${javadoc.destinationDir}-private") 328 options.memberLevel = JavadocMemberLevel.PRIVATE 329 options.addBooleanOption('Xdoclint:all,-missing', true) 330 } 331 check.dependsOn privateJavadoc 332 333 // Add tasks to generate the Javadoc and a source jar, to be uploaded to Maven 334 // together with the main jar (containing the compiled code). 335 task javadocJar(type: Jar, dependsOn: 'javadoc') { 336 from javadoc.destinationDir 337 classifier 'javadoc' 338 } 339 task sourcesJar(type: Jar, dependsOn: 'classes') { 340 from sourceSets.main.allSource 341 classifier 'sources' 342 } 343 java { 344 withJavadocJar() 345 withSourcesJar() 346 } 347} 348 349// Configure the root project, and those with a non-empty 'provides' property, 350// to be published in Maven with a POM. 351configure([rootProject] + subprojects.findAll { it.provides }) { 352 apply plugin: 'maven-publish' 353 apply plugin: 'signing' 354 publishing { 355 repositories { 356 maven { 357 def baseUrl = 'https://repository.ow2.org/nexus/' 358 def releasesUrl = baseUrl + 'service/local/staging/deploy/maven2' 359 def snapshotsUrl = baseUrl + 'content/repositories/snapshots' 360 name = 'nexus' 361 url = rootProject.hasProperty('release') ? releasesUrl : snapshotsUrl 362 credentials { 363 username System.env.NEXUS_USER_NAME 364 password System.env.NEXUS_PASSWORD 365 } 366 } 367 } 368 publications { 369 maven(MavenPublication) { 370 def isRoot = project == rootProject 371 artifactId (isRoot ? 'asm-bom' : project.name) 372 from (isRoot ? components.javaPlatform : components.java) 373 pom.withXml { 374 def parent = asNode().appendNode('parent') 375 parent.appendNode('groupId', 'org.ow2') 376 parent.appendNode('artifactId', 'ow2') 377 parent.appendNode('version', '1.5.1') 378 } 379 pom { 380 name = artifactId 381 description = project.description 382 packaging 'jar' 383 inceptionYear = '2000' 384 licenses { 385 license { 386 name = 'BSD-3-Clause' 387 url = 'https://asm.ow2.io/license.html' 388 } 389 } 390 url = 'http://asm.ow2.io/' 391 mailingLists { 392 mailingList { 393 name = 'ASM Users List' 394 subscribe = 'https://mail.ow2.org/wws/subscribe/asm' 395 post = 'asm@objectweb.org' 396 archive = 'https://mail.ow2.org/wws/arc/asm/' 397 } 398 mailingList { 399 name = 'ASM Team List' 400 subscribe = 'https://mail.ow2.org/wws/subscribe/asm-team' 401 post = 'asm-team@objectweb.org' 402 archive = 'https://mail.ow2.org/wws/arc/asm-team/' 403 } 404 } 405 issueManagement { 406 url = 'https://gitlab.ow2.org/asm/asm/issues' 407 } 408 scm { 409 connection = 'scm:git:https://gitlab.ow2.org/asm/asm/' 410 developerConnection = 'scm:git:https://gitlab.ow2.org/asm/asm/' 411 url = 'https://gitlab.ow2.org/asm/asm/' 412 } 413 developers { 414 developer { 415 name = 'Eric Bruneton' 416 id = 'ebruneton' 417 email = 'ebruneton@free.fr' 418 roles = ['Creator', 'Java Developer'] 419 } 420 developer { 421 name = 'Eugene Kuleshov' 422 id = 'eu' 423 email = 'eu@javatx.org' 424 roles = ['Java Developer'] 425 } 426 developer { 427 name = 'Remi Forax' 428 id = 'forax' 429 email = 'forax@univ-mlv.fr' 430 roles = ['Java Developer'] 431 } 432 } 433 organization { 434 name = 'OW2' 435 url = 'http://www.ow2.org/' 436 } 437 } 438 } 439 } 440 } 441 signing { 442 required rootProject.hasProperty('release') 443 sign publishing.publications.maven 444 } 445 tasks.withType(GenerateModuleMetadata) { enabled = false } 446} 447