summaryrefslogtreecommitdiffstats
path: root/src/engine
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-04-08 05:00:51 (GMT)
committerSteven Knight <knight@baldmt.com>2003-04-08 05:00:51 (GMT)
commit393e4ca7e9d1308803da49bee667f1a874c612db (patch)
treef0ac1818542b5cc730b5c6792f64fc5ee6f3b814 /src/engine
parentb967a4a50e7ad193583412bc5a585acde1fddbe7 (diff)
downloadSCons-393e4ca7e9d1308803da49bee667f1a874c612db.zip
SCons-393e4ca7e9d1308803da49bee667f1a874c612db.tar.gz
SCons-393e4ca7e9d1308803da49bee667f1a874c612db.tar.bz2
Enhance Java support for package names that don't match the source directory hierarchy.
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/SCons/Tool/javac.py175
1 files changed, 137 insertions, 38 deletions
diff --git a/src/engine/SCons/Tool/javac.py b/src/engine/SCons/Tool/javac.py
index fff6de5..22145fc 100644
--- a/src/engine/SCons/Tool/javac.py
+++ b/src/engine/SCons/Tool/javac.py
@@ -33,50 +33,149 @@ selection method.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import glob
import os.path
+import string
import SCons.Builder
+# Okay, I don't really know what configurability would be good for
+# parsing Java files for package and/or class names, but it was easy, so
+# here it is.
+#
+# Set java_parsing to the following values to enable three different
+# flavors of parsing:
+#
+# 0 The file isn't actually parsed, so this will be quickest. The
+# package + class name is assumed to be the file path name, and we
+# just split the path name. This breaks if a package name will
+# ever be different from the path to the .java file.
+#
+# 1 The file is read to find the package name, after which we stop.
+# This should be pretty darn quick, and allows flexibility in
+# package names, but assumes that the public class name in the
+# file matches the file name. This seems to be a good assumption
+# because, for example, if you try to declare a public class
+# with a different name from the file, javac tells you:
+#
+# class Foo is public, should be declared in a file named Foo.java
+#
+# 2 Full flexibility of class names. We parse for the package name
+# (like level #1) but the output .class file name is assumed to
+# match the declared public class name--and, as a bonus, this will
+# actually support multiple public classes in a single file. My
+# guess is that's illegal Java, though... Or is it an option
+# supported by some compilers?
+#
+java_parsing = 1
+
+if java_parsing == 0:
+ def parse_java(file, suffix):
+ """ "Parse" a .java file.
+
+ This actually just splits the file name, so the assumption here
+ is that the file name matches the public class name, and that
+ the path to the file is the same as the package name.
+ """
+ return os.path.split(file)
+elif java_parsing == 1:
+ def parse_java(file, suffix):
+ """Parse a .java file for a package name.
+
+ This, of course, is not full parsing of Java files, but
+ simple-minded searching for the usual begins-in-column-1
+ "package" string most Java programs use to define their package.
+ """
+ pkg_dir = None
+ classes = []
+ f = open(file, "rb")
+ while 1:
+ line = f.readline()
+ if not line:
+ break
+ if line[:7] == 'package':
+ pkg = string.split(line)[1]
+ if pkg[-1] == ';':
+ pkg = pkg[:-1]
+ pkg_dir = apply(os.path.join, string.split(pkg, '.'))
+ classes = [ os.path.split(file[:-len(suffix)])[1] ]
+ break
+ f.close()
+ return pkg_dir, classes
+
+elif java_parsing == 2:
+ import re
+ pub_re = re.compile('^\s*public(\s+abstract)?\s+class\s+(\S+)')
+ def parse_java(file, suffix):
+ """Parse a .java file for package name and classes.
+
+ This, of course, is not full parsing of Java files, but
+ simple-minded searching for the usual strings most Java programs
+ seem to use for packages and public class names.
+ """
+ pkg_dir = None
+ classes = []
+ f = open(file, "rb")
+ while 1:
+ line = f.readline()
+ if not line:
+ break
+ if line[:7] == 'package':
+ pkg = string.split(line)[1]
+ if pkg[-1] == ';':
+ pkg = pkg[:-1]
+ pkg_dir = apply(os.path.join, string.split(pkg, '.'))
+ elif line[:6] == 'public':
+ c = pub_re.findall(line)
+ try:
+ classes.append(c[0][1])
+ except IndexError:
+ pass
+ f.close()
+ return pkg_dir, classes
+
def generate(env, platform):
"""Add Builders and construction variables for javac to an Environment."""
- try:
- bld = env['BUILDERS']['Java']
- except KeyError:
- def emit_java_files(target, source, env):
- """Create and return lists of source java files
- and their corresponding target class files.
- """
- env['_JAVACLASSDIR'] = target[0]
- env['_JAVASRCDIR'] = source[0]
- java_suffix = env.get('JAVASUFFIX', '.java')
- class_suffix = env.get('JAVACLASSSUFFIX', '.class')
- slist = []
- def visit(arg, dirname, names, js=java_suffix):
- java_files = filter(lambda n, js=js: n[-len(js):] == js, names)
- java_paths = map(lambda f, d=dirname:
- os.path.join(d, f),
- java_files)
- arg.extend(java_paths)
- os.path.walk(source[0], visit, slist)
- tlist = map(lambda x, t=target[0], cs=class_suffix:
- os.path.join(t, x[:-5] + cs),
- slist)
-
- return tlist, slist
-
- JavaBuilder = SCons.Builder.Builder(action = '$JAVACCOM',
- emitter = emit_java_files,
- target_factory = SCons.Node.FS.default_fs.File,
- source_factory = SCons.Node.FS.default_fs.File)
-
- env['BUILDERS']['Java'] = JavaBuilder
-
- env['JAVAC'] = 'javac'
- env['JAVACFLAGS'] = ''
- env['JAVACCOM'] = '$JAVAC $JAVACFLAGS -d $_JAVACLASSDIR -sourcepath $_JAVASRCDIR $SOURCES'
- env['JAVACLASSSUFFIX'] = '.class'
- env['JAVASUFFIX'] = '.java'
+ def emit_java_files(target, source, env):
+ """Create and return lists of source java files
+ and their corresponding target class files.
+ """
+ env['_JAVACLASSDIR'] = target[0]
+ env['_JAVASRCDIR'] = source[0]
+ java_suffix = env.get('JAVASUFFIX', '.java')
+ class_suffix = env.get('JAVACLASSSUFFIX', '.class')
+ slist = []
+ def visit(arg, dirname, names, js=java_suffix):
+ java_files = filter(lambda n, js=js: n[-len(js):] == js, names)
+ java_paths = map(lambda f, d=dirname:
+ os.path.join(d, f),
+ java_files)
+ arg.extend(java_paths)
+ os.path.walk(source[0], visit, slist)
+ tlist = []
+ for file in slist:
+ pkg_dir, classes = parse_java(file, java_suffix)
+ if pkg_dir:
+ for c in classes:
+ tlist.append(os.path.join(target[0],
+ pkg_dir,
+ c + class_suffix))
+ else:
+ tlist.append(os.path.join(target[0],
+ file[:-5] + class_suffix))
+ return tlist, slist
+
+ JavaBuilder = SCons.Builder.Builder(action = '$JAVACCOM',
+ emitter = emit_java_files,
+ target_factory = SCons.Node.FS.default_fs.File,
+ source_factory = SCons.Node.FS.default_fs.File)
+
+ env['BUILDERS']['Java'] = JavaBuilder
+
+ env['JAVAC'] = 'javac'
+ env['JAVACFLAGS'] = ''
+ env['JAVACCOM'] = '$JAVAC $JAVACFLAGS -d $_JAVACLASSDIR -sourcepath $_JAVASRCDIR $SOURCES'
+ env['JAVACLASSSUFFIX'] = '.class'
+ env['JAVASUFFIX'] = '.java'
def exists(env):
return env.Detect('javac')