i.MX Yocto項目配置腳本解析(imx-setup-release.sh)


在使用i.MX官方提供Yocto工程構建Linux系統時,通常情況下我們要先執行imx-setup-release.sh腳本進行配置操作,然后再執行bitbake target命令去構建我們想要的目標。因此,如果想要深入理解Yocto工程的運行和構建的具體的技術細節,我們還是需要以這個配置腳本為切入點,詳細分析一下執行imx-setup-release.sh腳本時完成了哪些工作。

1、概述

由於imx-setup-release.sh腳本里的內容比較復雜,在它內部還嵌套了其它腳本的調用。所有,在進行詳細分析之前,我在這里先告訴大家它大概做了哪些操作,以及它調用的各個腳本實現的功能。這樣抱着目的來看后面的內容,反而更方便大家去理解。

總的來說,執行imx-setup-release.sh腳本完成的工作主要包含兩個部分。首先,它創建了構建目錄並設置了該目錄下的conf目錄里的內容(bitbake工具構建目標時,首先解析的就是該目錄里的文件),其次它把構建用到的腳本和工具集所在的目錄添加到PATH環境變量,以便於我們可以直接在終端中使用該工具集(比如我們執行bitbake target時,不需要加上bitbake所在路徑)

接着再來看下內部腳本的調用關系和各個腳本實現的功能吧!

 圖1.1 imx-setup-release.sh腳本內部調用關系

imx-setup-release.sh腳本通過層層的調用,最終會調用到了oe-init-build-env腳本和oe-setup-builddir腳本,這兩個腳本是在poky里面實現的。所謂poky是BitBake工具集和OE組件組合在一起以形成參考構建主機,Yocto項目的構建主機是基於這個來做的,可以理解為Yocto項目繼承了OpenEmbedded(OE)項目並且豐富了一些內容。所以,Yocto項目中最底層還是會調用到OE構建環境的腳本,但調用OE里的這些腳本之后,它還會根據自己的需求在自己構建的腳本中對OE構建環境默認的配置進行了適當的修改,這些修改的內容就是在imx-setup-release.sh和setup-environmen腳本中實現的。

下面簡要的說下前面列出的各個腳本的實現的功能:

  • oe-buildenv-internal:檢測目標主機上Python版本(bitbake等構建工具是Python編寫的,運行時需要Python來解析),將構建用的bitbake等工具路徑臨時添加到PATH環境變量,設置構建工具集用到的環境變量
  • oe-setup-builddir:創建構建目錄,將poky目錄下meta-poky層的conf目錄下默認的配置文件拷貝到構建目錄的conf目錄中去
  • oe-init-build-env:OE中提供給用戶用來進行配置構建環境的腳本,即它內部調用oe-buildenv-internal和oe-setup-builddir腳本
  • setup-environment:Yocto項目中提供給用戶用來進行配置構建環境的腳本,調用oe-init-build-env設置默認配置,然后再根據自己需求做了一些修改
  • imx-setup-release.sh:NXP公司維護Yocto版本提供給用戶用來配置構建環境的腳本,調用setup-envitonment設置默認配置,然后再根據基礎上做了一些修改

2、構建腳本分析

前面對Yocto項目的構建環境的腳本間的調用關系和每個腳本所實現的功能做了簡單的介紹,想必大家對配置過程有了一個大概的認識,現在就開始腳本源碼的角度詳細的分析每個腳本所做的具體工作。有了前面的內容作為鋪墊,再來看下面的這些內容應該容易理解了些。

2.1 oe-buildenv-internal

#!/bin/sh

# OE-Core Build Environment Setup Script
#
# Copyright (C) 2006-2011 Linux Foundation
#
# SPDX-License-Identifier: GPL-2.0-or-later
#

if ! $(return >/dev/null 2>&1) ; then
    echo 'oe-buildenv-internal: error: this script must be sourced'
    echo ''
    echo 'Usage: . $OEROOT/scripts/oe-buildenv-internal &&'
    echo ''
    echo 'OpenEmbedded oe-buildenv-internal - an internal script that is'
    echo 'used in oe-init-build-env to initialize oe build environment'
    echo ''
    exit 2
fi

# It is assumed OEROOT is already defined when this is called
if [ -z "$OEROOT" ]; then--------------------------------------------->echo >&2 "Error: OEROOT is not defined!"
    return 1
fi

if [ -z "$OE_SKIP_SDK_CHECK" ] && [ -n "$OECORE_SDK_VERSION" ]; then
    echo >&2 "Error: The OE SDK/ADT was detected as already being present in this shell environment. Please use a clean shell when sourcing this environment script."
    return 1
fi

py_v27_check=$(python2 -c 'import sys; print sys.version_info >= (2,7,3)')--------------------------------------------->if [ "$py_v27_check" != "True" ]; then
    echo >&2 "OpenEmbedded requires 'python' to be python v2 (>= 2.7.3), not python v3."
    echo >&2 "Please upgrade your python v2."
fi
unset py_v27_check

# We potentially have code that doesn't parse correctly with older versions 
# of Python, and rather than fixing that and being eternally vigilant for 
# any other new feature use, just check the version here.
py_v34_check=$(python3 -c 'import sys; print(sys.version_info >= (3,4,0))')
if [ "$py_v34_check" != "True" ]; then
    echo >&2 "BitBake requires Python 3.4.0 or later as 'python3'"
    return 1
fi
unset py_v34_check

if [ -z "$BDIR" ]; then--------------------------------------------->if [ -z "$1" ]; then
        BDIR="build"
    else
        BDIR="$1"
        if [ "$BDIR" = "/" ]; then
            echo >&2 "Error: / is not supported as a build directory."
            return 1
        fi

        # Remove any possible trailing slashes. This is used to work around
        # buggy readlink in Ubuntu 10.04 that doesn't ignore trailing slashes
        # and hence "readlink -f new_dir_to_be_created/" returns empty.
        BDIR=$(echo $BDIR | sed -re 's|/+$||')

        BDIR=$(readlink -f "$BDIR")
        if [ -z "$BDIR" ]; then
            PARENTDIR=$(dirname "$1")
            echo >&2 "Error: the directory $PARENTDIR does not exist?"
            return 1
        fi
    fi
    if [ -n "$2" ]; then
        BITBAKEDIR="$2"
    fi
