This repository has been archived on 2022-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
JavaProgressia/build.gradle

384 lines
9.2 KiB
Groovy

/*
* Build logic for Progressia
* build.gradle
*
* Please refer to
*
* docs/building/BuildScriptReference.md
*
* for user reference.
*/
plugins {
id 'java'
// GrGit
// A JGit wrapper for Groovy used to access git commit info
id 'org.ajoberstar.grgit' version '4.1.1'
}
/*
* Configure Java version
*/
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
compileJava {
/*
* We want to compile for Java 8.
* If we are using JDK 8, no further action is required.
* However, on JDK 9 and later versions, '--release' option is required,
* which is missing on JDK 8.
*/
if (JavaVersion.current() != JavaVersion.VERSION_1_8) {
options.compilerArgs.addAll(['--release', '8'])
}
}
/*
* Dependencies
*/
repositories {
mavenCentral()
/*
* Windcorp Maven repository
* Currently used by:
* - ru.windcorp.fork.io.github.java-graphics:glm:1.0.1
*/
maven { url 'https://windcorp.ru/./maven' }
}
dependencies {
// Google Guava
// A generic utilities library
implementation 'com.google.guava:guava:30.0-jre'
// Trove4j
// Provides optimized Collections for primitive types
implementation 'net.sf.trove4j:trove4j:3.0.3'
// java-graphics
// A GLM (OpenGL Mathematics) port to Java
// Unfortunately, Maven Central Repository provides an outdated version of this library, which contains several critical bugs
implementation 'ru.windcorp.fork.io.github.java-graphics:glm:1.0.1'
// Log4j
// A logging library
implementation 'org.apache.logging.log4j:log4j-api:2.17.0'
implementation 'org.apache.logging.log4j:log4j-core:2.17.0'
// JUnit
// A unit-testing library
testImplementation 'junit:junit:4.13.2'
// Also see LWJGL dependencies in build_logic/lwjgl.gradle
}
/*
* Version resolution
*/
import org.ajoberstar.grgit.*
// Pattern: vMAJOR.MINOR.PATCH[-SUFFIX]
project.ext.tagFormat = /^v(\d+)\.(\d+)\.(\d+)(-[\w\-]*)?$/
String version_parseVersion(String tag, boolean increment) {
try {
def data = (tag =~ tagFormat)[0]
def major = data[1]
def minor = data[2]
def patch = data[3] as int
def suffix = data[4] ?: ''
if (increment) {
def oldVersion = "$major.$minor.$patch$suffix"
patch++
def newVersion = "$major.$minor.$patch$suffix"
logger.info "Version parsed from Git: $oldVersion, incremented to $newVersion"
return newVersion
} else {
def newVersion = "$major.$minor.$patch$suffix"
logger.info "Version parsed from Git: $newVersion"
return newVersion
}
} catch (any) {
logger.warn "Could not parse version from tag \"$tag\""
return tag
}
}
Tag version_findRelevantTag(Grgit git) {
def tags = git.tag.list()
def commits = [ git.head() ]
def visited = new HashSet<>()
while (true) {
if (commits.isEmpty()) return null
def nextCommits = new HashSet<>()
def formatSpecificationPrinted = false
for (def commit : commits) {
def tag = tags.findAll { it.commit == commit } ?.max { it.dateTime }
if (tag != null) {
if (tag.name ==~ tagFormat) {
return tag
} else {
if (!formatSpecificationPrinted) {
formatSpecificationPrinted = true
logger.info 'Expecting tag format: vMAJOR.MINOR.PATCH[-SUFFIX]'
}
logger.info 'Ignoring tag due to invalid format: {}', tag.name
}
}
nextCommits.addAll commit.parentIds.collect(git.resolve.&toCommit)
}
visited.addAll commits
nextCommits.removeAll visited
commits = nextCommits
}
}
task resolveVersion {
description 'Resolves version information from Git repository or project properties.'
doFirst {
try {
def git = Grgit.open(dir: project.projectDir)
project.ext.commit = git.head().id
project.ext.branch = git.branch.current().name
if (project.version != 'unspecified') {
// Leave version as-is
return
}
def tag = version_findRelevantTag(git)
if (tag == null) {
String suffix
if (project.hasProperty('buildId')) {
suffix = project.buildId;
} else {
suffix = java.time.ZonedDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern('yyyy_MM_dd'))
}
project.version = "999.0.0-$suffix"
logger.warn 'Git repository does not contain an applicable tag, using dummy version {}\nSpecify version with -Pversion=1.2.3 or create a Git tag named v1.2.3', project.version
} else {
project.version = version_parseVersion(tag.name, tag.commit != git.head())
}
} catch (org.eclipse.jgit.errors.RepositoryNotFoundException e) {
if (project.version == 'unspecified') project.version = 'dev'
project.ext.commit = '-'
project.ext.branch = '-'
logger.warn 'No Git repository found in project root, using dummy version {}\nSpecify version with -Pversion=1.2.3 or create a Git tag named v1.2.3', project.version
}
}
doLast {
if (!project.hasProperty('buildId')) {
project.ext.buildId = '-'
}
}
}
/*
* Configure JAR manifest
*/
task configureManifest {
description 'Populates JAR manifest with Main-Class, Class-Path and version metadata.'
jar.dependsOn configureManifest
dependsOn resolveVersion
doFirst {
jar.manifest.attributes(
'Main-Class': 'ru.windcorp.progressia.client.ProgressiaClientMain',
'Class-Path': configurations.runtimeClasspath.collect { "lib/${it.name}" } .join(' '),
'Specification-Title': 'Progressia',
'Implementation-Title': 'Progressia',
'Implementation-Version': project.version,
'Implementation-Version-Git-Commit': project.commit,
'Implementation-Version-Git-Branch': project.branch,
'Implementation-Version-BuildId': project.buildId,
)
}
}
/*
* Copy libraries into buil/libs/lib directory, next to Progressia.jar
*/
task exportLibs(type: Sync) {
description 'Copies runtime libraries into a subdirectory next to the output JAR.'
jar.dependsOn exportLibs
from configurations.runtimeClasspath
into 'build/libs/lib'
}
/*
* Apply LWJGL logic
*/
apply from: 'build_logic/lwjgl.gradle'
/*
* Packaging working directory configuration
*/
import java.nio.file.*
import java.nio.file.attribute.*
task deletePackagingDirs(type: Delete) {
description 'Deletes build/tmp/packaging directory.'
followSymlinks = false
delete 'build/tmp/packaging'
}
task linkBuildOutputForPackaging {
description 'Symlinks the contents of build/libs into packaging working directory.'
dependsOn build
mustRunAfter deletePackagingDirs
onlyIf { preparePackaging.ext.mode == 'symlink' }
ext.from = 'build/libs'
ext.into = "build/tmp/packaging/workingDir/${ -> preparePackaging.ext.buildDest}"
inputs.dir from
outputs.dir into
doLast {
def fromPath = Paths.get from
def intoPath = Paths.get into
Files.createDirectories intoPath
Files.list(fromPath).each {
def fileName = it.fileName.toString()
// Exclude all JARs except the current one
if (fileName ==~ "${project.name}.*\\.jar" && fileName != tasks.jar.archiveFileName.get())
return
Files.createSymbolicLink intoPath.resolve(it.fileName), intoPath.relativize(it)
}
}
}
task copyBuildOutputForPackaging(type: Copy) {
description 'Copies the contents of build/libs into packaging working directory.'
dependsOn build
mustRunAfter deletePackagingDirs
onlyIf { preparePackaging.ext.mode == 'copy' }
from 'build/libs'
filesMatching("${project.name}*.jar") {
include tasks.jar.archiveFileName.get()
}
into "build/tmp/packaging/workingDir/${ -> preparePackaging.ext.buildDest}"
}
task preparePackaging {
preparePackaging.ext.buildDest = ''
preparePackaging.ext.mode = 'symlink'
dependsOn deletePackagingDirs
dependsOn linkBuildOutputForPackaging
dependsOn copyBuildOutputForPackaging
}
/*
* Apply all packaging scripts
*/
new File(projectDir, 'build_logic/packaging').list().each {
apply from: "build_logic/packaging/$it/script.gradle"
}
/*
* Ensure no more than one packaging task is scheduled
*/
gradle.taskGraph.whenReady { graph ->
if (graph.allTasks.count { it.name ==~ /package[^_]*/ } > 1) {
def offenders = graph.allTasks.findAll { it.name ==~ /package[^_]*/ }
throw new GradleException("Cannot execute multiple package tasks within a single build\n" +
"\tOffending tasks: $offenders")
}
}
/*
* Convenience build tasks
*/
task buildCrossPlatform {
description 'Builds the project including native libraries for all available platforms.'
group 'Progressia'
dependsOn requestCrossPlatformDependencies
dependsOn build
doLast {
logger.info 'Native libraries for all platforms have been added'
}
}
task buildLocal {
description "Builds the project including only native libraries for current platform (${lwjgl.localArch})."
group 'Progressia'
dependsOn build
doLast {
logger.info "Native libraries only for platform ${lwjgl.localArch} have been added"
}
}