Dear sirs,
I have been working on integrating Apache Tika (in Java) with our
open source intranet application (in Python/Django) using JCC, as
described here:
http://blog.aptivate.org/2012/02/01/content-indexing-in-django-using-apache-tika/
In order to make it easy to install Tika (which normally requires mystic
incantations of JCC) I have packaged it up with jar files and a setup.py
script. This required some changes to JCC. I hope you will consider these
for inclusion in your project. I don't believe that they break backwards
compatibility.
Changes implemented by the attached patch and visible online (formatted)
at <https://github.com/aptivate/jcc/commits/master>:
* Allow calling cpp.jcc with a --maxheap argument to reduce the heap size,
as the default doesn't fit in memory on a reasonably small virtual
machine.
* Allow calling cpp.jcc with --egg-info to generate the egg_info, without
doing a build.
* Allow calling cpp.jcc with --extra-setup-arg <arg> to pass additional
arguments to the setup() function call.
Changes that require more work:
* Can JCC please not fail completely if setuptools hasn't been patched?
Can it monkeypatch it instead, or at least fall back to non-shared mode?
* Why does JCC use non-standard command line arguments like --build and
--install? Can it be modified to make it easier to invoke from a
setup.py-style environment, such as exporting a setup() function as
setuptools does?
* Could JCC be used to generate dynamic proxies at runtime (with a
performance cost) in Python, to avoid the need for a compiler?
* Could JCC generate a source distribution (sdist) that could be uploaded
to pypi?
* "setup.py develop" is still broken in the current implementation
* JCC silently skips wrapping methods whose return type it doesn't know
(for example because I forgot to include a JAR file) which requires a lot
of debugging to track down and fix. This is doubly hard because it only
seems to work when installed, so I can't monkey patch it on the fly to
investigate problems, I have to remember to "setup.py install" each time.
Thanks in advance for your consideration.
Cheers, Chris.
--
Aptivate | http://www.aptivate.org | Phone: +44 1223 760887
The Humanitarian Centre, Fenner's, Gresham Road, Cambridge CB1 2ES
Aptivate is a not-for-profit company registered in England and Wales
with company number 04980791.
Index: jcc/python.py
===================================================================
--- jcc/python.py (revision 1238664)
+++ jcc/python.py (working copy)
@@ -1563,7 +1563,7 @@
def compile(env, jccPath, output, moduleName, install, dist, debug, jars,
version, prefix, root, install_dir, home_dir, use_distutils,
shared, compiler, modules, wininst, find_jvm_dll, arch, generics,
- resources, imports):
+ resources, imports, egg_info, extra_setup_args):
try:
if use_distutils:
@@ -1730,7 +1730,10 @@
if name.endswith('.cpp'):
sources.append(os.path.join(path, name))
- script_args = ['build_ext']
+ if egg_info:
+ script_args = ['egg_info']
+ else:
+ script_args = ['build_ext']
includes[0:0] = INCLUDES
compile_args = CFLAGS
@@ -1840,6 +1843,7 @@
config_vars['CFLAGS'] = ' '.join(cflags)
extensions = [Extension('.'.join([moduleName, extname]), **args)]
+ script_args.extend(extra_setup_args)
args = {
'name': moduleName,
@@ -1853,4 +1857,6 @@
if with_setuptools:
args['zip_safe'] = False
+ print "setup args = %s" % args
+
setup(**args)
Index: jcc/cpp.py
===================================================================
--- jcc/cpp.py (revision 1238664)
+++ jcc/cpp.py (working copy)
@@ -349,6 +349,7 @@
build = False
install = False
recompile = False
+ egg_info = False
output = 'build'
debug = False
excludes = []
@@ -372,7 +373,9 @@
arch = []
resources = []
imports = {}
-
+ extra_setup_args = []
+ initvm_args = {'maxstack': '512k'}
+
i = 1
while i < len(args):
arg = args[i]
@@ -398,6 +401,9 @@
elif arg == '--vmarg':
i += 1
vmargs.append(args[i])
+ elif arg == '--maxheap':
+ i += 1
+ initvm_args['maxheap'] = args[i]
elif arg == '--python':
from python import python, module
i += 1
@@ -414,6 +420,12 @@
elif arg == '--compile':
from python import compile
recompile = True
+ elif arg == '--egg-info':
+ from python import compile
+ egg_info = True
+ elif arg == '--extra-setup-arg':
+ i += 1
+ extra_setup_args.append(args[i])
elif arg == '--output':
i += 1
output = args[i]
@@ -492,9 +504,10 @@
if libpath:
vmargs.append('-Djava.library.path=' + os.pathsep.join(libpath))
- env = initVM(os.pathsep.join(classpath) or None,
- maxstack='512k', vmargs=' '.join(vmargs))
+ initvm_args['vmargs'] = ' '.join(vmargs)
+ env = initVM(os.pathsep.join(classpath) or None, **initvm_args)
+
typeset = set()
excludes = set(excludes)
@@ -504,7 +517,7 @@
else:
raise ValueError, "--shared must be used when using --import"
- if recompile or not build and (install or dist):
+ if recompile or not build and (install or dist or egg_info):
if moduleName is None:
raise ValueError, 'module name not specified (use --python)'
else:
@@ -512,7 +525,8 @@
install, dist, debug, jars, version,
prefix, root, install_dir, home_dir, use_distutils,
shared, compiler, modules, wininst, find_jvm_dll,
- arch, generics, resources, imports)
+ arch, generics, resources, imports, egg_info,
+ extra_setup_args)
else:
if imports:
def walk((include, importset), dirname, names):
@@ -647,12 +661,13 @@
module(out, allInOne, done, imports, cppdir, moduleName,
shared, generics)
out.close()
- if build or install or dist:
+ if build or install or dist or egg_info:
compile(env, os.path.dirname(args[0]), output, moduleName,
install, dist, debug, jars, version,
prefix, root, install_dir, home_dir, use_distutils,
shared, compiler, modules, wininst, find_jvm_dll,
- arch, generics, resources, imports)
+ arch, generics, resources, imports, egg_info,
+ extra_setup_args)
def header(env, out, cls, typeset, packages, excludes, generics, _dll_export):