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