@@ -8,6 +8,180 @@ 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+ 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 symbol stripping task
136+ def createStripTask (config , linkTask , addDebugLinkTask ) {
137+ return tasks. register(' stripLibRelease' , StripSymbols ) {
138+ onlyIf {
139+ config. active
140+ }
141+ dependsOn addDebugLinkTask
142+
143+ // Defer property access until execution time
144+ doFirst {
145+ targetPlatform = linkTask. get(). targetPlatform
146+ toolChain = linkTask. get(). toolChain
147+ binaryFile = linkTask. get(). linkedFile. get(). asFile
148+ outputFile = getStrippedFilePath(config)
149+ }
150+ }
151+ }
152+
153+ // Helper function to create debug file copy task
154+ def createDebugCopyTask (config , extractDebugTask ) {
155+ return tasks. register(' copyReleaseDebugFiles' , Copy ) {
156+ onlyIf {
157+ ! shouldSkipDebugExtraction()
158+ }
159+ dependsOn extractDebugTask
160+ from file(" $buildDir /lib/main/${ config.name} /${ osIdentifier()} /${ archIdentifier()} /debug" )
161+ into file(libraryTargetPath(config. name + ' -debug' ))
162+ include ' **/*.debug'
163+ include ' **/*.dSYM/**'
164+ }
165+ }
166+
167+ // Main function to setup debug extraction for release builds
168+ def setupDebugExtraction (config , linkTask ) {
169+ if (config. name == ' release' ) {
170+ // Create all debug-related tasks
171+ def extractDebugTask = createDebugExtractionTask(config, linkTask)
172+ def addDebugLinkTask = createDebugLinkTask(config, linkTask, extractDebugTask)
173+ def stripTask = createStripTask(config, linkTask, addDebugLinkTask)
174+ def copyDebugTask = createDebugCopyTask(config, extractDebugTask)
175+
176+ // Wire up the copy task to use stripped binaries
177+ def copyTask = tasks. findByName(" copyReleaseLibs" )
178+ if (copyTask != null ) {
179+ copyTask. dependsOn stripTask
180+ copyTask. inputs. files stripTask. get(). outputs. files
181+ }
182+ }
183+ }
184+
11185def libraryName = " ddprof"
12186
13187description = " Datadog Java Profiler Library"
@@ -366,77 +540,7 @@ tasks.whenTaskAdded { task ->
366540 outputs. file linkedFile
367541 }
368542 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- }
543+ setupDebugExtraction(config, linkTask)
440544 }
441545 }
442546 }
0 commit comments