GP-1209: Support for building natives from a release.

This commit is contained in:
Ryan Kurtz 2021-09-27 08:16:14 -04:00
parent af2d461d85
commit 3c07ca2962
22 changed files with 541 additions and 349 deletions

View File

@ -262,33 +262,16 @@ You may see build path errors until the environment is properly prepared, as des
### Building the natives ### Building the natives
Some of Ghidra's components are built for the native platform. Some of Ghidra's components are built for the native platform.
We currently support Linux, macOS, and Windows 64-bit x86 systems. We currently support 64-bit Linux x86/ARM, macOS x86/ARM, and Windows x86.
Others should be possible, but we do not test on them.
Now build using Gradle: Build the natives for your current platform using Gradle:
On Linux:
```bash ```bash
gradle buildNatives_linux_x86_64 gradle buildNatives
```
On macOS:
```bash
gradle buildNatives_mac_x86_64
```
On Windows:
```bash
gradle buildNatives_win_x86_64
``` ```
This will build the decompiler, the demangler for GNU toolchains, the sleigh compiler, and (on Windows only) the PDB parser. This will build the decompiler, the demangler for GNU toolchains, the sleigh compiler, and (on Windows only) the PDB parser.
**NOTE:** `buildNatives_linux_arm_64` and `buildNatives_mac_arm_64` are also supported.
### Pre-compile Language Modules (optional) ### Pre-compile Language Modules (optional)
Optionally, to pre-compile all the language modules, you may also execute: Optionally, to pre-compile all the language modules, you may also execute:

View File

@ -1,3 +0,0 @@
/* ###
* IP: Public Domain
*/

View File

@ -1,3 +0,0 @@
/* ###
* IP: Public Domain
*/

View File

@ -108,17 +108,27 @@ def shouldSkipNative(task) {
} }
/******************************************************************************************* /*******************************************************************************************
* Task Rule : builds all the natives in this module for a given platform. * Task Rule : buildNatives[_PlatformName]
* *
* Example : gradle buildNatives_win_x86_64 will build all win_x86_64 native executables and shared libraries. * Summary: Builds all the natives in this module for a given platform.
*
* Args: PlatformName - The name of the platform. If not specified, the current platform is used.
*
* Example: gradle buildNatives_win_x86_64 will build all win_x86_64 native executables and shared libraries.
* *
* NOTE: you must be on the appropriate platform for this to work. * NOTE: you must be on the appropriate platform for this to work.
*
******************************************************************************************/ ******************************************************************************************/
tasks.addRule("Pattern: buildNatives_<platform name>]: build all natives for given platform") { String taskName -> tasks.addRule("Pattern: buildNatives[_PlatformName]: build all natives for given platform") { String taskName ->
if (taskName.startsWith("buildNatives_")) { if (taskName.startsWith("buildNatives")) {
String platform = taskName - "buildNatives_" String currentPlatform = getCurrentPlatformName()
String platform = taskName - "buildNatives"
if (platform.length() == 0) {
platform = currentPlatform
}
if (platform.startsWith("_")) {
platform = platform - "_"
}
task(taskName) { myTask -> task(taskName) { myTask ->
@ -157,20 +167,30 @@ tasks.addRule("Pattern: buildNatives_<platform name>]: build all natives for giv
} }
} }
/******************************************************************************************* /*******************************************************************************************
* Task Rule : builds all the natives in this module for a given platform and copies the * Task Rule : prebuildNatives[_PlatformName]
* results to the bin repo.
* *
* Example : gradle prebuildNatives_win_x86_64 will build all win_x86_64 native executables and shared * Summary: Builds all the natives in this module for a given platform and copies the results
* libraries and copy the results to the appropriate project/os directory in the bin * to the bin repo.
* repo.
*
* NOTE: you must be on the appropriate platform for this to work.
* *
* Args: PlatformName - The name of the platform. If not specified, the current platform is used.
*
* Example: gradle prebuildNatives_win_x86_64 will build all win_x86_64 native executables and
* shared libraries and copy the results to the appropriate project/os directory in
* the bin repo.
*
* NOTE: you must be on the appropriate platform for this to work.
******************************************************************************************/ ******************************************************************************************/
tasks.addRule("Pattern: prebuildNatives_<platform name>]: build all natives for given platform") { String taskName -> tasks.addRule("Pattern: prebuildNatives<_platform name>]: build all natives for given platform") { String taskName ->
if (taskName.startsWith("prebuildNatives_")) { if (taskName.startsWith("prebuildNatives")) {
String platform = taskName - "prebuildNatives_" def currentPlatform = getCurrentPlatformName()
def platform = taskName - "prebuildNatives"
if (platform.length() == 0) {
platform = currentPlatform
}
if (platform.startsWith("_")) {
platform = platform - "_"
}
task(taskName) { myTask -> task(taskName) { myTask ->
dependsOn "buildNatives_$platform" dependsOn "buildNatives_$platform"
@ -214,8 +234,7 @@ gradle.taskGraph.whenReady {
} }
/***************************************************************************************** /*****************************************************************************************
* The following block of code ensures that the buildNatives_<platform> task is used * The following block of code ensures that the buildNatives (for current plaform) task is
* during assembly to ensure that missing toolchain generates an appropriate error * used during assembly to ensure that missing toolchain generates an appropriate error
****************************************************************************************/ ****************************************************************************************/
def currentPlatform = getCurrentPlatformName() assemble.dependsOn "buildNatives"
assemble.dependsOn "buildNatives_$currentPlatform"

12
GPL/settings.gradle Normal file
View File

@ -0,0 +1,12 @@
/* ###
* IP: Public Domain
*/
// Recurse root project subdirectories and include all discovered projects
// (directories containing a build.gradle file)
fileTree(rootProject.projectDir) {
exclude 'build.gradle' // exclude root project
include '**/build.gradle'
}.each {
include it.parentFile.name;
project(":$it.parentFile.name").projectDir = it.parentFile;
}

View File

@ -1,17 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: Public Domain
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
/**************************************************************************** /****************************************************************************
* Establish Visual Studio configuration environment for Windows native builds * Establish Visual Studio configuration environment for Windows native builds

View File

@ -20,6 +20,7 @@ apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
apply from: "$rootProject.projectDir/gradle/helpProject.gradle" apply from: "$rootProject.projectDir/gradle/helpProject.gradle"
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
apply from: "$rootProject.projectDir/gradle/javadoc.gradle" apply from: "$rootProject.projectDir/gradle/javadoc.gradle"
apply from: "buildNatives.gradle"
apply plugin: 'eclipse' apply plugin: 'eclipse'
@ -35,6 +36,14 @@ dependencies {
helpPath project(path: ":Base", configuration: 'helpPath') helpPath project(path: ":Base", configuration: 'helpPath')
} }
// Include buildable native source in distribution
rootProject.assembleDistribution {
from (this.project.projectDir.toString()) {
include "src/decompile/**"
into { getZipPath(this.project) }
}
}
ext.cppSourceDir = "src/decompile/cpp" ext.cppSourceDir = "src/decompile/cpp"
/** /**
@ -371,215 +380,6 @@ task buildDecompilerDocumentationHtml(type: Exec) {
} }
} }
/**
* 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 "win_x86_64"
targetPlatform "linux_x86_64"
targetPlatform "linux_arm_64"
targetPlatform "mac_x86_64"
targetPlatform "mac_arm_64"
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 "win_x86_64"
targetPlatform "linux_x86_64"
targetPlatform "linux_arm_64"
targetPlatform "mac_x86_64"
targetPlatform "mac_arm_64"
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 "-std=c++11"
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 == "win_x86_64") {
b.cppCompiler.define "WIN64"
b.cppCompiler.define "_WIN64"
}
}
}
else if (b.toolChain in Clang) {
b.cppCompiler.args "-std=c++11"
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 // Perform simple dependency change detection for generated files
// produced by bison or flex. A 5-second tolerance is used // produced by bison or flex. A 5-second tolerance is used

View File

@ -0,0 +1,233 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Native build files are already applied in development mode (indicated by presence of the
// Generic project). Only need to apply them if we are in a distribution.
if (findProject(':Generic') == null) {
apply from: "../../../GPL/utils.gradle"
apply from: "../../../GPL/nativePlatforms.gradle"
apply from: "../../../GPL/nativeBuildProperties.gradle"
}
/**
* 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 "win_x86_64"
targetPlatform "linux_x86_64"
targetPlatform "linux_arm_64"
targetPlatform "mac_x86_64"
targetPlatform "mac_arm_64"
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 "win_x86_64"
targetPlatform "linux_x86_64"
targetPlatform "linux_arm_64"
targetPlatform "mac_x86_64"
targetPlatform "mac_arm_64"
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 "-std=c++11"
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 == "win_x86_64") {
b.cppCompiler.define "WIN64"
b.cppCompiler.define "_WIN64"
}
}
}
else if (b.toolChain in Clang) {
b.cppCompiler.args "-std=c++11"
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

View File

@ -19,6 +19,7 @@ apply from: "$rootProject.projectDir/gradle/helpProject.gradle"
apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle" apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
apply from: "buildNatives.gradle"
apply plugin: 'eclipse' apply plugin: 'eclipse'
eclipse.project.name = 'Features PDB' eclipse.project.name = 'Features PDB'
@ -40,55 +41,10 @@ dependencies {
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts') testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
} }
/** // Include buildable native source in distribution
* Include PDB native source with sample Visual Studio project to allow users to
* rebuild against other versions.
*
* Note that we use 'this.project' to reference the PDB project - this is because
* inside the closure, 'project' refers to the root project, while 'this' refers to
* PDB.
*/
rootProject.assembleDistribution { rootProject.assembleDistribution {
into (getZipPath(this.project) + "/src/pdb") { from (this.project.projectDir.toString()) {
from projectDir.toString() + "/src/pdb" include "src/pdb/**"
into { getZipPath(this.project) }
} }
} }
if ("win_x86_64".equals(getCurrentPlatformName())) {
String makeName = "win_x86_64PDBMake"
task(type: Exec, makeName) {
def projectPath = projectDir.toString()
def solutionBatchFilePath = projectPath + "/build/buildSolution.bat"
def projectPathWindows = projectPath.replace("/", File.separator)
def solutionPathWindows = "\"${projectPathWindows}\\src\\pdb\\pdb.sln\""
doFirst {
file("build/os/win_x86_64").mkdirs()
def platformToolset = 'v' + VISUAL_STUDIO_TOOLS_VERSION_DEFAULT.substring(0, 4).replace('.', '');
def windowsTargetPlatformVersion = VISUAL_STUDIO_SDK_VERSION_OVERRIDE ?: VISUAL_STUDIO_SDK_VERSION_DEFAULT
def msbuildCmd = "msbuild ${solutionPathWindows} /p:Configuration=Release /p:PlatformToolset=${platformToolset} /p:WindowsTargetPlatformVersion=${windowsTargetPlatformVersion}"
println "Executing: " + msbuildCmd
new File(solutionBatchFilePath).withWriter { out ->
out.println "call " + VISUAL_STUDIO_VCVARS_CMD
out.println msbuildCmd
}
}
doLast {
assert file("build/os/win_x86_64/pdb.exe").exists() : "Failed to build pdb.exe"
}
executable "cmd"
args "/c"
args solutionBatchFilePath.replace("/", File.separator)
}
}

View File

@ -0,0 +1,59 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Native build files are already applied in development mode (indicated by presence of the
// Generic project). Only need to apply them if we are in a distribution.
if (findProject(':Generic') == null) {
apply from: "../../../GPL/utils.gradle"
apply from: "../../../GPL/nativePlatforms.gradle"
apply from: "../../../GPL/nativeBuildProperties.gradle"
}
if ("win_x86_64".equals(getCurrentPlatformName())) {
String makeName = "win_x86_64PDBMake"
task(type: Exec, makeName) {
def projectPath = projectDir.toString()
def solutionBatchFilePath = projectPath + "/build/buildSolution.bat"
def projectPathWindows = projectPath.replace("/", File.separator)
def solutionPathWindows = "\"${projectPathWindows}\\src\\pdb\\pdb.sln\""
doFirst {
file("build/os/win_x86_64").mkdirs()
def platformToolset = 'v' + VISUAL_STUDIO_TOOLS_VERSION_DEFAULT.substring(0, 4).replace('.', '');
def windowsTargetPlatformVersion = VISUAL_STUDIO_SDK_VERSION_OVERRIDE ?: VISUAL_STUDIO_SDK_VERSION_DEFAULT
def msbuildCmd = "msbuild ${solutionPathWindows} /p:Configuration=Release /p:PlatformToolset=${platformToolset} /p:WindowsTargetPlatformVersion=${windowsTargetPlatformVersion}"
println "Executing: " + msbuildCmd
new File(solutionBatchFilePath).withWriter { out ->
out.println "call " + VISUAL_STUDIO_VCVARS_CMD
out.println msbuildCmd
}
}
doLast {
assert file("build/os/win_x86_64/pdb.exe").exists() : "Failed to build pdb.exe"
}
executable "cmd"
args "/c"
args solutionBatchFilePath.replace("/", File.separator)
}
}

View File

@ -73,12 +73,6 @@
<PostBuildEvent> <PostBuildEvent>
<Command> <Command>
rem copy /y /v /b "$(VSInstallDir)DIA SDK\bin\amd64\msdia*.dll" "$(OutDir)" rem copy /y /v /b "$(VSInstallDir)DIA SDK\bin\amd64\msdia*.dll" "$(OutDir)"
set OS_DIR=$(SolutionDir)..\..\os
if exist "%OS_DIR%\win_x86_64" (
mkdir "%OS_DIR%"
mkdir "%OS_DIR%\win_x86_64"
xcopy /Y /S "$(OutDir)" "%OS_DIR%"
)
</Command> </Command>
</PostBuildEvent> </PostBuildEvent>
<PreLinkEvent> <PreLinkEvent>
@ -106,12 +100,6 @@ if exist "%OS_DIR%\win_x86_64" (
<PostBuildEvent> <PostBuildEvent>
<Command> <Command>
rem copy /y /v /b "$(VSInstallDir)DIA SDK\bin\amd64\msdia*.dll" "$(OutDir)" rem copy /y /v /b "$(VSInstallDir)DIA SDK\bin\amd64\msdia*.dll" "$(OutDir)"
set OS_DIR=$(SolutionDir)..\..\os
if exist "%OS_DIR%\win_x86_64" (
mkdir "%OS_DIR%"
mkdir "%OS_DIR%\win_x86_64"
xcopy /Y /S "$(OutDir)" "%OS_DIR%"
)
</Command> </Command>
</PostBuildEvent> </PostBuildEvent>
<PreLinkEvent> <PreLinkEvent>

View File

@ -470,7 +470,7 @@ public class Application {
exactFilename); exactFilename);
} }
// Allow win32 to be used for win64 as fallback // Allow win_x86_32 to be used for win_x86_64 as fallback
if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_X86_64) { if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_X86_64) {
file = getModuleFile(module, "build/os/" + Platform.WIN_X86_32.getDirectoryName(), file = getModuleFile(module, "build/os/" + Platform.WIN_X86_32.getDirectoryName(),
exactFilename); exactFilename);
@ -479,6 +479,16 @@ public class Application {
file = getModuleFile(module, "os/" + Platform.WIN_X86_32.getDirectoryName(), file = getModuleFile(module, "os/" + Platform.WIN_X86_32.getDirectoryName(),
exactFilename); exactFilename);
} }
// Allow mac_x86_64 to be used for mac_arm_64 as fallback (requires macOS Rosetta 2)
if (file == null && Platform.CURRENT_PLATFORM == Platform.MAC_ARM_64) {
file = getModuleFile(module, "build/os/" + Platform.MAC_X86_64.getDirectoryName(),
exactFilename);
}
if (file == null && Platform.CURRENT_PLATFORM == Platform.MAC_ARM_64) {
file = getModuleFile(module, "os/" + Platform.MAC_X86_64.getDirectoryName(),
exactFilename);
}
if (file == null) { if (file == null) {
throw new OSFileNotFoundException(moduleName, exactFilename); throw new OSFileNotFoundException(moduleName, exactFilename);
@ -506,13 +516,21 @@ public class Application {
file = findModuleFile("os/" + Platform.CURRENT_PLATFORM.getDirectoryName(), path); file = findModuleFile("os/" + Platform.CURRENT_PLATFORM.getDirectoryName(), path);
} }
// Allow win32 to be used for win64 as fallback // Allow win_x86_32 to be used for win_x86_64 as fallback
if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_X86_64) { if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_X86_64) {
file = findModuleFile("build/os/" + Platform.WIN_X86_32.getDirectoryName(), path); file = findModuleFile("build/os/" + Platform.WIN_X86_32.getDirectoryName(), path);
} }
if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_X86_64) { if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_X86_64) {
file = findModuleFile("os/" + Platform.WIN_X86_32.getDirectoryName(), path); file = findModuleFile("os/" + Platform.WIN_X86_32.getDirectoryName(), path);
} }
// Allow mac_x86_64 to be used for mac_arm_64 as fallback (requires macOS Rosetta 2)
if (file == null && Platform.CURRENT_PLATFORM == Platform.MAC_ARM_64) {
file = findModuleFile("build/os/" + Platform.MAC_X86_64.getDirectoryName(), path);
}
if (file == null && Platform.CURRENT_PLATFORM == Platform.MAC_ARM_64) {
file = findModuleFile("os/" + Platform.MAC_X86_64.getDirectoryName(), path);
}
if (file == null) { if (file == null) {
throw new OSFileNotFoundException(path); throw new OSFileNotFoundException(path);

View File

@ -0,0 +1,41 @@
#!/usr/bin/env bash
#----------------------------------------
# Build Native Binaries
#
# args: forwarded to gradle (-i, -s, etc)
#----------------------------------------
# Make sure gradle is on the path
if ! [ -x "$(command -v gradle)" ] ; then
echo "Gradle not found on the PATH."
exit 1
fi
# Resolve symbolic link if present and get the directory this script lives in.
# NOTE: "readlink -f" is best but works on Linux only, "readlink" will only work if your PWD
# contains the link you are calling (which is the best we can do on macOS), and the "echo" is the
# fallback, which doesn't attempt to do anything with links.
SCRIPT_FILE="$(readlink -f "$0" 2>/dev/null || readlink "$0" 2>/dev/null || echo "$0")"
SCRIPT_DIR="${SCRIPT_FILE%/*}"
buildGhidraNatives () {
echo "Building natives in Ghidra..."
pushd ${SCRIPT_DIR}/../Ghidra &>/dev/null
gradle "$@" buildNatives
result=$?
popd &>/dev/null
return $result
}
buildGplNatives () {
echo "Building natives in GPL..."
pushd ${SCRIPT_DIR}/../GPL &>/dev/null
gradle "$@" buildNatives
result=$?
popd &>/dev/null
return $result
}
buildGhidraNatives "$@" && buildGplNatives "$@"

View File

@ -0,0 +1,39 @@
:: Build Native Binaries
::
:: args: forwarded to gradle (-i, -s, etc)
@echo off
:: See if we were doubled clicked or run from a command prompt
set DOUBLE_CLICKED=n
for /f "tokens=2" %%# in ("%cmdcmdline%") do if /i "%%#" equ "/c" set DOUBLE_CLICKED=y
:: Make sure gradle is on the path
call gradle -h >nul 2>nul
if not %ERRORLEVEL% == 0 (
echo Gradle not found on the PATH
goto exit
)
echo Building natives in Ghidra...
pushd "%~dp0..\Ghidra"
call gradle %* buildNatives
popd
if not %ERRORLEVEL% == 0 (
goto exit
)
echo Building natives in GPL...
pushd "%~dp0..\GPL"
call gradle %* buildNatives
popd
if not %ERRORLEVEL% == 0 (
goto exit
)
:exit
if "%DOUBLE_CLICKED%"=="y" (
pause
)
exit /B %ERRORLEVEL%

View File

@ -14,6 +14,7 @@ Linux/server/svrInstall||GHIDRA||||END|
Linux/server/svrUninstall||GHIDRA||||END| Linux/server/svrUninstall||GHIDRA||||END|
Linux/support/analyzeHeadless||GHIDRA||||END| Linux/support/analyzeHeadless||GHIDRA||||END|
Linux/support/buildGhidraJar||GHIDRA||||END| Linux/support/buildGhidraJar||GHIDRA||||END|
Linux/support/buildNatives||GHIDRA||||END|
Linux/support/convertStorage||GHIDRA||||END| Linux/support/convertStorage||GHIDRA||||END|
Linux/support/ghidraDebug||GHIDRA||||END| Linux/support/ghidraDebug||GHIDRA||||END|
Linux/support/pythonRun||GHIDRA||||END| Linux/support/pythonRun||GHIDRA||||END|
@ -26,6 +27,7 @@ Windows/server/svrUninstall.bat||GHIDRA||||END|
Windows/support/README_createPdbXmlFiles.txt||GHIDRA||||END| Windows/support/README_createPdbXmlFiles.txt||GHIDRA||||END|
Windows/support/analyzeHeadless.bat||GHIDRA||||END| Windows/support/analyzeHeadless.bat||GHIDRA||||END|
Windows/support/buildGhidraJar.bat||GHIDRA||||END| Windows/support/buildGhidraJar.bat||GHIDRA||||END|
Windows/support/buildNatives.bat||GHIDRA||||END|
Windows/support/convertStorage.bat||GHIDRA||||END| Windows/support/convertStorage.bat||GHIDRA||||END|
Windows/support/createPdbXmlFiles.bat||GHIDRA||||END| Windows/support/createPdbXmlFiles.bat||GHIDRA||||END|
Windows/support/ghidra.ico||GHIDRA||||END| Windows/support/ghidra.ico||GHIDRA||||END|

View File

@ -31,6 +31,7 @@ future releases.
<li><a href="#JavaNotes">Java Notes</a></li> <li><a href="#JavaNotes">Java Notes</a></li>
</ul> </ul>
<li><a href="#Layout">Ghidra Installation Directory Layout</a></li> <li><a href="#Layout">Ghidra Installation Directory Layout</a></li>
<li><a href="#Build">Building Ghidra Native Components</a></li>
<li><a href="#Run">Running Ghidra</a></li> <li><a href="#Run">Running Ghidra</a></li>
<ul> <ul>
<li><a href="#RunGUI">GUI Mode</a></li> <li><a href="#RunGUI">GUI Mode</a></li>
@ -298,6 +299,39 @@ is complete.</p>
</table> </table>
<p>(<a href="#top">Back to Top</a>)</p> <p>(<a href="#top">Back to Top</a>)</p>
<h2><a name="Build"></a>Building Ghidra Native Components</h2>
<p>Ghidra requires several native binaries to be present in order to successfully run. An official
Ghidra release includes native binaries for the following platforms:</p>
<ul>
<li>Windows x86 64-bit</li>
<li>Linux x86 64-bit</li>
<li>macOS x86 64-bit</li>
<li>macOS ARM 64-bit (x86 using Rosetta translation)</li>
</ul>
<p>Ghidra supports running on the following additional platforms with user-built native binaries:
</p>
<ul>
<li>Linux ARM 64-bit</li>
<li>macOS ARM 64-bit (Apple silicon)</li>
</ul>
<p>In order to build native binaries for your platform, you will need the following installed on your
system:</p>
<ul>
<li>A <a href="#Requirements">supported</a> version of a Java Development Kit</li>
<li><a href="https://gradle.org/releases/">Gradle 6 or 7</a></li>
<li>make, gcc, and g++ (Linux/macOS-only)</li>
<li>
<a href="https://visualstudio.microsoft.com/vs/community/">Microsoft Visual Studio</a>
2017 or later (Windows-only)
</li>
</ul>
<p>To build the native binaries for your current platform, execute the following script:</p>
<pre><blockquote><i>&lt;GhidraInstallDir&gt;</i>/support/buildNatives(.bat)</i></blockquote></pre>
<p>When this script successfully completes, Ghidra will contain newly built native binaries in
the relevant modules' <i>build/os/&lt;platform&gt;/</i> subdirectories, which will override any
existing pre-built native binaries in the <i>os/&lt;platform&gt;/</i> subdirectories.</p>
<p>(<a href="#top">Back to Top</a>)</p>
<h2><a name="Run"></a>Running Ghidra</h2> <h2><a name="Run"></a>Running Ghidra</h2>
<h3><a name="RunGUI"></a>GUI Mode</h3> <h3><a name="RunGUI"></a>GUI Mode</h3>
<ol> <ol>

View File

@ -79,13 +79,10 @@ development process has been highly customized for.
* Follow the above build instructions so the build completes without errors * Follow the above build instructions so the build completes without errors
* Install [Eclipse IDE for Java Developers][eclipse] * Install [Eclipse IDE for Java Developers][eclipse]
##### Prepare the development environment (Linux/x86-only, see **NOTE** for other platforms): ##### Prepare the development environment:
``` ```
$ gradle prepdev eclipse buildNatives_linux_x86_64 $ gradle prepdev eclipse buildNatives
``` ```
**NOTE:** If you are on a different platform, change `buildNatives_linux_x86_64` to the gradle task
that is appropriate for your platform: `buildNatives_win_x86_64`, `buildNatives_mac_x86_64`,
`buildNatives_mac_arm_64`, or `buildNatives_linux_arm_64`
##### Import Ghidra projects into Eclipse: ##### Import Ghidra projects into Eclipse:
* *File* -> *Import...* * *File* -> *Import...*
@ -114,4 +111,4 @@ source project.
[gradle]: https://gradle.org/releases/ [gradle]: https://gradle.org/releases/
[vs]: https://visualstudio.microsoft.com/vs/community/ [vs]: https://visualstudio.microsoft.com/vs/community/
[eclipse]: https://www.eclipse.org/downloads/packages/ [eclipse]: https://www.eclipse.org/downloads/packages/
[master]: https://github.com/NationalSecurityAgency/ghidra/archive/refs/heads/master.zip [master]: https://github.com/NationalSecurityAgency/ghidra/archive/refs/heads/master.zip

View File

@ -19,10 +19,28 @@
A gradle project can add native code support by including the following it its build.gradle file: A gradle project can add native code support by including the following it its build.gradle file:
apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
*****************************************************************************************/ *****************************************************************************************/
// These same settings are needed in the GPL native, so rather than duplicating this file, we will just call the other file // These same settings are needed in the GPL native, so rather than duplicating this file, we will just call the other file
def projectRootDir = rootProject.projectDir.path def projectRootDir = rootProject.projectDir.path
apply from: "$projectRootDir/GPL/nativeBuildProperties.gradle" apply from: "$projectRootDir/GPL/nativeBuildProperties.gradle"
// Include and rename native projects' buildNative.gradle files to build.gradle in the distribution
// so a user can build or rebuild natives for their specific platform.
// NOTE: GPL projects' build.gradle files are already written to build their natives from a release,
// so we can just include their build.gradle as as-is.
rootProject.assembleDistribution {
def p = this.project
from (p.projectDir.toString()) {
if (p.projectDir.parentFile.name == "GPL") {
include "build.gradle"
}
else {
include "buildNatives.gradle"
rename "buildNatives.gradle", "build.gradle"
}
into { getZipPath(p) }
}
}

View File

@ -352,6 +352,15 @@ task assembleDistribution (type: Copy) {
from (ROOT_PROJECT_DIR + "/GhidraBuild/patch") { from (ROOT_PROJECT_DIR + "/GhidraBuild/patch") {
into "Ghidra/patch" into "Ghidra/patch"
} }
/////////////////////////////////
// Distro native build support
/////////////////////////////////
from (ROOT_PROJECT_DIR + "/GPL") {
include "settings.gradle"
into "Ghidra"
}
} }
/********************************************************************************* /*********************************************************************************

View File

@ -34,18 +34,18 @@ Primary gradle tasks for Ghidra
usage Displays this text [root/usage.gradle] usage Displays this text [root/usage.gradle]
prepDev Prepares development environment [root/prepDev.gradle] prepDev Prepares development environment [root/prepDev.gradle]
eclipse Create eclipse projects [root/eclipse.gradle]
buildHelp Builds help [root/buildHelp.gradle] buildHelp Builds help [root/buildHelp.gradle]
buildGhidra Builds Ghidra for the current platform [root/distribution.gradle] buildGhidra Builds Ghidra for the current platform [root/distribution.gradle]
buildGhidra -PallPlatforms Builds Ghidra for all platforms (assumes natives [root/distribution.gradle] buildGhidra -PallPlatforms Builds Ghidra for all platforms (assumes natives [root/distribution.gradle]
for other platforms are already built into for other platforms are already built into
appropriate os dirs) appropriate os dirs)
Task rules: Task rules:
buildNatives_[platform] builds the native executables and libraries for the buildNatives[_platform] Builds the native executables and libraries for the [GPL/nativeBuildProperties.gradle]
specified platform (win_x86_64, linux_arm_64, mac_x86_64, etc.) [nativeProject.gradle] current or specified platform (win_x86_64,
prebuildNatives_[platform] builds the native executables and libraries for the linux_arm_64, mac_x86_64, etc.)
specified platform and copies results to bin repo. [nativeProject.gradle]
""" """
} }
} }

View File

@ -126,6 +126,7 @@ def Map<String, List<String>> getIpForModule(Project p) {
exclude ".classpath" exclude ".classpath"
exclude "Module.manifest" exclude "Module.manifest"
exclude "build.gradle" exclude "build.gradle"
exclude "buildNatives.gradle"
exclude "**/Misc/Tips.htm" exclude "**/Misc/Tips.htm"
exclude "**/*.sla" exclude "**/*.sla"
exclude "**/.gradle/**" exclude "**/.gradle/**"

View File

@ -41,6 +41,7 @@ includeProject('GhidraTest', '.', true)
includeProject('decompile', 'Ghidra/Features/Decompiler/src', true) includeProject('decompile', 'Ghidra/Features/Decompiler/src', true)
includeProject('RuntimeScripts', 'Ghidra', true) includeProject('RuntimeScripts', 'Ghidra', true)
includeProject('IDAPro', 'GhidraBuild', true) includeProject('IDAPro', 'GhidraBuild', true)
includeProject('NativeSupport', 'GhidraBuild', true)
includeProject('GhidraDocs', '.', true) includeProject('GhidraDocs', '.', true)
includeProjects('GhidraBuild/EclipsePlugins/GhidraDev') // requires Eclipse PDE includeProjects('GhidraBuild/EclipsePlugins/GhidraDev') // requires Eclipse PDE
includeProjects('GhidraBuild/EclipsePlugins/GhidraSleighEditor') // requires Eclipse DSL includeProjects('GhidraBuild/EclipsePlugins/GhidraSleighEditor') // requires Eclipse DSL