package buildapk import ( "fmt" "os" "path/filepath" ) const ( DefaultSDKRoot = "/opt/android-sdk" DefaultNDKRoot = "/opt/android-ndk" DefaultJavaHome = "/usr/lib/jvm/java-25-openjdk" DefaultAppID = "org.julianfamily.keepassgo" DefaultAPKOut = "build/keepassgo.apk" DefaultVersion = "0.1.0.1" DefaultLdflags = "-X git.julianfamily.org/keepassgo/internal/appui.appVersion=dev" DefaultMinSDK = "28" DefaultTargetSDK = "35" DefaultIconPath = "internal/assets/keepassgo-icon.png" ) type Config struct { SDKRoot string NDKRoot string JavaHome string AppID string APKOut string Version string Ldflags string MinSDK string TargetSDK string IconPath string } func DefaultConfig() Config { return Config{ SDKRoot: DefaultSDKRoot, NDKRoot: DefaultNDKRoot, JavaHome: DefaultJavaHome, AppID: DefaultAppID, APKOut: DefaultAPKOut, Version: DefaultVersion, Ldflags: DefaultLdflags, MinSDK: DefaultMinSDK, TargetSDK: DefaultTargetSDK, IconPath: DefaultIconPath, } } func (c Config) GogioArgs() []string { return []string{ "-target", "android", "-buildmode", "exe", "-appid", c.AppID, "-ldflags", c.Ldflags, "-o", c.APKOut, "-version", c.Version, "-minsdk", c.MinSDK, "-targetsdk", c.TargetSDK, "-icon", c.IconPath, "./cmd/keepassgo", } } func (c Config) Validate() error { if !isExecutable(filepath.Join(c.JavaHome, "bin", "java")) { return fmt.Errorf("JAVA_HOME must point to a JDK 17+ install") } if !isDir(c.SDKRoot) { return fmt.Errorf("ANDROID_SDK_ROOT must point to an Android SDK install") } if !isDir(c.NDKRoot) { return fmt.Errorf("ANDROID_NDK_ROOT must point to an Android NDK install") } if !isExecutable(filepath.Join(c.SDKRoot, "cmdline-tools", "latest", "bin", "sdkmanager")) { return fmt.Errorf("android SDK cmdline-tools are missing") } if !isDir(filepath.Join(c.SDKRoot, "platforms", "android-"+c.TargetSDK)) { return fmt.Errorf("android platform android-%s is missing", c.TargetSDK) } if !isDir(filepath.Join(c.SDKRoot, "build-tools")) { return fmt.Errorf("android build-tools are missing") } if !isFile(c.IconPath) { return fmt.Errorf("android icon asset is missing: %s", c.IconPath) } return nil } func isDir(path string) bool { info, err := os.Stat(path) return err == nil && info.IsDir() } func isExecutable(path string) bool { info, err := os.Stat(path) if err != nil || info.IsDir() { return false } return info.Mode()&0o111 != 0 } func isFile(path string) bool { info, err := os.Stat(path) return err == nil && !info.IsDir() }