blob: 59d3fb8b9ce07fce7b67e52898402f29f4e035c2 [file] [log] [blame]
#
# Copyright (c) 2020 Project CHIP Authors
# Copyright (c) 2019 Google LLC.
# All rights reserved.
#
# 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.
#
#
# Description:
# Builds a Python wheel package for CHIP.
#
from __future__ import absolute_import
from datetime import datetime
from setuptools import setup
from wheel.bdist_wheel import bdist_wheel
import argparse
import json
import os
import platform
import shutil
parser = argparse.ArgumentParser(
description='build the pip package for chip using chip components generated during the build and python source code')
parser.add_argument('--package_name', default='chip',
help='configure the python package name')
parser.add_argument('--build_number', default='0.0',
help='configure the chip build number')
parser.add_argument('--build_dir', help='directory to build in')
parser.add_argument('--dist_dir', help='directory to place distribution in')
parser.add_argument('--manifest', help='list of files to package')
parser.add_argument(
'--plat-name', help='platform name to embed in generated filenames')
parser.add_argument(
'--server', help='build the server variant', default=False, type=bool)
args = parser.parse_args()
class InstalledScriptInfo:
"""Information holder about a script that is to be installed."""
def __init__(self, name):
self.name = name
self.installName = os.path.splitext(name)[0]
if args.server:
chipDLLName = "_ChipServer.so"
else:
chipDLLName = "_ChipDeviceCtrl.so"
packageName = args.package_name
chipPackageVer = args.build_number
if args.server:
installScripts = []
else:
installScripts = [
InstalledScriptInfo("chip-device-ctrl.py"),
InstalledScriptInfo("chip-repl.py"),
]
# Record the current directory at the start of execution.
curDir = os.curdir
manifestFile = os.path.abspath(args.manifest)
buildDir = os.path.abspath(args.build_dir)
distDir = os.path.abspath(args.dist_dir)
# Use a temporary directory within the build directory to assemble the components
# for the installable package.
tmpDir = os.path.join(buildDir, "chip-wheel-components")
manifest = json.load(open(manifestFile, "r"))
try:
#
# Perform a series of setup steps prior to creating the chip package...
#
# Create the temporary components directory.
if os.path.isdir(tmpDir):
shutil.rmtree(tmpDir)
os.makedirs(tmpDir, exist_ok=True)
# Switch to the temporary directory. (Foolishly, setuptools relies on the current directory
# for many of its features.)
os.chdir(tmpDir)
manifestBase = os.path.dirname(manifestFile)
for entry in manifest['files']:
srcDir = os.path.join(manifestBase, entry['src_dir'])
for path in entry['sources']:
srcFile = os.path.join(srcDir, path)
dstFile = os.path.join(tmpDir, path)
os.makedirs(os.path.dirname(dstFile), exist_ok=True)
shutil.copyfile(srcFile, dstFile)
for script in installScripts:
os.rename(os.path.join(tmpDir, script.name),
os.path.join(tmpDir, script.installName))
# Define a custom version of the bdist_wheel command that configures the
# resultant wheel as platform-specific (i.e. not "pure").
class bdist_wheel_override(bdist_wheel):
def finalize_options(self):
bdist_wheel.finalize_options(self)
self.root_is_pure = False
requiredPackages = [
"coloredlogs",
'construct',
#
# IPython 7.30.0 has a bug which results in the use of await ... failing on some platforms (see https://github.com/ipython/ipython/pull/13269)
# For now, let's just avoid that version.
#
'ipython!=7.30.0',
'dacite',
'rich',
'stringcase',
'pyyaml',
'ipdb'
]
if platform.system() == "Darwin":
requiredPackages.append("pyobjc-framework-corebluetooth")
if platform.system() == "Linux":
requiredPackages.append("dbus-python")
requiredPackages.append("pygobject")
#
# Build the chip package...
#
packages = [
'chip',
'chip.ble',
'chip.ble.commissioning',
'chip.configuration',
'chip.clusters',
'chip.discovery',
'chip.exceptions',
'chip.internal',
'chip.interaction_model',
'chip.logging',
'chip.native',
'chip.clusters',
'chip.tlv',
'chip.setup_payload',
]
#print ("Server: {}".format(args.server))
if args.server:
packages.append('chip.server')
#print("packages: {}".format(packages))
print("packageName: {}".format(packageName))
print("chipDLLName: {}".format(chipDLLName))
# Invoke the setuptools 'bdist_wheel' command to generate a wheel containing
# the CHIP python packages, shared libraries and scripts.
setup(
name=packageName,
version=chipPackageVer,
description="Python-base APIs and tools for CHIP.",
url="https://github.com/project-chip/connectedhomeip",
license="Apache",
classifiers=[
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
],
python_requires=">=2.7",
packages=packages,
package_dir={
# By default, look in the tmp directory for packages/modules to be included.
'': tmpDir,
},
package_data={
packageName: [
# Include the wrapper DLL as package data in the "chip" package.
chipDLLName
]
},
scripts=[name for name in map(
lambda script: os.path.join(tmpDir, script.installName),
installScripts
)],
install_requires=requiredPackages,
options={
'bdist_wheel': {
'universal': False,
# Place the generated .whl in the dist directory.
'dist_dir': distDir,
'py_limited_api': 'cp37',
'plat_name': args.plat_name,
},
'egg_info': {
# Place the .egg-info subdirectory in the tmp directory.
'egg_base': tmpDir
}
},
cmdclass={
'bdist_wheel': bdist_wheel_override
},
script_args=['clean', '--all', 'bdist_wheel']
)
finally:
# Switch back to the initial current directory.
os.chdir(curDir)
# Remove the temporary directory.
if os.path.isdir(tmpDir):
shutil.rmtree(tmpDir)