@invarn/cibuild 2.9.0 → 2.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"android.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/android.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"android.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/android.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import { existsSync, readFileSync } from 'node:fs';
10
10
  import { execSync } from 'node:child_process';
11
11
  import { BaseStepExecutor, javaHomeVersionSpec } from './base.js';
12
12
  import { gradleMemoryCommands } from './gradle-memory.js';
13
+ import { gradleSdkCmakeCommands } from './gradle-sdk-cmake.js';
13
14
  /**
14
15
  * Set Java version step executor
15
16
  * Sets the Java version to use for Android builds
@@ -461,6 +462,7 @@ export class GradleBuildStepExecutor extends BaseStepExecutor {
461
462
  commands.push(' exit 1');
462
463
  commands.push('fi');
463
464
  commands.push(...gradleMemoryCommands(this.getInput(inputs, 'jvmargs', ''), (v) => this.escapeBash(v), String(this.getInput(inputs, 'max_workers', '')).trim()));
465
+ commands.push(...gradleSdkCmakeCommands());
464
466
  // Build gradle command
465
467
  commands.push('');
466
468
  commands.push('# Timestamp marker — used to collect only artifacts from this build');
@@ -783,6 +785,7 @@ export class AndroidLintStepExecutor extends BaseStepExecutor {
783
785
  commands.push(' exit 1');
784
786
  commands.push('fi');
785
787
  commands.push(...gradleMemoryCommands(this.getInput(inputs, 'jvmargs', ''), (v) => this.escapeBash(v), String(this.getInput(inputs, 'max_workers', '')).trim()));
788
+ commands.push(...gradleSdkCmakeCommands());
786
789
  // Build lint task name
787
790
  commands.push('');
788
791
  commands.push('# Run lint');
@@ -973,6 +976,7 @@ export class AndroidUnitTestStepExecutor extends BaseStepExecutor {
973
976
  commands.push(' exit 1');
974
977
  commands.push('fi');
975
978
  commands.push(...gradleMemoryCommands(this.getInput(inputs, 'jvmargs', ''), (v) => this.escapeBash(v), String(this.getInput(inputs, 'max_workers', '')).trim()));
979
+ commands.push(...gradleSdkCmakeCommands());
976
980
  // Build test task name
977
981
  commands.push('');
978
982
  commands.push('# Run unit tests');
@@ -1041,6 +1045,7 @@ export class AndroidBuildForUITestingStepExecutor extends BaseStepExecutor {
1041
1045
  commands.push(' GRADLE_CMD="gradle"');
1042
1046
  commands.push('fi');
1043
1047
  commands.push(...gradleMemoryCommands(this.getInput(inputs, 'jvmargs', ''), (v) => this.escapeBash(v), String(this.getInput(inputs, 'max_workers', '')).trim()));
1048
+ commands.push(...gradleSdkCmakeCommands());
1044
1049
  commands.push('');
1045
1050
  // Build both app and test APKs
1046
1051
  const appTask = gradleTaskPath(this.escapeBash(module), `assemble${variantCap}`);
@@ -13,15 +13,17 @@
13
13
  *
14
14
  * 1. **Cap.** Read the machine's memory and the declared `-Xmx` of the Gradle
15
15
  * daemon and the Kotlin daemon. When their sum is past
16
- * `GRADLE_HEAP_SHARE_PERCENT` of memory, scale both down to fit, and pass
17
- * them on the command line (`-Dorg.gradle.jvmargs=`,
18
- * `-Pkotlin.daemon.jvmargs=`). One line names the old values and the new.
19
- * A Kotlin daemon that would inherit Gradle's -Xmx is given its own
20
- * instead, the budget split Kotlin 60 / Gradle 40: at an even split
21
- * (-Xmx3712m each) ReFra's Kotlin compile ran out of heap.
22
- * 2. **Say so.** When a Gradle run exits 137 or its output says the daemon
23
- * disappeared, print the kernel's out-of-memory lines and one sentence
24
- * with the machine's memory and what the build asked for.
16
+ * `GRADLE_HEAP_SHARE_PERCENT` of memory, run one heap instead: the Gradle
17
+ * daemon gets the whole budget (`-Dorg.gradle.jvmargs=`) and Kotlin
18
+ * compiles in it (`-Pkotlin.compiler.execution.strategy=in-process`). One
19
+ * line names the old values and the new. Two heaps did not fit: halved,
20
+ * ReFra's Kotlin compile ran out of heap; split 60/40, its Kotlin daemon
21
+ * was lost mid-compile, and mifos-mobile's Gradle daemon ran out of its
22
+ * 40 % on a 6 GiB guest.
23
+ * 2. **Say so.** When a Gradle run exits 137, its output says the daemon
24
+ * disappeared, or the Kotlin daemon was lost mid-compile, print the
25
+ * kernel's out-of-memory lines and one sentence with the machine's memory
26
+ * and what the build asked for.
25
27
  * 3. **Workers.** A heap cap does not bound what runs beside the heaps:
26
28
  * off-heap memory, and native compilers run in parallel. IacobIonut01/ReFra
27
29
  * was killed again at a capped -Xmx3712m, one JVM holding ~5.1 GiB
@@ -32,9 +34,10 @@
32
34
  * `-Dorg.gradle.jvmargs` on the command line beats both the Gradle user
33
35
  * home's and the project's `gradle.properties` for the daemon's heap, and
34
36
  * `-P` beats `gradle.properties` for a Gradle property, which is how the
35
- * Kotlin Gradle plugin reads `kotlin.daemon.jvmargs`; where the project
36
- * declares none, `-Pkotlin.daemon.jvmargs=-Xmx<n>` gives the Kotlin daemon
37
- * that heap instead of the Gradle daemon's. `--max-workers` beats
37
+ * Kotlin Gradle plugin reads `kotlin.daemon.jvmargs` and
38
+ * `kotlin.compiler.execution.strategy`: with
39
+ * `-Pkotlin.compiler.execution.strategy=in-process`, no Kotlin daemon starts
40
+ * even where the project's file says `daemon`. `--max-workers` beats
38
41
  * `org.gradle.workers.max` in both files (`gradle.startParameter.maxWorkerCount`).
39
42
  * `GRADLE_OPTS` is not used: it sizes the client JVM, not the daemon.
40
43
  *
@@ -43,13 +46,7 @@
43
46
  */
44
47
  /** The share of the machine's memory the two daemon heaps may take together. */
45
48
  export declare const GRADLE_HEAP_SHARE_PERCENT = 75;
