679 lines
23 KiB
Groovy
679 lines
23 KiB
Groovy
apply from: "$rootProject.projectDir/gradle/javaProject.gradle"
|
|
apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
|
|
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
|
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
|
|
apply from: "$rootProject.projectDir/gradle/helpProject.gradle"
|
|
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
|
apply plugin: 'eclipse'
|
|
|
|
eclipse.project.name = 'Features Decompiler'
|
|
|
|
dependencies {
|
|
compile project(':Base')
|
|
compile project(':SoftwareModeling')
|
|
// include Base src/test/resources when running decompiler integration tests (uses defaultTools)
|
|
integrationTestRuntime project(path: ':Base', configuration: 'testArtifacts')
|
|
testCompile "org.jmockit:jmockit:1.44"
|
|
|
|
helpPath project(path: ":Base", configuration: 'helpPath')
|
|
}
|
|
|
|
ext.cppSourceDir = "src/decompile/cpp"
|
|
|
|
/**
|
|
* The bison and flex generated files are maintained in source control and
|
|
* do not need regeneration unless changes have been made to the yacc (*.y),
|
|
* lex (*.l) or any critical header file. This stand-alone task should be
|
|
* executed as needed prior to building the decompiler or sleigh native
|
|
* executables.
|
|
*/
|
|
task generateParsers {
|
|
dependsOn "lexSleigh", "yaccDecompiler"
|
|
}
|
|
|
|
/**
|
|
* This task calls bison to process the grammar.y and xml.y files (yacc) to
|
|
* generate the corresponding *.cc files that will then be compiled with the rest
|
|
* of the decompiler code.
|
|
*/
|
|
task yaccDecompiler {
|
|
|
|
Task t1 = createBisonTask("xml", "decompile", false, true);
|
|
Task t2 = createBisonTask("grammar", "decompile", false, true);
|
|
|
|
if (t1 != null) {
|
|
dependsOn t1, t2
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This task calls bison to process the slghparse.y, pcodeparse.y and xml.y
|
|
* files (yacc) to generate the corresponding *.cc files that will then be compiled
|
|
* with the rest of the sleigh code.
|
|
*/
|
|
task yaccSleigh {
|
|
|
|
Task t1 = createBisonTask("slghparse", "sleigh", true, false); // also produces slghparse.hh header file
|
|
Task t2 = createBisonTask("pcodeparse", "sleigh", false, true);
|
|
Task t3 = createBisonTask("xml", "sleigh", false, true);
|
|
|
|
if (t1 != null) {
|
|
dependsOn t1,t2,t3
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This task calls flex to process the slghscan.l file (lex) into a cpp file that will then
|
|
* be compiled with the rest of the sleigh code.
|
|
*/
|
|
task lexSleigh {
|
|
|
|
dependsOn "yaccSleigh"
|
|
|
|
Task t1 = createLexTask("slghscan", "sleighlex")
|
|
|
|
if (t1 != null) {
|
|
// TODO: add missing task input file dependencies
|
|
dependsOn t1
|
|
}
|
|
}
|
|
|
|
def buildDir = "../../../build" // Relative to the 'workingDir' Exec task property.
|
|
|
|
def installPoint = "$rootDir/GhidraDocs/languages/html"
|
|
|
|
def installHelpPoint = "../help/help"
|
|
|
|
task buildDecompilerHelpHtml(type: Exec) {
|
|
|
|
workingDir 'src/main/doc'
|
|
|
|
// 'which' returns the number of failed arguments
|
|
// Using the 'which' command first will allow the task to fail if the required
|
|
// executables are not installed.
|
|
//
|
|
// The bash commands end with "2>&1" to redirect stderr to stdout and have all
|
|
// messages print in sequence
|
|
//
|
|
// 'commandLine' takes one command, so wrap multiple commands in bash.
|
|
commandLine 'bash', '-e', '-c', """
|
|
echo '** Checking if required executables are installed. **'
|
|
which xsltproc
|
|
which sed
|
|
|
|
echo '** Removing older html files installed under '$installHelpPoint' **'
|
|
rm -f $installHelpPoint/topics/DecompilePlugin/*.html
|
|
|
|
echo '** Building html files **'
|
|
xsltproc --output $buildDir/decomp_noscaling.xml --stringparam profile.condition "noscaling" /usr/share/sgml/docbook/xsl-stylesheets/profiling/profile.xsl decompileplugin.xml 2>&1
|
|
xsltproc --stringparam base.dir ${installHelpPoint}/topics/DecompilePlugin/ --stringparam root.filename Decompiler decompileplugin_html.xsl $buildDir/decomp_noscaling.xml 2>&1
|
|
rm ${installHelpPoint}/topics/DecompilePlugin/Decompiler.html
|
|
sed -i -e '/Frontpage.css/ { p; s/Frontpage.css/languages.css/; }' ${installHelpPoint}/topics/DecompilePlugin/*.html 2>&1
|
|
|
|
echo '** Done. **'
|
|
"""
|
|
|
|
// Allows doLast block regardless of exit value.
|
|
ignoreExitValue true
|
|
|
|
// Store the output instead of printing to the console.
|
|
standardOutput = new ByteArrayOutputStream()
|
|
ext.output = { standardOutput.toString() }
|
|
ext.errorOutput = { standardOutput.toString() }
|
|
|
|
// Check the OS before executing command.
|
|
doFirst {
|
|
if (!getCurrentPlatformName().startsWith("linux")) {
|
|
throw new TaskExecutionException( it, new Exception("The '$it.name' task only works on Linux."))
|
|
}
|
|
}
|
|
|
|
// Print the output of the commands and check the return value.
|
|
doLast {
|
|
println output()
|
|
if (execResult.exitValue) {
|
|
logger.error("$it.name: An error occurred. Here is the output:\n" + output())
|
|
throw new TaskExecutionException( it, new Exception("'$it.name': The command: '${commandLine.join(' ')}'" +
|
|
" task \nfailed with exit code $execResult.exitValue; see task output for details."))
|
|
}
|
|
}
|
|
}
|
|
|
|
task buildDecompilerHelpPdf(type: Exec) {
|
|
// Check the OS before enabling task.
|
|
if (!(org.gradle.internal.os.OperatingSystem.current().isLinux()
|
|
|| org.gradle.internal.os.OperatingSystem.current().isMacOsX())) {
|
|
it.enabled = false
|
|
}
|
|
|
|
workingDir 'src/main/doc'
|
|
|
|
// 'which' returns the number of failed arguments
|
|
// Using 'which' first will allow the entire command to fail if the required
|
|
// executables are not installed.
|
|
//
|
|
// The bash commands end with "2>&1" to redirect stderr to stdout and have all
|
|
// messages print in sequence
|
|
//
|
|
// 'commandLine' takes one command, so wrap multiple commands in bash.
|
|
commandLine 'bash', '-e', '-c', """
|
|
echo '** Checking if required executables are installed. **'
|
|
which fop 2>&1
|
|
which xsltproc 2>&1
|
|
rm -f decompileplugin.fo decompileplugin.pdf decompileplugin_withscaling.xml 2>&1
|
|
rm -rf ./images 2>&1
|
|
mkdir -p ./images 2>&1
|
|
cp $installHelpPoint/topics/DecompilePlugin/images/*.png ./images 2>&1
|
|
cp $installHelpPoint/topics/DecompilePlugin/images/*.gif ./images 2>&1
|
|
cp $installHelpPoint/shared/*.png ./images 2>&1
|
|
|
|
echo '** Building decompileplugin.fo **'
|
|
xsltproc --output ./decompileplugin_withscaling.xml --stringparam profile.condition "withscaling" /usr/share/sgml/docbook/xsl-stylesheets/profiling/profile.xsl decompileplugin.xml 2>&1
|
|
xsltproc --output ./decompileplugin.fo decompileplugin_pdf.xsl decompileplugin_withscaling.xml 2>&1
|
|
|
|
echo '** Building decompileplugin.pdf **'
|
|
fop decompileplugin.fo decompileplugin.pdf 2>&1
|
|
|
|
echo '** Done. **'
|
|
"""
|
|
|
|
// Allows doLast block regardless of exit value. Task does not fail if bash command fails.
|
|
ignoreExitValue true
|
|
|
|
// Store the output instead of printing to the console.
|
|
standardOutput = new ByteArrayOutputStream()
|
|
ext.output = { standardOutput.toString() }
|
|
ext.errorOutput = { standardOutput.toString() }
|
|
|
|
// Print the output of the commands and check the return value.
|
|
doLast {
|
|
println output()
|
|
if (execResult.exitValue) {
|
|
println "$it.name: An error occurred with this task. Here is the output:\n" + output()
|
|
println "Skipping task $it.name\n"
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build the pdfs docs for the decompiler and place them in the '$buildDir' directory.
|
|
* A build (ex: 'gradle buildGhidra') will place the pdfs in the distribution zip file.
|
|
* This task will fail gracefully and allow any distribution task (like buildGhidra) to continue,
|
|
* without pdfs in the distribution zip.
|
|
* There is an associated, auto-generated clean task.
|
|
*/
|
|
task buildDecompilerDocumentationPdfs(type: Exec) {
|
|
// Check the OS before enabling task.
|
|
if (!(org.gradle.internal.os.OperatingSystem.current().isLinux()
|
|
|| org.gradle.internal.os.OperatingSystem.current().isMacOsX())) {
|
|
it.enabled = false
|
|
}
|
|
|
|
workingDir 'src/main/doc'
|
|
|
|
// Gradle will provide a cleanBuildDecompilerDocumentationPdfs task that will remove these
|
|
// declared outputs.
|
|
outputs.file "$workingDir/$buildDir/pcoderef.fo"
|
|
outputs.file "$workingDir/$buildDir/pcoderef.pdf"
|
|
outputs.file "$workingDir/$buildDir/sleigh.fo"
|
|
outputs.file "$workingDir/$buildDir/sleigh.pdf"
|
|
|
|
// 'which' returns the number of failed arguments
|
|
// Using 'which' first will allow the entire command to fail if the required
|
|
// executables are not installed.
|
|
//
|
|
// The bash commands end with "2>&1" to redirect stderr to stdout and have all
|
|
// messages print in sequence
|
|
//
|
|
// 'commandLine' takes one command, so wrap multiple commands in bash.
|
|
commandLine 'bash', '-e', '-c', """
|
|
echo '** Checking if required executables are installed. **'
|
|
which fop 2>&1
|
|
which xsltproc 2>&1
|
|
mkdir -p $buildDir 2>&1
|
|
cp $installPoint/Diagram*.png $buildDir 2>&1
|
|
|
|
echo '** Building sleigh.fo **'
|
|
xsltproc --output $buildDir/sleigh.fo sleigh_pdf.xsl sleigh.xml 2>&1
|
|
|
|
echo '** Building sleigh.pdf **'
|
|
fop $buildDir/sleigh.fo $buildDir/sleigh.pdf 2>&1
|
|
|
|
echo '** Building pcoderef.fo **'
|
|
xsltproc --output $buildDir/pcoderef.fo pcoderef_pdf.xsl pcoderef.xml 2>&1
|
|
|
|
echo '** Building pcoderef.pdf **'
|
|
fop $buildDir/pcoderef.fo $buildDir/pcoderef.pdf 2>&1
|
|
|
|
echo '** Done. **'
|
|
"""
|
|
|
|
// Allows doLast block regardless of exit value. Task does not fail if bash command fails.
|
|
ignoreExitValue true
|
|
|
|
// Store the output instead of printing to the console.
|
|
standardOutput = new ByteArrayOutputStream()
|
|
ext.output = { standardOutput.toString() }
|
|
ext.errorOutput = { standardOutput.toString() }
|
|
|
|
// Print the output of the commands and check the return value.
|
|
doLast {
|
|
println output()
|
|
if (execResult.exitValue) {
|
|
println "$it.name: An error occurred with this task. Here is the output:\n" + output()
|
|
println "Skipping task $it.name\n"
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build the html docs for the decompiler and place them in the '$installPoint' directory.
|
|
* This gradle task will overwrite the html docs currently in the git repo.
|
|
* A build (ex: 'gradle buildGhidra') will place the html files in the distribution, but buildGhidra
|
|
* does not depend on buildDecompilerDocumentationHtml.
|
|
* There is an associated, auto-generated clean task.
|
|
**/
|
|
task buildDecompilerDocumentationHtml(type: Exec) {
|
|
|
|
workingDir 'src/main/doc'
|
|
|
|
// Gradle will provide a cleanBuildDecompilerDocumentationHtml task that will remove these
|
|
// declared outputs.
|
|
outputs.file "$workingDir/$buildDir/index.html"
|
|
outputs.dir "$workingDir/$buildDir/html"
|
|
|
|
|
|
// 'which' returns the number of failed arguments
|
|
// Using the 'which' command first will allow the task to fail if the required
|
|
// executables are not installed.
|
|
//
|
|
// The bash commands end with "2>&1" to redirect stderr to stdout and have all
|
|
// messages print in sequence
|
|
//
|
|
// 'commandLine' takes one command, so wrap multiple commands in bash.
|
|
commandLine 'bash', '-e', '-c', """
|
|
echo '** Checking if required executables are installed. **'
|
|
which sed 2>&1
|
|
which xsltproc 2>&1
|
|
|
|
echo -e '** Building index.html **'
|
|
xsltproc --output $buildDir/index.html main_html.xsl main.xml 2>&1
|
|
sed -i -e '/Frontpage.css/ { p; s/Frontpage.css/languages.css/; }' $buildDir/index.html
|
|
|
|
echo '** Building html/sleigh.html **'
|
|
xsltproc --stringparam base.dir $buildDir/html/ --stringparam root.filename sleigh sleigh_html.xsl sleigh.xml 2>&1
|
|
sed -i -e '/Frontpage.css/ { p; s/Frontpage.css/languages.css/; }' $buildDir/html/sleigh*.html
|
|
cp $installPoint/Frontpage.css $buildDir/html 2>&1
|
|
cp $installPoint/languages.css $buildDir/html
|
|
cp $installPoint/Diagram1.png $buildDir/html
|
|
cp $installPoint/Diagram2.png $buildDir/html
|
|
cp $installPoint/Diagram3.png $buildDir/html
|
|
|
|
echo '** Building html/pcoderef.html **'
|
|
xsltproc --stringparam base.dir $buildDir/html/ --stringparam root.filename pcoderef pcoderef_html.xsl pcoderef.xml 2>&1
|
|
sed -i -e '/Frontpage.css/ { p; s/Frontpage.css/languages.css/; }' $buildDir/html/pcoderef.html
|
|
sed -i -e '/Frontpage.css/ { p; s/Frontpage.css/languages.css/; }' $buildDir/html/pcodedescription.html
|
|
sed -i -e '/Frontpage.css/ { p; s/Frontpage.css/languages.css/; }' $buildDir/html/pseudo-ops.html
|
|
sed -i -e '/Frontpage.css/ { p; s/Frontpage.css/languages.css/; }' $buildDir/html/reference.html
|
|
cp $installPoint/Frontpage.css $buildDir/html
|
|
cp $installPoint/languages.css $buildDir/html
|
|
|
|
echo '** Installing html documentation. **'
|
|
cp $buildDir/index.html $installPoint/index.html
|
|
rm $installPoint/*.html $installPoint/*.png
|
|
cp $buildDir/html/*.html $buildDir/html/*.png $installPoint/
|
|
echo '** Done. **'
|
|
"""
|
|
|
|
// Allows doLast block regardless of exit value.
|
|
ignoreExitValue true
|
|
|
|
// Store the output instead of printing to the console.
|
|
standardOutput = new ByteArrayOutputStream()
|
|
ext.output = { standardOutput.toString() }
|
|
ext.errorOutput = { standardOutput.toString() }
|
|
|
|
// Check the OS before executing command.
|
|
doFirst {
|
|
if ( !(org.gradle.internal.os.OperatingSystem.current().isLinux()
|
|
|| org.gradle.internal.os.OperatingSystem.current().isMacOsX())) {
|
|
throw new TaskExecutionException( it,
|
|
new Exception( "The '$it.name' task only works on Linux or Mac Os X" ))
|
|
}
|
|
}
|
|
|
|
// Print the output of the commands and check the return value.
|
|
doLast {
|
|
println output()
|
|
if (execResult.exitValue) {
|
|
logger.error("$it.name: An error occurred. Here is the output:\n" + output())
|
|
throw new TaskExecutionException( it,
|
|
new Exception( "$it.name: The command: '${commandLine.join(' ')}'" +
|
|
"\nfailed with exit code $execResult.exitValue; see task output for details." )
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Define the "native build model" for building the decompiler executables.
|
|
*/
|
|
model {
|
|
|
|
// Define the source files that are compiled and linked to become the decompiler.
|
|
// The decompiler source is a bit weird in that all the cpp and headers all live in
|
|
// the same directory with other files that are not used by the decompiler.
|
|
// That is why we have to list every cpp file that makes up the decomplier.
|
|
components {
|
|
|
|
decompile(NativeExecutableSpec) {
|
|
|
|
baseName "decompile"
|
|
|
|
// these tell gradle for which platforms to build a decompiler executable.
|
|
targetPlatform "win64"
|
|
targetPlatform "linux64"
|
|
targetPlatform "osx64"
|
|
sources {
|
|
cpp {
|
|
// NOTE: The bison/flex generated files are assumed to be up-to-date.
|
|
// The task `generateParsers` should be executed if needed.
|
|
// builtBy yaccDecompiler
|
|
source {
|
|
srcDir "src/decompile/cpp"
|
|
|
|
include "space.cc"
|
|
include "float.cc"
|
|
include "address.cc"
|
|
include "pcoderaw.cc"
|
|
include "translate.cc"
|
|
include "opcodes.cc"
|
|
include "globalcontext.cc"
|
|
include "capability.cc"
|
|
include "architecture.cc"
|
|
include "options.cc"
|
|
include "graph.cc"
|
|
include "cover.cc"
|
|
include "block.cc"
|
|
include "cast.cc"
|
|
include "typeop.cc"
|
|
include "database.cc"
|
|
include "cpool.cc"
|
|
include "comment.cc"
|
|
include "stringmanage.cc"
|
|
include "fspec.cc"
|
|
include "action.cc"
|
|
include "loadimage.cc"
|
|
include "varnode.cc"
|
|
include "op.cc"
|
|
include "type.cc"
|
|
include "variable.cc"
|
|
include "varmap.cc"
|
|
include "jumptable.cc"
|
|
include "emulate.cc"
|
|
include "emulateutil.cc"
|
|
include "flow.cc"
|
|
include "userop.cc"
|
|
include "funcdata.cc"
|
|
include "funcdata_block.cc"
|
|
include "funcdata_varnode.cc"
|
|
include "funcdata_op.cc"
|
|
include "pcodeinject.cc"
|
|
include "heritage.cc"
|
|
include "prefersplit.cc"
|
|
include "rangeutil.cc"
|
|
include "ruleaction.cc"
|
|
include "subflow.cc"
|
|
include "transform.cc"
|
|
include "blockaction.cc"
|
|
include "merge.cc"
|
|
include "double.cc"
|
|
include "coreaction.cc"
|
|
include "condexe.cc"
|
|
include "override.cc"
|
|
include "dynamic.cc"
|
|
include "crc32.cc"
|
|
include "prettyprint.cc"
|
|
include "printlanguage.cc"
|
|
include "printc.cc"
|
|
include "printjava.cc"
|
|
include "memstate.cc"
|
|
include "opbehavior.cc"
|
|
include "paramid.cc"
|
|
include "ghidra_arch.cc"
|
|
include "inject_ghidra.cc"
|
|
include "ghidra_translate.cc"
|
|
include "loadimage_ghidra.cc"
|
|
include "typegrp_ghidra.cc"
|
|
include "database_ghidra.cc"
|
|
include "ghidra_context.cc"
|
|
include "cpool_ghidra.cc"
|
|
include "ghidra_process.cc"
|
|
include "comment_ghidra.cc"
|
|
include "string_ghidra.cc"
|
|
// include "callgraph.cc" // uncomment for debug
|
|
// include "ifacedecomp.cc" // uncomment for debug
|
|
// include "ifaceterm.cc" // uncomment for debug
|
|
// include "interface.cc" // uncomment for debug
|
|
|
|
// generated source files
|
|
|
|
include "xml.cc"
|
|
// include "grammar.cc" // used by diagnostic console mode
|
|
}
|
|
exportedHeaders {
|
|
srcDir "src/decompile/cpp"
|
|
}
|
|
} // end cpp
|
|
} // end sources
|
|
} // end decompile
|
|
|
|
sleigh(NativeExecutableSpec) {
|
|
targetPlatform "win64"
|
|
targetPlatform "linux64"
|
|
targetPlatform "osx64"
|
|
sources {
|
|
cpp {
|
|
// NOTE: The bison/flex generated files are assumed to be up-to-date.
|
|
// The task `generateParsers` should be executed if needed.
|
|
// builtBy lexSleigh
|
|
source {
|
|
srcDir "src/decompile/cpp"
|
|
|
|
include "space.cc"
|
|
include "float.cc"
|
|
include "address.cc"
|
|
include "pcoderaw.cc"
|
|
include "translate.cc"
|
|
include "opcodes.cc"
|
|
include "globalcontext.cc"
|
|
include "sleigh.cc"
|
|
include "pcodecompile.cc"
|
|
include "sleighbase.cc"
|
|
include "slghsymbol.cc"
|
|
include "slghpatexpress.cc"
|
|
include "slghpattern.cc"
|
|
include "semantics.cc"
|
|
include "context.cc"
|
|
include "filemanage.cc"
|
|
include "slgh_compile.cc"
|
|
|
|
// generated source files
|
|
|
|
include "xml.cc"
|
|
include "pcodeparse.cc"
|
|
include "slghparse.cc"
|
|
include "slghscan.cc"
|
|
}
|
|
exportedHeaders {
|
|
srcDir "src/decompile/cpp"
|
|
}
|
|
} // end cpp
|
|
} // end sources (sleigh)
|
|
} // end sleigh
|
|
|
|
} // end components
|
|
|
|
binaries {
|
|
all{ b ->
|
|
if (b.toolChain in Gcc) {
|
|
b.cppCompiler.args "-Wall"
|
|
b.cppCompiler.args "-O2" // for DEBUG, comment this line out
|
|
// b.cppCompiler.args "-g" // for DEBUG, uncomment this line
|
|
b.cppCompiler.args "-Wno-sign-compare"
|
|
if (b.targetPlatform.operatingSystem.linux) {
|
|
// b.linker.args "-static"
|
|
b.cppCompiler.define "LINUX"
|
|
b.cppCompiler.define "_LINUX"
|
|
}
|
|
}
|
|
else if (b.toolChain in VisualCpp) {
|
|
b.cppCompiler.args "/EHsc"
|
|
b.cppCompiler.define "_SECURE_SCL=0"
|
|
b.cppCompiler.define "_HAS_ITERATOR_DEBUGGING=0"
|
|
// b.cppCompiler.args "/Zi" // for DEBUG, uncomment this line
|
|
// b.cppCompiler.args "/FS" // for DEBUG, uncomment this line
|
|
// b.linker.args "/DEBUG" // for DEBUG, uncomment this line
|
|
if (b.targetPlatform.operatingSystem.windows) {
|
|
b.cppCompiler.define "WINDOWS"
|
|
b.cppCompiler.define "_WINDOWS"
|
|
b.cppCompiler.define "WIN32"
|
|
b.cppCompiler.define "_WIN32"
|
|
if (b.targetPlatform.name == "win64") {
|
|
b.cppCompiler.define "WIN64"
|
|
b.cppCompiler.define "_WIN64"
|
|
}
|
|
}
|
|
}
|
|
else if (b.toolChain in Clang) {
|
|
b.cppCompiler.args "-Wall"
|
|
b.cppCompiler.args "-O2" // for DEBUG, comment this line out
|
|
// b.cppCompiler.args "-g" // for DEBUG, uncomment this line
|
|
b.cppCompiler.args "-Wno-sign-compare"
|
|
b.cppCompiler.args "-w"
|
|
if (b.targetPlatform.operatingSystem.linux) {
|
|
// b.linker.args "-static"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // end model
|
|
|
|
// Perform simple dependency change detection for generated files
|
|
// produced by bison or flex. A 5-second tolerance is used
|
|
// to avoid arbitrary last-modified times which may be produced
|
|
// by a git checkout.
|
|
boolean isUpToDate(File srcFile, File resultFile) {
|
|
long resultLm = resultFile.lastModified()
|
|
if (resultLm == 0) {
|
|
return true
|
|
}
|
|
long srcLm = srcFile.lastModified()
|
|
long elapsedTime = srcLm - resultLm
|
|
if (elapsedTime < 5000) {
|
|
println "Is UpToDate: ${resultFile}"
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Create a bison task to compile a yacc file (*.y) for the sleigh/decompiler
|
|
*/
|
|
Task createBisonTask(String filename, String binaryName, boolean generateHeader, boolean qualifyVariables) {
|
|
|
|
def outputCppDir = "${cppSourceDir}"
|
|
def outputHeadersDir = "${cppSourceDir}"
|
|
|
|
def yaccFile = "${cppSourceDir}/${filename}.y"
|
|
def ccFile = "${outputCppDir}/${filename}.cc"
|
|
def headerFile = "${outputCppDir}/${filename}.hh"
|
|
|
|
return task("bison_${binaryName}_$filename", type: Exec) {
|
|
|
|
inputs.file "${yaccFile}"
|
|
outputs.file "${ccFile}"
|
|
if (generateHeader) {
|
|
outputs.file "${headerFile}"
|
|
}
|
|
|
|
// doFirst {
|
|
// file(outputCppDir).mkdirs()
|
|
// file(outputHeadersDir)mkdirs()
|
|
// }
|
|
|
|
executable 'bison' // use bison program to process yacc files
|
|
|
|
// specify the bison's output file
|
|
args "-o", "${ccFile}"
|
|
|
|
// most of the yacc files should be compiled with a variable qualifyer to avoid dupes.
|
|
// Unfortunately there is one (slghparse) that can't use a qualifyer because it
|
|
// declares a variable used by other files.
|
|
|
|
if (qualifyVariables) {
|
|
args "-p", filename
|
|
}
|
|
|
|
// tell bison where to put the hh file.
|
|
if (generateHeader) {
|
|
args "--defines=${headerFile}"
|
|
}
|
|
|
|
// tell bison the file to compile
|
|
args "${yaccFile}"
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a flex task to compile a lex file (*.l) for sleigh.
|
|
*/
|
|
Task createLexTask(String filename, String binaryName) {
|
|
|
|
def outputCppDir = "${cppSourceDir}"
|
|
|
|
def lexFile = "${cppSourceDir}/${filename}.l"
|
|
def ccFile = "${outputCppDir}/${filename}.cc"
|
|
|
|
return task("lex_${binaryName}_$filename", type: Exec) {
|
|
|
|
// set up inputs and outputs so that gradle knows when this needs to be rebuilt
|
|
inputs.file "${lexFile}"
|
|
outputs.files "${ccFile}"
|
|
|
|
// doFirst {
|
|
// file(outputCppDir).mkdirs();
|
|
// }
|
|
|
|
executable 'flex' // the program to execute
|
|
|
|
// tell flex where to put the output
|
|
args "-o", "${ccFile}"
|
|
|
|
// tell flex the input file
|
|
args "${lexFile}"
|
|
}
|
|
}
|
|
|
|
rootProject.createInstallationZip {
|
|
dependsOn buildDecompilerDocumentationPdfs
|
|
|
|
|
|
def decompilerPdfZipPath = rootProject.ext.ZIP_DIR_PREFIX + "/docs/languages/"
|
|
|
|
// Add decompiler pdf files to zip. If the pdf files do not exist during execution time
|
|
// (if there was an error or wrong platform), the zip task will move on.
|
|
buildDecompilerDocumentationPdfs.outputs.each { output ->
|
|
output.files.each { file ->
|
|
if (file.name.endsWith("pdf")) {
|
|
logger.debug("$project.name: Adding Decompiler documentation (if it exists) $file.name to $decompilerPdfZipPath")
|
|
rootProject.createInstallationZip.from (file) {
|
|
into {
|
|
decompilerPdfZipPath
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|