[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] Integrate javahl into build system

From: Justin Erenkrantz <justin_at_erenkrantz.com>
Date: 2003-12-24 11:52:18 CET

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

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.