Nexus5 的B2G OS v2.6系统源码编译机制详解

1.前提

    1、我在比对了Nexus5 的B2G OS v2.6系统与Nexus5 的Android4.4.4 系统后,发现B2G系统的编译虽然和Android一样依赖于build/、device/、vendor/,但是其在源码根目录上添加了一些辅助源码下载、编译的脚本(就是下图所示的绿色这些*.sh)。所以它的编译并不是像Android系统编译那样上来直接去执行source build/envsetup.sh 、lunch...什么的(实际上它是靠源码根目录上的几个脚本将原来Android编译命令进行了封装而已)

    2、最好先了解Android编译过程,可参考:https://blog.csdn.net/mr_raptor/article/details/7539978

2.开始分析B2G OS v2.6的编译过程

    既然是编译过程分析,就按顺序来吧。

    最根源还是要从执行./config nexus-5开始,因为我在FireFox OS(B2G)源码获取与Build code的4.1节提到过,下载Nexus5 的B2G源码最先要执行的脚本是config.sh。

    所以分析要从config.sh开始。

2.1 config.sh分析

#!/bin/bash

REPO=${REPO:-./repo}
sync_flags=""

repo_sync() {
	rm -rf .repo/manifest* &&
	$REPO init -u $GITREPO -b $BRANCH -m $1.xml $REPO_INIT_FLAGS &&
	$REPO sync $sync_flags $REPO_SYNC_FLAGS
	ret=$?
	if [ "$GITREPO" = "$GIT_TEMP_REPO" ]; then
		rm -rf $GIT_TEMP_REPO
	fi
	if [ $ret -ne 0 ]; then
		echo Repo sync failed
		exit -1
	fi
}

case `uname` in
"Darwin")
	# Should also work on other BSDs
	CORE_COUNT=`sysctl -n hw.ncpu`
	;;
"Linux")
	CORE_COUNT=`grep processor /proc/cpuinfo | wc -l`
	;;
*)
	echo Unsupported platform: `uname`
	exit -1
esac

GITREPO=${GITREPO:-"git://github.com/mozilla-b2g/b2g-manifest"}
#注意这里我将master修改成了v2.6
BRANCH=${BRANCH:-v2.6}

while [ $# -ge 1 ]; do
	case $1 in
	-d|-l|-f|-n|-c|-q|--force-sync|-j*)
		sync_flags="$sync_flags $1"
		if [ $1 = "-j" ]; then
			shift
			sync_flags+=" $1"
		fi
		shift
		;;
	--help|-h)
		# The main case statement will give a usage message.
		break
		;;
	-*)
		echo "$0: unrecognized option $1" >&2
		exit 1
		;;
	*)
		break
		;;
	esac
done

GIT_TEMP_REPO="tmp_manifest_repo"
if [ -n "$2" ]; then
	GITREPO=$GIT_TEMP_REPO
	rm -rf $GITREPO &&
	git init $GITREPO &&
	cp $2 $GITREPO/$1.xml &&
	cd $GITREPO &&
	git add $1.xml &&
	git commit -m "manifest" &&
	git branch -m $BRANCH &&
	cd ..
fi
#将MAKE_FLAGS、GECKO_OBJDIR、DEVICE_NAME写入.tmp-config
echo MAKE_FLAGS=-j$((CORE_COUNT + 2)) > .tmp-config
echo GECKO_OBJDIR=$PWD/objdir-gecko >> .tmp-config
echo DEVICE_NAME=$1 >> .tmp-config

case "$1" in
"galaxy-s2")
	echo DEVICE=galaxys2 >> .tmp-config &&
	repo_sync $1
	;;

"galaxy-nexus")
	echo DEVICE=maguro >> .tmp-config &&
	repo_sync $1
	;;

"nexus-4")
	echo DEVICE=mako >> .tmp-config &&
	repo_sync nexus-4
	;;

"nexus-4-kk")
	echo DEVICE=mako >> .tmp-config &&
	repo_sync nexus-4-kk
	;;

