Apply Upstream code (2021-03-15)
[platform/upstream/connectedhomeip.git] / src / controller / python / build-chip-wheel.py
1 #
2 #    Copyright (c) 2020 Project CHIP Authors
3 #    Copyright (c) 2019 Google LLC.
4 #    All rights reserved.
5 #
6 #    Licensed under the Apache License, Version 2.0 (the "License");
7 #    you may not use this file except in compliance with the License.
8 #    You may obtain a copy of the License at
9 #
10 #        http://www.apache.org/licenses/LICENSE-2.0
11 #
12 #    Unless required by applicable law or agreed to in writing, software
13 #    distributed under the License is distributed on an "AS IS" BASIS,
14 #    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 #    See the License for the specific language governing permissions and
16 #    limitations under the License.
17 #
18
19 #
20 #    Description:
21 #      Builds a Python wheel package for CHIP.
22 #
23
24 from __future__ import absolute_import
25 from datetime import datetime
26 from setuptools import setup
27 from wheel.bdist_wheel import bdist_wheel
28
29 import argparse
30 import json
31 import os
32 import platform
33 import shutil
34
35
36 parser = argparse.ArgumentParser(description='build the pip package for chip using chip components generated during the build and python source code')
37 parser.add_argument('--package_name', default='chip', help='configure the python package name')
38 parser.add_argument('--build_number', default='0.0', help='configure the chip build number')
39 parser.add_argument('--build_dir', help='directory to build in')
40 parser.add_argument('--dist_dir', help='directory to place distribution in')
41 parser.add_argument('--manifest', help='list of files to package')
42 parser.add_argument('--plat-name', help='platform name to embed in generated filenames')
43
44 args = parser.parse_args()
45
46 class InstalledScriptInfo:
47     """Information holder about a script that is to be installed."""
48
49     def __init__(self, name):
50       self.name = name
51       self.installName = os.path.splitext(name)[0]
52
53
54 chipDLLName = '_ChipDeviceCtrl.so'
55 packageName = args.package_name
56 chipPackageVer = args.build_number
57
58 installScripts = [
59     InstalledScriptInfo('chip-device-ctrl.py'),
60     InstalledScriptInfo('chip-repl.py'),
61 ]
62
63 # Record the current directory at the start of execution.
64 curDir = os.curdir
65
66 manifestFile = os.path.abspath(args.manifest)
67 buildDir = os.path.abspath(args.build_dir)
68 distDir = os.path.abspath(args.dist_dir)
69
70 # Use a temporary directory within the build directory to assemble the components
71 # for the installable package.
72 tmpDir = os.path.join(buildDir, 'chip-wheel-components')
73
74 manifest = json.load(open(manifestFile, 'r'))
75
76 try:
77
78     #
79     # Perform a series of setup steps prior to creating the chip package...
80     #
81
82     # Create the temporary components directory.
83     if os.path.isdir(tmpDir):
84         shutil.rmtree(tmpDir)
85     os.makedirs(tmpDir, exist_ok=True)
86
87     # Switch to the temporary directory. (Foolishly, setuptools relies on the current directory
88     # for many of its features.)
89     os.chdir(tmpDir)
90
91     manifestBase = os.path.dirname(manifestFile)
92     for entry in manifest['files']:
93         srcDir = os.path.join(manifestBase, entry['src_dir'])
94         for path in entry['sources']:
95           srcFile = os.path.join(srcDir, path)
96           dstFile = os.path.join(tmpDir, path)
97           os.makedirs(os.path.dirname(dstFile), exist_ok=True)
98           shutil.copyfile(srcFile, dstFile)
99
100     for script in installScripts:
101       os.rename(os.path.join(tmpDir, script.name),
102                 os.path.join(tmpDir, script.installName))
103
104     # Define a custom version of the bdist_wheel command that configures the
105     # resultant wheel as platform-specific (i.e. not "pure").
106     class bdist_wheel_override(bdist_wheel):
107         def finalize_options(self):
108             bdist_wheel.finalize_options(self)
109             self.root_is_pure = False
110
111     requiredPackages = [
112         "coloredlogs",
113         'construct',
114         'ipython',
115     ]
116
117     if platform.system() == 'Darwin':
118         requiredPackages.append('pyobjc-framework-corebluetooth')
119
120     if platform.system() == 'Linux':
121         requiredPackages.append('dbus-python')
122         requiredPackages.append('pygobject')
123
124     #
125     # Build the chip package...
126     #
127     packages=[
128             'chip',
129             'chip.ble',
130             'chip.ble.commissioning',
131             'chip.configuration',
132             'chip.exceptions',
133             'chip.internal',
134             'chip.logging',
135             'chip.native',
136             'chip.tlv',
137     ]
138
139     # Invoke the setuptools 'bdist_wheel' command to generate a wheel containing
140     # the CHIP python packages, shared libraries and scripts.
141     setup(
142         name=packageName,
143         version=chipPackageVer,
144         description='Python-base APIs and tools for CHIP.',
145         url='https://github.com/project-chip/connectedhomeip',
146         license='Apache',
147         classifiers=[
148             'Intended Audience :: Developers',
149             'License :: OSI Approved :: Apache Software License',
150             'Programming Language :: Python :: 2',
151             'Programming Language :: Python :: 2.7',
152             'Programming Language :: Python :: 3',
153         ],
154         python_requires='>=2.7',
155         packages=packages,
156         package_dir={
157             '':tmpDir,                      # By default, look in the tmp directory for packages/modules to be included.
158         },
159         package_data={
160             packageName:[
161                 chipDLLName                   # Include the wrapper DLL as package data in the "chip" package.
162             ]
163         },
164         scripts = [name for name in map(
165             lambda script: os.path.join(tmpDir, script.installName),
166             installScripts
167         )],
168         install_requires=requiredPackages,
169         options={
170             'bdist_wheel':{
171                 'universal':False,
172                 'dist_dir':distDir,         # Place the generated .whl in the dist directory.
173                 'py_limited_api':'cp37',
174                 'plat_name':args.plat_name,
175             },
176             'egg_info':{
177                 'egg_base':tmpDir           # Place the .egg-info subdirectory in the tmp directory.
178             }
179         },
180         cmdclass={
181             'bdist_wheel':bdist_wheel_override
182         },
183         script_args=[ 'clean', '--all', 'bdist_wheel' ]
184     )
185
186 finally:
187     
188     # Switch back to the initial current directory.
189     os.chdir(curDir)
190
191     # Remove the temporary directory.
192     if os.path.isdir(tmpDir):
193         shutil.rmtree(tmpDir)