mirror of https://github.com/apache/jmeter.git
678 lines
24 KiB
Plaintext
678 lines
24 KiB
Plaintext
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to you 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 com.github.vlsi.gradle.crlf.CrLfSpec
|
|
import com.github.vlsi.gradle.crlf.LineEndings
|
|
import com.github.vlsi.gradle.git.FindGitAttributes
|
|
import com.github.vlsi.gradle.git.dsl.gitignore
|
|
import com.github.vlsi.gradle.properties.dsl.props
|
|
import org.gradle.api.internal.TaskOutputsInternal
|
|
import kotlin.math.absoluteValue
|
|
|
|
plugins {
|
|
id("build-logic.build-params")
|
|
id("com.github.vlsi.crlf")
|
|
id("com.github.vlsi.stage-vote-release")
|
|
id("build-logic.jvm-library")
|
|
}
|
|
|
|
var jars = arrayOf(
|
|
":src:bshclient",
|
|
":src:launcher",
|
|
":src:components",
|
|
":src:core",
|
|
// ":src:examples",
|
|
":src:functions",
|
|
":src:jorphan",
|
|
":src:protocol:bolt",
|
|
":src:protocol:ftp",
|
|
":src:protocol:http",
|
|
":src:protocol:java",
|
|
":src:protocol:jdbc",
|
|
":src:protocol:jms",
|
|
":src:protocol:junit",
|
|
":src:protocol:ldap",
|
|
":src:protocol:mail",
|
|
":src:protocol:mongodb",
|
|
":src:protocol:native",
|
|
":src:protocol:tcp"
|
|
)
|
|
|
|
// https://github.com/gradle/gradle/pull/16627
|
|
inline fun <reified T : Named> AttributeContainer.attribute(attr: Attribute<T>, value: String) =
|
|
attribute(attr, objects.named<T>(value))
|
|
|
|
// isCanBeConsumed = false ==> other modules must not use the configuration as a dependency
|
|
val buildDocs by configurations.creating {
|
|
isCanBeConsumed = false
|
|
}
|
|
val generatorJar by configurations.creating {
|
|
isCanBeConsumed = false
|
|
}
|
|
val junitSampleJar by configurations.creating {
|
|
isCanBeConsumed = false
|
|
isTransitive = false
|
|
attributes {
|
|
attribute(Category.CATEGORY_ATTRIBUTE, Category.LIBRARY)
|
|
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, LibraryElements.JAR)
|
|
attribute(Usage.USAGE_ATTRIBUTE, Usage.JAVA_RUNTIME)
|
|
attribute(Bundling.BUNDLING_ATTRIBUTE, Bundling.EXTERNAL)
|
|
}
|
|
}
|
|
val binLicense by configurations.creating {
|
|
isCanBeConsumed = false
|
|
}
|
|
val srcLicense by configurations.creating {
|
|
isCanBeConsumed = false
|
|
}
|
|
|
|
// Note: you can inspect final classpath (list of jars in the binary distribution) via
|
|
// gw dependencies --configuration runtimeClasspath
|
|
dependencies {
|
|
for (p in jars) {
|
|
api(project(p))
|
|
}
|
|
|
|
binLicense(project(":src:licenses", "binLicense"))
|
|
srcLicense(project(":src:licenses", "srcLicense"))
|
|
generatorJar(project(":src:generator", "archives"))
|
|
junitSampleJar(project(":src:protocol:junit-sample"))
|
|
|
|
buildDocs(platform(projects.src.bomThirdparty))
|
|
buildDocs("org.apache.velocity:velocity")
|
|
buildDocs("commons-lang:commons-lang")
|
|
buildDocs("org.apache.commons:commons-collections4")
|
|
buildDocs("org.jdom:jdom")
|
|
}
|
|
|
|
tasks.clean {
|
|
// copyLibs uses Sync task, so it can't predict all the possible output files (e.g. from previous executions)
|
|
// So we register patterns to remove explicitly
|
|
delete(fileTree("$rootDir/bin") { include("ApacheJMeter.jar") })
|
|
delete(fileTree("$rootDir/lib") { include("*.jar") })
|
|
delete(fileTree("$rootDir/lib/ext") { include("ApacheJMeter*.jar") })
|
|
delete(fileTree("$rootDir/lib/junit") { include("test.jar") })
|
|
}
|
|
|
|
// Libs are populated dynamically since we can't get the full set of dependencies
|
|
// before we execute all the build scripts
|
|
val libs = copySpec {
|
|
// Third-party dependencies + jorphan.jar
|
|
}
|
|
|
|
val libsExt = copySpec {
|
|
// Apache JMeter jars
|
|
}
|
|
|
|
val binLibs = copySpec {
|
|
// ApacheJMeter.jar launcher
|
|
}
|
|
|
|
// Splits jar dependencies to "lib", "lib/ext", and "bin" folders
|
|
val populateLibs by tasks.registering {
|
|
dependsOn(configurations.runtimeClasspath)
|
|
doLast {
|
|
val deps = configurations.runtimeClasspath.get().resolvedConfiguration.resolvedArtifacts
|
|
// This ensures project exists, if project is renamed, names should be corrected here as wells
|
|
val launcherProject = projects.src.launcher.path
|
|
val bshclientProject = projects.src.bshclient.path
|
|
val jorphanProject = projects.src.jorphan.path
|
|
listOf(libs, libsExt, binLibs).forEach {
|
|
it.filePermissions {
|
|
unix("rw-r--r--")
|
|
}
|
|
it.dirPermissions {
|
|
unix("rwxr-xr-x")
|
|
}
|
|
}
|
|
for (dep in deps) {
|
|
val compId = dep.id.componentIdentifier
|
|
if (compId !is ProjectComponentIdentifier) {
|
|
// Move all non-JMeter jars to lib folder
|
|
libs.from(dep.file)
|
|
continue
|
|
}
|
|
// JMeter jars are spread across $root/bin, $root/libs, and $root/libs/ext
|
|
// for historical reasons
|
|
when (compId.projectPath) {
|
|
launcherProject -> binLibs
|
|
jorphanProject, bshclientProject -> libs
|
|
else -> libsExt
|
|
}.from(dep.file) {
|
|
// Remove version from the file name
|
|
rename { dep.name + "." + dep.extension }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
val updateExpectedJars by props()
|
|
|
|
val verifyReleaseDependencies by tasks.registering {
|
|
description = "Verifies if binary release archive contains the expected set of external jars"
|
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
|
|
|
dependsOn(configurations.runtimeClasspath)
|
|
val expectedLibs = file("src/dist/expected_release_jars.csv")
|
|
inputs.file(expectedLibs)
|
|
inputs.property("updateExpectedJars", updateExpectedJars)
|
|
val actualLibs = layout.buildDirectory.file("dist/expected_release_jars.csv")
|
|
outputs.file(actualLibs)
|
|
val ignoreJarsMismatch = version.toString().endsWith("-SNAPSHOT")
|
|
if (ignoreJarsMismatch || updateExpectedJars) {
|
|
// The task does not fail in case of -SNAPSHOT version, so we make the task never UP-TO-DATE
|
|
// in that case. Otherwise, the task never executes on the second request, even if the user runs with
|
|
// -PupdateExpectedJars
|
|
outputs.upToDateWhen { false }
|
|
}
|
|
doLast {
|
|
val caseInsensitive: Comparator<String> = compareBy(String.CASE_INSENSITIVE_ORDER, { it })
|
|
|
|
val deps = configurations.runtimeClasspath.get().resolvedConfiguration.resolvedArtifacts
|
|
val libs = deps.asSequence()
|
|
.filter {
|
|
val compId = it.id.componentIdentifier
|
|
compId !is ProjectComponentIdentifier || !compId.build.isCurrentBuild
|
|
}
|
|
.map { it.file.name to it.file.length() }
|
|
.sortedWith(compareBy(caseInsensitive) { it.first })
|
|
.associate { it }
|
|
|
|
val expected = expectedLibs.readLines().asSequence()
|
|
.filter { "," in it }
|
|
.map {
|
|
val (length, name) = it.split(",", limit = 2)
|
|
name to length.toLong()
|
|
}
|
|
.associate { it }
|
|
|
|
if (libs == expected) {
|
|
return@doLast
|
|
}
|
|
|
|
val sb = StringBuilder()
|
|
sb.append("External dependencies differ (you could update ${expectedLibs.relativeTo(rootDir)} if you run $path -PupdateExpectedJars):")
|
|
|
|
val sizeBefore = expected.values.sum()
|
|
val sizeAfter = libs.values.sum()
|
|
if (sizeBefore != sizeAfter) {
|
|
sb.append("\n $sizeBefore => $sizeAfter bytes")
|
|
sb.append(" (${if (sizeAfter > sizeBefore) "+" else "-"}${(sizeAfter - sizeBefore).absoluteValue} byte")
|
|
if ((sizeAfter - sizeBefore).absoluteValue > 1) {
|
|
sb.append("s")
|
|
}
|
|
sb.append(")")
|
|
}
|
|
if (libs.size != expected.size) {
|
|
sb.append("\n ${expected.size} => ${libs.size} files")
|
|
sb.append(" (${if (libs.size > expected.size) "+" else "-"}${(libs.size - expected.size).absoluteValue})")
|
|
}
|
|
sb.appendLine()
|
|
for (dep in (libs.keys + expected.keys).sortedWith(caseInsensitive)) {
|
|
val old = expected[dep]
|
|
val new = libs[dep]
|
|
if (old == new) {
|
|
continue
|
|
}
|
|
sb.append("\n")
|
|
if (old != null) {
|
|
sb.append("-").append(old.toString().padStart(8))
|
|
} else {
|
|
sb.append("+").append(new.toString().padStart(8))
|
|
}
|
|
sb.append(" ").append(dep)
|
|
}
|
|
val newline = System.getProperty("line.separator")
|
|
val actualLibsFile = actualLibs.get().asFile
|
|
actualLibsFile.writeText(
|
|
libs.map { "${it.value},${it.key}" }.joinToString(newline, postfix = newline)
|
|
)
|
|
if (updateExpectedJars) {
|
|
println("Updating ${expectedLibs.relativeTo(rootDir)}")
|
|
actualLibsFile.copyTo(expectedLibs, overwrite = true)
|
|
} else if (ignoreJarsMismatch) {
|
|
// Renovate requires self-hosted runner for executing postUpgradeTasks,
|
|
// so we can't make Renovate to update expected_release_jars.csv at the moment
|
|
logger.lifecycle(sb.toString())
|
|
} else {
|
|
throw GradleException(sb.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
tasks.check {
|
|
dependsOn(verifyReleaseDependencies)
|
|
}
|
|
|
|
// This adds dependency on "populateLibs" task
|
|
// This makes uses of these copySpecs transparently depend on the builder task
|
|
libs.from(populateLibs)
|
|
libsExt.from(populateLibs)
|
|
binLibs.from(populateLibs)
|
|
|
|
val copyLibs by tasks.registering(Sync::class) {
|
|
// Can't use $rootDir since Gradle somehow reports .gradle/caches/ as "always modified"
|
|
rootSpec.into("$rootDir/lib")
|
|
with(libs)
|
|
preserve {
|
|
// Sync does not really know which files it copied during previous times, so
|
|
// it just removes everything it sees.
|
|
// We configure it to keep txt files that should be present there (the files come from Git source tree)
|
|
include("**/*.txt")
|
|
// Keep jars in lib/ext so developers don't have to re-install the plugins again and again
|
|
include("ext/*.jar")
|
|
exclude("ext/ApacheJMeter*.jar")
|
|
}
|
|
into("ext") {
|
|
with(libsExt)
|
|
from(files(generatorJar)) {
|
|
rename { "ApacheJMeter_generator.jar" }
|
|
}
|
|
}
|
|
into("junit") {
|
|
from(files(junitSampleJar)) {
|
|
rename { "test.jar" }
|
|
}
|
|
}
|
|
}
|
|
|
|
val copyBinLibs by tasks.registering(Copy::class) {
|
|
// Can't use $rootDir since Gradle somehow reports .gradle/caches/ as "always modified"
|
|
rootSpec.into("$rootDir/bin")
|
|
with(binLibs)
|
|
// :src:config:jar conflicts with copyBinLibs on bin, bin/templates, bin/report-template folders
|
|
// so we add explicit ordering
|
|
mustRunAfter(":src:config:jar")
|
|
}
|
|
|
|
val createDist by tasks.registering {
|
|
group = LifecycleBasePlugin.BUILD_GROUP
|
|
description = "Copies JMeter jars and dependencies to projectRoot/lib/ folder"
|
|
dependsOn(copyLibs)
|
|
dependsOn(copyBinLibs)
|
|
}
|
|
|
|
// This task scans the project for gitignore / gitattributes, and that is reused for building
|
|
// source/binary artifacts with the appropriate eol/executable file flags
|
|
val gitProps by rootProject.tasks.existing(FindGitAttributes::class)
|
|
|
|
fun createAnakiaTask(
|
|
taskName: String,
|
|
baseDir: String,
|
|
extension: String = ".html",
|
|
style: String,
|
|
velocityProperties: String,
|
|
projectFile: String,
|
|
excludes: Array<String>,
|
|
includes: Array<String>
|
|
): TaskProvider<Task> {
|
|
val outputDir = layout.buildDirectory.dir("docs/$taskName").get().asFile
|
|
|
|
val prepareProps = tasks.register("prepareProperties$taskName") {
|
|
// AnakiaTask can't use relative paths, and it forbids ../, so we create a dedicated
|
|
// velocity.properties file that contains absolute path
|
|
inputs.file(velocityProperties)
|
|
val outputProps = layout.buildDirectory.file("docProps/$taskName/velocity.properties").get().asFile
|
|
outputs.file(outputProps)
|
|
doLast {
|
|
// Unfortunately, Velocity does not use Java properties format.
|
|
// For instance, Properties escape : as \:, however Velocity does not understand that.
|
|
// Thus it tries to use c\:\path\to\workspace which does not work
|
|
val p = `java.util`.Properties()
|
|
file(velocityProperties).reader().use {
|
|
p.load(it)
|
|
}
|
|
p["resource.loader"] = "file"
|
|
p["file.resource.loader.path"] = baseDir
|
|
p["file.resource.loader.class"] = "org.apache.velocity.runtime.resource.loader.FileResourceLoader"
|
|
val specials = Regex("""([,\\])""")
|
|
val lines = p.entries
|
|
.map { (it.key as String) + "=" + ((it.value as String).replace(specials, """\\$1""")) }
|
|
.sorted()
|
|
file(outputProps).apply {
|
|
parentFile.run { isDirectory || mkdirs() } || throw IllegalStateException("Unable to create directory $parentFile")
|
|
|
|
writer().use {
|
|
it.appendLine("# Auto-generated from $velocityProperties to pass absolute path to Velocity")
|
|
for (line in lines) {
|
|
it.appendLine(line)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return tasks.register(taskName) {
|
|
inputs.file("$baseDir/$style").withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("styleDir")
|
|
inputs.file("$baseDir/$projectFile").withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("projectDir")
|
|
inputs.files(
|
|
fileTree(baseDir) {
|
|
include(*includes)
|
|
exclude(*excludes)
|
|
}
|
|
).withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("baseDir")
|
|
inputs.property("extension", extension)
|
|
outputs.dir(outputDir)
|
|
outputs.cacheIf { true }
|
|
dependsOn(prepareProps)
|
|
|
|
doLast {
|
|
ant.withGroovyBuilder {
|
|
"taskdef"(
|
|
"name" to "anakia",
|
|
"classname" to "org.apache.velocity.anakia.AnakiaTask",
|
|
"classpath" to buildDocs.asPath
|
|
)
|
|
"anakia"(
|
|
"basedir" to baseDir,
|
|
"destdir" to outputDir,
|
|
"extension" to extension,
|
|
"style" to style,
|
|
"projectFile" to projectFile,
|
|
"excludes" to excludes.joinToString(" "),
|
|
"includes" to includes.joinToString(" "),
|
|
"lastModifiedCheck" to "true",
|
|
"velocityPropertiesFile" to prepareProps.get().outputs.files.singleFile
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
val xdocs = "$rootDir/xdocs"
|
|
|
|
fun CopySpec.docCssAndImages() {
|
|
from(xdocs) {
|
|
include(".htaccess")
|
|
include("css/**")
|
|
include("images/**")
|
|
}
|
|
}
|
|
|
|
fun CopySpec.manuals() {
|
|
from(xdocs) {
|
|
include("demos/**")
|
|
include("extending/jmeter_tutorial.pdf")
|
|
include("usermanual/**/*.pdf")
|
|
}
|
|
}
|
|
|
|
fun CopySpec.printableDocumentation() {
|
|
into("docs") {
|
|
docCssAndImages()
|
|
}
|
|
into("printable_docs") {
|
|
from(buildPrintableDoc)
|
|
manuals()
|
|
}
|
|
}
|
|
|
|
val buildPrintableDoc = createAnakiaTask(
|
|
"buildPrintableDoc", baseDir = xdocs,
|
|
style = "stylesheets/site_printable.vsl",
|
|
velocityProperties = "$xdocs/velocity.properties",
|
|
projectFile = "stylesheets/printable_project.xml",
|
|
excludes = arrayOf("**/stylesheets/**", "extending.xml", "extending/*.xml"),
|
|
includes = arrayOf("**/*.xml")
|
|
)
|
|
|
|
val previewPrintableDocs by tasks.registering(Copy::class) {
|
|
group = JavaBasePlugin.DOCUMENTATION_GROUP
|
|
description = "Creates preview of a printable documentation to build/docs/printable_preview"
|
|
into(layout.buildDirectory.dir("docs/printable_preview"))
|
|
CrLfSpec().run {
|
|
gitattributes(gitProps)
|
|
printableDocumentation()
|
|
}
|
|
}
|
|
|
|
val lastEditYear: String by rootProject.extra
|
|
|
|
fun xslt(
|
|
subdir: String,
|
|
outputDir: String,
|
|
includes: Array<String> = arrayOf("*.xml"),
|
|
excludes: Array<String> = arrayOf("extending.xml")
|
|
) {
|
|
|
|
val relativePath = if (subdir.isEmpty()) "." else ".."
|
|
ant.withGroovyBuilder {
|
|
"xslt"(
|
|
"style" to "$xdocs/stylesheets/website-style.xsl",
|
|
"basedir" to "$xdocs/$subdir",
|
|
"destdir" to "$outputDir/$subdir",
|
|
"excludes" to excludes.joinToString(" "),
|
|
"includes" to includes.joinToString(" ")
|
|
) {
|
|
"param"("name" to "relative-path", "expression" to relativePath)
|
|
"param"("name" to "subdir", "expression" to subdir)
|
|
"param"("name" to "year", "expression" to lastEditYear)
|
|
}
|
|
}
|
|
}
|
|
|
|
val processSiteXslt by tasks.registering {
|
|
val outputDir = layout.buildDirectory.dir("siteXslt").get().asFile
|
|
inputs.files(xdocs).withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("xdocs")
|
|
inputs.property("year", lastEditYear)
|
|
outputs.dir(outputDir)
|
|
outputs.cacheIf { true }
|
|
|
|
doLast {
|
|
for (f in (outputs as TaskOutputsInternal).previousOutputFiles) {
|
|
f.delete()
|
|
}
|
|
for (i in arrayOf("", "usermanual", "localising")) {
|
|
xslt(i, outputDir.absolutePath)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun CopySpec.siteLayout() {
|
|
// TODO: generate doap_JMeter.rdf
|
|
from("$xdocs/download_jmeter.cgi")
|
|
into("api") {
|
|
javadocs()
|
|
}
|
|
from(processSiteXslt)
|
|
docCssAndImages()
|
|
manuals()
|
|
}
|
|
|
|
// See https://github.com/gradle/gradle/issues/10960
|
|
val previewSiteDir = layout.buildDirectory.dir("site")
|
|
val previewSite by tasks.registering(Sync::class) {
|
|
group = JavaBasePlugin.DOCUMENTATION_GROUP
|
|
description = "Creates preview of a site to build/docs/site"
|
|
into(previewSiteDir)
|
|
CrLfSpec().run {
|
|
gitattributes(gitProps)
|
|
siteLayout()
|
|
}
|
|
doLast {
|
|
println("Site preview synchronized to ${previewSiteDir.get().file("index.html")}")
|
|
}
|
|
}
|
|
|
|
val distributionGroup = "distribution"
|
|
val baseFolder = "apache-jmeter-${rootProject.version}"
|
|
|
|
fun CopySpec.javadocs() = from(javadocAggregate)
|
|
|
|
fun CopySpec.excludeLicenseFromSourceRelease() {
|
|
// Source release has "/licenses" folder with licenses for third-party dependencies
|
|
// It is populated by "dependencyLicenses" above,
|
|
// so we ignore the folder when building source releases
|
|
exclude("licenses/**")
|
|
exclude("LICENSE")
|
|
}
|
|
|
|
fun CrLfSpec.binaryLayout() = copySpec {
|
|
gitattributes(gitProps)
|
|
into(baseFolder) {
|
|
// Note: license content is taken from "/build/..", so gitignore should not be used
|
|
// Note: this is a "license + third-party licenses", not just Apache-2.0
|
|
// Note: files(...) adds both "files" and "dependency"
|
|
from(files(binLicense))
|
|
from(rootDir) {
|
|
gitignore(gitProps)
|
|
exclude("bin/testfiles")
|
|
exclude("bin/rmi_keystore.jks")
|
|
include("bin/**")
|
|
include("lib/ext/**")
|
|
include("lib/junit/**")
|
|
include("extras/**")
|
|
include("README.md")
|
|
excludeLicenseFromSourceRelease()
|
|
}
|
|
into("bin") {
|
|
with(binLibs)
|
|
}
|
|
into("lib") {
|
|
with(libs)
|
|
into("ext") {
|
|
with(libsExt)
|
|
}
|
|
}
|
|
printableDocumentation()
|
|
into("docs/api") {
|
|
javadocs()
|
|
}
|
|
}
|
|
}
|
|
|
|
fun CrLfSpec.sourceLayout() = copySpec {
|
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
gitattributes(gitProps)
|
|
into(baseFolder) {
|
|
// Note: license content is taken from "/build/..", so gitignore should not be used
|
|
// Note: this is a "license + third-party licenses", not just Apache-2.0
|
|
// Note: files(...) adds both "files" and "dependency"
|
|
from(files(srcLicense))
|
|
// Include all the source files
|
|
from(rootDir) {
|
|
gitignore(gitProps)
|
|
excludeLicenseFromSourceRelease()
|
|
}
|
|
}
|
|
}
|
|
|
|
val javadocAggregate by tasks.registering(Javadoc::class) {
|
|
group = JavaBasePlugin.DOCUMENTATION_GROUP
|
|
description = "Generates aggregate javadoc for all the artifacts"
|
|
|
|
val sourceSets = jars.map { project(it).sourceSets.main }
|
|
|
|
classpath = files(sourceSets.map { set -> set.map { it.output + it.compileClasspath } })
|
|
// Aggregate javadoc needs to include generated JMeterVersion class
|
|
// So we use delay computation of source files
|
|
setSource(sourceSets.map { set -> set.map { it.allJava } })
|
|
setDestinationDir(layout.buildDirectory.dir("docs/javadocAggregate").get().asFile)
|
|
}
|
|
|
|
// Generates distZip, distTar, distZipSource, and distTarSource tasks
|
|
// The archives and checksums are put to build/distributions
|
|
for (type in listOf("binary", "source")) {
|
|
if (buildParameters.skipDist) {
|
|
break
|
|
}
|
|
for (archive in listOf(Zip::class, Tar::class)) {
|
|
val taskName = "dist${archive.simpleName}${type.replace("binary", "").replaceFirstChar { it.titlecaseChar() }}"
|
|
val archiveTask = tasks.register(taskName, archive) {
|
|
val eol = if (archive == Tar::class) LineEndings.LF else LineEndings.CRLF
|
|
group = distributionGroup
|
|
description = "Creates $type distribution with $eol line endings for text files"
|
|
if (this is Tar) {
|
|
compression = Compression.GZIP
|
|
}
|
|
// dist task excludes jar files from bin/, and lib/ however Gradle does not see that
|
|
// So we add an artificial dependency
|
|
mustRunAfter(copyBinLibs)
|
|
mustRunAfter(copyLibs)
|
|
mustRunAfter(":src:dist-check:copyExtraTestLibs")
|
|
// Gradle does not track "filters" as archive/copy task dependencies,
|
|
// So a mere change of a file attribute won't trigger re-execution of a task
|
|
// So we add a custom property to re-execute the task in case attributes change
|
|
inputs.property("gitproperties", gitProps.map { it.props.attrs.toString() })
|
|
|
|
// Gradle defaults to the following pattern, and JMeter was using apache-jmeter-5.1_src.zip
|
|
// [baseName]-[appendix]-[version]-[classifier].[extension]
|
|
archiveBaseName.set("apache-jmeter-${rootProject.version}${if (type == "source") "_src" else ""}")
|
|
// Discard project version since we want it to be added before "_src"
|
|
archiveVersion.set("")
|
|
CrLfSpec(eol).run {
|
|
wa1191SetInputs(gitProps)
|
|
with(if (type == "source") sourceLayout() else binaryLayout())
|
|
}
|
|
}
|
|
releaseArtifacts {
|
|
artifact(archiveTask)
|
|
}
|
|
}
|
|
}
|
|
|
|
releaseArtifacts {
|
|
previewSite(previewSite) {
|
|
into("site") {
|
|
from(previewSiteDir)
|
|
}
|
|
}
|
|
}
|
|
|
|
val runGui by tasks.registering(JavaExec::class) {
|
|
group = "Development"
|
|
description = "Builds and starts JMeter GUI"
|
|
dependsOn(createDist)
|
|
buildParameters.testJdk?.let {
|
|
javaLauncher.set(javaToolchains.launcherFor(it))
|
|
}
|
|
|
|
workingDir = File(project.rootDir, "bin")
|
|
mainClass.set("org.apache.jmeter.NewDriver")
|
|
classpath("$rootDir/bin/ApacheJMeter.jar")
|
|
jvmArgs("-Xss256k")
|
|
jvmArgs("-XX:MaxMetaspaceSize=256m")
|
|
|
|
val osName = System.getProperty("os.name")
|
|
if (osName.contains(Regex("mac os x|darwin|osx", RegexOption.IGNORE_CASE))) {
|
|
jvmArgs("-Xdock:name=JMeter")
|
|
jvmArgs("-Xdock:icon=$rootDir/xdocs/images/jmeter_square.png")
|
|
jvmArgs("-Dapple.laf.useScreenMenuBar=true")
|
|
jvmArgs("-Dapple.eawt.quitStrategy=CLOSE_ALL_WINDOWS")
|
|
}
|
|
|
|
fun passProperty(name: String, default: String? = null) {
|
|
val value = System.getProperty(name) ?: default
|
|
value?.let { systemProperty(name, it) }
|
|
}
|
|
|
|
passProperty("java.awt.headless")
|
|
|
|
val props = System.getProperties()
|
|
@Suppress("UNCHECKED_CAST")
|
|
for (e in props.propertyNames() as `java.util`.Enumeration<String>) {
|
|
// Pass -Djmeter.* and -Ddarklaf.* properties to the JMeter process
|
|
if (e.startsWith("jmeter.") || e.startsWith("darklaf.")) {
|
|
passProperty(e)
|
|
}
|
|
if (e == "darklaf.native") {
|
|
systemProperty("darklaf.decorations", "true")
|
|
systemProperty("darklaf.allowNativeCode", "true")
|
|
}
|
|
}
|
|
}
|