GP-3430 - Updated the gradle buildHelp task to better handle its inputs up-do-date state

This commit is contained in:
dragonmacher
2023-06-06 15:25:25 -04:00
parent 0d71657d05
commit a7668c7f85
32 changed files with 690 additions and 266 deletions
@@ -127,7 +127,7 @@ if (System.env.LLVM_HOME) {
}
}
} else {
println "Debugger-swig-lldb:buildNatives skipped - LLVM_HOME not defined"
logger.debug('Debugger-swig-lldb:buildNatives skipped - LLVM_HOME not defined')
}
task checkLLVM {
-4
View File
@@ -31,10 +31,6 @@ dependencies {
api project(':Decompiler')
api project(':ProposedUtils')
helpPath project(path: ':Base', configuration: 'helpPath')
helpPath project(path: ':Decompiler', configuration: 'helpPath')
helpPath project(path: ':ProgramDiff', configuration: 'helpPath')
testImplementation project(path: ':Base', configuration: 'testArtifacts')
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
testImplementation project(path: ':Framework-Debugging', configuration: 'testArtifacts')
@@ -23,7 +23,6 @@ eclipse.project.name = 'Xtra MachineLearning'
dependencies {
api project(':Base')
helpPath project(path: ":Base", configuration: 'helpPath')
api "com.oracle.labs.olcut:olcut-config-protobuf:5.2.0" //{exclude group: "com.google.protobuf", module: "protobuf-java"}
api ("com.oracle.labs.olcut:olcut-core:5.2.0") {exclude group: "org.jline"}
+12 -6
View File
@@ -61,7 +61,6 @@ dependencies {
testImplementation project(path: ':Project', configuration: 'testArtifacts')
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
testImplementation project(path: ':DB', configuration: 'testArtifacts')
helpPath project(path: ':Docking', configuration: 'helpPath') // this module's help has links to Base help files
javacc 'net.java.dev.javacc:javacc:5.0'
}
@@ -125,22 +124,29 @@ task buildJavacc {
}
// Note: this must happen before the standard buildHelp for Base
task generateExtraHelpFiles {
tasks.register('generateExtraHelpFiles') {
group = 'private'
description " Creates any extra help files for Base not covered by the standard build help system"
def rawTipsFile = file('src/main/resources/ghidra/app/plugin/core/totd/tips.txt')
def rawTipsFile = file('src/main/resources/ghidra/app/plugin/core/totd/tips.txt')
inputs.file(rawTipsFile)
def htmlTipsFile = file('src/main/help/help/topics/Misc/Tips.htm')
def htmlTipsFile = file('build/help/main/help/topics/Misc/Tips.htm')
outputs.file(htmlTipsFile)
doLast {
doLast {
createTipsHelpFile(rawTipsFile, htmlTipsFile)
}
}
// Base's help includes the file generated by the 'generateExtraHelpFiles' task. Signal that we
// depend on that task and it's output file.
tasks.named('buildHelp') {
dependsOn(tasks.named('generateExtraHelpFiles'))
inputs.files tasks.named('generateExtraHelpFiles').get().outputs
}
def createTipsHelpFile(input, output) {
// transform original contents - wrap each line in <li> tags
def buffy = new StringBuilder()
@@ -169,7 +175,7 @@ def createTipsHelpFile(input, output) {
output.text = htmlContent
println '\n\n\nwrote file ' + output + '\n\n\n'
logger.info '\n\n\nwrote file ' + output + '\n\n\n'
}
+1 -4
View File
@@ -24,8 +24,5 @@ eclipse.project.name = 'Features BytePatterns'
dependencies {
api project(':Base')
api project(':Utility')
helpPath project(path: ":Base", configuration: 'helpPath')
api project(':Utility')
}
-2
View File
@@ -26,6 +26,4 @@ dependencies {
api project(':Base')
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
helpPath project(path: ':Base', configuration: 'helpPath') // this module's help has links to Base help files
}
-2
View File
@@ -32,8 +32,6 @@ dependencies {
// include Base src/test/resources when running decompiler integration tests (uses defaultTools)
integrationTestImplementation project(path: ':Base', configuration: 'testArtifacts')
integrationTestImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
helpPath project(path: ":Base", configuration: 'helpPath')
}
// Include buildable native source in distribution
-2
View File
@@ -47,8 +47,6 @@ dependencies {
api 'net.sf.sevenzipjbinding:sevenzipjbinding:16.02-2.01'
runtimeOnly 'net.sf.sevenzipjbinding:sevenzipjbinding-all-platforms:16.02-2.01'
helpPath project(path: ":Base", configuration: 'helpPath')
// include code from src/test/slow in Base
testImplementation project(path: ':Base', configuration: 'integrationTestArtifacts')
}
@@ -22,15 +22,9 @@ apply plugin: 'eclipse'
eclipse.project.name = 'Features Graph FunctionGraph'
dependencies {
api project(":Base")
api project(":GraphServices")
helpPath project(path: ":Base", configuration: 'helpPath')
}
@@ -770,10 +770,6 @@
mouse scroll wheel. Disabling this option restores the original function graph scroll wheel
behavior of zooming when scrolled.</P>
<P>The <B>Start Fully Zoomed Out</B> option causes the initial graph to zoom out far enough
that the entire graph is displayed. When this option is off a new graph rendering will zoom
all the way in (no scaling) to the active vertex.</P>
<P>The <B>Update Vertex Colors When Grouping</B> option signals to the graph to make the
color of the grouped vertex be that of the vertices being grouped.</P>
+1 -3
View File
@@ -26,9 +26,7 @@ eclipse.project.name = 'Features FunctionID'
dependencies {
api project(":Base")
api project(":DB")
api project(":SoftwareModeling")
helpPath project(path: ":Base", configuration: 'helpPath')
api project(":SoftwareModeling")
}
// All *.fidb files located in the dependencies/fid directory OR the
@@ -26,14 +26,7 @@ eclipse.project.name = 'Features Graph FunctionCalls'
// Note: this module's name is 'GraphFunctionCalls'
dependencies {
api project(":Base")
helpPath project(path: ":Base", configuration: 'helpPath')
// This is needed now because we like to the help of the FunctionGraph. If and when that
// help is extracted to a higher-level help page, like 'Graphing', then this link should be
// removed
helpPath project(path: ":FunctionGraph", configuration: 'helpPath')
// These have abstract test classes and stubs needed by this module
testImplementation project(path: ':Project', configuration: 'testArtifacts')
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
@@ -226,20 +226,88 @@
<H2><A name="Satellite_View"></A>Satellite View</H2>
<BLOCKQUOTE>
<P>The Satellite View works exactly as the
<A href="help/topics/FunctionGraphPlugin/Function_Graph.html#Satellite_View">
Function Graph's Satellite View</A>.
</P>
</BLOCKQUOTE>
<P>The Satellite View provides an overview of the graph. From this view you may also perform
basic adjustment of the overall graph location. In addition to the complete graph, the
satellite view contains a <B>lens</B> (the white rectangle) that indicates how much of the
current graph fits into the primary view.</P>
<P>When you single left mouse click in the satellite view the graph is centered around the
corresponding point in the primary view. Alternatively, you may drag the lens of the
satellite view to the desired location by performing a mouse drag operation on the lens.</P>
<P>You may hide the satellite view by right-clicking anywhere in the Primary View and
deselecting the <B>Display Satellite View</B> toggle button from the popup menu.</P>
<BLOCKQUOTE>
<P><IMG src="help/shared/tip.png" alt="" border="0"> If the Primary View is painting
sluggishly, then hiding the Satellite View cause the Primary View to be more
responsive.</P>
</BLOCKQUOTE>
<H3><A name="Satellite_View_Dock"></A>Detached Satellite</H3>
<BLOCKQUOTE>
<P>The Satellite View is attached, or <B>docked</B>, to the Primary View by default.
However, you can detach, or undock, the Satellite View, which will put the view into a
Component Provider, which itself can be moved, resized and docked anywhere in the Tool you
wish.</P>
<P>To undock the Satellite View, right-click in the graph and deselect the <B>Dock
Satellite View</B> menu item.</P>
<P>To re-dock the Satellite View, right-click in the graph and select the <B>Dock Satellite
View</B> menu item.</P>
</BLOCKQUOTE>
<BLOCKQUOTE>
<P><IMG src="help/shared/tip.png" alt="" border="0"> To reshow the Satellite View if it is
hidden, whether docked or undocked, you can press the <IMG src=
"images/network-wireless.png" alt="" border="1"> button. This button is in the lower-right
hand corner of the graph and is only visible if the Satellite View is hidden or
undocked.</P>
</BLOCKQUOTE>
</BLOCKQUOTE>
<H2><A name="Options"></A>Options</H2>
<BLOCKQUOTE>
<P>The Function Call Graph options are currently a subset of the
<A href="help/topics/FunctionGraphPlugin/Function_Graph.html#Options">
Function Graph's Options</A>.
</P>
</BLOCKQUOTE>
<P>The <B>Scroll Wheel Pans</B> option signals to move the graph vertical when scrolling the
mouse scroll wheel. Disabling this option restores the original function graph scroll wheel
behavior of zooming when scrolled.</P>
<P>The <B>Use Animation</B> option signals to the graph whether to animate mutative graph
operations and navigations.</P>
<P><A name="Layout_Compressing"></A>The <B>Use Condensed Layout</B> option signals to the
graph to bring vertices as close together as possible when laying out the graph. Using this
option to fit as many vertices on the screen as possible. Disable this option to make the
overall layout of the graph more aesthetic.</P>
<P>The <B>Use Mouse-relative Zoom</B> option signals zoom the graph to and from the mouse
location when zooming from the middle-mouse. The default for this option is off, which
triggers zoom to work from the center of the graph, regardless of the mouse location.</P>
<P>The <B>View Settings</B> option describes how the graph will be zoomed when it is first
loaded. The values are:</P>
<UL>
<LI><B>Start Fully Zoomed Out</B> - always start fully zoomed out so that the entire
graph can be seen.</LI>
<LI><B>Start Fully Zoomed In</B> - always start fully zoomed in on the vertex containing
the current location.</LI>
<LI><B>Remember User Settings</B> - keep the zoom level where the user previously left
it.</LI>
</UL>
<BR>
<BR>
<P>There are various edge color and highlight color options available to change. The
highlight colors are those to be used when the flow animations take place.</P>
</BLOCKQUOTE>
</BLOCKQUOTE>
@@ -36,8 +36,5 @@ dependencies {
api ("org.jgrapht:jgrapht-io:1.5.1") { exclude group: "org.antlr", module: "antlr4-runtime" }
runtimeOnly "org.jheaps:jheaps:0.13"
helpPath project(path: ":Base", configuration: 'helpPath')
}
+1 -2
View File
@@ -33,8 +33,7 @@ dependencies {
// Demangler Analyzer needs to find MicrosoftDemangler
api project(":MicrosoftDemangler")
helpPath project(path: ':Base', configuration: 'helpPath') // this module's help has links to Base help files
testImplementation project(path: ':Base', configuration: 'testArtifacts')
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
}
-2
View File
@@ -25,6 +25,4 @@ eclipse.project.name = 'Features ProgramDiff'
dependencies {
api project(":Base")
helpPath project(path: ":Base", configuration: 'helpPath')
}
+1 -4
View File
@@ -25,9 +25,6 @@ eclipse.project.name = 'Features Graph ProgramGraph'
dependencies {
api project(":Base")
helpPath project(path: ":Base", configuration: 'helpPath')
helpPath project(path: ":GraphServices", configuration: 'helpPath')
api project(":GraphServices")
}
@@ -495,8 +495,7 @@
<P>These are the display options for graphs that are types of "Program Graphs" such as
Call graphs, Block graphs, etc. These types of graphs
use program elements as vertices and reference types as edges. See
<A href="help/topics/GraphServices/GraphDisplay.htm#Graph_Type_Display_Options">Graph Type Display Options</A> for
general help on graph type display options.</P>
<B>Graph Type Display Options</B> for general help on graph type display options.</P>
</BLOCKQUOTE>
<P class="providedbyplugin">Provided by: <I>Program Graph Plugin</I></P>
+1 -2
View File
@@ -33,8 +33,7 @@ configurations {
dependencies {
api project(':Base')
helpPath project(path: ":Base", configuration: "helpPath")
jython JYTHON
jython JYTHON
api JYTHON
}
@@ -25,5 +25,4 @@ eclipse.project.name = 'Features SourceCodeLookup'
dependencies {
api project(":Base")
api project(":Decompiler")
helpPath project(path: ":Decompiler", configuration: 'helpPath')
}
@@ -27,8 +27,6 @@ project.ext.excludeFromParallelIntegrationTests = true
dependencies {
api project(":Base")
helpPath project(path: ":Base", configuration: "helpPath")
testImplementation project(path: ':Project', configuration: 'testArtifacts')
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
}
-2
View File
@@ -30,6 +30,4 @@ dependencies {
// Only include this debug version of the jh library if necessary.
//api name:'jh2.with.debug'
api 'javax.help:javahelp:2.0.05'
}
@@ -357,17 +357,6 @@ public class GHelpBuilder {
errorMessage(buffy.toString());
}
private static void warningMessage(String... message) {
StringBuilder buffy = new StringBuilder();
buffy.append("\n");
buffy.append(" !!!!! WARNING !!!!!\n");
for (String string : message) {
buffy.append('\t').append('\t').append(string).append('\n');
}
buffy.append("\n");
errorMessage(buffy.toString());
}
private static void printErrorMessage(String message) {
// this prevents error messages getting interspersed with output messages
flush();
@@ -68,7 +68,11 @@ public class HelpBuildUtils {
return new DirectoryHelpModuleLocation(file);
}
else if (file.isFile()) {
return new JarHelpModuleLocation(file);
JarHelpModuleLocation jarLocation = JarHelpModuleLocation.fromFile(file);
if (jarLocation == null) {
HelpBuildUtils.debug("Jar file does not contain help: " + file);
}
return jarLocation;
}
throw new IllegalArgumentException(
"Don't know how to create a help module location for file: " + file);
@@ -15,16 +15,16 @@
*/
package help;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import ghidra.util.exception.AssertException;
import help.validator.LinkDatabase;
import help.validator.location.HelpModuleCollection;
import help.validator.model.AnchorDefinition;
import help.validator.model.GhidraTOCFile;
import java.io.*;
import java.nio.file.*;
import java.util.*;
/**
* This class:
* <ul>
@@ -129,7 +129,8 @@ public class JavaHelpFilesBuilder {
PrintWriter out = new LogFileWriter(mapFile);
try {
out.println("<?xml version='1.0' encoding='ISO-8859-1' ?>");
out.println("<!doctype MAP public \"-//Sun Microsystems Inc.//DTD JavaHelp Map Version 1.0//EN\">");
out.println(
"<!doctype MAP public \"-//Sun Microsystems Inc.//DTD JavaHelp Map Version 1.0//EN\">");
out.println("<!-- Auto-generated on " + (new Date()).toString() + " : Do Not Edit -->");
out.println("<map version=\"1.0\">");
@@ -166,8 +167,8 @@ public class JavaHelpFilesBuilder {
}
if (!parent.endsWith("help")) {
throw new AssertException("Map file expected in a directory name 'help'. "
+ "Update the map file generation code.");
throw new AssertException("Map file expected in a directory name 'help'. " +
"Update the map file generation code.");
}
if (!anchorTarget.startsWith("help")) {
@@ -92,8 +92,11 @@ public class UnusedHelpImageFileFinder {
}
SortedSet<Path> set =
new TreeSet<>((f1, f2) -> f1.toUri().toString().toLowerCase().compareTo(
f2.toUri().toString().toLowerCase()));
new TreeSet<>((f1, f2) -> f1.toUri()
.toString()
.toLowerCase()
.compareTo(
f2.toUri().toString().toLowerCase()));
for (Path file : imageFiles) {
IMG img = fileToIMGMap.get(file);
if (img == null && !isExcludedImageFile(file)) {
@@ -173,7 +176,10 @@ public class UnusedHelpImageFileFinder {
}
// Create the help directory
helpCollections.add(HelpBuildUtils.toLocation(helpDirectoryFile));
HelpModuleLocation location = HelpBuildUtils.toLocation(helpDirectoryFile);
if (location != null) {
helpCollections.add(location);
}
}
return helpCollections;
@@ -20,15 +20,16 @@ import java.net.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import javax.help.HelpSet;
import javax.help.Map.ID;
import javax.help.TOCView;
import javax.swing.tree.DefaultMutableTreeNode;
import help.CustomTOCView.CustomTreeItemDecorator;
import help.HelpBuildUtils;
import help.TOCItemProvider;
import help.CustomTOCView.CustomTreeItemDecorator;
import help.validator.model.*;
/**
@@ -98,7 +99,10 @@ public class HelpModuleCollection implements TOCItemProvider {
}
private HelpModuleCollection(Collection<HelpModuleLocation> locations) {
helpLocations = new LinkedHashSet<>(locations);
helpLocations = locations.stream()
.filter(l -> l != null)
.collect(Collectors.toCollection(LinkedHashSet::new));
loadTOCs();
@@ -22,6 +22,7 @@ import java.util.*;
import javax.help.HelpSet;
import ghidra.util.exception.AssertException;
import help.HelpBuildUtils;
import help.validator.model.*;
public abstract class HelpModuleLocation {
@@ -47,13 +48,16 @@ public abstract class HelpModuleLocation {
public abstract HelpSet loadHelpSet();
/** Returns true if this help location represents a source of input files to generate help output */
/**
* Returns true if this help location represents a source of input files to generate help output
* @return true if this help location represents a source of input files to generate help output
*/
public abstract boolean isHelpInputSource();
protected void loadHelpTopics() {
Path helpTopicsDir = helpDir.resolve("topics");
if (!Files.exists(helpTopicsDir)) {
throw new AssertException("No topics found in help dir: " + helpDir);
HelpBuildUtils.debug("No topics found in help dir: " + this);
}
try (DirectoryStream<Path> ds = Files.newDirectoryStream(helpTopicsDir);) {
@@ -65,7 +69,7 @@ public abstract class HelpModuleLocation {
}
catch (IOException e) {
// I suppose there aren't any
throw new AssertException("No topics found in help dir: " + helpDir);
throw new AssertException("No topics found in help dir: " + this);
}
}
@@ -193,7 +197,7 @@ public abstract class HelpModuleLocation {
}
List<AnchorDefinition> list = map.get(name);
if (list == null) {
list = new ArrayList<AnchorDefinition>();
list = new ArrayList<>();
map.put(name, list);
}
list.add(anchorDefinition);
@@ -21,7 +21,6 @@ import java.net.*;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import javax.help.HelpSet;
import javax.help.HelpSetException;
@@ -32,17 +31,29 @@ import help.validator.model.GhidraTOCFile;
public class JarHelpModuleLocation extends HelpModuleLocation {
/*
* format of 'helpDir':
* jar:file:///.../ghidra-prep/Ghidra/Features/Base/build/libs/Base.jar!/help
*/
private static final Pattern JAR_FILENAME_PATTERN = Pattern.compile(".*/(\\w*)\\.jar!/.*");
private static Map<String, String> env = new HashMap<String, String>();
private static Map<String, String> env = new HashMap<>();
static {
env.put("create", "false");
}
public static JarHelpModuleLocation fromFile(File jar) {
FileSystem fs = getOrCreateJarFS(jar);
Path helpRootPath = fs.getPath("/help");
if (!Files.exists(helpRootPath)) {
return null;
}
Path topicsPath = helpRootPath.resolve("topics");
if (!Files.exists(topicsPath)) {
// all help locations must have a topics directory; we can get here if the jar contains
// a package with the name 'help'
return null;
}
return new JarHelpModuleLocation(jar, helpRootPath);
}
private static FileSystem getOrCreateJarFS(File jar) {
URI jarURI;
try {
@@ -64,8 +75,8 @@ public class JarHelpModuleLocation extends HelpModuleLocation {
}
}
public JarHelpModuleLocation(File file) {
super(getOrCreateJarFS(file).getPath("/help"));
private JarHelpModuleLocation(File jar, Path path) {
super(path);
}
@Override
@@ -101,9 +112,11 @@ public class JarHelpModuleLocation extends HelpModuleLocation {
}
private String getModuleName(File jarFile) {
String name = jarFile.getName();
int dotIndex = name.indexOf('.');
int dotIndex = name.indexOf("-help.jar"); // dev mode
if (dotIndex == -1) {
dotIndex = name.indexOf(".jar"); // production mode
}
return name.substring(0, dotIndex);
}
@@ -17,8 +17,6 @@ package help.validator.location;
import java.nio.file.Path;
import help.validator.location.HelpModuleLocation;
public abstract class HelpModuleLocationTestDouble extends HelpModuleLocation {
// this class exists to open up the package-level constructor
@@ -42,14 +42,6 @@ file(ghidraDir + "/application.properties").withReader { reader ->
***************************************************************************************/
checkGradleVersion()
configurations {
helpPath
}
artifacts {
helpPath jar
}
task copyDependencies(type: Copy) {
from configurations.runtimeClasspath
into "lib"
@@ -76,7 +68,6 @@ dependencies {
api fileTree(dir: ghidraDir + '/Features', include: "**/*.jar")
api fileTree(dir: ghidraDir + '/Debug', include: "**/*.jar")
api fileTree(dir: ghidraDir + '/Processors', include: "**/*.jar")
helpPath fileTree(dir: ghidraDir + '/Features/Base', include: "**/Base.jar")
}
def ZIP_NAME_PREFIX = "${DISTRO_PREFIX}_${RELEASE_NAME}_${getCurrentDate()}"
@@ -180,73 +171,211 @@ task buildExtension (type: Zip) {
}
}
// 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()}
/*********************************************************************************
* Help Build Code
* Note: This code is derived from helpProject.gradle. Required changes should
* be made to that file and then reapplied here.
*********************************************************************************/
dependsOn configurations.helpPath
sourceSets {
// register help resources to be considered inputs to this project; when these resources change,
// this project will be considered out-of-date
main {
resources {
srcDir 'src/main/help' // help .html files to be copied to the jar
srcDir 'build/help/main' // generated help items (from the indexer); copied to the jar
}
}
}
// Turns the given file into a 'normalized' path using the Java Path API
def normalize(File file) {
def path = null;
try {
path = java.nio.file.Paths.get(file.getAbsolutePath());
}
catch (Exception e) { // InvalidPathException
// we have seen odd strings being placed into the classpath--ignore them
return cpPath;
}
def normalizedPath = path.normalize();
def absolutePath = normalizedPath.toAbsolutePath();
return absolutePath.toString();
}
// Returns the Ghidra module directory for the given file if it is a Ghidra jar file
def getModulePathFromJar(File file) {
String path = normalize(file)
String forwardSlashedPath = path.replaceAll("\\\\", "/")
def jarPattern = ~'.*/(.*)/(?:lib|build/libs)/(.+).jar'
def matcher = jarPattern.matcher(forwardSlashedPath)
if (!matcher.matches()) {
return null
}
def moduleName = matcher.group(1);
def index = forwardSlashedPath.indexOf(moduleName) + moduleName.length()
return forwardSlashedPath.substring(0, index)
}
// This method contains logic for calculating help inputs based on the classpath of the project
// The work is cached, as the inputs may be requested multiple times during a build
ext.helpInputsCache = null
def getHelpInputs(Collection fullClasspath) {
if (ext.helpInputsCache != null) {
return ext.helpInputsCache
}
def results = new HashSet<File>()
fullClasspath.each {
String moduleDirPath = getModulePathFromJar(it)
if (moduleDirPath == null) {
return // continue
}
getHelpInputsFromModule(moduleDirPath, results)
}
// the classpath above does not include my module's contents, so add that manually
def modulePath = file('.').getAbsolutePath()
getHelpInputsFromModule(modulePath, results)
ext.helpInputsCache = results.findAll(File::exists)
return ext.helpInputsCache
}
def getHelpInputsFromModule(String moduleDirPath, Set<File> results) {
// add all desired directories now and filter later those that do not exist
File moduleDir = new File(moduleDirPath)
results.add(new File(moduleDir, 'src/main/resources')) // images
results.add(new File(moduleDir, 'src/main/help')) // html files
File dataDir = new File(moduleDir, 'data') // theme properties files
if (dataDir.exists()) {
FileCollection themeFiles = fileTree(dataDir) {
include '**/*.theme.properties'
}
results.addAll(themeFiles.getFiles())
}
}
// Returns true if the given file is a jar file that contains a '/help/topics' diretory
def hasJarHelp(File file) {
if (!file.exists()) {
return false
}
if (!file.getAbsolutePath().endsWith(".jar")) {
return false
}
def fileSystem = null;
try {
def jarURI = new URI("jar:file://" + file.toURI().getRawPath());
fileSystem = java.nio.file.FileSystems.getFileSystem(jarURI);
}
catch (Exception e) { // FileSystemNotFoundException
// handled below
}
if (fileSystem == null) {
// not yet created; try to create the file system
def jarURI = new URI("jar:file://" + file.toURI().getRawPath());
def env = Map.of("create", "false")
fileSystem = java.nio.file.FileSystems.newFileSystem(jarURI, env);
}
def topicsPath = fileSystem.getPath("/help/topics");
return java.nio.file.Files.exists(topicsPath)
}
tasks.register('cleanHelp') {
File helpOutput = file('build/help/main/help')
doFirst {
delete helpOutput
}
}
// Task for calling the java help indexer, which creates a searchable index of the help contents
tasks.register('indexHelp', JavaExec) {
File helpRootDir = file('src/main/help/help')
File outputFile = file("build/help/main/help/${project.name}_JavaHelpSearch")
inputs.dir helpRootDir
outputs.dir outputFile
classpath = sourceSets.main.runtimeClasspath // this modules runtime classpath (contains jhall.jar)
mainClass = 'com.sun.java.help.search.Indexer' // main class to call
// tell the indexer where send its output
classpath = sourceSets.main.runtimeClasspath
args '-db', outputFile.absolutePath
mainClass = 'com.sun.java.help.search.Indexer'
// 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 {
// gather up all the help files into a file collection
FileTree helpFiles = fileTree('src/main/help') {
include '**/*.htm'
include '**/*.html'
}
// 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')
// create the config file when the task runs and not during configuration.
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"
// 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 {
// tell the indexer where send its output
args '-db', outputFile.absolutePath
// 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()}
// Task for building Ghidra help files
// - depends on the output from the help indexer
// - validates help
// - the files generated will be placed in a diretory usable during development mode and will
// eventually be placed in the <Module>.jar file
tasks.register('buildHelp', JavaExec) {
group "private"
dependsOn 'indexHelp'
File helpRootDir = file('src/main/help/help')
File outputDir = file('build/help/main/help')
inputs.dir helpRootDir
inputs.files({
// Note: this must be done lazily in a closure since the classpath is not ready at
// configuration time.
return getHelpInputs(sourceSets.main.runtimeClasspath.files)
})
outputs.dir outputDir
classpath = sourceSets.main.runtimeClasspath // this modules runtime classpath (contains jhall.jar)
mainClass = 'help.GHelpBuilder' // program to run to build help files.
mainClass = 'help.GHelpBuilder'
args '-n', "${project.name}" // use the modules name as the base for the help file name
args '-n', "${project.name}" // use the module's name for the help file name
args '-o', "${outputDir.absolutePath}" // set the output directory arg
@@ -254,21 +383,48 @@ task buildHelp(type: JavaExec, dependsOn: indexHelp) {
systemProperties = [
"ADDITIONAL_APPLICATION_ROOT_DIRS": "${ghidraInstallDir}/Ghidra"
]
// args '-debug' // print debug info
doFirst {
configurations.helpPath.each {
//
// The classpath needs to include:
// 1) the jar of each dependent Module that has already been built
// 2) 'src/main/resources'
//
// Each java project and its dependencies are needed to locate each Ghidra module. Each
// module is scanned to find the theme properties files in the 'data' directories.
classpath += sourceSets.main.runtimeClasspath
classpath += files('src/main/resources')
// To build help, the validator needs any other help content that this module may reference.
// Add each of these dependencies as an argument to the validator.
def helpJars = classpath.findAll(file -> hasJarHelp(file))
helpJars.each {
args "-hp"
args "${it.absolutePath}"
}
args "${helpRootDir.absolutePath}" // tell the help builder what help dir to process
// The help dir to process. This needs to be the last argument to the process,
// thus, this is why it is inside of this block
args "${helpRootDir.absolutePath}"
// Sigal that any System.out messages from this Java process should be logged at INFO level.
// To see this output, run gradle with the '-i' option to show INFO messages.
logging.captureStandardOutput LogLevel.INFO
}
description " Builds the help for this module. [gradle/helpProject.gradle]\n"
}
// include the help into the module's jar
jar {
duplicatesStrategy 'exclude'
from "build/help/main" // include the generated help index files
from "src/main/help" // include the help source files
from "src/main/help" // include the help source files
archiveVersion = ""
}
@@ -276,6 +432,10 @@ jar {
jar.dependsOn 'buildHelp'
/*********************************************************************************
* End Help Build Code
*********************************************************************************/
/*********************************************************************************
* Takes the given file and returns a string representing the file path with everything
+316 -96
View File
File diff suppressed because it is too large Load Diff