build/envsetup.sh概要

43201 ワード

  • build/envsetup.sh
  • 命令--envsetup.shの関数概要
  • source build/envsetup.sh実行フロー
  • build/envsetup.sh常用関数の紹介
  • lunchフロー
  • _lunch関数
  • gettop
  • hmm
  • mm
  • mmm
  • godir
  • sgrep


  • build/envsetupについて何編も見ました.shの紹介、メモのまとめ
    build/envsetup.sh
    コンパイルを開始するたびに最初のコマンドはsource build/envsetupです.sh、sourceコマンドはshellスクリプトコマンドを実行するために使用され、機能は「」に等しい.したがって、この命令も等価である.build/envsetup.sh.ファイルでshは、現在のセッション端末が利用可能なコマンドを宣言し、ここで注意しなければならないのは、現在のセッション端末であり、すなわち、新しい端末を開くたびに、これらのコマンドをもう一度実行しなければならないことを意味する.build/envsetup.shファイルが存在する意味は,いくつかの環境変数とshell関数を設定して後続のコンパイル作業に備えることである.次にenvsetupを分析します.sh.
    コマンド--envsetup.shの関数の概要
    envsetupをインポートします.shシステムはすべていくつかの命令を出して、先に命令の作用を見ます
    よく使うコマンド
    コンパイル命令
    説明する
    mm
    現在のパスの下にあるすべてのモジュールをコンパイルしますが、依存は含まれません.
    mmm [module_path]
    指定したパスの下にあるすべてのモジュールをコンパイルしますが、依存は含まれません.
    mma
    現在のパスの下にあるすべてのモジュールをコンパイルし、依存を含む
    mmma [module_path]
    指定したパスの下にあるすべてのモジュールをコンパイルし、依存を含む
    make [module_name]
    パラメータなしでAndroidコード全体をコンパイルする
    cgrep
    現在のディレクトリの下にあるすべてのC/C++ファイルの検索操作
    jgrep
    現在のディレクトリの下にあるすべてのJavaファイルの検索操作
    ggrep
    現在のディレクトリの下にあるすべてのGradleファイルの検索操作
    mangrep [keyword]
    現在のディレクトリの下にあるすべてのAndroidManifest.xmlファイル実行検索操作
    mgrep [keyword]
    現在のディレクトリの下にあるすべてのAndroid.mkファイル実行検索操作
    sepgrep [keyword]
    すべてのsepolicyファイルで検索操作を実行
    resgrep [keyword]
    現在のディレクトリの下にあるすべてのローカルres/*xmlファイル実行検索操作
    sgrep [keyword]
    現在のディレクトリの下で(c
    croot
    Androidルートディレクトリに切り替え
    cproj
    プロジェクトのルートディレクトリに切り替え
    godir [filename]
    ファイルを含むディレクトリに移動
    hmm
    すべての命令help情報をクエリー
    Tips:Androidソースコードは非常に膨大で、grepを直接採用してコードを検索するのは、方法が不器用で時間を浪費するだけでなく、無意味な混同結果を多く検索します.具体的なニーズに応じて、適切なコード検索命令を選択し、コード検索時間を節約し、検索結果の精度を高め、目標コードの位置決めを便利にすることができる.godir[filename]は最初の実行速度が遅く、その後findコマンドよりも動作効率が高い(詳細は後述)
  • その他の命令make clean:rm-rf out/make update-apiに等しいクリーンアップ操作を実行する:APIを更新し、framework APIが変更された後にこの命令を実行する必要があり、Apiはディレクトリframeworks/base/api
  • に記録する
    source build/envsetup.sh実行フロー
    envsetup.shは多くの関数を定義し、それ以外にも他の操作を実行し、以下は関数部分を除去するコードである.
    VARIANT_CHOICES=(user userdebug eng)#     3     ,     
    
    # Clear this variable.  It will be built up again when the vendorsetup.sh
    # files are included at the end of this file.
    #LUNCH_MENU_CHOICES       prodcut  ,
    #  source build/envsetup.sh      LUNCH_MENU_CHOICES
    #     include vendor/cm/vendorsetup.sh           LUNCH_MENU_CHOICES ,
    #          
    unset LUNCH_MENU_CHOICES   
    
    #        LUNCH_MENU_CHOICES     ,           ,         ,         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)
    }
    
    
    
     #       6     
    # 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 
    
    #         lunch _lunch  ,          _lunch    lunch         
    complete -F _lunch lunch 
    
    #shell     ,     bash,      shell     WARNING
    if [ "x$SHELL" != "x/bin/bash" ]; then
        case `ps -o command -p $$` in
            *bash*)
                ;;
            *)
                echo "WARNING: Only bash is supported, use of other shell would lead to erroneous results"
                ;;
        esac
    fi
    
    # Execute the contents of any vendorsetup.sh files we can find.
    #source vendor device       vendorsetup.sh
    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
    
    addcompletions
    

    最後にaddcompletionsが何をしたか見てみましょう
    function addcompletions()
    {
        local T dir f
    
        # Keep us from trying to run in something that isn't bash.
        if [ -z "${BASH_VERSION}" ]; then
            return
        fi
    
        # Keep us from trying to run in bash that's too old.
        if [ ${BASH_VERSINFO[0]} -lt 3 ]; then
            return
        fi
    
        dir="sdk/bash_completion"
        if [ -d ${dir} ]; then
            for f in `/bin/ls ${dir}/[a-z]*.bash 2> /dev/null`; do
                echo "including $f"
                . $f
            done
        fi
    }

    BASHのバージョンが空または3未満の場合は、android/sdk/bash_を印刷します.completion/ディレクトリの下の.bashの最後のすべてのファイルを実行します.bashファイル、Linux端末下adbコマンドの補完を実現
    これで、source build/envsetup.shの過程は分析が終わった.
    build/envsetup.sh常用関数の紹介
    lunchプロセス
    ソースフローの直後にlunch操作が実行する、lunch操作はbuild/envsetupが実行される.shスクリプトのlunch関数は、コードを直接見ます.
    function lunch()
    {
        local answer
    
        #  lunch       ,     answer  ;
        #  lunch       ,     print_lunch_menu            ,          answer   。
        if [ "$1" ] ; then
            answer=$1
        else
            print_lunch_menu #           LUNCH_MENU_CHOICES   
            echo -n "Which would you like? [aosp_arm-eng] "
            read answer
        fi
    
        local selection=
    
    
        #  answer  , selection     aosp_arm-eng;
        #  answer    ,  answer       LUNCH_MENU_CHOICES         ;
        #  anwser    ,       ”-”  ,  ”-”             ”-”,           ,    selection。
        if [ -z "$answer" ]
        then
            selection=aosp_arm-eng
        elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
        then
            if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
            then
                selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
            fi
        elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
        then
            selection=$answer
        fi
    
        #  selection    ,        
        if [ -z "$selection" ]
        then
            echo
            echo "Invalid lunch combo: $answer"
            return 1
        fi
    
        export TARGET_BUILD_APPS=
    
    
        # selection   “-”       product,
        local product=$(echo -n $selection | sed -e "s/-.*$//")
        #  product    ,   make    
        check_product $product
        if [ $? -ne 0 ]
        then
            echo
            echo "** Don't have a product spec for: '$product'"
            echo "** Do you have the right repo manifest?"
            product=
        fi
    
    
        #  selection   “-”       variant,      check_variant  variant      。check_variant     ,        source       "user userdebug eng" VARIANT_CHOICES  ,  variant         ,    0,     1。
        local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
        check_variant $variant
        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
    
        #              shell    
        export TARGET_PRODUCT=$product
        export TARGET_BUILD_VARIANT=$variant
        export TARGET_BUILD_TYPE=release
    
        echo
    
        #  PROMPT_COMMAND,ANDROID_BUILD_PATHS,JAVA_HOME BUILD_ENV_SEQUENCE_NUMBER      
        set_stuff_for_environment
    
        #            
        printconfig
    } 

    Tips:set_stuff_for_Environmentの中のset_java_home関数は、実際の状況に応じてjavaパスなどを変更することができ、異なるandroidバージョンのコンパイルやjavaバージョンの手動切り替えを避けることができます.
    _lunch関数
    lunchコマンドの補完を実現するには:
    まずlunch関数を定義しました
    そして定義しましたlunch関数
    completeコマンドの使用
    # Tab completion for lunch.
    function _lunch()
    {
        local cur prev opts
        COMPREPLY=()
        cur="${COMP_WORDS[COMP_CWORD]}"
        prev="${COMP_WORDS[COMP_CWORD-1]}"
    
        COMPREPLY=( $(compgen -W "${LUNCH_MENU_CHOICES[*]}" -- ${cur}) )
        return 0
    }

    ++complete -F _lunch lunch++は、上記のコードの中で最も重要な行です.
    bashがlunchという言葉に出会ったとき、_が呼び出されます.lunch関数.この関数には、補完するコマンド名、現在のカーソルがある語、現在のカーソルがある語の前の語の3つのパラメータが入力されます.補完結果はCOMPREPLY変数に格納し、bash取得を待つ必要があります.
    gettop
    function gettop
    {
        local TOPFILE=build/core/envsetup.mk
        if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
            # The following circumlocution ensures we remove symlinks from TOP.
            (cd $TOP; PWD= /bin/pwd)
        else
            if [ -f $TOPFILE ] ; then
                # The following circumlocution (repeated below as well) ensures
                # that we record the true directory name and not one that is
                # faked up with symlink names.
                PWD= /bin/pwd
            else
                local HERE=$PWD
                T=
                while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
                    \cd ..
                    T=`PWD= /bin/pwd -P`
                    done
                \cd $HERE
                if [ -f "$T/$TOPFILE" ]; then
                    echo $T
                fi
            fi
        fi
    }
    
    

    -n変数が存在するか
    -a論理と
    -fファイルが存在するか
    PWDカレントディレクトリの印刷
    この関数は主にAndroidソースのルートディレクトリを取得し、ルートディレクトリの下のbuild/core/envsetupに基づいています.mkファイルで判断しました.
    注意:この関数を呼び出すときに要求があります.ソースコードのルートディレクトリのサブディレクトリで、ルートディレクトリの上位ディレクトリで呼び出すと失敗します.この関数はcdを呼び出すためです.コマンドを実行し、ファイルbuild/core/envsetup.mkはソースコードルートディレクトリを判断する.
    hmm
    
    function hmm() {
    cat <<EOF
    Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
    - lunch:   lunch -
    - tapas:   tapas [  ...] [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.
    - mangrep: Greps on all local AndroidManifest.xml files.
    - sepgrep: Greps on all local sepolicy files.
    - sgrep:   Greps on all local source files.
    - godir:   Go to the directory containing a file.
    
    Environemnt options:
    - SANITIZE_HOST: Set to 'true' to use ASAN for all host modules. Note that
                     ASAN_OPTIONS=detect_leaks=0 will be set by default until the
                     build is leak-check clean.
    
    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
    }
    

    ヘルプ関数、cat$T/build/envsetup.sh | sed -n “/^[\t]function/s/function ([a-z_]).*/\1/p"|sort|uniqというスクリプトは主にenvsetupを取得する.shの中のfunctionで始まる関数は、関数名がアルファベットで、関数名を印刷します.sed-n"/^[t]*function/p"は、functionで始まる行s/function([a-z_])./を印刷する1この部分は関数名を抽出してsortソートuniqを重み付けします
    mm
    function mm()
    {
        local T=$(gettop)
        local DRV=$(getdriver $T)
        # If we're sitting in the root of the build tree, just do a
        # normal make.
        if [ -f build/core/envsetup.mk -a -f Makefile ]; then
            $DRV make $@
        else
            # Find the closest Android.mk file.
            local M=$(findmakefile)
            local MODULES=
            local GET_INSTALL_PATH=
            local ARGS=
            # Remove the path to top as the makefilepath needs to be relative
            local M=`echo $M|sed 's:'$T'/::'`
            if [ ! "$T" ]; then
                echo "Couldn't locate the top of the tree.  Try setting TOP."
                return 1
            elif [ ! "$M" ]; then
                echo "Couldn't locate a makefile from the current directory."
                return 1
            else
                for ARG in $@; do
                    case $ARG in
                      GET-INSTALL-PATH) GET_INSTALL_PATH=$ARG;;
                    esac
                done
                if [ -n "$GET_INSTALL_PATH" ]; then
                  MODULES=
                  ARGS=GET-INSTALL-PATH
                else
                  MODULES=all_modules
                  ARGS=$@
                fi
                ONE_SHOT_MAKEFILE=$M $DRV make -C $T -f build/core/main.mk $MODULES $ARGS
            fi
        fi
    }

    現在ソースコードルートの下にあり、Makefileファイルがある場合は、make$@コマンドを直接実行します.
    ソースコードルートディレクトリでない場合:cdをループ呼び出します.findmakefile関数を呼び出してAndroidを検索します.mkファイルは、ルートディレクトリまでAndroid.mkファイルの絶対パスはMに戻る.
    見つかった場合:M=/home/admin/android/frameworks/base/Android.mk,呼び出し:local M=echo $M|sed 's}'$T'/}}'ソースコードルートディレクトリ/home/admin/android/を削除し、相対ディレクトリを取得すると、M=frameworks/base/Android.mk
    最終実行:ONE_SHOT_MAKEFILE=frameworks/base/android.mk make -C/home/admin/android all_modules
    make-C/home/admin/android allに相当modules ONE_SHOT_MAKEFILE=frameworks/base/android.mk
    次に、ソースコードルートディレクトリの下にあるMakefileに呼び出されます.内容はinclude build/core/mainです.mkはbuild/core/mainに着いた.mkファイルにあります.後でMakefileに設計する問題について、後で分析します.mmコマンドがmakefileを呼び出す方法を知るだけでいい
    mmm
    mmmコマンドは、指定したディレクトリの下からすべてのモジュールのコンパイルを開始します.
    function mmm()
    {
        local T=$(gettop)
        local DRV=$(getdriver $T)
        if [ "$T" ]; then
            local MAKEFILE=
            local MODULES=
            local ARGS=
            local DIR TO_CHOP
            local GET_INSTALL_PATH=
            local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
            local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
            for DIR in $DIRS ; do
                MODULES=`echo $DIR | sed -n -e 's/.*:\(.*$\)/\1/p' | sed 's/,/ /'`
                if [ "$MODULES" = "" ]; then
                    MODULES=all_modules
                fi
                DIR=`echo $DIR | sed -e 's/:.*//' -e 's:/$::'`
                if [ -f $DIR/Android.mk ]; then
                    local TO_CHOP=`(\cd -P -- $T && pwd -P) | wc -c | tr -d ' '`
                    local TO_CHOP=`expr $TO_CHOP + 1`
                    local START=`PWD= /bin/pwd`
                    local MFILE=`echo $START | cut -c${TO_CHOP}-`
                    if [ "$MFILE" = "" ] ; then
                        MFILE=$DIR/Android.mk
                    else
                        MFILE=$MFILE/$DIR/Android.mk
                    fi
                    MAKEFILE="$MAKEFILE $MFILE"
                else
                    case $DIR in
                      showcommands | snod | dist | incrementaljavac | *=*) ARGS="$ARGS $DIR";;
                      GET-INSTALL-PATH) GET_INSTALL_PATH=$DIR;;
                      *) echo "No Android.mk in $DIR."; return 1;;
                    esac
                fi
            done
            if [ -n "$GET_INSTALL_PATH" ]; then
              ARGS=$GET_INSTALL_PATH
              MODULES=
            fi
            ONE_SHOT_MAKEFILE="$MAKEFILE" $DRV make -C $T -f build/core/main.mk $DASH_ARGS $MODULES $ARGS
        else
            echo "Couldn't locate the top of the tree.  Try setting TOP."
            return 1
        fi
    }

    まずT=$(gettop)ソースコードルートディレクトリを取得し、
    local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/') 

    mmmの後のパラメータに基づいて、-で始まる文字列を取得します.たとえば、mmm-B frameworks/baseではDASH_ARGS = -B
    local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/') 

    mmmの後のパラメータに基づいて、-で始まる文字列ではなく、スペースで区切られた文字列を取得します.例:DIRS=frameworks/base/
    DIR=`echo $DIR | sed -e 's:/$::'` 

    DIR末尾の/を削除し、DIR=frameworks/base
    if [ -f $DIR/Android.mk ] ;then
    TO_CHOP=`(cd -P -- $T && pwd -P) | wc -c | tr -d ' '`

    ソースコードルートディレクトリにジャンプし、pwd-Pで印刷し、/home/admin/androids TO_などの文字列長を取得します.CHOPは20
    TO_CHOP=`expr $TO_CHOP + 1`
    
    START=`PWD= /bin/pwd`
    
    MFILE=`echo $START | cut -c${TO_CHOP}-`

    現在のディレクトリ文字列を取得し、前の21文字を削除します.例えば、現在のディレクトリが/home/admin/androidであれば、MFILE="
      if [ "$MFILE" = "" ] ; then
        MFILE=$DIR/Android.mk
       else
        MFILE=$MFILE/frameworks/base/Android.mk 
     fi

    ここでは、現在のディレクトリがソースディレクトリであるか否かを判断する、もしそうであればMFILEは空であるため、MFILE=frameworks/base/Androidとなる.mk
    それ以外の場合:MFILE=$MFILE/frameworks/base/Android.mk
    要するに、現在のディレクトリの前のソースコードのルートディレクトリを行って、それから後ろのmmm-B**パラメータの部分の相対的なディレクトリを加えて、最後にAndroidを加えます.mkは最後のAndroidだmkファイルの相対パス.
    ONE_SHOT_MAKEFILE=”MAKEFILE” make -C T T DASH_ARGS all_modules $ARGS
    make-C/home/admin/android-Ball_に相当modules ONE_SHOT_MAKEFILE=frameworks/base/Android.mk
    godir
    function godir () {
        #               
        if [[ -z "$1" ]]; then
            echo "Usage: godir "
            return
        fi
    
        T=$(gettop)
        #  OUT_DIR       OUT_DIR    ,  FILELIST    
        if [ ! "$OUT_DIR" = "" ]; then
            mkdir -p $OUT_DIR
            FILELIST=$OUT_DIR/filelist
        else
            FILELIST=$T/filelist
        fi
    
        #  filelist    ,     
        if [[ ! -f $FILELIST ]]; then
            echo -n "Creating index..."
    
            #   find              "-type f"(  out .repo  ),       $FILELIST   
            # out   .repo          :
            # - "-wholename ./out -prune"
            # - "-wholename ./.repo -prune"
            #   find "-wholename pattern""-path pattern"    ,      find     
            #   filelist      out .repo             
    
            (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > $FILELIST)
            echo " Done"
            echo ""
        fi
        local lines
    
        #     godir   , filelist   ,  sed         lines 
        #   "sed -e 's/\/[^/]*$//'"             
        lines=($(\grep "$1" $FILELIST | sed -e 's/\/[^/]*$//' | sort | uniq))
    
         #   lines    , filelist  grep sed   ,         
        if [[ ${#lines[@]} = 0 ]]; then
            echo "Not found"
            return
        fi
        local pathname
        local choice
        #   lines     1if [[ ${#lines[@]} > 1 ]]; then
            while [[ -z "$pathname" ]]; do
                #  1    
                local index=1
                local line
                for line in ${lines[@]}; do
                    #                :
                    printf "%6s %s
    "
    "[$index]" $line # index=$(($index + 1)) done echo echo -n "Select one: " unset choice # read choice if [[ $choice -gt ${#lines[@]} || $choice -lt 1 ]]; then echo "Invalid choice" continue fi # pathname=${lines[$(($choice-1))]} done else # , pathname pathname=${lines[0]} fi \cd $T/$pathname }

    godirは、コンパイルパスの下でマッチングモードのディレクトリを検索し、このディレクトリにジャンプします.frameworks/base/core/res/res/res/valuesのようなファイルのパスをすばやく検索するために使用できます.overlayが直接godir frameworks/base/core/res/res/values/このパスを含むすべてのフォルダを検索し、上書きする可能性のあるすべての場所を検索します.
    sgrep
    case `uname -s` in
        Darwin)
            function sgrep()
            {
                find -E . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.(c|h|cc|cpp|S|java|xml|sh|mk|aidl)' -print0 | xargs -0 grep --color -n "$@"
            }
    
            ;;
        *)
            function sgrep()
            {   
                #    .repo, .git  
                #     (c|h|cc|cpp|S|java|xml|sh|mk|aidl|vts)     grep    
                find . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.\(c\|h\|cc\|cpp\|S\|java\|xml\|sh\|mk\|aidl\)' -print0 | xargs -0 grep --color -n "$@"
            }
            ;;
    esac
    

    ここでなぜoutディレクトリを行かなかったのか理解できない
    他のコード検索原理は似ていますが、一つ一つ列挙しません.