blob: 94642bae8e63d8dae28e9adc667c05ca60a3281c [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright (C) 2016 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.
#
"""NDK packaging APIs."""
from __future__ import absolute_import
import os
import shutil
import subprocess
import tempfile
from typing import Iterable, List, Optional, Set, Tuple
import ndk.abis
from ndk.hosts import Host, host_to_tag
PACKAGE_VARIANTS = (
'abi',
'arch',
'host',
'toolchain',
'triple',
)
def expand_path(package: str, host: Host) -> str:
"""Expands package definition tuple into a package name.
>>> expand_path('llvm-{host}', Host.Linux)
'llvm-linux-x86_64'
>>> expand_path('platforms', Host.Linux)
'platforms'
"""
host_tag = host_to_tag(host)
return package.format(host=host_tag)
def package_varies_by(install_path: str, variant: str) -> bool:
"""Determines if a package varies by a given input.
>>> package_varies_by('foo-{host}', 'host')
True
>>> package_varies_by('foo', 'host')
False
>>> package_varies_by('foo-{arch}', 'host')
False
"""
if variant not in PACKAGE_VARIANTS:
raise ValueError
variant_replacement_str = '{' + variant + '}'
return variant_replacement_str in install_path
def expand_package(package: str, install_path: str,
host: Host) -> Tuple[str, str]:
"""Returns a tuple of `(package, install_path)`."""
package_template = package
for variant in PACKAGE_VARIANTS:
if package_varies_by(install_path, variant):
package_template += '-{' + variant + '}'
expanded_packages = expand_path(package_template, host)
expanded_installs = expand_path(install_path, host)
return expanded_packages, expanded_installs
def extract_zip(package_path: str, install_path: str) -> None:
"""Extracts the contents of a zipfile to a directory.
This behaves similar to the following shell commands (using tar instead of
zip because `unzip` doesn't support `--strip-components`):
mkdir -p $install_path
tar xf $package_path -C $install_path --strip-components=1
That is, the first directory in the package is stripped and the contents
are placed in the install path.
Args:
package_path: Path to the zip file to extract.
install_path: Directory in which to extract zip contents.
Raises:
RuntimeError: The zip file was not in the allowed format. i.e. the zip
had more than one top level directory or was empty.
"""
package_name = os.path.basename(package_path)
extract_dir = tempfile.mkdtemp()
try:
subprocess.check_call(
['unzip', '-q', package_path, '-d', extract_dir])
dirs = os.listdir(extract_dir)
if len(dirs) > 1:
msg = 'Package has more than one root directory: ' + package_name
raise RuntimeError(msg)
if not dirs:
raise RuntimeError('Package was empty: ' + package_name)
parent_dir = os.path.dirname(install_path)
if not os.path.exists(parent_dir):
os.makedirs(parent_dir)
shutil.move(os.path.join(extract_dir, dirs[0]), install_path)
finally:
shutil.rmtree(extract_dir)