Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/actions/setup_cached_java/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ runs:
shell: bash
id: infer_build_jdk
run: |
echo "Infering JDK 11 [${{ inputs.arch }}]"
# Gradle 9 requires JDK 17+ to run; using JDK 21 (LTS)
echo "Inferring JDK 21 [${{ inputs.arch }}]"
if [[ ${{ inputs.arch }} =~ "-musl" ]]; then
echo "build_jdk=jdk11-librca" >> $GITHUB_OUTPUT
echo "build_jdk=jdk21-librca" >> $GITHUB_OUTPUT
else
echo "build_jdk=jdk11" >> $GITHUB_OUTPUT
echo "build_jdk=jdk21" >> $GITHUB_OUTPUT
fi
- name: Cache Build JDK [${{ inputs.arch }}]
id: cache_build_jdk
Expand Down
22 changes: 22 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: 2
updates:
# Gradle dependencies
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 5
groups:
gradle-minor:
update-types:
- "minor"
- "patch"

# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 5
7 changes: 7 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ jobs:
if: needs.check-for-pr.outputs.skip != 'true'
steps:
- uses: actions/checkout@v3

- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '21'

- name: Setup OS
run: |
sudo apt-get update
Expand Down
63 changes: 58 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,16 @@ Release builds automatically extract debug symbols:
## Development Workflow

### Running Single Tests
Use standard Gradle syntax:
Use project properties to filter tests (config-specific test tasks use Exec, not Test):
```bash
./gradlew :ddprof-test:test --tests "ClassName.methodName"
./gradlew :ddprof-test:testdebug -Ptests=ClassName.methodName # Single method
./gradlew :ddprof-test:testdebug -Ptests=ClassName # Entire class
```

**Note**: Use `-Ptests` (not `--tests`) because config-specific test tasks (testdebug, testrelease)
use Gradle's Exec task type to bypass toolchain issues on musl systems. The `--tests` flag only
works with Gradle's Test task type.

### Working with Native Code
Native compilation is automatic during build. C++ code changes require:
1. Full rebuild: `/build-and-summarize clean build`
Expand Down Expand Up @@ -573,7 +578,55 @@ See `gradle.properties.template` for all options. Key ones:
- Exclude ddprof-lib/build/async-profiler from searches of active usage

- Run tests with 'testdebug' gradle task
- Use at most Java 21 to build and run tests

## Build JDK Configuration

The project uses a **two-JDK pattern**:
- **Build JDK** (`JAVA_HOME`): Used to run Gradle itself. Must be JDK 17+ for Gradle 9.
- **Test JDK** (`JAVA_TEST_HOME`): Used to run tests against different Java versions.

**Current requirement:** JDK 21 (LTS) for building, targeting Java 8 bytecode via `--release 8`.

### Files to Modify When Changing Build JDK Version

When upgrading the build JDK (e.g., from JDK 21 to JDK 25), update these files:

| File | What to Change |
|------|----------------|
| `README.md` | Update "Prerequisites" section with new JDK version |
| `.github/actions/setup_cached_java/action.yml` | Change `build_jdk=jdk21` to new version (line ~25) |
| `.github/workflows/ci.yml` | Update `java-version` in `check-formatting` job's Setup Java step |
| `utils/run-docker-tests.sh` | Update `BUILD_JDK_VERSION="21"` constant |
| `build-logic/.../JavaConventionsPlugin.kt` | Update documentation comment if minimum changes |

### Files to Modify When Changing Target JDK Version

When changing the target bytecode version (e.g., from Java 8 to Java 11):

| File | What to Change |
|------|----------------|
| `build-logic/.../JavaConventionsPlugin.kt` | Change `--release 8` to new version |
| `ddprof-lib/build.gradle.kts` | Change `sourceCompatibility`/`targetCompatibility` |
| `README.md` | Update minimum Java runtime version |

### Gradle 9 API Changes Reference

When upgrading Gradle major versions, watch for these breaking changes:

| Old API | New API (Gradle 9+) | Affected Files |
|---------|---------------------|----------------|
| `project.exec { }` in task actions | `ProcessBuilder` directly | `GtestPlugin.kt` |
| `String.capitalize()` | `replaceFirstChar { it.uppercaseChar() }` | Kotlin plugins |
| `createTempFile()` | `kotlin.io.path.createTempFile()` | `PlatformUtils.kt` |
| Spotless `userData()` | `editorConfigOverride()` | `SpotlessConventionPlugin.kt` |
| Spotless `indentWithSpaces()` | `leadingTabsToSpaces()` | `SpotlessConventionPlugin.kt` |

### CI JDK Caching

