zoukankan      html  css  js  c++  java
  • 学习shell之后,实战分析

    #!/bin/bash
    
    ###############################################################################
    #Variables
    #查找project目录,以及子目录的所有文档!其中以"GCC/Makefile"结尾的!
    export PROJECT_LIST=$(find project | grep "GCC/Makefile$")
    #project下边所有的目录
    export BOARD_LIST="project/*"
    export OUT="$PWD/out"
    export FLASHGENERATOR="tools/flashgen/flashgen.pl"
    feature_mk=""
    
    platform=$(uname)
    # uname 得到 "Linux"
    if [[ "$platform" =~ "MINGW" ]]; then  # =~表示包含子串
        export EXTRA_VAR=-j
    else
        export EXTRA_VAR=-j`cat /proc/cpuinfo |grep ^processor|wc -l`
    fi
    ###############################################################################
    #Functions
    show_usage () {
        echo "==============================================================="
        echo "Build Project"
        echo "==============================================================="
        echo "Usage: $0 <board> <project> [bl|clean] <argument>"
        echo ""
        echo "Example:"
        echo "       $0 mt7687_hdk iot_sdk_demo"
        echo "       $0 mt7687_hdk iot_sdk_demo bl      (build with bootloader)"
        echo "       $0 clean                      (clean folder: out)"
        echo "       $0 mt7687_hdk clean           (clean folder: out/mt7687_hdk)"
        echo "       $0 mt7687_hdk iot_sdk_demo clean   (clean folder: out/mt7687_hdk/iot_sdk_demo)"
        echo ""
        echo "Argument:"
        echo "       -f=<feature makefile> or --feature=<feature makefile>"
        echo "           Replace feature.mk with other makefile. For example, "
        echo "           the feature_example.mk is under project folder, -f=feature_example.mk"
        echo "           will replace feature.mk with feature_example.mk."
        echo ""
        echo "       -o=<make option> or --option=<make option>"
        echo "           Assign additional make option. For example, "
        echo "           to compile module sequentially, use -o=-j1."
        echo "           to turn on specific feature in feature makefile, use -o=<feature_name>=y"
        echo "           to assign more than one options, use -o=<option_1> -o=<option_2>."
        echo ""
        echo "==============================================================="
        echo "List Available Example Projects"
        echo "==============================================================="
        echo "Usage: $0 list"
        echo ""
    }
    
    show_available_proj () {
        echo "==============================================================="
        echo "Available Build Projects:"
        echo "==============================================================="
        for b in $BOARD_LIST
        do
            project_path=""
            project_name_list=""
            p=$(echo $PROJECT_LIST | tr " " "
    " | grep "$b")
            if [ ! -z "$p" ]; then
                echo  "  "`basename $b`
            fi
            for q in $p
            do
                if [ -e "$q" ]; then
                    project_path=$(echo $q | sed 's/GCC/Makefile//')
                    project_name_list="${project_name_list} $(basename $project_path)" #project_name_list一直在叠加
                fi
            done
            for i in `echo $project_name_list | tr " " "
    " | sort`
            do
                echo "  ""  "$i
            done
        done
    }
    
    #当输入./build mt2523_hdk headset_ref_design时
    use_new_out_folder="FALSE"
    target_check () {
        for p in $PROJECT_LIST   # $p是PROJECT_LIST中的一个
        do
            q=$(echo $p | grep "project/$1/")
            if [ ! -z "$q" ]; then
                r=$(echo $q | sed 's/GCC/Makefile//')
                s=`basename $r`
                if [ "$s" == "$2" ]; then
                    echo "Build board:$1 project:$2"
                    if [ $use_new_out_folder == "FALSE" ]; then
                        OUT=$OUT/$1/$2
                    fi
                    BUILD=project/$1/$2
                    export TARGET_PATH=$(dirname $q)
                    return 0
                fi
            fi
        done
        return 1
    }
    
    # support MinGW
    mingw_check () {
        echo "platform=$platform"
        if [[ "$platform" =~ "MINGW" ]]; then
            pwdpath=$(pwd)
            echo $pwdpath
            if [[ "$pwdpath" =~ "[|]| " ]]; then  # "[|]| "表示有[或]或空格
                echo "Build.sh Exception: The codebase folder name should not have spacing, [ or ]."
                exit 1
            fi
        fi
    }
    
    clean_out () {
        rm -rf $1
        echo "rm -rf $1"
    }
    ###############################################################################
    #Begin here
    if [ "$#" -eq "0" ]; then
        show_usage
        exit 1
    fi
    
    # parsing arguments
    declare -a argv=($0)
    ori_argv=$@
    do_make_clean="FALSE"
    for i in $@
    do
        case $i in
            -o=*|--option=*)
                opt=" ${i#*=}"  # 变量的删除替换!删除从开始到等号之间的东西
                echo "$opt" | grep -q -E " OUT="
                if [[ $? -eq 0 ]]; then  # 上一步匹配到了,返回0
                    # grep -o只显示匹配到的部分:OUT=后边,以空格或Tab开头的东东
                    # cut -d 分隔符为=
                    # tr -d 删掉
                    OUT=`echo $opt | grep -o "OUT=[^ |^    ]*" | cut -d '=' -f2 | tr -d ' '`
                    if [ -z "$OUT" ]; then
                        echo "Error: -o=OUT= cannot be empty!"
                        show_usage
                        exit 1
                    fi
                    OUT=$PWD/$OUT  # 更新设置了out目录
                    use_new_out_folder="TRUE"
                    echo "output folder change to: $OUT"
                fi
                extra_opt+=$opt  #字符串变量的追加,也可以写成 extra_opt=${extra_opt}$opt
                do_make_clean="TRUE"
                shift
                ;;
            -blo=*|--bloption=*)
                opt=" ${i#*=}"
                echo "$opt" | grep -q -E " OUT="
                if [[ $? -eq 0 ]]; then
                    echo "Error: Unsupported -o=OUT= in [-blo|-bloption]."
                    exit 1
                fi
                bl_extra_opt+=$opt
                do_make_clean="TRUE"
                shift
                ;;
            -f=*|--feature=*)
                feature_mk="${i#*=}"
                shift
                ;;
            list)
                show_available_proj
                exit 0
                ;;
            -*)
                echo "Error: unknown parameter "$i""
                show_usage
                exit 1
                ;;
            *)
                argv+=($i)
                ;;
        esac
    done
    
    export PROJ_NAME=${argv[2]}
    ###############################################################################
    # 附带编译Bootloader时执行:       ./build mt2523_hdk headset_ref_design bl
    if [ "${argv[3]}" == "bl" ]; then
        if [ "${#argv[@]}" != "4" ]; then
            show_usage
            exit 1
        fi
        target_check ${argv[1]} ${argv[2]}
        if [ "$?" -ne "0" ]; then
            echo "Error: ${argv[1]} ${argv[2]} is not available board & project"
            show_usage
            exit 1
        fi
        if [ $do_make_clean == "TRUE" ]; then
            clean_out $OUT
        fi
        mingw_check
        where_to_find_feature_mk=$TARGET_PATH
        if [ ! -z $feature_mk ]; then
            if [ ! -e "$TARGET_PATH/$feature_mk" ]; then
                echo "Error: cannot find $feature_mk under $TARGET_PATH."
                exit 1
            fi
            EXTRA_VAR+=" FEATURE=$feature_mk"
        else
            # 举例 $TARGET_PATH=project/mt2523_hdk/apps/headset_ref_design/GCC
            # 在Makefile中搜索TARGET_PATH开头    *表示多个空格,也是防止表达式断了     [?:]表示?或:    {0,1}表示0个或1个
            # tail只查看1行
            where_to_find_feature_mk=`grep "^TARGET_PATH *[?:]{0,1}= *" $TARGET_PATH/Makefile | cut -d '=' -f2 | tr -d ' ' | tail -1`
            if [ -z $where_to_find_feature_mk ]; then
                where_to_find_feature_mk=$TARGET_PATH
            fi
            feature_mk=`grep "^FEATURE *[?:]{0,1}= *" $TARGET_PATH/Makefile | cut -d '=' -f2 | tr -d ' ' | tail -1`
            echo "FEATURE=$feature_mk"
        fi
        if [ -e "$OUT/obj/$TARGET_PATH/tmp.mk" ]; then
            # -q仅显示有无差异,不显示结果
            diff -q $where_to_find_feature_mk/$feature_mk $OUT/obj/$TARGET_PATH/tmp.mk
            if [ $? -ne 0 ]; then
                clean_out $OUT
            fi
        fi
        mkdir -p $OUT/obj/$TARGET_PATH
        cp $where_to_find_feature_mk/$feature_mk $OUT/obj/$TARGET_PATH/tmp.mk
    
        CM4_TARGET_PATH_BAK=$TARGET_PATH
        TARGET_PATH="project/${argv[1]}/apps/bootloader/GCC"
    
        # 创建log目录
        mkdir -p $OUT/log
        echo "$0 $ori_argv" > $OUT/log/build_time.log
        echo "Start Build: "`date` >> $OUT/log/build_time.log
        echo "Build bootloader..."
        # Check if the source dir is existed
        if [ ! -d "project/${argv[1]}/apps/bootloader" ]; then
            echo "Error: no bootloader source in project/${argv[1]}/apps/bootloader"
            exit 1
        fi
    
        # 开始编译bootloader
        mkdir -p $OUT
        make -C $TARGET_PATH BUILD_DIR=$OUT/obj/bootloader OUTPATH=$OUT BL_MAIN_PROJECT=${argv[2]} $extra_opt $bl_extra_opt 2>> $OUT/err.log
        BUILD_RESULT=$?
        mkdir -p $OUT/lib
        mv -f $OUT/*.a $OUT/lib/ 2> /dev/null
        mkdir -p $OUT/log
        mv -f $OUT/*.log $OUT/log/ 2> /dev/null
        if [ $BUILD_RESULT -ne 0 ]; then
            echo "Error: bootloader build failed!!"
            echo "BOOTLOADER BUILD : FAIL" >> $OUT/log/build_time.log
            exit 2;
        else
            echo "BOOTLOADER BUILD : PASS" >> $OUT/log/build_time.log
        fi
        echo "Build bootloader...Done"
    
        # build cm4 firmware  编译M4固件
        echo "Build CM4 Firmware..."
        TARGET_PATH=$CM4_TARGET_PATH_BAK
        mkdir -p $OUT/autogen
        EXTRA_VAR+="$extra_opt"
        #echo "make -C $TARGET_PATH BUILD_DIR=$OUT/obj OUTPATH=$OUT $EXTRA_VAR"
        make -C $TARGET_PATH BUILD_DIR=$OUT/obj OUTPATH=$OUT $EXTRA_VAR 2>> $OUT/err.log
        BUILD_RESULT=$?
        mkdir -p $OUT/lib
        mv -f $OUT/*.a $OUT/lib/ 2> /dev/null
        mkdir -p $OUT/log
        mv -f $OUT/*.log $OUT/log/ 2> /dev/null
        echo "Build CM4 Firmware...Done"
        echo "End Build: "`date` >> $OUT/log/build_time.log
        cat $OUT/log/build.log | grep "MODULE BUILD" >> $OUT/log/build_time.log
        if [ "$BUILD_RESULT" -eq "0" ]; then
            echo "TOTAL BUILD: PASS" >> $OUT/log/build_time.log
        else
            echo "TOTAL BUILD: FAIL" >> $OUT/log/build_time.log
        fi
        echo "=============================================================="
        cat $OUT/log/build_time.log
        exit $BUILD_RESULT
    elif [ "${argv[3]}" == "clean" ]; then
        if [ "${#argv[@]}" != "4" ]; then
            show_usage
            exit 1
        fi
        if [ "$use_new_out_folder" == "TRUE" ]; then
            rm -rf $OUT
        else
            rm -rf $OUT/${argv[1]}/${argv[2]}
        fi
    elif [ "${argv[2]}" == "clean" ]; then
        if [ "${#argv[@]}" != "3" ]; then
            show_usage
            exit 1
        fi
        if [ "$use_new_out_folder" == "TRUE" ]; then
            rm -rf $OUT
        else
            rm -rf $OUT/${argv[1]}
        fi
    elif [ "${argv[1]}" == "clean" ]; then
        if [ "${#argv[@]}" != "2" ]; then
            show_usage
            exit 1
        fi
        rm -rf $OUT
    else  
        # 最后这里是只编译M4内核的部分
        if [ "${#argv[@]}" != "3" ]; then
            show_usage
            exit 1
        fi
        target_check ${argv[1]} ${argv[2]}
        if [ "$?" -ne "0" ]; then
            echo "Error: ${argv[1]} ${argv[2]} is not available board & project or module"
            show_usage
            exit 1
        fi
        if [ $do_make_clean == "TRUE" ]; then
            clean_out $OUT
        fi
        mingw_check
        where_to_find_feature_mk=$TARGET_PATH
        if [ ! -z $feature_mk ]; then
            if [ ! -e "$TARGET_PATH/$feature_mk" ]; then
                echo "Error: cannot find $feature_mk under $TARGET_PATH."
                exit 1
            fi
            EXTRA_VAR+=" FEATURE=$feature_mk"
        else
            where_to_find_feature_mk=`grep "^TARGET_PATH *[?:]{0,1}= *" $TARGET_PATH/Makefile | cut -d '=' -f2 | tr -d ' ' | tail -1`
            if [ -z $where_to_find_feature_mk ]; then
                where_to_find_feature_mk=$TARGET_PATH
            fi
            feature_mk=`grep "^FEATURE *[?:]{0,1}= *" $TARGET_PATH/Makefile | cut -d '=' -f2 | tr -d ' ' | tail -1`
            echo "FEATURE=$feature_mk"
        fi
        if [ -e "$OUT/obj/$TARGET_PATH/tmp.mk" ]; then
            diff -q $where_to_find_feature_mk/$feature_mk $OUT/obj/$TARGET_PATH/tmp.mk
            if [ $? -ne 0 ]; then
                clean_out $OUT
            fi
        fi
        mkdir -p $OUT/obj/$TARGET_PATH
        cp $where_to_find_feature_mk/$feature_mk $OUT/obj/$TARGET_PATH/tmp.mk
        mkdir -p $OUT/autogen
        mkdir -p $OUT/log
        echo "$0 $ori_argv" > $OUT/log/build_time.log
        echo "Start Build: "`date` >> $OUT/log/build_time.log
        if [ ! -z $feature_mk ]; then
            EXTRA_VAR+=" FEATURE=$feature_mk"
        fi
        EXTRA_VAR+="$extra_opt"
        #echo "make -C $TARGET_PATH BUILD_DIR=$OUT/obj OUTPATH=$OUT $EXTRA_VAR"
        make -C $TARGET_PATH BUILD_DIR=$OUT/obj OUTPATH=$OUT $EXTRA_VAR 2>> $OUT/err.log
        BUILD_RESULT=$?
        mkdir -p $OUT/lib
        mv -f $OUT/*.a $OUT/lib/ 2> /dev/null
        mv -f $OUT/*.log $OUT/log/ 2> /dev/null
        echo "End Build: "`date` >> $OUT/log/build_time.log
        cat $OUT/log/build.log | grep "MODULE BUILD" >> $OUT/log/build_time.log
        if [ "$BUILD_RESULT" -eq "0" ]; then
            echo "TOTAL BUILD: PASS" >> $OUT/log/build_time.log
        else
            echo "TOTAL BUILD: FAIL" >> $OUT/log/build_time.log
        fi
        echo "=============================================================="
        cat $OUT/log/build_time.log
        exit $BUILD_RESULT
    fi

    分析过程中,单独摘出来试验某个语句的意思,尤其是正则表达式复杂的时候,做试验更直观一些。

    还有shell的调试方法,-x -n -v,要把整个脚本截短一点再调试,不然太庞大了。

    纵观下来,最有意思的部分是,获得各个文件文件夹、搜索和截取路径、basename/dirname、处理输入变量。
    最后肯定会调用make啦~~~
     
     
     
     
     
     
     
     
     
    联我:shen5773384##163.com
  • 相关阅读:
    JScript运行批处理命令的做法
    java_main
    MySQL 数据库设计 笔记与总结(1)需求分析
    学技术真累
    学习Spring框架等技术的方向、方法和动机
    学习Spring框架等技术的方向、方法和动机
    个人知识管理是职场必修课
    个人知识管理是职场必修课
    提高生产力的2个方法:软件复用和知识库
    提高生产力的2个方法:软件复用和知识库
  • 原文地址:https://www.cnblogs.com/WMCH/p/8615814.html
Copyright © 2011-2022 走看看