A-Team-Android_ROM_Builder/README-TECHNICAL.md
2026-08-14 05:12:17 -05:00

29 KiB

A-Team Android ROM Builder — Technical Documentation

1. Purpose

A-Team Android ROM Builder is a Python/GTK 3 application that provides a graphical project-management layer around Android ROM development.

The application is deliberately split into two major areas:

  1. Python application/backend

    • GUI
    • project state
    • configuration loading
    • environment generation
    • profile management
    • terminal integration
    • resource monitoring
    • host management
    • updater handling
  2. Bash/script layer

    • ROM synchronization
    • device setup
    • GApps synchronization
    • ROM building
    • cleaning
    • uploading
    • device-specific patches and setup

This separation is one of the most important architectural characteristics of the project.

The GUI should generally manage what project is being operated on, while scripts determine how the Android source tree is synchronized, modified, built, cleaned, or uploaded.


2. High-Level Architecture

                         gui.py
                           |
             +-------------+-------------+
             |             |             |
             v             v             v
         Project       Configs       UI Managers
             |             |             |
             +-------------+-------------+
                           |
                           v
                    Project.as_environment()
                           |
                           v
                    Script / Action Layer
                           |
              +------------+------------+
              |            |            |
              v            v            v
          sync.sh      build.sh     clean.sh
              |
              v
       device sync scripts
              |
              v
        Android ROM tree

The GUI owns project selections.

The Project object converts those selections and configuration files into an environment that scripts consume.


3. Main Application Entry Point

The primary entry point is:

gui.py

The application initializes GTK, creates the ROMBuilder window, and constructs the application's tabs.

The current interface contains:

1- Build Setup
2- Sync & Setup Device Source
3- Build
Terminal
Resource Monitor
Tools

The exact tab construction is contained in ROMBuilder.


4. Python Backend

The builder/ directory contains the application backend.

Current major modules include:

builder/
├── actions.py
├── button_actions.py
├── config_loader.py
├── device_manager.py
├── hosts_manager.py
├── icon_manager.py
├── launcher_shortcut.py
├── profile_manager.py
├── project.py
├── project_loader.py
├── project_summary.py
├── resource_monitor.py
├── script_runner.py
├── splash.py
├── splash_manager.py
├── terminal.py
├── updater.py
├── updater_overlay.py
└── version.py

The backend is intentionally separated from GTK-specific code wherever practical.


5. Configuration Loader

builder/config_loader.py contains the basic configuration parser.

It reads simple:

KEY=VALUE

files.

Supported behavior includes:

  • Blank lines are ignored
  • Lines beginning with # are comments
  • Lines without = are ignored
  • Values may be surrounded by single or double quotes
  • ~ is expanded to the user's home directory

Example:

DEVICE_CODENAME="milanf"
DEVICE_SOC="sm6375"
ROM_DISPLAY_NAME="LineageOS"

becomes a Python dictionary:

{
    "DEVICE_CODENAME": "milanf",
    "DEVICE_SOC": "sm6375",
    "ROM_DISPLAY_NAME": "LineageOS"
}

This deliberately simple format makes configuration files easy to edit from a terminal or text editor.


6. Device Discovery

Device discovery is handled by:

builder/device_manager.py

The application scans:

configs/devices/

for .conf files.

A device does not need to be hard-coded into the GUI.

This means adding a properly formatted configuration file is the primary mechanism for adding a device.

The device manager reads:

DEVICE_DISPLAY_NAME

for the user-facing device name.

If it is not present, the configuration filename is used as a fallback display name.

The device list is sorted by display name.


7. Adding a New Device

To add a new device, create:

configs/devices/<device_name>.conf

For example:

configs/devices/example.conf

A practical device configuration should define the device identity and the variables required by its scripts.

Example:

DEVICE_CODENAME="example"
DEVICE_DISPLAY_CODENAME="Example"
DEVICE_DISPLAY_NAME="Example Android Device"
DEVICE_KERNEL="5.4"
DEVICE_SOC="smXXXX"
DEVICE_MANUFACTURER="Motorola"
DEVICE_MODEL_NUMBER="XTXXXX"
DEVICE_SYNC_SCRIPT="example-sync.sh"

Important variables

DEVICE_CODENAME

The Android/device-tree codename used by scripts.

Example:

DEVICE_CODENAME="milanf"

DEVICE_DISPLAY_CODENAME

Human-readable short name used in messages.

DEVICE_DISPLAY_CODENAME="Milanf"

