eosio_build.sh 执行过程

eosio_build.sh

打开eos目录结构,eosio_build.sh在 eos/scripts目录下

1.定义usage方法,该方法在cli执行出错时打印出来,

function usage() {
   printf "Usage: $0 OPTION...
  -P          Build with pinned clang and libcxx
  -o TYPE     Build <Debug|Release|RelWithDebInfo|MinSizeRel> (default: Release)
  -s NAME     Core Symbol Name <1-7 characters> (default: SYS)
  -b DIR      Use pre-built boost in DIR
  -i DIR      Directory to use for installing dependencies & EOSIO (default: $HOME)
  -y          Noninteractive mode (answers yes to every prompt)
  -c          Enable Code Coverage
  -d          Generate Doxygen
  -m          Build MongoDB dependencies
   \\n" "$0" 1>&2
   exit 1
}

2.设置执行时间

# 开始时间,获取从1970年至现在的秒数
TIME_BEGIN=$( date -u +%s )

3.验证options#判断输入参数不为0

if [ $# -ne 0 ]; then
  # 参数循环验证
   while getopts "o:s:b:i:ycdhmPf" opt; do
#case选项匹配 case "${opt}" in o )
# 构建执行选项集合 options
=( "Debug" "Release" "RelWithDebInfo" "MinSizeRel" ) # 如果匹配到options中的一个,则将CMAKE_BUILD_TYPE设置到该选项 if [[ "${options[*]}" =~ "${OPTARG}" ]]; then CMAKE_BUILD_TYPE=$OPTARG else # 不匹配,输出错误 echo "Invalid argument: ${OPTARG}" 1>&2
# 调用usage方法
usage fi ;; s ) # 如果OPTARG值不在1~7或者optage为空,输出错误,执行usage方法 if [ "${#OPTARG}" -gt 7 ] || [ -z "${#OPTARG}" ]; then echo "Invalid argument: ${OPTARG}" 1>&2 usage else
#定义变量为设置环境变量CORE_SYMBOL_NAME
CORE_SYMBOL_NAME=$OPTARG fi ;; b )
BOOST_LOCATION
=$OPTARG ;; i ) INSTALL_LOCATION=$OPTARG ;; y ) NONINTERACTIVE=true PROCEED=true ;; f ) echo "DEPRECATION NOTICE: -f will be removed in the next release..." ;; # Needs to be removed in 1.9 c ) ENABLE_COVERAGE_TESTING=true ;; d ) ENABLE_DOXYGEN=true ;; m ) ENABLE_MONGO=true ;; P ) PIN_COMPILER=true ;; h ) usage ;; ? ) echo "Invalid Option!" 1>&2 usage ;; : ) echo "Invalid Option: -${OPTARG} requires an argument." 1>&2 usage ;; * ) usage ;; esac done fi

3.将当前工作路径设置为环境变量

export CURRENT_WORKING_DIR=$(pwd) 

4.切换到上级目录也就是项目目录

cd $( dirname "${BASH_SOURCE[0]}" )/..

5.加载eosio特定的辅助函数

. ./scripts/helpers/eosio.sh

-->现在深入了解下eosio.sh

首先是这段代码

[[ -z "${ARCH}" ]] && export ARCH=$( uname )
if [[ -z "${NAME}" ]]; then
    if [[ $ARCH == "Linux" ]]; then
        [[ ! -e /etc/os-release ]] && echo "${COLOR_RED} - /etc/os-release not found! It seems you're attempting to use an unsupported Linux distribution.${COLOR_NC}" && exit 1
        # Obtain OS NAME, and VERSION
        . /etc/os-release
    elif [[ $ARCH == "Darwin" ]]; then export NAME=$(sw_vers -productName)
    else echo " ${COLOR_RED}- EOSIO is not supported for your Architecture!${COLOR_NC}" && exit 1
    fi
fi

# Setup yum and apt variables
if [[ $NAME =~ "Amazon Linux" ]] || [[ $NAME == "CentOS Linux" ]]; then
    if ! YUM=$( command -v yum 2>/dev/null ); then echo "${COLOR_RED}YUM must be installed to compile EOSIO${COLOR_NC}" && exit 1; fi
elif [[ $NAME == "Ubuntu" ]]; then
    if ! APTGET=$( command -v apt-get 2>/dev/null ); then echo "${COLOR_RED}APT-GET must be installed to compile EOSIO${COLOR_NC}" && exit 1; fi
fi

上述代码主要功能是验证操作系统,根据不同的操作系统设置不同的NAME环境变量

接着这段代码,设置eos必须的环境变量

. ./scripts/.environment
.environment内容如下
export SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export REPO_ROOT="${SCRIPT_DIR}/.."
export BUILD_DIR="${REPO_ROOT}/build"

export EOSIO_VERSION_MAJOR=$(cat $REPO_ROOT/CMakeLists.txt | grep -E "^[[:blank:]]*set[[:blank:]]*\([[:blank:]]*VERSION_MAJOR" | tail -1 | sed 's/.*VERSION_MAJOR //g' | sed 's/ //g' | sed 's/"//g' | cut -d\) -f1)
export EOSIO_VERSION_MINOR=$(cat $REPO_ROOT/CMakeLists.txt | grep -E "^[[:blank:]]*set[[:blank:]]*\([[:blank:]]*VERSION_MINOR" | tail -1 | sed 's/.*VERSION_MINOR //g' | sed 's/ //g' | sed 's/"//g' | cut -d\) -f1)
export EOSIO_VERSION_PATCH=$(cat $REPO_ROOT/CMakeLists.txt | grep -E "^[[:blank:]]*set[[:blank:]]*\([[:blank:]]*VERSION_PATCH" | tail -1 | sed 's/.*VERSION_PATCH //g' | sed 's/ //g' | sed 's/"//g' | cut -d\) -f1)
export EOSIO_VERSION_SUFFIX=$(cat $REPO_ROOT/CMakeLists.txt | grep -E "^[[:blank:]]*set[[:blank:]]*\([[:blank:]]*VERSION_SUFFIX" | tail -1 | sed 's/.*VERSION_SUFFIX //g' | sed 's/ //g' | sed 's/"//g' | cut -d\) -f1)
export EOSIO_VERSION="${EOSIO_VERSION_MAJOR}.${EOSIO_VERSION_MINOR}"
if [[ -z $EOSIO_VERSION_SUFFIX ]]; then
    export EOSIO_VERSION_FULL="${EOSIO_VERSION_MAJOR}.${EOSIO_VERSION_MINOR}.${EOSIO_VERSION_PATCH}"
else
    export EOSIO_VERSION_FULL="${EOSIO_VERSION_MAJOR}.${EOSIO_VERSION_MINOR}.${EOSIO_VERSION_PATCH}-${EOSIO_VERSION_SUFFIX}"
fi

export CMAKE_REQUIRED_VERSION=$(cat $REPO_ROOT/CMakeLists.txt | grep -E "^[[:blank:]]*cmake_minimum_required[[:blank:]]*\([[:blank:]]*VERSION" | tail -1 | sed 's/.*VERSION //g' | sed 's/ //g' | sed 's/"//g' | cut -d\) -f1)

export EOSIO_INSTALL_DIR="${HOME}/eosio/${EOSIO_VERSION}"
export TEMP_DIR="${TEMP_DIR:-${HOME}/tmp}"

[[ -f ${BUILD_DIR}/CMakeCache.txt ]] && export CACHED_INSTALL_PATH=$(grep "CMAKE_INSTALL_PREFIX:PATH" ${BUILD_DIR}/CMakeCache.txt | cut -d= -f2)
#执行.build_vars,设置环境变量
. ./scripts/.build_vars
.build_vars代码,
# See install-directory-prompt for logic that sets EOSIO_INSTALL_DIR
export SRC_DIR=${EOSIO_INSTALL_DIR}/src
export OPT_DIR=${EOSIO_INSTALL_DIR}/opt
export VAR_DIR=${EOSIO_INSTALL_DIR}/var
export ETC_DIR=${EOSIO_INSTALL_DIR}/etc
export BIN_DIR=${EOSIO_INSTALL_DIR}/bin
export LIB_DIR=${EOSIO_INSTALL_DIR}/lib
export DATA_DIR=${EOSIO_INSTALL_DIR}/data

# CMAKE
export CMAKE_VERSION_MAJOR=3
export CMAKE_VERSION_MINOR=13
export CMAKE_VERSION_PATCH=2
export CMAKE_VERSION=${CMAKE_VERSION_MAJOR}.${CMAKE_VERSION_MINOR}.${CMAKE_VERSION_PATCH}

# MONGO
export MONGODB_VERSION=3.6.3
export MONGODB_ROOT=${OPT_DIR}/mongodb-${MONGODB_VERSION}
export MONGODB_BIN=${BIN_DIR}/mongod
export MONGODB_CONF=${ETC_DIR}/mongod.conf
export MONGODB_LOG_DIR=${VAR_DIR}/log/mongodb
export MONGODB_LINK_DIR=${OPT_DIR}/mongodb
export MONGODB_DATA_DIR=${DATA_DIR}/mongodb
export MONGO_C_DRIVER_VERSION=1.13.0
export MONGO_C_DRIVER_ROOT=${SRC_DIR}/mongo-c-driver-${MONGO_C_DRIVER_VERSION}
export MONGO_CXX_DRIVER_VERSION=3.4.0
export MONGO_CXX_DRIVER_ROOT=${SRC_DIR}/mongo-cxx-driver-r${MONGO_CXX_DRIVER_VERSION}
export ENABLE_MONGO=${ENABLE_MONGO:-false}
export INSTALL_MONGO=${INSTALL_MONGO:-false}

# BOOST
export BOOST_VERSION_MAJOR=1
export BOOST_VERSION_MINOR=70
export BOOST_VERSION_PATCH=0
export BOOST_VERSION=${BOOST_VERSION_MAJOR}_${BOOST_VERSION_MINOR}_${BOOST_VERSION_PATCH}
export BOOST_ROOT=${BOOST_LOCATION:-${SRC_DIR}/boost_${BOOST_VERSION}}
export BOOST_LINK_LOCATION=${OPT_DIR}/boost

# LLVM
export LLVM_VERSION=release_40
export LLVM_ROOT=${OPT_DIR}/llvm
export LLVM_DIR=${LLVM_ROOT}/lib/cmake/llvm

# DOXYGEN
export DOXYGEN_VERSION=1_8_14
export DOXYGEN_ROOT=${SRC_DIR}/doxygen-${DOXYGEN_VERSION}
export ENABLE_DOXYGEN=${ENABLE_DOXYGEN:-false}

# CLANG
export CLANG_ROOT=${OPT_DIR}/clang8
export PINNED_COMPILER_BRANCH=release_80
export PINNED_COMPILER_LLVM_COMMIT=18e41dc
export PINNED_COMPILER_CLANG_COMMIT=a03da8b
export PINNED_COMPILER_LLD_COMMIT=d60a035
export PINNED_COMPILER_POLLY_COMMIT=1bc06e5
export PINNED_COMPILER_CLANG_TOOLS_EXTRA_COMMIT=6b34834
export PINNED_COMPILER_LIBCXX_COMMIT=1853712
export PINNED_COMPILER_LIBCXXABI_COMMIT=d7338a4
export PINNED_COMPILER_LIBUNWIND_COMMIT=57f6739
export PINNED_COMPILER_COMPILER_RT_COMMIT=5bc7979
export NO_CPP17=${NO_CPP17:-false}
export PIN_COMPILER=${PIN_COMPILER:-false}
export BUILD_CLANG=${BUILD_CLANG:-false}

export CORE_SYMBOL_NAME=${CORE_SYMBOL_NAME:-SYS}

export CPU_CORES=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu)
export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Release}

export NONINTERACTIVE=${NONINTERACTIVE:-false}
export PROCEED=${PROCEED:-false}

export CURRENT_USER=${CURRENT_USER:-$(whoami)}

export ENABLE_COVERAGE_TESTING=${ENABLE_COVERAGE_TESTING:-false}
export HOMEBREW_NO_AUTO_UPDATE=1
export TINI_VERSION=0.18.0
export DISK_MIN=5
export COUNT=0
export DRYRUN=${DRYRUN:-false}
export VERBOSE=${VERBOSE:-false}
export SUDO_LOCATION=$( command -v sudo )

从environment和build.vars可知,上述都是eosio必须的系统变量,后续可以直接根据系统变量执行相应的函数

回到eosio.sh,接下来执行

. ./scripts/helpers/general.sh

general.sh内部主要分为两类,最开始代码为

# 如果是交互式模式
if [[ $- == *i* ]]; then # Disable if the shell isn't interactive (avoids: tput: No value for $TERM and no -T specified)
  export COLOR_NC=$(tput sgr0) # No Color
  export COLOR_RED=$(tput setaf 1)
  export COLOR_GREEN=$(tput setaf 2)
  export COLOR_YELLOW=$(tput setaf 3)
  export COLOR_BLUE=$(tput setaf 4)
  export COLOR_MAGENTA=$(tput setaf 5)
  export COLOR_CYAN=$(tput setaf 6)
  export COLOR_WHITE=$(tput setaf 7)
fi

该代码是在交互式模式下进行环境变量声明,后面的代码都是一些函数定义,因为在eosio_build.sh会在general用到(ensure-sudo、ensure-git-clone)这2个函数,所以目前我们只对这几个函数进行分析

查看代码:

ensure-sudo:确保是root用户或者是普通用户根据sudo进行root授权执行

function ensure-sudo() {
  ( [[ $CURRENT_USER != "root" ]] && [[ -z $SUDO_LOCATION ]] ) && echo "${COLOR_RED}Please install the 'sudo' command before proceeding!${COLOR_NC}" && exit 1
  true 1>/dev/null # Needed
}
ensure-git-clone:确保是git代码
function ensure-git-clone() {
  if [[ ! -e "${REPO_ROOT}/.git" ]]; then
    echo "This build script only works with sources cloned from git"
    exit 1
  fi
}

回到eosio.sh,接下来也是一系列函数,这里也只关注eosio_build.sh所需的函数(ensure-which,install-directory-prompt,previous-install-prompt,prompt-mongo-install,setup)

ensure-which

 1 function ensure-which() {
 2  //如果未安装which命令
 3   if ! which ls &>/dev/null; then
 4     while true; do
 5       [[ $NONINTERACTIVE == false ]] && printf "${COLOR_YELLOW}EOSIO compiler checks require the 'which' package: Would you like for us to install it? (y/n)?${COLOR_NC}" && read -p " " PROCEED
 6       echo ""
 7       case $PROCEED in
 8           "" ) echo "What would you like to do?";;
 9           0 | true | [Yy]* ) install-package which WETRUN; break;;
10           1 | false | [Nn]* ) echo "${COLOR_RED}Please install the 'which' command before proceeding!${COLOR_NC}"; exit 1;;
11           * ) echo "Please type 'y' for yes or 'n' for no.";;
12       esac
13     done
14   fi
15 }

 

该方法是确保linux有which命令,如果没有,则根据选择是否安装which命令,安装which命令,关键代码在第10行这段代码

install-package which WETRUN;

其中install-package是通用方法,方法在general.sh中

 1 function install-package() {
 2   if [[ $ARCH == "Linux" ]]; then
 3     EXECUTION_FUNCTION="execute"
 4     [[ $2 == "WETRUN" ]] && EXECUTION_FUNCTION="execute-always"
 5     ( [[ $2 =~ "--" ]] || [[ $3 =~ "--" ]] ) && OPTIONS="${2}${3}"
 6     [[ $CURRENT_USER != "root" ]] && [[ ! -z $SUDO_LOCATION ]] && NEW_SUDO_COMMAND="$SUDO_LOCATION -E"
 7     ( [[ $NAME =~ "Amazon Linux" ]] || [[ $NAME == "CentOS Linux" ]] ) && eval $EXECUTION_FUNCTION $NEW_SUDO_COMMAND $YUM $OPTIONS install -y $1
 8     ( [[ $NAME =~ "Ubuntu" ]] ) && eval $EXECUTION_FUNCTION $NEW_SUDO_COMMAND $APTGET $OPTIONS install -y $1
 9   fi
10   true # Required; Weird behavior without it
11 }

仔细分析install-package方法第4行和install-package which WETRUN命令,知道

EXECUTION_FUNCTION="execute-always"

然后分析第6行,验证root用户和root权限用户,第7、8行主要时构建安装命令以及执行安装命令,

eval作用:可读取一连串的参数,然后再依参数本身的特性来执行

如果不是root用户,则 Amazon Linux或CentOS Linux eval命令如下

execute-always /usr/bin/sudo -E yum install -y which

ubuntu系统安装命令如下

execute-always /usr/bin/sudo -E yum apt-get -y which

其中 execute-always,方法也在general.sh中,代码如下

 1 function execute-always() {
 2   ORIGINAL_DRYRUN=$DRYRUN
 3   DRYRUN=false
 4   execute "$@"
 5   DRYRUN=$ORIGINAL_DRYRUN
 6 }
 7 
 8 function execute() {
 9   $VERBOSE && echo "--- Executing: $@"
10   $DRYRUN || "$@"
11 }

这里也把内部执行方法execute贴出来,这里时作一些准备工作,主要时必要时打印参数

接着分析install-directory-prompt方法,代码如下

function install-directory-prompt() {
    if [[ -z $INSTALL_LOCATION ]]; then
        echo "No installation location was specified. Please provide the location where EOSIO is installed."
        while true; do
            [[ $NONINTERACTIVE == false ]] && printf "${COLOR_YELLOW}Do you wish to use the default location? ${EOSIO_INSTALL_DIR}? (y/n)${COLOR_NC}" && read -p " " PROCEED
            echo ""
            case $PROCEED in
                "" )
                echo "What would you like to do?";;
                0 | true | [Yy]* )
                break;;
                1 | false | [Nn]* )
                printf "Enter the desired installation location." && read -p " " EOSIO_INSTALL_DIR;
                export EOSIO_INSTALL_DIR;
                break;;
                * ) echo "Please type 'y' for yes or 'n' for no.";;
            esac
        done
    else
        # 这里时支持相对路径
        [[ ! $INSTALL_LOCATION =~ ^\/ ]] && export INSTALL_LOCATION="${CURRENT_WORKING_DIR}/$INSTALL_LOCATION"
        export EOSIO_INSTALL_DIR="$INSTALL_LOCATION"
    fi
    . ./scripts/.build_vars
    echo "EOSIO will be installed to: ${EOSIO_INSTALL_DIR}"
}

该 方法时设置EOSIO安装目录,可以使用默认安装目录,也可以自定义安装目录。然后重新设置.build_vars中的环境变量

previous-install-promp:安装确认

function  previous-install-prompt() {
  if [[ -d $EOSIO_INSTALL_DIR ]]; then
    echo "EOSIO has already been installed into ${EOSIO_INSTALL_DIR}... It's suggested that you eosio_uninstall.sh before re-running this script."
    while true; do
      [[ $NONINTERACTIVE == false ]] && printf "${COLOR_YELLOW}Do you wish to proceed anyway? (y/n)${COLOR_NC}" && read -p " " PROCEED
      echo ""
      case $PROCEED in
        "" ) echo "What would you like to do?";;
        0 | true | [Yy]* ) break;;
        1 | false | [Nn]* ) exit;;
        * ) echo "Please type 'y' for yes or 'n' for no.";;
      esac
      done
  fi
}

promp-mongo-install:mongo db安装确认

function prompt-mongo-install() {
    if $ENABLE_MONGO; then
        while true; do
            [[ $NONINTERACTIVE == false ]] && printf "${COLOR_YELLOW}You have chosen to include MongoDB support. Do you want for us to install MongoDB as well? (y/n)?${COLOR_NC}" && read -p " " PROCEED
            echo ""
            case $PROCEED in
                "" ) echo "What would you like to do?";;
                0 | true | [Yy]* ) export INSTALL_MONGO=true; break;;
                1 | false | [Nn]* ) echo "${COLOR_RED} - Existing MongoDB will be used.${COLOR_NC}"; break;;
                * ) echo "Please type 'y' for yes or 'n' for no.";;
            esac
        done
    fi
}

setup:创建安装目录

function setup() {
#打印待创建目录信息
if $VERBOSE; then echo "VERBOSE: ${VERBOSE}" echo "DRYRUN: ${DRYRUN}" echo "TEMP_DIR: ${TEMP_DIR}" echo "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}" echo "CORE_SYMBOL_NAME: ${CORE_SYMBOL_NAME}" echo "BOOST_LOCATION: ${BOOST_LOCATION}" echo "INSTALL_LOCATION: ${INSTALL_LOCATION}" echo "BUILD_DIR: ${BUILD_DIR}" echo "EOSIO_INSTALL_DIR: ${EOSIO_INSTALL_DIR}" echo "NONINTERACTIVE: ${NONINTERACTIVE}" echo "PROCEED: ${PROCEED}" echo "ENABLE_COVERAGE_TESTING: ${ENABLE_COVERAGE_TESTING}" echo "ENABLE_DOXYGEN: ${ENABLE_DOXYGEN}" echo "ENABLE_MONGO: ${ENABLE_MONGO}" echo "INSTALL_MONGO: ${INSTALL_MONGO}" echo "SUDO_LOCATION: ${SUDO_LOCATION}" echo "PIN_COMPILER: ${PIN_COMPILER}" fi
#如果有删除旧的build目录 ( [[ -d $BUILD_DIR ]] && [[ -z $BUILD_DIR_CLEANUP_SKIP ]] ) && execute rm -rf $BUILD_DIR # cleanup old build directory; support disabling it (Zach requested) execute-always mkdir -p $TEMP_DIR execute mkdir -p $BUILD_DIR execute mkdir -p $SRC_DIR execute mkdir -p $OPT_DIR execute mkdir -p $VAR_DIR execute mkdir -p $BIN_DIR execute mkdir -p $VAR_DIR/log execute mkdir -p $ETC_DIR execute mkdir -p $LIB_DIR if $ENABLE_MONGO; then execute mkdir -p $MONGODB_LOG_DIR execute mkdir -p $MONGODB_DATA_DIR fi }

创建目录参考.build.vars

# See install-directory-prompt for logic that sets EOSIO_INSTALL_DIR
export SRC_DIR=${EOSIO_INSTALL_DIR}/src
export OPT_DIR=${EOSIO_INSTALL_DIR}/opt
export VAR_DIR=${EOSIO_INSTALL_DIR}/var
export ETC_DIR=${EOSIO_INSTALL_DIR}/etc
export BIN_DIR=${EOSIO_INSTALL_DIR}/bin
export LIB_DIR=${EOSIO_INSTALL_DIR}/lib
export DATA_DIR=${EOSIO_INSTALL_DIR}/data

export MONGODB_LOG_DIR=${VAR_DIR}/log/mongodb
export MONGODB_DATA_DIR=${DATA_DIR}/mongodb

检查git文件是否存在

function ensure-git-clone() {
  if [[ ! -e "${REPO_ROOT}/.git" ]]; then
    echo "This build script only works with sources cloned from git"
    exit 1
  fi
}

回到eosio_build.sh,接下来 的代码是

# 打印版本,eos版本,日期,当前用户,git分支等
$VERBOSE && echo "Build Script Version: ${SCRIPT_VERSION}" echo "EOSIO Version: ${EOSIO_VERSION_FULL}" echo "$( date -u )" echo "User: ${CURRENT_USER}" # echo "git head id: %s" "$( cat .git/refs/heads/master )" echo "Current branch: $( execute git rev-parse --abbrev-ref HEAD 2>/dev/null )" # 如果是ubuntu或者是darwin系统,则 ( [[ ! $NAME == "Ubuntu" ]] && [[ ! $ARCH == "Darwin" ]] ) && set -i # Ubuntu doesn't support interactive mode since it uses dash + Some folks are having this issue on Darwin; colors aren't supported yet anyway # 从之前的函数介绍,可以知道调用的方法内部逻辑 # 使用sudo调用root权限 ensure-sudo # 如果没有which命令,则安装 ensure-which # 防止运行非git克隆 ensure-git-clone # 提示用户安装路径install-directory-prompt #验证相同版本安装 previous-install-prompt # 是否安装mongo prompt-mongo-install # 设置目录和必须的环境 setup
#切换到项目目录
execute cd $REPO_ROOT

# 验证子模块是否更新
ensure-submodules-up-to-date
验证cmake是否安装,安装是否符合安装版本(3.8)
( [[ -z "${CMAKE}" ]] && [[ ! -z $(command -v cmake 2>/dev/null) ]] ) && export CMAKE=$(command -v cmake 2>/dev/null) && export CMAKE_CURRENT_VERSION=$($CMAKE --version | grep -E "cmake version[[:blank:]]*" | sed 's/.*cmake version //g')
# If it exists, check that it's > required version + 
if [[ ! -z $CMAKE_CURRENT_VERSION ]] && [[ $((10#$( echo $CMAKE_CURRENT_VERSION | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }' ))) -lt $((10#$( echo $CMAKE_REQUIRED_VERSION | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }' ))) ]]; then
   export CMAKE=
   if [[ $ARCH == 'Darwin' ]]; then
      echo "${COLOR_RED}The currently installed cmake version ($CMAKE_CURRENT_VERSION) is less than the required version ($CMAKE_REQUIRED_VERSION). Cannot proceed."
      exit 1
   else
      echo "${COLOR_YELLOW}The currently installed cmake version ($CMAKE_CURRENT_VERSION) is less than the required version ($CMAKE_REQUIRED_VERSION). We will be installing $CMAKE_VERSION.${COLOR_NC}"
   fi
fi

接下来是安装特定的操作系统进行build(build内容之后再介绍)

if [[ $ARCH == "Linux" ]]; then
   export CMAKE=${CMAKE:-${EOSIO_INSTALL_DIR}/bin/cmake}
   OPENSSL_ROOT_DIR=/usr/include/openssl
   [[ ! -e /etc/os-release ]] && print_supported_linux_distros_and_exit
   case $NAME in
      "Amazon Linux AMI" | "Amazon Linux")
         echo "${COLOR_CYAN}[Ensuring YUM installation]${COLOR_NC}"
         FILE="${REPO_ROOT}/scripts/eosio_build_amazonlinux.sh"
      ;;
      "CentOS Linux")
         FILE="${REPO_ROOT}/scripts/eosio_build_centos.sh"
      ;;
      "Ubuntu")
         FILE="${REPO_ROOT}/scripts/eosio_build_ubuntu.sh"
      ;;
      *) print_supported_linux_distros_and_exit;;
   esac
   CMAKE_PREFIX_PATHS="${EOSIO_INSTALL_DIR}"
fi

if [ "$ARCH" == "Darwin" ]; then
   # opt/gettext: cleos requires Intl, which requires gettext; it's keg only though and we don't want to force linking: https://github.com/EOSIO/eos/issues/2240#issuecomment-396309884
   # EOSIO_INSTALL_DIR/lib/cmake: mongo_db_plugin.cpp:25:10: fatal error: 'bsoncxx/builder/basic/kvp.hpp' file not found
   CMAKE_PREFIX_PATHS="/usr/local/opt/gettext;${EOSIO_INSTALL_DIR}"
   FILE="${SCRIPT_DIR}/eosio_build_darwin.sh"
   OPENSSL_ROOT_DIR=/usr/local/opt/openssl
   export CMAKE=${CMAKE}
fi

在pinned_toolchain中查找并替换OPT_DIR.cmake,然后将其移动到build dir

execute bash -c "sed -e 's~@~$OPT_DIR~g' $SCRIPT_DIR/pinned_toolchain.cmake &> $BUILD_DIR/pinned_toolchain.cmake"

其中pinned_toolchain.cmake内容如下:

# 赋值变量
set(OPT_PATH @) set(CMAKE_C_COMPILER_WORKS
1) set(CMAKE_CXX_COMPILER_WORKS 1) set(CMAKE_C_COMPILER ${OPT_PATH}/clang8/bin/clang) set(CMAKE_CXX_COMPILER ${OPT_PATH}/clang8/bin/clang++) set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${OPT_PATH}/clang8/include/c++/v1 /usr/local/include /usr/include) set(CMAKE_CXX_FLAGS_INIT "-nostdinc++") set(CMAKE_EXE_LINKER_FLAGS_INIT "-stdlib=libc++ -nostdlib++") set(CMAKE_SHARED_LINKER_FLAGS_INIT "-stdlib=libc++ -nostdlib++") set(CMAKE_MODULE_LINKER_FLAGS_INIT "-stdlib=libc++ -nostdlib++") set(CMAKE_CXX_STANDARD_LIBRARIES "${OPT_PATH}/clang8/lib/libc++.a ${OPT_PATH}/clang8/lib/libc++abi.a")