fi
if [ "${BDIR#/}" != "$BDIR" ]; then
    BUILDDIR="$BDIR"
else
    BUILDDIR="$(pwd)/$BDIR"
fi
unset BDIR

if [ -z "$BITBAKEDIR" ]; then--------------------------------------------->④
    BITBAKEDIR="$OEROOT/bitbake$BBEXTRA"
    test -d "$BITBAKEDIR" || BITBAKEDIR="$OEROOT/../bitbake$BBEXTRA"
fi

BITBAKEDIR=$(readlink -f "$BITBAKEDIR")
BUILDDIR=$(readlink -f "$BUILDDIR")
BBPATH=$BUILDDIR

export BBPATH

if [ ! -d "$BITBAKEDIR" ]; then
    echo >&2 "Error: The bitbake directory ($BITBAKEDIR) does not exist!  Please ensure a copy of bitbake exists at this location or specify an alternative path on the command line"
    return 1
fi

# Make sure our paths are at the beginning of $PATH
for newpath in "$BITBAKEDIR/bin" "$OEROOT/scripts"; do--------------------------------------------->⑤
    # Remove any existences of $newpath from $PATH
    PATH=$(echo $PATH | sed -re "s#(^|:)$newpath(:|$)#\2#g;s#^:##")

    # Add $newpath to $PATH
    PATH="$newpath:$PATH"
done
unset BITBAKEDIR newpath

# Used by the runqemu script
export BUILDDIR--------------------------------------------->⑤
export PATH

BB_ENV_EXTRAWHITE_OE="MACHINE DISTRO TCMODE TCLIBC HTTP_PROXY http_proxy \
HTTPS_PROXY https_proxy FTP_PROXY ftp_proxy FTPS_PROXY ftps_proxy ALL_PROXY \
all_proxy NO_PROXY no_proxy SSH_AGENT_PID SSH_AUTH_SOCK BB_SRCREV_POLICY \
SDKMACHINE BB_NUMBER_THREADS BB_NO_NETWORK PARALLEL_MAKE GIT_PROXY_COMMAND \
SOCKS5_PASSWD SOCKS5_USER SCREENDIR STAMPS_DIR BBPATH_EXTRA BB_SETSCENE_ENFORCE"

BB_ENV_EXTRAWHITE="$(echo $BB_ENV_EXTRAWHITE $BB_ENV_EXTRAWHITE_OE | tr ' ' '\n' | LC_ALL=C sort --unique | tr '\n' ' ')"

export BB_ENV_EXTRAWHITE
oe-buildenv-internal

① 檢測OEROOT變量是否定義,如果沒定義腳本立刻返回。OEROOT變量在oe-init-build-env腳本中設置,該變量表示oe-init-build-env腳本所在目錄位置信息

② 檢測主機安裝python版本信息,Python2需大於2.7.3,Python3需大於3.4.0

③ 設置BUILDDIR變量等於構建目錄的絕對路徑信息。如果執行該腳本時沒指定構建目錄的路徑為腳本的第一個參數的話,腳本設置使用"build"作為默認構建目錄名

④ 令BITBAKEDIR="$OEROOT/bitbake,該路徑是存放bitbake工具集和腳本的路徑

⑤ 將"$BITBAKEDIR/bin" "$OEROOT/scripts"路徑臨時增加到PATH環境變量中,$BITBAKEDIR/bin路徑存放的是bitbake工具,$OEROOT/scripts目錄存放的是構建的腳本

⑥ 設置構建工具集使用的環境變量

2.2 oe-buildenv-builddir

#!/bin/sh

# OE Build Environment Setup Script
#
# Copyright (C) 2006-2011 Linux Foundation
#
# SPDX-License-Identifier: GPL-2.0-or-later
#

if [ -z "$BUILDDIR" ]; then
    echo >&2 "Error: The build directory (BUILDDIR) must be set!"
    exit 1
fi

if [ "$1" = '--help' -o "$1" = '-h' ]; then
    echo 'Usage: oe-setup-builddir'
    echo ''
    echo "OpenEmbedded setup-builddir - setup build directory $BUILDDIR"
    echo ''
    exit 2
fi

mkdir -p "$BUILDDIR/conf"--------------------------------------------------->if [ ! -d "$BUILDDIR" ]; then
    echo >&2 "Error: The builddir ($BUILDDIR) does not exist!"
    exit 1
fi

if [ ! -w "$BUILDDIR" ]; then
    echo >&2 "Error: Cannot write to $BUILDDIR, perhaps try sourcing with a writable path? i.e. . oe-init-build-env ~/my-build"
    exit 1
fi

# Attempting removal of sticky,setuid bits from BUILDDIR, BUILDDIR/conf
chmod -st "$BUILDDIR" 2>/dev/null || echo "WARNING: unable to chmod $BUILDDIR"
chmod -st "$BUILDDIR/conf" 2>/dev/null || echo "WARNING: unable to chmod $BUILDDIR/conf"

cd "$BUILDDIR"------------------------------------------------>if [ -f "$BUILDDIR/conf/templateconf.cfg" ]; then-------------------------------------->③
    TEMPLATECONF=$(cat "$BUILDDIR/conf/templateconf.cfg")
fi

. $OEROOT/.templateconf---------------------------------------------------------------->if [ ! -f "$BUILDDIR/conf/templateconf.cfg" ]; then------------------------------------>echo "$TEMPLATECONF" >"$BUILDDIR/conf/templateconf.cfg"
fi

# 
# $TEMPLATECONF can point to a directory for the template local.conf & bblayers.conf
#
if [ -n "$TEMPLATECONF" ]; then------------------------------------------------------->if [ ! -d "$TEMPLATECONF" ]; then
        # Allow TEMPLATECONF=meta-xyz/conf as a shortcut
        if [ -d "$OEROOT/$TEMPLATECONF" ]; then
            TEMPLATECONF="$OEROOT/$TEMPLATECONF"
        fi
        if [ ! -d "$TEMPLATECONF" ]; then
            echo >&2 "Error: TEMPLATECONF value points to nonexistent directory '$TEMPLATECONF'"
            exit 1
        fi
    fi
    OECORELAYERCONF="$TEMPLATECONF/bblayers.conf.sample"
    OECORELOCALCONF="$TEMPLATECONF/local.conf.sample"
    OECORENOTESCONF="$TEMPLATECONF/conf-notes.txt"
fi

unset SHOWYPDOC
if [ -z "$OECORELOCALCONF" ]; then------------------------------------------------------->⑦
    OECORELOCALCONF="$OEROOT/meta/conf/local.conf.sample"
fi
if [ ! -r "$BUILDDIR/conf/local.conf" ]; then------------------------------------------------------->cat <<EOM
You had no conf/local.conf file. This configuration file has therefore been
created for you with some default values. You may wish to edit it to, for
example, select a different MACHINE (target hardware). See conf/local.conf
for more information as common configuration options are commented.

EOM
    cp -f $OECORELOCALCONF "$BUILDDIR/conf/local.conf"
    SHOWYPDOC=yes
fi

if [ -z "$OECORELAYERCONF" ]; then------------------------------------------------------->⑦
    OECORELAYERCONF="$OEROOT/meta/conf/bblayers.conf.sample"
fi
if [ ! -r "$BUILDDIR/conf/bblayers.conf" ]; then------------------------------------------------------->cat <<EOM
You had no conf/bblayers.conf file. This configuration file has therefore been
created for you with some default values. To add additional metadata layers
into your configuration please add entries to conf/bblayers.conf.

EOM

    # Put the abosolute path to the layers in bblayers.conf so we can run
    # bitbake without the init script after the first run
    # ##COREBASE## is deprecated as it's meaning was inconsistent, but continue
    # to replace it for compatibility.
    sed -e "s|##OEROOT##|$OEROOT|g" \
        -e "s|##COREBASE##|$OEROOT|g" \
        $OECORELAYERCONF > "$BUILDDIR/conf/bblayers.conf"
    SHOWYPDOC=yes
fi

# Prevent disturbing a new GIT clone in same console
unset OECORELOCALCONF
unset OECORELAYERCONF

# Ending the first-time run message. Show the YP Documentation banner.
if [ ! -z "$SHOWYPDOC" ]; then--------------------------------------------------->cat <<EOM
The Yocto Project has extensive documentation about OE including a reference
manual which can be found at:
    http://yoctoproject.org/documentation

For more information about OpenEmbedded see their website:
    http://www.openembedded.org/

EOM
#    unset SHOWYPDOC
fi

if [ -z "$OECORENOTESCONF" ]; then----------------------------------------------->⑦
    OECORENOTESCONF="$OEROOT/meta/conf/conf-notes.txt"
fi
[ ! -r "$OECORENOTESCONF" ] || cat $OECORENOTESCONF------------------------------->⑩
unset OECORENOTESCONF
oe-buildenv-builddir

① 遞歸創建$BUILDDIR/conf,$BUILDDIR表示的是構建目錄的路徑,創建的目錄和子目錄應該有可讀可寫權限(此時創建了構建目錄,並且在構建目錄下創建了conf目錄)

② 切換到構建目錄

③ 判斷構建目錄下子目錄conf中templateconf.cfg文件是否存在,如果存在用它里面的內容去設置TEMPLATECONF變量(如果是第一次創建肯定不存在此文件,此時使用$OEROOT/.templateconf中對TEMPLATECONF變量設置)

④ $OEROOT/.templateconf腳本內容:TEMPLATECONF=${TEMPLATECONF:-meta-poky/conf}。如果是第一次構建,構建目錄下子目錄conf中templateconf.cfg文件不存在,在前面TEMPLATECONF變量沒被設置,此處設置TEMPLATECONF=meta-poky/conf

⑤ 如果是第一次構建,需要將meta-poky/conf信息寫到$BUILDDIR/conf/templateconf.cfg文件中

⑥ TEMPLATECONF="$OEROOT/meta-poky/conf"
     OECORELAYERCONF="$OEROOT/meta-poky/conf/bblayers.conf.sample"
     OECORELOCALCONF="$OEROOT/meta-poky/conf/local.conf.sample"
     OECORENOTESCONF="$OEROOT/meta-poky/conf/conf-notes.txt"
    (OEROOT=$(pwd)/sources/poky,此處的$(pwd)表示你yocto工程存放的絕對路徑)

使用poky/meta-poky/conf目錄下的bblayers.conf.sample和local.conf.sample作為默認配置文件

⑦ 判斷poky/meta-poky/conf目錄下的bblayers.conf.sample和local.conf.sample配置文件是否存在,不存在使用poky/meta/conf目錄下的

⑧ 如果是第一次構建,構建目錄下conf中bblayers.conf、local.conf文件不存在
拷貝$OEROOT/meta-poky/conf/bblayers.conf.sample到$BUILDDIR/conf/bblayers.conf文件
拷貝$OEROOT/meta-poky/conf/local.conf.sample到$BUILDDIR/conf/local.conf文件

(在拷貝OEROOT/meta-poky/conf/local.conf.sample文件時,將文件中含有"##OEROOT##"和"##COREBASE##"內容換成$OEROOT表示的路徑后,再拷貝到$BUILDDIR/conf/local.conf文件)

這里的$BUILDDIR表示的是構建目錄的位置信息

⑨ 如果時第一次構建,SHOWYPDOC=yes,打印下面信息

The Yocto Project has extensive documentation about OE including a reference
                    manual which can be found at:
                        http://yoctoproject.org/documentation
                    
                    For more information about OpenEmbedded see their website:
                        http://www.openembedded.org/

⑩ 如果是第一次構建,打印$OEROOT/meta-poky/conf/conf-notes.txt文件信息

2.3 oe-init-build-env

#!/bin/sh

# OE Build Environment Setup Script
#
# Copyright (C) 2006-2011 Linux Foundation
#
# SPDX-License-Identifier: GPL-2.0-or-later
#

#
# Normally this is called as '. ./oe-init-build-env <builddir>'
#
# This works in most shells (not dash), but not all of them pass the arguments
# when being sourced.  To workaround the shell limitation use "set <builddir>"
# prior to sourcing this script.
#
if [ -n "$BASH_SOURCE" ]; then-------------------------->①
    THIS_SCRIPT=$BASH_SOURCE
elif [ -n "$ZSH_NAME" ]; then
    THIS_SCRIPT=$0
else
    THIS_SCRIPT="$(pwd)/oe-init-build-env"
    if [ ! -e "$THIS_SCRIPT" ]; then
        echo "Error: $THIS_SCRIPT doesn't exist!" >&2
        echo "Please run this script in oe-init-build-env's directory." >&2
        exit 1
    fi
fi
if [ -n "$BBSERVER" ]; then
    unset BBSERVER
fi

if [ -z "$ZSH_NAME" ] && [ "$0" = "$THIS_SCRIPT" ]; then
    echo "Error: This script needs to be sourced. Please run as '. $THIS_SCRIPT'" >&2
    exit 1
fi

if [ -z "$OEROOT" ]; then--------------------------------->②
    OEROOT=$(dirname "$THIS_SCRIPT")
    OEROOT=$(readlink -f "$OEROOT")
fi
unset THIS_SCRIPT

export OEROOT-------------------------------------------->③
. $OEROOT/scripts/oe-buildenv-internal &&
    TEMPLATECONF="$TEMPLATECONF" $OEROOT/scripts/oe-setup-builddir || {---------------->④
    unset OEROOT
    return 1
}
unset OEROOT

[ -z "$BUILDDIR" ] || cd "$BUILDDIR"-------------------------------------------------->⑤
oe-init-build-env

① 判斷是哪種shell解析的oe-init-build-env,並根據該shell解釋器的特點,獲取該腳本所在的位置信息,位置信息存放到THIS_SCRIPT變量中

. 或者source這種執行腳本的方式,會使用主機默認的shell解釋器解釋腳本。如果是以./xxx方式運行腳本,使用的是腳本開頭指定的解釋器,如果腳本開頭沒指定使用主機默認的解釋器

② 判斷是否設置了OEROOT變量,如果OEROOT沒被設置,提取THIS_SCRIPT的前綴去設置OEROOT

(由於在調用該腳本前,setup-environment腳本設置OEROOT=$PWD/sources/poky,所以此處不會被執行)

③ export OEROOT 設置臨時環境變量

④ 執行$PWD/sources/poky目錄下的子目錄scripts中的oe-buildenv-internal和oe-setup-builddir腳本

⑤ 判斷oe-buildenv-internal和oe-setup-builddir腳本中是否設置了BUILDDIR變量,如果設置了,切換到他表示的目錄里

2.4 setup-environment

#!/bin/sh
# -*- mode: shell-script; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
#
# Copyright (C) 2012, 2013, 2016 O.S. Systems Software LTDA.
# Authored-by:  Otavio Salvador <otavio@ossystems.com.br>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Add options for the script
# Copyright (C) 2013 Freescale Semiconductor, Inc.

CWD=`pwd`
PROGNAME="setup-environment"
PACKAGE_CLASSES=${PACKAGE_CLASSES:-package_rpm}

