blob: 6ea3bad736565cf000ca73dc9c7eea9c75b790c4 [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001#! /usr/bin/env python
2#
3# See README for usage instructions.
4import glob
5import os
6import subprocess
7import sys
8
9# We must use setuptools, not distutils, because we need to use the
10# namespace_packages option for the "google" package.
11from setuptools import setup, Extension, find_packages
12
13from distutils.command.clean import clean as _clean
14
15if sys.version_info[0] == 3:
16 # Python 3
17 from distutils.command.build_py import build_py_2to3 as _build_py
18else:
19 # Python 2
20 from distutils.command.build_py import build_py as _build_py
21from distutils.spawn import find_executable
22
23# Find the Protocol Compiler.
24if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']):
25 protoc = os.environ['PROTOC']
26elif os.path.exists("../src/protoc"):
27 protoc = "../src/protoc"
28elif os.path.exists("../src/protoc.exe"):
29 protoc = "../src/protoc.exe"
30elif os.path.exists("../vsprojects/Debug/protoc.exe"):
31 protoc = "../vsprojects/Debug/protoc.exe"
32elif os.path.exists("../vsprojects/Release/protoc.exe"):
33 protoc = "../vsprojects/Release/protoc.exe"
34else:
35 protoc = find_executable("protoc")
36
37
38def GetVersion():
39 """Gets the version from google/protobuf/__init__.py
40
41 Do not import google.protobuf.__init__ directly, because an installed
42 protobuf library may be loaded instead."""
43
44 with open(os.path.join('google', 'protobuf', '__init__.py')) as version_file:
45 exec(version_file.read(), globals())
46 return __version__
47
48
49def generate_proto(source, require = True):
50 """Invokes the Protocol Compiler to generate a _pb2.py from the given
51 .proto file. Does nothing if the output already exists and is newer than
52 the input."""
53
54 if not require and not os.path.exists(source):
55 return
56
57 output = source.replace(".proto", "_pb2.py").replace("../src/", "")
58
59 if (not os.path.exists(output) or
60 (os.path.exists(source) and
61 os.path.getmtime(source) > os.path.getmtime(output))):
62 print("Generating %s..." % output)
63
64 if not os.path.exists(source):
65 sys.stderr.write("Can't find required file: %s\n" % source)
66 sys.exit(-1)
67
68 if protoc is None:
69 sys.stderr.write(
70 "protoc is not installed nor found in ../src. Please compile it "
71 "or install the binary package.\n")
72 sys.exit(-1)
73
74 protoc_command = [ protoc, "-I../src", "-I.", "--python_out=.", source ]
75 if subprocess.call(protoc_command) != 0:
76 sys.exit(-1)
77
78def GenerateUnittestProtos():
79 generate_proto("../src/google/protobuf/map_unittest.proto", False)
80 generate_proto("../src/google/protobuf/unittest_arena.proto", False)
81 generate_proto("../src/google/protobuf/unittest_no_arena.proto", False)
82 generate_proto("../src/google/protobuf/unittest_no_arena_import.proto", False)
83 generate_proto("../src/google/protobuf/unittest.proto", False)
84 generate_proto("../src/google/protobuf/unittest_custom_options.proto", False)
85 generate_proto("../src/google/protobuf/unittest_import.proto", False)
86 generate_proto("../src/google/protobuf/unittest_import_public.proto", False)
87 generate_proto("../src/google/protobuf/unittest_mset.proto", False)
88 generate_proto("../src/google/protobuf/unittest_mset_wire_format.proto", False)
89 generate_proto("../src/google/protobuf/unittest_no_generic_services.proto", False)
90 generate_proto("../src/google/protobuf/unittest_proto3_arena.proto", False)
91 generate_proto("../src/google/protobuf/util/json_format_proto3.proto", False)
92 generate_proto("google/protobuf/internal/any_test.proto", False)
93 generate_proto("google/protobuf/internal/descriptor_pool_test1.proto", False)
94 generate_proto("google/protobuf/internal/descriptor_pool_test2.proto", False)
95 generate_proto("google/protobuf/internal/factory_test1.proto", False)
96 generate_proto("google/protobuf/internal/factory_test2.proto", False)
97 generate_proto("google/protobuf/internal/import_test_package/inner.proto", False)
98 generate_proto("google/protobuf/internal/import_test_package/outer.proto", False)
99 generate_proto("google/protobuf/internal/missing_enum_values.proto", False)
100 generate_proto("google/protobuf/internal/message_set_extensions.proto", False)
101 generate_proto("google/protobuf/internal/more_extensions.proto", False)
102 generate_proto("google/protobuf/internal/more_extensions_dynamic.proto", False)
103 generate_proto("google/protobuf/internal/more_messages.proto", False)
104 generate_proto("google/protobuf/internal/packed_field_test.proto", False)
105 generate_proto("google/protobuf/internal/test_bad_identifiers.proto", False)
106 generate_proto("google/protobuf/pyext/python.proto", False)
107
108
109class clean(_clean):
110 def run(self):
111 # Delete generated files in the code tree.
112 for (dirpath, dirnames, filenames) in os.walk("."):
113 for filename in filenames:
114 filepath = os.path.join(dirpath, filename)
115 if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \
116 filepath.endswith(".so") or filepath.endswith(".o") or \
117 filepath.endswith('google/protobuf/compiler/__init__.py') or \
118 filepath.endswith('google/protobuf/util/__init__.py'):
119 os.remove(filepath)
120 # _clean is an old-style class, so super() doesn't work.
121 _clean.run(self)
122
123class build_py(_build_py):
124 def run(self):
125 # Generate necessary .proto file if it doesn't exist.
126 generate_proto("../src/google/protobuf/descriptor.proto")
127 generate_proto("../src/google/protobuf/compiler/plugin.proto")
128 generate_proto("../src/google/protobuf/any.proto")
129 generate_proto("../src/google/protobuf/api.proto")
130 generate_proto("../src/google/protobuf/duration.proto")
131 generate_proto("../src/google/protobuf/empty.proto")
132 generate_proto("../src/google/protobuf/field_mask.proto")
133 generate_proto("../src/google/protobuf/source_context.proto")
134 generate_proto("../src/google/protobuf/struct.proto")
135 generate_proto("../src/google/protobuf/timestamp.proto")
136 generate_proto("../src/google/protobuf/type.proto")
137 generate_proto("../src/google/protobuf/wrappers.proto")
138 GenerateUnittestProtos()
139
140 # Make sure google.protobuf/** are valid packages.
141 for path in ['', 'internal/', 'compiler/', 'pyext/', 'util/']:
142 try:
143 open('google/protobuf/%s__init__.py' % path, 'a').close()
144 except EnvironmentError:
145 pass
146 # _build_py is an old-style class, so super() doesn't work.
147 _build_py.run(self)
148
149class test_conformance(_build_py):
150 target = 'test_python'
151 def run(self):
152 if sys.version_info >= (2, 7):
153 # Python 2.6 dodges these extra failures.
154 os.environ["CONFORMANCE_PYTHON_EXTRA_FAILURES"] = (
155 "--failure_list failure_list_python-post26.txt")
156 cmd = 'cd ../conformance && make %s' % (test_conformance.target)
157 status = subprocess.check_call(cmd, shell=True)
158
159
160if __name__ == '__main__':
161 ext_module_list = []
162 cpp_impl = '--cpp_implementation'
163 warnings_as_errors = '--warnings_as_errors'
164 if cpp_impl in sys.argv:
165 sys.argv.remove(cpp_impl)
166 extra_compile_args = ['-Wno-write-strings', '-Wno-invalid-offsetof']
167 test_conformance.target = 'test_python_cpp'
168
169 if "clang" in os.popen('$CC --version 2> /dev/null').read():
170 extra_compile_args.append('-Wno-shorten-64-to-32')
171
172 if warnings_as_errors in sys.argv:
173 extra_compile_args.append('-Werror')
174 sys.argv.remove(warnings_as_errors)
175
176 # C++ implementation extension
177 ext_module_list.append(
178 Extension(
179 "google.protobuf.pyext._message",
180 glob.glob('google/protobuf/pyext/*.cc'),
181 include_dirs=[".", "../src"],
182 libraries=['protobuf'],
183 library_dirs=['../src/.libs'],
184 extra_compile_args=extra_compile_args,
185 )
186 )
187 os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
188
189 # Keep this list of dependencies in sync with tox.ini.
190 install_requires = ['six>=1.9', 'setuptools']
191 if sys.version_info <= (2,7):
192 install_requires.append('ordereddict')
193 install_requires.append('unittest2')
194
195 setup(
196 name='protobuf',
197 version=GetVersion(),
198 description='Protocol Buffers',
199 long_description="Protocol Buffers are Google's data interchange format",
200 url='https://developers.google.com/protocol-buffers/',
201 maintainer='protobuf@googlegroups.com',
202 maintainer_email='protobuf@googlegroups.com',
203 license='New BSD License',
204 classifiers=[
205 "Programming Language :: Python",
206 "Programming Language :: Python :: 2",
207 "Programming Language :: Python :: 2.6",
208 "Programming Language :: Python :: 2.7",
209 "Programming Language :: Python :: 3",
210 "Programming Language :: Python :: 3.3",
211 "Programming Language :: Python :: 3.4",
212 ],
213 namespace_packages=['google'],
214 packages=find_packages(
215 exclude=[
216 'import_test_package',
217 ],
218 ),
219 test_suite='google.protobuf.internal',
220 cmdclass={
221 'clean': clean,
222 'build_py': build_py,
223 'test_conformance': test_conformance,
224 },
225 install_requires=install_requires,
226 ext_modules=ext_module_list,
227 )