Android Build-A ./build/envsetup.sh ——> lunch

我們編譯Android源碼的步驟是什么?

全編:

  1. source build/envsetup.sh
  2. lunch 特定的分支
  3. make -j8 2>&1|tee build.log
    單編:
  4. mm frameworks/base/
  5. mmm packages/apps/Settings/

基礎(chǔ)知識(shí):正則霎箍,bash shell

source build/envsetup.sh

source是Linux 內(nèi)部命令琼蚯,這里不多講解沈跨,可以理解為執(zhí)行界斜;我們直接看build/envsetup.sh命令慷彤;

function hmm() {
cat <<EOF
Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
- lunch:   lunch <product_name>-<build_variant>
- tapas:   tapas [<App1> <App2> ...] [arm|x86|mips|armv5|arm64|x86_64|mips64] [eng|userdebug|user]
- croot:   Changes directory to the top of the tree.
- m:       Makes from the top of the tree.
- mm:      Builds all of the modules in the current directory, but not their dependencies.
- mmm:     Builds all of the modules in the supplied directories, but not their dependencies.
           To limit the modules being built use the syntax: mmm dir/:target1,target2.
- mma:     Builds all of the modules in the current directory, and their dependencies.
- mmma:    Builds all of the modules in the supplied directories, and their dependencies.
- cgrep:   Greps on all local C/C++ files.
- ggrep:   Greps on all local Gradle files.
- jgrep:   Greps on all local Java files.
- resgrep: Greps on all local res/*.xml files.
- sgrep:   Greps on all local source files.
- godir:   Go to the directory containing a file.

Look at the source to view more functions. The complete list is:
EOF
    T=$(gettop)
    local A
    A=""
    for i in `cat $T/build/envsetup.sh | sed -n "/^[ \t]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
      A="$A $i"
    done
    echo $A
}
......

文件以function開(kāi)始获搏,function就是一個(gè)方法,cat <<EOP就是把EOF后面到下一個(gè)EOF前面的內(nèi)容當(dāng)做一個(gè)文件輸出到標(biāo)準(zhǔn)輸出如孝。
當(dāng)我們?cè)赟hell 中執(zhí)行source build/envsetup.sh后宪哩,執(zhí)行hmm命令看看,截圖如下:


hmm.png

function也對(duì)應(yīng)于命令第晰,這里暫時(shí)只舉例了一個(gè)锁孟,有需要再列舉;回到我們我們的主線茁瘦,從source build/envsetup.sh開(kāi)始品抽;

1-1:source build/envsetup.sh

source build/envsetup.sh和". build/envsetup.sh"等價(jià),就是執(zhí)行這個(gè)sh腳本腹躁,這個(gè)腳本中全是方法桑包,方法是被調(diào)用的,所以程序肯定從方法外的程序開(kāi)始執(zhí)行:

......
# Clear this variable.  It will be built up again when the vendorsetup.sh
# files are included at the end of this file.
unset LUNCH_MENU_CHOICES
function add_lunch_combo()
{
    local new_combo=$1
    local c
    for c in ${LUNCH_MENU_CHOICES[@]} ; do
        if [ "$new_combo" = "$c" ] ; then
            return
        fi
    done
    LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
}
# add the default one here
add_lunch_combo aosp_arm-eng
add_lunch_combo aosp_arm64-eng
add_lunch_combo aosp_mips-eng
add_lunch_combo aosp_mips64-eng
add_lunch_combo aosp_x86-eng
add_lunch_combo aosp_x86_64-eng
......

unset LUNCH_MENU_CHOICES 刪除LUNCH_MENU_CHOICES纺非,
add_lunch_combo()的功能是向LUNCH_MENU_CHOICES變量中添加元素哑了,
相當(dāng)于初始化LUNCH_MENU_CHOICES;
這里執(zhí)行完成后LUNCH_MENU_CHOICES數(shù)組中就有了上述的元素值烧颖;

# Execute the contents of any vendorsetup.sh files we can find.
for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
         `test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort`
do
    echo "including $f"
    . $f
done
unset f

shell 中反引號(hào)的作用:將反引號(hào)中的內(nèi)容當(dāng)做shell 命令來(lái)執(zhí)行弱左;
反引號(hào)中使用test -d 判斷device目錄是否存在,如果存在則利用find在device中查找vendorsetup.sh腳本炕淮,查找深度為4級(jí)目錄拆火;"2> /dev/null"是重定向等級(jí)為2的輸出到/dev/null,2代表錯(cuò)誤涂圆,即不輸出錯(cuò)誤们镜,sort 是排序; echo "including $f"將找到的文件輸出到標(biāo)準(zhǔn)輸出润歉,". $f"和source $f等價(jià)模狭,即執(zhí)行找到的vendorsetup.sh;

我在項(xiàng)目中執(zhí)行source build/envsetup.sh踩衩,截圖如下:

source.png

上述途中的including 項(xiàng)就是我們找到的vendorsetup.sh嚼鹉,這里我打開(kāi)第一個(gè)device/samsung/manta/vendorsetup.sh腳本:

add_lunch_combo aosp_manta-userdebug

這里只有這一句話,調(diào)用add_lunch_combo 方法驱富,即LUNCH_MENU_CHOICES數(shù)組中添加元素锚赤;上述圖中的vendorsetup.sh 在不同的目錄下,不同的vendorsetup.sh中內(nèi)容還不同褐鸥,比如asus,hts,samsung等线脚,代表不同公司不同項(xiàng)目;add_lunch_combo的參數(shù)由兩部分組成:product-variant,aosp_manta-userdebug代表product=aosp_manta酒贬,variant=userdebug又憨;
所有source build/envsetup.sh腳本執(zhí)行結(jié)束后翠霍,即初始化LUNCH_MENU_CHOICES數(shù)組完成锭吨;接下來(lái)我們一般執(zhí)行l(wèi)unch命令:

lunch

截圖如下:


lunch.png

這里顯示的內(nèi)容就是前面source build/envsetup.sh調(diào)用add_lunch_combo初始化的LUNCH_MENU_CHOICES數(shù)組內(nèi)容;我們看看具體代碼是如何顯示的呢寒匙?

function print_lunch_menu()
{
    local uname=$(uname)
    echo
    echo "You're building on" $uname
    echo
    echo "Lunch menu... pick a combo:"

    local i=1
    local choice
    for choice in ${LUNCH_MENU_CHOICES[@]}
    do
        echo "     $i. $choice"
        i=$(($i+1))
    done

    echo
}

function lunch()
{
    local answer

    if [ "$1" ] ; then
        answer=$1
    else
        print_lunch_menu
        echo -n "Which would you like? [aosp_arm-eng] "
        read answer
    fi

    local selection=
    #這里是判斷answer變量長(zhǎng)度是否為0
    if [ -z "$answer" ]
    then
    #如果長(zhǎng)度為0零如,則 selection=aosp_arm-eng
        selection=aosp_arm-eng
    #這里是通過(guò)echo -n輸出answer值,輸出沒(méi)輸出到屏幕锄弱,而是通過(guò)管道傳遞給grep -q -e "^[0-9][0-9]*$"考蕾,
    #即判斷answer是不是以兩個(gè)數(shù)字開(kāi)頭,是則返回true
    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
    then
    #如果answer的值是否小于等于數(shù)組LUNCH_MENU_CHOICES個(gè)數(shù)
        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
        then
    #如果上述條件都成立会宪,將LUNCH_MENU_CHOICES數(shù)組的answer-1位數(shù)據(jù)賦值給selection
            selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
        fi
    #方括號(hào)中的^表示排除, 也就是不是這些字符的字符此例中的[^\-]表示一個(gè)不是'-'的字符,
    #因?yàn)?-'在方括號(hào)中有表示范圍的意思,所以前面加了'\'來(lái)轉(zhuǎn)義成一個(gè)普通字#符'-',
    #(但在此處轉(zhuǎn)義符'\'多余:此例中'-'明顯不是表示范圍,作者低估了正則引擎的理解能力)
    #全表達(dá)式意思是:字符串開(kāi)頭是一個(gè)不為'-'的字符,后面跟0個(gè)到多個(gè)不為'-'的字符,
    #再后面是一個(gè)'-',再后面又是一個(gè)不為'-'的字符,后面跟0個(gè)到多個(gè)不為'-'的字符肖卧;
    #這里扯了這么多,其實(shí)這里就是期望得到product-varient的形式掸鹅。也就是我們之前
    #使用add_lunch_combo添加的那些字符串的格式塞帐。比如:aosp_arm-eng,
    #product就是aosp_arm,varient就是eng.中間的-是必須的
    elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
    then
        selection=$answer
    fi
    #如果selecetion長(zhǎng)度為0巍沙,則不合法葵姥,輸出提示
    if [ -z "$selection" ]
    then
        echo
        echo "Invalid lunch combo: $answer"
        return 1
    fi

    export TARGET_BUILD_APPS=
    #利用sed替換selection中"-eng,-user,-userdebug"為空,即去掉"-"后面部分
    local product=$(echo -n $selection | sed -e "s/-.*$//")
    #j檢查product是否合法
    check_product $product
    #根據(jù)上面product是否合法繼續(xù)執(zhí)行下面操作句携,如果返回值不等于0就出現(xiàn)問(wèn)題了
    if [ $? -ne 0 ]
    then
        echo
        echo "** Don't have a product spec for: '$product'"
        echo "** Do you have the right repo manifest?"
        product=
    fi
    #利用sed替換selection中product部分榔幸,即去掉"-"前面部分
    local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
    #檢查variant
    check_variant $variant
    #如果返回值不為0就出現(xiàn)問(wèn)題了
    if [ $? -ne 0 ]
    then
        echo
        echo "** Invalid variant: '$variant'"
        echo "** Must be one of ${VARIANT_CHOICES[@]}"
        variant=
    fi

    if [ -z "$product" -o -z "$variant" ]
    then
        echo
        return 1
    fi

    export TARGET_PRODUCT=$product
    export TARGET_BUILD_VARIANT=$variant
    export TARGET_BUILD_TYPE=release

    echo

    set_stuff_for_environment
    printconfig
}

這個(gè)函數(shù)首先判斷有沒(méi)有傳入?yún)?shù),如果傳入了就把值賦給answer這個(gè)變量矮嫉,如果沒(méi)有傳參數(shù)削咆,也就是說(shuō)知識(shí)執(zhí)行了lunch,那么就會(huì)調(diào)用fprint_lunch_menu函數(shù)顯示一份菜單出來(lái)蠢笋,顯示出來(lái)后拨齐,接受用戶的輸入。
fprint_lunch_menu 就是利用for循環(huán)將LUNCH_MENU_CHOICES中的所有值都打印到屏幕上挺尿;接下來(lái)就是校驗(yàn)answer變量奏黑,看看answer是否合法;校驗(yàn)過(guò)程見(jiàn)上述代碼注釋编矾,校驗(yàn)完成就是從answer變量中獲取product值熟史,后去后再調(diào)用check_product檢驗(yàn)product的合法性;

# check to see if the supplied product is one we can build
function check_product()
{
    #獲取源碼跟目錄
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi
        TARGET_PRODUCT=$1 \
        TARGET_BUILD_VARIANT= \
        TARGET_BUILD_TYPE= \
        TARGET_BUILD_APPS= \
        get_build_var TARGET_DEVICE > /dev/null
    # hide successful answers, but allow the errors to show
}

上述代碼會(huì)調(diào)用get_build_var方法窄俏,這里我們可以在shell中執(zhí)行這個(gè)命令看看結(jié)果:輸出了generic蹂匹,具體來(lái)看看代碼;

get_build_var.png
# Get the exact value of a build variable.
function get_build_var()
{
    #獲取源碼跟目錄
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi
    (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
      command make --no-print-directory -f build/core/config.mk dumpvar-$1)
}

get_build_var 很簡(jiǎn)單凹蜈,就是執(zhí)行make --no-print-directory -f build/core/config.mk dumpvar-$1限寞,$1為T(mén)ARGET_DEVICE忍啸,這里傳遞的完整參數(shù)為dumpvar-TARGET_DEVICE,config.mk會(huì)include dumpvar.mk,這個(gè)文件中會(huì)提取我們傳入的dumpvar-TARGET_DEVICE變量中的TARGET_DEVICE履植,然后打印$(TARGET_DEVICE)计雌。

add_lunch_combo添加的字符串的格式為product-variant,檢查完了product接下來(lái)就會(huì)檢查variant玫霎;variant必須是(user userdebug eng)中的一種凿滤;

VARIANT_CHOICES=(user userdebug eng)
# check to see if the supplied variant is valid
function check_variant()
{
    for v in ${VARIANT_CHOICES[@]}
    do
        if [ "$v" = "$1" ]
        then
            return 0
        fi
    done
    return 1
}

各種校驗(yàn)結(jié)束后會(huì)調(diào)用

    #product和variant都不能為空,為空就是有問(wèn)題
    if [ -z "$product" -o -z "$variant" ]
    then
        echo
        return 1
    fi
    export TARGET_PRODUCT=$product
    export TARGET_BUILD_VARIANT=$variant
    export TARGET_BUILD_TYPE=release

    echo
    set_stuff_for_environment
    printconfig

上述代碼就是就前面的product和variant變量賦值給全局變量并且導(dǎo)出為環(huán)境變量庶近。以后的需要用到這幾個(gè)變量就是這里賦值的翁脆;set_stuff_for_environment 函數(shù)還會(huì)設(shè)置一些變量:

function set_stuff_for_environment()
{
    settitle
    set_java_home
    setpaths
    set_sequence_number

    export ANDROID_BUILD_TOP=$(gettop)
    # With this environment variable new GCC can apply colors to warnings/errors
    export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
}

其中set_java_home會(huì)檢查導(dǎo)出JAVA_HOME這個(gè)環(huán)境變量,這個(gè)環(huán)境變量就是JDK所在路徑鼻种,setpaths函數(shù)會(huì)給PATH環(huán)境變量增加編譯Android需要的一些路徑反番。最后lunch調(diào)用了 printconfig函數(shù),這個(gè)函數(shù)打印出了配置信息叉钥。

總結(jié):source build/envsetup.sh會(huì)調(diào)用add_lunch_combo函數(shù)添加編譯信息罢缸,同時(shí)還會(huì)查找/device和/vendor下的vendorsetup.sh文件,查找深度為4級(jí)目錄沼侣,找到后就執(zhí)行它祖能,它里面至少會(huì)有這么一行:add_lunch_combo xxxx,繼續(xù)添加編譯信息。lunch函數(shù)則會(huì)打印出所有的單板信息供你選擇蛾洛,你輸入選擇后养铸,luch命令會(huì)對(duì)你的選擇做一系列檢測(cè),并從中提取出product和varient轧膘,并最終導(dǎo)出這些信息钞螟,供正式編譯的時(shí)候使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谎碍,一起剝皮案震驚了整個(gè)濱河市鳞滨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蟆淀,老刑警劉巖拯啦,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異熔任,居然都是意外死亡褒链,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)疑苔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)甫匹,“玉大人,你說(shuō)我怎么就攤上這事”福” “怎么了抢韭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)恍箭。 經(jīng)常有香客問(wèn)我刻恭,道長(zhǎng),這世上最難降的妖魔是什么季惯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任吠各,我火速辦了婚禮,結(jié)果婚禮上勉抓,老公的妹妹穿的比我還像新娘。我一直安慰自己候学,他們只是感情好藕筋,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著梳码,像睡著了一般隐圾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掰茶,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天暇藏,我揣著相機(jī)與錄音,去河邊找鬼濒蒋。 笑死盐碱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的沪伙。 我是一名探鬼主播瓮顽,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼围橡!你這毒婦竟也來(lái)了暖混?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤翁授,失蹤者是張志新(化名)和其女友劉穎拣播,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體收擦,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贮配,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了炬守。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牧嫉。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酣藻,到底是詐尸還是另有隱情曹洽,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布辽剧,位于F島的核電站送淆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏怕轿。R本人自食惡果不足惜偷崩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撞羽。 院中可真熱鬧阐斜,春花似錦、人聲如沸诀紊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)邻奠。三九已至笤喳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碌宴,已是汗流浹背杀狡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贰镣,地道東北人呜象。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像八孝,于是被迫代替她去往敵國(guó)和親董朝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容