/docker-lineageos

A more automated Docker-based build environment for LineageOS

Primary LanguageShellMIT LicenseMIT

docker-lineageos

Docker Stars Docker Pulls

Docker container for building LineageOS (formerly known as CyanogenMod).

TLDR

Note: Remember that LineageOS is a huge project. It will consume a large amount of disk space (~80 GB).

# pass required env variables
$ docker run --rm --privileged \
  -v "$(pwd)/android":/home/lineageos \
  -e GIT_USER_NAME=jfloff \
  -e GIT_USER_EMAIL=jfloff@inesc-id.pt \
  -e DEVICE_CODENAME=klte \
  -ti jfloff/lineageos lineageos init build

# or pass a custom .env file
$ docker run --rm --privileged \
  -v "$(pwd)/android":/home/lineageos \
  --env-file custom.env
  -ti jfloff/lineageos lineageos init build

Why?

Existing Docker images only provide a container with all the dependencies installed, and still require the user the manually input most build commands. There have been some attempts to have a more automated based on scripts, but they lack flexibility when building the repository (for example, they expect you to input the devices' proprietary blobs in between steps). On top of these issues, most of the repos use Ubuntu as their base image (which is known for being a large base image) and do not follow the Dockerfile recommendations (unoptimized layer caching).

We strive for more automation. Our goal is for users to be able to compile LineageOS for a specific device with single docker run command. Let's go over what was done in this image.

Usage

The main working directory is a shared folder on the host system, so the Docker container can be removed at any time and used just to build. For example, -v "$(pwd)/android":/home/lineageos: here we are mounting the android directory into the $BASE_DIR directory which by default is /home/lineageos.

Next, we have to set the device we want to build through an env variable, for example -e DEVICE_CODENAME=klte. This will also trigger the default configuration for that device (if a configuration available in the device-config folder).

Finally we also have to set our git user information, for example -e GIT_USER_NAME=jfloff -e GIT_USER_EMAIL=jfloff@inesc-id.pt.

This should be the minimium working example for this image. Note however that klte device has a configuration available in the device-config.

$ docker run --rm --privileged \
  -v "$(pwd)/android":/home/lineageos \
  -e GIT_USER_NAME=jfloff \
  -e GIT_USER_EMAIL=jfloff@inesc-id.pt \
  -e DEVICE_CODENAME=klte \
  -ti jfloff/lineageos lineageos init build

Instead of settings multiple env variables, you can also pass an env-file (as per docker run reference).

$ docker run --rm --privileged \
  -v "$(pwd)/android":/home/lineageos \
  --env-file custom.env
  -ti jfloff/lineageos lineageos init build

Note that we ran lineageos init build which is our custom script that is used to help init, sync and build LineageOS from within the container. Check lineageos script details below.

If your device doesn't have an env configuration available in the device-config folder, you have to build a custom device configuration. We show how you build your own configuration below.

Here is a list of devices that have configuration files available (check device-config folder):

  • klte
  • kltevzw
  • bacon (thanks @GRBurst)
  • mako (thanks @brainstorm)
  • cancro (thanks Oguz Ersen - via email)

Feel free to open a PR to submit another device configuration.

lineageos script

Inside the container there is script, called lineageos, that's used to automate most of the commands needed to init, sync and build LineageOS. Let's go go over each option:

  • -c|--clean: Removes all the repo files (cache included)
  • i|init: Initializes the repository making it ready to build LineageOS. In this step we init the repo and sync it. We also download the device's proprietary blobs, the user's extra files, and enable caching.
  • b|build: Builds LineageOS!
  • s|sync: Forces sync of the LineageOS repo sync and (if set) of the device's proprietary blobs repo
  • all: Shortcut for performing lineageos init build

Remember you can compose multiple instructions, for example, for a completly clean build you can run lineageos all --clean (or lineageos -c init build).

Building a custom device configuration

A device configuration is a simple file with several env variables set (you can also pass these variables directly to docker run). All the magic happens underneath.

NOTE: Any env variables you pass as will overwrite the default configurations (from the default.env file), and the pre-existing device-specific configuration files from the device-config folder. I.e., the precedence order looks something like this: custom env > device-config-file.env > default.env

Here is a rundown of all the variables that you can set.

Variable Description Type Default
GIT_USER_NAME Username for git.
Example: João Loff
Required
GIT_USER_EMAIL User email for git.
Example: jfloff@inesc-id.pt
Required
DEVICE_CODENAME Device's codename (see more).
Example: klte
Required
BASE_DIR Directory where host volume with LineageOS was mounted optional /home/$USER
LINEAGEOS_REPO LineageOS repository optional https://github.com/LineageOS/android.git
LINEAGEOS_BRANCH LineageOS Branch. optional cm-14.1
LINEAGEOS_LOCAL_MANIFEST_REPO LineageOS local manifest repository. optional
LINEAGEOS_LOCAL_MANIFEST_BRANCH LineageOS local manifest branch. optional
PROPRIETARY_BLOBS_REPO Repo with the device's proprietary blobs.
Example: https://github.com/TheMuppets/proprietary_vendor_samsung 
 optional
PROPRIETARY_BLOBS_DIR Directory to where the repo with the device's blobs will be cloned to.
Example: $BASE_DIR/vendor/samsung
optional
USE_CCACHE Turn on caching to speed up build (see more) optional 1
CCACHE_SIZE Maximum amount of cache disk space allowed optional 50G
CCACHE_COMPRESS Enable the ccache compression optional 1
CCACHE_DIR Directory used for caching optional $BASE_DIR/cache
ANDROID_JACK_VM_ARGS Fixes out-of-memory error for Jack compiler. Increase the assigned memory if necessary optional "-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4G"
WITH_SU Builds rom with root access optional false
PRE_SYNC_SCRIPT Path to script to run before sync.
Example: /home/scripts/pre_sync.sh
optional
PRE_BUILD_SCRIPT Path to script to run before build.
Example: /home/scripts/pre_build.sh
optional
POST_BUILD_SCRIPT Path to script to run after build.
Example: /home/scripts/post_build.sh
optional

You can pass any other env variable that you need, or just do some scripting. It's that flexible!

You also have a template-like env variable with the following format EXTRA_DOWNLOAD_<ID> that you can use to download extra files before you build. This template can be useful to download some files like the device's proprietary blobs that were obtain from the device itself (you can place those files in a link somewhere, and the script will download them), or just overall missing files while building.

These variables have to use the following template EXTRA_DOWNLOAD_<ID>=("<URL>" "<TARGET_PATH>"), where URL is the url where the file is located and will be downloaded from (using curl), and <TARGET_PATH> is the folder (inside the container) to which the file will be downloaded to.

For example, the following env will download the file msm8974pro_sec_klte_vzw_defconfig to kernel/samsung/klte/arch/arm/configs/:

EXTRA_DOWNLOAD_1=(
    'https://raw.githubusercontent.com/badowl/android_kernel_samsung_klte/cm-14.1/arch/arm/configs/msm8974pro_sec_klte_vzw_defconfig'
    'kernel/samsung/klte/arch/arm/configs/msm8974pro_sec_klte_vzw_defconfig'
)

License

MIT (see LICENSE)