From aa12f73a33f645e021eaf15c270f19a3b18ae3fb Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Thu, 9 May 2024 16:43:23 -0700 Subject: [PATCH] Add an ARCHITECTURE.md. --- ARCHITECTURE.md | 96 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 ++ docs/run-sample.png | Bin 0 -> 18687 bytes 3 files changed, 99 insertions(+) create mode 100644 ARCHITECTURE.md create mode 100644 docs/run-sample.png diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 000000000..be7a21642 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,96 @@ +# Architecture + +This document describes the layout of the samples repository. + +The top level directory is a Gradle project. This directory can be opened in +Android Studio (and that will be the easiest way to work with the samples). + +## Directory structure + +### Samples + +Most subdirectories are the individual sample apps. These can't be opened in +Android Studio individually, as they rely on common code from the top level +project. These subdirectories have their own `build.gradle` (the Groovy DSL) or +`build.gradle.kts` (the Kotlin DSL) files. In Gradle terms these are "projects". +Android Studio calls them "modules". The documentation in this repository will +typically call them "modules". + +Each sample has its own README.md that explains what features it demonstrates, +as well as any unique requirements. + +To run a sample, use the configuration selector in the top panel of Android +Studio to select the sample and then click run. For example, to run the +endless-tunnel sample game: + +![Select and run a sample][docs/run-sample.png] + +#### Build types + +Android Gradle modules have multiple "build types", sometimes called "variants". +For most of the samples, there are only two build types: debug and release. A +few samples, notably the sanitizers sample, have more. To view the build types +for the modules in this repository, in the Android Studio application menu, +select View -> Tool Windows -> Build Variants. A window will open that lets you +select the active variant for each sample. + +### build-logic + +The `build-logic` directory contains Gradle convention plugins used by this +repository. This is where Gradle policy decisions that apply to the whole +repository are made. + +See the README.md in that directory for more details. + +### docs + +Documentation and supporting artifacts for this repository. Yes, for now it's +just images for the READMEs and this doc. + +### gradle/libs.versions.toml + +This is a Gradle [version catalog]. It's the central location that defines the +library and plugin dependencies for each sample. + +The Android Gradle Plugin does not support evaluating version catalog fields in +its DSL, so versions for SDK and NDK tools (`ndkVersion`, `compileSdkVersion`, +`targetSdkVersion`, etc) are all defined by the convention plugins in +[build-logic](#build-logic). + +[version catalog]: https://docs.gradle.org/current/userguide/platforms.html + +### Gradle wrapper + +The `gradlew` and `gradlew.bat` scripts are the Gradle wrappers, macOS/Linux- +and Windows batch-compatible respectively. They will manage the Gradle +installation used by this repository for you, ensuring that the correct versions +and environment are used. These should be used instead of running `gradle` +directly. + +`gradle/wrapper/gradle-wrapper.properties` defines which version of Gradle will +be used. This should rarely be modified manually. Android Studio's Upgrade +Assistant will manage that file and upgrade to whatever version of Gradle it +prefers for that version of Android Studio and Android Gradle. + +### build.gradle and settings.gradle + +The build.gradle (or build.gradle.kts) file is the top level build file. It +doesn't do anything interesting but declares which plugins will be used by the +child modules. Each sample's module has its own build.gradle file that defines +properties of the app. + +The settings.gradle (or settings.gradle.kts) file configures repositories for +fetching dependencies, and declares each app module. + +### Metadata directories + +#### .github + +This directory contains GitHub metadata files, such as GitHub Action workflows +and Issue templates. + +#### .google + +The `packaging.yaml` file in this directory is used by Android Studio to enable +the File -> New -> Import Sample feature. As this repository is a monolithic +sample project, it should not need to be changed. diff --git a/README.md b/README.md index 9de7cd805..756ef5e81 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ This repository contains sample apps that use the [Android NDK]. +For an explanation of the layout of this repository, see +[ARCHITECTURE.md](ARCHITECTURE.md). + ## Build and run 1. Clone the repository diff --git a/docs/run-sample.png b/docs/run-sample.png new file mode 100644 index 0000000000000000000000000000000000000000..5f61ba94d0e87da56cdb74bf84eddf86b11bf84e GIT binary patch literal 18687 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