有关CMAKE的内容需要对CMAKE有一定了解,请自行查询相关资料,这里简要介绍就是进行对应赋值,类似于常规编程语言的map,set命令左边为key,右边为value,供之后cmake实际调用准备数据,

接下来,切换到build/src目录,设置系统变量,从注释可以看出主要是设置job,内存,硬盘可用空间等:

echo "${COLOR_CYAN}====================================================================================="
echo "======================= ${COLOR_WHITE}Starting EOSIO Dependency Install${COLOR_CYAN} ===========================${COLOR_NC}"
execute cd $SRC_DIR
set_system_vars # JOBS, Memory, disk space available, etc

核心在set_system_vars,源码如下

 1 function set_system_vars() {
 2     if [[ $ARCH == "Darwin" ]]; then
 3         export OS_VER=$(sw_vers -productVersion)
 4         export OS_MAJ=$(echo "${OS_VER}" | cut -d'.' -f1)
 5         export OS_MIN=$(echo "${OS_VER}" | cut -d'.' -f2)
 6         export OS_PATCH=$(echo "${OS_VER}" | cut -d'.' -f3)
 7         export MEM_GIG=$(bc <<< "($(sysctl -in hw.memsize) / 1024000000)")
 8         export DISK_INSTALL=$(df -h . | tail -1 | tr -s ' ' | cut -d\  -f1 || cut -d' ' -f1)
 9         export blksize=$(df . | head -1 | awk '{print $2}' | cut -d- -f1)
10         export gbfactor=$(( 1073741824 / blksize ))
11         export total_blks=$(df . | tail -1 | awk '{print $2}')
12         export avail_blks=$(df . | tail -1 | awk '{print $4}')
13         export DISK_TOTAL=$((total_blks / gbfactor ))
14         export DISK_AVAIL=$((avail_blks / gbfactor ))
15     else
16         export DISK_INSTALL=$( df -h . | tail -1 | tr -s ' ' | cut -d\  -f1 )
17         export DISK_TOTAL_KB=$( df . | tail -1 | awk '{print $2}' )
18         export DISK_AVAIL_KB=$( df . | tail -1 | awk '{print $4}' )
19         export MEM_GIG=$(( ( ( $(cat /proc/meminfo | grep MemTotal | awk '{print $2}') / 1000 ) / 1000 ) ))
20         export DISK_TOTAL=$(( DISK_TOTAL_KB / 1048576 ))
21         export DISK_AVAIL=$(( DISK_AVAIL_KB / 1048576 ))
22     fi
23     export JOBS=${JOBS:-$(( MEM_GIG > CPU_CORES ? CPU_CORES : MEM_GIG ))}
24 }

因为一般是linux系统,所以重点在16到21,以及23行,分别为


#硬盘安装地址,centos在/dev/mapper/centos-root,ubuntu在/dev/vda1
export DISK_INSTALL=$( df -h . | tail -1 | tr -s ' ' | cut -d\ -f1 )
#硬盘总空间(KB)
export DISK_TOTAL_KB=$( df . | tail -1 | awk '{print $2}' )
#硬盘可用空间(KB)
export DISK_AVAIL_KB=$( df . | tail -1 | awk '{print $4}' )
#总内存(G)
export MEM_GIG=$(( ( ( $(cat /proc/meminfo | grep MemTotal | awk '{print $2}') / 1000 ) / 1000 ) ))
#磁盘空间(GB)
export DISK_TOTAL=$(( DISK_TOTAL_KB / 1048576 ))
#可用磁盘空间(GB)
export DISK_AVAIL=$(( DISK_AVAIL_KB / 1048576 ))
#可用工作线程,其中CPU_CORES=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu)
export JOBS=${JOBS:-$(( MEM_GIG > CPU_CORES ? CPU_CORES : MEM_GIG ))}

其实就是对操作系统性能进行评估,可以make并发几个线程

接下来的代码,执行对应操作系统的build

echo "Architecture: ${ARCH}"
. $FILE # Execute OS specific build file

之后就是设置cmake变量

echo ""
echo "${COLOR_CYAN}========================================================================"
echo "======================= ${COLOR_WHITE}Starting EOSIO Build${COLOR_CYAN} ===========================${COLOR_NC}"
if $VERBOSE; then
   echo "CXX: $CXX"
   echo "CC: $CC"
fi
execute cd $BUILD_DIR
# LOCAL_CMAKE_FLAGS
$ENABLE_MONGO && LOCAL_CMAKE_FLAGS="-DBUILD_MONGO_DB_PLUGIN=true ${LOCAL_CMAKE_FLAGS}" # Enable Mongo DB Plugin if user has enabled -m
if $PIN_COMPILER; then
   CMAKE_PREFIX_PATHS="${CMAKE_PREFIX_PATHS};${LLVM_ROOT}"
   LOCAL_CMAKE_FLAGS="${PINNED_TOOLCHAIN} -DCMAKE_PREFIX_PATH='${CMAKE_PREFIX_PATHS}' ${LOCAL_CMAKE_FLAGS}"
else
   LOCAL_CMAKE_FLAGS="-DCMAKE_CXX_COMPILER='${CXX}' -DCMAKE_C_COMPILER='${CC}' -DCMAKE_PREFIX_PATH='${CMAKE_PREFIX_PATHS}' ${LOCAL_CMAKE_FLAGS}"
fi
$ENABLE_DOXYGEN && LOCAL_CMAKE_FLAGS="-DBUILD_DOXYGEN='${DOXYGEN}' ${LOCAL_CMAKE_FLAGS}"
$ENABLE_COVERAGE_TESTING && LOCAL_CMAKE_FLAGS="-DENABLE_COVERAGE_TESTING='${ENABLE_COVERAGE_TESTING}' ${LOCAL_CMAKE_FLAGS}"

上述比较复杂,主要是构建build所需的变量,后面是实际的build过程,CMAKE需要对CMAKE有相应的了解,请自行查阅资料

execute bash -c "$CMAKE -DCMAKE_BUILD_TYPE='${CMAKE_BUILD_TYPE}' -DCORE_SYMBOL_NAME='${CORE_SYMBOL_NAME}' -DOPENSSL_ROOT_DIR='${OPENSSL_ROOT_DIR}' -DCMAKE_INSTALL_PREFIX='${EOSIO_INSTALL_DIR}' ${LOCAL_CMAKE_FLAGS} '${REPO_ROOT}'"
execute make -j$JOBS
execute cd $REPO_ROOT 1>/dev/null

最后是打印build结果

TIME_END=$(( $(date -u +%s) - $TIME_BEGIN ))

echo " _______  _______  _______ _________ _______"
echo "(  ____ \(  ___  )(  ____   __   __ (  ___  )"
echo "| (    \/| (   ) || (    \/   ) (   | (   ) |"
echo "| (__    | |   | || (_____    | |   | |   | |"
echo "|  __)   | |   | |(_____  )   | |   | |   | |"
echo "| (      | |   | |      ) |   | |   | |   | |"
echo "| (____/\| (___) |/\____) |___) (___| (___) |"
echo "(_______/(_______)\_______)\_______/(_______)"
echo "=============================================${COLOR_NC}"

echo "${COLOR_GREEN}EOSIO has been successfully built. $(($TIME_END/3600)):$(($TIME_END%3600/60)):$(($TIME_END%60))"
echo "${COLOR_GREEN}You can now install using: ${SCRIPT_DIR}/eosio_install.sh${COLOR_NC}"
echo "${COLOR_YELLOW}Uninstall with: ${SCRIPT_DIR}/eosio_uninstall.sh${COLOR_NC}"

echo ""
echo "${COLOR_CYAN}If you wish to perform tests to ensure functional code:${COLOR_NC}"
if $ENABLE_MONGO; then
   echo "${BIN_DIR}/mongod --dbpath ${MONGODB_DATA_DIR} -f ${MONGODB_CONF} --logpath ${MONGODB_LOG_DIR}/mongod.log &"
   PATH_TO_USE=" PATH=\$PATH:$OPT_DIR/mongodb/bin"
fi
echo "cd ${BUILD_DIR} && ${PATH_TO_USE} make test" # PATH is set as currently 'mongo' binary is required for the mongodb test

echo ""
resources

其中resources代码在eosio.sh中,是实现打印资源地址。代码如下

function resources() {
    echo "${COLOR_CYAN}EOSIO website:${COLOR_NC} https://eos.io"
    echo "${COLOR_CYAN}EOSIO Telegram channel:${COLOR_NC} ...(由于含有违规内容,故没有贴出来)"
    echo "${COLOR_CYAN}EOSIO resources:${COLOR_NC} https://eos.io/resources/"
    echo "${COLOR_CYAN}EOSIO Stack Exchange:${COLOR_NC} https://eosio.stackexchange.com"
}

整个eosio整体build过程就分析完了,接下来会重点介绍下eosio_build_centos.sh的执行过程。 

posted @ 2019-11-11 21:13  重设代码的天空  阅读(898)  评论(0编辑  收藏  举报