I'd love to get some feedback on this (incomplete, hence no log) patch that
integrates javahl into the main Subversion build system.
It compiles and does the javac, javah, and C++ steps. It doesn't do
installation yet, nor have I managed to test that it produces 'correct' code.
Once it's completed, I'd probably need some Python gurus to review the changes
to the generator (hey, I know more about that code now!). I'm thinking that
once I get it working (by this weekend?), I should just commit it to trunk and
we can fix it up in-tree as I don't think it'll break anything that is already
there...
Thoughts? -- justin
Index: Makefile.in
===================================================================
--- Makefile.in (revision 8069)
+++ Makefile.in (working copy)
@@ -77,6 +77,7 @@
CC = @CC@
+CXX = @CXX@
EXEEXT = @EXEEXT@
SHELL = @SHELL@
@@ -117,6 +118,7 @@
LDFLAGS = @LDFLAGS@ $(EXTRA_LDFLAGS)
COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDES)
+COMPILE_CXX = $(CXX) $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) $(INCLUDES)
LT_COMPILE = $(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE)
# special compilation for files destined for mod_dav_svn
@@ -127,6 +129,11 @@
COMPILE_SWIG_JAVA = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CPPFLAGS)
$(CFLAGS) $(SWIG_JAVA_INCLUDES) $(INCLUDES) -o $@ -c
COMPILE_SWIG_PL = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CPPFLAGS)
$(CFLAGS) $(SWIG_PL_INCLUDES) $(INCLUDES) -o $@ -c
+# special compilation for files destined for javahl (i.e. C++)
+COMPILE_JAVAHL_CXX = $(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE_CXX)
$(SWIG_JAVA_INCLUDES) -o $@ -c
+COMPILE_JAVAHL_JAVAC = $(JAVAC)
+COMPILE_JAVAHL_JAVAH = $(JAVAH)
+
LINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS)
$(LDFLAGS) -rpath $(libdir)
# special link rule for mod_dav_svn
@@ -148,6 +155,7 @@
LINK_JAVA_WRAPPER = $(LIBTOOL) $(LTFLAGS) --mode=link $(SWIG_JAVA_LINK)
$(SWIG_LDFLAGS) -rpath $(swig_javadir) -avoid-version -module
LINK_PL_WRAPPER = $(LIBTOOL) $(LTFLAGS) --mode=link $(SWIG_PL_LINK)
$(SWIG_LDFLAGS) -rpath $(swig_pldir) -avoid-version -module
+LINK_JAVAHL_CXX = $(LIBTOOL) $(LTFLAGS) --mode=link $(CXX) $(LT_LDFLAGS)
$(CFLAGS) $(LDFLAGS) -rpath $(libdir)
INSTALL = @INSTALL@
INSTALL_LIB = $(LIBTOOL) --mode=install $(INSTALL)
@@ -206,6 +214,7 @@
JDK = @JDK@
JAVAC = @JAVAC@
+JAVAH = @JAVAH@
JAR = @JAR@
ECHO_C = @ECHO_C@
Index: build.conf
===================================================================
--- build.conf (revision 8069)
+++ build.conf (working copy)
@@ -338,6 +338,41 @@
# ----------------------------------------------------------------------------
#
+# JavaHL targets
+#
+[javahl-java]
+type = java
+path = subversion/bindings/java/javahl/src/org/tigris/subversion/javahl
+sources = *.java
+install = javahl-java
+link-cmd = $(COMPILE_JAVAHL_JAVAC)
+classes = subversion/bindings/java/javahl/classes
+
+[javahl-javah]
+type = javah
+path = subversion/bindings/java/javahl/src/org/tigris/subversion/javahl
+classes = subversion/bindings/java/javahl/classes
+headers = subversion/bindings/java/javahl/include
+package = org.tigris.subversion.javahl
+extra-classes = Notify\$$Action Notify\$$Status Revision\$$DateSpec
Revision\$$Kind Revision\$$Number SVNClient\$$LogLevel Status\$$Kind
+sources = *.java
+install = javahl-javah
+link-cmd = $(COMPILE_JAVAHL_JAVAH)
+
+[libjavahl]
+type = lib
+path = subversion/bindings/java/javahl/native
+#libs = javahl-javah aprutil apriconv apr
+libs = libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_subr
+ aprutil apriconv apr neon
+sources = *.cpp *.c
+install = javahl-cxx
+# need special build rule to include -I$(JDK)/include/jni.h
+compile-cmd = $(COMPILE_JAVAHL_CXX)
+link-cmd = $(LINK_JAVAHL_CXX)
+
+# ----------------------------------------------------------------------------
+#
# TESTING TARGETS
#
Index: configure.in
===================================================================
--- configure.in (revision 8069)
+++ configure.in (working copy)
@@ -509,6 +509,20 @@
AC_SUBST(SVN_RA_LIB_LINK)
+dnl Possibly compile JavaHL (experimental)
+do_javahl_build=no
+AC_ARG_ENABLE(javahl,
+ AC_HELP_STRING([--enable-javahl],
+ [Enable compilation of Java high-level bindings (requires C++)]),
+ [ if test "$enableval" = "yes" ; then
+ do_javahl_build="yes"
+ fi
+ ])
+
+if test "$do_javahl_build" = "yes"; then
+ AC_PROG_CXX
+fi
+
dnl Pass some config data ----------------------------
AC_SUBST(abs_builddir)
Index: build/ac-macros/java.m4
===================================================================
--- build/ac-macros/java.m4 (revision 8069)
+++ build/ac-macros/java.m4 (working copy)
@@ -50,12 +50,30 @@
fi
AC_MSG_RESULT([$JDK_SUITABLE])
- JAVAC='$(JDK)/bin/javac'
+ JAVA_BIN='$(JDK)/bin'
+ if test -f "$JDK/include/jni.h"; then
+ JNI_INCLUDES="$JDK/include"
+ fi
+
+ dnl Correct for Darwin's odd JVM layout. Ideally, we should use realpath,
+ dnl but Darwin doesn't have that utility. /usr/bin/java is a symlink into
+ dnl /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Commands
+ os_arch=`uname`
+ if test "$JDK_SUITABLE" = "yes" -a "$JDK" = "/usr" -a "$os_arch" = "Darwin"
-a -d "/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK"; then
+ JDK="/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK"
+ JAVA_BIN='$(JDK)/Commands'
+ JNI_INCLUDES="$JDK/Headers"
+ fi
+
+ JAVAC="$JAVA_BIN/javac"
# TODO: Test for Jikes, which should be preferred (for speed) if available
- JAR='$(JDK)/bin/jar'
+ JAVAH="$JAVA_BIN/javah"
+ JAR="$JAVA_BIN/jar"
dnl We use JDK in both the swig.m4 macros and the Makefile
AC_SUBST(JDK)
AC_SUBST(JAVAC)
+ AC_SUBST(JAVAH)
AC_SUBST(JAR)
+ AC_SUBST(JNI_INCLUDES)
])
Index: build/ac-macros/swig.m4
===================================================================
--- build/ac-macros/swig.m4 (revision 8069)
+++ build/ac-macros/swig.m4 (working copy)
@@ -100,8 +100,8 @@
fi
if test "$JDK" != "none" -a "$SWIG_SUITABLE" = "yes"; then
- SWIG_JAVA_INCLUDES='-I$(JDK)/include'
- list="`find "$JDK/include" -type d -print`"
+ SWIG_JAVA_INCLUDES="-I$JNI_INCLUDES"
+ list="`find "$JNI_INCLUDES" -type d -print`"
for dir in $list; do
SWIG_JAVA_INCLUDES="$SWIG_JAVA_INCLUDES -I$dir"
done
Index: build/generator/gen_base.py
===================================================================
--- build/generator/gen_base.py (revision 8069)
+++ build/generator/gen_base.py (working copy)
@@ -132,6 +132,11 @@
self.graph.add(DT_SWIG_C, sources[0], include_deps[short][0])
continue
+ if isinstance(sources[0], ObjectFile) or \
+ isinstance(sources[0], HeaderFile):
+ if sources[0].source_generated == 1:
+ continue
+
hdrs = [ ]
for short in _find_includes(sources[0].filename, include_deps):
self.graph.add(DT_OBJECT, objname, include_deps[short][0])
@@ -249,6 +254,7 @@
def __init__(self, filename, compile_cmd = None):
DependencyNode.__init__(self, filename)
self.compile_cmd = compile_cmd
+ self.source_generated = 0
class SWIGObject(ObjectFile):
def __init__(self, filename, lang):
@@ -259,6 +265,12 @@
self.compile_cmd = '$(COMPILE_%s_WRAPPER)' %
string.upper(self.lang_abbrev)
self.source_generated = 1
+class HeaderFile(DependencyNode):
+ def __init__(self, filename, classname = None, compile_cmd = None):
+ DependencyNode.__init__(self, filename)
+ self.classname = classname
+ self.compile_cmd = compile_cmd
+
class SourceFile(DependencyNode):
def __init__(self, filename, reldir):
DependencyNode.__init__(self, filename)
@@ -337,10 +349,8 @@
self.install = options.get('install')
self.compile_cmd = options.get('compile-cmd')
self.sources = options.get('sources', '*.c')
+ self.link_cmd = options.get('link-cmd', '$(LINK)')
- ### hmm. this is Makefile-specific
- self.link_cmd = '$(LINK)'
-
self.external_lib = options.get('external-lib')
self.external_project = options.get('external-project')
self.msvc_libs = string.split(options.get('msvc-libs', ''))
@@ -358,11 +368,13 @@
sources.sort()
for src, reldir in sources:
- if src[-2:] != '.c':
+ if src[-2:] == '.c':
+ objname = src[:-2] + self.objext
+ elif src[-4:] == '.cpp':
+ objname = src[:-4] + self.objext
+ else:
raise GenError('ERROR: unknown file extension on ' + src)
- objname = src[:-2] + self.objext
-
ofile = ObjectFile(objname, self.compile_cmd)
# object depends upon source
@@ -568,6 +580,131 @@
TargetProject.__init__(self, name, options, cfg, extmap)
self.lang = options.get('lang')
+class TargetJava(TargetLib):
+ def __init__(self, name, options, cfg, extmap):
+ TargetLib.__init__(self, name, options, cfg, extmap)
+ self.link_cmd = options.get('link-cmd')
+ self.deps = [ ]
+ self.filename = ''
+
+class TargetJavaHeaders(TargetJava):
+ def __init__(self, name, options, cfg, extmap):
+ TargetJava.__init__(self, name, options, cfg, extmap)
+ self.objext = '.class'
+ self.javah_objext = '.h'
+ self.headers = options.get('headers')
+ self.classes = options.get('classes')
+ self.package = options.get('package')
+ self.extra_classes = string.split(options.get('extra-classes'))
+ self.output_dir = self.headers
+
+ def add_dependencies(self, graph, cfg, extmap):
+ sources = _collect_paths(self.sources, self.path)
+
+ for src, reldir in sources:
+ if src[-5:] != '.java':
+ raise GenError('ERROR: unknown file extension on ' + src)
+
+ class_path = os.path.split(src[:-5])
+
+ class_header = os.path.join(self.headers, class_path[1] + '.h')
+ class_pkg_list = string.split(self.package, '.')
+ class_pkg = ''
+ for dir in class_pkg_list:
+ class_pkg = os.path.join(class_pkg, dir)
+ class_file = ObjectFile(os.path.join(self.classes, class_pkg,
+ class_path[1] + self.objext))
+ class_file.source_generated = 1
+ hfile = HeaderFile(class_header, self.package + '.' + class_path[1],
+ self.compile_cmd)
+ hfile.source_generated = 1
+ graph.add(DT_OBJECT, hfile, class_file)
+ self.deps.append(hfile)
+
+ # target (a linked item) depends upon object
+ graph.add(DT_LINK, self.name, hfile)
+
+ for extra in self.extra_classes:
+ hfile = HeaderFile('', self.package + '.' + extra)
+ hfile.source_generated = 1
+ self.deps.append(hfile)
+
+ # collect all the paths where stuff might get built
+ ### we should collect this from the dependency nodes rather than
+ ### the sources. "what dir are you going to put yourself into?"
+ graph.add(DT_LIST, LT_TARGET_DIRS, self.path)
+ graph.add(DT_LIST, LT_TARGET_DIRS, self.classes)
+ graph.add(DT_LIST, LT_TARGET_DIRS, self.headers)
+ for pattern in string.split(self.sources):
+ idx = string.rfind(pattern, '/')
+ if idx != -1:
+ ### hmm. probably shouldn't be os.path.join() right here
+ ### (at this point in the control flow; defer to output)
+ graph.add(DT_LIST, LT_TARGET_DIRS, os.path.join(self.path,
+ pattern[:idx]))
+
+ graph.add(DT_INSTALL, self.name, self)
+
+
+ def get_dep_targets(self, target):
+ return [ self.target ]
+
+class TargetJavaClasses(TargetJava):
+ def __init__(self, name, options, cfg, extmap):
+ TargetJava.__init__(self, name, options, cfg, extmap)
+ self.objext = '.class'
+ self.lang = 'java'
+ self.classes = options.get('classes')
+ self.output_dir = self.classes
+
+ def add_dependencies(self, graph, cfg, extmap):
+ sources = _collect_paths(self.sources, self.path)
+
+ for src, reldir in sources:
+ if src[-5:] == '.java':
+ objname = src[:-5] + self.objext
+ else:
+ raise GenError('ERROR: unknown file extension on ' + src)
+
+ ofile = ObjectFile(objname, self.compile_cmd)
+
+ # object depends upon source
+ graph.add(DT_OBJECT, ofile, SourceFile(src, reldir))
+ self.deps.append(ofile)
+
+ # target (a linked item) depends upon object
+ graph.add(DT_LINK, self.name, ofile)
+
+ # collect all the paths where stuff might get built
+ ### we should collect this from the dependency nodes rather than
+ ### the sources. "what dir are you going to put yourself into?"
+ graph.add(DT_LIST, LT_TARGET_DIRS, self.path)
+ graph.add(DT_LIST, LT_TARGET_DIRS, self.classes)
+ for pattern in string.split(self.sources):
+ idx = string.rfind(pattern, '/')
+ if idx != -1:
+ ### hmm. probably shouldn't be os.path.join() right here
+ ### (at this point in the control flow; defer to output)
+ graph.add(DT_LIST, LT_TARGET_DIRS, os.path.join(self.path,
+ pattern[:idx]))
+
+ graph.add(DT_INSTALL, self.name, self)
+
+ class Section(TargetLib.Section):
+ def create_targets(self, graph, name, cfg, extmap):
+ self.targets = { }
+ target = self.target_class(name, self.options, cfg, extmap)
+ target.add_dependencies(graph, cfg, extmap)
+ self.targets = target
+
+ def get_targets(self):
+ return self.targets.values()
+
+ def get_dep_targets(self, target):
+ target = self.targets
+ return target and [target] or [ ]
+
+
_build_types = {
'exe' : TargetExe,
'script' : TargetScript,
@@ -580,6 +717,8 @@
'swig_project' : TargetSWIGProject,
'ra-module': TargetRaModule,
'apache-mod': TargetApacheMod,
+ 'javah' : TargetJavaHeaders,
+ 'java' : TargetJavaClasses,
}
Index: build/generator/gen_make.py
===================================================================
--- build/generator/gen_make.py (revision 8069)
+++ build/generator/gen_make.py (working copy)
@@ -60,6 +60,9 @@
elif isinstance(source, gen_base.ObjectFile):
# link in the object file
objects.append(source.filename)
+ elif isinstance(source, gen_base.HeaderFile):
+ # skip the header files.
+ pass
else:
### we don't know what this is, so we don't know what to do with it
raise UnknownDependency
@@ -67,21 +70,42 @@
targ_varname = string.replace(target, '-', '_')
objnames = string.join(gen_base._strip_path(path, objects))
- self.ofile.write(
- '%s_DEPS = %s %s\n'
- '%s_OBJECTS = %s\n'
- '%s: $(%s_DEPS)\n'
- '\tcd %s && %s -o %s $(%s_OBJECTS) %s $(LIBS)\n\n'
- % (targ_varname, target_ob.add_deps, string.join(objects + deps),
+ if isinstance(target_ob, gen_base.TargetJava):
+ self.ofile.write(
+ '%s_DEPS = %s %s\n'
+ '%s: $(%s_DEPS)\n'
+ '\t%s -d %s '
+ % (targ_varname, target_ob.add_deps, string.join(objects + deps),
- targ_varname, objnames,
+ target_ob.name, targ_varname,
+ target_ob.link_cmd, target_ob.output_dir))
+ if isinstance(target_ob, gen_base.TargetJavaHeaders):
+ self.ofile.write('-classpath %s ' % target_ob.classes);
+ for dep in target_ob.deps:
+ if isinstance(dep, gen_base.ObjectFile):
+ self.ofile.write('%s ' % os.path.join('$(abs_srcdir)',
dep.filename))
+ elif isinstance(dep, gen_base.HeaderFile):
+ self.ofile.write('%s ' % dep.classname)
+ else:
+ print type(dep)
+ raise UnknownDependency
+ self.ofile.write('\n\n')
+ else:
+ self.ofile.write(
+ '%s_DEPS = %s %s\n'
+ '%s_OBJECTS = %s\n'
+ '%s: $(%s_DEPS)\n'
+ '\tcd %s && %s -o %s $(%s_OBJECTS) %s $(LIBS)\n\n'
+ % (targ_varname, target_ob.add_deps, string.join(objects + deps),
- target_ob.filename, targ_varname,
+ targ_varname, objnames,
- path, target_ob.link_cmd, os.path.basename(target_ob.filename),
- targ_varname, string.join(gen_base.unique(libs)))
- )
+ target_ob.filename, targ_varname,
+ path, target_ob.link_cmd, os.path.basename(target_ob.filename),
+ targ_varname, string.join(gen_base.unique(libs)))
+ )
+
# for each install group, write a rule to install its outputs
for itype, i_targets in self.graph.get_deps(gen_base.DT_INSTALL):
outputs = [ ]
@@ -161,6 +185,8 @@
'\t$(MKDIR) $(DESTDIR)$(%sdir)\n'
% (area, string.join(files), area_var))
for file in files:
+ if file == '':
+ continue
# cd to dirname before install to work around libtool 1.4.2 bug.
dirname, fname = os.path.split(file)
self.ofile.write('\tcd %s ; $(INSTALL_%s) %s $(DESTDIR)%s\n'
@@ -169,7 +195,8 @@
fname,
os.path.join('$(%sdir)' % area_var, fname)))
### we should turn AREA into an object, then test it instead of this
- if area[:5] == 'swig-' and area[-4:] != '-lib':
+ if area[:5] == 'swig-' and area[-4:] != '-lib' or \
+ area[:7] == 'javahl-':
self.ofile.write('\t$(INSTALL_EXTRA_%s)\n' % upper_var)
self.ofile.write('\n')
@@ -185,7 +212,8 @@
self.ofile.write('\n# handy shortcut targets\n')
for target in self.graph.get_all_sources(gen_base.DT_INSTALL):
- if not isinstance(target, gen_base.TargetScript):
+ if not isinstance(target, gen_base.TargetScript) and \
+ not isinstance(target, gen_base.TargetJava):
self.ofile.write('%s: %s\n' % (target.name, target.filename))
self.ofile.write('\n')
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Dec 24 11:52:59 2003