[WIP] [BUILD] Add Gradle build support and replace Maven in CI#11576
[WIP] [BUILD] Add Gradle build support and replace Maven in CI#11576liuneng1994 wants to merge 53 commits into
Conversation
Add a complete Gradle build system that coexists with the existing Maven build. This enables developers to choose their preferred build tool while maintaining full feature parity. Features: - Root Gradle configuration with version catalog (libs.versions.toml) - Convention plugins for common patterns (Scala, shading, native, spotless) - All core modules with proper dependencies - Multi-version support (Spark 3.3-4.1, Scala 2.12/2.13, Java 8-21) - Backend selection (Velox, ClickHouse) via -Pbackend property - Native C++ build integration via CMake - Dependency shading with Shadow plugin Default configuration: Spark 4.1, Scala 2.13, Java 17, Velox backend Usage examples: - ./gradlew build # Default build - ./gradlew build -PsparkVersion=3.5 # Spark 3.5 - ./gradlew build -Pbackend=clickhouse # ClickHouse backend - ./gradlew build -Pdelta=true -Piceberg=true # With optional modules Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Fix test dependencies and configuration to enable running ScalaTest suites via Gradle. Add scalatest plugin to backends-velox, include missing test dependencies (javafaker, flexmark, spark-common-utils), and apply Kotlin formatting fixes from spotless. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
philo-he
left a comment
There was a problem hiding this comment.
Thanks for the PR. Not sure if we need to add this support, especially considering the maintenance efforts for the two build tools' configurations.
- Derive scalaVersion from scalaBinaryVersion when overridden via -P - Use Java-version-aware Caffeine dependency (2.9.3 for Java 8, 3.1.8 for Java 11+) matching Maven behavior - Add scalatest plugin dependency to convention plugins - Propagate compileOnly dependencies to testImplementation scope Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Add full native build task chain to backends-velox: - getVelox: Fetch Velox source code - buildVelox: Build the Velox C++ library - configureNative: Configure CMake for Gluten C++ - buildNative: Build libgluten.so + libvelox.so - buildNativeAll: Convenience task for full pipeline All tasks support configurable properties (veloxHome, nativeBuildType, nativeThreads, enableHdfs, enableS3, etc.) and include onlyIf guards to skip already-completed steps. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Add backends-velox test JARs, Spark test JARs, and library-specific test dependencies to delta, iceberg, hudi, paimon modules so their test suites (extending WholeStageTransformerSuite) can compile. Fix spotless formatting in gluten-uniffle. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
These are Gradle internal cache files that should not be version controlled. The .gitignore entry already exists but only prevents new files from being added; tracked files need explicit removal. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Replace overly broad 'gradle' entry (which would ignore the entire gradle/ source directory) with proper entries: - .gradle/ - Gradle cache directories (anywhere in tree) - gradlew, gradlew.bat - Gradle wrapper scripts (if generated) Remove redundant per-file entries that are now covered by .gradle/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Remove ~430 lines of duplication across 30 build files: - Remove redundant protoc config (already in gluten.protobuf plugin) - Remove redundant ShadowJar config (already in gluten.shading plugin) - Remove redundant scala-library compileOnly (already in convention plugin) - Remove redundant JavaCompile config from root (already in convention plugin) - Remove unused variables (antlr4Version, hadoopVersion, scalaVersion, etc.) - Simplify optional module includes with map-based loop - Merge duplicate sparkProperties branches (4.0 and 4.1 are identical) - Extract gitOutput helper in generateBuildInfo - Make spark-common-utils conditional (Spark 4.0+ only) Verified: all Spark versions (3.4, 3.5, 4.0, 4.1) build successfully. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move duplicated Spark compile-only deps (spark-sql, spark-core, spark-catalyst, spark-hive), common test deps (scalatest, junit), and Spark test JARs into gluten.scala-library convention plugin. Removes ~200 lines of boilerplate across 11 module build files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Add spotless-plugin-gradle 6.25.0 with the same rules as Maven's spotless-maven-plugin: google-java-format for Java, scalafmt 3.8.3 for Scala, import ordering, license headers, and toggleOffOn support. The plugin is conditionally loaded based on the build JDK: - JDK 8: no-op (Spotless requires Java 11+) - JDK 11-16: google-java-format 1.7 - JDK 17+: google-java-format 1.17.0 GlutenSpotless.kt is excluded from compilation on JDK < 11 to avoid classpath issues, and invoked via reflection from the convention plugin. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Spotless enforces minimum google-java-format versions per JDK (1.8 for JDK 11, 1.10.0 for JDK 17). Using 1.17.0 universally satisfies all constraints and produces consistent formatting across JDKs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
The extractIncludeProto task scans the entire compile classpath for .proto files, which can block indefinitely due to network issues or dependency cache locks. A 5-minute timeout ensures the build fails with a clear error instead of hanging. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
If Gradle is much better than Maven, we needn't maintain Maven anymore. |
…Proto blocking - Add gluten.scalatest to 14 modules that had test sources but were not executing them: gluten-core, gluten-substrait, gluten-arrow, gluten-delta, gluten-iceberg, gluten-hudi, gluten-paimon, backends-clickhouse, gluten-ut/test, and gluten-ut/spark33-41. - Fix extractIncludeProto root cause: disconnect compileProtoPath from the full compile classpath (600+ JARs) and add only protobuf-java, so proto extraction scans just 1 JAR instead of the entire dependency tree. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
…Every support The gradle-scalatest plugin replaced Gradle's Test task with a single javaexec() call that ran all suites in one JVM, ignoring forkEvery=1. This caused SparkContext leaks between suites. Switch to JUnit 5 Platform with ScalaTest's junit-5-9 engine so Gradle's built-in Test task handles forking correctly. Add AbstractClassExcludeSpec to filter abstract classes and traits from test discovery by reading ACC_ABSTRACT from class file headers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
The ScalaTest JUnit 5 engine does not support JUnit Platform's includeTags/excludeTags, so tag filtering was silently broken. Replace with TagExcludeSpec that scans class file constant pools for annotation type descriptors at the Gradle test scanning level. Make gluten-ut modules opt-in via -Pspark-ut=true to match Maven's -Pspark-ut profile, and translate the flag in ci-gradle-build.sh. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Test code navigates from classpath root to source tree via relative
paths like getClass.getResource("/").getPath + "../../../src/...".
This breaks with Gradle's 4-level output dir (build/classes/scala/test/)
vs Maven's 2-level (target/test-classes/). The build/src -> ../src
symlink was only in backends-velox; move it to gluten.scala-conventions
so all modules (including gluten-ut) get it automatically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
GenerateExample is a string-based ScalaTest Tag object, not a @TagAnnotation annotation. TagExcludeSpec can only filter annotation- based tags via class file constant pool scanning. Translate the GenerateExample tagsToInclude to a --tests class name filter in ci-gradle-build.sh since the ScalaTest JUnit 5 engine doesn't support method-level tag filtering either. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
…ation Switch from JUnit 5 Platform (scalatestplus junit-5-9 engine + forkEvery=1) to the gradle-scalatest plugin with a custom ScalaTestPerSuiteAction that invokes `org.scalatest.tools.Runner -s <Suite>` in a separate javaexec per test suite class. This achieves per-suite JVM isolation without JUnit, preventing Spark's JVM-global state (SparkContext, daemon threads) from leaking between suites. Key changes: - Add gradle-scalatest plugin (0.32) dependency and apply it in the gluten.scalatest convention plugin - Create ScalaTestPerSuiteAction with bytecode-level suite discovery (superclass chain walking), class-level tag exclusion via constant pool scanning, and per-test tag include/exclude via Runner's -n/-l flags - Remove JUnit 5 runtime dependencies (junit-5-9, junit-jupiter-engine, junit-vintage-engine, junit-4-13) from backends-velox - Remove GenerateExample special-case in CI script (now handled natively by Runner's -n flag) - Clean up redundant comments across build.gradle.kts files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Only gluten-ut modules need per-suite JVM isolation because they extend Spark's own test suites (SharedSparkSession) which leak JVM-global state (SparkContext, daemon threads, shutdown hooks) between suites. Other modules (backends-velox, gluten-ras, etc.) keep the gradle-scalatest plugin's default single-JVM behavior (Runner -R <dir>), matching Maven's scalatest-maven-plugin. This avoids breaking tests like VeloxRasSuite that depend on native libraries loaded by earlier suites within the same JVM. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Use a bounded thread pool to run multiple suite JVMs concurrently, controlled by Gradle's maxParallelForks property. Set maxParallelForks=3 for gluten-ut modules (GitHub Actions runner: 4 vCPUs, 16 GB RAM; each suite JVM uses ~4 GB heap, so 3 parallel forks use ~12 GB). When maxParallelForks=1 (default for non-ut modules), execution remains sequential with no thread pool overhead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
Pass task.environment to each javaexec call so that any environment variables configured on the Test task are inherited by forked suite JVMs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Run Gluten Clickhouse CI on x86 |
|
Closing: Gradle build system works for compilation and non-ut module tests, but running gluten-ut (Spark UT) via Gradle has fundamental issues with Spark's JVM-global state, spark-warehouse directory collisions in parallel forks, and excessive memory consumption. CI workflows for Spark UT will remain on Maven. |
What changes are proposed in this pull request?
Add a complete Gradle build system that coexists with the existing Maven build. CI workflows for Spark UT (
velox_backend_x86.yml,velox_backend_enhanced.yml) remain on Maven.Gradle Build System:
libs.versions.toml)-PbackendpropertyDefault configuration: Spark 4.1, Scala 2.13, Java 17, Velox backend
Spark UT: Gradle Limitations (why Maven is kept for gluten-ut)
Running gluten-ut tests via Gradle was attempted with a per-suite JVM forking approach (
ScalaTestPerSuiteAction) but failed due to the following issues:LOCATION_ALREADY_EXISTSerrors from sharedspark-warehousedirectories: Parallel suite JVMs all resolvegetClass.getResource("/")to the sametest-classesdir, causing Spark's managed table creation to fail with warehouse directory collisions. Even with per-suite working directories (gluten.test.workDir), the classpath-based resource resolution inGlutenTestsBaseTrait.basePathmakes true isolation difficult.Excessive memory consumption: Per-suite JVM forking with the required 4g heap per JVM scales linearly (e.g., 6 forks × 4g = 24GB+), exceeding CI runner memory limits. Reducing parallelism defeats the purpose of per-suite forking.
Spark's JVM-global state leaking: Spark uses JVM-global singletons (SparkContext, daemon threads, native library loading) that leak between suites in a shared JVM. The gradle-scalatest plugin's default
Runner -R <dir>mode runs all suites in one JVM, causing failures when one suite's SparkContext is not properly stopped before the next suite starts.Tag filtering complexity: ScalaTest tag annotations are class-level but per-test
Tagobjects (e.g.,test("name", MyTag)) only produce runtime-visible metadata, requiring constant pool scanning heuristics for class-level pre-filtering that is fragile and incomplete.Maven's scalatest-maven-plugin handles these issues with battle-tested process isolation, making it the pragmatic choice for gluten-ut. Non-ut modules (backends-velox, gluten-ras, shims, etc.) continue to run tests via Gradle successfully.
Usage examples:
Native build Gradle tasks
getVeloxbuildVeloxconfigureNativebuildNativebuildNativeAllConfigurable properties:
-PveloxHome=,-PnativeBuildType=Debug|Release,-PnativeThreads=N,-PenableHdfs=ON,-PenableS3=ON,-PenableGcs=ON,-PenableAbfs=ON,-PenableQat=ON,-PenableGpu=ON,-PnativeBuildTests=ON,-PnativeBuildBenchmarks=ONKey Gradle build fixes (Maven compatibility)
Several fixes were needed to match Maven's behavior in Gradle:
No Spark Shim Provider foundwhen switching Spark versionsgenerateBuildInfotask had no declared inputs; Gradle cached stalegluten-build-info.propertiesinputs.property()declarations for sparkVersion, scalaVersion, etc.VeloxParquetWriteSuitefailures in Spark 3.3FileFormatWriternot loaded before Spark's own versionVeloxExpandSuiteNPE in CIforkEvery = 1— fork new JVM per test class (matches Maven)-Wconfrules not matching Maven config-Wconf:cat=deprecation&msg=symbol literal is deprecated:sUnsafeRowenableAssertions = falsein test configurationFileNotFoundExceptionaarch64→arm64; JNI loader uses rawaarch64aarch64to match Maven and JNI${config_loc}not set in Maven${config_loc}like Gradle does<propertyExpansion>to pom.xml; Gradle usesconfigDirectoryHow was this patch tested?
x86,enhanced,arm) — all jobs passingonlyIfguards skip already-built artifactsenabled = false), run via Maven in CIWas this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Opus 4 (Anthropic)