"nexus-5")
    #config.sh 传入参数为nexus-5,所以将DEVICE=hammerhead写入.tmp-config
	echo DEVICE=hammerhead >> .tmp-config &&
    #调用repo_sync下载nexus-5源码
	repo_sync nexus-5
	;;

"nexus-5-l")
	echo DEVICE=hammerhead >> .tmp-config &&
	repo_sync nexus-5-l
	;;

"nexus-6-l")
	echo DEVICE=shamu >> .tmp-config &&
	echo PRODUCT_NAME=aosp_shamu >> .tmp-config &&
	repo_sync nexus-6-l
	;;

"nexusplayer-l")
	echo DEVICE=fugu >> .tmp-config &&
	echo PRODUCT_NAME=aosp_fugu >> .tmp-config &&
	repo_sync nexusplayer-l
	;;

"nexus-s")
	echo DEVICE=crespo >> .tmp-config &&
	repo_sync $1
	;;

"nexus-s-4g")
	echo DEVICE=crespo4g >> .tmp-config &&
	repo_sync $1
	;;

"otoro"|"unagi"|"keon"|"inari"|"hamachi"|"peak"|"helix"|"wasabi"|"flatfish")
	echo DEVICE=$1 >> .tmp-config &&
	repo_sync $1
	;;

"flame"|"flame-kk"|"flame-l")
	echo PRODUCT_NAME=flame >> .tmp-config &&
	repo_sync $1
	;;

"tarako")
	echo DEVICE=sp6821a_gonk >> .tmp-config &&
	echo PRODUCT_NAME=sp6821a_gonk >> .tmp-config &&
	repo_sync $1
	;;

"dolphin")
	echo DEVICE=scx15_sp7715ga >> .tmp-config &&
	echo PRODUCT_NAME=scx15_sp7715gaplus >> .tmp-config &&
	repo_sync $1
	;;

"dolphin-512")
	echo DEVICE=scx15_sp7715ea >> .tmp-config &&
	echo PRODUCT_NAME=scx15_sp7715eaplus >> .tmp-config &&
	repo_sync $1
	;;

"pandaboard")
	echo DEVICE=panda >> .tmp-config &&
	repo_sync $1
	;;

"vixen")
	echo DEVICE=vixen >> .tmp-config &&
	echo PRODUCT_NAME=vixen >> .tmp-config &&
	repo_sync $1
	;;  

"emulator"|"emulator-jb"|"emulator-kk"|"emulator-l")
	echo DEVICE=generic >> .tmp-config &&
	echo LUNCH=full-eng >> .tmp-config &&
	repo_sync $1
	;;

"emulator-x86"|"emulator-x86-jb"|"emulator-x86-kk"|"emulator-x86-l")
	echo DEVICE=generic_x86 >> .tmp-config &&
	echo LUNCH=full_x86-eng >> .tmp-config &&
	repo_sync $1
	;;

"flo")
	echo DEVICE=flo >> .tmp-config &&
	repo_sync $1
	;;

"rpi")
	echo PRODUCT_NAME=rpi >> .tmp-config &&
	repo_sync $1
	;;

"rpi2b-l")
	echo PRODUCT_NAME=rpi2b >> .tmp-config &&
	repo_sync $1
	;;

"leo-kk")
	echo PRODUCT_NAME=leo >> .tmp-config &&
	repo_sync $1
	;;

# We need aries-l with repo_sync $1 for using manifest symlink for releng stuff
"aries"|"aries-l")
	echo PRODUCT_NAME=aries >> .tmp-config &&
	repo_sync $1
	;;

"fairphone2")
	echo PRODUCT_NAME=FP2 >> .tmp-config &&
	repo_sync $1
	;;

"openc-fr")
	echo DEVICE=zte_p821a10 >> .tmp-config &&
	echo PRODUCT_NAME=zte_openc_fr >> .tmp-config &&
	repo_sync $1
	;;

"openc-ebay")
	echo DEVICE=zte_p821a10 >> .tmp-config &&
	echo PRODUCT_NAME=zte_openc_eu >> .tmp-config &&
	repo_sync $1
	;;

