@@ -8,6 +8,166 @@ plugins {
88 id ' de.undercouch.download' version ' 4.1.1'
99}
1010
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+
11171def libraryName = " ddprof"
12172
13173description = " Datadog Java Profiler Library"
@@ -366,23 +526,7 @@ tasks.whenTaskAdded { task ->
366526 outputs. file linkedFile
367527 }
368528 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)
386530 }
387531 }
388532 }
0 commit comments