@@ -8,6 +8,178 @@ plugins {
8
8
id ' de.undercouch.download' version ' 4.1.1'
9
9
}
10
10
11
+ // Helper function to check if objcopy is available
12
+ def checkObjcopyAvailable () {
13
+ try {
14
+ def process = [' objcopy' , ' --version' ]. execute()
15
+ process. waitFor()
16
+ return process. exitValue() == 0
17
+ } catch (Exception e) {
18
+ return false
19
+ }
20
+ }
21
+
22
+ // Helper function to check if dsymutil is available (for macOS)
23
+ def checkDsymutilAvailable () {
24
+ try {
25
+ def process = [' dsymutil' , ' --version' ]. execute()
26
+ process. waitFor()
27
+ return process. exitValue() == 0
28
+ } catch (Exception e) {
29
+ return false
30
+ }
31
+ }
32
+
33
+ // Helper function to check if debug extraction should be skipped
34
+ def shouldSkipDebugExtraction () {
35
+ return project. hasProperty(' skip-debug-extraction' )
36
+ }
37
+
38
+ // Helper function to get debug file path for a given config
39
+ def getDebugFilePath (config ) {
40
+ def extension = os(). isLinux() ? ' so' : ' dylib'
41
+ return file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /debug/libjavaProfiler.${ extension} .debug" )
42
+ }
43
+
44
+ // Helper function to get stripped file path for a given config
45
+ def getStrippedFilePath (config ) {
46
+ def extension = os(). isLinux() ? ' so' : ' dylib'
47
+ return file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /stripped/libjavaProfiler.${ extension} " )
48
+ }
49
+
50
+ // Helper function to create error message for missing tools
51
+ def getMissingToolErrorMessage (toolName , installInstructions ) {
52
+ return """
53
+ |${ toolName} is not available but is required for split debug information.
54
+ |
55
+ |To fix this issue:
56
+ |${ installInstructions}
57
+ |
58
+ |If you want to build without split debug info, set -Pskip-debug-extraction=true
59
+ """ . stripMargin()
60
+ }
61
+
62
+ // Helper function to create debug extraction task
63
+ def createDebugExtractionTask (config , linkTask ) {
64
+ return tasks. register(' extractDebugLibRelease' , Exec ) {
65
+ onlyIf {
66
+ config. active && ! shouldSkipDebugExtraction()
67
+ }
68
+ dependsOn linkTask
69
+ description = ' Extract debug symbols from release library'
70
+ workingDir project. buildDir
71
+
72
+ doFirst {
73
+ def sourceFile = linkTask. get(). linkedFile. get(). asFile
74
+ def debugFile = getDebugFilePath(config)
75
+
76
+ // Check for required tools before proceeding
77
+ if (os(). isLinux()) {
78
+ if (! checkObjcopyAvailable()) {
79
+ def installInstructions = """
80
+ | - On Ubuntu/Debian: sudo apt-get install binutils
81
+ | - On RHEL/CentOS: sudo yum install binutils
82
+ | - On Alpine: apk add binutils""" . stripMargin()
83
+ throw new GradleException (getMissingToolErrorMessage(' objcopy' , installInstructions))
84
+ }
85
+ } else if (os(). isMacOsX()) {
86
+ if (! checkDsymutilAvailable()) {
87
+ def installInstructions = """
88
+ | dsymutil should be available with Xcode command line tools:
89
+ | xcode-select --install""" . stripMargin()
90
+ throw new GradleException (getMissingToolErrorMessage(' dsymutil' , installInstructions))
91
+ }
92
+ }
93
+
94
+ // Ensure debug directory exists
95
+ debugFile. parentFile. mkdirs()
96
+
97
+ // Set the command line based on platform
98
+ if (os(). isLinux()) {
99
+ commandLine = [' objcopy' , ' --only-keep-debug' , sourceFile. absolutePath, debugFile. absolutePath]
100
+ } else {
101
+ // For macOS, we'll use dsymutil instead
102
+ commandLine = [' dsymutil' , sourceFile. absolutePath, ' -o' , debugFile. absolutePath. replace(' .debug' , ' .dSYM' )]
103
+ }
104
+ }
105
+ }
106
+ }
107
+
108
+ // Helper function to create debug link task (Linux only)
109
+ def createDebugLinkTask (config , linkTask , extractDebugTask ) {
110
+ return tasks. register(' addDebugLinkLibRelease' , Exec ) {
111
+ onlyIf {
112
+ config. active && os(). isLinux() && ! shouldSkipDebugExtraction()
113
+ }
114
+ dependsOn extractDebugTask
115
+ description = ' Add debug link to the original library'
116
+
117
+ doFirst {
118
+ def sourceFile = linkTask. get(). linkedFile. get(). asFile
119
+ def debugFile = getDebugFilePath(config)
120
+
121
+ // Check for objcopy availability
122
+ if (! checkObjcopyAvailable()) {
123
+ def installInstructions = """
124
+ | - On Ubuntu/Debian: sudo apt-get install binutils
125
+ | - On RHEL/CentOS: sudo yum install binutils
126
+ | - On Alpine: apk add binutils""" . stripMargin()
127
+ throw new GradleException (getMissingToolErrorMessage(' objcopy' , installInstructions))
128
+ }
129
+
130
+ commandLine = [' objcopy' , ' --add-gnu-debuglink=' + debugFile. absolutePath, sourceFile. absolutePath]
131
+ }
132
+ }
133
+ }
134
+
135
+ // Helper function to create debug file copy task
136
+ def createDebugCopyTask (config , extractDebugTask ) {
137
+ return tasks. register(' copyReleaseDebugFiles' , Copy ) {
138
+ onlyIf {
139
+ ! shouldSkipDebugExtraction()
140
+ }
141
+ dependsOn extractDebugTask
142
+ from file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /debug" )
143
+ into file(libraryTargetPath(config. name + ' -debug' ))
144
+ include ' **/*.debug'
145
+ include ' **/*.dSYM/**'
146
+ }
147
+ }
148
+
149
+ // Main function to setup debug extraction for release builds
150
+ def setupDebugExtraction (config , linkTask ) {
151
+ if (config. name == ' release' ) {
152
+ // Create all debug-related tasks
153
+ def extractDebugTask = createDebugExtractionTask(config, linkTask)
154
+ def addDebugLinkTask = createDebugLinkTask(config, linkTask, extractDebugTask)
155
+
156
+ // Create the strip task and configure it properly
157
+ def stripTask = tasks. register(' stripLibRelease' , StripSymbols ) {
158
+ onlyIf {
159
+ config. active
160
+ }
161
+ dependsOn addDebugLinkTask
162
+ }
163
+
164
+ // Configure the strip task after registration
165
+ stripTask. configure {
166
+ targetPlatform = linkTask. get(). targetPlatform
167
+ toolChain = linkTask. get(). toolChain
168
+ binaryFile = linkTask. get(). linkedFile. get(). asFile
169
+ outputFile = getStrippedFilePath(config)
170
+ }
171
+
172
+ def copyDebugTask = createDebugCopyTask(config, extractDebugTask)
173
+
174
+ // Wire up the copy task to use stripped binaries
175
+ def copyTask = tasks. findByName(" copyReleaseLibs" )
176
+ if (copyTask != null ) {
177
+ copyTask. dependsOn stripTask
178
+ copyTask. inputs. files stripTask. get(). outputs. files
179
+ }
180
+ }
181
+ }
182
+
11
183
def libraryName = " ddprof"
12
184
13
185
description = " Datadog Java Profiler Library"
@@ -366,77 +538,7 @@ tasks.whenTaskAdded { task ->
366
538
outputs. file linkedFile
367
539
}
368
540
if (config. name == ' release' ) {
369
- def extractDebugTask = tasks. register(' extractDebugLibRelease' , Exec ) {
370
- onlyIf {
371
- config. active
372
- }
373
- dependsOn linkTask
374
- description = ' Extract debug symbols from release library'
375
- workingDir project. buildDir
376
-
377
- def sourceFile = tasks. linkLibRelease. linkedFile. get()
378
- def debugFile = file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /debug/libjavaProfiler.${ os().isLinux() ? 'so' : 'dylib'} .debug" )
379
-
380
- inputs. file sourceFile
381
- outputs. file debugFile
382
-
383
- doFirst {
384
- // Ensure debug directory exists
385
- debugFile. parentFile. mkdirs()
386
- }
387
-
388
- if (os(). isLinux()) {
389
- commandLine ' objcopy' , ' --only-keep-debug' , sourceFile. asFile. absolutePath, debugFile. absolutePath
390
- } else {
391
- // For macOS, we'll use dsymutil instead
392
- commandLine ' dsymutil' , sourceFile. asFile. absolutePath, ' -o' , debugFile. absolutePath. replace(' .debug' , ' .dSYM' )
393
- }
394
- }
395
-
396
- def addDebugLinkTask = tasks. register(' addDebugLinkLibRelease' , Exec ) {
397
- onlyIf {
398
- config. active && os(). isLinux()
399
- }
400
- dependsOn extractDebugTask
401
- description = ' Add debug link to the original library'
402
-
403
- def sourceFile = tasks. linkLibRelease. linkedFile. get()
404
- def debugFile = file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /debug/libjavaProfiler.${ os().isLinux() ? 'so' : 'dylib'} .debug" )
405
-
406
- inputs. file sourceFile
407
- inputs. file debugFile
408
- outputs. file sourceFile // modifies the source file
409
-
410
- commandLine ' objcopy' , ' --add-gnu-debuglink=' + debugFile. absolutePath, sourceFile. asFile. absolutePath
411
- }
412
-
413
- def stripTask = tasks. register(' stripLibRelease' , StripSymbols ) {
414
- onlyIf {
415
- config. active
416
- }
417
- dependsOn addDebugLinkTask
418
- targetPlatform = tasks. linkLibRelease. targetPlatform
419
- toolChain = tasks. linkLibRelease. toolChain
420
- binaryFile = tasks. linkLibRelease. linkedFile. get()
421
- outputFile = file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /stripped/libjavaProfiler.${ os().isLinux() ? 'so' : 'dylib'} " )
422
- inputs. file binaryFile
423
- outputs. file outputFile
424
- }
425
-
426
- // Create a task to copy debug files to the final location
427
- def copyDebugTask = tasks. register(' copyReleaseDebugFiles' , Copy ) {
428
- dependsOn extractDebugTask
429
- from file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /debug" )
430
- into file(libraryTargetPath(config. name + ' -debug' ))
431
- include ' **/*.debug'
432
- include ' **/*.dSYM/**'
433
- }
434
-
435
- def copyTask = tasks. findByName(" copyReleaseLibs" )
436
- if (copyTask != null ) {
437
- copyTask. dependsOn stripTask
438
- copyTask. inputs. files stripTask. get(). outputs. files
439
- }
541
+ setupDebugExtraction(config, linkTask)
440
542
}
441
543
}
442
544
}
0 commit comments