@@ -8,6 +8,166 @@ 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
+ // Skip if explicitly disabled
36
+ if (project. hasProperty(' skip-debug-extraction' )) {
37
+ return true
38
+ }
39
+
40
+ // Skip if required tools are not available
41
+ if (os(). isLinux() && ! checkObjcopyAvailable()) {
42
+ return true
43
+ }
44
+
45
+ if (os(). isMacOsX() && ! checkDsymutilAvailable()) {
46
+ return true
47
+ }
48
+
49
+ return false
50
+ }
51
+
52
+ // Helper function to get debug file path for a given config
53
+ def getDebugFilePath (config ) {
54
+ def extension = os(). isLinux() ? ' so' : ' dylib'
55
+ return file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /debug/libjavaProfiler.${ extension} .debug" )
56
+ }
57
+
58
+ // Helper function to get stripped file path for a given config
59
+ def getStrippedFilePath (config ) {
60
+ def extension = os(). isLinux() ? ' so' : ' dylib'
61
+ return file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /stripped/libjavaProfiler.${ extension} " )
62
+ }
63
+
64
+ // Helper function to create error message for missing tools
65
+ def getMissingToolErrorMessage (toolName , installInstructions ) {
66
+ return """
67
+ |${ toolName} is not available but is required for split debug information.
68
+ |
69
+ |To fix this issue:
70
+ |${ installInstructions}
71
+ |
72
+ |If you want to build without split debug info, set -Pskip-debug-extraction=true
73
+ """ . stripMargin()
74
+ }
75
+
76
+ // Helper function to create debug extraction task
77
+ def createDebugExtractionTask (config , linkTask ) {
78
+ return tasks. register(' extractDebugLibRelease' , Exec ) {
79
+ onlyIf {
80
+ ! shouldSkipDebugExtraction()
81
+ }
82
+ dependsOn linkTask
83
+ description = ' Extract debug symbols from release library'
84
+ workingDir project. buildDir
85
+
86
+ doFirst {
87
+ def sourceFile = linkTask. get(). linkedFile. get(). asFile
88
+ def debugFile = getDebugFilePath(config)
89
+
90
+ // Ensure debug directory exists
91
+ debugFile. parentFile. mkdirs()
92
+
93
+ // Set the command line based on platform
94
+ if (os(). isLinux()) {
95
+ commandLine = [' objcopy' , ' --only-keep-debug' , sourceFile. absolutePath, debugFile. absolutePath]
96
+ } else {
97
+ // For macOS, we'll use dsymutil instead
98
+ commandLine = [' dsymutil' , sourceFile. absolutePath, ' -o' , debugFile. absolutePath. replace(' .debug' , ' .dSYM' )]
99
+ }
100
+ }
101
+ }
102
+ }
103
+
104
+ // Helper function to create debug link task (Linux only)
105
+ def createDebugLinkTask (config , linkTask , extractDebugTask ) {
106
+ return tasks. register(' addDebugLinkLibRelease' , Exec ) {
107
+ onlyIf {
108
+ os(). isLinux() && ! shouldSkipDebugExtraction()
109
+ }
110
+ dependsOn extractDebugTask
111
+ description = ' Add debug link to the original library'
112
+
113
+ doFirst {
114
+ def sourceFile = linkTask. get(). linkedFile. get(). asFile
115
+ def debugFile = getDebugFilePath(config)
116
+
117
+ commandLine = [' objcopy' , ' --add-gnu-debuglink=' + debugFile. absolutePath, sourceFile. absolutePath]
118
+ }
119
+ }
120
+ }
121
+
122
+ // Helper function to create debug file copy task
123
+ def createDebugCopyTask (config , extractDebugTask ) {
124
+ return tasks. register(' copyReleaseDebugFiles' , Copy ) {
125
+ onlyIf {
126
+ ! shouldSkipDebugExtraction()
127
+ }
128
+ dependsOn extractDebugTask
129
+ from file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /debug" )
130
+ into file(libraryTargetPath(config. name + ' -debug' ))
131
+ include ' **/*.debug'
132
+ include ' **/*.dSYM/**'
133
+ }
134
+ }
135
+
136
+ // Main function to setup debug extraction for release builds
137
+ def setupDebugExtraction (config , linkTask ) {
138
+ if (config. name == ' release' && config. active && ! project. hasProperty(' skip-native' )) {
139
+ // Create all debug-related tasks
140
+ def extractDebugTask = createDebugExtractionTask(config, linkTask)
141
+ def addDebugLinkTask = createDebugLinkTask(config, linkTask, extractDebugTask)
142
+
143
+ // Create the strip task and configure it properly
144
+ def stripTask = tasks. register(' stripLibRelease' , StripSymbols ) {
145
+ // No onlyIf needed here - setupDebugExtraction already handles the main conditions
146
+ dependsOn addDebugLinkTask
147
+ }
148
+
149
+ // Configure the strip task after registration
150
+ stripTask. configure {
151
+ targetPlatform = linkTask. get(). targetPlatform
152
+ toolChain = linkTask. get(). toolChain
153
+ binaryFile = linkTask. get(). linkedFile. get(). asFile
154
+ outputFile = getStrippedFilePath(config)
155
+ }
156
+
157
+ def copyDebugTask = createDebugCopyTask(config, extractDebugTask)
158
+
159
+ // Wire up the copy task to use stripped binaries
160
+ def copyTask = tasks. findByName(" copyReleaseLibs" )
161
+ if (copyTask != null ) {
162
+ copyTask. dependsOn stripTask
163
+ copyTask. inputs. files stripTask. get(). outputs. files
164
+
165
+ // Create an extra folder for the debug symbols
166
+ copyTask. dependsOn copyDebugTask
167
+ }
168
+ }
169
+ }
170
+
11
171
def libraryName = " ddprof"
12
172
13
173
description = " Datadog Java Profiler Library"
@@ -366,23 +526,7 @@ tasks.whenTaskAdded { task ->
366
526
outputs. file linkedFile
367
527
}
368
528
if (config. name == ' release' ) {
369
- def stripTask = tasks. register(' stripLibRelease' , StripSymbols ) {
370
- onlyIf {
371
- config. active
372
- }
373
- dependsOn linkTask
374
- targetPlatform = tasks. linkLibRelease. targetPlatform
375
- toolChain = tasks. linkLibRelease. toolChain
376
- binaryFile = tasks. linkLibRelease. linkedFile. get()
377
- outputFile = file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /stripped/libjavaProfiler.${ os().isLinux() ? 'so' : 'dylib'} " )
378
- inputs. file binaryFile
379
- outputs. file outputFile
380
- }
381
- def copyTask = tasks. findByName(" copyReleaseLibs" )
382
- if (copyTask != null ) {
383
- copyTask. dependsOn stripTask
384
- copyTask. inputs. files stripTask. get(). outputs. files
385
- }
529
+ setupDebugExtraction(config, linkTask)
386
530
}
387
531
}
388
532
}
0 commit comments