The CI caches JDKs via `.github/workflows/cache_java.yml`. When adding a new JDK version:
1. Add version URLs to `cache_java.yml` environment variables
2. Add to the `java_variant` matrix in cache jobs
3. Run the `cache_java.yml` workflow manually to populate caches

## Agentic Work

Expand All @@ -591,11 +644,11 @@ See `gradle.properties.template` for all options. Key ones:
```
- Instead of:
```bash
./gradlew :prof-utils:test --tests "UpscaledMethodSampleEventSinkTest"
./gradlew :ddprof-test:testdebug -Ptests=MuslDetectionTest
```
use:
```bash
./.claude/commands/build-and-summarize :prof-utils:test --tests "UpscaledMethodSampleEventSinkTest"
./.claude/commands/build-and-summarize :ddprof-test:testdebug -Ptests=MuslDetectionTest
```

- This ensures the full build log is captured to a file and only a summary is shown in the main session.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ If you need a full-fledged Java profiler head back to [async-profiler](https://g
## Build

### Prerequisites
1. JDK 8 or later (required for building)
2. Gradle (included in wrapper)
1. JDK 21 or later (required for building - Gradle 9 requirement)
2. Gradle 9.3.1 (included in wrapper)
3. C++ compiler (clang++ preferred, g++ supported)
- Build system auto-detects clang++ or g++
- Override with: `./gradlew build -Pnative.forceCompiler=g++`
Expand Down
2 changes: 1 addition & 1 deletion build-logic/conventions/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repositories {

dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
implementation("com.diffplug.spotless:spotless-plugin-gradle:6.11.0")
implementation("com.diffplug.spotless:spotless-plugin-gradle:7.0.2")
}

gradlePlugin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,18 @@ class GtestPlugin : Plugin<Project> {
val libDir = File("$targetDir/$libName")
val libSrcDir = File("$srcDir/$libName")

project.exec {
commandLine("sh", "-c", """
echo "Processing library: $libName @ $libSrcDir"
mkdir -p $libDir
cd $libSrcDir
make TARGET_DIR=$libDir
""".trimIndent())
// Use ProcessBuilder directly (Gradle 9 removed project.exec in task actions)
val process = ProcessBuilder("sh", "-c", """
echo "Processing library: $libName @ $libSrcDir"
mkdir -p $libDir
cd $libSrcDir
make TARGET_DIR=$libDir
""".trimIndent())
.inheritIO()
.start()
val exitCode = process.waitFor()
if (exitCode != 0) {
throw org.gradle.api.GradleException("Failed to build native lib: $libName (exit code: $exitCode)")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import com.datadoghq.native.model.Platform
import org.gradle.api.GradleException
import org.gradle.api.Project
import java.io.File
import kotlin.io.path.createTempFile
import kotlin.io.path.deleteIfExists
import kotlin.io.path.writeText
import java.util.concurrent.TimeUnit

object PlatformUtils {
Expand Down Expand Up @@ -124,15 +127,15 @@ object PlatformUtils {
"clang++",
"-fsanitize=fuzzer",
"-c",
testFile.absolutePath,
testFile.toAbsolutePath().toString(),
"-o",
"/dev/null"
).redirectErrorStream(true).start()

process.waitFor()
process.exitValue() == 0
} finally {
testFile.delete()
testFile.deleteIfExists()
}
} catch (e: Exception) {
false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import org.gradle.api.tasks.compile.JavaCompile
*
* Applies standard Java compilation options across all subprojects:
* - Java 8 release target for broad JVM compatibility
* - Suppresses JDK 21+ deprecation warnings for --release 8
*
* Requires JDK 9+ for building (uses --release flag).
* Requires JDK 21+ for building (Gradle 9 requirement).
* The compiled bytecode targets Java 8 runtime.
*
* Usage:
Expand All @@ -23,18 +24,10 @@ import org.gradle.api.tasks.compile.JavaCompile
*/
class JavaConventionsPlugin : Plugin<Project> {
override fun apply(project: Project) {
val javaVersion = System.getProperty("java.specification.version")?.toDoubleOrNull() ?: 0.0

project.tasks.withType(JavaCompile::class.java).configureEach {
if (javaVersion >= 9) {
// JDK 9+ supports --release flag which handles source, target, and boot classpath
options.compilerArgs.addAll(listOf("--release", "8"))
} else {
// Fallback for JDK 8 (not recommended for building)
sourceCompatibility = "8"
targetCompatibility = "8"
project.logger.warn("Building with JDK 8 is not recommended. Use JDK 11+ with --release 8 for better compatibility.")
}
// JDK 21+ deprecated --release 8 with warnings; suppress with -Xlint:-options
// The deprecation is informational - Java 8 targeting still works
options.compilerArgs.addAll(listOf("--release", "8", "-Xlint:-options"))
}
}
}
Loading
Loading