---
# System prepended metadata

title: build_android.sh

---

## /root/android_4.0.4_dma4412L/build_android.sh
```build_android.sh=
#!/bin/bash

set -e
export CPU_JOB_NUM=`grep -c processor /proc/cpuinfo`

```
## set 指令:

1. set 指令用來修改 shell 環境變數，是 Bash 脚本的重要工具，適當的使用可以增加脚本的安全性和可維護性。

2. set 不加任何選項會列出所有環境變數及 shell 函式

3. set 是 shell 內建的命令，要用 sh -c "help set" 查看輔助說明
:::info
選項說明:
-a 　  標示已修改的變數，以供輸出至環境變數。
-b 　  使被中止的後台程序立刻回報執行狀態。
-e 　  若指令傳回值不等於 0，則立即退出 shell。
-H 　  Shell 可利用"!"加<指令編號>的方式來執行 history 中記錄的指令。
-k 　  指令所給的參數都會被視為此指令的環境變數。
-l 　  記錄 for 迴圈的變數名稱。
-m 　  使用監視模式。
-n 　  不要執行 script，僅查詢語法的問題。
-p 　  啟動優先順序模式。
-P 　  啟動 -P 選項後，執行指令時，會以實際的文件或目錄來取代符號連接。
-t 　  執行完隨後的指令，即退出 shell。
-u 　  當執行時使用到未定義過的變數，則顯示錯誤信息。
-v 　  執行 sccript 前，先將 script 的內容輸出到螢幕上；
-x 　  執行指令前，先顯示該指令及所下的選項。
:::

4. set -e 使shell script只要發生錯誤，就終止執行
:::warning
#!/usr/bin/env bash
set -e

foo
echo bar
:::
```
Result:
    $ bash script.sh
    script.sh:行4: foo: 未找到命令
```

---
## Linux環境變量分類:
一、按照生命週期來分，Linux環境變量可分為兩類：
1. 永久的：需要用戶修改相關的配置文件，該變量會永久生效
2. 臨時的：用戶利用export指令，在當前終端下聲明環境變量，在關閉Shell時會失效

二、按照作用域來分，Linux環境變量可以分為：
1. 系統環境變量：對該系統中所有用戶都有效。
2. 用戶環境變量：只對特定的用戶有效。