46
- /**
47
- * Gradle's share of that budget when the Kotlin daemon would inherit its
48
- * -Xmx; the Kotlin daemon gets the rest as its own. The Kotlin compile is the
49
- * larger heap: ReFra's ran out at an even split.
50
- */
51
- export declare const GRADLE_HEAP_SPLIT_PERCENT = 40;
52
- export declare const GRADLE_MEMORY_FUNCTIONS = "# This machine's memory in MiB, or nothing when it cannot be read.\ncibuild_mem_mib() {\n if [ -r /proc/meminfo ]; then\n awk '/^MemTotal:/ { print int($2 / 1024); exit }' /proc/meminfo\n else\n local bytes\n bytes=$(sysctl -n hw.memsize 2>/dev/null || true)\n if [ -n \"$bytes\" ]; then echo $(( bytes / 1048576 )); fi\n fi\n}\n\n# $1 a .properties file, $2 a key. Prints \"<line number><TAB><value>\" for the\n# last assignment of the key, or nothing.\ncibuild_prop_line() {\n [ -f \"$1\" ] || return 0\n awk -v key=\"$2\" '\n { line = $0; sub(/^[ \\t]+/, \"\", line) }\n line ~ /^[#!]/ { next }\n {\n k = line; sub(/[ \\t]*[=:].*$/, \"\", k)\n if (k == key) { v = line; sub(/^[^=:]*[=:][ \\t]*/, \"\", v); sub(/[ \\t\\r]+$/, \"\", v); found = NR \"\\t\" v }\n }\n END { if (found != \"\") print found }\n ' \"$1\"\n}\n\n# The -Xmx of a JVM argument string in MiB (the last one wins, as in the JVM),\n# or nothing when it has none.\ncibuild_xmx_mib() {\n printf '%s\\n' \"$1\" | tr ' \\t' '\\n\\n' | awk '\n /^-Xmx[0-9]+[kKmMgGtT]?$/ {\n n = substr($0, 5); u = substr(n, length(n))\n if (u ~ /[0-9]/) { v = n / 1048576 }\n else {\n n = substr(n, 1, length(n) - 1)\n if (u ~ /[kK]/) v = n / 1024\n else if (u ~ /[mM]/) v = n\n else if (u ~ /[gG]/) v = n * 1024\n else v = n * 1048576\n }\n r = int(v)\n }\n END { if (r != \"\") print r }'\n}\n\n# $1 a JVM argument string, $2 a heap in MiB: the same arguments with every\n# -Xmx replaced by that one (added in front when there was none).\ncibuild_with_xmx() (\n set -f\n out=\"\"\n replaced=0\n for arg in $1; do\n case \"$arg\" in\n -Xmx*) if [ \"$replaced\" -eq 0 ]; then out=\"$out -Xmx${2}m\"; replaced=1; fi ;;\n *) out=\"$out $arg\" ;;\n esac\n done\n [ \"$replaced\" -eq 1 ] || out=\" -Xmx${2}m$out\"\n printf '%s' \"${out# }\"\n)\n\n# MiB as GiB with one decimal.\ncibuild_gib() {\n awk -v m=\"$1\" 'BEGIN { printf \"%.1f\", m / 1024 }'\n}\n\n# A heap scaled by budget/total, rounded down to 64 MiB, never below 512 MiB.\ncibuild_scaled_heap() {\n local v=$(( $1 * $2 / $3 / 64 * 64 ))\n [ \"$v\" -ge 512 ] || v=512\n echo \"$v\"\n}\n\n# The plan, from its inputs only, so a test can run it:\n# $1 this machine's memory in MiB (empty when unknown)\n# $2 the project's gradle.properties $3 the Gradle user home's\n# $4 JVM arguments the pipeline asks for instead (may be empty)\n# Sets CIBUILD_GRADLE_MEMORY_ARGS (extra Gradle arguments),\n# CIBUILD_GRADLE_MEMORY_LINE (what to print before Gradle runs; empty when\n# nothing changes) and CIBUILD_GRADLE_MEMORY_SENTENCE (what to print if a\n# daemon is killed).\n#\n# Precedence is Gradle's own: the command line beats GRADLE_USER_HOME's\n# gradle.properties, which beats the project's. A Kotlin daemon with no -Xmx of\n# its own inherits the Gradle daemon's, and in-process compilation has no\n# Kotlin daemon at all.\ncibuild_gradle_memory_plan() {\n local mem=\"$1\" project=\"$2\" user=\"$3\" preferred=\"$4\" l\n local jvm=\"\" jvm_at=\"\" kd=\"\" kd_at=\"\" strategy=\"\"\n CIBUILD_GRADLE_MEMORY_ARGS=()\n CIBUILD_GRADLE_MEMORY_LINE=\"\"\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"\"\n\n if [ -n \"$preferred\" ]; then jvm=\"$preferred\"; jvm_at=\"the pipeline\"; fi\n for f in \"$user\" \"$project\"; do\n if [ -z \"$jvm_at\" ]; then\n l=$(cibuild_prop_line \"$f\" org.gradle.jvmargs)\n if [ -n \"$l\" ]; then jvm=\"${l#*\t}\"; jvm_at=\"$f:${l%%\t*}\"; fi\n fi\n if [ -z \"$kd_at\" ]; then\n l=$(cibuild_prop_line \"$f\" kotlin.daemon.jvmargs)\n if [ -n \"$l\" ]; then kd=\"${l#*\t}\"; kd_at=\"$f:${l%%\t*}\"; fi\n fi\n if [ -z \"$strategy\" ]; then\n l=$(cibuild_prop_line \"$f\" kotlin.compiler.execution.strategy)\n strategy=\"${l#*\t}\"\n fi\n done\n\n local g k kd_own=\"\"\n g=$(cibuild_xmx_mib \"$jvm\")\n [ -n \"$g\" ] || g=512\n if [ \"$strategy\" = \"in-process\" ]; then\n k=0\n else\n kd_own=$(cibuild_xmx_mib \"$kd\")\n k=\"${kd_own:-$g}\"\n fi\n local total=$(( g + k ))\n\n local asked\n if [ -n \"$jvm_at\" ]; then asked=\"org.gradle.jvmargs=$jvm at ${jvm_at}\"; else asked=\"Gradle's default -Xmx512m\"; fi\n if [ \"$k\" -eq 0 ]; then\n asked=\"$asked; Kotlin compiles in-process\"\n elif [ -n \"$kd_own\" ]; then\n asked=\"$asked, kotlin.daemon.jvmargs=$kd at ${kd_at}\"\n else\n asked=\"$asked; the Kotlin daemon inherits its -Xmx\"\n fi\n\n if [ -z \"$mem\" ]; then\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"This build's Gradle and Kotlin daemons asked for $(cibuild_gib \"$total\") GiB ($asked); this machine's memory could not be read.\"\n if [ -n \"$preferred\" ]; then CIBUILD_GRADLE_MEMORY_ARGS=(\"-Dorg.gradle.jvmargs=$preferred\"); fi\n return 0\n fi\n\n local budget=$(( mem * 75 / 100 ))\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"The build machine has $(cibuild_gib \"$mem\") GiB; this build's Gradle and Kotlin daemons asked for $(cibuild_gib \"$total\") GiB ($asked).\"\n\n if [ \"$total\" -le \"$budget\" ]; then\n if [ -n \"$preferred\" ]; then\n CIBUILD_GRADLE_MEMORY_ARGS=(\"-Dorg.gradle.jvmargs=$preferred\")\n CIBUILD_GRADLE_MEMORY_LINE=\"Gradle memory: org.gradle.jvmargs=$preferred, as the pipeline asks (-Dorg.gradle.jvmargs on the command line).\"\n fi\n return 0\n fi\n\n case \"$jvm\" in\n *\\\\)\n CIBUILD_GRADLE_MEMORY_LINE=\"Gradle memory: the declared heaps ask for $(cibuild_gib \"$total\") GiB of this machine's $(cibuild_gib \"$mem\") GiB, but org.gradle.jvmargs at ${jvm_at} continues onto another line, so it is left as it is.\"\n return 0\n ;;\n esac\n\n local ng nk now\n if [ \"$k\" -gt 0 ] && [ -z \"$kd_own\" ]; then\n # A Kotlin daemon that would inherit Gradle's -Xmx gets its own, from a\n # split budget: halved, ReFra's Kotlin compile ran out of heap.\n ng=$(cibuild_scaled_heap \"$budget\" 40 100)\n nk=$(cibuild_scaled_heap \"$budget\" 60 100)\n else\n ng=$(cibuild_scaled_heap \"$g\" \"$budget\" \"$total\")\n fi\n CIBUILD_GRADLE_MEMORY_ARGS=(\"-Dorg.gradle.jvmargs=$(cibuild_with_xmx \"$jvm\" \"$ng\")\")\n now=\"Gradle -Xmx${ng}m\"\n if [ \"$k\" -eq 0 ]; then\n :\n elif [ -n \"$kd_own\" ]; then\n nk=$(cibuild_scaled_heap \"$k\" \"$budget\" \"$total\")\n CIBUILD_GRADLE_MEMORY_ARGS+=(\"-Pkotlin.daemon.jvmargs=$(cibuild_with_xmx \"$kd\" \"$nk\")\")\n now=\"$now and the Kotlin daemon -Xmx${nk}m\"\n else\n CIBUILD_GRADLE_MEMORY_ARGS+=(\"-Pkotlin.daemon.jvmargs=-Xmx${nk}m\")\n now=\"$now and the Kotlin daemon -Xmx${nk}m of its own (it would inherit Gradle's, so the heaps are split Kotlin 60 / Gradle 40)\"\n fi\n CIBUILD_GRADLE_MEMORY_LINE=\"Gradle memory: this machine has $(cibuild_gib \"$mem\") GiB and the declared heaps ask for $(cibuild_gib \"$total\") GiB ($asked), past the $(cibuild_gib \"$budget\") GiB this build allows them. Running with $now, set on the command line.\"\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"$CIBUILD_GRADLE_MEMORY_SENTENCE This build ran them capped: $now.\"\n}\n\n# $1 the number of Gradle workers the pipeline asks for (may be empty). Adds\n# --max-workers to the plan's arguments; run after cibuild_gradle_memory_plan.\n# Sets CIBUILD_GRADLE_WORKERS_LINE (what to print; empty when nothing asked).\ncibuild_gradle_workers_plan() {\n CIBUILD_GRADLE_WORKERS_LINE=\"\"\n [ -n \"$1\" ] || return 0\n case \"$1\" in\n *[!0-9]*|0*)\n CIBUILD_GRADLE_WORKERS_LINE=\"Gradle memory: max_workers=$1 is not a positive whole number, so it is not passed and Gradle picks its own worker count.\"\n return 0\n ;;\n esac\n CIBUILD_GRADLE_MEMORY_ARGS+=(\"--max-workers=$1\")\n CIBUILD_GRADLE_WORKERS_LINE=\"Gradle memory: running with --max-workers=$1, as the pipeline asks (set on the command line, over any org.gradle.workers.max).\"\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"$CIBUILD_GRADLE_MEMORY_SENTENCE Gradle ran with --max-workers=$1.\"\n}\n\n# The kernel's out-of-memory lines, if this user may read the kernel log.\n# Linux guests restrict dmesg to root by default; their build user has\n# non-interactive sudo, so that is the second try.\ncibuild_kernel_oom_lines() {\n { dmesg 2>/dev/null || sudo -n dmesg 2>/dev/null || true; } |\n grep -i -E 'out of memory|oom-kill|oom_reaper|killed process' | tail -n 20 || true\n}\n\n# $1 Gradle's exit status, $2 a file holding its output. Says so when the\n# failure is a killed daemon rather than a failed build.\ncibuild_gradle_memory_report() {\n if [ \"$1\" -ne 137 ] && ! grep -q \"daemon disappeared unexpectedly\" \"$2\" 2>/dev/null; then\n return 0\n fi\n local oom\n oom=$(cibuild_kernel_oom_lines)\n echo \"\"\n echo \"Gradle memory: a Gradle daemon was killed rather than failing the build (exit $1).\"\n if [ -n \"$oom\" ]; then\n echo \"The kernel's out-of-memory lines:\"\n printf '%s\\n' \"$oom\" | sed 's/^/ /'\n else\n echo \"The kernel log shows no out-of-memory kill, or this machine does not let the build read it.\"\n fi\n if [ -n \"$CIBUILD_GRADLE_MEMORY_SENTENCE\" ]; then echo \"$CIBUILD_GRADLE_MEMORY_SENTENCE\"; fi\n}\n\n# Runs Gradle with the plan's arguments, and reports a killed daemon.\ncibuild_gradle() {\n local log rc\n log=$(mktemp)\n set +e\n \"$CIBUILD_GRADLE_BIN\" \"${CIBUILD_GRADLE_MEMORY_ARGS[@]}\" \"$@\" 2>&1 | tee \"$log\"\n rc=${PIPESTATUS[0]}\n set -e\n if [ \"$rc\" -ne 0 ]; then cibuild_gradle_memory_report \"$rc\" \"$log\" || true; fi\n rm -f \"$log\"\n return \"$rc\"\n}\n\n# $1 JVM arguments the pipeline asks for, $2 the Gradle workers it asks for\n# (either may be empty). Run in the Gradle project directory, after GRADLE_CMD\n# is chosen.\ncibuild_gradle_memory_cap() {\n cibuild_gradle_memory_plan \"$(cibuild_mem_mib || true)\" \"gradle.properties\" \\\n \"${GRADLE_USER_HOME:-$HOME/.gradle}/gradle.properties\" \"$1\"\n cibuild_gradle_workers_plan \"$2\"\n if [ -n \"$CIBUILD_GRADLE_MEMORY_LINE\" ]; then echo \"$CIBUILD_GRADLE_MEMORY_LINE\"; fi\n if [ -n \"$CIBUILD_GRADLE_WORKERS_LINE\" ]; then echo \"$CIBUILD_GRADLE_WORKERS_LINE\"; fi\n CIBUILD_GRADLE_BIN=\"$GRADLE_CMD\"\n GRADLE_CMD=cibuild_gradle\n}";
49
+ export declare const GRADLE_MEMORY_FUNCTIONS = "# This machine's memory in MiB, or nothing when it cannot be read.\ncibuild_mem_mib() {\n if [ -r /proc/meminfo ]; then\n awk '/^MemTotal:/ { print int($2 / 1024); exit }' /proc/meminfo\n else\n local bytes\n bytes=$(sysctl -n hw.memsize 2>/dev/null || true)\n if [ -n \"$bytes\" ]; then echo $(( bytes / 1048576 )); fi\n fi\n}\n\n# $1 a .properties file, $2 a key. Prints \"<line number><TAB><value>\" for the\n# last assignment of the key, or nothing.\ncibuild_prop_line() {\n [ -f \"$1\" ] || return 0\n awk -v key=\"$2\" '\n { line = $0; sub(/^[ \\t]+/, \"\", line) }\n line ~ /^[#!]/ { next }\n {\n k = line; sub(/[ \\t]*[=:].*$/, \"\", k)\n if (k == key) { v = line; sub(/^[^=:]*[=:][ \\t]*/, \"\", v); sub(/[ \\t\\r]+$/, \"\", v); found = NR \"\\t\" v }\n }\n END { if (found != \"\") print found }\n ' \"$1\"\n}\n\n# The -Xmx of a JVM argument string in MiB (the last one wins, as in the JVM),\n# or nothing when it has none.\ncibuild_xmx_mib() {\n printf '%s\\n' \"$1\" | tr ' \\t' '\\n\\n' | awk '\n /^-Xmx[0-9]+[kKmMgGtT]?$/ {\n n = substr($0, 5); u = substr(n, length(n))\n if (u ~ /[0-9]/) { v = n / 1048576 }\n else {\n n = substr(n, 1, length(n) - 1)\n if (u ~ /[kK]/) v = n / 1024\n else if (u ~ /[mM]/) v = n\n else if (u ~ /[gG]/) v = n * 1024\n else v = n * 1048576\n }\n r = int(v)\n }\n END { if (r != \"\") print r }'\n}\n\n# $1 a JVM argument string, $2 a heap in MiB: the same arguments with every\n# -Xmx replaced by that one (added in front when there was none).\ncibuild_with_xmx() (\n set -f\n out=\"\"\n replaced=0\n for arg in $1; do\n case \"$arg\" in\n -Xmx*) if [ \"$replaced\" -eq 0 ]; then out=\"$out -Xmx${2}m\"; replaced=1; fi ;;\n *) out=\"$out $arg\" ;;\n esac\n done\n [ \"$replaced\" -eq 1 ] || out=\" -Xmx${2}m$out\"\n printf '%s' \"${out# }\"\n)\n\n# MiB as GiB with one decimal.\ncibuild_gib() {\n awk -v m=\"$1\" 'BEGIN { printf \"%.1f\", m / 1024 }'\n}\n\n# A heap scaled by budget/total, rounded down to 64 MiB, never below 512 MiB.\ncibuild_scaled_heap() {\n local v=$(( $1 * $2 / $3 / 64 * 64 ))\n [ \"$v\" -ge 512 ] || v=512\n echo \"$v\"\n}\n\n# The plan, from its inputs only, so a test can run it:\n# $1 this machine's memory in MiB (empty when unknown)\n# $2 the project's gradle.properties $3 the Gradle user home's\n# $4 JVM arguments the pipeline asks for instead (may be empty)\n# Sets CIBUILD_GRADLE_MEMORY_ARGS (extra Gradle arguments),\n# CIBUILD_GRADLE_MEMORY_LINE (what to print before Gradle runs; empty when\n# nothing changes) and CIBUILD_GRADLE_MEMORY_SENTENCE (what to print if a\n# daemon is killed).\n#\n# Precedence is Gradle's own: the command line beats GRADLE_USER_HOME's\n# gradle.properties, which beats the project's. A Kotlin daemon with no -Xmx of\n# its own inherits the Gradle daemon's, and in-process compilation has no\n# Kotlin daemon at all.\ncibuild_gradle_memory_plan() {\n local mem=\"$1\" project=\"$2\" user=\"$3\" preferred=\"$4\" l\n local jvm=\"\" jvm_at=\"\" kd=\"\" kd_at=\"\" strategy=\"\"\n CIBUILD_GRADLE_MEMORY_ARGS=()\n CIBUILD_GRADLE_MEMORY_LINE=\"\"\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"\"\n\n if [ -n \"$preferred\" ]; then jvm=\"$preferred\"; jvm_at=\"the pipeline\"; fi\n for f in \"$user\" \"$project\"; do\n if [ -z \"$jvm_at\" ]; then\n l=$(cibuild_prop_line \"$f\" org.gradle.jvmargs)\n if [ -n \"$l\" ]; then jvm=\"${l#*\t}\"; jvm_at=\"$f:${l%%\t*}\"; fi\n fi\n if [ -z \"$kd_at\" ]; then\n l=$(cibuild_prop_line \"$f\" kotlin.daemon.jvmargs)\n if [ -n \"$l\" ]; then kd=\"${l#*\t}\"; kd_at=\"$f:${l%%\t*}\"; fi\n fi\n if [ -z \"$strategy\" ]; then\n l=$(cibuild_prop_line \"$f\" kotlin.compiler.execution.strategy)\n strategy=\"${l#*\t}\"\n fi\n done\n\n local g k kd_own=\"\"\n g=$(cibuild_xmx_mib \"$jvm\")\n [ -n \"$g\" ] || g=512\n if [ \"$strategy\" = \"in-process\" ]; then\n k=0\n else\n kd_own=$(cibuild_xmx_mib \"$kd\")\n k=\"${kd_own:-$g}\"\n fi\n local total=$(( g + k ))\n\n local asked\n if [ -n \"$jvm_at\" ]; then asked=\"org.gradle.jvmargs=$jvm at ${jvm_at}\"; else asked=\"Gradle's default -Xmx512m\"; fi\n if [ \"$k\" -eq 0 ]; then\n asked=\"$asked; Kotlin compiles in-process\"\n elif [ -n \"$kd_own\" ]; then\n asked=\"$asked, kotlin.daemon.jvmargs=$kd at ${kd_at}\"\n else\n asked=\"$asked; the Kotlin daemon inherits its -Xmx\"\n fi\n\n if [ -z \"$mem\" ]; then\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"This build's Gradle and Kotlin daemons asked for $(cibuild_gib \"$total\") GiB ($asked); this machine's memory could not be read.\"\n if [ -n \"$preferred\" ]; then CIBUILD_GRADLE_MEMORY_ARGS=(\"-Dorg.gradle.jvmargs=$preferred\"); fi\n return 0\n fi\n\n local budget=$(( mem * 75 / 100 ))\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"The build machine has $(cibuild_gib \"$mem\") GiB; this build's Gradle and Kotlin daemons asked for $(cibuild_gib \"$total\") GiB ($asked).\"\n\n if [ \"$total\" -le \"$budget\" ]; then\n if [ -n \"$preferred\" ]; then\n CIBUILD_GRADLE_MEMORY_ARGS=(\"-Dorg.gradle.jvmargs=$preferred\")\n CIBUILD_GRADLE_MEMORY_LINE=\"Gradle memory: org.gradle.jvmargs=$preferred, as the pipeline asks (-Dorg.gradle.jvmargs on the command line).\"\n fi\n return 0\n fi\n\n case \"$jvm\" in\n *\\\\)\n CIBUILD_GRADLE_MEMORY_LINE=\"Gradle memory: the declared heaps ask for $(cibuild_gib \"$total\") GiB of this machine's $(cibuild_gib \"$mem\") GiB, but org.gradle.jvmargs at ${jvm_at} continues onto another line, so it is left as it is.\"\n return 0\n ;;\n esac\n\n # One heap, the whole budget. Two did not fit: ReFra's Kotlin daemon was\n # lost mid-compile at a 60/40 split, and mifos-mobile's Gradle daemon ran out\n # of its 40 %. In-process, Kotlin compiles in the Gradle daemon's heap.\n local ng now\n ng=$(cibuild_scaled_heap \"$budget\" 1 1)\n CIBUILD_GRADLE_MEMORY_ARGS=(\"-Dorg.gradle.jvmargs=$(cibuild_with_xmx \"$jvm\" \"$ng\")\")\n now=\"Gradle -Xmx${ng}m\"\n if [ \"$k\" -gt 0 ]; then\n CIBUILD_GRADLE_MEMORY_ARGS+=(\"-Pkotlin.compiler.execution.strategy=in-process\")\n now=\"$now and Kotlin compiled in-process in it (kotlin.compiler.execution.strategy=in-process: one heap, not a Gradle and a Kotlin daemon)\"\n fi\n CIBUILD_GRADLE_MEMORY_LINE=\"Gradle memory: this machine has $(cibuild_gib \"$mem\") GiB and the declared heaps ask for $(cibuild_gib \"$total\") GiB ($asked), past the $(cibuild_gib \"$budget\") GiB this build allows them. Running with $now, set on the command line.\"\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"$CIBUILD_GRADLE_MEMORY_SENTENCE This build ran them capped: $now.\"\n}\n\n# $1 the number of Gradle workers the pipeline asks for (may be empty). Adds\n# --max-workers to the plan's arguments; run after cibuild_gradle_memory_plan.\n# Sets CIBUILD_GRADLE_WORKERS_LINE (what to print; empty when nothing asked).\ncibuild_gradle_workers_plan() {\n CIBUILD_GRADLE_WORKERS_LINE=\"\"\n [ -n \"$1\" ] || return 0\n case \"$1\" in\n *[!0-9]*|0*)\n CIBUILD_GRADLE_WORKERS_LINE=\"Gradle memory: max_workers=$1 is not a positive whole number, so it is not passed and Gradle picks its own worker count.\"\n return 0\n ;;\n esac\n CIBUILD_GRADLE_MEMORY_ARGS+=(\"--max-workers=$1\")\n CIBUILD_GRADLE_WORKERS_LINE=\"Gradle memory: running with --max-workers=$1, as the pipeline asks (set on the command line, over any org.gradle.workers.max).\"\n CIBUILD_GRADLE_MEMORY_SENTENCE=\"$CIBUILD_GRADLE_MEMORY_SENTENCE Gradle ran with --max-workers=$1.\"\n}\n\n# The kernel's out-of-memory lines, if this user may read the kernel log.\n# Linux guests restrict dmesg to root by default; their build user has\n# non-interactive sudo, so that is the second try.\ncibuild_kernel_oom_lines() {\n { dmesg 2>/dev/null || sudo -n dmesg 2>/dev/null || true; } |\n grep -i -E 'out of memory|oom-kill|oom_reaper|killed process' | tail -n 20 || true\n}\n\n# $1 Gradle's exit status, $2 a file holding its output. Says so when the\n# failure is a killed daemon rather than a failed build.\ncibuild_gradle_memory_report() {\n local kotlin_lost=\"\"\n if grep -q \"Connection to the Kotlin daemon has been unexpectedly lost\" \"$2\" 2>/dev/null; then kotlin_lost=1; fi\n if [ \"$1\" -ne 137 ] && [ -z \"$kotlin_lost\" ] && ! grep -q \"daemon disappeared unexpectedly\" \"$2\" 2>/dev/null; then\n return 0\n fi\n local oom\n oom=$(cibuild_kernel_oom_lines)\n echo \"\"\n if [ -n \"$kotlin_lost\" ]; then\n echo \"Gradle memory: the Kotlin daemon was lost mid-compile rather than the build failing (exit $1). Kotlin then compiled without it, in the Gradle daemon's heap.\"\n else\n echo \"Gradle memory: a Gradle daemon was killed rather than failing the build (exit $1).\"\n fi\n if [ -n \"$oom\" ]; then\n echo \"The kernel's out-of-memory lines:\"\n printf '%s\\n' \"$oom\" | sed 's/^/ /'\n else\n echo \"The kernel log shows no out-of-memory kill, or this machine does not let the build read it.\"\n fi\n if [ -n \"$CIBUILD_GRADLE_MEMORY_SENTENCE\" ]; then echo \"$CIBUILD_GRADLE_MEMORY_SENTENCE\"; fi\n}\n\n# Runs Gradle with the plan's arguments, and reports a killed daemon.\ncibuild_gradle() {\n local log rc\n log=$(mktemp)\n set +e\n \"$CIBUILD_GRADLE_BIN\" \"${CIBUILD_GRADLE_MEMORY_ARGS[@]}\" \"$@\" 2>&1 | tee \"$log\"\n rc=${PIPESTATUS[0]}\n set -e\n if [ \"$rc\" -ne 0 ]; then cibuild_gradle_memory_report \"$rc\" \"$log\" || true; fi\n rm -f \"$log\"\n return \"$rc\"\n}\n\n# $1 JVM arguments the pipeline asks for, $2 the Gradle workers it asks for\n# (either may be empty). Run in the Gradle project directory, after GRADLE_CMD\n# is chosen.\ncibuild_gradle_memory_cap() {\n cibuild_gradle_memory_plan \"$(cibuild_mem_mib || true)\" \"gradle.properties\" \\\n \"${GRADLE_USER_HOME:-$HOME/.gradle}/gradle.properties\" \"$1\"\n cibuild_gradle_workers_plan \"$2\"\n if [ -n \"$CIBUILD_GRADLE_MEMORY_LINE\" ]; then echo \"$CIBUILD_GRADLE_MEMORY_LINE\"; fi\n if [ -n \"$CIBUILD_GRADLE_WORKERS_LINE\" ]; then echo \"$CIBUILD_GRADLE_WORKERS_LINE\"; fi\n CIBUILD_GRADLE_BIN=\"$GRADLE_CMD\"\n GRADLE_CMD=cibuild_gradle\n}";
53
50
  /**
54
51
  * The commands a Gradle step runs once it has chosen `GRADLE_CMD` and is in
55
52
  * the project directory. Afterwards `$GRADLE_CMD` runs Gradle with the plan's
@@ -1 +1 @@
1
- {"version":3,"file":"gradle-memory.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/gradle-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,gFAAgF;AAChF,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C,eAAO,MAAM,uBAAuB,q9TAuPlC,CAAC;AAEH;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EACjC,UAAU,SAAK,GACd,MAAM,EAAE,CAOV"}
1
+ {"version":3,"file":"gradle-memory.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/gradle-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,gFAAgF;AAChF,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAG5C,eAAO,MAAM,uBAAuB,ohUAmPlC,CAAC;AAEH;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EACjC,UAAU,SAAK,GACd,MAAM,EAAE,CAOV"}
@@ -13,15 +13,17 @@
13
13
  *
14
14
  * 1. **Cap.** Read the machine's memory and the declared `-Xmx` of the Gradle
15
15
  * daemon and the Kotlin daemon. When their sum is past
16
- * `GRADLE_HEAP_SHARE_PERCENT` of memory, scale both down to fit, and pass
17
- * them on the command line (`-Dorg.gradle.jvmargs=`,
18
- * `-Pkotlin.daemon.jvmargs=`). One line names the old values and the new.
19
- * A Kotlin daemon that would inherit Gradle's -Xmx is given its own
20
- * instead, the budget split Kotlin 60 / Gradle 40: at an even split
21
- * (-Xmx3712m each) ReFra's Kotlin compile ran out of heap.
22
- * 2. **Say so.** When a Gradle run exits 137 or its output says the daemon
23
- * disappeared, print the kernel's out-of-memory lines and one sentence
24
- * with the machine's memory and what the build asked for.
16
+ * `GRADLE_HEAP_SHARE_PERCENT` of memory, run one heap instead: the Gradle
17
+ * daemon gets the whole budget (`-Dorg.gradle.jvmargs=`) and Kotlin
18
+ * compiles in it (`-Pkotlin.compiler.execution.strategy=in-process`). One
19
+ * line names the old values and the new. Two heaps did not fit: halved,
20
+ * ReFra's Kotlin compile ran out of heap; split 60/40, its Kotlin daemon
21
+ * was lost mid-compile, and mifos-mobile's Gradle daemon ran out of its
22
+ * 40 % on a 6 GiB guest.
23
+ * 2. **Say so.** When a Gradle run exits 137, its output says the daemon
24
+ * disappeared, or the Kotlin daemon was lost mid-compile, print the
25
+ * kernel's out-of-memory lines and one sentence with the machine's memory
26
+ * and what the build asked for.
25
27
  * 3. **Workers.** A heap cap does not bound what runs beside the heaps:
26
28
  * off-heap memory, and native compilers run in parallel. IacobIonut01/ReFra
27
29
  * was killed again at a capped -Xmx3712m, one JVM holding ~5.1 GiB
@@ -32,9 +34,10 @@
32
34
  * `-Dorg.gradle.jvmargs` on the command line beats both the Gradle user
33
35
  * home's and the project's `gradle.properties` for the daemon's heap, and
34
36
  * `-P` beats `gradle.properties` for a Gradle property, which is how the
35
- * Kotlin Gradle plugin reads `kotlin.daemon.jvmargs`; where the project
36
- * declares none, `-Pkotlin.daemon.jvmargs=-Xmx<n>` gives the Kotlin daemon
37
- * that heap instead of the Gradle daemon's. `--max-workers` beats
37
+ * Kotlin Gradle plugin reads `kotlin.daemon.jvmargs` and
38
+ * `kotlin.compiler.execution.strategy`: with
39
+ * `-Pkotlin.compiler.execution.strategy=in-process`, no Kotlin daemon starts
40
+ * even where the project's file says `daemon`. `--max-workers` beats
38
41
  * `org.gradle.workers.max` in both files (`gradle.startParameter.maxWorkerCount`).
39
42
  * `GRADLE_OPTS` is not used: it sizes the client JVM, not the daemon.
40
43
  *
@@ -43,12 +46,6 @@
43
46
  */
44
47
  /** The share of the machine's memory the two daemon heaps may take together. */
45
48
  export const GRADLE_HEAP_SHARE_PERCENT = 75;
46
- /**
47
- * Gradle's share of that budget when the Kotlin daemon would inherit its
48
- * -Xmx; the Kotlin daemon gets the rest as its own. The Kotlin compile is the
49
- * larger heap: ReFra's ran out at an even split.
50
- */
51
- export const GRADLE_HEAP_SPLIT_PERCENT = 40;
52
49
  export const GRADLE_MEMORY_FUNCTIONS = `# This machine's memory in MiB, or nothing when it cannot be read.
53
50
  cibuild_mem_mib() {
54
51
  if [ -r /proc/meminfo ]; then
@@ -203,26 +200,16 @@ cibuild_gradle_memory_plan() {
203
200
  ;;
204
201
  esac
205
202
 
206
- local ng nk now
207
- if [ "$k" -gt 0 ] && [ -z "$kd_own" ]; then
208
- # A Kotlin daemon that would inherit Gradle's -Xmx gets its own, from a
209
- # split budget: halved, ReFra's Kotlin compile ran out of heap.
210
- ng=$(cibuild_scaled_heap "$budget" ${GRADLE_HEAP_SPLIT_PERCENT} 100)
211
- nk=$(cibuild_scaled_heap "$budget" ${100 - GRADLE_HEAP_SPLIT_PERCENT} 100)
212
- else
213
- ng=$(cibuild_scaled_heap "$g" "$budget" "$total")
214
- fi
203
+ # One heap, the whole budget. Two did not fit: ReFra's Kotlin daemon was
204
+ # lost mid-compile at a 60/40 split, and mifos-mobile's Gradle daemon ran out
205
+ # of its 40 %. In-process, Kotlin compiles in the Gradle daemon's heap.
206
+ local ng now
207
+ ng=$(cibuild_scaled_heap "$budget" 1 1)
215
208
  CIBUILD_GRADLE_MEMORY_ARGS=("-Dorg.gradle.jvmargs=$(cibuild_with_xmx "$jvm" "$ng")")
216
209
  now="Gradle -Xmx\${ng}m"
217
- if [ "$k" -eq 0 ]; then
218
- :
219
- elif [ -n "$kd_own" ]; then
220
- nk=$(cibuild_scaled_heap "$k" "$budget" "$total")
221
- CIBUILD_GRADLE_MEMORY_ARGS+=("-Pkotlin.daemon.jvmargs=$(cibuild_with_xmx "$kd" "$nk")")
222
- now="$now and the Kotlin daemon -Xmx\${nk}m"
223
- else
224
- CIBUILD_GRADLE_MEMORY_ARGS+=("-Pkotlin.daemon.jvmargs=-Xmx\${nk}m")
225
- now="$now and the Kotlin daemon -Xmx\${nk}m of its own (it would inherit Gradle's, so the heaps are split Kotlin ${100 - GRADLE_HEAP_SPLIT_PERCENT} / Gradle ${GRADLE_HEAP_SPLIT_PERCENT})"
210
+ if [ "$k" -gt 0 ]; then
211
+ CIBUILD_GRADLE_MEMORY_ARGS+=("-Pkotlin.compiler.execution.strategy=in-process")
212
+ now="$now and Kotlin compiled in-process in it (kotlin.compiler.execution.strategy=in-process: one heap, not a Gradle and a Kotlin daemon)"
226
213
  fi
227
214
  CIBUILD_GRADLE_MEMORY_LINE="Gradle memory: this machine has $(cibuild_gib "$mem") GiB and the declared heaps ask for $(cibuild_gib "$total") GiB ($asked), past the $(cibuild_gib "$budget") GiB this build allows them. Running with $now, set on the command line."
228
215
  CIBUILD_GRADLE_MEMORY_SENTENCE="$CIBUILD_GRADLE_MEMORY_SENTENCE This build ran them capped: $now."
@@ -256,13 +243,19 @@ cibuild_kernel_oom_lines() {
256
243
  # $1 Gradle's exit status, $2 a file holding its output. Says so when the
257
244
  # failure is a killed daemon rather than a failed build.
258
245
  cibuild_gradle_memory_report() {
259
- if [ "$1" -ne 137 ] && ! grep -q "daemon disappeared unexpectedly" "$2" 2>/dev/null; then
246
+ local kotlin_lost=""
247
+ if grep -q "Connection to the Kotlin daemon has been unexpectedly lost" "$2" 2>/dev/null; then kotlin_lost=1; fi
248
+ if [ "$1" -ne 137 ] && [ -z "$kotlin_lost" ] && ! grep -q "daemon disappeared unexpectedly" "$2" 2>/dev/null; then
260
249
  return 0
261
250
  fi
262
251
  local oom
263
252
  oom=$(cibuild_kernel_oom_lines)
264
253
  echo ""
265
- echo "Gradle memory: a Gradle daemon was killed rather than failing the build (exit $1)."
254
+ if [ -n "$kotlin_lost" ]; then
255
+ echo "Gradle memory: the Kotlin daemon was lost mid-compile rather than the build failing (exit $1). Kotlin then compiled without it, in the Gradle daemon's heap."
256
+ else
257
+ echo "Gradle memory: a Gradle daemon was killed rather than failing the build (exit $1)."
258
+ fi
266
259
  if [ -n "$oom" ]; then
267
260
  echo "The kernel's out-of-memory lines:"
268
261
  printf '%s\\n' "$oom" | sed 's/^/ /'
@@ -50,36 +50,35 @@ describe("cibuild_gradle_memory_plan", () => {
50
50
  test("ReFra: -Xmx8G, inherited by the Kotlin daemon, is capped on a 10 GiB machine", () => {
51
51
  copyFileSync(join(FIXTURES, "refra.gradle.properties"), join(dir, "gradle.properties"));
52
52
  const p = plan(TEN_GIB);
53
- // 75% of 10 GiB, split Kotlin 60 / Gradle 40: halved, the inherited
54
- // -Xmx3712m ran out of heap in ReFra's Kotlin compile.
55
- expect(p.args).toEqual([
56
- "-Dorg.gradle.jvmargs=-Xmx3072m -Dfile.encoding=UTF-8",
57
- "-Pkotlin.daemon.jvmargs=-Xmx4608m",
58
- ]);
53
+ // One heap, the whole 75% of 10 GiB, with Kotlin compiled in it: two
54
+ // daemons did not fit (split 60/40, ReFra's Kotlin daemon was lost
55
+ // mid-compile, and the fallback ran out of the Gradle daemon's heap).
56
+ expect(p.args).toEqual(["-Dorg.gradle.jvmargs=-Xmx7680m -Dfile.encoding=UTF-8", "-Pkotlin.compiler.execution.strategy=in-process"]);
59
57
  expect(p.line).toContain("org.gradle.jvmargs=-Xmx8G -Dfile.encoding=UTF-8 at gradle.properties:9");
60
58
  expect(p.line).toContain("16.0 GiB");
61
- expect(p.line).toContain("Running with Gradle -Xmx3072m and the Kotlin daemon -Xmx4608m of its own (it would inherit Gradle's, so the heaps are split Kotlin 60 / Gradle 40), set on the command line.");
59
+ expect(p.line).toContain("Running with Gradle -Xmx7680m and Kotlin compiled in-process in it (kotlin.compiler.execution.strategy=in-process: one heap, not a Gradle and a Kotlin daemon), set on the command line.");
62
60
  expect(p.sentence).toMatch(/^The build machine has 10\.0 GiB; this build's Gradle and Kotlin daemons asked for 16\.0 GiB/);
63
- expect(p.sentence).toMatch(/This build ran them capped: Gradle -Xmx3072m and the Kotlin daemon -Xmx4608m of its own .*\.$/);
61
+ expect(p.sentence).toMatch(/This build ran them capped: Gradle -Xmx7680m and Kotlin compiled in-process in it .*\.$/);
64
62
  });
65
63
  test("ReFra on its 9.7 GiB build guest", () => {
66
64
  copyFileSync(join(FIXTURES, "refra.gradle.properties"), join(dir, "gradle.properties"));
67
- expect(plan("9933").args).toEqual([
68
- "-Dorg.gradle.jvmargs=-Xmx2944m -Dfile.encoding=UTF-8",
69
- "-Pkotlin.daemon.jvmargs=-Xmx4416m",
65
+ expect(plan("9933").args).toEqual(["-Dorg.gradle.jvmargs=-Xmx7424m -Dfile.encoding=UTF-8", "-Pkotlin.compiler.execution.strategy=in-process"]);
66
+ });
67
+ test("mifos-mobile on its 6 GiB mac guest gets the one heap too", () => {
68
+ writeFileSync(join(dir, "gradle.properties"), "org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g\n");
69
+ expect(plan("6144").args).toEqual([
70
+ "-Dorg.gradle.jvmargs=-Xmx4608m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g",
71
+ "-Pkotlin.compiler.execution.strategy=in-process",
70
72
  ]);
71
73
  });
72
- test("the split never goes below 512 MiB either heap", () => {
74
+ test("the one heap never goes below 512 MiB", () => {
73
75
  writeFileSync(join(dir, "gradle.properties"), "org.gradle.jvmargs=-Xmx4g\n");
74
- expect(plan("1024").args).toEqual(["-Dorg.gradle.jvmargs=-Xmx512m", "-Pkotlin.daemon.jvmargs=-Xmx512m"]);
76
+ expect(plan("600").args).toEqual(["-Dorg.gradle.jvmargs=-Xmx512m", "-Pkotlin.compiler.execution.strategy=in-process"]);
75
77
  });
76
- test("amethyst: both heaps are scaled, and the Kotlin one keeps its other flags", () => {
78
+ test("amethyst: a Kotlin daemon with its own -Xmx is compiled in-process too, in one heap", () => {
77
79
  copyFileSync(join(FIXTURES, "amethyst.gradle.properties"), join(dir, "gradle.properties"));
78
80
  const p = plan(TEN_GIB);
79
- expect(p.args).toEqual([
80
- "-Dorg.gradle.jvmargs=-Xmx3264m -Dfile.encoding=UTF-8",
81
- "-Pkotlin.daemon.jvmargs=-Xmx4352m -XX:MaxMetaspaceSize=2g",
82
- ]);
81
+ expect(p.args).toEqual(["-Dorg.gradle.jvmargs=-Xmx7680m -Dfile.encoding=UTF-8", "-Pkotlin.compiler.execution.strategy=in-process"]);
83
82
  expect(p.line).toContain("kotlin.daemon.jvmargs=-Xmx8g -XX:MaxMetaspaceSize=2g at gradle.properties:27");
84
83
  expect(p.line).toContain("14.0 GiB");
85
84
  });
@@ -106,10 +105,7 @@ describe("cibuild_gradle_memory_plan", () => {
106
105
  mkdirSync(home);
107
106
  writeFileSync(join(home, "gradle.properties"), "org.gradle.jvmargs=-Xmx6g -XX:+UseParallelGC\n");
108
107
  const p = plan(TEN_GIB, "", home);
109
- expect(p.args).toEqual([
110
- "-Dorg.gradle.jvmargs=-Xmx3072m -XX:+UseParallelGC",
111
- "-Pkotlin.daemon.jvmargs=-Xmx4608m",
112
- ]);
108
+ expect(p.args).toEqual(["-Dorg.gradle.jvmargs=-Xmx7680m -XX:+UseParallelGC", "-Pkotlin.compiler.execution.strategy=in-process"]);
113
109
  expect(p.line).toContain(`at ${home}/gradle.properties:1`);
114
110
  });
115
111
  test("JVM arguments the pipeline asks for replace the project's, and are still capped", () => {
@@ -118,10 +114,7 @@ describe("cibuild_gradle_memory_plan", () => {
118
114
  expect(fits.args).toEqual(["-Dorg.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8"]);
119
115
  expect(fits.line).toContain("as the pipeline asks");
120
116
  const capped = plan("4096", "-Xmx4g -Dfile.encoding=UTF-8");
121
- expect(capped.args).toEqual([
122
- "-Dorg.gradle.jvmargs=-Xmx1216m -Dfile.encoding=UTF-8",
123
- "-Pkotlin.daemon.jvmargs=-Xmx1792m",
124
- ]);
117
+ expect(capped.args).toEqual(["-Dorg.gradle.jvmargs=-Xmx3072m -Dfile.encoding=UTF-8", "-Pkotlin.compiler.execution.strategy=in-process"]);
125
118
  expect(capped.line).toContain("at the pipeline");
126
119
  });
127
120
  test("a value continued onto another line is left as it is, and says so", () => {
@@ -139,10 +132,7 @@ describe("cibuild_gradle_memory_plan", () => {
139
132
  test("-Xmx in every unit, and a comment is not an assignment", () => {
140
133
  writeFileSync(join(dir, "gradle.properties"), "# org.gradle.jvmargs=-Xmx64g\norg.gradle.jvmargs = -Xms1g -Xmx6144m\nkotlin.daemon.jvmargs:-Xmx4194304k\n");
141
134
  const p = plan("8192");
142
- expect(p.args).toEqual([
143
- "-Dorg.gradle.jvmargs=-Xms1g -Xmx3648m",
144
- "-Pkotlin.daemon.jvmargs=-Xmx2432m",
145
- ]);
135
+ expect(p.args).toEqual(["-Dorg.gradle.jvmargs=-Xms1g -Xmx6144m", "-Pkotlin.compiler.execution.strategy=in-process"]);
146
136
  });
147
137
  });
148
138
  /** The plan, then the workers plan, as the step runs them. */
@@ -171,13 +161,9 @@ describe("cibuild_gradle_workers_plan", () => {
171
161
  test("ReFra: the worker count goes after the heap cap, and the sentence names it", () => {
172
162
  copyFileSync(join(FIXTURES, "refra.gradle.properties"), join(dir, "gradle.properties"));
173
163
  const p = workersPlan(TEN_GIB, "2");
174
- expect(p.args).toEqual([
175
- "-Dorg.gradle.jvmargs=-Xmx3072m -Dfile.encoding=UTF-8",
176
- "-Pkotlin.daemon.jvmargs=-Xmx4608m",
177
- "--max-workers=2",
178
- ]);
164
+ expect(p.args).toEqual(["-Dorg.gradle.jvmargs=-Xmx7680m -Dfile.encoding=UTF-8", "-Pkotlin.compiler.execution.strategy=in-process", "--max-workers=2"]);
179
165
  expect(p.line).toBe("Gradle memory: running with --max-workers=2, as the pipeline asks (set on the command line, over any org.gradle.workers.max).");
180
- expect(p.sentence).toMatch(/This build ran them capped: Gradle -Xmx3072m and the Kotlin daemon -Xmx4608m .* Gradle ran with --max-workers=2\.$/);
166
+ expect(p.sentence).toMatch(/This build ran them capped: Gradle -Xmx7680m and Kotlin compiled in-process in it .* Gradle ran with --max-workers=2\.$/);
181
167
  });
182
168
  test("heaps that fit still get the worker count", () => {
183
169
  const p = workersPlan(TEN_GIB, "4");
@@ -229,6 +215,17 @@ describe("the Gradle steps", () => {
229
215
  expect(run.stdout).toMatch(/The build machine has [0-9.]+ GiB; this build's Gradle and Kotlin daemons asked for 16\.0 GiB/);
230
216
  expect(run.stdout).not.toContain("Gradle build completed successfully");
231
217
  });
218
+ test("a lost Kotlin daemon is named like a killed Gradle daemon", async () => {
219
+ copyFileSync(join(FIXTURES, "refra.gradle.properties"), join(dir, "gradle.properties"));
220
+ // ReFra, bld_bd0132cc5229acb16c54130f: KGP's words, then its fallback.
221
+ fakeGradlew('echo "e: Daemon compilation failed"\necho "org.jetbrains.kotlin.gradle.tasks.DaemonCrashedException: Connection to the Kotlin daemon has been unexpectedly lost. This might be caused by the daemon being killed by another process or the operating system, or by JVM crash."\necho "Using fallback strategy: Compile without Kotlin daemon"\nexit 1');
222
+ const step = await new GradleBuildStepExecutor().execute({ gradle_task: "assembleDebug" }, {}, testConfig);
223
+ const run = runStep(step.script, fakeBin(OOM_LINE));
224
+ expect(run.status).toBe(1);
225
+ expect(run.stdout).toContain("Gradle memory: the Kotlin daemon was lost mid-compile rather than the build failing (exit 1). Kotlin then compiled without it, in the Gradle daemon's heap.");
226
+ expect(run.stdout).toContain(` ${OOM_LINE}`);
227
+ expect(run.stdout).toMatch(/The build machine has [0-9.]+ GiB; this build's Gradle and Kotlin daemons asked for 16\.0 GiB/);
228
+ });
232
229
  test("an ordinary failure says nothing about memory", async () => {
233
230
  fakeGradlew('echo "Compilation error"\nexit 1');
234
231
  const step = await new GradleBuildStepExecutor().execute({ gradle_task: "assembleDebug" }, {}, testConfig);
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The SDK CMake a build file pins, installed before Gradle runs.
3
+ *
4
+ * A module may pin its CMake (`android { externalNativeBuild { cmake {
5
+ * version = "3.31.6" } } }`). AGP downloads a pinned CMake it lacks, but only
6
+ * when it configures CMake, and a build's own Gradle task can need it first.
7
+ * IacobIonut01/ReFra's `buildHeifEncodeNative*` tasks run
8
+ * `scripts/native/build-heif-encode.sh`, which requires
9
+ * `$SDK/cmake/3.31.6/bin/cmake` and stops with "cmake 3.31.6 not found". The
10
+ * build images bake no SDK CMake, and a runner image cannot carry every
11
+ * version, so the version the project pins is installed with the SDK's own
12
+ * `sdkmanager` (its licences are accepted when the image is baked).
13
+ *
14
+ * Only literal versions inside a `cmake { }` block count. When there is no SDK
15
+ * or no sdkmanager, or the install fails, one line says so and the step goes
16
+ * on: AGP may still manage on its own.
17
+ *
18
+ * Written as shell functions so what ships is what the tests run. The shell
19
+ * is a raw string with no `${`, so every escape here is the one bash and awk
20
+ * read. Its lines start with "Android SDK:", never with a step-progress marker.
21
+ */
22
+ export declare const GRADLE_SDK_CMAKE_FUNCTIONS: string;
23
+ /**
24
+ * The commands a Gradle step runs in the project directory before Gradle, so
25
+ * a CMake the project pins is in the SDK when its own tasks look for it.
26
+ */
27
+ export declare function gradleSdkCmakeCommands(): string[];
28
+ //# sourceMappingURL=gradle-sdk-cmake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gradle-sdk-cmake.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/gradle-sdk-cmake.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,eAAO,MAAM,0BAA0B,QA6ErC,CAAC;AAEH;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAEjD"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * The SDK CMake a build file pins, installed before Gradle runs.
3
+ *
4
+ * A module may pin its CMake (`android { externalNativeBuild { cmake {
5
+ * version = "3.31.6" } } }`). AGP downloads a pinned CMake it lacks, but only
6
+ * when it configures CMake, and a build's own Gradle task can need it first.
7
+ * IacobIonut01/ReFra's `buildHeifEncodeNative*` tasks run
8
+ * `scripts/native/build-heif-encode.sh`, which requires
9
+ * `$SDK/cmake/3.31.6/bin/cmake` and stops with "cmake 3.31.6 not found". The
10
+ * build images bake no SDK CMake, and a runner image cannot carry every
11
+ * version, so the version the project pins is installed with the SDK's own
12
+ * `sdkmanager` (its licences are accepted when the image is baked).
13
+ *
14
+ * Only literal versions inside a `cmake { }` block count. When there is no SDK
15
+ * or no sdkmanager, or the install fails, one line says so and the step goes
16
+ * on: AGP may still manage on its own.
17
+ *
18
+ * Written as shell functions so what ships is what the tests run. The shell
19
+ * is a raw string with no `${`, so every escape here is the one bash and awk
20
+ * read. Its lines start with "Android SDK:", never with a step-progress marker.
21
+ */
22
+ export const GRADLE_SDK_CMAKE_FUNCTIONS = String.raw `# The CMake versions the project's build files pin, one per line as
23
+ # "<file>:<line><TAB><version>", first pin of each version only. Build
24
+ # outputs, .git and .gradle are not read.
25
+ cibuild_pinned_cmake_versions() {
26
+ find . \( -name build -o -name .git -o -name .gradle -o -name node_modules \) -prune -o \
27
+ -type f \( -name build.gradle -o -name build.gradle.kts \) -print 2>/dev/null | sort |
28
+ while IFS= read -r f; do
29
+ awk -v file="$f" '
30
+ FNR == 1 { inblk = 0; depth = 0 }
31
+ {
32
+ line = $0
33
+ sub(/\/\/.*$/, "", line)
34
+ if (!inblk && line ~ /(^|[^A-Za-z0-9_])cmake[ \t]*\{/) {
35
+ inblk = 1; depth = 0
36
+ sub(/.*(^|[^A-Za-z0-9_])cmake[ \t]*\{/, "{", line)
37
+ }
38
+ if (!inblk) next
39
+ if (match(line, /(^|[^A-Za-z0-9_.])version[ \t]*=?[ \t]*["\047][0-9]+\.[0-9]+(\.[0-9]+)?["\047]/)) {
40
+ v = substr(line, RSTART, RLENGTH); sub(/^.*version/, "", v); gsub(/[^0-9.]/, "", v)
41
+ print file ":" FNR "\t" v
42
+ }
43
+ depth += gsub(/\{/, "{", line) - gsub(/\}/, "}", line)
44
+ if (depth <= 0) inblk = 0
45
+ }
46
+ ' "$f"
47
+ done | awk -F '\t' '!seen[$2]++'
48
+ }
49
+
50
+ # The Android SDK: ANDROID_HOME, then ANDROID_SDK_ROOT, then local.properties'
51
+ # sdk.dir. Prints nothing when none names a directory.
52
+ cibuild_android_sdk_dir() {
53
+ local d
54
+ for d in "$ANDROID_HOME" "$ANDROID_SDK_ROOT"; do
55
+ if [ -n "$d" ] && [ -d "$d" ]; then echo "$d"; return 0; fi
56
+ done
57
+ if [ -f local.properties ]; then
58
+ d=$(sed -n 's/^[ \t]*sdk\.dir[ \t]*[=:][ \t]*//p' local.properties | tail -n 1 | sed 's/[ \t\r]*$//')
59
+ if [ -n "$d" ] && [ -d "$d" ]; then echo "$d"; return 0; fi
60
+ fi
61
+ return 0
62
+ }
63
+
64
+ # Installs every pinned CMake the SDK does not have. Never fails the step.
65
+ cibuild_install_pinned_cmake() {
66
+ local pins sdk sdkmanager at v out rc
67
+ pins=$(cibuild_pinned_cmake_versions)
68
+ [ -n "$pins" ] || return 0
69
+ sdk=$(cibuild_android_sdk_dir)
70
+ sdkmanager=""
71
+ if [ -n "$sdk" ] && [ -x "$sdk/cmdline-tools/latest/bin/sdkmanager" ]; then
72
+ sdkmanager="$sdk/cmdline-tools/latest/bin/sdkmanager"
73
+ elif [ -n "$sdk" ] && command -v sdkmanager >/dev/null 2>&1; then
74
+ sdkmanager=$(command -v sdkmanager)
75
+ fi
76
+ while IFS=' ' read -r at v; do
77
+ if [ -n "$sdk" ] && [ -x "$sdk/cmake/$v/bin/cmake" ]; then continue; fi
78
+ if [ -z "$sdk" ]; then
79
+ echo "Android SDK: $at pins cmake;$v, but no Android SDK was found (ANDROID_HOME, ANDROID_SDK_ROOT, local.properties sdk.dir), so it is not installed here."
80
+ continue
81
+ fi
82
+ if [ -z "$sdkmanager" ]; then
83
+ echo "Android SDK: $at pins cmake;$v, but $sdk has no sdkmanager, so it is not installed here."
84
+ continue
85
+ fi
86
+ echo "Android SDK: installing cmake;$v, which $at pins (externalNativeBuild cmake version) and this SDK does not have."
87
+ # Licences are answered from a process substitution, not a pipe, so
88
+ # neither set -e nor pipefail turns yes's SIGPIPE into a failure.
89
+ rc=0
90
+ out=$("$sdkmanager" "--sdk_root=$sdk" "cmake;$v" < <(yes 2>/dev/null) 2>&1) || rc=$?
91
+ if [ "$rc" -eq 0 ] && [ -x "$sdk/cmake/$v/bin/cmake" ]; then
92
+ echo "Android SDK: cmake;$v installed."
93
+ else
94
+ echo "Android SDK: installing cmake;$v failed (sdkmanager exit $rc); Gradle runs anyway:"
95
+ printf '%s\n' "$out" | tail -n 5 | sed 's/^/ /'
96
+ fi
97
+ done <<< "$pins"
98
+ return 0
99
+ }`;
100
+ /**
101
+ * The commands a Gradle step runs in the project directory before Gradle, so
102
+ * a CMake the project pins is in the SDK when its own tasks look for it.
103
+ */
104
+ export function gradleSdkCmakeCommands() {
105
+ return ['', GRADLE_SDK_CMAKE_FUNCTIONS, '', 'cibuild_install_pinned_cmake'];
106
+ }
107
+ //# sourceMappingURL=gradle-sdk-cmake.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gradle-sdk-cmake.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gradle-sdk-cmake.test.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/gradle-sdk-cmake.test.ts"],"names":[],"mappings":""}