DEVICE_DISPLAY_NAME

Name shown in the GUI device selector.

DEVICE_DISPLAY_NAME="Moto G Stylus 5G 2022"

DEVICE_SYNC_SCRIPT

Name of the device-specific synchronization script.

DEVICE_SYNC_SCRIPT="milanf-sync.sh"

The main scripts/sync.sh script uses this value to locate:

scripts/devices_sync/<DEVICE_SYNC_SCRIPT>

Device-specific variables

Any additional variables can be added to the device configuration.

For example:

DEVICE_KERNEL="5.4"
DEVICE_SOC="sm6375"
DEVICE_MANUFACTURER="Motorola"
DEVICE_MODEL_NUMBER="XT2215"

Those values become part of the project environment and can therefore be consumed by Bash scripts.


8. Device Sync Scripts

Device-specific sync scripts live under:

scripts/devices_sync/

A device configuration selects its script with:

DEVICE_SYNC_SCRIPT="example-sync.sh"

The main synchronization flow effectively becomes:

scripts/sync.sh
        |
        +--> load device configuration
        |
        +--> A-Team setup
        |
        +--> determine DEVICE_SYNC_SCRIPT
        |
        +--> cd "$ROM_PATH"
        |
        +--> run scripts/devices_sync/<device-script>

This allows each device to have completely different synchronization or patching requirements without turning the main GUI into a collection of device-specific conditionals.


9. Project Object

builder/project.py contains the Project dataclass.

Important project state includes:

profile_name
host_name
device_name
rom_name
rom_branch
android_version
rom_path
build_variant
build_command
gapps_variant
clean_variant
installer_variant
build_jobs
use_ccache
custom_apn
device_vars
rom_vars
rom_config_path
setup_vars
upload_vars

This object is the central representation of the currently selected project.


10. ROM Path Interpretation

When a ROM source path is selected, Project.set_rom_path() derives:

ROM_BRANCH
ROM_NAME

from the directory structure.

For a path such as:

/home/pizzag/Android/Roms/Lineage/23.2

the project interprets:

ROM_NAME   = Lineage
ROM_BRANCH = 23.2
ROM_PATH   = /home/pizzag/Android/Roms/Lineage/23.2

This is important because the scripts receive these values automatically.


11. ROM Configuration System

There are two supported locations for the ROM configuration.

Application-level default

configs/rom.conf

ROM-local override

<ROM_ROOT>/rom.conf

The loader checks the selected ROM root first.

If:

<ROM_ROOT>/rom.conf

exists, it is loaded.

Otherwise:

configs/rom.conf

is loaded.

This allows a ROM tree to carry its own configuration.

Example

Builder:

A-Team-Android_ROM_Builder/
└── configs/
    └── rom.conf

ROM:

Lineage/
└── 23.2/
    ├── build/
    ├── device/
    ├── vendor/
    └── rom.conf

The second file overrides the builder-level ROM configuration for that project.

Case sensitivity

The loader currently checks for:

rom.conf

in lowercase.

On Linux:

rom.conf
ROM.conf
Rom.conf

are different filenames.

The build-command dropdown may display a human-readable entry such as:

Default --> Rom.conf

but the actual loader filename is:

rom.conf

12. ROM Configuration Variables

The ROM configuration is not restricted to a fixed set of variables.

Example:

M="make"

CCACHE_SIZE="300"

DEFAULT_ROM_BUILD_COMMAND="brunch $DEVICE_CODENAME"

ROM_BUILD_NAME=lineage
ROM_TARGET_RELEASE="bp4a"
ROM_FINAL_LOCATION="~/Desktop/Release_Test"
ROM_BUILD_ZIP_NAME="*-UNOFFICIAL-$DEVICE_CODENAME.zip"
ROM_DISPLAY_NAME="LineageOS"
ROM_VENDOR_NAME=lineage
ROM_MANIFEST="https://github.com/LineageOS/android.git"
ROM_BRANCH_PREFIX="lineage-"
ROM_MAJOR_VERSION="23"
ROM_MINOR_VERSION="2"

Additional variables can be added when scripts require them.


13. Variable Resolution

Project.as_environment() combines several sources of variables.

The environment begins with GUI/project values.

Examples:

DEVICE_NAME
ROM_NAME
ROM_BRANCH
ROM_PATH
ANDROID_VERSION
BUILD_VARIANT
BUILD_COMMAND
GAPPS_VARIANT
CLEAN_VARIANT
INSTALLER_VARIANT
BUILD_JOBS
USE_CCACHE
APN_VARIANT

