blob: 5c321f509a0974eadab36130afa85e5a848f7158 [file] [log] [blame]
Tamir Duberstein9d9d0b72015-04-11 20:23:45 -07001#! /usr/bin/env python
temporal40ee5512008-07-10 02:12:20 +00002#
3# See README for usage instructions.
Tamir Duberstein5018c432015-05-08 08:48:40 -04004import glob
temporal40ee5512008-07-10 02:12:20 +00005import os
kenton@google.coma6de64a2009-04-18 02:28:15 +00006import subprocess
Tamir Duberstein5018c432015-05-08 08:48:40 -04007import sys
temporal40ee5512008-07-10 02:12:20 +00008
liujisi@google.com9ced30c2012-08-01 06:22:19 +00009# We must use setuptools, not distutils, because we need to use the
10# namespace_packages option for the "google" package.
11try:
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070012 from setuptools import setup, Extension, find_packages
liujisi@google.com9ced30c2012-08-01 06:22:19 +000013except ImportError:
jieluo@google.com7580a892014-08-12 21:28:31 +000014 try:
15 from ez_setup import use_setuptools
16 use_setuptools()
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070017 from setuptools import setup, Extension, find_packages
jieluo@google.com7580a892014-08-12 21:28:31 +000018 except ImportError:
19 sys.stderr.write(
20 "Could not import setuptools; make sure you have setuptools or "
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070021 "ez_setup installed.\n"
22 )
jieluo@google.com7580a892014-08-12 21:28:31 +000023 raise
liujisi@google.com9ced30c2012-08-01 06:22:19 +000024
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070025from distutils.command.clean import clean as _clean
26
27if sys.version_info[0] == 3:
28 # Python 3
29 from distutils.command.build_py import build_py_2to3 as _build_py
30else:
31 # Python 2
32 from distutils.command.build_py import build_py as _build_py
33from distutils.spawn import find_executable
temporal40ee5512008-07-10 02:12:20 +000034
35# Find the Protocol Compiler.
liujisi@google.come34f1f62012-12-05 01:25:12 +000036if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']):
37 protoc = os.environ['PROTOC']
38elif os.path.exists("../src/protoc"):
temporal40ee5512008-07-10 02:12:20 +000039 protoc = "../src/protoc"
kenton@google.com4152d552009-04-22 03:20:21 +000040elif os.path.exists("../src/protoc.exe"):
41 protoc = "../src/protoc.exe"
kenton@google.com80aa23d2010-09-28 21:58:36 +000042elif os.path.exists("../vsprojects/Debug/protoc.exe"):
43 protoc = "../vsprojects/Debug/protoc.exe"
44elif os.path.exists("../vsprojects/Release/protoc.exe"):
45 protoc = "../vsprojects/Release/protoc.exe"
temporal40ee5512008-07-10 02:12:20 +000046else:
47 protoc = find_executable("protoc")
48
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070049
Jisi Liu4573e112015-03-04 16:45:13 -080050def GetVersion():
51 """Gets the version from google/protobuf/__init__.py
52
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070053 Do not import google.protobuf.__init__ directly, because an installed
54 protobuf library may be loaded instead."""
Jisi Liu4573e112015-03-04 16:45:13 -080055
Jisi Liu4573e112015-03-04 16:45:13 -080056 with open(os.path.join('google', 'protobuf', '__init__.py')) as version_file:
Behzad Tabibian2bf92b32015-05-07 19:04:56 +020057 exec(version_file.read(), globals())
Jisi Liu4573e112015-03-04 16:45:13 -080058 return __version__
59
60
temporal40ee5512008-07-10 02:12:20 +000061def generate_proto(source):
62 """Invokes the Protocol Compiler to generate a _pb2.py from the given
63 .proto file. Does nothing if the output already exists and is newer than
64 the input."""
65
66 output = source.replace(".proto", "_pb2.py").replace("../src/", "")
67
temporal40ee5512008-07-10 02:12:20 +000068 if (not os.path.exists(output) or
69 (os.path.exists(source) and
70 os.path.getmtime(source) > os.path.getmtime(output))):
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070071 print("Generating %s..." % output)
temporal40ee5512008-07-10 02:12:20 +000072
liujisi@google.com9ced30c2012-08-01 06:22:19 +000073 if not os.path.exists(source):
74 sys.stderr.write("Can't find required file: %s\n" % source)
75 sys.exit(-1)
76
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070077 if protoc is None:
temporal40ee5512008-07-10 02:12:20 +000078 sys.stderr.write(
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070079 "protoc is not installed nor found in ../src. "
80 "Please compile it or install the binary package.\n"
81 )
temporal40ee5512008-07-10 02:12:20 +000082 sys.exit(-1)
83
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070084 protoc_command = [protoc, "-I../src", "-I.", "--python_out=.", source]
kenton@google.coma6de64a2009-04-18 02:28:15 +000085 if subprocess.call(protoc_command) != 0:
temporal40ee5512008-07-10 02:12:20 +000086 sys.exit(-1)
87
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070088
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000089def GenerateUnittestProtos():
Tamir Dubersteine4f4d9f2015-05-07 07:40:38 -040090 # Unittest protos are only needed for development.
91 if not os.path.exists("../.git"):
92 return
93
Bo Yang5db21732015-05-21 14:28:59 -070094 generate_proto("../src/google/protobuf/map_unittest.proto")
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000095 generate_proto("../src/google/protobuf/unittest.proto")
96 generate_proto("../src/google/protobuf/unittest_custom_options.proto")
97 generate_proto("../src/google/protobuf/unittest_import.proto")
98 generate_proto("../src/google/protobuf/unittest_import_public.proto")
99 generate_proto("../src/google/protobuf/unittest_mset.proto")
100 generate_proto("../src/google/protobuf/unittest_no_generic_services.proto")
Jisi Liuada65562015-02-25 16:39:11 -0800101 generate_proto("../src/google/protobuf/unittest_proto3_arena.proto")
jieluo@google.com4de8f552014-07-18 00:47:59 +0000102 generate_proto("google/protobuf/internal/descriptor_pool_test1.proto")
103 generate_proto("google/protobuf/internal/descriptor_pool_test2.proto")
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000104 generate_proto("google/protobuf/internal/factory_test1.proto")
105 generate_proto("google/protobuf/internal/factory_test2.proto")
Feng Xiao6ef984a2014-11-10 17:34:54 -0800106 generate_proto("google/protobuf/internal/import_test_package/inner.proto")
107 generate_proto("google/protobuf/internal/import_test_package/outer.proto")
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700108 generate_proto("google/protobuf/internal/missing_enum_values.proto")
109 generate_proto("google/protobuf/internal/more_extensions.proto")
110 generate_proto("google/protobuf/internal/more_extensions_dynamic.proto")
111 generate_proto("google/protobuf/internal/more_messages.proto")
112 generate_proto("google/protobuf/internal/test_bad_identifiers.proto")
jieluo@google.combde4a322014-08-12 21:10:30 +0000113 generate_proto("google/protobuf/pyext/python.proto")
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000114
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700115
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000116class clean(_clean):
117 def run(self):
118 # Delete generated files in the code tree.
temporal40ee5512008-07-10 02:12:20 +0000119 for (dirpath, dirnames, filenames) in os.walk("."):
120 for filename in filenames:
121 filepath = os.path.join(dirpath, filename)
liujisi@google.com33165fe2010-11-02 13:14:58 +0000122 if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700123 filepath.endswith(".so") or filepath.endswith(".o") or \
124 filepath.endswith('google/protobuf/compiler/__init__.py'):
temporal40ee5512008-07-10 02:12:20 +0000125 os.remove(filepath)
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000126 # _clean is an old-style class, so super() doesn't work.
127 _clean.run(self)
128
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700129
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000130class build_py(_build_py):
131 def run(self):
temporal40ee5512008-07-10 02:12:20 +0000132 # Generate necessary .proto file if it doesn't exist.
temporal40ee5512008-07-10 02:12:20 +0000133 generate_proto("../src/google/protobuf/descriptor.proto")
liujisi@google.com9b7f6c52010-12-08 03:45:27 +0000134 generate_proto("../src/google/protobuf/compiler/plugin.proto")
jieluo@google.combde4a322014-08-12 21:10:30 +0000135 GenerateUnittestProtos()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000136
jieluo@google.combde4a322014-08-12 21:10:30 +0000137 # Make sure google.protobuf/** are valid packages.
138 for path in ['', 'internal/', 'compiler/', 'pyext/']:
139 try:
140 open('google/protobuf/%s__init__.py' % path, 'a').close()
141 except EnvironmentError:
142 pass
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000143 # _build_py is an old-style class, so super() doesn't work.
144 _build_py.run(self)
jieluo@google.combde4a322014-08-12 21:10:30 +0000145 # TODO(mrovner): Subclass to run 2to3 on some files only.
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700146 # Tracing what https://wiki.python.org/moin/PortingPythonToPy3k's
147 # "Approach 2" section on how to get 2to3 to run on source files during
148 # install under Python 3. This class seems like a good place to put logic
149 # that calls python3's distutils.util.run_2to3 on the subset of the files we
150 # have in our release that are subject to conversion.
jieluo@google.combde4a322014-08-12 21:10:30 +0000151 # See code reference in previous code review.
152
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000153if __name__ == '__main__':
jieluo@google.com1eba9d92014-08-25 20:17:53 +0000154 ext_module_list = []
jieluo@google.coma21bf2e2014-08-25 23:26:40 +0000155 cpp_impl = '--cpp_implementation'
156 if cpp_impl in sys.argv:
jieluo@google.comb70e5862014-08-13 21:05:19 +0000157 sys.argv.remove(cpp_impl)
jieluo@google.com1eba9d92014-08-25 20:17:53 +0000158 # C++ implementation extension
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700159 ext_module_list.append(
160 Extension(
161 "google.protobuf.pyext._message",
Tamir Duberstein5018c432015-05-08 08:48:40 -0400162 glob.glob('google/protobuf/pyext/*.cc'),
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700163 define_macros=[('GOOGLE_PROTOBUF_HAS_ONEOF', '1')],
164 include_dirs=[".", "../src"],
165 libraries=['protobuf'],
166 library_dirs=['../src/.libs'],
167 )
168 )
Jisi Liuada65562015-02-25 16:39:11 -0800169 os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
liujisi@google.com33165fe2010-11-02 13:14:58 +0000170
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700171 setup(
172 name='protobuf',
173 version=GetVersion(),
174 description='Protocol Buffers',
175 long_description="Protocol Buffers are Google's data interchange format",
176 url='https://developers.google.com/protocol-buffers/',
177 maintainer='protobuf@googlegroups.com',
178 maintainer_email='protobuf@googlegroups.com',
179 license='New BSD License',
180 classifiers=[
181 'Programming Language :: Python :: 2.7',
182 ],
183 namespace_packages=['google'],
184 packages=find_packages(
185 exclude=[
186 'import_test_package',
187 ],
188 ),
189 test_suite='google.protobuf.internal',
190 cmdclass={
191 'clean': clean,
192 'build_py': build_py,
193 },
194 install_requires=['setuptools'],
195 ext_modules=ext_module_list,
196 )