Skip to content

Migrate build system to Kotlin build-logic - #358

Merged
jbachorik merged 44 commits into
mainfrom
jb/build_revamp
Feb 11, 2026
Merged

jbachorik merged 44 commits into
mainfrom
jb/build_revamp

Conversation

@jbachorik

@jbachorik jbachorik commented Feb 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Migrates the native build system from buildSrc to a Gradle composite build (build-logic/) with modern Kotlin DSL plugins. This provides better IDE support, faster incremental builds, and a cleaner architecture.

Key changes:

  • Replace buildSrc/ with build-logic/conventions/ composite build
  • Convert all build scripts from Groovy to Kotlin DSL (.gradle → .gradle.kts)
  • Create reusable Gradle plugins: NativeBuildPlugin, GtestPlugin, ScanBuildPlugin
  • Add automatic musl libc detection with -D__musl__ compiler flag
  • Add comprehensive documentation in build-logic/README.md and QUICKSTART.md
  • Create tooling-agnostic AGENTS.md for AI coding assistants
  • Reorganize documentation with PascalCase naming and clear directory structure

Build system improvements:

  • Platform-aware native compilation (Linux/macOS, x64/arm64)
  • Configurable build configurations (release, debug, asan, tsan, fuzzer)
  • Automatic debug symbol extraction for release builds
  • Google Test integration with per-test task granularity
  • scan-build static analysis integration (Linux only)

Documentation improvements:

  • Reorganized doc/ into architecture/, build/, reference/, temp/ directories
  • Standardized all docs to PascalCase naming
  • Added doc/README.md navigation index
  • Added PascalCase naming rule to AGENTS.md

Test plan

  • Build compiles on macOS arm64
  • Build compiles on Linux x64
  • Build compiles on Linux arm64
  • Build compiles on Linux x64 musl
  • All Java tests pass (testDebug)
  • All C++ tests pass (gtestDebug)
  • CI pipeline passes
# Local testing
./gradlew buildDebug
./gradlew testDebug
./gradlew gtestDebug

🤖 Generated with Claude Code

jbachorik and others added 19 commits February 5, 2026 10:35
Eliminated fragile "parasite pattern" that relied on cpp-library/cpp-application plugins.
These plugins had version parsing issues with newer compilers and JNI header detection problems.

Created custom SimpleCppCompile/SimpleLinkShared/SimpleLinkExecutable task types that:
- Directly invoke compilers without version string parsing
- Explicitly specify JNI include paths from JAVA_HOME
- Support parallel compilation for faster builds
- Maintain all existing build configurations (release/debug/asan/tsan/fuzzer)

Migrated modules:
- ddprof-lib: Main profiler library
- ddprof-lib/gtest: C++ unit tests
- ddprof-lib/fuzz: Fuzzer targets
- ddprof-lib/benchmarks: Benchmark executable
- malloc-shim: Memory interceptor

Code reduction: ~530 lines removed (parasite pattern, task disabling workarounds)
Code addition: ~600 lines in buildSrc (clean, maintainable task types)

Verified: assembleDebug, gtestDebug (127 tests passed), benchmarks build successful

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Based on code review feedback:

Error Handling Improvements:
- SimpleCppCompile: Capture and display compiler stderr/stdout on compilation failure
- SimpleLinkShared/SimpleLinkExecutable: Capture and display linker stderr/stdout on link failure
- SimpleCppCompile: Support .c and .cc extensions in addition to .cpp

Task Naming Consistency:
- Fixed hardcoded task names in ddprof-lib/build.gradle helper functions
- Now uses config.name for extractDebugLib*, addDebugLinkLib*, copy*DebugFiles tasks

Documentation:
- Updated CLAUDE.md to reflect Google Test compilation via Gradle tasks (not CMake)
- Added note about parallelJobs property using default ForkJoinPool

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Compiler and linker diagnostics may appear on stdout or stderr. Capturing both
ensures complete error information when builds fail.

Changes:
- SimpleCppCompile: Capture and display both stdout+stderr on compilation failure
- SimpleLinkShared: Capture and display both stdout+stderr on link failure
- SimpleLinkExecutable: Capture and display both stdout+stderr on link failure
- Updated javadoc example to show .c/.cc/.cpp extension support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create SourceSet for per-directory compiler flags
- Create CppBuildExtension with LogLevel and ErrorHandlingMode enums
- Enhance SimpleCppCompile with source sets, logging, and error handling
- Enhance SimpleLinkShared with symbol management and debug extraction
- Enhance SimpleLinkExecutable with library conveniences and verification
- Update CLAUDE.md with configuration examples

All properties are optional with backward-compatible defaults.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extracts C++ build support functionality into two reusable Gradle plugins
for better code organization and reusability across projects:

GtestPlugin:
- Automatic test discovery and task creation for Google Test
- Platform-aware configuration (Linux/macOS)
- Integration with SimpleCppCompile/SimpleLinkExecutable tasks
- Per-config (debug/release/asan/tsan) and master aggregation tasks

DebugSymbolsPlugin:
- Automated debug symbol extraction from release builds
- Platform-specific workflows (objcopy/strip on Linux, dsymutil/strip on macOS)
- Reduces production binary size ~80% (6.1MB → 1.2MB)
- Maintains separate debug files for symbolication

Changes:
- Created GtestExtension/GtestPlugin with comprehensive configuration DSL
- Created DebugSymbolsExtension/DebugSymbolsPlugin with helper method pattern
- Applied both plugins to ddprof-lib/build.gradle
- Removed 183 lines of legacy debug extraction code
- Removed ddprof-lib/gtest module (replaced by plugin)
- Updated ddprof-test to reference plugin tasks
- Added comprehensive documentation (README_GTEST_PLUGIN.md, README_DEBUG_SYMBOLS_PLUGIN.md)
- Updated CLAUDE.md with plugin usage examples

Benefits:
- Cleaner project structure (removed gtest module)
- Reusable across malloc-shim and future C++ projects
- Declarative configuration with sensible defaults
- Consistent build patterns across projects

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Update librarySourcePath to match plugin's build/lib/main/ structure
- Add consumable configurations for inter-project dependencies
- Enables ddprof-test to depend on specific build configurations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…nted

Release builds now use unstripped libraries temporarily. Debug symbol
extraction will be re-added as an incremental feature.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Implement extractDebugInfo in NativeLinkTask
  * Linux: objcopy extracts symbols, adds GNU debuglink
  * macOS: dsymutil creates .dSYM bundle
- Enable extraction and stripping for release builds
- Add -g flag to macOS release builds
- Exclude debug symbols from production JARs

Results:
- Stripped library: 404KB (69% smaller than 1.3MB debug)
- Debug symbols: 3.7MB dSYM bundle (separate)
- Release JAR: 183KB (down from 1.6MB with symbols)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Ensure all copy tasks depend on their corresponding link tasks,
not just release. Prevents copyDebugLibs from failing when
library directory doesn't exist yet.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Document the native build plugin architecture, usage, configurations,
and debug symbol extraction process.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace deprecated capitalize() with replaceFirstChar { it.titlecase() }
- Fix Linux version script to use single local section (valid syntax)
- Improve JAVA_HOME error message clarity
- Document macOS symbol export wildcard limitation
- Fix FAIL_FAST mode to properly terminate on first error
- Remove unused import

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enables automatic detection of clang++ or g++ with explicit override support, fixing sanitizer builds on clang-only systems.

- Auto-detect clang++ or g++ (prefers clang++)
- Support -Pnative.forceCompiler=<compiler> for explicit control
- Fix sanitizer detection on clang-only systems (macOS with Xcode)
- Add macOS wildcard warning for symbol exports
- Improve error messages when no compiler found

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove Groovy buildSrc (GtestPlugin, DebugSymbolsPlugin, SimpleCpp*)
- Add Kotlin GtestPlugin to build-logic with NativeBuildPlugin integration
- Migrate malloc-shim, fuzz, benchmarks to Kotlin DSL
- Update documentation to reflect final architecture

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jbachorik jbachorik added the AI label Feb 6, 2026
jbachorik and others added 3 commits February 6, 2026 12:33
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@DataDog DataDog deleted a comment from pr-commenter Bot Feb 6, 2026
@DataDog DataDog deleted a comment from dd-octo-sts Bot Feb 6, 2026
@dd-octo-sts

dd-octo-sts Bot commented Feb 6, 2026 •

Copy link
Copy Markdown
Contributor

Scan-Build Report

User:runner@runnervmwffz4
Working Directory:/home/runner/work/java-profiler/java-profiler/ddprof-lib/src/test/make
Command Line:make -j4 all
Clang Version:Ubuntu clang version 18.1.3 (1ubuntu1)
Date:Sun Feb 8 19:41:07 2026

Bug Summary

Bug TypeQuantityDisplay?
All Bugs1
Unused code
Dead assignment1

Reports

Bug Group Bug Type ▾ File Function/Method Line Path Length
Unused codeDead assignmentlibraryPatcher_linux.cpppatch_library_unlocked941

@dd-octo-sts

dd-octo-sts Bot commented Feb 6, 2026 •

Copy link
Copy Markdown
Contributor

CI Test Results

Run: #34248393885 | Commit: 76205bd | Duration: 0s (longest job)

✅ All 0 test jobs passed

Summary: Total: 0 | Passed: 0 | Failed: 0


Updated: 2026-09-08 16:06:21 UTC

@jbachorik
jbachorik marked this pull request as ready for review February 6, 2026 13:43
@jbachorik
jbachorik requested a review from a team as a code owner February 6, 2026 13:43
jbachorik and others added 18 commits February 8, 2026 15:31
CLAUDE.md is now generated locally by Claude via bootstrap
instructions in AGENTS.md. This prevents accidental overwrites.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comprehensive quick-start documentation for native build plugins covering:
- Common workflows (debug, sanitizers, release, scan-build)
- How-to guides for configuration and customization
- Tips and tricks for performance, debugging, testing, and static analysis
- CI/CD integration examples
- Platform-specific setup instructions
- Troubleshooting common issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add prominent link to QUICKSTART.md at top of README and Documentation section at bottom. Include scanbuild plugin in file listing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
JDK versions as rows, platforms as columns (fewer platforms).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Convert ddprof-test-tracer, ddprof-stresstest, ddprof-test to Kotlin DSL
- Convert common.gradle and configurations.gradle to Kotlin DSL
- Update root build.gradle.kts to reference new .kts files
- spotless.gradle remains in Groovy (applied script type issues)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create RootProjectPlugin to expose nativeBuild extension
- Add query methods to NativeBuildExtension
- Update ddprof-test to use plugin extension
- Remove redundant gradle/configurations.gradle files
- ConfigurationPresets.kt is now single source of truth

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extract native test helpers (JNI library) into separate subproject.
Compile without optimization to prevent inlining of static functions
like do_primes() which must be visible in stack traces for profiler
testing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ProfilerTestPlugin convention plugin for multi-config test tasks
- Expand version catalog with testing and profiler-runtime bundles
- Simplify ddprof-test/build.gradle.kts from ~350 to ~110 lines
- Move native test sources to ddprof-test-native subproject
- Add path utility methods to NativeBuildExtension

The plugin auto-generates test tasks (testdebug, testrelease, etc.)
and application tasks from NativeBuildExtension configurations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add JavaConventionsPlugin for Java 8 release flag
- Add FuzzTargetsPlugin for libFuzzer test infrastructure
- Add SimpleNativeLibPlugin for single-output native libs
- Extract GtestTaskBuilder for cleaner task creation
- Consolidate JAVA_HOME/test helpers in PlatformUtils
- Add task name helpers to BuildConfiguration
- Centralize repository definitions in settings.gradle.kts

Reduces build file sizes significantly:
- ddprof-lib/fuzz: 319→28 lines (91%)
- malloc-shim: 67→36 lines (46%)
- ddprof-test-native: 108→43 lines (60%)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove obsolete common.gradle.kts (duplicated PlatformUtils)
- Use dynamic config discovery instead of hardcoded lists
- Create testCommon/mainCommon configs eagerly in ProfilerTestPlugin
- Simplify ddprof-test dependency declarations
- Remove copyright headers from build files
- Add gradle.properties.template documenting all properties
- Add doc/GRADLE-TASKS.md with task reference
- Add doc/BUILD-SYSTEM-GUIDE.md with maintenance guide
- Update AGENTS.md with build system quick reference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create build/, reference/ directories
- Move build docs to doc/build/
- Move reference docs to doc/reference/
- Rename all docs to PascalCase
- Add doc/README.md index
- Add PascalCase naming rule to AGENTS.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add double parentheses to while assignments (os_linux.cpp)
- Remove fully qualified names, add imports (build plugins)
- Remove redundant -v linker flag

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove trailing space from comment

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@jbachorik
jbachorik marked this pull request as ready for review February 8, 2026 19:38
@jbachorik
jbachorik requested a review from zhengyu123 February 10, 2026 14:01

@rkennke rkennke left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@jbachorik
jbachorik merged commit 76205bd into main Feb 11, 2026
97 checks passed
@jbachorik
jbachorik deleted the jb/build_revamp branch February 11, 2026 11:12
@github-actions github-actions Bot added this to the 1.38.0 milestone Feb 11, 2026
@zhengyu123 zhengyu123 added the fixed_version: v_1.38.0 Version this PR's fix shipped in label Sep 8, 2026
@rkennke rkennke mentioned this pull request Oct 5, 2026
2 of 3 tasks
rkennke added a commit that referenced this pull request Oct 5, 2026
The gtest plugin's buildNativeLibs task builds the helper DSOs under
src/test/resources/native-libs, but its onlyIf requires
nativeLibsSourceDir and nativeLibsOutputDir to be set, and neither has a
convention nor was set by ddprof-lib. The task has therefore been
skipped since the move to the Kotlin build-logic (#358), and tests that
need those DSOs found them missing and exited early.

Set both directories in the ddprof-lib gtest block, and make the
build-only buildGtest{Config} tasks depend on buildNativeLibs too: the
CI gtest jobs run those and then execute the binaries directly, so
wiring it only into the gtest{Config}_{Test} run tasks was not enough.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI fixed_version: v_1.38.0 Version this PR's fix shipped in

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants