From 3c07ca2962bc1ae74294b6a3d01d1390f68951fd Mon Sep 17 00:00:00 2001
From: Ryan Kurtz
Date: Mon, 27 Sep 2021 08:16:14 -0400
Subject: [PATCH] GP-1209: Support for building natives from a release.
---
DevGuide.md | 23 +-
GPL/DMG/settings.gradle | 3 -
GPL/DemanglerGnu/settings.gradle | 3 -
GPL/nativeBuildProperties.gradle | 63 +++--
GPL/settings.gradle | 12 +
GPL/vsconfig.gradle | 14 +-
Ghidra/Features/Decompiler/build.gradle | 218 +---------------
.../Features/Decompiler/buildNatives.gradle | 233 ++++++++++++++++++
Ghidra/Features/PDB/build.gradle | 54 +---
Ghidra/Features/PDB/buildNatives.gradle | 59 +++++
Ghidra/Features/PDB/src/pdb/pdb.vcxproj | 12 -
.../java/ghidra/framework/Application.java | 22 +-
.../RuntimeScripts/Linux/support/buildNatives | 41 +++
.../Windows/support/buildNatives.bat | 39 +++
Ghidra/RuntimeScripts/certification.manifest | 2 +
GhidraDocs/InstallationGuide.html | 34 +++
README.md | 9 +-
gradle/nativeProject.gradle | 20 +-
gradle/root/distribution.gradle | 9 +
gradle/root/usage.gradle | 18 +-
gradle/support/ip.gradle | 1 +
settings.gradle | 1 +
22 files changed, 541 insertions(+), 349 deletions(-)
delete mode 100644 GPL/DMG/settings.gradle
delete mode 100644 GPL/DemanglerGnu/settings.gradle
create mode 100644 GPL/settings.gradle
create mode 100644 Ghidra/Features/Decompiler/buildNatives.gradle
create mode 100644 Ghidra/Features/PDB/buildNatives.gradle
create mode 100755 Ghidra/RuntimeScripts/Linux/support/buildNatives
create mode 100644 Ghidra/RuntimeScripts/Windows/support/buildNatives.bat
diff --git a/DevGuide.md b/DevGuide.md
index 95573732a0..5bcb127e95 100644
--- a/DevGuide.md
+++ b/DevGuide.md
@@ -262,33 +262,16 @@ You may see build path errors until the environment is properly prepared, as des
### Building the natives
Some of Ghidra's components are built for the native platform.
-We currently support Linux, macOS, and Windows 64-bit x86 systems.
-Others should be possible, but we do not test on them.
+We currently support 64-bit Linux x86/ARM, macOS x86/ARM, and Windows x86.
-Now build using Gradle:
-
-On Linux:
+Build the natives for your current platform using Gradle:
```bash
-gradle buildNatives_linux_x86_64
-```
-
-On macOS:
-
-```bash
-gradle buildNatives_mac_x86_64
-```
-
-On Windows:
-
-```bash
-gradle buildNatives_win_x86_64
+gradle buildNatives
```
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)
Optionally, to pre-compile all the language modules, you may also execute:
diff --git a/GPL/DMG/settings.gradle b/GPL/DMG/settings.gradle
deleted file mode 100644
index 1092a7aaab..0000000000
--- a/GPL/DMG/settings.gradle
+++ /dev/null
@@ -1,3 +0,0 @@
-/* ###
- * IP: Public Domain
- */
diff --git a/GPL/DemanglerGnu/settings.gradle b/GPL/DemanglerGnu/settings.gradle
deleted file mode 100644
index 1092a7aaab..0000000000
--- a/GPL/DemanglerGnu/settings.gradle
+++ /dev/null
@@ -1,3 +0,0 @@
-/* ###
- * IP: Public Domain
- */
diff --git a/GPL/nativeBuildProperties.gradle b/GPL/nativeBuildProperties.gradle
index 494e2be7f8..1b2d4feb82 100644
--- a/GPL/nativeBuildProperties.gradle
+++ b/GPL/nativeBuildProperties.gradle
@@ -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_]: 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_")) {
- String platform = taskName - "buildNatives_"
+ if (taskName.startsWith("buildNatives")) {
+ String currentPlatform = getCurrentPlatformName()
+ String platform = taskName - "buildNatives"
+ if (platform.length() == 0) {
+ platform = currentPlatform
+ }
+ if (platform.startsWith("_")) {
+ platform = platform - "_"
+ }
task(taskName) { myTask ->
@@ -157,20 +167,30 @@ tasks.addRule("Pattern: buildNatives_]: build all natives for giv
}
}
-/*******************************************************************************************
- * Task Rule : builds all the natives in this module for a given platform and copies the
- * results to the bin repo.
+ /*******************************************************************************************
+ * Task Rule : prebuildNatives[_PlatformName]
*
- * 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.
+ * Summary: Builds all the natives in this module for a given platform and copies the results
+ * to the bin repo.
*
+ * 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_]: build all natives for given platform") { String taskName ->
- if (taskName.startsWith("prebuildNatives_")) {
- String platform = taskName - "prebuildNatives_"
+tasks.addRule("Pattern: prebuildNatives<_platform name>]: build all natives for given platform") { String taskName ->
+ if (taskName.startsWith("prebuildNatives")) {
+ def currentPlatform = getCurrentPlatformName()
+ def platform = taskName - "prebuildNatives"
+ if (platform.length() == 0) {
+ platform = currentPlatform
+ }
+ if (platform.startsWith("_")) {
+ platform = platform - "_"
+ }
task(taskName) { myTask ->
dependsOn "buildNatives_$platform"
@@ -214,8 +234,7 @@ gradle.taskGraph.whenReady {
}
/*****************************************************************************************
- * The following block of code ensures that the buildNatives_ task is used
- * during assembly to ensure that missing toolchain generates an appropriate error
+ * The following block of code ensures that the buildNatives (for current plaform) task is
+ * used during assembly to ensure that missing toolchain generates an appropriate error
****************************************************************************************/
-def currentPlatform = getCurrentPlatformName()
-assemble.dependsOn "buildNatives_$currentPlatform"
+assemble.dependsOn "buildNatives"
diff --git a/GPL/settings.gradle b/GPL/settings.gradle
new file mode 100644
index 0000000000..2f7a52d862
--- /dev/null
+++ b/GPL/settings.gradle
@@ -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;
+}
diff --git a/GPL/vsconfig.gradle b/GPL/vsconfig.gradle
index a21190cb0b..915b90ea90 100644
--- a/GPL/vsconfig.gradle
+++ b/GPL/vsconfig.gradle
@@ -1,17 +1,5 @@
/* ###
- * 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.
+ * IP: Public Domain
*/
/****************************************************************************
* Establish Visual Studio configuration environment for Windows native builds
diff --git a/Ghidra/Features/Decompiler/build.gradle b/Ghidra/Features/Decompiler/build.gradle
index e5f9069112..f95278172b 100644
--- a/Ghidra/Features/Decompiler/build.gradle
+++ b/Ghidra/Features/Decompiler/build.gradle
@@ -20,6 +20,7 @@ apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
apply from: "$rootProject.projectDir/gradle/helpProject.gradle"
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
apply from: "$rootProject.projectDir/gradle/javadoc.gradle"
+apply from: "buildNatives.gradle"
apply plugin: 'eclipse'
@@ -35,6 +36,14 @@ dependencies {
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"
/**
@@ -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
// produced by bison or flex. A 5-second tolerance is used
diff --git a/Ghidra/Features/Decompiler/buildNatives.gradle b/Ghidra/Features/Decompiler/buildNatives.gradle
new file mode 100644
index 0000000000..a05736f686
--- /dev/null
+++ b/Ghidra/Features/Decompiler/buildNatives.gradle
@@ -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
diff --git a/Ghidra/Features/PDB/build.gradle b/Ghidra/Features/PDB/build.gradle
index 43fe526337..beea3a7c24 100644
--- a/Ghidra/Features/PDB/build.gradle
+++ b/Ghidra/Features/PDB/build.gradle
@@ -19,6 +19,7 @@ apply from: "$rootProject.projectDir/gradle/helpProject.gradle"
apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
+apply from: "buildNatives.gradle"
apply plugin: 'eclipse'
eclipse.project.name = 'Features PDB'
@@ -40,55 +41,10 @@ dependencies {
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
}
-/**
- * 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.
- */
+// Include buildable native source in distribution
rootProject.assembleDistribution {
- into (getZipPath(this.project) + "/src/pdb") {
- from projectDir.toString() + "/src/pdb"
+ from (this.project.projectDir.toString()) {
+ 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)
- }
-
-
-
-}
diff --git a/Ghidra/Features/PDB/buildNatives.gradle b/Ghidra/Features/PDB/buildNatives.gradle
new file mode 100644
index 0000000000..a29e190008
--- /dev/null
+++ b/Ghidra/Features/PDB/buildNatives.gradle
@@ -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)
+ }
+}
diff --git a/Ghidra/Features/PDB/src/pdb/pdb.vcxproj b/Ghidra/Features/PDB/src/pdb/pdb.vcxproj
index cf7d709341..f77ba5f770 100644
--- a/Ghidra/Features/PDB/src/pdb/pdb.vcxproj
+++ b/Ghidra/Features/PDB/src/pdb/pdb.vcxproj
@@ -73,12 +73,6 @@
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%"
-)
@@ -106,12 +100,6 @@ if exist "%OS_DIR%\win_x86_64" (
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%"
-)
diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/Application.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/Application.java
index 2b82f0f754..854a81b691 100644
--- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/Application.java
+++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/Application.java
@@ -470,7 +470,7 @@ public class Application {
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) {
file = getModuleFile(module, "build/os/" + Platform.WIN_X86_32.getDirectoryName(),
exactFilename);
@@ -479,6 +479,16 @@ public class Application {
file = getModuleFile(module, "os/" + Platform.WIN_X86_32.getDirectoryName(),
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) {
throw new OSFileNotFoundException(moduleName, exactFilename);
@@ -506,13 +516,21 @@ public class Application {
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) {
file = findModuleFile("build/os/" + Platform.WIN_X86_32.getDirectoryName(), path);
}
if (file == null && Platform.CURRENT_PLATFORM == Platform.WIN_X86_64) {
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) {
throw new OSFileNotFoundException(path);
diff --git a/Ghidra/RuntimeScripts/Linux/support/buildNatives b/Ghidra/RuntimeScripts/Linux/support/buildNatives
new file mode 100755
index 0000000000..76dafe9722
--- /dev/null
+++ b/Ghidra/RuntimeScripts/Linux/support/buildNatives
@@ -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 "$@"
+
diff --git a/Ghidra/RuntimeScripts/Windows/support/buildNatives.bat b/Ghidra/RuntimeScripts/Windows/support/buildNatives.bat
new file mode 100644
index 0000000000..5fae87b936
--- /dev/null
+++ b/Ghidra/RuntimeScripts/Windows/support/buildNatives.bat
@@ -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%
diff --git a/Ghidra/RuntimeScripts/certification.manifest b/Ghidra/RuntimeScripts/certification.manifest
index c01853669d..cfc9b7e8c7 100644
--- a/Ghidra/RuntimeScripts/certification.manifest
+++ b/Ghidra/RuntimeScripts/certification.manifest
@@ -14,6 +14,7 @@ Linux/server/svrInstall||GHIDRA||||END|
Linux/server/svrUninstall||GHIDRA||||END|
Linux/support/analyzeHeadless||GHIDRA||||END|
Linux/support/buildGhidraJar||GHIDRA||||END|
+Linux/support/buildNatives||GHIDRA||||END|
Linux/support/convertStorage||GHIDRA||||END|
Linux/support/ghidraDebug||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/analyzeHeadless.bat||GHIDRA||||END|
Windows/support/buildGhidraJar.bat||GHIDRA||||END|
+Windows/support/buildNatives.bat||GHIDRA||||END|
Windows/support/convertStorage.bat||GHIDRA||||END|
Windows/support/createPdbXmlFiles.bat||GHIDRA||||END|
Windows/support/ghidra.ico||GHIDRA||||END|
diff --git a/GhidraDocs/InstallationGuide.html b/GhidraDocs/InstallationGuide.html
index 811fc7dfad..65219dd50b 100644
--- a/GhidraDocs/InstallationGuide.html
+++ b/GhidraDocs/InstallationGuide.html
@@ -31,6 +31,7 @@ future releases.
Java Notes
Ghidra Installation Directory Layout
+ Building Ghidra Native Components
Running Ghidra
- GUI Mode
@@ -298,6 +299,39 @@ is complete.
(Back to Top)
+Building Ghidra Native Components
+Ghidra requires several native binaries to be present in order to successfully run. An official
+Ghidra release includes native binaries for the following platforms:
+
+ - Windows x86 64-bit
+ - Linux x86 64-bit
+ - macOS x86 64-bit
+ - macOS ARM 64-bit (x86 using Rosetta translation)
+
+Ghidra supports running on the following additional platforms with user-built native binaries:
+
+
+ - Linux ARM 64-bit
+ - macOS ARM 64-bit (Apple silicon)
+
+In order to build native binaries for your platform, you will need the following installed on your
+system:
+
+To build the native binaries for your current platform, execute the following script:
+<GhidraInstallDir>/support/buildNatives(.bat)
+When this script successfully completes, Ghidra will contain newly built native binaries in
+the relevant modules' build/os/<platform>/ subdirectories, which will override any
+existing pre-built native binaries in the os/<platform>/ subdirectories.
+(Back to Top)
+
Running Ghidra
GUI Mode
diff --git a/README.md b/README.md
index 65153b66a9..6e1891729d 100644
--- a/README.md
+++ b/README.md
@@ -79,13 +79,10 @@ development process has been highly customized for.
* Follow the above build instructions so the build completes without errors
* 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:
* *File* -> *Import...*
@@ -114,4 +111,4 @@ source project.
[gradle]: https://gradle.org/releases/
[vs]: https://visualstudio.microsoft.com/vs/community/
[eclipse]: https://www.eclipse.org/downloads/packages/
-[master]: https://github.com/NationalSecurityAgency/ghidra/archive/refs/heads/master.zip
\ No newline at end of file
+[master]: https://github.com/NationalSecurityAgency/ghidra/archive/refs/heads/master.zip
diff --git a/gradle/nativeProject.gradle b/gradle/nativeProject.gradle
index fb2a369aa1..5e67309675 100644
--- a/gradle/nativeProject.gradle
+++ b/gradle/nativeProject.gradle
@@ -19,10 +19,28 @@
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
def projectRootDir = rootProject.projectDir.path
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) }
+ }
+}
diff --git a/gradle/root/distribution.gradle b/gradle/root/distribution.gradle
index a8f88b0f16..4e364bdc40 100644
--- a/gradle/root/distribution.gradle
+++ b/gradle/root/distribution.gradle
@@ -352,6 +352,15 @@ task assembleDistribution (type: Copy) {
from (ROOT_PROJECT_DIR + "/GhidraBuild/patch") {
into "Ghidra/patch"
}
+
+ /////////////////////////////////
+ // Distro native build support
+ /////////////////////////////////
+ from (ROOT_PROJECT_DIR + "/GPL") {
+ include "settings.gradle"
+ into "Ghidra"
+ }
+
}
/*********************************************************************************
diff --git a/gradle/root/usage.gradle b/gradle/root/usage.gradle
index 59fba64401..b82158a7dd 100644
--- a/gradle/root/usage.gradle
+++ b/gradle/root/usage.gradle
@@ -34,18 +34,18 @@ Primary gradle tasks for Ghidra
usage Displays this text [root/usage.gradle]
prepDev Prepares development environment [root/prepDev.gradle]
+ eclipse Create eclipse projects [root/eclipse.gradle]
buildHelp Builds help [root/buildHelp.gradle]
- buildGhidra Builds Ghidra for the current platform [root/distribution.gradle]
- buildGhidra -PallPlatforms Builds Ghidra for all platforms (assumes natives [root/distribution.gradle]
- for other platforms are already built into
- appropriate os dirs)
+ buildGhidra Builds Ghidra for the current platform [root/distribution.gradle]
+ buildGhidra -PallPlatforms Builds Ghidra for all platforms (assumes natives [root/distribution.gradle]
+ for other platforms are already built into
+ appropriate os dirs)
Task rules:
- buildNatives_[platform] builds the native executables and libraries for the
- specified platform (win_x86_64, linux_arm_64, mac_x86_64, etc.) [nativeProject.gradle]
- prebuildNatives_[platform] builds the native executables and libraries for the
- specified platform and copies results to bin repo. [nativeProject.gradle]
-
+ buildNatives[_platform] Builds the native executables and libraries for the [GPL/nativeBuildProperties.gradle]
+ current or specified platform (win_x86_64,
+ linux_arm_64, mac_x86_64, etc.)
+
"""
}
}
diff --git a/gradle/support/ip.gradle b/gradle/support/ip.gradle
index d8fc9f89d2..2b01fac95d 100644
--- a/gradle/support/ip.gradle
+++ b/gradle/support/ip.gradle
@@ -126,6 +126,7 @@ def Map> getIpForModule(Project p) {
exclude ".classpath"
exclude "Module.manifest"
exclude "build.gradle"
+ exclude "buildNatives.gradle"
exclude "**/Misc/Tips.htm"
exclude "**/*.sla"
exclude "**/.gradle/**"
diff --git a/settings.gradle b/settings.gradle
index 66751b3fc6..13335a393d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -41,6 +41,7 @@ includeProject('GhidraTest', '.', true)
includeProject('decompile', 'Ghidra/Features/Decompiler/src', true)
includeProject('RuntimeScripts', 'Ghidra', true)
includeProject('IDAPro', 'GhidraBuild', true)
+includeProject('NativeSupport', 'GhidraBuild', true)
includeProject('GhidraDocs', '.', true)
includeProjects('GhidraBuild/EclipsePlugins/GhidraDev') // requires Eclipse PDE
includeProjects('GhidraBuild/EclipsePlugins/GhidraSleighEditor') // requires Eclipse DSL