Then configuration dictionaries are merged:

device_vars
rom_vars
setup_vars
upload_vars

The project then resolves references such as:

$DEVICE_CODENAME
${DEVICE_CODENAME}

Nested variable references are supported through repeated resolution passes.

This allows a ROM configuration to contain:

DEFAULT_ROM_BUILD_COMMAND="brunch $DEVICE_CODENAME"

without requiring Python code to know what the device codename is.


14. Environment Precedence

The environment is constructed approximately in this order:

Base project variables
        |
        v
Device variables
        |
        v
ROM variables
        |
        v
A-Team setup variables
        |
        v
Upload variables
        |
        v
Variable reference resolution

Therefore, configuration values should be named carefully to avoid unintentionally overriding a project variable.


15. Build Commands

The Build tab reads:

configs/rom_build_commands.conf

The current file can contain entries such as:

Default --> Rom.conf
Lineage
Derpfest

Lines beginning with # and blank lines are ignored.

Entries containing:

-->

are treated as display-only entries by the current loader.

Normal entries are converted into a lowercase command value.

The selected command becomes:

BUILD_COMMAND

in the project environment.

This makes it possible to expand the GUI's build command selector without modifying the Build tab itself.


16. Build Execution

The Build button calls the action layer.

The action layer creates a temporary environment shell file containing the current project variables.

Conceptually:

export DEVICE_NAME='milanf'
export ROM_NAME='Lineage'
export ROM_BRANCH='23.2'
export ROM_PATH='/home/pizzag/...'
export ANDROID_VERSION='16'
...

The requested script is then executed.

The build script is:

scripts/build.sh

The GUI therefore does not need to contain the ROM's actual build command logic.


17. Script Execution

builder/script_runner.py provides generic script execution.

It:

  1. Copies the current process environment.
  2. Adds project.as_environment().
  3. Verifies that the script exists.
  4. Executes it with Bash.
  5. Returns the exit status.

The action layer provides another mechanism that is useful when the GUI needs a shell command containing the generated environment.

This architecture allows scripts to remain independently testable.

For example, a script can generally be debugged directly from a terminal after exporting the required variables.


18. Sync Workflow

The main synchronization entry point is:

scripts/sync.sh

It:

  1. Determines the builder root.
  2. Locates the device configuration.
  3. Checks for the A-Team setup marker.
  4. Installs/runs the A-Team addon setup when necessary.
  5. Determines the selected device synchronization script.
  6. Changes to the selected ROM source.
  7. Runs the device-specific synchronization script.

The device setup marker is stored under the ROM tree:

device/A-Team/A-Team-Setup.check

When the marker exists, the main A-Team setup is skipped.

This avoids repeatedly performing setup operations on the same ROM tree.


19. MindTheGapps Synchronization

The GApps script is:

scripts/gapps_sync.sh

The script selects the MindTheGapps branch from ANDROID_VERSION.

The current mapping includes:

Android 16 -> baklava
Android 17 -> cinnamonbun

The destination is:

$ROM_PATH/vendor/gapps

The existing GApps source is removed before cloning the selected branch.

Git LFS assets are then pulled.


20. Build Options

The GUI currently exposes several build-related selections.

Android Version

Current GUI options include:

16
17

The selected value becomes:

ANDROID_VERSION

Build Variant

Current options include:

Userdebug
Eng
User

The internal project values are lowercase equivalents.

GApps Variant

Current options include:

Vanilla
Gapps
Micro-G
Foss

Clean Variant

Current options include:

Full
Lite
None

Installer Variant

Current options include:

Custom A-Team ROM Installer
Default ROM Installer

Build Jobs

The Build Jobs control determines the parallel job count passed into the project.

Ccache

The Ccache checkbox controls:

USE_CCACHE

Custom APN

The Custom APN checkbox controls:

APN_VARIANT

The current project environment represents enabled/disabled boolean selections using the values expected by the existing script layer.


21. Project Profiles

Project profiles are JSON files stored in:

profiles/

A profile can preserve:

profile_name
host_name
device_name
rom_path
android_version
build_variant
build_command
gapps_variant
clean_variant
installer_variant
build_jobs
use_ccache
custom_apn

Profiles are useful for repeatedly building the same device/ROM combination.

A profile does not replace the device or ROM configuration files.

Instead, it stores the user's selected project state and the configuration system is still loaded when the project is used.


