@@ -8,6 +8,166 @@ plugins {
88  id ' de.undercouch.download' ' 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()} ${ extension} " 
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()} ${ extension} " 
62+ }
63+ 
64+ //  Helper function to create error message for missing tools
65+ def  getMissingToolErrorMessage (toolName , installInstructions ) {
66+   return  """ 
67+     |${ toolName}  
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' . absolutePath, debugFile. absolutePath]
96+       } else  {
97+         //  For macOS, we'll use dsymutil instead
98+         commandLine =  [' dsymutil' . absolutePath, ' -o' . 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()} " 
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()} ${ 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