ghidra/Ghidra/Features/GhidraServer/build.gradle

303 lines
10 KiB
Groovy

apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
apply from: "$rootProject.projectDir/gradle/javaProject.gradle"
apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
apply plugin: 'eclipse'
eclipse.project.name = 'Features GhidraServer'
def yajswRelease = "yajsw-stable-12.12"
configurations {
runGhidraServer
}
dependencies {
compile project(":FileSystem")
compile project(":DB")
compile project(":Generic")
runGhidraServer project
}
addExports([
'java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED'
])
CopySpec yajswCopySpec = copySpec {
File localFile = file("build/${yajswRelease}.zip")
File binFile = file("${BIN_REPO}/Ghidra/Features/GhidraServer/${yajswRelease}.zip")
// First check if the file was downloaded and dropped in locally. If not, check in the bin
// repo.
def yajswZipTree = localFile.exists() ? zipTree(localFile) : zipTree(binFile)
from(yajswZipTree) {
include "${yajswRelease}/lib/core/**"
include "${yajswRelease}/lib/extended/**"
include "${yajswRelease}/templates/**"
include "${yajswRelease}/*.jar"
include "${yajswRelease}/doc/**"
include "${yajswRelease}/LICENSE.txt"
include "${yajswRelease}/yajsw.policy.txt"
}
}
// Unpack YAJSW archive into build/data for development use
task yajswDevUnpack(type:Copy) {
description "Unpack YAJSW archive for development use"
group "Development Preparation"
with yajswCopySpec
destinationDir file("build/data")
}
/*********************************************************************************
* CLASSPATH FRAGMENT FILE: Production
*
* This task creates a file, 'GhidraServer/build/classpath.fragment',
* which contains all classpath info necessary for running the server in
* production mode.
*
* The basic conops is this:
* 1. Loop over each lib in the runGhidraServer configuration.
* 2. For each, find the location of that library in our distribution.
* a. Search the artifacts in the parent project (GhidraServer)
* b. If not found, loop over all dependent projects, searching their
* artifacts.
* 3. Put the path in the output file.
*********************************************************************************/
task generateGhidraServerClasspath {
description "Generate a configuration fragment for the Ghidra Server's classpath (release)"
File outfile = file("${buildDir}/classpath.frag")
outputs.file outfile
// Force the task to be executed every time by setting to false.
outputs.upToDateWhen { false }
doLast {
outfile.parentFile.mkdirs()
outfile.withPrintWriter { out ->
int idx = 0
configurations.runGhidraServer.each { jarFile ->
if (!jarFile.path.contains("/libsForBuild/")) {
def JAR_PATH = rootProject.relativePath(jarFile.absolutePath)
File distPath = file("/")
String resPath
for (Configuration conf : project.getConfigurations()) {
resPath = findJarInDistribution(project, conf, jarFile)
if (resPath != null) {
out.println("wrapper.java.classpath.${++idx}=\${ghidra_home}/${resPath}")
break
}
}
}
}
}
}
}
/**
* The classpath.frag file created below needs to be placed in the staging folder under the root
* path of this project.
*
* Note that we use 'this.project' to reference the GhidraServer project - this is because
* inside the closure, 'project' refers to the root project, while 'this' refers to
* GhidraServer.
*/
rootProject.assembleDistribution {
into (getZipPath(this.project) + "/data") {
with yajswCopySpec
from generateGhidraServerClasspath
}
into (getZipPath(this.project) + "/os") {
from (projectDir.toString() + "/os")
}
}
/*********************************************************************************
* CLASSPATH FRAGMENT FILE: Developer
*
* This task creates a file, 'GhidraServer/build/dev-meta/classpath.fragment',
* which contains all classpath info necessary for running the server in
* dev mode.
*
* All items in the classpath will have the form:
* wrapper.java.classpath.1=${ghidra_home}/<path-to-jar>
*
* The items we gather are pulled exclusively from the 'runGhidraServer' configuration,
* which is essentially the 'runtime' config + the GhidraServer jar.
*
*********************************************************************************/
task generateDevGhidraServerClasspath {
description "Generate a configuration fragment for the Ghidra Server's classpath (development)"
File outfile = file("${buildDir}/dev-meta/classpath.frag")
outputs.file outfile
// Force the task to be executed every time by setting to false.
outputs.upToDateWhen { false }
doLast {
outfile.parentFile.mkdirs()
outfile.withPrintWriter { out ->
int idx = 0
configurations.runGhidraServer.each { jarFile ->
def JAR_PATH = rootProject.relativePath(jarFile.absolutePath).replace('\\','/')
def index = JAR_PATH.indexOf("build/")
if (index != -1) {
JAR_PATH = JAR_PATH.substring(0, index) + "bin/main"
}
if (!jarFile.path.contains("/libsForBuild/")) {
out.println("wrapper.java.classpath.${++idx}=\${ghidra_home}/${JAR_PATH}")
}
}
}
}
}
/*****************************************************************************************
* We want the two main tasks in this build file to be run at the appropriate time; the
* dev task should be run during prepDev; the other should be run during the build
*****************************************************************************************/
rootProject.prepDev.dependsOn(generateDevGhidraServerClasspath)
rootProject.prepDev.dependsOn(yajswDevUnpack)
//compileJava.dependsOn(generateGhidraServerClasspath)
/*********************************************************************************
* Searches the artifacts of a given configuration for a given jar. If
* found, constructs a path to that jar ralative to the given project.
*
* Note that we have to check both the given configuration, AND the resolved
* configuration to ensure we find all possible matches.
*********************************************************************************/
def String searchArtifactsForJar (proj, conf, jarFile) {
if (conf == null) {
return null
}
String resolution = null
PublishArtifactSet artifacts = conf.getArtifacts()
artifacts.getFiles().each { f ->
if (jarFile.equals(f)) {
String path = rootProject.relativePath(proj.projectDir) + "/lib/" + f.name
resolution = path
}
}
if (artifacts.isEmpty()) {
if (conf.isCanBeResolved()) {
ResolvedConfiguration resolvedConfiguration = conf.getResolvedConfiguration()
Set<ResolvedArtifact> resolvedArtifacts = resolvedConfiguration.getResolvedArtifacts()
for (ResolvedArtifact resolvedArtifact : resolvedArtifacts) {
if (resolvedArtifact.getFile().equals(jarFile)) {
Project artifactProject = getProjectForArtifact(resolvedArtifact)
if (artifactProject != null) {
String path = rootProject.relativePath(artifactProject.projectDir) + "/lib/" + resolvedArtifact.getFile().name
resolution = path
}
break;
}
}
}
}
return resolution
}
/*********************************************************************************
* Returns the Project associated with a given ResolvedArtifact.
*********************************************************************************/
def Project getProjectForArtifact(resolvedArtifact) {
ResolvedModuleVersion moduleVersion = resolvedArtifact.getModuleVersion()
ModuleVersionIdentifier versionIdent = moduleVersion.getId()
String moduleName = versionIdent.getName()
Project project = rootProject.findProject(moduleName)
return project
}
/*********************************************************************************
* Searches the files of the given configuration for the given jar. If found,
* constructs a path to that jar ralative to the given project.
*
* Note that we hvae to use the resolved configuration here; if we don't have
* access to this, the file is not available.
*********************************************************************************/
def String searchFilesForJar (proj, conf, jar) {
if (conf == null) {
return null
}
String resolution = null
if (conf.isCanBeResolved()) {
ResolvedConfiguration rc = conf.getResolvedConfiguration()
rc.getFiles().each { f ->
if (jar.equals(f)) {
resolution = rootProject.relativePath(proj.projectDir) + "/lib/" + f.name
}
}
}
return resolution
}
/*********************************************************************************
* Searches all dependencies of a given configuration for a particular jar
* file.
*
* Note that there are two types of dependencies we have to check here: project
* dependencies and normal files. The former requires that we recursively check
* all the artifacts and dependencies of that project; the latter is just a check
* of a list of files.
*********************************************************************************/
def String searchDependenciesForJar (proj, conf, jarFile) {
String relPath = null
Set<ProjectDependency> projectDependencies = conf.getAllDependencies().withType(ProjectDependency)
for (ProjectDependency dependency : projectDependencies) {
Project dependencyProject = dependency.getDependencyProject()
Configuration depProjectConf = dependencyProject.getConfigurations().getByName(conf.getName())
relPath = findJarInDistribution(dependencyProject, depProjectConf, jarFile);
if (relPath != null) {
return relPath;
}
}
relPath = searchFilesForJar(proj, conf, jarFile)
return relPath
}
/*********************************************************************************
* Finds the location of a given jar in our distribution and returns the path
* (relative to the root project).
*
* To do this, first search the artifacts of the project and if it's not found,
* search all dependencies.
*********************************************************************************/
def String findJarInDistribution(proj, conf, jarFile) {
if (conf == null) {
return null
}
String path = null
path = searchArtifactsForJar(proj, conf, jarFile)
if (path == null) {
path = searchDependenciesForJar(proj, conf, jarFile)
}
return path
}