22. Build Hosts

Hosts are managed by:

builder/hosts_manager.py

Configuration:

configs/hosts.conf

The format is INI-style.

Example:

[Local]
type=local

[BuildServer]
type=ssh
server_address=192.168.1.100
port=22
user=pizzag
remote_rom_source_path=/home/pizzag/Android
ssh_options=

The host manager builds SSH arguments using:

server_address
user
port
ssh_options

SSH options can contain an identity file and other supported SSH arguments.


23. Remote Build Considerations

Remote builds require more than simply having SSH available.

The remote machine needs:

  • Android build dependencies
  • Git
  • Repo where required
  • Git LFS where required
  • ROM source at the expected location
  • Device/vendor/kernel source as required by the ROM
  • Any external tools required by the scripts

The GUI is the management layer.

It does not automatically install every Android build dependency on a remote machine.


24. Terminal

The Terminal tab creates a VTE terminal and starts:

/bin/bash

This is intentionally independent from the script runner.

It gives the developer a direct shell for:

repo
git
lunch
m
brunch
adb
fastboot
grep
sed
python
bash

and other normal Android development operations.


25. Resource Monitor

The Resource Monitor launches:

btop

when available.

If btop is unavailable, the script checks for:

bpytop

This is useful during large builds because Android compilation can heavily stress CPU, memory, storage, and other system resources.


26. Tools Tab

The Tools tab currently handles application-side utility functions.

Splash Screen

The splash selector loads available splash assets and stores the selected splash.

Desktop Launcher Icon

The icon selector loads available launcher icon choices.

The selected icon is used when creating the application desktop launcher.

Desktop Launcher

The launcher button invokes the launcher creation backend.

Clean ROM

The clean button invokes the ROM cleaning action.

The clean operation itself remains script/backend driven.


27. UI Sizing Variables

UI dimensions are deliberately exposed as constants near the top of gui.py.

Current button width controls include:

SYNC_SETUP_BUTTON_WIDTH
SYNC_GAPPS_BUTTON_WIDTH
BUILD_ROM_BUTTON_WIDTH
LAUNCHER_BUTTON_WIDTH
CLEAN_BUTTON_WIDTH

This means button widths can be adjusted without hunting through individual GTK layout blocks.

Other UI spacing controls include:

BUILD_SETUP_TOP_SPACING
PROJECT_PROFILES_TOP_SPACING
SYNC_SETUP_TOP_SPACING

These provide independent control over vertical spacing in the corresponding UI sections.

This pattern should be followed when adding future UI dimensions.

Instead of hard-coding:

button.set_size_request(140, -1)

prefer:

button.set_size_request(
    BUILD_ROM_BUTTON_WIDTH,
    -1
)

This keeps layout tuning centralized.


28. Updater Architecture

Updater functionality is split between:

builder/updater.py
builder/updater_overlay.py
scripts/updater.sh

The shell updater emits machine-readable progress messages.

For example:

::PROGRESS::1::5
::STATUS::Downloading Update ...

The current updater stages are:

1/5 Downloading Update
2/5 Extracting Update
3/5 Backing Up Current Installation
4/5 Installing Update
5/5 Update Installed Successfully

The GTK overlay consumes these messages and advances its progress bar.

This is preferable to guessing progress from arbitrary terminal output.


29. Adding a New ROM

A ROM does not normally require a new Python module.

The typical process is:

  1. Create or sync the ROM source tree.
  2. Select the ROM source directory in the GUI.
  3. Add or select the appropriate ROM configuration.
  4. Define required variables in rom.conf.
  5. Add a build command entry if desired.
  6. Ensure scripts/build.sh understands the resulting environment.
  7. Add any ROM-specific sync/build scripts where needed.

If the ROM should carry its own settings, place:

rom.conf

at the ROM root.

This is especially useful when multiple ROM trees have different:

  • build commands
  • manifest information
  • branch naming
  • vendor names
  • output locations
  • release naming
  • version values

30. Recommended Device Addition Workflow

When adding a device, use this order:

Step 1 — Device config

Create:

configs/devices/<codename>.conf

Step 2 — Device identity

Define:

DEVICE_CODENAME
DEVICE_DISPLAY_CODENAME
DEVICE_DISPLAY_NAME
DEVICE_MANUFACTURER
DEVICE_MODEL_NUMBER

Step 3 — Device sync script

Create:

scripts/devices_sync/<codename>-sync.sh

Step 4 — Connect the two

Set:

DEVICE_SYNC_SCRIPT="<codename>-sync.sh"

Step 5 — Add device-specific variables

Add only the values actually required by the device's scripts.

Step 6 — Test the sync script directly

Before debugging the GUI, test the shell script with the required environment.

Step 7 — Launch the GUI

The device should automatically appear in the device selector because discovery scans configs/devices/*.conf.


31. Adding a New Build Command

Edit:

configs/rom_build_commands.conf

Add a simple entry:

Lineage

or:

Derpfest

The current GUI turns normal entries into a lowercase command value.

If a display-only/configuration entry is desired:

Default --> Rom.conf

can be used.

After changing this file, restart the application so the Build tab reloads the list.


32. Adding a New Build Variable

If a script needs another value, first determine where the value belongs.

Device-specific

Put it in:

configs/devices/<device>.conf

ROM-specific

Put it in:

configs/rom.conf

or preferably the ROM-local:

<ROM_ROOT>/rom.conf

when the value belongs only to that ROM.

A-Team-wide setup

Put it in:

configs/a_team_setup.conf

Upload-specific

Put it in:

configs/upload_services.conf

Then consume it from Bash:

echo "$MY_VARIABLE"

Avoid modifying Python simply to introduce a variable that is naturally a configuration value.


33. Debugging Configuration

If a configuration value appears to be missing, check in this order:

  1. Is the file present?
  2. Is the filename correct?
  3. Is the filename case correct?
  4. Does the line contain =?
  5. Is the variable name spelled correctly?
  6. Is the selected device correct?
  7. Does the selected ROM contain its own rom.conf?
  8. If it does, is that local file overriding configs/rom.conf?
  9. Does the variable reference another variable that exists?
  10. Does the script receive the environment being expected?

The Project.debug_dump() helper can be useful when inspecting project state.


34. Debugging the Script Layer

Because the project is script-driven, a useful debugging technique is to run the underlying script manually.

For example:

cd /path/to/A-Team-Android_ROM_Builder
bash scripts/sync.sh

or:

bash scripts/build.sh

with the required environment exported.

This isolates Android build problems from GTK problems.

If the script fails directly, changing the GUI usually will not fix the underlying ROM build problem.


35. Debugging the GUI

When modifying gui.py, test in layers.

Syntax

python3 -m py_compile gui.py

Startup

python3 gui.py

UI construction

Verify that all tabs initialize:

Build Setup
Sync & Setup Device Source
Build
Terminal
Resource Monitor
Tools

Action testing

Exercise the changed button or dropdown rather than stopping after startup.

This is particularly important for GTK code because a valid Python file can still fail during widget construction.


36. Adding a New GUI Control

The preferred pattern is:

  1. Add a constant near the other UI constants.
  2. Create the widget.
  3. Apply the constant.
  4. Connect the signal.
  5. Implement the callback.
  6. Keep actual work in the backend/action/script layer.

Example:

MY_BUTTON_WIDTH = 140

Then:

self.my_button = Gtk.Button(
    label="My Action"
)

set_button_width(
    self.my_button,
    MY_BUTTON_WIDTH
)

self.my_button.connect(
    "clicked",
    self.my_action_clicked
)

This is preferable to embedding a large shell workflow directly inside a GTK callback.


37. Why Scripts Should Stay Separate

Android ROM build operations frequently become device- and ROM-specific.

Keeping the logic in:

scripts/

allows:

  • shell testing without GTK
  • easier debugging
  • device-specific scripts
  • ROM-specific behavior
  • reuse outside the GUI
  • simpler Python code
  • easier migration between machines

The GUI should primarily select and prepare the environment.


38. Environment Flow Example

Suppose the user selects:

Device:
Moto G Stylus 5G 2022

ROM:
Lineage

Branch:
23.2

Android:
16

Build Variant:
Userdebug

Jobs:
32

The project state may become conceptually:

DEVICE_NAME=milanf
ROM_NAME=Lineage
ROM_BRANCH=23.2
ANDROID_VERSION=16
BUILD_VARIANT=userdebug
BUILD_JOBS=32

The device configuration then adds values such as:

DEVICE_CODENAME=milanf
DEVICE_SOC=sm6375
DEVICE_MANUFACTURER=Motorola

The ROM configuration adds values such as:

ROM_VENDOR_NAME=lineage
ROM_BRANCH_PREFIX=lineage-
ROM_MAJOR_VERSION=23
ROM_MINOR_VERSION=2

The final environment is what the scripts consume.


39. Design Principles for Future Development

When extending the project, prefer these rules:

Keep GUI and build logic separate

Do not move large Bash workflows into GTK callbacks.

Prefer configuration over hard-coding

If a value changes between devices or ROMs, it probably belongs in a config file.

Prefer device configs over device conditionals

Prefer:

configs/devices/milanf.conf

over:

if device == "milanf":
    ...

Prefer ROM-local rom.conf for ROM-specific behavior

This keeps a ROM's settings with its source tree.

Keep reusable UI dimensions centralized

Add constants rather than hard-coding sizes in multiple places.

Test the actual UI

Python syntax validation is not sufficient for GTK changes.

Test scripts independently

A failing Android build script should be debugged as a script before changing GUI code.


40. Common Failure Areas

Device does not appear

Check:

configs/devices/

and make sure the file ends in:

.conf

Also verify that it is not named one of the configuration files intentionally ignored by the device scanner.

ROM settings seem wrong

Check whether:

<ROM_ROOT>/rom.conf

exists.

If it does, it overrides:

configs/rom.conf

Build command is missing

Check:

configs/rom_build_commands.conf

and restart the application.

Device sync script is missing

Check:

DEVICE_SYNC_SCRIPT

and verify:

scripts/devices_sync/<script>

exists.

Remote host does not appear

The host loader only exposes the Local host or SSH host entries with a non-empty:

server_address

Resource monitor does not start

Install:

btop

or:

bpytop

GApps sync fails

Check:

  • Android version
  • Git
  • Git LFS
  • network access
  • destination ROM path

41. Extending the Architecture

The project is suitable for adding additional managers.

A future feature should generally follow this structure:

GUI
 |
 +--> Backend module
       |
       +--> Project/config data
       |
       +--> Action
             |
             +--> Script

For example, a future kernel configuration feature could be:

gui.py
   |
builder/kernel_manager.py
   |
scripts/kernel_setup.sh

rather than placing the entire kernel setup implementation inside gui.py.


42. Current Configuration Files

The current project contains:

configs/
├── a_team_setup.conf
├── devices/
│   ├── avatrn.conf
│   ├── fogo.conf
│   ├── fogos-1.conf
│   ├── fogos-2.conf
│   ├── genevn.conf
│   ├── milanf.conf
│   ├── mona.conf
│   ├── rtwo-1.conf
│   ├── rtwo-2.conf
│   └── rtwo-3.conf
├── hosts.conf
├── rom.conf
├── rom_build_commands.conf
└── upload_services.conf

This demonstrates the intended extensibility of the configuration system.


43. Current Script Categories

The script layer contains functionality for:

Build
Clean
Device Sync
A-Team Setup
GApps Sync
Updater
Resource Monitoring
Uploading

Device-specific synchronization scripts live separately under:

scripts/devices_sync/

This allows the common synchronization flow to remain stable while individual devices can have different setup requirements.


44. Updater Progress Protocol

Updater status is communicated using dedicated lines.

Status:

::STATUS::Some Status Text

Progress:

::PROGRESS::<current>::<total>

For example:

::PROGRESS::3::5
::STATUS::Backing Up Current Installation ...

The GUI recognizes these messages and updates the updater overlay.

If future updater stages are added, keep this protocol stable.


45. Safe Extension Pattern for Scripts

When adding a script:

  1. Put it under scripts/.
  2. Make it executable where appropriate.
  3. Validate required environment variables.
  4. Fail with a non-zero exit code when an operation fails.
  5. Print useful progress information.
  6. Avoid assuming a specific ROM unless the script is intentionally ROM-specific.
  7. Use $ROM_PATH rather than hard-coded source paths.
  8. Use device configuration variables instead of duplicating device-specific values.

46. Summary

A-Team Android ROM Builder is best understood as a project orchestration layer for Android ROM development.

The most important concepts are:

Device config
      +
ROM config
      +
GUI project selections
      |
      v
Project environment
      |
      v
Bash scripts
      |
      v
Android ROM source tree

The configuration-driven design means developers can add devices, ROMs, build commands, variables, scripts, and hosts without continuously modifying the core GUI.

For new development, preserve that separation.

The GUI should remain the control surface.

The builder/ package should manage application state and actions.

The configs/ directory should describe the environment.

The scripts/ directory should perform the actual ROM-development work.

The ROM-local rom.conf mechanism should be used whenever a ROM needs to carry its own build configuration independently of the application-wide default.