diff --git a/.github/workflows/matrix_ci.yml b/.github/workflows/matrix_ci.yml index 00429b4..ca32246 100644 --- a/.github/workflows/matrix_ci.yml +++ b/.github/workflows/matrix_ci.yml @@ -17,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-20.04] + os: [ubuntu-24.04] java-version: [11,15,20] android-api: [31, 33] fail-fast: false @@ -55,7 +55,20 @@ jobs: - name: Run vab --help run: vab --help - - name: Run vab doctor + - name: Run 'vab doctor' before install + run: vab doctor + + # It is a Sisyphus task to get all combinations of the pre-installed SDK / tools and Java working + # so we simply remove the system install and use our own minimal base-setup via 'vab install auto'... + - name: Setup predictable Android environment + run: | + sudo rm -fr /usr/local/lib/android # location of pre-installed SDK on Ubuntu + unset ANDROID_SDK_ROOT # These are set in the CI by default + unset ANDROID_HOME + unset ANDROID_NDK_ROOT + vab install auto + + - name: Run 'vab doctor' after install run: vab doctor - name: Run tests @@ -70,12 +83,11 @@ jobs: - name: Run vab install build-tools run: vab install "build-tools;29.0.0" - - name: Run vab doctor2 + - name: Run 'vab doctor' after build-tools install run: vab doctor - name: Build examples as APK + AAB (Java ${{ matrix.java-version }}) ${{ matrix.android-api }} run: | - declare -a v_examples=('flappylearning' '2048' 'fireworks' 'tetris' 'sokol/particles' 'sokol/drawing.v' 'sokol/freetype_raven.v' 'gg/polygons.v' 'gg/raven_text_rendering.v' 'gg/rectangles.v' 'gg/stars.v' 'gg/worker_thread.v') for example in "${v_examples[@]}"; do @@ -101,13 +113,13 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-20.04] + os: [ubuntu-24.04] java-version: [11, 15, 20] android-api: [31, 33] fail-fast: false timeout-minutes: 20 env: - VAB_FLAGS: -v 3 -gc none --build-tools 29.0.0 + VAB_FLAGS: -v 3 -gc none steps: - uses: actions/setup-java@v4 with: @@ -166,13 +178,13 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-20.04] + os: [ubuntu-24.04] java-version: [8] # 9, 10 is in a bad state currently android-api: [31, 33] fail-fast: false timeout-minutes: 20 env: - VAB_FLAGS: -v 3 --build-tools 29.0.0 + VAB_FLAGS: -v 3 steps: - uses: actions/setup-java@v4 with: @@ -208,7 +220,7 @@ jobs: run: | sudo rm -fr /usr/local/lib/android - - name: Run 'vab doctor' + - name: Run 'vab doctor' before install run: vab doctor - name: Run 'vab install auto' @@ -218,7 +230,7 @@ jobs: unset ANDROID_NDK_ROOT vab install auto - - name: Run vab doctor + - name: Run 'vab doctor' after install run: vab doctor - name: Run tests diff --git a/android/env/env.v b/android/env/env.v index fa2ab8a..62a804d 100644 --- a/android/env/env.v +++ b/android/env/env.v @@ -24,6 +24,7 @@ pub const accepted_components = ['auto', 'cmdline-tools', 'platform-tools', 'ndk // build-tools - Version where apksigner is included from @[deprecated: 'use get_default_components() instead'] +@[deprecated_after: '2027-01-01'] pub const default_components = { 'cmdline-tools': { 'name': 'cmdline-tools' @@ -154,6 +155,9 @@ pub fn (io &InstallOptions) verbose(verbosity_level int, msg string) { } } +// managable returns `true` if the host system's SDK can be managed by `vab`. +@[deprecated: 'use "is_manageable() or { false }" instead'] +@[deprecated_after: '2027-07-20'] pub fn managable() bool { sdk_is_writable := os.is_writable(sdk.root()) // sdkmanager checks @@ -199,7 +203,55 @@ pub fn managable() bool { return sdk_is_writable && has_sdkmanager && sdkmanger_works } +// is_manageable returns `true` if the host system's SDK can be managed by `vab`, an error with +// details is returned otherwise. +pub fn is_manageable() !bool { + if !os.is_writable(sdk.root()) { + return error('No permission to write in Android SDK root. Please install manually or ensure write access to "${sdk.root()}".') + } + + // sdkmanager checks + sdkm := sdkmanager() + if sdkm == '' { + return error('An executable `sdkmanager` seems to be missing.') + } + // We have detected `sdkmanager` - but does it work with the Java version? *sigh* + // Android development will let us find out I guess: + cmd := [ + sdkm, + '--list', + ] + mut cmd_res := util.run(cmd) + if cmd_res.exit_code > 0 { + // Failed let's try a workaround from stackoverflow: + // https://stackoverflow.com/a/51644855/1904615 + if 'windows' == os.user_os() { + util.run([ + 'set JAVA_OPTS=-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee', + ]) + util.run([ + 'set JAVA_OPTS=-XX:+IgnoreUnrecognizedVMOptions --add-modules java.xml.bind', + ]) + } else { + util.run([ + "export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee'", + ]) + util.run([ + "export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.xml.bind'", + ]) + } + // Let try again + cmd_res = util.run(cmd) + if cmd_res.exit_code != 0 { + return error('The detected `sdkmanager` seems outdated or incompatible with the Java version used. Manual intervention is needed.\nPath: "${sdkmanager()}"\nVersion: ${sdkmanager_version()}\nOutput: ${cmd_res.output}') + } + // Give up trying to fix this horrible eco-system + } + return true +} + @[deprecated: 'use install_components instead'] +@[deprecated_after: '2027-01-01'] pub fn install(components string, verbosity int) int { mut iopts := []InstallOptions{} mut ensure_sdk := true @@ -500,16 +552,9 @@ pub fn install_components(arguments []string, verbosity int) ! { fn install_opt(opt InstallOptions) !bool { loose := opt.dep == .bundletool || opt.dep == .aapt2 - if !loose && !managable() { - if !os.is_writable(sdk.root()) { - return error(@MOD + '.' + @FN + ' ' + - 'No permission to write in Android SDK root. Please install manually or ensure write access to "${sdk.root()}".') - } else { - return error(@MOD + '.' + @FN + ' ' + - 'The `sdkmanager` seems outdated or incompatible with the Java version used". Please fix your setup manually.\nPath: "${sdkmanager()}"\nVersion: ${sdkmanager_version()}') - } + if !loose { + is_manageable()! } - // Accept all SDK licenses $if windows { os.mkdir_all(work_path) or {} diff --git a/cli/cli.v b/cli/cli.v index 1ab59c8..360d12f 100644 --- a/cli/cli.v +++ b/cli/cli.v @@ -111,6 +111,7 @@ pub fn input_from_args(arguments []string) (string, []string) { // args_to_options returns an `Option` merged from (CLI/Shell) `arguments` using `defaults` as // values where no value can be obtained from `arguments`. @[deprecated: 'use options_from_arguments and run_vab_sub_command instead'] +@[deprecated_after: '2027-01-01'] pub fn args_to_options(arguments []string, defaults Options) !(Options, &flag.FlagParser) { mut args := arguments.clone() diff --git a/cli/doctor.v b/cli/doctor.v index 35ea4c0..1b60aca 100644 --- a/cli/doctor.v +++ b/cli/doctor.v @@ -14,7 +14,16 @@ import vab.android.env // diagnosticing the work environment. pub fn doctor(opt Options) { sdkm := env.sdkmanager() - env_managable := env.managable() + env_managable := env.is_manageable() or { + util.vab_notice('${err.msg()}', + details: 'For `${exe_short_name}` to control it\'s own dependencies, please update `sdkmanager` found in: +"${sdkm}" +or use a Java version that is compatible with your `sdkmanager`. +You can set the `SDKMANAGER` env variable or try your luck with `${exe_short_name} install auto`. +See https://stackoverflow.com/a/61176718/1904615 for more help.\n' + ) + false + } env_vars := os.environ() // Validate Android `sdkmanager` tool @@ -31,23 +40,6 @@ pub fn doctor(opt Options) { See https://stackoverflow.com/a/61176718/1904615 for more help.\n' } util.vab_notice('No "sdkmanager" could be detected.', details) - } else { - if !env_managable { - sdk_is_writable := os.is_writable(sdk.root()) - if !sdk_is_writable { - util.vab_notice('The SDK at "${sdk.root()}" is not writable.', - details: "`${exe_short_name}` is not able to control the SDK and it's dependencies." - ) - } else { - util.vab_notice('The detected `sdkmanager` seems outdated or incompatible with the Java version used.', - details: 'For `${exe_short_name}` to control it\'s own dependencies, please update `sdkmanager` found in: -"${sdkm}" -or use a Java version that is compatible with your `sdkmanager`. -You can set the `SDKMANAGER` env variable or try your luck with `${exe_short_name} install auto`. -See https://stackoverflow.com/a/61176718/1904615 for more help.\n' - ) - } - } } avdmanager := env.avdmanager() diff --git a/cli/options.v b/cli/options.v index 19e0da5..d9df70b 100644 --- a/cli/options.v +++ b/cli/options.v @@ -428,6 +428,7 @@ fn (mut o Options) merge_additional_args(default_additional_args []string) { // extend_from_dot_vab will merge the `Options` with any content // found in any `.vab` config files. @[deprecated: 'use options_from_dot_vab instead'] +@[deprecated_after: '2027-01-01'] pub fn (mut opt Options) extend_from_dot_vab() { // Look up values in input .vab file next to input if no flags or defaults was set dot_vab_file := dot_vab_path(opt.input) diff --git a/tests/at-runtime/emulator/emulator_test.vv b/tests/at-runtime/emulator/emulator_test.vv index c2b36c1..0772c71 100644 --- a/tests/at-runtime/emulator/emulator_test.vv +++ b/tests/at-runtime/emulator/emulator_test.vv @@ -26,7 +26,7 @@ const test_v_examples = [ 'gg/worker_thread.v', ] -const env_is_managable = env.managable() +const env_is_manageable = env.is_manageable() or { false } const is_ci = os.getenv('CI') != '' @@ -77,7 +77,7 @@ fn ensure_env() { os.unsetenv('ANDROID_SERIAL') if !env.has_emulator() { - assert env_is_managable == true, 'These tests requires a *writable* SDK' + assert env_is_manageable == true, 'These tests requires a *writable* SDK' eprintln('No emulator detected. Installing...') install_emulator_res := run([vab_exe, 'install', 'emulator']) if install_emulator_res.exit_code != 0 {