Skip to content

Commit cc768fa

Browse files
authored
Merge pull request #336 from OpenHub-Store/flatpak-integration
2 parents 42f8b5a + f8d3519 commit cc768fa

7 files changed

Lines changed: 3522 additions & 0 deletions

build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
plugins {
2+
id("io.github.jwharm.flatpak-gradle-generator") version "1.7.0"
23
alias(libs.plugins.android.application) apply false
34
alias(libs.plugins.android.library) apply false
45
alias(libs.plugins.compose.hot.reload) apply false
@@ -11,6 +12,10 @@ plugins {
1112
alias(libs.plugins.room) apply false
1213
}
1314

15+
tasks.named<io.github.jwharm.flatpakgradlegenerator.FlatpakGradleGeneratorTask>("flatpakGradleGenerator") {
16+
outputFile.set(layout.buildDirectory.file("flatpak-sources.json"))
17+
}
18+
1419
subprojects {
1520
afterEvaluate {
1621
tasks.configureEach {
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
#!/bin/bash
2+
# disable-android-for-flatpak.sh
3+
#
4+
# Strips all Android-related configuration from the project so it can
5+
# build inside the Flatpak sandbox where no Android SDK is available.
6+
# This script modifies files IN-PLACE — only run during Flatpak builds.
7+
8+
set -euo pipefail
9+
10+
echo "=== Disabling Android targets for Flatpak build ==="
11+
12+
# ─────────────────────────────────────────────────────────────────────
13+
# 1. Root build.gradle.kts — comment out Android plugin declarations
14+
# ─────────────────────────────────────────────────────────────────────
15+
echo "[1/6] Patching root build.gradle.kts"
16+
sed -i \
17+
-e 's|alias(libs.plugins.android.application)|// alias(libs.plugins.android.application)|' \
18+
-e 's|alias(libs.plugins.android.library)|// alias(libs.plugins.android.library)|' \
19+
-e 's|alias(libs.plugins.android.kotlin.multiplatform.library)|// alias(libs.plugins.android.kotlin.multiplatform.library)|' \
20+
build.gradle.kts
21+
22+
# ─────────────────────────────────────────────────────────────────────
23+
# 2. Convention plugins — replace Android plugin applies with no-ops
24+
# ─────────────────────────────────────────────────────────────────────
25+
CONVENTION_DIR="build-logic/convention/src/main/kotlin"
26+
27+
echo "[2/6] Patching KmpLibraryConventionPlugin (remove Android library plugin + config)"
28+
cat > "$CONVENTION_DIR/KmpLibraryConventionPlugin.kt" << 'KOTLIN'
29+
import org.gradle.api.Plugin
30+
import org.gradle.api.Project
31+
import org.gradle.kotlin.dsl.dependencies
32+
import zed.rainxch.githubstore.convention.configureJvmTarget
33+
import zed.rainxch.githubstore.convention.libs
34+
import zed.rainxch.githubstore.convention.pathToResourcePrefix
35+
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
36+
import org.gradle.kotlin.dsl.configure
37+
38+
class KmpLibraryConventionPlugin : Plugin<Project> {
39+
override fun apply(target: Project) {
40+
with(target) {
41+
with(pluginManager) {
42+
apply("org.jetbrains.kotlin.multiplatform")
43+
apply("org.jetbrains.kotlin.plugin.serialization")
44+
}
45+
46+
configureJvmTarget()
47+
48+
extensions.configure<KotlinMultiplatformExtension> {
49+
compilerOptions {
50+
freeCompilerArgs.add("-Xexpect-actual-classes")
51+
freeCompilerArgs.add("-Xmulti-dollar-interpolation")
52+
freeCompilerArgs.add("-opt-in=kotlin.RequiresOptIn")
53+
freeCompilerArgs.add("-opt-in=kotlin.time.ExperimentalTime")
54+
}
55+
}
56+
57+
dependencies {
58+
"commonMainImplementation"(libs.findLibrary("kotlinx-serialization-json").get())
59+
}
60+
}
61+
}
62+
}
63+
KOTLIN
64+
65+
echo "[3/6] Patching CmpApplicationConventionPlugin (remove Android application)"
66+
cat > "$CONVENTION_DIR/CmpApplicationConventionPlugin.kt" << 'KOTLIN'
67+
import org.gradle.api.Plugin
68+
import org.gradle.api.Project
69+
import org.gradle.kotlin.dsl.dependencies
70+
import zed.rainxch.githubstore.convention.configureJvmTarget
71+
import zed.rainxch.githubstore.convention.libs
72+
73+
class CmpApplicationConventionPlugin : Plugin<Project> {
74+
override fun apply(target: Project) {
75+
with(target) {
76+
with(pluginManager) {
77+
apply("org.jetbrains.kotlin.multiplatform")
78+
apply("org.jetbrains.compose")
79+
apply("org.jetbrains.kotlin.plugin.compose")
80+
}
81+
82+
configureJvmTarget()
83+
}
84+
}
85+
}
86+
KOTLIN
87+
88+
echo "[4/6] Patching CmpLibraryConventionPlugin & CmpFeatureConventionPlugin"
89+
90+
# CmpLibraryConventionPlugin — remove Android library dependency
91+
sed -i \
92+
-e 's|apply("com.android.library")|// apply("com.android.library")|' \
93+
"$CONVENTION_DIR/CmpLibraryConventionPlugin.kt" 2>/dev/null || true
94+
95+
sed -i \
96+
-e 's|apply("com.android.library")|// apply("com.android.library")|' \
97+
"$CONVENTION_DIR/CmpFeatureConventionPlugin.kt" 2>/dev/null || true
98+
99+
# Remove configureKotlinAndroid calls and Android extension blocks (only at call sites)
100+
for f in "$CONVENTION_DIR"/*.kt "$CONVENTION_DIR"/zed/rainxch/githubstore/convention/*.kt; do
101+
[ -f "$f" ] || continue
102+
# Skip files that define these functions (declarations, not call sites)
103+
grep -q "fun Project.configureAndroidTarget" "$f" && continue
104+
grep -q "fun Project.configureKotlinAndroid" "$f" && continue
105+
sed -i \
106+
-e 's|configureAndroidTarget()|// configureAndroidTarget()|g' \
107+
-e 's|configureKotlinAndroid(this)|// configureKotlinAndroid(this)|g' \
108+
"$f"
109+
done
110+
111+
# ─────────────────────────────────────────────────────────────────────
112+
# 3. KotlinMultiplatform.kt — skip Android configuration
113+
# ─────────────────────────────────────────────────────────────────────
114+
echo "[5/6] Patching KotlinMultiplatform.kt"
115+
cat > "$CONVENTION_DIR/zed/rainxch/githubstore/convention/KotlinMultiplatform.kt" << 'KOTLIN'
116+
package zed.rainxch.githubstore.convention
117+
118+
import org.gradle.api.Project
119+
import org.gradle.kotlin.dsl.configure
120+
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
121+
122+
internal fun Project.configureKotlinMultiplatform() {
123+
// Android target disabled for Flatpak build
124+
configureJvmTarget()
125+
126+
extensions.configure<KotlinMultiplatformExtension> {
127+
compilerOptions {
128+
freeCompilerArgs.add("-Xexpect-actual-classes")
129+
freeCompilerArgs.add("-Xmulti-dollar-interpolation")
130+
freeCompilerArgs.add("-opt-in=kotlin.RequiresOptIn")
131+
freeCompilerArgs.add("-opt-in=kotlin.time.ExperimentalTime")
132+
}
133+
}
134+
}
135+
KOTLIN
136+
137+
# ─────────────────────────────────────────────────────────────────────
138+
# 4. Module build.gradle.kts files — remove android {} blocks
139+
# ─────────────────────────────────────────────────────────────────────
140+
echo "[6/6] Removing android {} blocks from module build.gradle.kts files"
141+
142+
# composeApp — remove android {} block and its contents
143+
python3 -c "
144+
import re, sys
145+
146+
with open('composeApp/build.gradle.kts', 'r') as f:
147+
content = f.read()
148+
149+
# Remove top-level android { ... } blocks (handles nested braces)
150+
def remove_block(text, keyword):
151+
result = []
152+
i = 0
153+
while i < len(text):
154+
# Look for 'android {' at line start (possibly with whitespace)
155+
line_start = text.rfind('\n', 0, i) + 1
156+
prefix = text[line_start:i].strip()
157+
if text[i:].startswith(keyword + ' {') or text[i:].startswith(keyword + '{'):
158+
if prefix == '' or prefix.endswith('\n'):
159+
# Find matching closing brace
160+
brace_start = text.index('{', i)
161+
depth = 1
162+
j = brace_start + 1
163+
while j < len(text) and depth > 0:
164+
if text[j] == '{': depth += 1
165+
elif text[j] == '}': depth -= 1
166+
j += 1
167+
# Skip past the block and any trailing newline
168+
if j < len(text) and text[j] == '\n':
169+
j += 1
170+
i = j
171+
continue
172+
result.append(text[i])
173+
i += 1
174+
return ''.join(result)
175+
176+
content = remove_block(content, 'android')
177+
with open('composeApp/build.gradle.kts', 'w') as f:
178+
f.write(content)
179+
"
180+
181+
# core/data — remove android {} block
182+
for gradle_file in \
183+
core/data/build.gradle.kts \
184+
core/domain/build.gradle.kts \
185+
core/presentation/build.gradle.kts; do
186+
if [ -f "$gradle_file" ]; then
187+
python3 -c "
188+
import sys
189+
with open('$gradle_file', 'r') as f:
190+
lines = f.readlines()
191+
result = []
192+
skip_depth = 0
193+
i = 0
194+
while i < len(lines):
195+
stripped = lines[i].strip()
196+
if stripped.startswith('android {') or stripped == 'android{':
197+
skip_depth = 1
198+
i += 1
199+
while i < len(lines) and skip_depth > 0:
200+
for ch in lines[i]:
201+
if ch == '{': skip_depth += 1
202+
elif ch == '}': skip_depth -= 1
203+
i += 1
204+
continue
205+
result.append(lines[i])
206+
i += 1
207+
with open('$gradle_file', 'w') as f:
208+
f.writelines(result)
209+
"
210+
fi
211+
done
212+
213+
# Remove AndroidApplicationComposeConventionPlugin registration attempt
214+
# (it won't compile without AGP)
215+
cat > "$CONVENTION_DIR/AndroidApplicationComposeConventionPlugin.kt" << 'KOTLIN'
216+
import org.gradle.api.Plugin
217+
import org.gradle.api.Project
218+
219+
class AndroidApplicationComposeConventionPlugin : Plugin<Project> {
220+
override fun apply(target: Project) {
221+
// No-op: Android disabled for Flatpak build
222+
}
223+
}
224+
KOTLIN
225+
226+
cat > "$CONVENTION_DIR/AndroidApplicationConventionPlugin.kt" << 'KOTLIN'
227+
import org.gradle.api.Plugin
228+
import org.gradle.api.Project
229+
230+
class AndroidApplicationConventionPlugin : Plugin<Project> {
231+
override fun apply(target: Project) {
232+
// No-op: Android disabled for Flatpak build
233+
}
234+
}
235+
KOTLIN
236+
237+
echo "=== Android targets disabled successfully ==="

0 commit comments

Comments
 (0)