usage()
{
    echo -e "
Usage: MACHINE=<machine> DISTRO=<distro> source $PROGNAME <build-dir>
Usage:                                   source $PROGNAME <build-dir>
    <machine>    machine name
    <distro>     distro name
    <build-dir>  build directory

The first usage is for creating a new build directory. In this case, the
script creates the build directory <build-dir>, configures it for the
specified <machine> and <distro>, and prepares the calling shell for running
bitbake on the build directory.

The second usage is for using an existing build directory. In this case,
the script prepares the calling shell for running bitbake on the build
directory <build-dir>. The build directory configuration is unchanged.
"

    ls sources/*/conf/machine/*.conf > /dev/null 2>&1
    ls sources/meta-freescale-distro/conf/distro/fslc-*.conf > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo -e "
Supported machines: `echo; ls sources/*/conf/machine/*.conf \
| sed s/\.conf//g | sed -r 's/^.+\///' | xargs -I% echo -e "\t%"`

Supported Freescale's distros: `echo; ls sources/meta-freescale-distro/conf/distro/fslc-*.conf \
| sed s/\.conf//g | sed -r 's/^.+\///' | xargs -I% echo -e "\t%"`

Available Poky's distros: `echo; ls sources/poky/meta-poky/conf/distro/*.conf \
| sed s/\.conf//g | sed -r 's/^.+\///' | xargs -I% echo -e "\t%"`

Examples:

- To create a new Yocto build directory:
  $ MACHINE=imx6qdlsabresd DISTRO=fslc-framebuffer source $PROGNAME build

- To use an existing Yocto build directory:
  $ source $PROGNAME build
"
    fi
}

clean_up()
{
   unset EULA LIST_MACHINES VALID_MACHINE
   unset CWD TEMPLATES SHORTOPTS LONGOPTS ARGS PROGNAME
   unset generated_config updated
   unset MACHINE SDKMACHINE DISTRO OEROOT
}

# get command line options
SHORTOPTS="h"
LONGOPTS="help"

ARGS=$(getopt --options $SHORTOPTS  \
  --longoptions $LONGOPTS --name $PROGNAME -- "$@" )
# Print the usage menu if invalid options are specified
if [ $? != 0 -o $# -lt 1 ]; then
   usage && clean_up
   return 1
fi

eval set -- "$ARGS"--------------------------------------->①
while true;
do
    case $1 in
        -h|--help)
           usage
           clean_up
           return 0
           ;;
        --)
           shift
           break
           ;;
    esac
done

if [ "$(whoami)" = "root" ]; then-------------------------------->②
    echo "ERROR: do not use the BSP as root. Exiting..."
fi

if [ ! -e $1/conf/local.conf.sample ]; then---------------------->③
    build_dir_setup_enabled="true"
else
    build_dir_setup_enabled="false"
fi

if [ "$build_dir_setup_enabled" = "true" ] && [ -z "$MACHINE" ]; then
    usage
    echo -e "ERROR: You must set MACHINE when creating a new build directory."
    clean_up
    return 1
fi

if [ -z "$SDKMACHINE" ]; then
    SDKMACHINE='i686'
fi

if [ "$build_dir_setup_enabled" = "true" ] && [ -z "$DISTRO" ]; then
    usage
    echo -e "ERROR: You must set DISTRO when creating a new build directory."
    clean_up
    return 1
fi

[ -z "$FSL_EULA_FILE" ] && FSL_EULA_FILE=$CWD/sources/meta-freescale/EULA--------------->④
if [ ! -e $FSL_EULA_FILE ]; then
    echo -e "ERROR: EULA not found at $FSL_EULA_FILE."
    clean_up
    return 1
fi

OEROOT=$PWD/sources/poky---------------------------------->⑤
if [ -e $PWD/sources/oe-core ]; then
    OEROOT=$PWD/sources/oe-core
fi

. $OEROOT/oe-init-build-env $CWD/$1 > /dev/null----------------------->⑥

# if conf/local.conf not generated, no need to go further
if [ ! -e conf/local.conf ]; then
    clean_up && return 1
fi

# Clean up PATH, because if it includes tokens to current directories somehow,
# wrong binaries can be used instead of the expected ones during task execution
export PATH="`echo $PATH | sed 's/\(:.\|:\)*:/:/g;s/^.\?://;s/:.\?$//'`"----------------------->⑦

generated_config=
if [ "$build_dir_setup_enabled" = "true" ]; then-------------------------->⑧
    mv conf/local.conf conf/local.conf.sample

    # Generate the local.conf based on the Yocto defaults
    TEMPLATES=$CWD/sources/base/conf 
    grep -v '^#\|^$' conf/local.conf.sample > conf/local.conf
    cat >> conf/local.conf <<EOF

DL_DIR ?= "\${BSPDIR}/downloads/"
EOF
    # Change settings according environment
    sed -e "s,MACHINE ??=.*,MACHINE ??= '$MACHINE',g" \
        -e "s,SDKMACHINE ??=.*,SDKMACHINE ??= '$SDKMACHINE',g" \
        -e "s,DISTRO ?=.*,DISTRO ?= '$DISTRO',g" \
        -e "s,PACKAGE_CLASSES ?=.*,PACKAGE_CLASSES ?= '$PACKAGE_CLASSES',g" \
        -i conf/local.conf

    cp $TEMPLATES/* conf/

    for s in $HOME/.oe $HOME/.yocto; do
        if [ -e $s/site.conf ]; then
            echo "Linking $s/site.conf to conf/site.conf"
            ln -s $s/site.conf conf
        fi
    done

    generated_config=1
fi

# Handle EULA setting
EULA_ACCEPTED=

# EULA has been accepted already (ACCEPT_FSL_EULA is set in local.conf)
if grep -q '^\s*ACCEPT_FSL_EULA\s*=\s*["'\'']..*["'\'']' conf/local.conf; then--------------------------->⑨
    EULA_ACCEPTED=1
fi

if [ -z "$EULA_ACCEPTED" ] && [ -n "$EULA" ]; then
    # The FSL EULA is not set as accepted in local.conf, but the EULA
    # variable is set in the environment, so we just configure
    # ACCEPT_FSL_EULA in local.conf according to $EULA.
    echo "ACCEPT_FSL_EULA = \"$EULA\"" >> conf/local.conf
elif [ -n "$EULA_ACCEPTED" ]; then
    # The FSL EULA has been accepted once, so ACCEPT_FSL_EULA is set
    # in local.conf.  No need to do anything.
    :
else
    # THE FSL EULA is not set as accepted in local.conf, and EULA is
    # not set in the environment, so we need to ask user if he/she
    # accepts the FSL EULA:
    cat <<EOF

Some BSPs depend on libraries and packages which are covered by Freescale's
End User License Agreement (EULA). To have the right to use these binaries in
your images, you need to read and accept the following...

EOF

    sleep 4

    more -d $FSL_EULA_FILE
    echo
    REPLY=
    while [ -z "$REPLY" ]; do
        echo -n "Do you accept the EULA you just read? (y/n) "
        read REPLY
        case "$REPLY" in
            y|Y)
            echo "EULA has been accepted."
            echo "ACCEPT_FSL_EULA = \"1\"" >> conf/local.conf
            ;;
            n|N)
            echo "EULA has not been accepted."
            ;;
            *)
            REPLY=
            ;;
        esac
    done
fi

cat <<EOF

Welcome to Freescale Community BSP

The Yocto Project has extensive documentation about OE including a
reference manual which can be found at:
    http://yoctoproject.org/documentation

For more information about OpenEmbedded see their website:
    http://www.openembedded.org/

You can now run 'bitbake <target>'

Common targets are:
    core-image-minimal
    meta-toolchain
    meta-toolchain-sdk
    adt-installer
    meta-ide-support

EOF

if [ -n "$generated_config" ]; then------------------->⑩
    cat <<EOF
Your build environment has been configured with:

    MACHINE=$MACHINE
    SDKMACHINE=$SDKMACHINE
    DISTRO=$DISTRO
    EULA=$EULA
EOF
else
    echo "Your configuration files at $1 have not been touched."
fi

clean_up
setup-environment

① 命令行參數處理,如果執行腳本傳入的是-h|--help參數,打印幫助信息,退出腳本

(有關腳本如何處理命令行信息,可以參考這里

② 判斷是否是root用戶執行腳本,如果是,打印錯誤信息並退出

③ 根據構建目錄下的conf/local.conf.sample文件是否存在,判斷是否為第一次構建。如果是第一次構建build_dir_setup_enabled="true",否則build_dir_setup_enabled="false"

如果是第一次構建,但在執行腳本時沒設置MACHINE和DISTRO變量,打印錯誤提示信息,並退出腳本

④ 判斷是否設置了FSL_EULA_FILE變量(該變量表示最終用戶協議文件),如果沒設置,設置FSL_EULA_FILE=$(pwd)/sources/meta-freescale/EULA

(前面imx-setup-release.sh腳本已經設置了FSL_EULA_FILE變量,FSL_EULA_FILE=$(pwd)/sources/meta-imx/EULA.txt)   

⑤ 判斷$PWD/sources/oe-core該目錄是否存在,如果存在,OEROOT=$PWD/sources/oe-core,否則,OEROOT=$PWD/sources/poky

(此處OEROOT=$PWD/sources/poky)

⑥ $OEROOT/oe-init-build-env $CWD/$1 > /dev/null
  執行$PWD/sources/poky目錄下的oe-init-build-env腳本,執行該腳本傳入的參數是構建目錄的絕對路徑,腳本的輸出信息重定向到/dev/null(即oe-init-build-env腳本打印的內容不顯示到終端)

⑦ 重新設置PATH環境變量
        export PATH="`echo $PATH | sed 's/\(:.\|:\)*:/:/g;s/^.\?://;s/:.\?$//'`"

⑧ 如果是第一次執行配置:build_dir_setup_enabled" = "true"
        將構建目錄下conf目錄里的local.conf重新修改名字為local.conf.sample
        TEMPLATES=$CWD/sources/base/conf
        將local.conf.sample文件中那些非#開頭和$開頭的內容寫道local.conf中
        
        sed -e "s,MACHINE ??=.*,MACHINE ??= '$MACHINE',g" \
        -e "s,SDKMACHINE ??=.*,SDKMACHINE ??= '$SDKMACHINE',g" \
        -e "s,DISTRO ?=.*,DISTRO ?= '$DISTRO',g" \
        -e "s,PACKAGE_CLASSES ?=.*,PACKAGE_CLASSES ?= '$PACKAGE_CLASSES',g" \
        -i conf/local.conf

        將DL_DIR ?= "\${BSPDIR}/downloads/"插入到local.conf文件中
       
        將local.conf文件中MACHINE ??= 替換成MACHINE ??= '$MACHINE'
        DISTRO ?=.*替換成DISTRO ?= '$DISTRO'
         ...
        
        拷貝TEMPLATES描述目錄下內容(該目錄下只有一個bblayers.conf文件)到構建目錄中的conf目錄里(TEMPLATES=$CWD/sources/base/conf)

        (sources/base/conf目錄下只有一個bblaers.conf文件,拷貝該目錄下bblayers.conf文件到構建目錄的conf目錄,覆蓋了oe-buildenv-internal腳本中在構建目錄的conf目錄設置的默認的bblayers.conf文件)
        
        generated_config=1

⑨ 判斷是否是第一次構建,如果是第一次構建,打印出EULA信息,提示讓用戶接受。用戶接受后ACCEPT_FSL_EULA=1會被追加到conf/local.conf文件中

緊接着打印下面信息
        Welcome to Freescale Community BSP

        The Yocto Project has extensive documentation about OE including a
        reference manual which can be found at:
            http://yoctoproject.org/documentation

        For more information about OpenEmbedded see their website:
            http://www.openembedded.org/

        You can now run 'bitbake <target>'

        Common targets are:
            core-image-minimal
            meta-toolchain
            meta-toolchain-sdk
            adt-installer
            meta-ide-support

⑩ 如果是第一次配置(根據generated_config判斷),打印下面信息
            Your build environment has been configured with:

            MACHINE=$MACHINE
            SDKMACHINE=$SDKMACHINE
            DISTRO=$DISTRO
            EULA=$EULA

否則打印下面信息
            Your configuration files at $1 have not been touched.

2.5 imx-setup-release.sh

#!/bin/sh
#
# i.MX Yocto Project Build Environment Setup Script
#
# Copyright (C) 2011-2016 Freescale Semiconductor
# Copyright 2017 NXP
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

. sources/meta-imx/tools/setup-utils.sh

CWD=`pwd`
PROGNAME="setup-environment"
exit_message ()
{
   echo "To return to this build environment later please run:"
   echo "    source setup-environment <build_dir>"

}

usage()
{
    echo -e "\nUsage: source imx-setup-release.sh
    Optional parameters: [-b build-dir] [-h]"
echo "
    * [-b build-dir]: Build directory, if unspecified script uses 'build' as output directory
    * [-h]: help
"
}


clean_up()
{

    unset CWD BUILD_DIR FSLDISTRO
    unset fsl_setup_help fsl_setup_error fsl_setup_flag
    unset usage clean_up
    unset ARM_DIR META_FSL_BSP_RELEASE
    exit_message clean_up
}

# get command line options
OLD_OPTIND=$OPTIND
unset FSLDISTRO

while getopts "k:r:t:b:e:gh" fsl_setup_flag---------------------->(1
do
    case $fsl_setup_flag in
        b) BUILD_DIR="$OPTARG";
           echo -e "\n Build directory is " $BUILD_DIR
           ;;
        h) fsl_setup_help='true';
           ;;
        \?) fsl_setup_error='true';
           ;;
    esac
done
shift $((OPTIND-1))
if [ $# -ne 0 ]; then
    fsl_setup_error=true
    echo -e "Invalid command line ending: '$@'"
fi
OPTIND=$OLD_OPTIND
if test $fsl_setup_help; then
    usage && clean_up && return 1
elif test $fsl_setup_error; then
    clean_up && return 1
fi


if [ -z "$DISTRO" ]; then----------------------------------->(2
    if [ -z "$FSLDISTRO" ]; then
        FSLDISTRO='fsl-imx-xwayland'
    fi
else
    FSLDISTRO="$DISTRO"
fi

if [ -z "$BUILD_DIR" ]; then---------------------------------->(2
    BUILD_DIR='build'
fi

if [ -z "$MACHINE" ]; then----------------------------------->(2
    echo setting to default machine
    MACHINE='imx6qpsabresd'
fi

case $MACHINE in
imx8*)
    case $DISTRO in
    *wayland)
        : ok
        ;;
    *)
        echo -e "\n ERROR - Only Wayland distros are supported for i.MX 8 or i.MX 8M"
        echo -e "\n"
        return 1
        ;;
    esac
    ;;
*)
    : ok
    ;;
esac

# Cleanup previous meta-freescale/EULA overrides
cd $CWD/sources/meta-freescale--------------------------------------------->(3
if [ -h EULA ]; then
    echo Cleanup meta-freescale/EULA...
    git checkout -- EULA
fi
if [ ! -f classes/fsl-eula-unpack.bbclass ]; then
    echo Cleanup meta-freescale/classes/fsl-eula-unpack.bbclass...
    git checkout -- classes/fsl-eula-unpack.bbclass
fi
cd - ----------------------------------->(4

# Override the click-through in meta-freescale/EULA
FSL_EULA_FILE=$CWD/sources/meta-imx/EULA.txt---------------------->(5

# Set up the basic yocto environment
if [ -z "$DISTRO" ]; then----------------------------------------->(6
   DISTRO=$FSLDISTRO MACHINE=$MACHINE . ./$PROGNAME $BUILD_DIR
else
   MACHINE=$MACHINE . ./$PROGNAME $BUILD_DIR
fi

# Point to the current directory since the last command changed the directory to $BUILD_DIR
BUILD_DIR=.--------------------------------->(7

if [ ! -e $BUILD_DIR/conf/local.conf ]; then---------------------->(8
    echo -e "\n ERROR - No build directory is set yet. Run the 'setup-environment' script before running this script to create " $BUILD_DIR
    echo -e "\n"
    return 1
fi

# On the first script run, backup the local.conf file
# Consecutive runs, it restores the backup and changes are appended on this one.
if [ ! -e $BUILD_DIR/conf/local.conf.org ]; then------------------>(9
    cp $BUILD_DIR/conf/local.conf $BUILD_DIR/conf/local.conf.org
else
    cp $BUILD_DIR/conf/local.conf.org $BUILD_DIR/conf/local.conf
fi

echo >> conf/local.conf----------------------------------------->(10
echo "# Switch to Debian packaging and include package-management in the image" >> conf/local.conf
echo "PACKAGE_CLASSES = \"package_deb\"" >> conf/local.conf
echo "EXTRA_IMAGE_FEATURES += \"package-management\"" >> conf/local.conf

if [ ! -e $BUILD_DIR/conf/bblayers.conf.org ]; then-------------->(11
    cp $BUILD_DIR/conf/bblayers.conf $BUILD_DIR/conf/bblayers.conf.org
else
    cp $BUILD_DIR/conf/bblayers.conf.org $BUILD_DIR/conf/bblayers.conf
fi


META_FSL_BSP_RELEASE="${CWD}/sources/meta-imx/meta-bsp"--------->(12

echo "" >> $BUILD_DIR/conf/bblayers.conf
echo "# i.MX Yocto Project Release layers" >> $BUILD_DIR/conf/bblayers.conf------------------------>(13
hook_in_layer meta-imx/meta-bsp---------------------->(14
hook_in_layer meta-imx/meta-sdk
hook_in_layer meta-imx/meta-ml
hook_in_layer meta-nxp-demo-experience

echo "" >> $BUILD_DIR/conf/bblayers.conf-------------------------->(15
echo "BBLAYERS += \"\${BSPDIR}/sources/meta-browser\"" >> $BUILD_DIR/conf/bblayers.conf
echo "BBLAYERS += \"\${BSPDIR}/sources/meta-rust\"" >> $BUILD_DIR/conf/bblayers.conf
echo "BBLAYERS += \"\${BSPDIR}/sources/meta-clang\"" >> $BUILD_DIR/conf/bblayers.conf
echo "BBLAYERS += \"\${BSPDIR}/sources/meta-openembedded/meta-gnome\"" >> $BUILD_DIR/conf/bblayers.conf
echo "BBLAYERS += \"\${BSPDIR}/sources/meta-openembedded/meta-networking\"" >> $BUILD_DIR/conf/bblayers.conf
echo "BBLAYERS += \"\${BSPDIR}/sources/meta-openembedded/meta-filesystems\"" >> $BUILD_DIR/conf/bblayers.conf

echo "BBLAYERS += \"\${BSPDIR}/sources/meta-qt5\"" >> $BUILD_DIR/conf/bblayers.conf
echo "BBLAYERS += \"\${BSPDIR}/sources/meta-python2\"" >> $BUILD_DIR/conf/bblayers.conf

if [ -d ../sources/meta-ivi ]; then
    echo -e "\n## Genivi layers" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-gplv2\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-ivi/meta-ivi\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-ivi/meta-ivi-bsp\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-ivi/meta-ivi-test\"" >> $BUILD_DIR/conf/bblayers.conf
fi

echo BSPDIR=$BSPDIR----------------------------->(16
echo BUILD_DIR=$BUILD_DIR

# Support integrating community meta-freescale instead of meta-fsl-arm
if [ -d ../sources/meta-freescale ]; then-------------->(17
    echo meta-freescale directory found
    # Change settings according to environment
    sed -e "s,meta-fsl-arm\s,meta-freescale ,g" -i conf/bblayers.conf
    sed -e "s,\$.BSPDIR./sources/meta-fsl-arm-extra\s,,g" -i conf/bblayers.conf
fi

cd  $BUILD_DIR
clean_up
unset FSLDISTRO
imx-setup-release.sh

1) 命令行參數處理
    BUILD_DIR等於腳本-b選項后面的參數

2) 判斷執行腳本時,是否設置了DISTRO變量
        如果DISTRO變量沒被設置,再進一步判斷FSLDISTRO變量是否被設置
            如果FSLDISTRO變量也沒被設置,給FSLDISTRO變量指定默認值:FSLDISTRO='fsl-imx-xwayland'
        如果設置了DISTRO變量,就設置FSLDISTRO變量等於DISTRO變量內容   

        判斷執行腳本時是否設置了構建目錄,如果沒有設置,使用默認的構建目錄,BUILD_DIR=build
        判斷執行腳本時是否設置了MACHINE變量,如果MCHINE變量沒被設置,使用默認的MACHINE值,MACHINE='imx6qpsabresd'
        判斷傳入的DISTRO是否支持該MACHINE,如果不支持打印錯誤信息並退出
     (對於i.MX8系列,只支持DISTRO=fsl-imx-wayland/fsl-imx-xwayland的配置)

3) 切換到$(pwd)/sources/meta-freescale目錄
        判斷該目錄下是否存在一個名字為EULA的軟鏈接文件,如果存在,清除該文件
        判斷該目錄下的子目錄classes中是否存在fsl-eula-unpack.bbclass文件 

4) 切換回之前目錄(yocto工程存放目錄)

5) FSL_EULA_FILE=$(pwd)/sources/meta-imx/EULA.txt

6) 判斷執行腳本時是否設置了DISTRO變量
        如果沒設置,以下面方式調用setup-environment腳本
            DISTRO=$FSLDISTRO MACHINE=$MACHINE . ./setup-environment $BUILD_DIR
        否則,以下面方式調用setup-environment腳本
            MACHINE=$MACHINE . ./$setup-environment $BUILD_DIR
        執行腳本傳入的參數是構建目錄的名稱

7) BUILD_DIR=.
    (已經切換到構建目錄了,所有BUILD_DIR=.表示當前目錄)

8) 判斷構建目錄下conf目錄中local.conf是否存在,如果不存在退出。前面6)中調用了setup-environment,該文件已經被正常創建

9) 判斷$BUILD_DIR/conf/local.conf.org文件是否存在,如果第一次執行腳本配置,該文件肯定不存在
        不存在
            拷貝$BUILD_DIR/conf/local.conf文件內容到$BUILD_DIR/conf/local.conf.org文件
        存在
            拷貝$BUILD_DIR/conf/local.conf.org文件內容到$BUILD_DIR/conf/local.conf文件

備份local.conf文件內容到local.conf.org文件原因,避免下面10)中的內容被重復追加到local.conf文件

10) 追加下面信息到conf/local.conf文件
    echo >> conf/local.conf
    echo "# Switch to Debian packaging and include package-management in the image" >> conf/local.conf
    echo "PACKAGE_CLASSES = \"package_deb\"" >> conf/local.conf
    echo "EXTRA_IMAGE_FEATURES += \"package-management\"" >> conf/local.conf

11) 判斷$BUILD_DIR/conf/local.conf.org文件是否存在
        不存在
            拷貝$BUILD_DIR/conf/bblayers.conf文件內容到$BUILD_DIR/conf/bblayers.conf.org文件
        存在
            拷貝$BUILD_DIR/conf/bblayers.conf.org文件內容到$BUILD_DIR/conf/bblayers.conf文件

12) META_FSL_BSP_RELEASE="${CWD}/sources/meta-imx/meta-bsp"

13) 追加下面信息到bblayers.conf
    echo "" >> $BUILD_DIR/conf/bblayers.conf
    cho "# i.MX Yocto Project Release layers" >> $BUILD_DIR/conf/bblayers.conf

14) hook_in_layer meta-imx/meta-bsp
    hook_in_layer meta-imx/meta-sdk
    hook_in_layer meta-imx/meta-ml
    hook_in_layer meta-nxp-demo-experience
    追加下面信息到bblayers.conf,同時分別判斷meta-imx目錄下的meta-bsp、meta-sdk、meta-ml、meta-nxp-demo-experience目錄里的conf/machine和conf/machine/include里的配置是否和
    meta-freescale/conf和/meta-freescale/conf/machine/include配置名是否相同,如果相同刪除meta-freescale里的該項配置。meta-imx下內容是最新的,是對meta-freescale里的內容的更新和補充
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-imx/meta-bsp\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-imx/meta-sdk\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-imx/meta-ml\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-nxp-demo-experience\"" >> $BUILD_DIR/conf/bblayers.conf

15) 主機下面信息到bblayers.conf
    echo "" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-browser\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-rust\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-clang\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-openembedded/meta-gnome\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-openembedded/meta-networking\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-openembedded/meta-filesystems\"" >> $BUILD_DIR/conf/bblayers.conf

    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-qt5\"" >> $BUILD_DIR/conf/bblayers.conf
    echo "BBLAYERS += \"\${BSPDIR}/sources/meta-python2\"" >> $BUILD_DIR/conf/bblayers.conf

16) echo BSPDIR=$BSPDIR
    echo BUILD_DIR=$BUILD_DIR

17) 如果../sources/meta-freescale目錄存在
    echo meta-freescale directory found
    # Change settings according to environment
    sed -e "s,meta-fsl-arm\s,meta-freescale ,g" -i conf/bblayers.conf----------------->conf/bblayers.conf文件中"meta-fsl-arm "替換成"meta-freescale "
    sed -e "s,\$.BSPDIR./sources/meta-fsl-arm-extra\s,,g" -i conf/bblayers.conf------->將conf/bbylayers文件中的"${BSPDIR}/sources/meta-fsl-arm-extra "內容替換為空字符

3、總結

至此,關於執行imx-setup-release.sh腳本完成的工作分析完了。總的概況來說執行該腳本,創建了構建目錄下的conf目錄下的內容,將構建所要用到的工具集和腳本所在路徑添加到了PATH環境變量,並且設置了bitbake構建機制所使用的環境變量。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM