sentencepiece
201 строка · 6.1 Кб
1#!/usr/bin/env python
2
3# Copyright 2018 Google Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.!
16
17import codecs
18import os
19import string
20import subprocess
21import sys
22from setuptools import Extension, setup
23from setuptools.command.build_ext import build_ext as _build_ext
24from setuptools.command.build_py import build_py as _build_py
25
26sys.path.append(os.path.join('.', 'test'))
27
28
29def long_description():
30with codecs.open('README.md', 'r', 'utf-8') as f:
31long_description = f.read()
32return long_description
33
34
35exec(open('src/sentencepiece/_version.py').read())
36
37
38def run_pkg_config(section, pkg_config_path=None):
39try:
40cmd = 'pkg-config sentencepiece --{}'.format(section)
41if pkg_config_path:
42cmd = 'env PKG_CONFIG_PATH={} {}'.format(pkg_config_path, cmd)
43output = subprocess.check_output(cmd, shell=True)
44if sys.version_info >= (3, 0, 0):
45output = output.decode('utf-8')
46except subprocess.CalledProcessError:
47sys.stderr.write('Failed to find sentencepiece pkg-config\n')
48sys.exit(1)
49return output.strip().split()
50
51
52def is_sentencepiece_installed():
53try:
54subprocess.check_call('pkg-config sentencepiece --libs', shell=True)
55return True
56except subprocess.CalledProcessError:
57return False
58
59
60def get_cflags_and_libs(root):
61cflags = ['-std=c++17', '-I' + os.path.join(root, 'include')]
62libs = []
63if os.path.exists(os.path.join(root, 'lib/pkgconfig/sentencepiece.pc')):
64libs = [
65os.path.join(root, 'lib/libsentencepiece.a'),
66os.path.join(root, 'lib/libsentencepiece_train.a'),
67]
68elif os.path.exists(os.path.join(root, 'lib64/pkgconfig/sentencepiece.pc')):
69libs = [
70os.path.join(root, 'lib64/libsentencepiece.a'),
71os.path.join(root, 'lib64/libsentencepiece_train.a'),
72]
73return cflags, libs
74
75
76class build_ext(_build_ext):
77"""Override build_extension to run cmake."""
78
79def build_extension(self, ext):
80cflags, libs = get_cflags_and_libs('../build/root')
81
82if len(libs) == 0:
83if is_sentencepiece_installed():
84cflags = cflags + run_pkg_config('cflags')
85libs = run_pkg_config('libs')
86else:
87subprocess.check_call(['./build_bundled.sh', __version__])
88cflags, libs = get_cflags_and_libs('./build/root')
89
90# Fix compile on some versions of Mac OSX
91# See: https://github.com/neulab/xnmt/issues/199
92if sys.platform == 'darwin':
93cflags.append('-mmacosx-version-min=10.9')
94else:
95cflags.append('-Wl,-strip-all')
96libs.append('-Wl,-strip-all')
97if sys.platform == 'linux':
98libs.append('-Wl,-Bsymbolic')
99print('## cflags={}'.format(' '.join(cflags)))
100print('## libs={}'.format(' '.join(libs)))
101ext.extra_compile_args = cflags
102ext.extra_link_args = libs
103_build_ext.build_extension(self, ext)
104
105
106if os.name == 'nt':
107# Must pre-install sentencepice into build directory.
108arch = 'win32'
109if sys.maxsize > 2**32:
110arch = 'amd64'
111if os.path.exists('..\\build\\root_{}\\lib'.format(arch)):
112cflags = ['/std:c++17', '/I..\\build\\root_{}\\include'.format(arch)]
113libs = [
114'..\\build\\root_{}\\lib\\sentencepiece.lib'.format(arch),
115'..\\build\\root_{}\\lib\\sentencepiece_train.lib'.format(arch),
116]
117elif os.path.exists('..\\build\\root\\lib'):
118cflags = ['/std:c++17', '/I..\\build\\root\\include']
119libs = [
120'..\\build\\root\\lib\\sentencepiece.lib',
121'..\\build\\root\\lib\\sentencepiece_train.lib',
122]
123else:
124# build library locally with cmake and vc++.
125cmake_arch = 'Win32'
126if arch == 'amd64':
127cmake_arch = 'x64'
128subprocess.check_call([
129'cmake',
130'sentencepiece',
131'-A',
132cmake_arch,
133'-B',
134'build',
135'-DSPM_ENABLE_SHARED=OFF',
136'-DCMAKE_INSTALL_PREFIX=build\\root',
137])
138subprocess.check_call([
139'cmake',
140'--build',
141'build',
142'--config',
143'Release',
144'--target',
145'install',
146'--parallel',
147'8',
148])
149cflags = ['/std:c++17', '/I.\\build\\root\\include']
150libs = [
151'.\\build\\root\\lib\\sentencepiece.lib',
152'.\\build\\root\\lib\\sentencepiece_train.lib',
153]
154
155SENTENCEPIECE_EXT = Extension(
156'sentencepiece._sentencepiece',
157sources=['src/sentencepiece/sentencepiece_wrap.cxx'],
158extra_compile_args=cflags,
159extra_link_args=libs,
160)
161cmdclass = {}
162else:
163SENTENCEPIECE_EXT = Extension(
164'sentencepiece._sentencepiece',
165sources=['src/sentencepiece/sentencepiece_wrap.cxx'],
166)
167cmdclass = {'build_ext': build_ext}
168
169setup(
170name='sentencepiece',
171author='Taku Kudo',
172author_email='taku@google.com',
173description='SentencePiece python wrapper',
174long_description=long_description(),
175long_description_content_type='text/markdown',
176version=__version__,
177package_dir={'': 'src'},
178url='https://github.com/google/sentencepiece',
179license='Apache',
180platforms='Unix',
181py_modules=[
182'sentencepiece/__init__',
183'sentencepiece/_version',
184'sentencepiece/sentencepiece_model_pb2',
185'sentencepiece/sentencepiece_pb2',
186],
187ext_modules=[SENTENCEPIECE_EXT],
188cmdclass=cmdclass,
189classifiers=[
190'Development Status :: 5 - Production/Stable',
191'Environment :: Console',
192'Intended Audience :: Developers',
193'Intended Audience :: Science/Research',
194'License :: OSI Approved :: Apache Software License',
195'Operating System :: Unix',
196'Programming Language :: Python',
197'Topic :: Text Processing :: Linguistic',
198'Topic :: Software Development :: Libraries :: Python Modules',
199],
200test_suite='sentencepiece_test.suite',
201)
202