![](https://hackmd.io/_uploads/Hkd7kB2Fh.png)

:::danger
EX: 
```shell
vim ~/.bash.profile
export CLASSPATH=./JAVA_HOME/lib;$JAVA_HOME/jre/lib
```
:::
---
## export 指令:
```
export [-fnp][變量名稱]=[變量設置值]
```
1. Linux export 命令用於設置或顯示環境變量。
2. 在 shell 中執行程序時，shell 會提供一組環境變量。
3. export 可新增、修改或刪除環境變量，供後續執行的程序使用。
4. export 的效力僅限於該次登陸操作。
5. 參數說明：

    -f 　代表[變量名稱]中為函數名稱。
    -n 　刪除指定的變量。變量實際上並未刪除，只是不會輸出到後續指令的執行環境中。
    -p 　列出所有的shell賦予程序的環境變量。

:::danger
EX: 
```shell
export MYENV=7 
export -p
```
Result:
:::info
declare -x MYENV=“7“
:::
---
## grep 指令
```
grep [options] pattern [files]
```
* pattern - 表示要查找的字符串或正則表達式。
* files - 表示要查找的文件名，可以同時查找多個文件，如果省略 files 參數，則默認從標準輸入中讀取數據。

1. Linux grep 命令用於查找文件裡符合條件的字符串或正則表達式。

2. grep 指令用於查找內容包含指定的範本樣式的文件，如果發現某文件的內容符合所指定的範本樣式，預設 grep 指令會把含有範本樣式的那一列顯示出來。

3. 若不指定任何文件名稱，或是所給予的文件名為 -，則 grep 指令會從標準輸入設備讀取數據。

4. 常用選項：

    -i 　忽略大小寫進行匹配。
    -v 　反向查找，只打印不匹配的行。
    -n 　顯示匹配行的行號。
    -r 　遞歸查找子目錄中的文件。
    -l 　只打印匹配的文件名。
    -c 　只打印匹配的行數。
    
5. 常用方式為 : 
```
find . -name "*.c" -exec grep -l "欲搜索字串" {} \;
```

參考資料:
>[set 命令](https://dywang.csie.cyut.edu.tw/dywang/linuxProgram/node61.html)
>[set 命令2](https://www.ruanyifeng.com/blog/2017/11/bash-set.html)
>[Linux 使用 find 與 grep 指令搜尋檔案教學與範例](https://officeguide.cc/linux-find-grep-command-search-files-tutorial-examples/)
>[Linux export 命令](https://www.runoob.com/linux/linux-comm-export.html)
>[Linux grep 命令](https://www.runoob.com/linux/linux-comm-grep.html)
>[Linux环境变量总结](https://www.jianshu.com/p/ac2bc0ad3d74)
>[/proc/cpuinfo文件解读](https://www.cnblogs.com/wxxjianchi/p/10522049.html)

```build_android.sh=6
SEC_PRODUCT=smdk4x12
JAVA_HOME=/usr/local/arm/jdk1.6.0_35
ANDROID_JAVA_HOME=$JAVA_HOME
PATH=$JAVA_HOME/bin:$PATH
CLIENT=$(whoami)
```
## $PATH 路徑環境變數
在 Linux 執行指令時，如果只輸入指令名稱，而沒有輸入完整指令路徑，系統會在 $PATH 變數設定的目錄搜尋相關指令。
## whoami 指令
```
whoami [--help][--version]
```
1. Linux whoami命令用於顯示自身用戶名稱，相當於執行"id -un"指令。

2. 參數說明：

    --help 　在線幫助
    --version 　顯示版本信息

參考資料:
>[Linux whoami命令](https://www.runoob.com/linux/linux-comm-whoami.html)
>[設定 $PATH 路徑環境變數](https://www.ltsplus.com/linux/set-path-var)

```build_android.sh=11
TARGET_PRODUCT=full_$SEC_PRODUCT
TARGET_BUILD_VARIANT=eng

ROOT_DIR=$(pwd)
OUT="$ROOT_DIR/out/target/product/$SEC_PRODUCT"

export TARGET_PRODUCT TARGET_BUILD_VARIANT ANDROID_JAVA_HOME PATH JAVA_HOME SEC_PRODUCT CPU_JOB_NUM OUT
if [ $# -lt 1 ]
then
        echo
        echo "Usage: ./build_android.sh [ uboot | kernel | android | all | clean ]"
fi
```
## 預設變數 $0、\$1、\$#、\$@、\$*、\$?

參考資料:
>[自己的 Shell Script 自己寫 - 參數應用](https://ithelp.ithome.com.tw/articles/10225645)
>[第二十四章 Shell Script](https://www.twbsd.org/cht/book/ch24.htm)
>[shell腳本中$0 $1 $# $@ $* $? $$](https://kknews.cc/zh-tw/code/j3mx44l.html)

```build_android.sh=23
BUILD_OPTION=$1

export UBOOT_DIR="$ROOT_DIR/u-boot-dma4412L"
export KERNEL_DIR="$ROOT_DIR/kernel_dma4412L"
OUT_DIR="$ROOT_DIR/out/target/product/$SEC_PRODUCT"

#Modify the below path suitably as per your requirements
export TFTP_DIR=$ROOT_DIR/$SEC_PRODUCT
OUT_HOSTBIN_DIR="$ROOT_DIR/out/host/linux-x86/bin"
OUT_TARGET_APP="$OUT_DIR/obj/PACKAGING/target_files_intermediates/full_smdk4x12-target_files-eng.root/SYSTEM/app"

function check_exit()
{
        if [ $? != 0 ]
        then
                exit $?
        fi
}

function transfer_img()
{
        chmod 666 $1
        check_exit

        echo $1 '->' $TFTP_DIR
        rm -f $TFTP_DIR/$1
        cp $1 $TFTP_DIR
        check_exit
}

function build_uboot()
{
        echo
        echo '[[[[[[[ Build android uboot ]]]]]]]'
        echo

        cd $UBOOT_DIR

        ./build_uboot.sh make

        echo
        transfer_img  u-boot-exynos4412.bin

        cd $ROOT_DIR
        echo
        echo "Uboot Make End "
}

function build_kernel()
{
        echo
        echo '[[[[[[[ Build android kernel ]]]]]]]'
        echo

        cd $KERNEL_DIR

        ./build_kernel.sh

        cd $KERNEL_DIR/arch/arm/boot/

        transfer_img zImage
        cd $ROOT_DIR
        echo "Kernel Make End "
}


function build_android()
{
        echo
        echo '[[[[[[[ Build android platform ]]]]]]]'
        echo

        rm -rf $OUT_DIR/*.zip
        rm -rf $OUT_DIR/*.img
        rm -rf $OUT_DIR/obj/PACKAGING/systemimage_intermediates/*.img
#       rm -rf $OUT_DIR/system/
#       rm -rf $OUT_DIR/root/

        START_TIME=`date +%s`
        echo make -j$CPU_JOB_NUM PRODUCT-full_$SEC_PRODUCT-eng
        echo
        make -j4 PRODUCT-full_$SEC_PRODUCT-eng

        check_exit

        END_TIME=`date +%s`
        let "ELAPSED_TIME=$END_TIME-$START_TIME"
        echo "Total compile time is $ELAPSED_TIME seconds"
}
```

第102行並不會執行echo 之後的make動作
第104行會根據 -eng 的編譯模式選擇欲編譯的資料夾，包含:
* Intended for platform-level debugging
* LOCAL_MODULE_TAGS := eng, debug, user, and/or development
* Installs non-APK modules that have no tags specified
* Installs APKs according to the product definition files, in addition to taggedAPKs
* Sets ro.secure=1
* Sets ro.debuggable=0
* Sets ro.kernel.android.checkjni=1
* adbd is enabled by default



## let 指令
```
let arg [arg ...]
```
* arg - 要執行的表達式

1. let 命令是 BASH 中用於計算的工具，用於執行一個或多個表達式，變量計算中不需要加上 $ 來表示變量。

2. 如果表達式中包含了空格或其他特殊字符，則必須引起來。

:::danger
EX: 
```shell
#!/bin/bash

let a=5+4
let b=9-3 
echo $a $b
```
Result:
:::info
9 6
:::

參考網址:
>PRODUCT-full_smdk4x12-eng -> [android 4.0 编译模式 eng -- > user 时遇到的问题](https://www.cnblogs.com/szsky/articles/3060686.html)
>[build_android.sh 範例程式](https://blog.csdn.net/niepengpeng333/article/details/7046306)
>[Android编译选项eng、user、userdebug的区别](https://www.cnblogs.com/hellokitty2/p/11248975.html)
>[Linux let 命令](https://www.runoob.com/linux/linux-comm-let.html)
>[Android源码编译选项eng、user、userdebug的区别](https://blog.csdn.net/u010783226/article/details/115998499?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-115998499-blog-117776151.235%5Ev38%5Epc_relevant_anti_t3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-115998499-blog-117776151.235%5Ev38%5Epc_relevant_anti_t3&utm_relevant_index=1)
>[Shell Script function 函式](https://shengyu7697.github.io/shell-script-function/)

```build_android.sh=113
function make_uboot_img()
{
        cd $OUT_DIR

        echo
        echo '[[[[[[[ Make ramdisk image for u-boot ]]]]]]]'
        echo

        mkimage -A arm -O linux -T ramdisk -C none -a 0x40800000 -n "ramdisk" -d ramdisk.img ramdisk-uboot.img
        check_exit

        rm -f ramdisk.img

        echo
        cd ../../../..
}

function make_fastboot_img()
{
        echo '[[[[[[[ Make update images for fastboot ]]]]]]]'
        echo

        cd $TFTP_DIR

        echo 'boot.img ->' $OUT_DIR
        $OUT_HOSTBIN_DIR/mkbootimg --kernel zImage --ramdisk ramdisk-uboot.img -o boot.img
        check_exit

        echo 'update.zip ->' $OUT_DIR
        zip -j $TFTP_DIR/update.zip android-info.txt boot.img system.img
        check_exit

        cd ../

        echo
}

function clean_bsp()
{
        echo
        echo '[[[[[[[ Clean android platform ]]]]]]]'
        echo

        echo "  Clean U-boot Source"
        cd $UBOOT_DIR
        ./build_uboot.sh clean
        cd ..

        echo "  Clean Kernel Source"
        cd $KERNEL_DIR
        make clean ARCH=arm
        cd ..

        echo "  Clean Android Source"
        rm -rf out
        rm -rf v8.log

        echo
        echo "Clean Bsp Success !!!"
        echo
}

function transfer_android_img()
{
        cd $OUT_DIR

        transfer_img ramdisk-uboot.img
        transfer_img system.img
        transfer_img android-info.txt

        echo
        cd ../../../..
        echo
}

echo
echo '                Build android for '$SEC_PRODUCT''
echo

echo 'Build android for '$SEC_PRODUCT''
mkdir -p $TFTP_DIR

case "$BUILD_OPTION" in
        uboot)
                build_uboot
                ;;
        kernel)
                build_kernel
                ;;
        android)
                build_android
                transfer_android_img
                make_fastboot_img
                ;;
        all)
                build_uboot
                build_kernel
                build_android
                transfer_android_img
                make_fastboot_img
                ;;
        clean)
                clean_bsp
                ;;

esac

echo ok success !!!

exit 0

```

參考資料:
>mkbootimg.c -> boot_img_hdr5 之 [引導映像標題](https://source.android.com/docs/core/architecture/bootloader/boot-image-header?hl=zh-tw)
>mkbootimg --kernel zImage --ramdisk ramdisk-uboot.img -o boot.img -> [ramdisk.img及boot.img的生成过程](https://blog.csdn.net/zhijianjingling00/article/details/16841683)
>[make -j 資料](https://www.gnu.org/software/make/manual/html_node/Parallel.html)
>[GNU make: should the number of jobs equal the number of CPU cores in a system?](https://stackoverflow.com/questions/2499070/gnu-make-should-the-number-of-jobs-equal-the-number-of-cpu-cores-in-a-system)
>[Parallel make](https://www.oreilly.com/library/view/managing-projects-with/0596006101/ch10.html)