一、工具链基础介绍

1.1 工具链下载

repo init -u https://gitee.com/OpenHarmony/manifest.git -b master -m llvm-toolchain.xml

repo sync -c

repo forall -c 'git lfs pull'

repo start master --all

1.2 环境配置

下载clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz为github网址,当前已经下载了,可以直接使用

bash ./toolchain/llvm-project/llvm-build/env_prepare.sh

1.3 安装依赖

1.3.1 基础组件安装

sudo apt-get install autoconf

sudo apt-get install automake

sudo apt-get install autotools-dev

sudo apt-get install texinfo

sudo apt-get install libncursesw5-dev

sudo apt-get install swig3.0

sudo apt-get install liblzma-dev

sudo apt-get install liblua5.3-dev

sudo apt-get install libedit-dev

sudo apt-get install libsphinxbase-dev

sudo apt-get install lzma-dev

sudo apt-get install swig

sudo apt-get install lua5.1

sudo apt-get install liblua5.1-dev

sudo apt install libncurses5

sudo apt install python3-sphinx

python3 -m pip install pyyaml

pip3 install -U Sphinx -i https://mirrors.aliyun.com/pypi/simple

pip3 install recommonmark -i https://mirrors.aliyun.com/pypi/simple

1.4 工具链编译

1.4.1 clang15.0.4版本全量编译

python3 ./toolchain/llvm-project/llvm-build/build.py

1.4.2 clang15.0.4版本不编译windows平台

python3 ./toolchain/llvm-project/llvm-build/build.py --no-build windows

1.4.3 clang12.0.1版本全量编译

【Note】:该版本编译不支持gtx30xx系列显卡的电脑编译

# 方法一:官方指导

repo init -u https://gitee.com/OpenHarmony/manifest.git -b master -m llvm-toolchain.xml

# 将.repo/manifests/llvm-toolchain.xml文件内容替换成https://repo.huaweicloud.com/harmonyos/compiler/clang/12.0.1-1971c8/manifest-20230313.xml里面内容

repo sync -c

repo forall -c 'git lfs pull'

./toolchain/llvm-project/llvm-build/env_prepare.sh

python3 ./toolchain/llvm-project/llvm-build/build.py

# 方法二:本地指导

二、工具链脚本介绍

文档作为基于x86_64的Ubuntu20.04环境的解析,对于windows以及mac下编译直接忽略

2.1 env_prepare.sh脚本解析

脚本路径:toolchain/llvm-project/llvm-build/env_prepare.sh

Ubuntu下功能:

下载cmake解压到prebuilts/cmake/linux-x86里面 下载llvm解压到prebuilts/clang/ohos/linux-x86_64 下载clang解压到prebuilts/clang/ohos/linux-x86_64 重命名prebuilts/clang/ohos/linux-x86_64/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04为prebuilts/clang/ohos/linux-x86_64/clang-10.0.1

2.1.1 设置host_platform

当前是在Ubuntu中编译,所以host_platform=linux

case $(uname -s) in

  Linux)

       host_platform=linux

      ;;

  Darwin)

       host_platform=darwin

      ;;

  *)

       echo "Unsupported host platform: $(uname -s)"

       exit 1

esac

2.1.2 设置host_cpu

当前使用的是x86_64,所以host_cpu=x86_64

case $(uname -m) in

  arm64)

       host_cpu=arm64

      ;;

  *)

       host_cpu=x86_64

esac

2.1.3 设置当前根目录路径code_dir

code_dir=$(pwd)

2.1.4 设置并创建下载安装包目录bin_dir

bin_dir=${code_dir}/download_packages

if [ ! -d "${bin_dir}" ];then

   mkdir -p "${bin_dir}"

fi

2.1.5 download_and_archive函数介绍

下载文件并解压

function download_and_archive() {

archive_dir=$1

download_source_url=$2

# 获取download_source_url链接中的文件名,默认以/为分隔符

bin_file=$(basename ${download_source_url})

# 下载download_source_ur里的内容保存到${bin_dir}/${bin_file}文件中

# -t3表示最大尝试链接次数为3次

# -T10设定响应超时的秒数为10s

# -O 把文档写到FILE文件中

wget -t3 -T10 -O "${bin_dir}/${bin_file}" "${download_source_url}"

if [ ! -d "${code_dir}/${archive_dir}" ];then

mkdir -p "${code_dir}/${archive_dir}"

fi

# ${bin_file:0-3}表示获取bin_file的最后3个字符

if [ "X${bin_file:0-3}" = "Xzip" ];then

unzip -o "${bin_dir}/${bin_file}" -d "${code_dir}/${archive_dir}/"

elif [ "X${bin_file:0-6}" = "Xtar.gz" ];then

tar -xvzf "${bin_dir}/${bin_file}" -C "${code_dir}/${archive_dir}"

else

tar -xvf "${bin_dir}/${bin_file}" -C "${code_dir}/${archive_dir}"

fi

}

2.1.6 配置下载路径和链接

copy_config="""

"""

copy_config_linux_x86_64="""

prebuilts/cmake,https://mirrors.huaweicloud.com/harmonyos/compiler/cmake/3.16.5/${host_platform}/cmake-${host_platform}-x86-3.16.5.tar.gz

prebuilts/clang/ohos/${host_platform}-${host_cpu},https://mirrors.huaweicloud.com/openharmony/compiler/clang/10.0.1-62608/${host_platform}/llvm.tar.gz

prebuilts/clang/ohos/${host_platform}-${host_cpu},https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz

"""

copy_config_darwin_x86_64="""

prebuilts/cmake,https://mirrors.huaweicloud.com/harmonyos/compiler/cmake/3.16.5/${host_platform}/cmake-${host_platform}-x86-3.16.5.tar.gz

prebuilts/clang/ohos/${host_platform}-${host_cpu},https://github.com/llvm/llvm-project/releases/download/llvmorg-12.0.0/clang+llvm-12.0.0-x86_64-apple-darwin.tar.xz

"""

if [[ "${host_platform}" == "linux" ]]; then

   if [[ "${host_cpu}" == "x86_64" ]]; then

      copy_config+=${copy_config_linux_x86_64}

       echo "add ubuntu here"

   else

       echo "unknwon host_cpu - ${host_cpu} for linux"

   fi

elif [[ "${host_platform}" == "darwin" ]]; then

   if [[ "${host_cpu}" == "x86_64" ]]; then

      copy_config+=${copy_config_darwin_x86_64}

       echo "add x86-64 mac here"

   elif [[ "${host_cpu}" == "arm64" ]]; then

       echo "add m1 config here"

   else

       echo "unknwon host_cpu - ${host_cpu} for darwin"

   fi

else

   echo "unknown ${host_platform}"

fi

# 当前配置完成后

copy_config="""

prebuilts/cmake,https://mirrors.huaweicloud.com/harmonyos/compiler/cmake/3.16.5/${host_platform}/cmake-${host_platform}-x86-3.16.5.tar.gz

prebuilts/clang/ohos/${host_platform}-${host_cpu},https://mirrors.huaweicloud.com/openharmony/compiler/clang/10.0.1-62608/${host_platform}/llvm.tar.gz

prebuilts/clang/ohos/${host_platform}-${host_cpu},https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz

"""

2.1.7 下载代码

for i in $(echo ${copy_config})

do

   unzip_dir=$(echo $i|awk -F ',' '{print $1}')

   remote_url=$(echo $i|awk -F ',' '{print $2}')

  download_and_archive "${unzip_dir}" "${remote_url}"

done

2.1.8 配置工具链

# 不执行

if [ -d "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-62608" ];then

   rm -rf "${code_dir}/prebuilts/clang/ohos/linux-x86_64/llvm"

   mv "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-62608" "${code_dir}/prebuilts/clang/ohos/linux-x86_64/llvm"

   ln -snf 10.0.1 "${code_dir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib/clang/current"

fi

# 执行

if [ -d "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04" ];then

   rm -rf "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-10.0.1"

   mv "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04" "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-10.0.1"

fi

# 不执行

if [ -d "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang+llvm-12.0.0-x86_64-apple-darwin" ];then

   rm -rf "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang-10.0.1"

   mv "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang+llvm-12.0.0-x86_64-apple-darwin" "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang-10.0.1"

fi

2.2 build.py脚本解析

2.2.1 BuildConfig类解析

2.2.1.1 parse_args方法解析

定义所有编译的参数选项,然后返回该对象,从返回的对象中可以获取编译选项的状态

def parse_args(self):

# description 用于描述该程序用来做什么

   parser = argparse.ArgumentParser(description='Process some integers.')

   # Options to skip build or packaging, can't skip two

   # 创建一个互斥组,确保互斥组中只有一个参数在命令行中可用

   # 参考用例:https://blog.csdn.net/weixin_36670529/article/details/113783239

   build_package_group = parser.add_mutually_exclusive_group()

   build_package_group.add_argument(

       '--skip-build',

       '-sb',

       action='store_true',

       default=False,

       help='Omit the build, perform the packaging step directly.')

   build_package_group.add_argument(

       '--skip-package',

       '-sp',

       action='store_true',

       default=False,

       help='Omit the packaging, perform the packaging step directly.')

   self.parse_add_argument(parser)

   known_platforms = ('windows', 'libs', 'lldb-mi', 'lldb-server', 'linux', 'check-api')

   # 将known_platforms的值以, + 空格串联起来,结果为"windows, libs, lldb-mi, lldb-server, linux, check-api"

   known_platforms_str = ', '.join(known_platforms)

   class SeparatedListByCommaAction(argparse.Action):

       # 把类当做一个方法使用

       # 参考用例:https://zhuanlan.zhihu.com/p/165245990

       def __call__(self, parser, namespace, vals, option_string):

           for val in vals.split(','):

               if val in known_platforms:

                   continue

               else:

                   error = '\'{}\' invalid. Choose from {}'.format(val, known_platforms)

                   raise argparse.ArgumentError(self, error)

           setattr(namespace, self.dest, vals.split(','))

   parser.add_argument(

       '--no-build',

       action=SeparatedListByCommaAction,

       default=list(),

       help='Don\'t build toolchain for specified platforms. Choices: ' + known_platforms_str)

   return parser.parse_args()

2.2.1.2 parse_add_argument方法解析

增加运行命令的可能参数

@staticmethod

def parse_add_argument(parser):

   parser.add_argument(

       '--enable-assertions',

       action='store_true',

       default=False,

       help='Apply assertions, some parameters are affected.')

   parser.add_argument(

       '--build-name',

       default='dev',

       help='Release name for the package.')

   parser.add_argument(

       '--debug',

       action='store_true',

       default=False,

       help='Building Clang and LLVM Tools for Debugging (only affects stage2)')

   parser.add_argument(

       '--strip',

       action='store_true',

       default=False,

       help='Strip final LLVM binaries.')

   parser.add_argument(

       '--no-build-arm',

       action='store_true',

       default=False,

       help='Omit build os target: arm.')

   parser.add_argument(

       '--no-build-aarch64',

       action='store_true',

       default=False,

       help='Omit build os target: aarch64.')

   parser.add_argument(

       '--no-build-riscv64',

       action='store_true',

       default=False,

       help='Omit build os target: 64-bit RISC-V.')

   parser.add_argument(

       '--no-build-mipsel',

       action='store_true',

       default=False,

       help='Omit build os target: mipsel.')

   parser.add_argument(

       '--no-build-x86_64',

       action='store_true',

       default=False,

       help='Omit build os target: x86_64.')

   parser.add_argument(

       '--no-lto',

       action='store_true',

       default=False,

       help='Accelerate builds by disabling LTO (only affects llvm product)')

   parser.add_argument(

       '--build-instrumented',

       action='store_true',

       default=False,

       help='Using the PGO instrumentation to build LLVM tool')

   parser.add_argument(

       '--xunit-xml-output',

       default=None,

       help='Output path for LLVM unit tests XML report')

2.2.1.3 discover_paths方法解析

设置各种路径

def discover_paths(self):

# 获取当前脚本所在目录的绝对路径

self.LLVM_BUILD_DIR = os.path.abspath(os.path.dirname(__file__))

# 获取脚本所在的目录的父目录名称

parent_of_llvm_build = os.path.basename(os.path.dirname(self.LLVM_BUILD_DIR))

if parent_of_llvm_build == 'toolchain':

# 设置编译root路径

self.REPOROOT_DIR = os.path.abspath(os.path.join(self.LLVM_BUILD_DIR, '../..'))

else:

assert parent_of_llvm_build == 'llvm-project'

self.REPOROOT_DIR = os.path.abspath(os.path.join(self.LLVM_BUILD_DIR, '../../..'))

# 设置llvm-project路径

self.LLVM_PROJECT_DIR = os.path.join(self.REPOROOT_DIR, 'toolchain', 'llvm-project')

# 设置out路径

self.OUT_PATH = os.path.join(self.REPOROOT_DIR, 'out')

2.2.1.4 logging.basicConfig方法解析

logging.basicConfig(level=logging.INFO)

2.2.2 ClangVersion类解析

2.2.2.1 _parse_version_file方法解析

从version_file文件中获取major、minor、patch的值

def _parse_version_file(self, version_file):

   with open(version_file, 'r') as fp:

       text = fp.read()

   self.major = self._parse(text, 'CLANG_VERSION_MAJOR')

   self.minor = self._parse(text, 'CLANG_VERSION_MINOR')

   self.patch = self._parse(text, 'CLANG_VERSION_PATCHLEVEL')

2.2.2.2 _parse方法解析

通过正则表达式来获取字符串中变量对应的值

@staticmethod

def _parse(text, key):

   # %s 表示搜索到匹配key字符串

   # \s+ 表示匹配一个或多个空白符合(空格、回车、Tab等)

   # () 表示提取匹配字符串

   # \d+ 表示一个或多个数字

   # 整个意思是查找每个key字符串后提取后面的数字

   return re.findall(r'%s\s+(\d+)' % key, text)[0]

2.2.2.3 long_version方法解析

将major、minor、patch以major.minor.patch连接

def long_version(self):

return '.'.join([self.major, self.minor, self.patch])

2.2.2.4 short_version方法解析

将major、minor以major.minor连接

def short_version(self):

   return '.'.join([self.major, self.minor])

2.2.2.5 major_version方法解析

def major_version(self):

   return self.major

2.2.3 BuildUtils类解析

2.2.3.0 __init__方法解析

def __init__(self, build_config):

   self.build_config = build_config

   # 结果是prebuilts/cmake/linux-x86/bin

   self.CMAKE_BIN_DIR = os.path.abspath(

       os.path.join(self.build_config.REPOROOT_DIR, 'prebuilts/cmake', self.platform_prefix(), 'bin'))

2.2.3.1 platform_prefix方法解析

基于Ubuntu的x86_64架构直接返回linux-x86

def platform_prefix(self):

prefix = self.use_platform()

if (prefix.endswith('x86_64')):

return prefix[:-3]

return prefix

2.2.3.2 use_platform方法解析

直接返回的是linux-x86_64

@staticmethod

def use_platform():

# 以小写字母返回当前系统名称,这里返回的是linux

sysstr = platform.system().lower()

# 返回当前的架构类型,这里返回的是x86_64

arch = platform.machine()

return "%s-%s" % (sysstr, arch)

2.2.3.3 open_ohos_triple方法解析

返回值推测是${arch}-linux-ohos

def open_ohos_triple(self, arch):

return arch + self.build_config.OPENHOS_SFX

2.2.3.4 liteos_triple方法解析

返回值推测是${arch}-liteos-ohos

def liteos_triple(self, arch):

return arch + self.build_config.LITEOS_SFX

2.2.3.4 set_clang_version方法解析

从prebuilts/clang/ohos/linux-x86_64/clang-10.0.1/include/clang/Basic/Version.inc文件中获取long_version,结果是10.0.1

def set_clang_version(self, install_dir):

self.build_config.VERSION = self.get_clang_version(install_dir).long_version()

2.2.3.5 get_clang_version方法解析

打开prebuilts/clang/ohos/linux-x86_64/clang-10.0.1/include/clang/Basic/Version.inc文件,用于获取其中的version

@staticmethod

def get_clang_version(llvm_install):

version_file = os.path.join(llvm_install, 'include', 'clang', 'Basic',

'Version.inc')

return ClangVersion(version_file)

2.2.3.5 invoke_ninja方法解析

def invoke_ninja(self,

out_path,

env,

target=None,

install=True,

build_threads=False):

# 获取的ninja路径为:prebuilts/cmake/linux-x86/bin/ninja

ninja_bin_path = os.path.join(self.CMAKE_BIN_DIR, 'ninja')

ninja_list = ['-l{}'.format(build_threads)] if build_threads else []

ninja_target = [target] if target else []

self.check_call([ninja_bin_path] + ninja_list + ninja_target, cwd=out_path, env=env)

if install:

self.check_call([ninja_bin_path, 'install'], cwd=out_path, env=env)

2.2.3.6 check_call方法解析

def check_call(self, cmd, *args, **kwargs):

"""subprocess.check_call with logging."""

self.logger().info('check_call:%s %s',

datetime.datetime.now().strftime("%H:%M:%S"), subprocess.list2cmdline(cmd))

subprocess.check_call(cmd, *args, **kwargs)

2.2.3.7 invoke_cmake方法解析

def invoke_cmake(self,

cmake_path,

out_path,

invoke_defines,

env):

cmake_bin_path = os.path.join(self.CMAKE_BIN_DIR, 'cmake')

# 设置后面编译使用Ninja

flags = ['-G', 'Ninja']

flags += ['-DCMAKE_PREFIX_PATH=%s' % self.CMAKE_BIN_DIR]

for key in invoke_defines:

# 将invoke_defines中的宏定义字典按照'-Dkey=value'重新组合

newdef = ''.join(['-D', key, '=', invoke_defines[key]])

flags += [newdef]

flags += [cmake_path]

self.check_create_dir(out_path)

self.check_call([cmake_bin_path] + flags, cwd=out_path, env=env)

# 具体的执行命令形式可能是这样的

# cmake -G "Ninja" \

# -DCOMPILER_RT_BUILD_BUILTINS=ON \

# -DCOMPILER_RT_INCLUDE_TESTS=OFF \

# -DCOMPILER_RT_BUILD_SANITIZERS=ON \

# -DCOMPILER_RT_BUILD_XRAY=ON \

# -DCOMPILER_RT_BUILD_LIBFUZZER=ON \

# -DCOMPILER_RT_BUILD_PROFILE=ON \

# -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \

# -DCMAKE_C_COMPILER=clang \

# -DCMAKE_CXX_COMPILER=clang++ \

# -DCMAKE_ASM_COMPILER_TARGET="riscv64-unknown-linux-gnu" \

# -DCMAKE_C_COMPILER_TARGET="riscv64-unknown-linux-gnu" \

# -DCMAKE_CXX_COMPILER_TARGET="riscv64-unknown-linux-gnu" \

# -DCMAKE_ASM_FLAGS="-O2 --gcc-toolchain=/home/wen_fei/toolchains/riscv64-gnu-gcc -march=rv64imafdc -mabi=lp64d -mno-relax" \

# -DCMAKE_C_FLAGS="-O2 --gcc-toolchain=/home/wen_fei/toolchains/riscv64-gnu-gcc -march=rv64imafdc -mabi=lp64d -mno-relax" \

# -DCMAKE_CXX_FLAGS="-O2 --gcc-toolchain=/home/wen_fei/toolchains/riscv64-gnu-gcc -march=rv64imafdc -mabi=lp64d -mno-relax" \

# -DCMAKE_EXE_LINKER_FLAGS="-z separate-code" \

# -DCMAKE_SYSROOT="/home/wen_fei/toolchains/riscv64-gnu-gcc/sysroot" \

# -DCMAKE_INSTALL_PREFIX="/home/wen_fei/toolchains/sysroot" \

# -DCMAKE_C_COMPILER_WORKS=1 \

# -DCMAKE_CXX_COMPILER_WORKS=1 \

# -DCMAKE_SIZEOF_VOID_P=8 \

# ../compiler-rt

2.2.3.8 check_create_dir方法解析

递归创建目录

def check_create_dir(self, path):

if not os.path.exists(path):

"""Proxy for os.makedirs with logging and dry-run support."""

self.logger().info('makedirs %s', path)

os.makedirs(path)

2.2.3.9 check_rm_tree方法解析

递归删除目录

def check_rm_tree(self, tree_dir):

"""Removes directory tree."""

def chmod_and_retry(func, path, _):

if not os.access(path, os.W_OK):

os.chmod(path, stat.S_IWUSR)

return func(path)

raise IOError("rmtree on %s failed" % path)

if os.path.exists(tree_dir):

self.logger().info('shutil rmtree %s', tree_dir)

shutil.rmtree(tree_dir, οnerrοr=chmod_and_retry)

2.2.3.10 check_copy_tree方法解析

拷贝目录

def check_copy_tree(self, src_dir, dst_dir):

self.check_rm_tree(dst_dir)

"""Proxy for shutil.copytree with logging and dry-run support."""

self.logger().info('copytree %s %s', src_dir, dst_dir)

shutil.copytree(src_dir, dst_dir, symlinks=True)

2.2.3.11 check_copy_file方法解析

拷贝文件

def check_copy_file(self, src_file, dst_file):

if os.path.exists(src_file):

"""Proxy for shutil.copy2 with logging and dry-run support."""

self.logger().info('copy %s %s', src_file, dst_file)

shutil.copy2(src_file, dst_file)

2.2.3.12 check_call方法解析

创建子进程执行命令

def check_call(self, cmd, *args, **kwargs):

"""subprocess.check_call with logging."""

self.logger().info('check_call:%s %s',

datetime.datetime.now().strftime("%H:%M:%S"), subprocess.list2cmdline(cmd))

# 创建子进程执行cmd命令,如果命令执行成功返回0,否则抛出异常,也可以使用subprocess.Popen接口

subprocess.check_call(cmd, *args, **kwargs)

2.2.3.13 merge_out_path方法解析

返回输出路径

def merge_out_path(self, *args):

return os.path.abspath(os.path.join(self.build_config.OUT_PATH, *args))

2.2.3.14 host_is_linux方法解析

判断是否为linux,这里返回的是True

def host_is_linux(self):

return self.use_platform().startswith('linux-')

2.2.3.15 host_is_darwin方法解析

def host_is_darwin(self):

return self.use_platform().startswith('darwin-')

2.2.3.16 rm_cmake_cache方法解析

def rm_cmake_cache(self, cache_dir):

os.walk()主要用来扫描某个指定目录下所包含的子目录和文件

for dirpath, dirs, files in os.walk(cache_dir):

if 'CMakeCache.txt' in files:

self.logger().info('rm CMakeCache.txt on %s', cache_dir)

os.remove(os.path.join(dirpath, 'CMakeCache.txt'))

if 'CMakeFiles' in dirs:

self.logger().info('rm CMakeFiles on %s', cache_dir)

self.check_rm_tree(os.path.join(dirpath, 'CMakeFiles'))

2.2.3.17 find_program方法解析

返回命令的路径

@staticmethod

def find_program(name):

# FIXME: Do we need Windows support here?

return os.popen('which ' + name).read().strip()

2.2.3.18 base_cmake_defines方法解析

以字典形式定义了cmake编译的基本选项

def base_cmake_defines(self):

mac_min_version = '10.9'

defines = {}

defines['CMAKE_BUILD_TYPE'] = 'Release'

defines['LLVM_ENABLE_ASSERTIONS'] = 'OFF'

defines['LLVM_ENABLE_TERMINFO'] = 'OFF'

defines['LLVM_ENABLE_THREADS'] = 'ON'

defines['LLVM_USE_NEWPM'] = 'ON'

defines['LLVM_ENABLE_BINDINGS'] = 'OFF'

defines['CLANG_REPOSITORY_STRING'] = 'llvm-project'

if self.host_is_darwin():

defines['CMAKE_OSX_DEPLOYMENT_TARGET'] = mac_min_version

defines['LLDB_INCLUDE_TESTS'] = 'OFF'

defines['LIBCXX_INCLUDE_TESTS'] = 'OFF'

defines['COMPILER_RT_BUILD_XRAY'] = 'OFF'

return defines

2.2.4 LlvmCore类

2.2.4.1 build_llvm方法解析

执行编译命令

def build_llvm(self,

              targets,

              build_dir,

              install_dir,

              build_name,

              extra_defines=None,

              extra_env=None):

   # 获取cmake编译的基本选项

   common_defines = self.base_cmake_defines()

   common_defines['CMAKE_INSTALL_PREFIX'] = install_dir

   common_defines['LLVM_INSTALL_UTILS'] = 'ON'

   common_defines['LLVM_TARGETS_TO_BUILD'] = targets

   common_defines['LLVM_BUILD_LLVM_DYLIB'] = 'ON'

   build_number = ''

   # 字符串必须是数字-非数字组合才能匹配,例如: 1234-abcd

   # \d+ 表示至少匹配一个数字

   # - 表示要匹配一个字符'-'

   # . 表示任意一个字符

   # \D* 表示匹配任意的非数字的字符

   # $ 表示直到结尾

   if re.match(r'\d+-.\D*$', build_name):

       build_number, build_name = build_name.split('-', 1)

   # ^\d+$ 表示匹配全数字字符串

   elif re.match(r'^\d+$', build_name):

       build_number = build_name

       build_name = ''

   # ^\D+$ 表示匹配全非数字字符串

   elif re.match(r'^\D+$', build_name):

       build_name = build_name

   else:

       raise Exception('Warning! Build name is invalid, because it must not contain digits. '

                       'If you want to pass digit version, please, use follow template: {NUMBER}-{SUFFIX} '

                       'or just pass number. Otherwise unit tests will fail with assertions')

   common_defines['CLANG_VENDOR'] = 'OHOS (%s) ' % build_name

   common_defines['CLANG_VENDOR_BUILD_VERSION'] = build_number

   common_defines.update(extra_defines)

   env = dict(self.build_config.ORIG_ENV)

   if extra_env is not None:

       env.update(extra_env)

   llvm_project_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm'))

   # 执行cmake命令生成ninja编译的环境

   self.invoke_cmake(llvm_project_path,

                     build_dir,

                     common_defines,

                     env=env)

   # 调用ninja进行编译

   self.invoke_ninja(out_path=build_dir,

                     env=env,

                     target=None,

                     install=True)

