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的执行过程。