"leo-l"|"scorpion-l"|"sirius-l"|"castor-l"|"castor_windy-l"|"honami-l"|"amami-l"|"tianchi-l"|"flamingo-l"|"eagle-l"|"seagull-l")
	echo PRODUCT_NAME=$1 | sed 's/..$//' >> .tmp-config &&
	repo_sync sony-aosp-l
	;;

"project-tablet")
	echo PRODUCT_NAME=castor_windy >> .tmp-config &&
	repo_sync project-tablet
	;;

"project-tablet-lte")
	echo PRODUCT_NAME=castor >> .tmp-config &&
	repo_sync project-tablet
	;;

*)
	echo "Usage: $0 [-cdflnq] [-j <jobs>] [--force-sync] (device name)"
	echo "Flags are passed through to |./repo sync|."
	echo
	echo Valid devices to configure are:
	echo - galaxy-s2
	echo - galaxy-nexus
	echo - nexus-4
	echo - nexus-4-kk
	echo - nexus-5
	echo - nexus-5-l
	echo - nexus-6-l
	echo - nexusplayer-l
	echo - nexus-s
	echo - nexus-s-4g
	echo - flo "(Nexus 7 2013)"
	echo - otoro
	echo - unagi
	echo - inari
	echo - keon
	echo - peak
	echo - hamachi
	echo - helix
	echo - tarako
	echo - dolphin
	echo - dolphin-512
	echo - pandaboard
	echo - vixen
	echo - fairphone2
	echo - flatfish
	echo - flame
	echo - flame-kk
	echo - flame-l
	echo - openc-fr
	echo - openc-ebay
	echo - "> Raspberry Pi boards"
	echo - rpi "(Revision B)"
	echo - rpi2b-l
	echo - emulator
	echo - emulator-jb
	echo - emulator-kk
	echo - emulator-l
	echo - emulator-x86
	echo - emulator-x86-jb
	echo - emulator-x86-kk
	echo - emulator-x86-l
	echo "> Sony Xperia devices"
	echo - aries "(Z3 Compact KK)"
	echo - aries-l "(Z3 Compact L)"
	echo - leo-kk "(Z3 KK)"
	echo - leo-l "(Z3 L)"
	echo - scorpion-l "(Z3 Tablet Compact L)"
	echo - sirius-l "(Z2 L)"
	echo - castor-l "(Z2 L Tablet LTE/WiFi)"
	echo - castor_windy-l "(Z2 L Tablet WiFi only)"
	echo - honami-l "(Z1 L)"
	echo - amami-l "(Z1 Compact L)"
	echo - tianchi-l "(T2U L)"
	echo - flamingo-l "(E3 L)"
	echo - eagle-l "(M2 L)"
	echo - seagull-l "(T3 L)"
	exit -1
	;;
esac

if [ $? -ne 0 ]; then
	echo Configuration failed
	exit -1
fi
#源码下载完成后会将.tmp-config 转存为.config文件,后面编译时会用到
mv .tmp-config .config

echo Run \|./build.sh\| to start building

    到此,执行./config nexus-5脚本过程中,其自动下载了Nexus-5的v2.6版本的源码,并配置了.config文件供后面编译时使用。

    .config文件内容为下图所示,值得注意的时,如果将源码复制到其他地方编译的话,记得手动把这个GECKO_OBJDIR修改成:新的源码目录+/objdir-gecko,图中GECKO_OBJDIR目录就是我移动硬盘的目录(因为我电脑空间不够用了,想放到移动硬盘编译,但发现出错了,最后发现是这个GECKO_OBJDIR没有跟着改过来的原因...)

        

2.2 build.sh分析

    源码下载好后,要执行./build.sh -j4命令进行编译了,所以下面分析build.sh脚本。

#!/bin/bash

# We want to figure out if we need to re-run the firmware
# extraction routine.  The first time we run build.sh, we
# store the hash of important files.  On subsequent runs,
# we check if the hash is the same as the previous run.
# If the hashes differ, we use a per-device script to redo
# the firmware extraction
#这个函数的意思直接看英文好了

function configure_device() {
    hash_file="$OUT/firmware.hash"

    # Make sure that our assumption that device codenames are unique
    # across vendors is true
    if [ $(ls -d device/*/$DEVICE 2> /dev/null | wc -l) -gt 1 ] ; then
        echo $DEVICE is ambiguous \"$(ls -d device/*/$DEVICE 2> /dev/null)\"
        return 1
    fi

    # Select which blob setup script to use, if any.  We currently
    # assume that $DEVICE maps to the filesystem location, which is true
    # for the devices we support now (oct 2012) that do not require blobs.
    # The emulator uses a $DEVICE of 'emulator' but its device/ directory
    # uses the 'goldfish' name.
    if [ -f device/*/$DEVICE/download-blobs.sh ] ; then
        important_files="device/*/$DEVICE/download-blobs.sh"
        script="cd device/*/$DEVICE && ./download-blobs.sh"
    elif [ -f device/*/$DEVICE/extract-files.sh ] ; then
        important_files="device/*/$DEVICE/extract-files.sh"
        script="cd device/*/$DEVICE && ./extract-files.sh"
    else
        important_files=
        script=
    fi

    # If we have files that are important to look at, we need
    # to check if they've changed
    if [ -n "$important_files" ] ; then
        new_hash=$(cat $important_files | openssl sha1)
        if [ -f "$hash_file" ] ; then
            old_hash=$(cat "$hash_file")
        fi
        if [ "$old_hash" != "$new_hash" ] ; then
            echo Blob setup script has changed, re-running &&
            sh -c "$script" &&
            mkdir -p "$(dirname "$hash_file")" &&
            echo "$new_hash" > "$hash_file"
        fi
    else
        rm -f $hash_file
    fi

    return $?
}

unset CDPATH
#首先执行setup.sh脚本
. setup.sh &&
if [ -f patches/patch.sh ] ; then
    . patches/patch.sh
fi &&
#执行了上面定义的脚本函数
configure_device &&
#执行make 命令进行编译系统
time nice -n19 make $MAKE_FLAGS $@
#根据make的返回值判断编译是否成功,进而返回不同提示信息。
ret=$?
echo -ne \\a
if [ $ret -ne 0 ]; then
	echo
	echo \> Build failed\! \<
	echo
	echo Build with \|./build.sh -j1\| for better messages
	echo If all else fails, use \|rm -rf objdir-gecko\| to clobber gecko and \|rm -rf out\| to clobber everything else.
else
	case "$1" in
	"gecko")
		echo Run \|./build.sh snod\| to update the system image.
		echo Run \|./flash.sh gecko\| to update gecko.
		if echo $DEVICE | grep generic > /dev/null ; then
			echo $(tput setaf 1)$(tput bold)You must update the system image for emulator to pick up the updated gecko.$(tput sgr0)
		fi
		;;
	*)
		if echo $DEVICE | grep generic > /dev/null ; then
			echo Run \|./run-emulator.sh\| to start the emulator
		else
			echo Run \|./flash.sh\| to flash all partitions of your device
		fi
		;;
	esac
	exit 0
fi

exit $ret

在build.sh脚本中,执行了setup.sh脚本,setup.sh脚本内容为:

#!/bin/bash
#执行load-config.sh脚本
. load-config.sh
#输出些变量到环境中
export USE_CCACHE=yes &&
export GECKO_PATH &&
export GAIA_PATH &&
export GAIA_DOMAIN &&
export GAIA_PORT &&
export GAIA_DEBUG &&
export GECKO_OBJDIR &&
export B2G_NOOPT &&
export B2G_DEBUG &&
export MOZ_CHROME_MULTILOCALE &&
export L10NBASEDIR &&
export MOZ_B2G_DSDS &&
#从此进入Android系统的那种编译过程了
. build/envsetup.sh &&
lunch $LUNCH

在setup.sh脚本中,首先执行了load-config.sh脚本,并输出了些变量到编译环境中,最后执行Android系统编译的那些命令,后面编译就和Android系统一样了。load-config.sh脚本内容为:

#!/bin/bash

if [[ ! -n "$B2G_DIR" ]]; then
  B2G_DIR=$(cd `dirname ${BASH_SOURCE[0]}`; pwd)
fi

. "$B2G_DIR/.config"
if [ $? -ne 0 ]; then
        echo Could not load .config. Did you run config.sh?
        exit -1
fi

if [ -f "$B2G_DIR/.userconfig" ]; then
        . "$B2G_DIR/.userconfig"
fi

# Use default Gecko location if it's not provided in config files.
if [ -z $GECKO_PATH ]; then
  GECKO_PATH=$B2G_DIR/gecko
fi

VARIANT=${VARIANT:-eng}
PRODUCT_NAME=${PRODUCT_NAME:-full_${DEVICE}}
DEVICE=${DEVICE:-${PRODUCT_NAME}}
LUNCH=${LUNCH:-${PRODUCT_NAME}-${VARIANT}}
DEVICE_DIR=${DEVICE_DIR:-device/*/$DEVICE}

load-config.sh脚本配置了些变量,控制setup.sh脚本最后的lunch $LUNCH命令。

回到build.sh脚本中,执行time nice -n19 make $MAKE_FLAGS $@,就开始编译了。

2.3 进入像Android系统编译的过程

其实到了setup.sh脚本末端时候,开始执行source build/envsetup.sh和lunch时,就已经进入了像Android系统那样的配置、编译过程了,完全可以参照https://blog.csdn.net/mr_raptor/article/details/7539978所述的过程去分析B2G系统的配置、编译过程了。

为了节省时间,分析到此就可以了,后面和Android完全一样,暂时留个尾巴吧,后面我可能会继续分析。。。

3.开始分析B2G OS v2.6的刷机过程

官网文档中提示,编译完成后直接执行源码根目录下的flash.sh脚本即可。

所以先分析flash.sh脚本。

3.1 flash.sh分析

flash.sh脚本内容如下:(有点长)

#!/bin/bash

. load-config.sh
test -f $DEVICE_DIR/flash.sh && . $DEVICE_DIR/flash.sh

ADB=${ADB:-adb}
FASTBOOT=${FASTBOOT:-fastboot}
HEIMDALL=${HEIMDALL:-heimdall}
VARIANT=${VARIANT:-eng}
FULLFLASH=false

if [ ! -f "`which \"$ADB\"`" ]; then
	ADB=out/host/`uname -s | tr "[[:upper:]]" "[[:lower:]]"`-x86/bin/adb
fi
if [ ! -f "`which \"$FASTBOOT\"`" ]; then
	FASTBOOT=out/host/`uname -s | tr "[[:upper:]]" "[[:lower:]]"`-x86/bin/fastboot
fi

run_adb()
{
	$ADB $ADB_FLAGS $@
}

run_fastboot()
{
	if [ "$1" = "devices" ]; then
		$FASTBOOT $@
	else
		$FASTBOOT $FASTBOOT_FLAGS $@
	fi
	return $?
}

update_time()
{
	if [ `uname` = Darwin ]; then
		OFFSET=`date +%z`
		OFFSET=${OFFSET:0:3}
		TIMEZONE=`date +%Z$OFFSET|tr +- -+`
	else
		TIMEZONE=`date +%Z%:::z|tr +- -+`
	fi
	echo Attempting to set the time on the device
	run_adb wait-for-device &&
	run_adb shell "toolbox date $(date +%s) ||
	               toolbox date -s $(date +%Y%m%d.%H%M%S)" &&
	run_adb shell setprop persist.sys.timezone $TIMEZONE

	has_timekeep=$(run_adb shell ls /system/bin/timekeep | tr -d '\r\n')
	if [ "${has_timekeep}" = "/system/bin/timekeep" ]; then
	        cur_date=$(date +%s)
	        since_epoch=$(run_adb shell cat /sys/class/rtc/rtc0/since_epoch | tr -d '\r\n')
		timeadjust=$(echo "${cur_date}-${since_epoch}" | bc)
		run_adb shell setprop persist.sys.timeadjust ${timeadjust}
		run_adb shell timekeep restore
	fi;
}

fastboot_flash_image()
{
	# $1 = {userdata,boot,system,recovery} the image filename
	# $2 = {userdata,boot,system,recovery} the fastboot partition target
	#    if non specified, then $2 = $1
	PARTITION_FILE=$1
	PARTITION_NAME=$2

	if [ -z "${PARTITION_NAME}" ]; then
		PARTITION_NAME=${PARTITION_FILE}
	fi

	if [ "$DEVICE" == "flatfish" ] && [ "${PARTITION_NAME}" == "userdata" ]; then
		PARTITION_NAME="data"
	fi
	imgpath="out/target/product/$DEVICE/${PARTITION_FILE}.img"
	out="$(run_fastboot flash "${PARTITION_NAME}" "$imgpath" 2>&1)"
	rv="$?"
	echo "$out"

	if [[ "$rv" != "0" ]]; then
		# Print a nice error message if we understand what went wrong.
		if grep -q "too large" <(echo "$out"); then
			echo ""
			echo "Flashing $imgpath failed because the image was too large."
			echo "Try re-flashing after running"
			echo "  \$ rm -rf $(dirname "$imgpath")/data && ./build.sh"
		fi
		return $rv
	fi
}

fastboot_flash_image_if_exists()
{
	if [ -e "out/target/product/$DEVICE/$1.img" ]; then
		fastboot_flash_image $1
	fi
}


flash_fastboot()
{
	local lockedness=$1 project=$2
	case $lockedness in
	"unlock"|"nounlock")
		;;
	*)
		echo "$0: $FUNCNAME: Invalid argument: $lockedness"
		return 1
		;;
	esac
	case $project in
	"system"|"boot"|"userdata"|"cache"|"")
		;;
	*)
		echo "$0: Unrecognized project/partition: $project"
		return 1
		;;
	esac

	delete_single_variant_persist

	case $DEVICE in
	"helix")
		run_adb reboot oem-1
		;;
	"flatfish")
		run_adb reboot boot-fastboot
		;;
	*)
		run_adb reboot bootloader
		;;
	esac

	if ! run_fastboot devices; then
		echo Couldn\'t setup fastboot
		return 1
	fi

	case $lockedness in
	"unlock")
		run_fastboot oem unlock || true
		;;
	esac

	case $project in
	"system" | "boot" | "userdata" | "cache")
		fastboot_flash_image $project &&
		run_fastboot reboot
		;;

	"")
		VERB="erase"
		if [ "$DEVICE" == "hammerhead" ] || [ "$DEVICE" == "mako" ] ||
		[ "$DEVICE" == "flo" ] || [ "$DEVICE" == "fugu" ]; then
			VERB="format"
		fi
		DATA_PART_NAME="userdata"
		if [ "$DEVICE" == "flatfish" ]; then
			DATA_PART_NAME="data"
		fi
		# helix/dolphin don't support erase command in fastboot mode.
		if [ "$DEVICE" != "helix" -a "$DEVICE_NAME" != "dolphin" ]; then
			run_fastboot $VERB cache &&
			run_fastboot $VERB $DATA_PART_NAME
			if [ $? -ne 0 ]; then
				return $?
			fi
		fi
		case ${DEVICE} in
		"aries"|"leo"|"scorpion"|"sirius"|"castor"|"castor_windy"|"honami"|"amami"|"tianchi"|"flamingo"|"eagle"|"seagull")
			fastboot_flash_image recovery FOTAKernel
			;;
		esac
		fastboot_flash_image userdata &&
		fastboot_flash_image_if_exists cache &&
		fastboot_flash_image_if_exists boot &&
		fastboot_flash_image system &&
		run_fastboot reboot &&
		update_time
		;;
	esac
	echo -ne \\a
}

flash_heimdall()
{
	local project=$1
	case $project in
	"system"|"kernel"|"")
		;;
	*)
		echo "$0: Unrecognized project: $project"
		return 1
		;;
	esac

	if [ ! -f "`which \"$HEIMDALL\"`" ]; then
		echo Couldn\'t find heimdall.
		echo Install Heimdall v1.3.1 from http://www.glassechidna.com.au/products/heimdall/
		exit -1
	fi

	delete_single_variant_persist &&
	run_adb reboot download && sleep 8
	if [ $? -ne 0 ]; then
		echo Couldn\'t reboot into download mode. Hope you\'re already in download mode
	fi

	case $project in
	"system")
		$HEIMDALL flash --factoryfs out/target/product/$DEVICE/$project.img
		;;

	"kernel")
		$HEIMDALL flash --kernel device/samsung/$DEVICE/kernel
		;;

	"")
		$HEIMDALL flash --factoryfs out/target/product/$DEVICE/system.img --kernel device/samsung/$DEVICE/kernel &&
		update_time
		;;
	esac

	ret=$?
	echo -ne \\a
	if [ $ret -ne 0 ]; then
		echo Heimdall flashing failed.
		case "`uname`" in
		"Darwin")
			if kextstat | grep com.devguru.driver.Samsung > /dev/null ; then
				echo Kies drivers found.
				echo Uninstall kies completely and restart your system.
			else
				echo Restart your system if you\'ve just installed heimdall.
			fi
			;;
		"Linux")
			echo Make sure you have a line like
			echo SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"04e8\", MODE=\"0666\"
			echo in /etc/udev/rules.d/android.rules
			;;
		esac
		exit -1
	fi

	echo Run \|./flash.sh gaia\| if you wish to install or update gaia.
}

# Delete files in the device's /system/b2g that aren't in
# $GECKO_OBJDIR/dist/b2g.
#
# We do this for general cleanliness, but also because b2g.sh determines
# whether to use DMD by looking for the presence of libdmd.so in /system/b2g.
# If we switch from a DMD to a non-DMD build and then |flash.sh gecko|, we want
# to disable DMD, so we have to delete libdmd.so.
#
# Note that we do not delete *folders* in /system/b2g.  This is intentional,
# because some user data is stored under /system/b2g (e.g. prefs), but it seems
# to be stored only inside directories.
delete_extra_gecko_files_on_device()
{
	files_to_remove="$(cat <(ls "$GECKO_OBJDIR/dist/b2g") <(run_adb shell "ls /system/b2g" | tr -d '\r') | sort | uniq -u)"
	if [[ "$files_to_remove" != "" ]]; then
		# We expect errors from the call to rm below under two circumstances:
		#
		#  - We ask rm to remove a directory (per above, we don't
		#    actually want to remove directories, so rm is doing the
		#    right thing by not removing dirs)
		#
		#  - We ask rm to remove a file which isn't on the device (if
		#    you squint at files_to_remove, you'll see that it will
		#    contain files which are on the host but not on the device;
		#    obviously we can't remove those files from the device).
		for to_remove in $files_to_remove; do
			run_adb shell "rm /system/b2g/$to_remove" > /dev/null
		done
	fi
	return 0
}

delete_single_variant_persist()
{
	run_adb shell 'rm -rf /persist/svoperapps'
}

flash_gecko()
{
	delete_extra_gecko_files_on_device &&
	run_adb push $GECKO_OBJDIR/dist/b2g /system/b2g &&
	return 0
}

flash_gaia()
{
	GAIA_MAKE_FLAGS="ADB=\"$ADB\""
	USER_VARIANTS="user(debug)?"
	# We need to decide where to push the apps here.
	# If the VARIANTS is user or userdebug, send them to /system/b2g.
	# or, we will try to connect the phone and see where Gaia was installed
	# and try not to push to the wrong place.
	if [[ "$VARIANT" =~ $USER_VARIANTS ]]; then
		# Gaia's build takes care of remounting /system for production builds
		echo "Push to /system/b2g ..."
		GAIA_MAKE_FLAGS+=" GAIA_INSTALL_PARENT=/system/b2g"
	else
		echo "Detect GAIA_INSTALL_PARENT ..."
		# This part has been re-implemented in Gaia build script (bug 915484),
		# XXX: Remove this once we no longer support old Gaia branches.
		# Install to /system/b2g if webapps.json does not exist, or
		# points any installed app to /system/b2g.
		run_adb wait-for-device
		if run_adb shell 'cat /data/local/webapps/webapps.json || echo \"basePath\": \"/system\"' | grep -qs '"basePath": "/system' ; then
			echo "Push to /system/b2g ..."
			GAIA_MAKE_FLAGS+=" GAIA_INSTALL_PARENT=/system/b2g"
		else
			echo "Push to /data/local ..."
			GAIA_MAKE_FLAGS+=" GAIA_INSTALL_PARENT=/data/local"
		fi
	fi
	make -C gaia push $GAIA_MAKE_FLAGS

	# For older Gaia without |push| target,
	# run the original |install-gaia| target.
	# XXX: Remove this once we no longer support old Gaia branches.
	if [[ $? -ne 0 ]]; then
		make -C gaia install-gaia $GAIA_MAKE_FLAGS
	fi
	return $?
}

while [ $# -gt 0 ]; do
	case "$1" in
	"-s")
		ADB_FLAGS+="-s $2"
		FASTBOOT_FLAGS+="-s $2"
		shift
		;;
	"-f")
		FULLFLASH=true
		;;
	"-h"|"--help")
		echo "Usage: $0 [-s device] [-f] [project]"
		exit 0
		;;
	"-"*)
		echo "$0: Unrecognized option: $1"
		exit 1
		;;
	*)
		FULLFLASH=true
		PROJECT=$1
		;;
	esac
	shift
done

case "$PROJECT" in
"shallow")
	resp=`run_adb root` || exit $?
	[ "$resp" != "adbd is already running as root" ] && run_adb wait-for-device
	run_adb shell stop b2g &&
	run_adb remount &&
	flash_gecko &&
	flash_gaia &&
	update_time &&
	echo Restarting B2G &&
	run_adb shell start b2g
	exit $?
	;;

"gecko")
	resp=`run_adb root` || exit $?
	[ "$resp" != "adbd is already running as root" ] && run_adb wait-for-device
	run_adb shell stop b2g &&
	run_adb remount &&
	flash_gecko &&
	echo Restarting B2G &&
	run_adb shell start b2g
	exit $?
	;;

"gaia")
	flash_gaia
	exit $?
	;;

"time")
	update_time
	exit $?
	;;
esac

case "$DEVICE" in
"hamachi"|"helix"|"sp6821a_gonk")
	if $FULLFLASH; then
		flash_fastboot nounlock $PROJECT
		exit $?
	else
		run_adb root &&
		run_adb shell stop b2g &&
		run_adb remount &&
		flash_gecko &&
		flash_gaia &&
		update_time &&
		echo Restarting B2G &&
		run_adb shell start b2g
	fi
	exit $?
	;;

"flame"|"otoro"|"unagi"|"keon"|"peak"|"inari"|"wasabi"|"flatfish"|"aries"|"leo"|"scorpion"|"sirius"|"castor"|"castor_windy"|"honami"|"amami"|"tianchi"|"flamingo"|"eagle"|"seagull"|"scx15_sp7715"*|"zte_p821a10")
	flash_fastboot nounlock $PROJECT
	;;

"panda"|"maguro"|"crespo"|"crespo4g"|"mako"|"hammerhead"|"flo"|"shamu"|"FP2"|"fugu")
	flash_fastboot unlock $PROJECT
	;;

"galaxys2")
	flash_heimdall $PROJECT
	;;

*)
	if [[ $(type -t flash_${DEVICE}) = function ]]; then
		flash_${DEVICE} $PROJECT
	else
		echo Unsupported device \"$DEVICE\", can\'t flash
		exit -1
	fi
	;;
esac

猜你喜欢

转载自blog.csdn.net/Xiaoma_Pedro/article/details/81129511