2.2.4.2 llvm_compile_darwin_defines方法解析

设置darwin环境编译的红

def llvm_compile_darwin_defines(self, llvm_defines):

if self.host_is_darwin():

llvm_defines['LIBUNWIND_ENABLE_SHARED'] = 'OFF'

llvm_defines['LLDB_ENABLE_LIBEDIT'] = 'OFF'

llvm_defines['LLDB_NO_DEBUGSERVER'] = 'ON'

llvm_defines['LLDB_ENABLE_PYTHON'] = 'ON'

llvm_defines['COMPILER_RT_BUILD_LIBFUZZER'] = 'OFF'

llvm_defines['LLVM_BUILD_EXTERNAL_COMPILER_RT'] = 'ON'

2.2.4.3 llvm_compile_linux_defines方法解析

定义linux编译的宏

def llvm_compile_linux_defines(self,

llvm_defines,

debug_build=False,

no_lto=False,

build_instrumented=False):

if self.host_is_linux():

llvm_defines['LLVM_ENABLE_LLD'] = 'ON'

llvm_defines['COMPILER_RT_BUILD_LIBFUZZER'] = 'ON'

llvm_defines['LIBCXX_ENABLE_STATIC_ABI_LIBRARY'] = 'ON'

llvm_defines['LIBCXX_ENABLE_ABI_LINKER_SCRIPT'] = 'OFF'

llvm_defines['LIBCXX_USE_COMPILER_RT'] = 'ON'

llvm_defines['LIBCXXABI_USE_LLVM_UNWINDER'] = 'ON'

llvm_defines['LIBCXXABI_ENABLE_STATIC_UNWINDER'] = 'ON'

llvm_defines['LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY'] = 'YES'

llvm_defines['LIBCXXABI_USE_COMPILER_RT'] = 'ON'

llvm_defines['COMPILER_RT_USE_LLVM_UNWINDER'] = 'ON'

llvm_defines['COMPILER_RT_ENABLE_STATIC_UNWINDER'] = 'ON'

llvm_defines['COMPILER_RT_USE_BUILTINS_LIBRARY'] = 'ON'

llvm_defines['COMPILER_RT_BUILD_ORC'] = 'OFF'

llvm_defines['LIBUNWIND_USE_COMPILER_RT'] = 'ON'

llvm_defines['LLVM_BINUTILS_INCDIR'] = '/usr/include'

if not build_instrumented and not no_lto and not debug_build:

llvm_defines['LLVM_ENABLE_LTO'] = 'Thin'

2.2.4.4 llvm_compile_llvm_defines方法解析

定义llvm编译的宏

@staticmethod

def llvm_compile_llvm_defines(llvm_defines, llvm_root, cflags, ldflags):

llvm_defines['LLVM_ENABLE_PROJECTS'] = 'clang;lld;clang-tools-extra;openmp;lldb'

llvm_defines['LLVM_ENABLE_RUNTIMES'] = 'libunwind;libcxxabi;libcxx;compiler-rt'

llvm_defines['LLVM_ENABLE_BINDINGS'] = 'OFF'

llvm_defines['CMAKE_C_COMPILER'] = os.path.join(llvm_root, 'bin', 'clang')

llvm_defines['CMAKE_CXX_COMPILER'] = os.path.join(llvm_root, 'bin', 'clang++')

llvm_defines['CMAKE_AR'] = os.path.join(llvm_root, 'bin', 'llvm-ar')

llvm_defines['CMAKE_RANLIB'] = os.path.join(llvm_root, 'bin', 'llvm-ranlib')

llvm_defines['LLVM_ENABLE_LIBCXX'] = 'ON'

llvm_defines['SANITIZER_ALLOW_CXXABI'] = 'OFF'

llvm_defines['LIBOMP_ENABLE_SHARED'] = 'FALSE'

llvm_defines['OPENMP_TEST_FLAGS'] = '-Wl,-ldl'

llvm_defines['CLANG_BUILD_EXAMPLES'] = 'OFF'

llvm_defines['LLDB_ENABLE_LIBEDIT'] = 'OFF'

llvm_defines['LLDB_ENABLE_PYTHON'] = 'ON'

llvm_defines['COMPILER_RT_BUILD_SANITIZERS'] = 'OFF'

llvm_defines['COMPILER_RT_BUILD_MEMPROF'] = 'OFF'

llvm_defines['CMAKE_ASM_FLAGS'] = cflags

llvm_defines['CMAKE_C_FLAGS'] = cflags

llvm_defines['CMAKE_CXX_FLAGS'] = '%s -stdlib=libc++' % cflags

llvm_defines['CMAKE_EXE_LINKER_FLAGS'] = ldflags

llvm_defines['CMAKE_SHARED_LINKER_FLAGS'] = ldflags

llvm_defines['CMAKE_MODULE_LINKER_FLAGS'] = ldflags

2.2.4.5 llvm_compile方法解析

配置相关的宏,然后调用编译

python中基础数据类型,如:int、float、str等是值传递,对于list、dict、tuple等是地址传递

def llvm_compile(self,

                build_name,

                out_dir,

                debug_build=False,

                no_lto=False,

                build_instrumented=False,

                xunit_xml_output=None):

   llvm_clang_install = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR,

                                                     'prebuilts/clang/ohos', self.use_platform(),

                                                     'clang-%s' % self.build_config.CLANG_VERSION))

   llvm_path = self.merge_out_path('llvm_make')

   llvm_profdata = os.path.join(llvm_clang_install, 'bin', 'llvm-profdata')

   if self.host_is_darwin():

       ldflags = ''

   else:

       ldflags = '-fuse-ld=lld'

   ldflags = '%s -L%s' % (ldflags, os.path.join(llvm_clang_install, 'lib'))

   llvm_extra_env = {}

   llvm_extra_env['LD_LIBRARY_PATH'] = os.path.join(llvm_clang_install, 'lib')

   llvm_defines = {}

   self.llvm_compile_darwin_defines(llvm_defines)

   self.llvm_compile_linux_defines(llvm_defines, debug_build, no_lto, build_instrumented)

   if self.host_is_linux():

       ldflags += ' -l:libunwind.a -l:libc++abi.a --rtlib=compiler-rt -stdlib=libc++ -static-libstdc++'

   if xunit_xml_output:

       llvm_defines['LLVM_LIT_ARGS'] = "--xunit-xml-output={} -sv".format(xunit_xml_output)

   if self.build_config.enable_assertions:

       llvm_defines['LLVM_ENABLE_ASSERTIONS'] = 'ON'

   if debug_build:

       llvm_defines['CMAKE_BUILD_TYPE'] = 'Debug'

   if build_instrumented:

       llvm_defines['LLVM_BUILD_INSTRUMENTED'] = 'ON'

       llvm_defines['LLVM_PROFDATA'] = llvm_profdata

       resource_dir = "lib/clang/10.0.1/lib/linux/libclang_rt.profile-x86_64.a"

       ldflags += ' %s' % os.path.join(llvm_clang_install, resource_dir)

   cflags = '-fstack-protector-strong -fPIE'

   if not self.host_is_darwin():

       ldflags += ' -Wl,-z,relro,-z,now -pie'

       if self.build_config.strip:

           ldflags += ' -s'

   self.llvm_compile_llvm_defines(llvm_defines, llvm_clang_install, cflags, ldflags)

   linker_path = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, 'prebuilts', 'clang',

       'ohos', 'linux-x86_64', 'llvm', 'bin', 'ld.lld'))

   llvm_defines['CMAKE_LINKER'] = linker_path

   self.build_llvm(targets=self.build_config.TARGETS,

                   build_dir=llvm_path,

                   install_dir=out_dir,

                   build_name=build_name,

                   extra_defines=llvm_defines,

                   extra_env=llvm_extra_env)

2.2.4.6 llvm_compile_windows_defines方法解析

windows环境宏定义

def llvm_compile_windows_defines(self,

                                windows_defines,

                                cc,

                                cxx,

                                windows_sysroot):

   if self.build_config.enable_assertions:

       windows_defines['LLVM_ENABLE_ASSERTIONS'] = 'ON'

   windows_defines['LLDB_RELOCATABLE_PYTHON'] = 'OFF'

   win_sysroot = self.merge_out_path('mingw', self.build_config.MINGW_TRIPLE)

   windows_defines['LLDB_ENABLE_PYTHON'] = 'ON'

   windows_defines['LLDB_PYTHON_HOME'] = 'python'

   windows_defines['LLDB_PYTHON_RELATIVE_PATH'] = \

     'bin/python/lib/python%s' % (self.build_config.LLDB_PY_VERSION)

   windows_defines['LLDB_PYTHON_EXE_RELATIVE_PATH'] = 'bin/python'

   windows_defines['LLDB_PYTHON_EXT_SUFFIX'] = '.pys'

   windows_defines['PYTHON_INCLUDE_DIRS'] = os.path.join(win_sysroot,

                                   'include', 'python%s' % self.build_config.LLDB_PY_VERSION)

   windows_defines['PYTHON_LIBRARIES'] = os.path.join(win_sysroot, 'lib', 'libpython%s.dll.a'

                                                       % self.build_config.LLDB_PY_VERSION)

   windows_defines['SWIG_EXECUTABLE'] = self.find_program('swig')

   windows_defines['PYTHON_EXECUTABLE'] = self.find_program('python3')

   windows_defines['CMAKE_C_COMPILER'] = cc

   windows_defines['CMAKE_CXX_COMPILER'] = cxx

   windows_defines['CMAKE_SYSTEM_NAME'] = 'Windows'

   windows_defines['CMAKE_BUILD_TYPE'] = 'Release'

   windows_defines['LLVM_BUILD_RUNTIME'] = 'OFF'

   windows_defines['LLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD'] = 'ON'

   windows_defines['LLVM_TOOL_OPENMP_BUILD'] = 'OFF'

   windows_defines['LLVM_INCLUDE_TESTS'] = 'OFF'

   windows_defines['LLVM_ENABLE_LIBCXX'] = 'ON'

   windows_defines['LLVM_ENABLE_PROJECTS'] = 'clang;clang-tools-extra;lld;lldb'

   windows_defines['LLVM_BUILD_LLVM_DYLIB'] = 'OFF'

   windows_defines['CLANG_BUILD_EXAMPLES'] = 'OFF'

   windows_defines['CMAKE_SYSROOT'] = windows_sysroot

   windows_defines['CMAKE_FIND_ROOT_PATH_MODE_INCLUDE'] = 'ONLY'

   windows_defines['CMAKE_FIND_ROOT_PATH_MODE_LIBRARY'] = 'ONLY'

   windows_defines['CMAKE_FIND_ROOT_PATH_MODE_PACKAGE'] = 'ONLY'

   windows_defines['CMAKE_FIND_ROOT_PATH_MODE_PROGRAM'] = 'NEVER'

   windows_defines['LLDB_ENABLE_LIBEDIT'] = 'OFF'

   windows_defines['LLDB_RELOCATABLE_PYTHON'] = 'OFF'

2.2.4.7 llvm_compile_windows_flags方法解析

windows环境宏定义

def llvm_compile_windows_flags(self,

windows_defines,

windowstool_path,

windows64_install,

ldflags,

cflags):

windows_defines['CROSS_TOOLCHAIN_FLAGS_NATIVE'] = ';'.join([

'-DCMAKE_PREFIX_PATH=%s' % self.CMAKE_BIN_DIR,

'-DCOMPILER_RT_BUILD_LIBFUZZER=OFF',

'-DLLVM_ENABLE_LIBCXX=ON',

'-DCMAKE_BUILD_WITH_INSTALL_RPATH=TRUE',

'-DCMAKE_INSTALL_RPATH=%s' % os.path.join(windowstool_path, 'lib')]

)

ldflag = ['-fuse-ld=lld',

'-stdlib=libc++',

'--rtlib=compiler-rt',

'-lunwind', '-Wl,--dynamicbase',

'-Wl,--nxcompat',

'-lucrt',

'-lucrtbase',

'-L',

os.path.join(windows64_install, 'lib'),

'-Wl,--high-entropy-va']

ldflags.extend(ldflag)

cflag = ['-stdlib=libc++',

'--target=x86_64-pc-windows-gnu',

'-D_LARGEFILE_SOURCE',

'-D_FILE_OFFSET_BITS=64',

'-D_WIN32_WINNT=0x0600',

'-DWINVER=0x0600',

'-D__MSVCRT_VERSION__=0x1400',

'-DMS_WIN64']

cflags.extend(cflag)

2.2.4.8 llvm_compile_windows_cmake方法解析

windows环境宏定义

def llvm_compile_windows_cmake(self,

cflags,

cxxflags,

ldflags,

windows_defines):

zlib_path = self.merge_out_path('../', 'prebuilts', 'clang', 'host', 'windows-x86', 'toolchain-prebuilts',

'zlib')

zlib_inc = os.path.join(zlib_path, 'include')

zlib_lib = os.path.join(zlib_path, 'lib')

cflags.extend(['-I', zlib_inc])

cxxflags.extend(['-I', zlib_inc])

ldflags.extend(['-L', zlib_lib])

