blob: daae8343d997b7708fffed7038cee0118034c58b [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright (C) 2020 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Package to manage LLVM sources when building a toolchain.
"""
import os
import shutil
import string
import subprocess
import android_version
import utils
def apply_patches(source_dir, svn_version, patch_json, patch_dir):
"""Apply patches in $patch_dir/$patch_json to $source_dir.
Invokes external/toolchain-utils/llvm_tools/patch_manager.py to apply the
patches.
"""
patch_manager_cmd = [
utils.android_path('prebuilts', 'build-tools', utils.build_os_type(),
'bin', 'py3-cmd'),
utils.android_path('external', 'toolchain-utils', 'llvm_tools',
'patch_manager.py'),
# Python3 prebuilts in prebuilts/build-tools has an issue with argument
# parsing and ignores the first argument. Pass a dummy argument until
# the issue is fixed.
'blah',
'--svn_version', svn_version,
'--patch_metadata_file', patch_json,
'--filesdir_path', patch_dir,
'--src_path', source_dir,
'--use_src_head',
'--failure_mode', 'fail'
]
# py3-cmd in prebuilts/build-tools doesn't seem to add the current script's
# directory to sys.path. Explicitly pass the path in PYTHONPATH
env = dict(os.environ)
env['PYTHONPATH'] = utils.android_path('external', 'toolchain-utils',
'llvm_tools')
subprocess.check_call(patch_manager_cmd, env=env)
def setup_sources(source_dir, build_llvm_next):
"""Setup toolchain sources into source_dir.
Copy toolchain/llvm-project into source_dir.
Apply patches per the specification in
toolchain/llvm_android/patches/PATCHES.json. The function overwrites
source_dir only if necessary to avoid recompiles during incremental builds.
"""
copy_from = utils.android_path('toolchain', 'llvm-project')
# Copy llvm source tree to a temporary directory.
tmp_source_dir = source_dir.rstrip('/') + '.tmp'
if os.path.exists(tmp_source_dir):
utils.rm_tree(tmp_source_dir)
# mkdir parent of tmp_source_dir if necessary - so we can call 'cp' below.
tmp_source_parent = os.path.dirname(tmp_source_dir)
if not os.path.exists(tmp_source_parent):
os.makedirs(tmp_source_parent)
# Use 'cp' instead of shutil.copytree. The latter uses copystat and retains
# timestamps from the source. We instead use rsync below to only update
# changed files into source_dir. Using 'cp' will ensure all changed files
# get a newer timestamp than files in $source_dir.
# Note: Darwin builds don't copy symlinks with -r. Use -R instead.
subprocess.check_call(['cp', '-Rf', copy_from, tmp_source_dir])
# patch source tree
patch_dir = utils.android_path('toolchain', 'llvm_android', 'patches')
patch_json = os.path.join(patch_dir, 'PATCHES.json')
svn_version = android_version.get_svn_revision(build_llvm_next)
# strip the leading 'r' and letter suffix, e.g., r377782b => 377782
svn_version = svn_version[1:].rstrip(string.ascii_lowercase)
apply_patches(tmp_source_dir, svn_version, patch_json, patch_dir)
# Copy tmp_source_dir to source_dir if they are different. This avoids
# invalidating prior build outputs.
if not os.path.exists(source_dir):
os.rename(tmp_source_dir, source_dir)
else:
# Without a trailing '/' in $SRC, rsync copies $SRC to
# $DST/BASENAME($SRC) instead of $DST.
tmp_source_dir = tmp_source_dir.rstrip('/') + '/'
# rsync to update only changed files. Use '-c' to use checksums to find
# if files have changed instead of only modification time and size -
# which could have inconsistencies. Use '--delete' to ensure files not
# in tmp_source_dir are deleted from $source_dir.
subprocess.check_call(['rsync', '-r', '--delete', '--links', '-c',
tmp_source_dir, source_dir])
utils.rm_tree(tmp_source_dir)