plugins {
    id "ndksamples.android.application"
    id "ndksamples.android.kotlin"
}

android {
    namespace 'com.example.sanitizers'

    defaultConfig {
        applicationId "com.example.sanitizers"
        // If you raise minSdk to 23 or higher, make sure you've read the note
        // below about useLegacyPackaging.
        //
        // Note that the hwasan build type will override this. See the
        // androidComponents stanza below.
        minSdk 21
        versionCode 1
        versionName "1.0"

        // The sanitizers aren't all mutually compatible, so this sample is
        // split into a buildType per sanitizer below. For most of those
        // sanitizers, we support every ABI. The HWASan buildType is the
        // exception, where we want to enable only arm64-v8a.
        //
        // Unfortunately, the convention plugin enables every ABI using
        // defaultConfig.ndk.abiFilters, which apparently overrides anything we
        // do in buildTypes. To be able to control which ABIs get built here
        // using buildTypes, we have to undo the work done by the convention
        // plugin by clearing the defaultConfig abiFilters. Instead, we enable
        // all the ABIs in the debug and release buildTypes below, inherit from
        // those for most of the sanitizers, but then again reset the list for
        // HWASan to enable only arm64-v8a.
        //
        // We could instead change the convention plugin to use buildType
        // instead, but then all the samples that need to disable rv64 would
        // have to do it twice (once for release and once for debug). Since the
        // sanitizers sample is the only one that needs this behavior, I'd
        // rather keep the mess here rather than spread it around.
        ndk {
            abiFilters.clear()
        }
    }

    buildTypes {
        // Now that the defaultConfig abiFilters have been cleared, the
        // buildType abiFilters will actually have an effect. Enable all ABIs,
        // since that's what we want for most of the sanitizers.
        debug {
            ndk {
                abiFilters(
                    "arm64-v8a",
                    "armeabi-v7a",
                    "riscv64",
                    "x86",
                    "x86_64",
                )
            }

            // Allows buildTypes which inherit from debug to match dependencies
            // with the debug buildType.
            matchingFallbacks = ["debug"]
        }

        release {
            ndk {
                abiFilters(
                    "arm64-v8a",
                    "armeabi-v7a",
                    "riscv64",
                    "x86",
                    "x86_64",
                )
            }
        }

        // HWASan for devices starting from Android 14. Does no longer require a special system image.
        // See https://developer.android.com/ndk/guides/hwasan.
        hwasan {
            initWith debug
            debuggable true
            packagingOptions {
                jniLibs {
                    // Needed for wrap.sh.
                    useLegacyPackaging = true
                }
            }
            externalNativeBuild {
                cmake {
                    arguments "-DANDROID_STL=c++_shared", "-DSANITIZE=hwasan"
                }
            }
            ndk {
                // The defaultConfig's abiFilters were cleared above, but then
                // we also populated the debug buildType's abiFilters with all
                // ABIs, which the hwasan buildType inherits. We only want
                // arm64-v8a here.
                abiFilters.clear()
                abiFilters "arm64-v8a"
            }
        }
        asan {
            initWith debug
            debuggable true
            packagingOptions {
                jniLibs {
                    // Without legacy packaging, the Android package manager
                    // will not extract the libraries from the APK, and the app
                    // will instead load them directly from the APK. That saves
                    // space on disk so is generally preferable, but ASan
                    // doesn't work in that configuration, so we need to
                    // opt-out of the new behavior.
                    //
                    // Note that this won't actually do anything to the sample
                    // in its default configuration. The sample uses minSdk 21,
                    // and legacy packaging is the default for all builds below
                    // minSdk 23.
                    useLegacyPackaging true
                }
            }
            externalNativeBuild {
                cmake {
                    arguments "-DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared", "-DSANITIZE=asan"
                }
            }
        }
        ubsan {
            initWith debug
            externalNativeBuild {
                cmake {
                    arguments "-DSANITIZE=ubsan"
                }
            }
        }
    }

    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
        }
    }

    buildFeatures {
        prefab true
        viewBinding true
    }

    androidComponents {
        beforeVariants(selector().withBuildType("hwasan")) { variantBuilder ->
            variantBuilder.minSdk = 34
        }
    }
}

dependencies {
    implementation project(":base")
    implementation libs.appcompat
    implementation libs.material
    implementation libs.androidx.constraintlayout
}