windows_defines['CMAKE_ASM_FLAGS'] = ' '.join(cflags)

windows_defines['CMAKE_C_FLAGS'] = ' '.join(cflags)

windows_defines['CMAKE_CXX_FLAGS'] = ' '.join(cxxflags)

windows_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags)

windows_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags)

windows_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags)

2.2.4.9 llvm_compile_for_windows方法解析

windows环境编译

def llvm_compile_for_windows(self,

targets,

enable_assertions,

build_name):

self.logger().info('Building llvm for windows.')

build_dir = self.merge_out_path("windows-x86_64")

windowstool_path = self.merge_out_path('llvm-install')

windows64_install = self.merge_out_path('windows-x86_64-install')

windows_sysroot = self.merge_out_path('mingw', self.build_config.MINGW_TRIPLE)

self.check_create_dir(build_dir)

# Write a NATIVE.cmake in windows_path that contains the compilers used

# to build native tools such as llvm-tblgen and llvm-config. This is

# used below via the CMake variable CROSS_TOOLCHAIN_FLAGS_NATIVE.

cc = os.path.join(windowstool_path, 'bin', 'clang')

cxx = os.path.join(windowstool_path, 'bin', 'clang++')

# Extra cmake defines to use while building for Windows

windows_defines = {}

self.llvm_compile_windows_defines(windows_defines, cc, cxx, windows_sysroot)

# Set CMake path, toolchain file for native compilation (to build tablegen

# etc). Also disable libfuzzer build during native compilation.

ldflags = []

cflags = []

self.llvm_compile_windows_flags(windows_defines,

windowstool_path, windows64_install, ldflags, cflags)

cxxflags = list(cflags)

windows_extra_env = dict()

cxxflags.append('-fuse-cxa-atexit')

cxxflags.extend(('-I', os.path.join(windows64_install, 'include', 'c++', 'v1')))

self.llvm_compile_windows_cmake(cflags, cxxflags, ldflags, windows_defines)

self.build_llvm(self.build_config.TARGETS,

build_dir,

windows64_install,

build_name,

extra_defines=windows_defines,

extra_env=windows_extra_env)

2.2.5 SysrootComposer类

2.2.5.1 setup_cmake_platform方法解析

重新拷贝OHOS.cmake到prebuilts/cmake/linux-x86/share/cmake-3.16/Modules/Platform目录下

def setup_cmake_platform(self, llvm_install):

# OHOS.cmake already exsit on cmake prebuilts,

# but it didn't contain these two lines, so we still need OHOS.cmake.

ohos_cmake = 'OHOS.cmake'

# 这个目录路径是 prebuilts/cmake/linux-x86/share/cmake-3.16/Modules/Platform

dst_dir = self.merge_out_path(

'../prebuilts/cmake/%s/share/cmake-3.16/Modules/Platform' % self.platform_prefix())

# 这个文件路径是 toolchain/llvm-project/llvm-build/OHOS.cmake

src_file = '%s/%s' % (self.build_config.LLVM_BUILD_DIR, ohos_cmake)

if os.path.exists(os.path.join(dst_dir, ohos_cmake)):

os.remove(os.path.join(dst_dir, ohos_cmake))

shutil.copy2(src_file, dst_dir)

2.2.5.2 build_musl方法解析

调用build_musl.sh脚本执行命令

def build_musl(self, llvm_install, target, *extra_args):

cur_dir = os.getcwd()

os.chdir(self.build_config.LLVM_BUILD_DIR)

self.logger().info('build musl %s', self.merge_out_path('install'))

args = ['./build_musl.sh', '-t', target,

'-c', self.merge_out_path(llvm_install, 'bin'),

'-o', self.merge_out_path(),

'-T', self.build_config.REPOROOT_DIR] + list(extra_args)

self.check_call(args)

os.chdir(cur_dir)

2.2.5.3 install_linux_headers方法解析

def install_linux_headers(self, arch, target):

dir_suffix = arch

if arch == 'x86_64':

dir_suffix = 'x86'

elif arch == 'mipsel':

dir_suffix = 'mips'

linux_kernel_dir = os.path.join('kernel_linux_patches', 'linux-5.10')

linux_kernel_path = os.path.join(self.build_config.OUT_PATH, '..', linux_kernel_dir)

ohosmusl_sysroot_dst = self.merge_out_path('sysroot', target, 'usr')

headers_tmp_dir = os.path.join(linux_kernel_path, 'prebuilts', 'usr', 'include')

self.check_copy_tree(os.path.join(headers_tmp_dir, 'linux'),

os.path.join(ohosmusl_sysroot_dst, 'include/linux'))

self.check_copy_tree(os.path.join(headers_tmp_dir, 'asm-%s' % dir_suffix,'asm'),

os.path.join(ohosmusl_sysroot_dst, 'include', 'asm'))

self.check_copy_tree(os.path.join(headers_tmp_dir, 'asm-generic'),

os.path.join(ohosmusl_sysroot_dst, 'include/asm-generic'))

2.2.5.4copy_libz_to_sysroot方法解析

def copy_libz_to_sysroot(self, libz_path, llvm_triple):

# Install to sysroot

dest_usr = self.merge_out_path('sysroot', llvm_triple, 'usr')

dest_usr_include = os.path.join(dest_usr, 'include')

# Copy over usr/include.

zlib_h = self.merge_out_path('../third_party/zlib', 'zlib.h')

self.check_copy_file(zlib_h, dest_usr_include)

zconf_h = os.path.join(libz_path, 'zconf.h')

self.check_copy_file(zconf_h, dest_usr_include)

# Copy over usr/lib.

dest_usr_lib = os.path.join(dest_usr, 'lib')

static_zlib = os.path.join(libz_path, 'libz.a')

self.check_copy_file(static_zlib, dest_usr_lib)

2.2.6 LlvmLibs类

2.2.6.1 build_crt_libs方法解析

编译crt库

def build_crt_libs(self, configs, llvm_install, need_lldb_server):

for (arch, target) in configs:

self.sysroot_composer.build_musl(llvm_install, target)

# self.build_config.OPENHOS_SFX 值是 '-linux-ohos'

if target.endswith(self.build_config.OPENHOS_SFX):

self.sysroot_composer.install_linux_headers(arch, target)

self.build_libs(need_lldb_server,

llvm_install,

target,

precompilation=True)

self.sysroot_composer.build_musl(llvm_install, target, '-l')

2.2.6.2 build_libs_defines方法解析

编译库的基础宏配置

def build_libs_defines(self,

llvm_triple,

defines,

cc,

cxx,

ar,

llvm_config,

ldflags,

cflags,

extra_flags):

sysroot = self.merge_out_path('sysroot')

defines['CMAKE_C_COMPILER'] = cc

defines['CMAKE_CXX_COMPILER'] = cxx

defines['CMAKE_AR'] = ar

defines['LLVM_CONFIG_PATH'] = llvm_config

defines['CMAKE_SYSROOT'] = sysroot

defines['CMAKE_FIND_ROOT_PATH_MODE_INCLUDE'] = 'ONLY'

defines['CMAKE_FIND_ROOT_PATH_MODE_LIBRARY'] = 'ONLY'

defines['CMAKE_FIND_ROOT_PATH_MODE_PACKAGE'] = 'ONLY'

defines['CMAKE_FIND_ROOT_PATH_MODE_PROGRAM'] = 'NEVER'

ldflag = [

'-fuse-ld=lld',

'-Wl,--gc-sections',

'-Wl,--build-id=sha1',

'--rtlib=compiler-rt',

'-stdlib=libc++', ]

if not self.host_is_darwin():

ldflag.append('-Wl,-z,relro,-z,now -pie')

if self.build_config.strip:

ldflag.append('-s')

ldflags.extend(ldflag)

cflag = [

'-fstack-protector-strong',

'-fPIE',

'--target=%s' % llvm_triple,

'-ffunction-sections',

'-fdata-sections',

extra_flags, ]

cflags.extend(cflag)

2.2.6.3 build_libs方法解析 # Todo

编译库

def build_libs(self, need_lldb_server, llvm_install, llvm_build, precompilation=False):

   # self.liteos_triple('arm') 返回的是'arm-linux-ohos'

   configs_list = [

      ('arm', self.liteos_triple('arm'), '-march=armv7-a -mfloat-abi=soft', ''),

      ('arm', self.liteos_triple('arm'), '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft', 'a7_soft'),

      ('arm', self.liteos_triple('arm'),

        '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4', 'a7_softfp_neon-vfpv4'),

      ('arm', self.liteos_triple('arm'),

        '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4', 'a7_hard_neon-vfpv4'),

      ('arm', self.open_ohos_triple('arm'), '-march=armv7-a -mfloat-abi=soft', ''),

      ('arm', self.open_ohos_triple('arm'), '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft', 'a7_soft'),

      ('arm', self.open_ohos_triple('arm'),

        '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4', 'a7_softfp_neon-vfpv4'),

      ('arm', self.open_ohos_triple('arm'),

        '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4', 'a7_hard_neon-vfpv4'),

      ('aarch64', self.open_ohos_triple('aarch64'), '', ''),

      ('riscv64', self.open_ohos_triple('riscv64'), '', ''),

      ('mipsel', self.open_ohos_triple('mipsel'), '-march=mips32r2', ''),

      ('x86_64', self.open_ohos_triple('x86_64'), '', ''),]

   cc = os.path.join(llvm_install, 'bin', 'clang')

   cxx = os.path.join(llvm_install, 'bin', 'clang++')

   ar = os.path.join(llvm_install, 'bin', 'llvm-ar')

   llvm_config = os.path.join(llvm_install, 'bin', 'llvm-config')

   seen_arch_list = [self.liteos_triple('arm')]

   self.set_clang_version(llvm_install)

   for (arch, llvm_triple, extra_flags, multilib_suffix) in configs_list:

       if llvm_build != llvm_triple:

           continue

       has_lldb_server = arch not in ['riscv64', 'mipsel']

       defines = {}

       ldflags = []

       cflags = []

       self.logger().info('Build libs for %s', llvm_triple)

       self.build_libs_defines(llvm_triple, defines, cc, cxx, ar, llvm_config, ldflags, cflags, extra_flags)

       if arch == 'mipsel':

           ldflags.append('-Wl,-z,notext')

           ldflags.append('-Wl,--no-check-dynamic-relocations')

       llvm_path = self.merge_out_path('llvm_make')

       arch_list = [self.liteos_triple('arm'), self.open_ohos_triple('arm'),

                    self.open_ohos_triple('aarch64'), self.open_ohos_triple('riscv64'),

                    self.open_ohos_triple('mipsel'), self.open_ohos_triple('x86_64')]

       if precompilation:

           self.build_crts(llvm_install, arch, llvm_triple, cflags, ldflags, multilib_suffix, defines)

           continue

       # libunwind is added to linker command line by OHOS toolchain, so we have to use two step build

       self.build_runtimes(llvm_install, "libunwind", ldflags, cflags, llvm_triple, arch, multilib_suffix, defines)

       self.build_runtimes(llvm_install, "libunwind;libcxxabi;libcxx", ldflags, cflags, llvm_triple, arch, multilib_suffix, defines)

       libcxx_ndk_install = self.merge_out_path('libcxx-ndk')

       libcxx_ndk_install_tmp = self.merge_out_path('libcxx-ndk-tmp')

       self.check_create_dir(libcxx_ndk_install)

       self.build_runtimes(libcxx_ndk_install_tmp, "libunwind;libcxxabi;libcxx", ldflags, cflags, llvm_triple,

                               arch, multilib_suffix, defines, libcxx_ndk_install)

       self.build_crts(llvm_install, arch, llvm_triple, cflags, ldflags, multilib_suffix, defines,

                           first_time=False)

       if llvm_triple in arch_list:

           if need_lldb_server and has_lldb_server and llvm_triple not in seen_arch_list:

               self.build_lldb_server(llvm_install, llvm_path, arch, llvm_triple, cflags, ldflags,

                                              defines)

               seen_arch_list.append(llvm_triple)

           continue

       self.build_libomp(llvm_install, arch, llvm_triple, cflags, ldflags, multilib_suffix, defines)

       self.build_libz(arch, llvm_triple, cflags, ldflags, defines)

       if need_lldb_server and has_lldb_server and llvm_triple not in seen_arch_list:

           self.build_lldb_server(llvm_install, llvm_path, arch, llvm_triple, cflags, ldflags, defines)

           seen_arch_list.append(llvm_triple)

2.2.6.4 build_runtimes方法解析 # Todo

编译运行时库

def build_runtimes(self,

llvm_install,

rt_list,

ldflags,

cflags,

llvm_triple,

arch,

multilib_suffix,

defines,

libcxx_ndk_install=None):

self.logger().info('Building runtimes(%s) for %s', rt_list, arch)

ndk_suffix = '-ndk' if libcxx_ndk_install else ''

out_path = self.merge_out_path('lib', rt_list.replace(';', '-') + ndk_suffix + '-' + str(llvm_triple))

rt_cflags = list(cflags)

rt_cflags.append('-fstack-protector-strong')

rt_defines = defines.copy()

rt_defines['OHOS'] = '1'

rt_defines['LLVM_ENABLE_PER_TARGET_RUNTIME_DIR'] = 'ON'

