forked from LeeKamentsky/python-javabridge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup.py
233 lines (205 loc) · 8.26 KB
/
setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
"""setup.py - build python-javabridge
python-javabridge is licensed under the BSD license. See the
accompanying file LICENSE for details.
Copyright (c) 2003-2009 Massachusetts Institute of Technology
Copyright (c) 2009-2013 Broad Institute
All rights reserved.
"""
import errno
import glob
import os
import re
import sys
import subprocess
import traceback
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext as _build_ext
from numpy import get_include
# Hack to avoid importing the javabridge package
sys.path.append(os.path.join(os.path.dirname(__file__), 'javabridge'))
from locate import *
def in_cwd(basename):
return os.path.join(os.path.dirname(__file__), basename)
def build_cython():
"""Compile the pyx files if we have them.
The git repository has the .pyx files but not the .c files, and
the source distributions that are uploaded to PyPI have the .c
files and not the .pyx files. (The reason for the latter is that
some versions of pip discovers the .pyx files and implicitly adds
a dependency on Cython.) Therefore, if we have the .pyx files,
compile them.
"""
stems = ['_javabridge', '_javabridge_mac', '_javabridge_nomac']
pyx_filenames = [in_cwd(s + '.pyx') for s in stems]
if any(map(os.path.exists, pyx_filenames)):
cmd = ['cython'] + pyx_filenames
print ' '.join(cmd)
subprocess.check_call(cmd)
def ext_modules():
extensions = []
extra_link_args = None
java_home = find_javahome()
if java_home is None:
raise JVMNotFoundError()
jdk_home = find_jdk()
print "Using jdk_home =", jdk_home
include_dirs = [get_include()]
libraries = None
library_dirs = None
javabridge_sources = ['_javabridge.c']
if is_mac:
javabridge_sources += ['_javabridge_mac.c']
else:
javabridge_sources += ['_javabridge_nomac.c']
if is_win:
if jdk_home is not None:
jdk_include = os.path.join(jdk_home, "include")
jdk_include_plat = os.path.join(jdk_include, sys.platform)
include_dirs += [jdk_include, jdk_include_plat]
if is_mingw:
#
# Build libjvm from jvm.dll on Windows.
# This assumes that we're using mingw32 for build
#
cmd = ["dlltool", "--dllname",
os.path.join(jdk_home,"jre\\bin\\client\\jvm.dll"),
"--output-lib","libjvm.a",
"--input-def","jvm.def",
"--kill-at"]
p = subprocess.Popen(cmd)
p.communicate()
library_dirs = [os.path.abspath(".")]
else:
#
# Use the MSVC lib in the JDK
#
extra_link_args = ['/MANIFEST']
jdk_lib = os.path.join(jdk_home, "lib")
library_dirs = [jdk_lib]
javabridge_sources.append("strtoull.c")
libraries = ["jvm"]
elif is_mac:
javabridge_sources += [ "mac_javabridge_utils.c" ]
include_dirs += ['/System/Library/Frameworks/JavaVM.framework/Headers']
extra_link_args = ['-framework', 'JavaVM']
elif is_linux:
include_dirs += [os.path.join(java_home,'include'),
os.path.join(java_home,'include','linux')]
library_dirs = [os.path.join(java_home,'jre','lib', arch, cs)
for arch in ['amd64', 'i386']
for cs in ['client', 'server']]
libraries = ["jvm"]
extension_kwargs = dict(
name="javabridge._javabridge",
sources=javabridge_sources,
libraries=libraries,
library_dirs=library_dirs,
include_dirs=include_dirs,
extra_link_args=extra_link_args)
if not is_win:
extension_kwargs["runtime_library_dirs"] =library_dirs
extensions += [Extension(**extension_kwargs)]
return extensions
def needs_compilation(target, *sources):
try:
target_date = os.path.getmtime(target)
except OSError, e:
if e.errno != errno.ENOENT:
raise
return True
for source in sources:
source_date = os.path.getmtime(source)
if source_date > target_date:
return True
return False
def package_path(relpath):
return os.path.normpath(os.path.join(os.path.dirname(__file__), relpath))
def build_jar_from_single_source(jar, source):
if needs_compilation(jar, source):
javac_loc = find_javac_cmd()
javac_command = [javac_loc, package_path(source)]
print ' '.join(javac_command)
subprocess.check_call(javac_command)
if not os.path.exists(os.path.dirname(jar)):
os.mkdir(os.path.dirname(jar))
jar_command = [find_jar_cmd(), 'cf', package_path(jar)]
for klass in glob.glob(source[:source.rindex('.')] + '*.class'):
jar_command.extend(['-C', package_path('java'), klass[klass.index('/') + 1:]])
print ' '.join(jar_command)
subprocess.check_call(jar_command)
def build_runnablequeue():
jar = 'javabridge/jars/runnablequeue.jar'
source = 'java/org/cellprofiler/runnablequeue/RunnableQueue.java'
build_jar_from_single_source(jar, source)
def build_test():
jar = 'javabridge/jars/test.jar'
source = 'java/org/cellprofiler/javabridge/test/RealRect.java'
build_jar_from_single_source(jar, source)
def build_java():
print "running build_java"
build_runnablequeue()
build_test()
class build_ext(_build_ext):
def run(self, *args, **kwargs):
build_java()
build_cython()
return _build_ext.run(self, *args, **kwargs)
def get_version():
"""Get version from git or file system.
If this is a git repository, try to get the version number by
running ``git describe``, then store it in
javabridge/_version.py. Otherwise, try to load the version number
from that file. If both methods fail, quietly return None.
"""
git_version = None
if os.path.exists(os.path.join(os.path.dirname(__file__), '.git')):
import subprocess
try:
git_version = subprocess.Popen(['git', 'describe'],
stdout=subprocess.PIPE).communicate()[0].strip()
except:
pass
version_file = os.path.join(os.path.dirname(__file__), 'javabridge',
'_version.py')
if os.path.exists(version_file):
with open(version_file) as f:
cached_version_line = f.read().strip()
try:
# From http://stackoverflow.com/a/3619714/17498
cached_version = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
cached_version_line, re.M).group(1)
except:
raise RuntimeError("Unable to find version in %s" % version_file)
else:
cached_version = None
if git_version and git_version != cached_version:
with open(version_file, 'w') as f:
print >>f, '__version__ = "%s"' % git_version
return git_version or cached_version
if __name__ == '__main__':
if '/' in __file__:
os.chdir(os.path.dirname(__file__))
setup(name="javabridge",
version=get_version(),
description="Python wrapper for the Java Native Interface",
long_description='''The python-javabridge package makes it easy to start a Java virtual
machine (JVM) from Python and interact with it. Python code can
interact with the JVM using a low-level API or a more convenient
high-level API. Python-javabridge was developed for and is used by the
cell image analysis software CellProfiler (cellprofiler.org).''',
url="http://github.com/CellProfiler/python-javabridge/",
packages=['javabridge'],
classifiers=['Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: BSD License',
'Programming Language :: Java',
],
license='BSD License',
install_requires=['numpy'],
tests_require="nose",
entry_points={'nose.plugins.0.10': [
'javabridge = javabridge.noseplugin:JavabridgePlugin'
]},
test_suite="nose.collector",
package_data={"javabridge": ['jars/*.jar', 'VERSION']},
ext_modules=ext_modules(),
cmdclass={'build_ext': build_ext,})