229 lines
7.3 KiB
Python
229 lines
7.3 KiB
Python
# Copyright 2018 The TensorFlow Authors. 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.
|
|
# ==============================================================================
|
|
"""TensorFlow Lite is for mobile and embedded devices.
|
|
|
|
TensorFlow Lite is the official solution for running machine learning models on
|
|
mobile and embedded devices. It enables on-device machine learning inference
|
|
with low latency and a small binary size on Android, iOS, and other operating
|
|
systems.
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
|
|
import glob
|
|
import multiprocessing
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import sysconfig
|
|
|
|
from distutils.command.build_ext import build_ext
|
|
import numpy
|
|
import pybind11
|
|
|
|
from setuptools import Extension
|
|
from setuptools import find_packages
|
|
from setuptools import setup
|
|
from setuptools.command.build_py import build_py
|
|
PACKAGE_NAME = 'tflite_runtime'
|
|
PACKAGE_VERSION = os.environ['PACKAGE_VERSION']
|
|
DOCLINES = __doc__.split('\n')
|
|
TENSORFLOW_DIR = os.environ['TENSORFLOW_DIR']
|
|
RELATIVE_MAKE_DIR = os.path.join('tensorflow', 'lite', 'tools', 'make')
|
|
MAKE_DIR = os.path.join(TENSORFLOW_DIR, RELATIVE_MAKE_DIR)
|
|
DOWNLOADS_DIR = os.path.join(MAKE_DIR, 'downloads')
|
|
RELATIVE_MAKEFILE_PATH = os.path.join(RELATIVE_MAKE_DIR, 'Makefile')
|
|
DOWNLOAD_SCRIPT_PATH = os.path.join(MAKE_DIR, 'download_dependencies.sh')
|
|
|
|
# Setup cross compiling
|
|
TARGET = os.environ.get('TENSORFLOW_TARGET')
|
|
if TARGET == 'rpi':
|
|
os.environ['CXX'] = 'arm-linux-gnueabihf-g++'
|
|
os.environ['CC'] = 'arm-linux-gnueabihf-gcc'
|
|
elif TARGET == 'aarch64':
|
|
os.environ['CXX'] = 'aarch64-linux-gnu-g++'
|
|
os.environ['CC'] = 'aarch64-linux-gnu-gcc'
|
|
|
|
MAKE_CROSS_OPTIONS = []
|
|
for name in [
|
|
'TARGET', 'TARGET_ARCH', 'CC_PREFIX', 'EXTRA_CXXFLAGS', 'EXTRA_CFLAGS'
|
|
]:
|
|
value = os.environ.get('TENSORFLOW_%s' % name)
|
|
if value:
|
|
MAKE_CROSS_OPTIONS.append('%s=%s' % (name, value))
|
|
|
|
|
|
# Check physical memory and if we are on a reasonable non small SOC machine
|
|
# with more than 4GB, use all the CPUs, otherwise only 1.
|
|
def get_build_cpus():
|
|
physical_bytes = os.sysconf('SC_PAGESIZE') * os.sysconf('SC_PHYS_PAGES')
|
|
if physical_bytes < (1 << 30) * 4:
|
|
return 1
|
|
else:
|
|
return multiprocessing.cpu_count()
|
|
|
|
|
|
def make_args(target='', quiet=True):
|
|
"""Construct make command line."""
|
|
args = ([
|
|
'make', 'SHELL=/bin/bash', 'BUILD_WITH_NNAPI=false', '-C', TENSORFLOW_DIR
|
|
] + MAKE_CROSS_OPTIONS +
|
|
['-f', RELATIVE_MAKEFILE_PATH, '-j',
|
|
str(get_build_cpus())])
|
|
if quiet:
|
|
args.append('--quiet')
|
|
if target:
|
|
args.append(target)
|
|
return args
|
|
|
|
|
|
def make_output(target):
|
|
"""Invoke make on the target and return output."""
|
|
return subprocess.check_output(make_args(target)).decode('utf-8').strip()
|
|
|
|
|
|
def make():
|
|
"""Invoke make to build tflite C++ sources.
|
|
|
|
Build dependencies:
|
|
apt-get install swig libjpeg-dev zlib1g-dev python3-dev python3-nump
|
|
"""
|
|
subprocess.check_call(make_args(quiet=False))
|
|
|
|
|
|
def download_dependencies():
|
|
"""Download build dependencies if haven't done yet."""
|
|
if not os.path.isdir(DOWNLOADS_DIR) or not os.listdir(DOWNLOADS_DIR):
|
|
subprocess.check_call(DOWNLOAD_SCRIPT_PATH)
|
|
|
|
|
|
class CustomBuildExt(build_ext, object):
|
|
"""Customized build extension."""
|
|
|
|
def get_ext_filename(self, ext_name):
|
|
if TARGET:
|
|
ext_path = ext_name.split('.')
|
|
return os.path.join(*ext_path) + '.so'
|
|
return super(CustomBuildExt, self).get_ext_filename(ext_name)
|
|
|
|
def run(self):
|
|
download_dependencies()
|
|
make()
|
|
|
|
return super(CustomBuildExt, self).run()
|
|
|
|
|
|
class CustomBuildPy(build_py, object):
|
|
|
|
def run(self):
|
|
self.run_command('build_ext')
|
|
return super(CustomBuildPy, self).run()
|
|
|
|
|
|
def get_pybind_include():
|
|
"""pybind11 include directory is not correctly resolved.
|
|
|
|
This fixes include directory to /usr/local/pythonX.X
|
|
|
|
Returns:
|
|
include directories to find pybind11
|
|
"""
|
|
if sys.version_info[0] == 3:
|
|
include_dirs = glob.glob('/usr/local/include/python3*')
|
|
else:
|
|
include_dirs = glob.glob('/usr/local/include/python2*')
|
|
include_dirs.append(sysconfig.get_path('include'))
|
|
tmp_include_dirs = []
|
|
pip_dir = os.path.join(TENSORFLOW_DIR, 'tensorflow', 'lite', 'tools',
|
|
'pip_package', 'gen')
|
|
for include_dir in include_dirs:
|
|
tmp_include_dir = os.path.join(pip_dir, include_dir[1:])
|
|
tmp_include_dirs.append(tmp_include_dir)
|
|
try:
|
|
os.makedirs(tmp_include_dir)
|
|
os.symlink(include_dir, os.path.join(tmp_include_dir, 'include'))
|
|
except IOError: # file already exists.
|
|
pass
|
|
return tmp_include_dirs
|
|
|
|
|
|
LIB_TFLITE = 'tensorflow-lite'
|
|
LIB_TFLITE_DIR = make_output('libdir')
|
|
|
|
ext = Extension(
|
|
name='%s._pywrap_tensorflow_interpreter_wrapper' % PACKAGE_NAME,
|
|
language='c++',
|
|
sources=[
|
|
'interpreter_wrapper/interpreter_wrapper.cc',
|
|
'interpreter_wrapper/interpreter_wrapper_pybind11.cc',
|
|
'interpreter_wrapper/numpy.cc',
|
|
'interpreter_wrapper/python_error_reporter.cc',
|
|
'interpreter_wrapper/python_utils.cc'
|
|
],
|
|
extra_compile_args=['--std=c++11'],
|
|
include_dirs=[
|
|
TENSORFLOW_DIR,
|
|
os.path.join(TENSORFLOW_DIR, 'tensorflow', 'lite', 'tools',
|
|
'pip_package'),
|
|
numpy.get_include(),
|
|
os.path.join(DOWNLOADS_DIR, 'flatbuffers', 'include'),
|
|
os.path.join(DOWNLOADS_DIR, 'absl'),
|
|
pybind11.get_include()
|
|
],
|
|
libraries=[LIB_TFLITE],
|
|
library_dirs=[LIB_TFLITE_DIR])
|
|
|
|
setup(
|
|
name=PACKAGE_NAME.replace('_', '-'),
|
|
version=PACKAGE_VERSION,
|
|
description=DOCLINES[0],
|
|
long_description='\n'.join(DOCLINES[2:]),
|
|
url='https://www.tensorflow.org/lite/',
|
|
author='Google, LLC',
|
|
author_email='packages@tensorflow.org',
|
|
license='Apache 2.0',
|
|
include_package_data=True,
|
|
keywords='tflite tensorflow tensor machine learning',
|
|
classifiers=[
|
|
'Development Status :: 5 - Production/Stable',
|
|
'Intended Audience :: Developers',
|
|
'Intended Audience :: Education',
|
|
'Intended Audience :: Science/Research',
|
|
'License :: OSI Approved :: Apache Software License',
|
|
'Programming Language :: Python :: 3',
|
|
'Programming Language :: Python :: 3.4',
|
|
'Programming Language :: Python :: 3.5',
|
|
'Programming Language :: Python :: 3.6',
|
|
'Programming Language :: Python :: 3.7',
|
|
'Topic :: Scientific/Engineering',
|
|
'Topic :: Scientific/Engineering :: Mathematics',
|
|
'Topic :: Scientific/Engineering :: Artificial Intelligence',
|
|
'Topic :: Software Development',
|
|
'Topic :: Software Development :: Libraries',
|
|
'Topic :: Software Development :: Libraries :: Python Modules',
|
|
],
|
|
packages=find_packages(exclude=[]),
|
|
ext_modules=[ext],
|
|
install_requires=[
|
|
'numpy >= 1.16.0',
|
|
'pybind11 >= 2.4.3',
|
|
],
|
|
cmdclass={
|
|
'build_ext': CustomBuildExt,
|
|
'build_py': CustomBuildPy,
|
|
})
|