rt_defines['LLVM_TARGET_MULTILIB_SUFFIX'] = multilib_suffix

rt_defines['LLVM_DEFAULT_TARGET_TRIPLE'] = llvm_triple

rt_defines['LLVM_ENABLE_RUNTIMES'] = rt_list

rt_defines['LIBUNWIND_USE_COMPILER_RT'] = 'ON'

rt_defines['LIBUNWIND_ENABLE_SHARED'] = 'OFF'

rt_defines['LIBCXXABI_USE_COMPILER_RT'] = 'ON'

rt_defines['LIBCXXABI_USE_LLVM_UNWINDER'] = 'ON'

rt_defines['LIBCXXABI_ENABLE_STATIC_UNWINDER'] = 'ON'

rt_defines['LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL'] = 'OFF'

rt_defines['LIBCXXABI_ENABLE_SHARED'] = 'OFF'

rt_defines['LIBCXXABI_LIBCXX_INCLUDES'] = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'libcxx', 'include'))

rt_defines['LIBCXX_USE_COMPILER_RT'] = 'ON'

rt_defines['LIBCXX_ENABLE_ABI_LINKER_SCRIPT'] = 'OFF'

rt_defines['LIBCXX_ENABLE_STATIC_ABI_LIBRARY'] = 'ON'

rt_defines['CMAKE_ASM_FLAGS'] = ' '.join(rt_cflags)

rt_defines['CMAKE_C_FLAGS'] = ' '.join(rt_cflags)

rt_defines['CMAKE_CXX_FLAGS'] = ' '.join(rt_cflags)

rt_defines['CMAKE_INSTALL_PREFIX'] = llvm_install

rt_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags)

rt_defines['CMAKE_SYSTEM_NAME'] = 'OHOS'

rt_defines['CMAKE_CROSSCOMPILING'] = 'True'

rt_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY'

if libcxx_ndk_install:

rt_defines['LIBCXX_ABI_NAMESPACE'] = '__n1'

rt_defines['LIBCXX_OUTPUT_NAME'] = 'c++_shared'

rt_defines['LIBCXX_OUTPUT_STATIC_NAME'] = 'c++_static'

rt_defines['LIBCXX_INSTALL_INCLUDE_DIR'] = self.merge_out_path(libcxx_ndk_install, 'include', 'libcxx-ohos', 'include', 'c++', 'v1')

rt_defines['LIBCXX_INSTALL_LIBRARY_DIR'] = self.merge_out_path(libcxx_ndk_install, 'lib', llvm_triple, 'c++', multilib_suffix)

rt_defines['LIBCXXABI_INSTALL_LIBRARY'] = 'OFF'

rt_defines['LIBUNWIND_INSTALL_LIBRARY'] = 'OFF'

else:

rt_defines['LIBCXX_ABI_NAMESPACE'] = '__h'

self.check_rm_tree(out_path)

cmake_rt = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'runtimes'))

self.invoke_cmake(cmake_rt,

out_path,

rt_defines,

env=dict(self.build_config.ORIG_ENV))

self.invoke_ninja(out_path=out_path,

env=dict(self.build_config.ORIG_ENV),

target=None,

install=True)

2.2.6.5 build_crts方法解析

def build_crts(self,

              llvm_install,

              arch,

              llvm_triple,

              cflags,

              ldflags,

              multilib_suffix,

              defines,

              first_time=True):

   self.logger().info('Building compiler-rt for %s', arch)

   suffix = '-' + multilib_suffix if multilib_suffix else ''

   crt_path = self.merge_out_path('lib', 'clangrt-%s%s' % (llvm_triple, suffix))

   crt_install = os.path.join(llvm_install, 'lib', 'clang', self.build_config.VERSION)

   crt_extra_flags = []

   if not self.build_config.debug:

       # Remove absolute paths from compiler-rt debug info emitted with -gline-tables-only

       crt_extra_flags = ['-ffile-prefix-map=%s=.' % self.build_config.REPOROOT_DIR]

   crt_defines = defines.copy()

   crt_defines.update(self.base_cmake_defines())

   crt_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags)

   crt_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags)

   crt_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags)

   crt_defines['CMAKE_C_FLAGS'] = ' '.join(cflags + crt_extra_flags)

   crt_defines['CMAKE_ASM_FLAGS'] = ' '.join(cflags + crt_extra_flags)

   crt_defines['CMAKE_CXX_FLAGS'] = ' '.join(cflags + crt_extra_flags)

   crt_defines['COMPILER_RT_TEST_COMPILER_CFLAGS'] = ' '.join(cflags)

   crt_defines['OHOS'] = '1'

   crt_defines['COMPILER_RT_TEST_TARGET_TRIPLE'] = llvm_triple

   crt_defines['COMPILER_RT_INCLUDE_TESTS'] = 'ON'

   crt_defines['CMAKE_INSTALL_PREFIX'] = crt_install

   crt_defines['LLVM_TARGET_MULTILIB_SUFFIX'] = multilib_suffix

   if first_time or llvm_triple == self.liteos_triple('arm'):

       crt_defines['COMPILER_RT_BUILD_LIBFUZZER'] = 'OFF'

   else:

       crt_defines['COMPILER_RT_BUILD_LIBFUZZER'] = 'ON'

   crt_defines['COMPILER_RT_BUILD_ORC'] = 'OFF'

   crt_defines['LLVM_ENABLE_PER_TARGET_RUNTIME_DIR'] = 'ON'

   crt_defines['COMPILER_RT_USE_BUILTINS_LIBRARY'] = 'ON'

   crt_defines['CMAKE_SYSTEM_NAME'] = 'OHOS'

   crt_defines['CMAKE_CROSSCOMPILING'] = 'True'

   crt_defines['SANITIZER_CXX_ABI'] = 'libcxxabi'

   crt_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY'

   crt_defines['COMPILER_RT_HWASAN_WITH_INTERCEPTORS'] = 'OFF'

   crt_defines['COMPILER_RT_BUILD_SANITIZERS'] = \

       'OFF' if llvm_triple == self.liteos_triple('arm') or first_time else 'ON'

   crt_defines['COMPILER_RT_DEFAULT_TARGET_TRIPLE'] = llvm_triple

   crt_cmake_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'compiler-rt'))

   self.rm_cmake_cache(crt_path)

   self.invoke_cmake(crt_cmake_path,

                     crt_path,

                     crt_defines,

                     env=dict(self.build_config.ORIG_ENV))

   self.invoke_ninja(out_path=crt_path,

                     env=dict(self.build_config.ORIG_ENV),

                     target=None,

                     install=True)

2.2.6.6 build_libomp方法解析

def build_libomp(self,

llvm_install,

arch,

llvm_triple,

cflags,

ldflags,

multilib_suffix,

defines):

self.logger().info('Building libomp for %s', arch)

libomp_path = self.merge_out_path('lib', 'libomp-%s' % llvm_triple)

out_dir = os.path.join(libomp_path, 'lib')

libomp_cflags = list(cflags)

libomp_cflags.append('-fPIC')

libomp_defines = defines.copy()

libomp_defines.update(self.base_cmake_defines())

libomp_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags)

libomp_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags)

libomp_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags)

libomp_defines['OHOS'] = '1'

libomp_defines['CMAKE_ASM_FLAGS'] = ' '.join(libomp_cflags)

libomp_defines['CMAKE_C_FLAGS'] = ' '.join(libomp_cflags)

libomp_defines['CMAKE_CXX_FLAGS'] = ' '.join(libomp_cflags)

libomp_defines['OPENMP_ENABLE_LIBOMPTARGET'] = 'FALSE'

libomp_defines['OPENMP_LIBDIR_SUFFIX'] = os.path.join(os.sep, llvm_triple, multilib_suffix)

libomp_defines['LIBOMP_ENABLE_SHARED'] = 'FALSE'

libomp_defines['CMAKE_POLICY_DEFAULT_CMP0056'] = 'NEW'

libomp_defines['CMAKE_INSTALL_PREFIX'] = llvm_install

libomp_defines['COMPILER_RT_USE_BUILTINS_LIBRARY'] = 'ON'

libomp_defines['CMAKE_SYSTEM_NAME'] = 'OHOS'

libomp_defines['CMAKE_CROSSCOMPILING'] = 'True'

libomp_defines['LLVM_ENABLE_LIBCXX'] = 'ON'

libomp_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY'

libomp_cmake_path = os.path.join(self.build_config.LLVM_PROJECT_DIR, 'openmp')

self.rm_cmake_cache(libomp_path)

self.invoke_cmake(libomp_cmake_path,

libomp_path,

libomp_defines,

env=dict(self.build_config.ORIG_ENV))

self.invoke_ninja(out_path=libomp_path,

env=dict(self.build_config.ORIG_ENV),

target=None,

install=True)

2.2.6.7 build_libz方法解析

def build_libz(self,

arch,

llvm_triple,

cflags,

ldflags,

defines):

self.logger().info('Building libz for %s ', arch)

libz_path = self.merge_out_path('lib', 'libz-%s' % llvm_triple)

if llvm_triple == self.hos_triple('arm'):

ldflags.append('-lunwind')

libz_cflags = list(cflags)

libz_cflags.append('-fPIC')

libz_defines = defines.copy()

libz_defines.update(self.base_cmake_defines())

libz_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags)

libz_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags)

libz_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags)

libz_defines['OHOS'] = '1'

libz_defines['CMAKE_ASM_FLAGS'] = ' '.join(libz_cflags)

libz_defines['CMAKE_C_FLAGS'] = ' '.join(libz_cflags)

libz_defines['CMAKE_CXX_FLAGS'] = ' '.join(libz_cflags)

libz_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY'

libz_cmake_path = os.path.join(self.build_config.REPOROOT_DIR, 'third_party/zlib')

self.rm_cmake_cache(libz_path)

self.invoke_cmake(libz_cmake_path,

libz_path,

libz_defines,

env=dict(self.build_config.ORIG_ENV))

self.invoke_ninja(out_path=libz_path,

env=dict(self.build_config.ORIG_ENV),

target=None,

install=False)

self.sysroot_composer.copy_libz_to_sysroot(libz_path, llvm_triple)

2.2.6.8 build_lldb_server方法解析

def build_lldb_server(self,

                     llvm_install,

                     llvm_path,

                     arch,

                     llvm_triple,

                     cflags,

                     ldflags,

                     defines):

   self.logger().info('Building lldb for %s', arch)

   lldb_path = self.merge_out_path('lib', 'lldb-server-%s' % llvm_triple)

   crt_install = os.path.join(llvm_install, 'lib', 'clang', self.build_config.VERSION)

   out_dir = os.path.join(lldb_path, 'bin')

   lldb_ldflags = list(ldflags)

   lldb_cflags = list(cflags)

   lldb_ldflags.append('-lunwind')

   lldb_ldflags.append('-static')

   lldb_defines = defines.copy()

   lldb_defines.update(self.base_cmake_defines())

   lldb_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(lldb_ldflags)

   lldb_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(lldb_ldflags)

   lldb_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(lldb_ldflags)

   lldb_defines['OHOS'] = '1'

   lldb_defines['CMAKE_C_FLAGS'] = ' '.join(lldb_cflags)

   lldb_defines['CMAKE_ASM_FLAGS'] = ' '.join(lldb_cflags)

   lldb_defines['CMAKE_CXX_FLAGS'] = ' '.join(lldb_cflags)

   lldb_defines['CMAKE_INSTALL_PREFIX'] = crt_install

   lldb_defines['LLVM_ENABLE_PER_TARGET_RUNTIME_DIR'] = 'ON'

   lldb_defines['COMPILER_RT_USE_BUILTINS_LIBRARY'] = 'ON'

   lldb_defines['CMAKE_SYSTEM_NAME'] = 'OHOS'

   lldb_defines['CMAKE_CROSSCOMPILING'] = 'True'

   lldb_defines['LLVM_DEFAULT_TARGET_TRIPLE'] = llvm_triple

   lldb_defines['LLVM_ENABLE_LIBCXX'] = 'ON'

   lldb_defines['LLVM_ENABLE_PROJECTS'] = 'clang;lldb'

   lldb_defines['LLVM_TABLEGEN'] = os.path.join(llvm_install, 'bin', 'llvm-tblgen')

   lldb_defines['CLANG_TABLEGEN'] = os.path.join(llvm_install, '..', llvm_path, 'bin', 'clang-tblgen')

   lldb_defines['LLDB_TABLEGEN'] = os.path.join(llvm_install, '..', llvm_path, 'bin', 'lldb-tblgen')

   lldb_defines['LLVM_HOST_TRIPLE'] = llvm_triple

   lldb_defines['LLVM_TARGET_ARCH'] = arch

   lldb_defines['LLVM_TARGETS_TO_BUILD'] = self.build_config.TARGETS

   lldb_cmake_path = os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm')

   self.invoke_cmake(lldb_cmake_path,

                     lldb_path,

                     lldb_defines,

                     env=dict(self.build_config.ORIG_ENV))

   self.invoke_ninja(out_path=lldb_path,

                     env=dict(self.build_config.ORIG_ENV),

                     target='lldb-server',

                     install=False)

   self.llvm_package.copy_lldb_server_to_llvm_install(lldb_path, crt_install, llvm_triple)

2.2.6.9 build_runtimes_for_windows方法解析

def build_runtimes_for_windows(self, enable_assertions):

self.logger().info('Building libs for windows.')

toolchain_dir = self.merge_out_path('llvm-install')

install_dir = self.merge_out_path('windows-x86_64-install')

windows_sysroot = self.merge_out_path('mingw', self.build_config.MINGW_TRIPLE)

cflags = ['-stdlib=libc++', '--target=x86_64-pc-windows-gnu', '-D_LARGEFILE_SOURCE',

'-D_FILE_OFFSET_BITS=64', '-D_WIN32_WINNT=0x0600', '-DWINVER=0x0600', '-D__MSVCRT_VERSION__=0x1400']

cmake_defines = {}

cmake_defines['CMAKE_C_COMPILER'] = os.path.join(toolchain_dir, 'bin', 'clang')

cmake_defines['CMAKE_CXX_COMPILER'] = os.path.join(toolchain_dir, 'bin', 'clang++')

cmake_defines['CMAKE_CROSSCOMPILING'] = 'True'

cmake_defines['CMAKE_SYSTEM_NAME'] = 'Windows'

cmake_defines['CMAKE_SYSROOT'] = windows_sysroot

cmake_defines['CMAKE_ASM_FLAGS'] = ' '.join(cflags)

cmake_defines['CMAKE_C_FLAGS'] = ' '.join(cflags)

cmake_defines['CMAKE_CXX_FLAGS'] = ' '.join(cflags)

cmake_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY'

cmake_defines['CMAKE_INSTALL_PREFIX'] = install_dir

cmake_defines['LLVM_CONFIG_PATH'] = os.path.join(toolchain_dir, 'bin', 'llvm-config')

cmake_defines['LIBCXX_ENABLE_SHARED'] = 'OFF'

cmake_defines['LIBCXX_ENABLE_STATIC_ABI_LIBRARY'] = 'ON'

cmake_defines['LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS'] = 'ON'

cmake_defines['LIBCXXABI_ENABLE_SHARED'] = 'OFF'

cmake_defines['LIBUNWIND_ENABLE_SHARED'] = 'OFF'

cmake_defines['LIBCXXABI_USE_LLVM_UNWINDER'] = 'ON'

cmake_defines['LLVM_ENABLE_RUNTIMES'] = 'libunwind;libcxxabi;libcxx'

cmake_defines['LLVM_ENABLE_ASSERTIONS'] = 'ON' if enable_assertions else 'OFF'

out_path = self.merge_out_path('lib', 'windows-runtimes')

cmake_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'runtimes'))

self.invoke_cmake(cmake_path,

out_path,

cmake_defines,

env=dict(self.build_config.ORIG_ENV))

self.invoke_ninja(out_path,

env=dict(self.build_config.ORIG_ENV),

install=True)

2.2.7 LldbMi类

2.2.7.1 build_lldb_mi方法解析

def build_lldb_mi(self, llvm_install):

self.logger().info('Building lldb-mi for linux.')

llvm_path = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR,

'prebuilts/clang/ohos', self.use_platform(), 'clang-%s' % self.build_config.CLANG_VERSION))

lldb_mi_cmake_path = os.path.join(self.build_config.LLVM_PROJECT_DIR, '../lldb-mi')

lldb_mi_path = self.merge_out_path('lldb_mi_build')

self.check_rm_tree(lldb_mi_path)

self.rm_cmake_cache(lldb_mi_path)

if self.host_is_darwin():

cflags = []

cxxflags =[]

ldflags = ['-Wl,-rpath,%s' % '@loader_path/../lib']

else:

cflags = []

cxxflags =[]

ldflags = ['-fuse-ld=lld', '-Wl,-rpath,%s' % '\$ORIGIN/../lib']

ldflags.append('-Wl,-z,relro,-z,now -pie')

if self.build_config.strip:

ldflags.append('-s')

ldflags.append('-L%s' % os.path.join(llvm_path, 'lib'))

cxxflags.append('-std=c++14')

cxxflags.append('-fstack-protector-strong -fPIE')

cflags.append('-fstack-protector-strong -fPIE')

lldb_mi_defines = {}

lldb_mi_defines['CMAKE_C_COMPILER'] = os.path.join(llvm_path, 'bin', 'clang')

lldb_mi_defines['CMAKE_CXX_COMPILER'] = os.path.join(llvm_path, 'bin', 'clang++')

lldb_mi_defines['CMAKE_C_FLAGS'] = ' '.join(cflags)

lldb_mi_defines['CMAKE_CXX_FLAGS'] = ' '.join(cxxflags)

lldb_mi_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags)

lldb_mi_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags)

lldb_mi_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags)

lldb_mi_defines['LLVM_DIR'] = os.path.join(llvm_install, 'lib/cmake/llvm/')

lldb_mi_defines['LLVM_ENABLE_LIBCXX'] = 'ON'

lldb_mi_defines['CMAKE_INSTALL_PREFIX'] = llvm_install

self.invoke_cmake(lldb_mi_cmake_path,

lldb_mi_path,

lldb_mi_defines,

env=dict(self.build_config.ORIG_ENV))

self.invoke_ninja(lldb_mi_path,

env=dict(self.build_config.ORIG_ENV),

install=False)

self.llvm_package.copy_lldb_mi_to_llvm_install(lldb_mi_path, llvm_install)

2.2.7.2 ldflags_lists_define方法解析

@staticmethod

def ldflags_lists_define():

ldflags_lists = ['-Wl,--dynamicbase',

'-Wl,--nxcompat',

'-lucrt',

'-lucrtbase',

'-L', ]

return ldflags_lists

2.2.7.3 cflags_lists_define方法解析

@staticmethod

def cflags_lists_define():

cflags_lists = ['-D_LARGEFILE_SOURCE',

'-D_FILE_OFFSET_BITS=64',

'-D_WIN32_WINNT=0x0600',

'-DWINVER=0x0600',

'-D__MSVCRT_VERSION__=0x1400',

'-DMS_WIN64', ]

return cflags_lists

2.2.7.4 lldb_mi_windefines_dictionary方法解析

def lldb_mi_windefines_dictionary(self, cc, cxx, windows_sysroot, cflags, cxxflags, ldflags):

lldb_mi_windefines = {}

lldb_mi_windefines['CMAKE_C_COMPILER'] = cc

lldb_mi_windefines['CMAKE_CXX_COMPILER'] = cxx

lldb_mi_windefines['CMAKE_C_COMPILER_WORKS'] = '1'

lldb_mi_windefines['CMAKE_CXX_COMPILER_WORKS'] = '1'

lldb_mi_windefines['CMAKE_SYSTEM_NAME'] = 'Windows'

lldb_mi_windefines['CMAKE_SYSTEM_PROCESSOR'] = 'x86_64'

lldb_mi_windefines['LLVM_ENABLE_LIBCXX'] = 'ON'

lldb_mi_windefines['CMAKE_SYSROOT'] = windows_sysroot

lldb_mi_windefines['LLVM_INSTALL_PREFIX'] = self.merge_out_path('windows-x86_64-install')

lldb_mi_windefines['LLVM_DIR'] = self.merge_out_path('windows-x86_64-install/lib/cmake/llvm/')

lldb_mi_windefines['CMAKE_C_FLAGS'] = ' '.join(cflags)

lldb_mi_windefines['CMAKE_CXX_FLAGS'] = ' '.join(cxxflags)

lldb_mi_windefines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags)

lldb_mi_windefines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags)

lldb_mi_windefines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags)

if self.build_config.enable_assertions:

lldb_mi_windefines['LLVM_ENABLE_ASSERTIONS'] = 'ON'

return lldb_mi_windefines

2.2.7.5 build_lldb_mi_for_windows方法解析

def build_lldb_mi_for_windows(self):

   self.logger().info('Building lldb-mi for windows.')

   build_dir = self.merge_out_path('llvm-install')

   lldb_mi_windows64_path = self.merge_out_path('windows-x86_64-lldb-mi')

   lldb_mi_cmake_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, '../lldb-mi'))

   windows64_install = self.merge_out_path('windows-x86_64-install')

   cc = os.path.join(build_dir, 'bin', 'clang')

   cxx = os.path.join(build_dir, 'bin', 'clang++')

   windows_sysroot = self.merge_out_path('mingw', self.build_config.MINGW_TRIPLE)

   self.check_create_dir(lldb_mi_windows64_path)

   ldflags = ['-fuse-ld=lld',

              '--rtlib=compiler-rt',

              '-lunwind',

              '-L%s' % os.path.join(windows64_install, 'lib'),

              ]

   ldflags.extend(self.ldflags_lists_define())

   ldflags.append(os.path.join(windows64_install, 'lib'))

   ldflags.append('-Wl,--high-entropy-va')

   cflags = ['-stdlib=libc++',

             '--target=x86_64-pc-windows-gnu',

            ]

   cflags.extend(self.cflags_lists_define())

   cflags.append('-fno-exceptions')

   cflags.append('-fno-rtti')

   cxxflags = list(cflags)

   cxxflags.extend(('-I', os.path.join(windows64_install, 'include', 'c++', 'v1')))

   zlib_path = os.path.abspath(

       os.path.join('../../', 'prebuilts', 'clang', 'host', 'windows-x86', 'toolchain-prebuilts', 'zlib'))

   zlib_inc = os.path.join(zlib_path, 'include')

   zlib_lib = os.path.join(zlib_path, 'lib')

   cflags.extend(['-I', zlib_inc])

   cxxflags.extend(['-I', zlib_inc])

   ldflags.extend(['-L', zlib_lib])

   lldb_mi_env = dict(self.build_config.ORIG_ENV)

   lldb_mi_env['LD_LIBRARY_PATH'] = os.path.join(build_dir, 'lib')

   self.rm_cmake_cache(lldb_mi_windows64_path)

   self.invoke_cmake(lldb_mi_cmake_path,

                     lldb_mi_windows64_path,

                     self.lldb_mi_windefines_dictionary(cc, cxx, windows_sysroot, cflags, cxxflags, ldflags),

                     env=lldb_mi_env)

   self.invoke_ninja(lldb_mi_windows64_path,

                     env=lldb_mi_env,

                     install=False)

   self.llvm_package.copy_lldb_mi_to_windows(windows64_install, lldb_mi_windows64_path)

2.2.8 LlvmPackage类

2.2.8.1 copy_lldb_server_to_llvm_install方法解析

拷贝lldb-server到install目录

def copy_lldb_server_to_llvm_install(self, lldb_path, crt_install, llvm_triple):

   # Copy lldb-server

   libname = 'lldb-server'

   src_lib = os.path.join(lldb_path, 'bin', libname)

   dst_dir = os.path.join(crt_install, 'bin', llvm_triple)

   self.check_create_dir(dst_dir)

   self.check_copy_file(src_lib, os.path.join(dst_dir, libname))

2.2.8.2 copy_lldb_mi_to_llvm_install方法解析

拷贝lldb-mi到install目录

def copy_lldb_mi_to_llvm_install(self, lldb_mi_path, llvm_install):

   # Copy lldb-mi

   lldb_mi_dst = os.path.join(llvm_install, 'bin', 'lldb-mi')

   lldb_mi_src = os.path.join(lldb_mi_path, 'src', 'lldb-mi')

   if os.path.exists(lldb_mi_dst):

       os.remove(lldb_mi_dst)

   self.check_copy_file(lldb_mi_src, lldb_mi_dst)

2.2.8.3 copy_lldb_mi_to_windows方法解析

拷贝lldb-mi到windows目录

def copy_lldb_mi_to_windows(self, windows64_install, lldb_mi_windows64_path):

   # Copy lldb-mi for windows

   lldb_mi_dst = os.path.join(windows64_install, 'bin', 'lldb-mi.exe')

   lldb_mi_src = os.path.join(lldb_mi_windows64_path, 'src', 'lldb-mi.exe')

   if os.path.exists(lldb_mi_dst):

       os.remove(lldb_mi_dst)

   self.check_copy_file(lldb_mi_src, lldb_mi_dst)

2.2.8.4 package_libcxx方法解析

打包镜像成tar.bz2格式

def package_libcxx(self):

   libcxx_ndk_install=self.merge_out_path('libcxx-ndk')

   libcxx_ndk_install_tmp=self.merge_out_path('libcxx-ndk-tmp')

   libcxx_ndk_install_include=self.merge_out_path(libcxx_ndk_install, 'include', 'libcxx-ohos', 'include', 'c++', 'v1')

   hosts_list=['linux-x86_64', 'darwin-x86_64', 'windows-x86_64', 'darwin-arm64']

   if os.path.exists(libcxx_ndk_install):

       for headerfile in os.listdir(libcxx_ndk_install_include):

           if not headerfile =='__config':

               if os.path.isdir(os.path.join(libcxx_ndk_install_include, headerfile)):

                   shutil.rmtree(os.path.join(libcxx_ndk_install_include, headerfile))

               else:

                   os.remove(os.path.join(libcxx_ndk_install_include, headerfile))

       #Package libcxx-ndk

       for host in hosts_list:

           tarball_name = 'libcxx-ndk-%s-%s' % (self.build_config.build_name, host)

           package_path = '%s%s' % (self.merge_out_path(tarball_name), '.tar.bz2')

           self.logger().info('Packaging %s', package_path)

           args = ['tar', '-chjC', self.build_config.OUT_PATH, '-f', package_path, 'libcxx-ndk']

           self.check_call(args)

       self.check_rm_tree(libcxx_ndk_install)

       self.check_rm_tree(libcxx_ndk_install_tmp)

