ghidra/Ghidra/RuntimeScripts/Common/support/buildExtension.gradle

287 lines
9.0 KiB
Groovy

import org.apache.tools.ant.filters.ReplaceTokens
defaultTasks 'buildExtension'
apply plugin: 'java'
/*****************************************************************************************
*
* Reads the application.properties file and sets properties for the version,
* release name, and distro prefix (ghidira_<version>)
*
*****************************************************************************************/
def ghidraDir = buildscript.sourceFile.getAbsolutePath() + "/../../Ghidra"
def ghidraProps = new Properties()
file(ghidraDir + "/application.properties").withReader { reader ->
ghidraProps.load(reader)
project.ext.ghidra_version = ghidraProps.getProperty('application.version')
project.ext.RELEASE_NAME = ghidraProps.getProperty('application.release.name')
project.ext.DISTRO_PREFIX = "ghidra_${ghidra_version}"
}
configurations {
helpPath
}
artifacts {
helpPath jar
}
compileJava {
sourceCompatibility = ghidraProps.getProperty('application.java.compiler')
targetCompatibility = ghidraProps.getProperty('application.java.compiler')
}
dependencies {
compile fileTree(dir: 'lib', include: "*.jar")
compile fileTree(dir: ghidraDir + '/Framework', include: "**/*.jar")
compile fileTree(dir: ghidraDir + '/Features', include: "**/*.jar")
helpPath fileTree(dir: ghidraDir + '/Features/Base', include: "**/Base.jar")
}
def ZIP_NAME_PREFIX = "${DISTRO_PREFIX}_${RELEASE_NAME}_${getCurrentDate()}"
def DISTRIBUTION_DIR = file("dist")
def pathInZip = "${project.name}"
task zipSource (type: Zip) {
// Define some metadata about the zip (name, location, version, etc....)
it.baseName project.name + "-src"
it.extension 'zip'
it.destinationDir file(project.projectDir.path + "/build/tmp/src")
// We MUST copy from a directory, and not just grab a list of source files.
// This is the only way to preserve the directory structure.
it.from project.projectDir
it.include 'src/**/*'
}
task buildExtension (type: Zip) {
baseName "${ZIP_NAME_PREFIX}_${project.name}"
extension 'zip'
destinationDir DISTRIBUTION_DIR
version ''
// Make sure that we don't try to copy the same file with the same path into the
// zip (this can happen!)
duplicatesStrategy 'exclude'
// This filtered property file copy must appear before the general
// copy to ensure that it is prefered over the unmodified file
File propFile = new File(project.projectDir, "extension.properties")
from (propFile) {
String version = "${ghidra_version}"
String name = "${project.name}"
filter (ReplaceTokens, tokens: [extversion: version])
filter (ReplaceTokens, tokens: [extname: name])
into pathInZip
}
from (project.jar) {
into pathInZip + "/lib"
}
from (project.projectDir) {
exclude 'build/**'
exclude '*.gradle'
exclude 'certification.manifest'
exclude 'dist/**'
exclude 'bin/**'
exclude 'src/**'
exclude '.gradle/**'
exclude '.classpath'
exclude '.project'
exclude '.settings/**'
exclude 'developer_scripts'
exclude '.antProperties.xml'
exclude 'gradlew'
exclude 'gradlew.bat'
exclude 'gradle/wrapper/gradle-wrapper.jar'
exclude 'gradle/wrapper/gradle-wrapper.properties'
into pathInZip
}
/////////////////
// SOURCE
/////////////////
from (tasks["zipSource"]) {
into pathInZip + "/lib"
}.dependsOn(zipSource)
/////////////////
// GLOBALS
/////////////////
// First get a list of all files that are under 'src/global'.
FileTree fileTree = project.fileTree('src/global') {
include '**/*'
}
// Now loop over each one, copying it into the zip we're creating. Each will be placed
// at the root level, starting with the first folder AFTER 'src/global/'.
//
// eg: If the file is '/Ghidra/Extensions/Sample/src/global/docs/hello.html', then
// the file in the zip will be at /docs/hello.html
//
fileTree.each { File file ->
String filePath = stripGlobalFilePath(file)
from (file) {
into filePath
}
}
doLast {
println "\nCreated " + baseName + "." + extension + " in " + destinationDir
}
}
// task for calling the java help indexer
task indexHelp(type: JavaExec) {
File helpRootDir = file('src/main/help') // this the root dir for the help source
File outputFile = file("build/help/main/help/${project.name}_JavaHelpSearch")
onlyIf {helpRootDir.exists()}
dependsOn configurations.helpPath
inputs.dir helpRootDir
outputs.dir outputFile
classpath = sourceSets.main.runtimeClasspath // this modules runtime classpath (contains jhall.jar)
main = 'com.sun.java.help.search.Indexer' // main class to call
// tell the indexer where send its output
args '-db', outputFile.absolutePath
// The index has a config file parameter. The only thing we use in the config file
// is a root directory path that should be stripped off all the help references to
// make them relative instead of absolute
File configFile = file('build/helpconfig') // this is the config file that we will create
// create the config file when the task runs and not during configuration.
doFirst {
configFile.parentFile.mkdirs();
configFile.write "IndexRemove ${helpRootDir.absolutePath}" + File.separator + "\n"
}
// pass the config file we created as an argument to the indexer
args '-c',"$configFile"
// gather up all the help files into a file collection
FileTree helpFiles = fileTree('src/main/help') {
include '**/*.htm'
include '**/*.html'
}
doFirst {
// for each help file that was found, add it as an argument to the indexer
helpFiles.each { File file ->
args "${file.absolutePath}"
}
}
group "private"
description "indexes the helps files for this module. [gradle/helpProject.gradle]"
}
// task for building Ghidra help files - depends on the output from the help indexer
task buildHelp(type: JavaExec, dependsOn: indexHelp) {
File helpRootDir = file('src/main/help/help') // help root where topics dir lives
File outputDir = file('build/help/main/help') // dir where we want the help files to be generated
onlyIf {helpRootDir.exists()}
inputs.dir helpRootDir
outputs.dir outputDir
classpath = sourceSets.main.runtimeClasspath // this modules runtime classpath (contains jhall.jar)
main = 'help.GHelpBuilder' // program to run to build help files.
args '-n', "${project.name}" // use the modules name as the base for the help file name
args '-o', "${outputDir.absolutePath}" // set the output directory arg
doFirst {
configurations.helpPath.each {
args "-hp"
args "${it.absolutePath}"
}
args "${helpRootDir.absolutePath}" // tell the help builder what help dir to process
}
description " Builds the help for this module. [gradle/helpProject.gradle]\n"
}
// include the help into the module's jar
jar {
from "build/help/main" // include the generated help index files
from "src/main/help" // include the help source files
version = ""
}
// build the help whenever this module's jar file is built
jar.dependsOn 'buildHelp'
/*********************************************************************************
* Takes the given file and returns a string representing the file path with everything
* up-to and including 'src/global' removed, as well as the filename.
*
* eg: If the file path is '/Ghidra/Configurations/Common/src/global/docs/hello.html',
* the returned string will be at /docs
*
* Note: We have to use 'File.separator' instead of a slash ('/') because of how
* windows/unix handle slashes ('/' vs. '\'). We only need to do this in cases where we're
* using java string manipulation libraries (eg String.replace); Gradle already
* understands how to use the proper slash.
*********************************************************************************/
String stripGlobalFilePath(File file) {
// First strip off everything before 'src/global/ in the file path.
def slashIndex = file.path.indexOf('src' + File.separator + 'global')
String filePath = file.path.substring(slashIndex);
// Now remove 'src/global/' from the string.
filePath = filePath.replace('src' + File.separator + 'global' + File.separator, "");
// Now we need to strip off the filename itself, which we do by finding the last
// instance of a slash ('/') in the string. Unfortunately, groovy doesn't give
// us a "lastIndexOf('/')" or something nice like that, so we reverse the string
// and look for the slash that way, remove the filename, then reverse it back.
//
// Note that it's possible there is no slash (all we have is a filename), meaning
// this file will be placed at the root level.
//
String reverseFilePath = filePath.reverse()
slashIndex = reverseFilePath.indexOf(File.separator)
if (slashIndex != -1) {
reverseFilePath = reverseFilePath.substring(slashIndex)
filePath = reverseFilePath.reverse()
}
else {
filePath = ""
}
return filePath
}
/*********************************************************************************
* Returns the current date formatted as yyyyMMdd.
*********************************************************************************/
def getCurrentDate() {
def date = new Date()
def formattedDate = date.format('yyyyMMdd')
return formattedDate
}