1+ plugins {
2+ id ' java'
3+ id ' application'
4+ }
5+
6+ // Extension properties
7+ ext. GHIDRA_INSTALL_DIR = findProperty(' GHIDRA_INSTALL_DIR' ) ?: System . env. GHIDRA_INSTALL_DIR ?: ' /path/to/ghidra'
8+
9+ // Java version compatibility
10+ java {
11+ sourceCompatibility = JavaVersion . VERSION_21
12+ targetCompatibility = JavaVersion . VERSION_21
13+ }
14+
15+ repositories {
16+ mavenCentral()
17+ }
18+
19+ configurations {
20+ ghidraRuntime
21+ }
22+
23+ dependencies {
24+ // External dependencies
25+ implementation ' org.reflections:reflections:0.10.2'
26+ implementation ' com.google.code.gson:gson:2.10.1'
27+
28+ // Ghidra dependencies (from lib directory)
29+ implementation fileTree(dir : ' lib' , include : ' *.jar' )
30+
31+ // Test dependencies
32+ testImplementation ' junit:junit:4.13.2'
33+ }
34+
35+ // Compile with specific settings
36+ compileJava {
37+ options. compilerArgs + = [' -Xlint:-options' ]
38+ options. encoding = ' UTF-8'
39+ }
40+
41+ // Create the main JAR
42+ jar {
43+ archiveBaseName = ' GhidraMCP'
44+ archiveVersion = ' 1.0-SNAPSHOT'
45+ archiveClassifier = ' '
46+
47+ from sourceSets. main. output
48+
49+ // Include only our compiled classes, not Ghidra JARs
50+ exclude ' **/App.class'
51+
52+ // Set manifest
53+ manifest {
54+ from ' src/main/resources/META-INF/MANIFEST.MF'
55+ }
56+ }
57+
58+ // Task to copy Ghidra JARs from installation
59+ task copyGhidraJars (type : Copy ) {
60+ from " ${ GHIDRA_INSTALL_DIR} /Ghidra/Framework/Generic/lib/Generic.jar"
61+ from " ${ GHIDRA_INSTALL_DIR} /Ghidra/Framework/SoftwareModeling/lib/SoftwareModeling.jar"
62+ from " ${ GHIDRA_INSTALL_DIR} /Ghidra/Framework/Project/lib/Project.jar"
63+ from " ${ GHIDRA_INSTALL_DIR} /Ghidra/Framework/Docking/lib/Docking.jar"
64+ from " ${ GHIDRA_INSTALL_DIR} /Ghidra/Framework/Utility/lib/Utility.jar"
65+ from " ${ GHIDRA_INSTALL_DIR} /Ghidra/Framework/Gui/lib/Gui.jar"
66+ from " ${ GHIDRA_INSTALL_DIR} /Ghidra/Features/Base/lib/Base.jar"
67+ from " ${ GHIDRA_INSTALL_DIR} /Ghidra/Features/Decompiler/lib/Decompiler.jar"
68+
69+ into ' lib'
70+
71+ doFirst {
72+ println " Copying Ghidra JARs from: ${ GHIDRA_INSTALL_DIR} "
73+ }
74+ }
75+
76+ // Task to create the extension zip
77+ task createExtension (type : Zip , dependsOn : jar) {
78+ archiveBaseName = ' GhidraMCP'
79+ archiveVersion = ' 1.0-SNAPSHOT'
80+ archiveClassifier = ' '
81+ destinationDirectory = file(' dist' )
82+
83+ from(' src/main/resources' ) {
84+ include ' extension.properties'
85+ include ' Module.manifest'
86+ }
87+
88+ from jar. archiveFile
89+ rename { ' lib/GhidraMCP.jar' }
90+
91+ // Include external dependencies but exclude Ghidra JARs
92+ from(configurations. runtimeClasspath) {
93+ into ' lib'
94+ exclude ' Generic-*.jar'
95+ exclude ' SoftwareModeling-*.jar'
96+ exclude ' Project-*.jar'
97+ exclude ' Docking-*.jar'
98+ exclude ' Utility-*.jar'
99+ exclude ' Gui-*.jar'
100+ exclude ' Base-*.jar'
101+ exclude ' Decompiler-*.jar'
102+ exclude ' *.jar' // Exclude all JARs from lib directory
103+ }
104+
105+ // Include only specific non-Ghidra dependencies
106+ from(configurations. runtimeClasspath. filter {
107+ it. name. contains(' reflections' ) || it. name. contains(' gson' )
108+ }) {
109+ into ' lib'
110+ }
111+ }
112+
113+ // Task to clean and build everything
114+ task buildExtension {
115+ dependsOn ' clean' , ' jar' , ' createExtension'
116+ description = ' Builds the complete Ghidra extension'
117+
118+ doLast {
119+ println " "
120+ println " Extension built successfully!"
121+ println " Output: ${ file('dist/GhidraMCP-1.0-SNAPSHOT.zip').absolutePath} "
122+ println " "
123+ println " To install:"
124+ println " 1. Open Ghidra"
125+ println " 2. File -> Install Extensions"
126+ println " 3. Click '+' and select the zip file"
127+ println " 4. Restart Ghidra"
128+ }
129+ }
130+
131+ // Helper task to check if Ghidra JARs exist
132+ task checkGhidraJars {
133+ doLast {
134+ def requiredJars = [
135+ ' Generic.jar' , ' SoftwareModeling.jar' , ' Project.jar' , ' Docking.jar' ,
136+ ' Utility.jar' , ' Gui.jar' , ' Base.jar' , ' Decompiler.jar'
137+ ]
138+
139+ def missingJars = []
140+ requiredJars. each { jar ->
141+ if (! file(" lib/${ jar} " ). exists()) {
142+ missingJars. add(jar)
143+ }
144+ }
145+
146+ if (missingJars. isEmpty()) {
147+ println " ✓ All required Ghidra JARs found in lib/ directory"
148+ } else {
149+ println " ✗ Missing Ghidra JARs in lib/ directory:"
150+ missingJars. each { jar -> println " - ${ jar} " }
151+ println " "
152+ println " Run: gradle copyGhidraJars -PGHIDRA_INSTALL_DIR=/path/to/ghidra"
153+ println " Or manually copy the JARs to lib/ directory"
154+ }
155+ }
156+ }
157+
158+ // Make jar depend on checking Ghidra JARs
159+ jar. dependsOn checkGhidraJars
0 commit comments