2.2.8.5 merge_tree方法解析

拷贝文件和目录

@staticmethod

def merge_tree(src_dir, dst_dir):

for item in os.listdir(src_dir):

src_path = os.path.join(src_dir, item)

dst_path = os.path.join(dst_dir, item)

if os.path.isfile(src_path):

shutil.copyfile(src_path, dst_path)

else:

shutil.copytree(src_path, dst_path)

2.2.8.6 install_mingw_python方法解析

安装mingw_python

def install_mingw_python(self, install_dir):

py_root = self.merge_out_path('../third_party', 'mingw-w64', 'mingw-w64-python',

self.build_config.LLDB_PY_VERSION)

bin_root = os.path.join(install_dir, 'bin')

py_dll = 'libpython' + self.build_config.LLDB_PY_VERSION + '.dll'

shutil.copyfile(os.path.join(py_root, py_dll), os.path.join(bin_root, py_dll))

self.merge_tree(os.path.join(py_root, 'lib'),

os.path.join(bin_root, 'python', 'lib', 'python%s' % self.build_config.LLDB_PY_VERSION))

2.2.8.7 windows_lib_files_operation方法解析

windows库文件的操作,不介绍

def windows_lib_files_operation(self, lib_files, lib_dir, install_dir):

# Remove unnecessary Windows lib files.

windows_necessary_lib_files = ['libc++.a', 'libc++abi.a']

for lib_file in lib_files:

if lib_file.endswith('.a') and lib_file not in windows_necessary_lib_files:

static_library = os.path.join(lib_dir, lib_file)

os.remove(static_library)

for necessary_lib_file in windows_necessary_lib_files:

if not os.path.isfile(os.path.join(lib_dir, necessary_lib_file)):

raise RuntimeError('Did not find %s under %s' % (necessary_lib_file, lib_dir))

self.install_mingw_python(install_dir)

2.2.8.8 darwin_stripped_xargs方法解析

darwin系统相关,不介绍

def darwin_stripped_xargs(self, bin_dir, necessary_bin_files, script_bins, need_x_bins_darwin):

   for bin_filename in os.listdir(bin_dir):

       binary = os.path.join(bin_dir, bin_filename)

       if not os.path.isfile(binary):

           continue

       if bin_filename not in necessary_bin_files:

           os.remove(binary)

       elif bin_filename not in script_bins and self.build_config.strip:

           if bin_filename not in need_x_bins_darwin and self.host_is_darwin():

               self.check_call(['strip', '-x', binary])

           else:

               self.check_call(['strip', binary])

2.2.8.9 strip_lldb_server方法解析

使用llvm-strip工具对${clang_version_bin_dir}/lib/clang/bin里面的文件进行瘦身,也就是lldb-server文件

def strip_lldb_server(self, host, install_dir):

   clang_version_bin_dir = os.path.join(install_dir, 'lib', 'clang', self.build_config.CLANG_VERSION, 'bin')

   if not host.startswith('linux') or not os.path.exists(clang_version_bin_dir) or not self.build_config.strip:

       return

   llvm_strip = os.path.join(install_dir, 'bin', 'llvm-strip')

   # os.listdir 返回指定路径下的目录和文件列表

   for llvm_triple_dir in os.listdir(clang_version_bin_dir):

       llvm_triple_bin_dir = os.path.join(clang_version_bin_dir, llvm_triple_dir)

       if not os.path.isdir(llvm_triple_bin_dir):

           continue

       for bin_filename in os.listdir(llvm_triple_bin_dir):

           binary = os.path.join(llvm_triple_bin_dir, bin_filename)

           if os.path.isfile(binary):

               self.check_call([llvm_strip, binary])

2.2.8.10 notice_prebuilts_file方法解析

添加NOTICE文件到每个工程下

def notice_prebuilts_file(self, host, projects, install_dir):

   # Fetch all the LICENSE.* files under our projects and append them into a

   # Single NOTICE file for the resulting prebuilts.

   notices = []

   for project in projects:

       license_pattern = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, project, 'LICENSE.*'))

       # glob.glob 查找符合特定规则的文件路径名

       for license_file in glob.glob(license_pattern):

           with open(license_file) as notice_file:

               notices.append(notice_file.read())

   zlib_license_file = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, 'third_party/zlib/LICENSE'))

   with open(zlib_license_file) as notice_file:

       notices.append(notice_file.read())

   if host.startswith('windows'):

       mingw_license_file = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR,

                                                           'third_party/mingw-w64/COPYING'))

       with open(mingw_license_file) as notice_file:

           notices.append(notice_file.read())

   with open(os.path.join(install_dir, 'NOTICE'), 'w') as notice_file:

       notice_file.write('\n'.join(notices))

2.2.8.11 package_clang_bin_file方法解析

二进制文件添加扩展名,linux里面不涉及

@staticmethod

def package_clang_bin_file(self, necessary_bin_files, ext):

   necessary_bin_file = [

       'clang%s' % ext,

       'clang++%s' % ext,

       'clang-cpp%s' % ext,

       'clang-%s%s' % (self.build_config.VERSION.split('.')[0], ext),

       'clang-check%s' % ext,

       'clang-cl%s' % ext,

       'clang-format%s' % ext,

       'clang-tidy%s' % ext,

       'clangd%s' % ext,

       'count%s' % ext,

      ]

   necessary_bin_files.extend(necessary_bin_file)

2.2.8.12 package_lldb_bin_file方法解析

同上

@staticmethod

def package_llvm_bin_file(necessary_bin_files, ext):

   necessary_bin_file = [

       'llvm-addr2line%s' % ext,

       'llvm-ar%s' % ext,

       'llvm-as%s' % ext,

       'llvm-cfi-verify%s' % ext,

       'llvm-config%s' % ext,

       'llvm-cov%s' % ext,

       'llvm-cxxfilt%s' % ext,

       'llvm-dis%s' % ext,

       'llvm-lib%s' % ext,

       'llvm-link%s' % ext,

       'llvm-modextract%s' % ext,

       'llvm-nm%s' % ext,

       'llvm-objcopy%s' % ext,

       'llvm-objdump%s' % ext,

       'llvm-profdata%s' % ext,

       'llvm-ranlib%s' % ext,

       'llvm-readelf%s' % ext,

       'llvm-readobj%s' % ext,

       'llvm-rc%s' % ext,

       'llvm-size%s' % ext,

       'llvm-strings%s' % ext,

       'llvm-strip%s' % ext,

       'llvm-symbolizer%s' % ext,

      ]

   necessary_bin_files.extend(necessary_bin_file)

2.2.8.13package_llvm_bin_file方法解析

同上

@staticmethod

def package_llvm_bin_file(necessary_bin_files, ext):

necessary_bin_file = [

'llvm-addr2line%s' % ext,

'llvm-ar%s' % ext,

'llvm-as%s' % ext,

'llvm-cfi-verify%s' % ext,

'llvm-config%s' % ext,

'llvm-cov%s' % ext,

'llvm-cxxfilt%s' % ext,

'llvm-dis%s' % ext,

'llvm-lib%s' % ext,

'llvm-link%s' % ext,

'llvm-modextract%s' % ext,

'llvm-nm%s' % ext,

'llvm-objcopy%s' % ext,

'llvm-objdump%s' % ext,

'llvm-profdata%s' % ext,

'llvm-ranlib%s' % ext,

'llvm-readelf%s' % ext,

'llvm-readobj%s' % ext,

'llvm-rc%s' % ext,

'llvm-size%s' % ext,

'llvm-strings%s' % ext,

'llvm-strip%s' % ext,

'llvm-symbolizer%s' % ext,

]

necessary_bin_files.extend(necessary_bin_file)

2.2.8.14 package_scan_bin_file方法解析

同上

@staticmethod

def package_scan_bin_file(necessary_bin_files, ext):

   necessary_bin_file = [

       'not%s' % ext,

       'sancov%s' % ext,

       'sanstats%s' % ext,

       'scan-build%s' % ext,

       'scan-view%s' % ext,

       'yaml2obj%s' % ext,

      ]

   necessary_bin_files.extend(necessary_bin_file)

2.2.8.15 package_license_project_tuple方法解析

@staticmethod

def package_license_project_tuple():

   # Install license files as NOTICE in the toolchain install dir.

   projects = (

       'llvm',

       'compiler-rt',

       'libcxx',

       'libcxxabi',

       'openmp',

       'clang',

       'clang-tools-extra',

       'lld',

       'lldb',

       'libunwind',

  )

   return projects

2.2.8.16 remove_unnecessary_bin方法解析

移除无用的文件,针对linux环境就是移除.a静态库

def remove_unnecessary_bin(self, necessary_bin_files, host, lib_dir, install_dir, ext, shlib_ext):

   lib_files = []

   if os.path.isdir(lib_dir):

           lib_files = os.listdir(lib_dir)

   if host.startswith('windows'):

       vers_major = int(self.build_config.VERSION.split('.')[0])

       # Redefining necessary bin files for Windows.

       windows_forbidden_list_bin_files = ['clang-%s%s' % (vers_major, ext), 'scan-build%s' % ext,

                                      'scan-view%s' % ext]

       windows_additional_bin_files = ['liblldb%s' % shlib_ext, 'libpython3.10%s' % shlib_ext]

       new_necessary_bin_files = list(set(necessary_bin_files) - set(windows_forbidden_list_bin_files))

       new_necessary_bin_files.extend(windows_additional_bin_files)

       del necessary_bin_files[:]

       necessary_bin_files.extend(new_necessary_bin_files)

       self.windows_lib_files_operation(lib_files, lib_dir, install_dir)

   else:

       # Remove unnecessary static libraries.

       for lib_file in lib_files:

           if lib_file.endswith('.a'):

               static_library = os.path.join(lib_dir, lib_file)

               os.remove(static_library)

2.2.8.17 package_up_resulting方法解析

打包结果

def package_up_resulting(self, package_name, host, install_host_dir):

# Package up the resulting trimmed install/ directory.

tarball_name = '%s-%s' % (package_name, host)

package_path = '%s%s' % (self.merge_out_path(tarball_name), '.tar.bz2')

self.logger().info('Packaging %s', package_path)

args = ['tar', '-cjC', install_host_dir, '-f', package_path, package_name]

if host.startswith('windows'):

# windows do not support symlinks,

# replace them with file copies

args.insert(1, '--dereference')

self.check_call(args)

# Package ohos NDK

if os.path.exists(self.merge_out_path('sysroot')):

tarball_ndk_name = 'ohos-sysroot-%s' % self.build_config.build_name

package_ndk_path = '%s%s' % (self.merge_out_path(tarball_ndk_name), '.tar.bz2')

self.logger().info('Packaging %s', package_ndk_path)

args = ['tar', '-chjC', self.build_config.OUT_PATH, '-f', package_ndk_path, 'sysroot']

self.check_call(args)

2.2.8.18 package_operation方法解析

打包操作

   def package_operation(self, build_dir, host):

       self.logger().info('Packaging for other environments.')

       package_name = 'clang-%s' % self.build_config.build_name

       self.set_clang_version(build_dir)

       if host.startswith('windows'):

           ext = '.exe'

           shlib_ext = '.dll'

       elif host.startswith('linux'):

           ext = ''

           shlib_ext = '.so'

       else:

           ext = ''

           shlib_ext = '.dylib'

       install_dir = self.merge_out_path('install', host, package_name)

       bin_dir = os.path.join(install_dir, 'bin')

       lib_dir = os.path.join(install_dir, 'lib')

       install_host_dir = os.path.abspath(os.path.join(install_dir, '../'))

       self.check_rm_tree(install_host_dir)

       self.check_copy_tree(build_dir, install_dir)

       # copy readme file to install_dir

       shutil.copyfile(os.path.join(self.build_config.LLVM_BUILD_DIR, "toolchain_readme.md"),

                       os.path.join(install_dir, "README.md"))

       # Generate manifest in install_dir

       manifest = os.path.join(install_dir, 'manifest.xml')

       repo_tool = os.path.join(self.build_config.REPOROOT_DIR, '.repo', 'repo', 'repo')

       if os.path.isfile(repo_tool):

           self.logger().info('Generating manifest.')

           # 执行命令 .repo/repo/repo manifest -r -o

           subprocess.run([repo_tool, 'manifest', '-r', '-o', manifest], shell=False,

                          stdout=subprocess.PIPE, cwd=self.build_config.REPOROOT_DIR)

       else:

           self.logger().error('Cannot generate manifest, repo tool not found.')

       # Remove unnecessary binaries.

       necessary_bin_files = []

       self.package_clang_bin_file(necessary_bin_files, ext)

       self.package_lldb_bin_file(necessary_bin_files, ext)

       self.package_llvm_bin_file(necessary_bin_files, ext)

       self.package_scan_bin_file(necessary_bin_files, ext)

       if self.build_config.need_lldb_mi:

           necessary_bin_files.append('lldb-mi%s' % ext)

       self.remove_unnecessary_bin(necessary_bin_files, host, lib_dir, install_dir, ext, shlib_ext)

       # Scripts that should not be stripped

       script_bins = ['git-clang-format', 'scan-build', 'scan-view']

       need_x_bins_darwin = ['clang', 'clang++', 'clang-9', 'clang-cl', 'clang-cpp']

       # Bin file in the list should be stripped with -x args when host=darwin

       self.darwin_stripped_xargs(bin_dir, necessary_bin_files, script_bins, need_x_bins_darwin)

       # Strip lldb-server

       self.strip_lldb_server(host, install_dir)

       for necessary_bin_file in necessary_bin_files:

           if not os.path.isfile(os.path.join(bin_dir, necessary_bin_file)):

               print('Did not find %s in %s' % (necessary_bin_file, bin_dir))

               raise RuntimeError('Did not find %s in %s' % (necessary_bin_file, bin_dir))

       cmake_dir = os.path.join(lib_dir, 'cmake')

       self.check_rm_tree(cmake_dir)

       self.notice_prebuilts_file(host, self.package_license_project_tuple(), install_dir)

       create_tar = True

       if create_tar:

           self.package_up_resulting(package_name, host, install_host_dir)

       return

2.2.9 main函数介绍

def main():

  build_config = BuildConfig()

  build_utils = BuildUtils(build_config)

  sysroot_composer = SysrootComposer(build_config)

  llvm_core = LlvmCore(build_config)

  llvm_package = LlvmPackage(build_config)

  lldb_mi = LldbMi(build_config, llvm_package)

  llvm_libs = LlvmLibs(build_config, sysroot_composer, llvm_package)

  args = build_config.parse_args()

  need_host = build_utils.host_is_darwin() or ('linux' not in args.no_build)

  need_windows = build_utils.host_is_linux() and \

                  ('windows' not in args.no_build)

  llvm_install = build_utils.merge_out_path('llvm-install')

  windows64_install = build_utils.merge_out_path('windows-x86_64-install')

  configs = []

   if not build_config.no_build_arm:

      configs.append(('arm', build_utils.liteos_triple('arm')))

      configs.append(('arm', build_utils.open_ohos_triple('arm')))

   if not build_config.no_build_aarch64:

      configs.append(('arm64', build_utils.open_ohos_triple('aarch64')))

   if not build_config.no_build_riscv64:

      configs.append(('riscv', build_utils.open_ohos_triple('riscv64')))

   if not build_config.no_build_mipsel:

      configs.append(('mipsel', build_utils.open_ohos_triple('mipsel')))

   if not build_config.no_build_x86_64:

      configs.append(('x86_64', build_utils.open_ohos_triple('x86_64')))

   if build_config.do_build and need_host:

      llvm_core.llvm_compile(

          build_config.build_name,

          llvm_install,

          build_config.debug,

          build_config.no_lto,

          build_config.build_instrumented,

          build_config.xunit_xml_output)

  llvm_core.set_clang_version(llvm_install)

   if build_config.do_build and build_utils.host_is_linux():

      sysroot_composer.setup_cmake_platform(llvm_install)

      llvm_libs.build_crt_libs(configs, llvm_install, build_config.need_lldb_server)

       if build_config.need_libs:

           for (arch, target) in configs:

              llvm_libs.build_libs(build_config.need_lldb_server, llvm_install, target)

   if build_config.do_build and need_windows:

      mingw.main(build_config.VERSION)

      llvm_libs.build_runtimes_for_windows(build_config.enable_assertions)

      llvm_core.llvm_compile_for_windows(build_config.TARGETS,

                                        build_config.enable_assertions,

                                        build_config.build_name)

       if build_config.need_lldb_mi:

          lldb_mi.build_lldb_mi_for_windows()

   if build_config.do_build and build_config.need_lldb_mi and need_host:

      lldb_mi.build_lldb_mi(llvm_install)

   if build_config.do_package:

       if build_utils.host_is_linux():

          llvm_package.package_libcxx()

      llvm_package.package_operation(llvm_install, build_utils.use_platform())

       if build_config.do_package and need_windows:

          llvm_package.package_operation(windows64_install, 'windows-x86_64')

三、编译报错问题解决

3.1 编译报Curses问题处理

【问题描述】

执行命令python3 ./toolchain/llvm-project/llvm-build/build.py报错如下:

CMake Error at /home/wen_fei/OpenHarmony/llvm-toolchains/prebuilts/cmake/linux-x86/share/cmake-3.16/Modules/FindPackageHandleStandardArgs.cmake:146 (message):

Could NOT find Curses (missing: CURSES_LIBRARY CURSES_INCLUDE_PATH)

Call Stack (most recent call first):

/home/wen_fei/OpenHarmony/llvm-toolchains/prebuilts/cmake/linux-x86/share/cmake-3.16/Modules/FindPackageHandleStandardArgs.cmake:393 (_FPHSA_FAILURE_MESSAGE)

/home/wen_fei/OpenHarmony/llvm-toolchains/prebuilts/cmake/linux-x86/share/cmake-3.16/Modules/FindCurses.cmake:258 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)

src/CMakeLists.txt:92 (find_package)

-- Configuring incomplete, errors occurred!

【问题分析】

出现该错误的是因为在系统中找不到libncurses.so库的原因

【问题处理】

安装如下软件 sudo apt-get install liblua5.1-dev

sudo apt install libncurses5 进入/usr/lib目录下执行find ./ -name libncurses.so*,发现这些库都在x86_64-linux-gnu目录下 # find . -name libncurses.so*

./x86_64-linux-gnu/libncurses.so.6

./x86_64-linux-gnu/libncurses.so

./x86_64-linux-gnu/libncurses.so.5.9

./x86_64-linux-gnu/libncurses.so.5

./x86_64-linux-gnu/libncurses.so.6.2 添加软链接 sudo su

cd /usr/lib

ln -s ./x86_64-linux-gnu/libncurses.so libncurses.so 重新编译即可

3.2 编译报fatal error: 'plugin-api.h'问题处理

【问题描述】

执行命令python3 ./toolchain/llvm-project/llvm-build/build.py报错如下:

-- Failed to find LLVM FileCheck

-- git version: v0.0.0-dirty normalized to 0.0.0

-- Version: 1.6.0

-- Performing Test HAVE_THREAD_SAFETY_ATTRIBUTES -- failed to compile

-- Performing Test HAVE_GNU_POSIX_REGEX -- failed to compile

-- Performing Test HAVE_POSIX_REGEX -- success

-- Performing Test HAVE_STEADY_CLOCK -- success

-- Configuring done

-- Generating done

-- Build files have been written to: /home/wen_fei/OpenHarmony/llvm/out/llvm_make

INFO:__main__:check_call:22:34:51 /home/wen_fei/OpenHarmony/llvm/prebuilts/cmake/linux-x86/bin/ninja

[92/3581] Building CXX object tools/gold/CMakeFiles/LLVMgold.dir/gold-plugin.cpp.o

FAILED: tools/gold/CMakeFiles/LLVMgold.dir/gold-plugin.cpp.o

/home/wen_fei/OpenHarmony/llvm/prebuilts/clang/ohos/linux-x86_64/clang-10.0.1/bin/clang++ -DGTEST_HAS_RTTI=0 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools/gold -I/home/wen_fei/OpenHarmony/llvm/toolchain/llvm-project/llvm/tools/gold -Iinclude -I/home/wen_fei/OpenHarmony/llvm/toolchain/llvm-project/llvm/include -fstack-protector-strong -fPIE -stdlib=libc++ -stdlib=libc++ -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wno-comment -Wstring-conversion -Wmisleading-indentation -fdiagnostics-color -ffunction-sections -fdata-sections -flto=thin -O3 -DNDEBUG -fPIC   -fno-exceptions -fno-rtti -std=c++14 -MD -MT tools/gold/CMakeFiles/LLVMgold.dir/gold-plugin.cpp.o -MF tools/gold/CMakeFiles/LLVMgold.dir/gold-plugin.cpp.o.d -o tools/gold/CMakeFiles/LLVMgold.dir/gold-plugin.cpp.o -c /home/wen_fei/OpenHarmony/llvm/toolchain/llvm-project/llvm/tools/gold/gold-plugin.cpp

/home/wen_fei/OpenHarmony/llvm/toolchain/llvm-project/llvm/tools/gold/gold-plugin.cpp:38:10: fatal error: 'plugin-api.h' file not found

#include

        ^~~~~~~~~~~~~~

1 error generated.

[125/3581] Linking CXX shared library lib/libLTO.so.15

clang-10: warning: argument unused during compilation: '-pie' [-Wunused-command-line-argument]

ninja: build stopped: subcommand failed.

Traceback (most recent call last):

File "./toolchain/llvm-project/llvm-build/build.py", line 1855, in

   main()

File "./toolchain/llvm-project/llvm-build/build.py", line 1816, in main

  llvm_core.llvm_compile(

File "./toolchain/llvm-project/llvm-build/build.py", line 556, in llvm_compile

  self.build_llvm(targets=self.build_config.TARGETS,

File "./toolchain/llvm-project/llvm-build/build.py", line 431, in build_llvm

  self.invoke_ninja(out_path=build_dir,

File "./toolchain/llvm-project/llvm-build/build.py", line 256, in invoke_ninja

  self.check_call([ninja_bin_path] + ninja_list + ninja_target, cwd=out_path, env=env)

File "./toolchain/llvm-project/llvm-build/build.py", line 325, in check_call

  subprocess.check_call(cmd, *args, **kwargs)

File "/usr/lib/python3.8/subprocess.py", line 364, in check_call

  raise CalledProcessError(retcode, cmd)

subprocess.CalledProcessError: Command '['/home/wen_fei/OpenHarmony/llvm/prebuilts/cmake/linux-x86/bin/ninja']' returned non-zero exit status 1.

【问题分析】

出现该错误是需要安装binutils-dev

【问题处理】

执行如下命令 sudo apt-get -f -y install binutils-dev

使用以下命令查找plugin-api.h文件是否存在 $ find /usr -name plugin-api.h

/usr/include/plugin-api.h

/usr/lib/gcc/arm-none-eabi/9.2.1/plugin/include/plugin-api.h

/usr/lib/gcc/x86_64-linux-gnu/9/plugin/include/plugin-api.h

3.3 编译报fatal error: 'asm/errno.h'问题处理

【问题描述】

执行命令python3 ./toolchain/llvm-project/llvm-build/build.py报错如下:

-- check-shadowcallstack does nothing.

-- Configuring done

-- Generating done

CMake Warning:

Manually-specified variables were not used by the project:

  LLVM_BUILD_TOOLS

-- Build files have been written to: /home/wen_fei/OpenHarmony/llvm/out/llvm_make/runtimes/runtimes-bins

[2892/3455] Performing build step for 'runtimes'

[819/1056] Building C object compiler-rt/lib/profile/CMakeFiles/clang_rt.profile-i386.dir/GCDAProfiling.c.o

FAILED: compiler-rt/lib/profile/CMakeFiles/clang_rt.profile-i386.dir/GCDAProfiling.c.o

/home/wen_fei/OpenHarmony/llvm/out/llvm_make/./bin/clang --target=x86_64-unknown-linux-gnu -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/wen_fei/OpenHarmony/llvm/toolchain/llvm-project/compiler-rt/lib/profile/.. -I/home/wen_fei/OpenHarmony/llvm/toolchain/llvm-project/compiler-rt/lib/profile/../../include -fPIC -fno-semantic-interposition -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wmissing-field-initializers -Wimplicit-fallthrough -Wcovered-switch-default -Wno-comment -Wstring-conversion -Wmisleading-indentation -fdiagnostics-color -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -O3 -DNDEBUG   -m32 -fno-lto -fPIC -Wno-pedantic -DCOMPILER_RT_HAS_ATOMICS=1 -DCOMPILER_RT_HAS_FCNTL_LCK=1 -DCOMPILER_RT_HAS_UNAME=1 -nostdinc++ -MD -MT compiler-rt/lib/profile/CMakeFiles/clang_rt.profile-i386.dir/GCDAProfiling.c.o -MF compiler-rt/lib/profile/CMakeFiles/clang_rt.profile-i386.dir/GCDAProfiling.c.o.d -o compiler-rt/lib/profile/CMakeFiles/clang_rt.profile-i386.dir/GCDAProfiling.c.o   -c /home/wen_fei/OpenHarmony/llvm/toolchain/llvm-project/compiler-rt/lib/profile/GCDAProfiling.c

In file included from /home/wen_fei/OpenHarmony/llvm/toolchain/llvm-project/compiler-rt/lib/profile/GCDAProfiling.c:24:

In file included from /usr/include/errno.h:28:

In file included from /usr/include/bits/errno.h:26:

/usr/include/linux/errno.h:1:10: fatal error: 'asm/errno.h' file not found

#include

        ^~~~~~~~~~~~~

1 error generated.

【问题分析】

/usr/include/目录下有x86_64-linux-gnu/asm目录却没有asm目录,需要手动创建软链接

【问题处理】

执行如下命令即可

sudo su

cd /usr/include

ln -s x86_64-linux-gnu/asm asm

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: