Skip to content

Commit 5847293

Browse files
aselletensorflower-gardener
authored andcommitted
Create a simple PIP package generator for standalone TF Lite.
Based on original dkovalev@ PiperOrigin-RevId: 221543483
1 parent 6f99a81 commit 5847293

File tree

5 files changed

+241
-0
lines changed

5 files changed

+241
-0
lines changed

tensorflow/lite/tools/make/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ $(BENCHMARK_BINARY) : $(BENCHMARK_LIB)
208208

209209
benchmark: $(BENCHMARK_BINARY)
210210

211+
libdir:
212+
@echo $(LIBDIR)
213+
211214
# Gets rid of all generated files.
212215
clean:
213216
rm -rf $(MAKEFILE_DIR)/gen
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
recursive-include * *.py
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Building TensorFlow Lite Standalone Pip
2+
3+
Many users would like to deploy TensorFlow lite interpreter and use it from
4+
Python without requiring the rest of TensorFlow.
5+
6+
## Steps
7+
8+
To build a binary wheel run this script:
9+
```
10+
sudo apt install swig libjpeg-dev zlib1g-dev python3-dev python3-numpy
11+
sh tensorflow/lite/tools/pip_package/build_pip_package.sh
12+
```
13+
That will print out some output and a .whl file. You can then install that
14+
```
15+
pip install --upgrade <wheel>
16+
```
17+
18+
Note, unlike tensorflow this will be installed to a tflite_runtime namespace.
19+
You can then use the Tensorflow Lite interpreter as.
20+
```
21+
import tflite_runtime as tflr
22+
interpreter = tflr.lite.Interpreter(model_path="foo.tflite")
23+
```
24+
25+
This currently works to build on Linux machines including Raspberry Pi. In
26+
the future, cross compilation to smaller SOCs like Raspberry Pi from
27+
bigger host will be supported.
28+
29+
## Caveats
30+
31+
* You cannot use TensorFlow Select ops, only TensorFlow Lite builtins.
32+
* Currently custom ops and delegates cannot be registered.
33+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env bash
2+
# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
# ==============================================================================
16+
17+
set -e
18+
19+
# Find where this script lives and then the Tensorflow root.
20+
MY_DIRECTORY=`dirname $0`
21+
export TENSORFLOW_SRC_ROOT=`realpath $MY_DIRECTORY/../../../..`
22+
23+
export TENSORFLOW_VERSION=`grep "_VERSION = " $TENSORFLOW_SRC_ROOT/tensorflow/tools/pip_package/setup.py | cut -d'=' -f 2 | sed "s/[ '-]//g"`;
24+
25+
26+
# Build a pip build tree.
27+
BUILD_ROOT=/tmp/tflite_pip
28+
rm -rf $BUILD_ROOT
29+
mkdir -p $BUILD_ROOT/tflite_runtime/lite
30+
mkdir -p $BUILD_ROOT/tflite_runtime/lite/python
31+
32+
# Build an importable module tree
33+
cat > $BUILD_ROOT/tflite_runtime/__init__.py <<EOF;
34+
import tflite_runtime.lite.interpreter
35+
EOF
36+
37+
cat > $BUILD_ROOT/tflite_runtime/lite/__init__.py <<EOF;
38+
from interpreter import Interpreter as Interpreter
39+
EOF
40+
41+
cat > $BUILD_ROOT/tflite_runtime/lite/python/__init__.py <<EOF;
42+
# Python module for TensorFlow Lite
43+
EOF
44+
45+
# Copy necessary source files
46+
TFLITE_ROOT=$TENSORFLOW_SRC_ROOT/tensorflow/lite
47+
cp -r $TFLITE_ROOT/python/interpreter_wrapper $BUILD_ROOT
48+
cp $TFLITE_ROOT/python/interpreter.py $BUILD_ROOT/tflite_runtime/lite/
49+
cp $TFLITE_ROOT/tools/pip_package/setup.py $BUILD_ROOT
50+
cp $TFLITE_ROOT/tools/pip_package/MANIFEST.in $BUILD_ROOT
51+
52+
# Build the Pip
53+
cd $BUILD_ROOT
54+
python setup.py bdist_wheel
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ==============================================================================
15+
"""TensorFlow Lite is for mobile and embedded devices.
16+
17+
TensorFlow Lite is the official solution for running machine learning models on
18+
mobile and embedded devices. It enables on-device machine learning inference
19+
with low latency and a small binary size on Android, iOS, and other operating
20+
systems.
21+
"""
22+
23+
from __future__ import absolute_import
24+
from __future__ import division
25+
from __future__ import print_function
26+
27+
import multiprocessing
28+
import os
29+
import subprocess
30+
31+
from distutils.command.build_ext import build_ext
32+
import numpy
33+
34+
from setuptools import Extension
35+
from setuptools import find_packages
36+
from setuptools import setup
37+
from setuptools.command.build_py import build_py
38+
PACKAGE_NAME = 'tflite-runtime'
39+
PACKAGE_VERSION = os.environ['TENSORFLOW_VERSION']
40+
DOCLINES = __doc__.split('\n')
41+
PACKAGE = 'tflite_runtime.lite.python'
42+
TENSORFLOW_DIR = os.environ['TENSORFLOW_SRC_ROOT']
43+
44+
# Setup cross compiling
45+
TARGET = (
46+
os.environ['TENSORFLOW_TARGET'] if 'TENSORFLOW_TARGET' in os.environ
47+
else None)
48+
if TARGET == 'rpi':
49+
os.environ['CXX'] = 'arm-linux-gnueabihf-g++'
50+
os.environ['CC'] = 'arm-linux-gnueabihf-g++'
51+
MAKE_CROSS_OPTIONS = ['TARGET=%s' % TARGET] if TARGET else []
52+
53+
RELATIVE_MAKE_DIR = os.path.join('tensorflow', 'lite', 'tools', 'make')
54+
MAKE_DIR = os.path.join(TENSORFLOW_DIR, RELATIVE_MAKE_DIR)
55+
DOWNLOADS_DIR = os.path.join(MAKE_DIR, 'downloads')
56+
RELATIVE_MAKEFILE_PATH = os.path.join(RELATIVE_MAKE_DIR, 'Makefile')
57+
DOWNLOAD_SCRIPT_PATH = os.path.join(MAKE_DIR, 'download_dependencies.sh')
58+
59+
60+
def make_args(target='', quiet=True):
61+
"""Construct make command line."""
62+
args = (['make', 'SHELL=/bin/bash', '-C', TENSORFLOW_DIR]
63+
+ MAKE_CROSS_OPTIONS +
64+
['-f', RELATIVE_MAKEFILE_PATH, '-j',
65+
str(multiprocessing.cpu_count())])
66+
if quiet:
67+
args.append('--quiet')
68+
if target:
69+
args.append(target)
70+
return args
71+
72+
73+
def make_output(target):
74+
"""Invoke make on the target and return output."""
75+
return subprocess.check_output(make_args(target)).decode('utf-8').strip()
76+
77+
78+
def make():
79+
"""Invoke make to build tflite C++ sources.
80+
81+
Build dependencies:
82+
apt-get install swig libjpeg-dev zlib1g-dev python3-dev python3-nump
83+
"""
84+
subprocess.check_call(make_args(quiet=False))
85+
86+
87+
def download_dependencies():
88+
"""Download build dependencies if haven't done yet."""
89+
if not os.path.isdir(DOWNLOADS_DIR) or not os.listdir(DOWNLOADS_DIR):
90+
subprocess.check_call(DOWNLOAD_SCRIPT_PATH)
91+
92+
93+
class CustomBuildExt(build_ext, object):
94+
95+
def run(self):
96+
download_dependencies()
97+
make()
98+
99+
return super(CustomBuildExt, self).run()
100+
101+
102+
class CustomBuildPy(build_py, object):
103+
104+
def run(self):
105+
self.run_command('build_ext')
106+
return super(CustomBuildPy, self).run()
107+
108+
109+
LIB_TFLITE = 'tensorflow-lite'
110+
LIB_TFLITE_DIR = make_output('libdir')
111+
112+
ext = Extension(
113+
name='%s._interpreter_wrapper' % PACKAGE,
114+
language='c++',
115+
sources=['interpreter_wrapper/interpreter_wrapper.i',
116+
'interpreter_wrapper/interpreter_wrapper.cc'],
117+
swig_opts=['-c++',
118+
'-I%s' % TENSORFLOW_DIR,
119+
'-module', 'interpreter_wrapper',
120+
'-outdir', '.'],
121+
extra_compile_args=['-std=c++11'],
122+
include_dirs=[TENSORFLOW_DIR,
123+
os.path.join(TENSORFLOW_DIR, 'tensorflow', 'lite', 'tools',
124+
'pip_package'),
125+
numpy.get_include(),
126+
os.path.join(DOWNLOADS_DIR, 'flatbuffers', 'include'),
127+
os.path.join(DOWNLOADS_DIR, 'absl')],
128+
libraries=[LIB_TFLITE],
129+
library_dirs=[LIB_TFLITE_DIR])
130+
131+
132+
setup(
133+
name=PACKAGE_NAME,
134+
version=PACKAGE_VERSION,
135+
description=DOCLINES[0],
136+
long_description='\n'.join(DOCLINES[2:]),
137+
url='https://www.tensorflow.org/lite/',
138+
author='Google Inc.',
139+
author_email='[email protected]',
140+
license='Apache 2.0',
141+
include_package_data=True,
142+
keywords='tflite tensorflow tensor machine learning',
143+
packages=find_packages(exclude=[]),
144+
ext_modules=[ext],
145+
package_dir={PACKAGE: '.'},
146+
cmdclass={
147+
'build_ext': CustomBuildExt,
148+
'build_py': CustomBuildPy,
149+
}
150+
)

0 commit comments

Comments
 (0)