diff options
Diffstat (limited to 'buildtools/wafadmin/Tools/javaw.py')
-rw-r--r-- | buildtools/wafadmin/Tools/javaw.py | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/buildtools/wafadmin/Tools/javaw.py b/buildtools/wafadmin/Tools/javaw.py new file mode 100644 index 0000000000..301ebc426b --- /dev/null +++ b/buildtools/wafadmin/Tools/javaw.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2006-2008 (ita) + +""" +Java support + +Javac is one of the few compilers that behaves very badly: +* it outputs files where it wants to (-d is only for the package root) +* it recompiles files silently behind your back +* it outputs an undefined amount of files (inner classes) + +Fortunately, the convention makes it possible to use the build dir without +too many problems for the moment + +Inner classes must be located and cleaned when a problem arise, +for the moment waf does not track the production of inner classes. + +Adding all the files to a task and executing it if any of the input files +change is only annoying for the compilation times + +Compilation can be run using Jython[1] rather than regular Python. Instead of +running one of the following commands: + ./waf configure + python waf configure +You would have to run: + java -jar /path/to/jython.jar waf configure + +[1] http://www.jython.org/ +""" + +import os, re +from Configure import conf +import TaskGen, Task, Utils, Options, Build +from TaskGen import feature, before, taskgen + +class_check_source = ''' +public class Test { + public static void main(String[] argv) { + Class lib; + if (argv.length < 1) { + System.err.println("Missing argument"); + System.exit(77); + } + try { + lib = Class.forName(argv[0]); + } catch (ClassNotFoundException e) { + System.err.println("ClassNotFoundException"); + System.exit(1); + } + lib = null; + System.exit(0); + } +} +''' + +@feature('jar') +@before('apply_core') +def jar_files(self): + basedir = getattr(self, 'basedir', '.') + destfile = getattr(self, 'destfile', 'test.jar') + jaropts = getattr(self, 'jaropts', []) + jarcreate = getattr(self, 'jarcreate', 'cf') + + dir = self.path.find_dir(basedir) + if not dir: raise + + jaropts.append('-C') + jaropts.append(dir.abspath(self.env)) + jaropts.append('.') + + out = self.path.find_or_declare(destfile) + + tsk = self.create_task('jar_create') + tsk.set_outputs(out) + tsk.inputs = [x for x in dir.find_iter(src=0, bld=1) if x.id != out.id] + tsk.env['JAROPTS'] = jaropts + tsk.env['JARCREATE'] = jarcreate + +@feature('javac') +@before('apply_core') +def apply_java(self): + Utils.def_attrs(self, jarname='', jaropts='', classpath='', + sourcepath='.', srcdir='.', source_re='**/*.java', + jar_mf_attributes={}, jar_mf_classpath=[]) + + if getattr(self, 'source_root', None): + # old stuff + self.srcdir = self.source_root + + + nodes_lst = [] + + if not self.classpath: + if not self.env['CLASSPATH']: + self.env['CLASSPATH'] = '..' + os.pathsep + '.' + else: + self.env['CLASSPATH'] = self.classpath + + srcdir_node = self.path.find_dir(self.srcdir) + if not srcdir_node: + raise Utils.WafError('could not find srcdir %r' % self.srcdir) + + src_nodes = [x for x in srcdir_node.ant_glob(self.source_re, flat=False)] + bld_nodes = [x.change_ext('.class') for x in src_nodes] + + self.env['OUTDIR'] = [srcdir_node.bldpath(self.env)] + + tsk = self.create_task('javac') + tsk.set_inputs(src_nodes) + tsk.set_outputs(bld_nodes) + + if getattr(self, 'compat', None): + tsk.env.append_value('JAVACFLAGS', ['-source', self.compat]) + + if hasattr(self, 'sourcepath'): + fold = [self.path.find_dir(x) for x in self.to_list(self.sourcepath)] + names = os.pathsep.join([x.srcpath() for x in fold]) + else: + names = srcdir_node.srcpath() + + if names: + tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) + + if self.jarname: + jtsk = self.create_task('jar_create', bld_nodes, self.path.find_or_declare(self.jarname)) + jtsk.set_run_after(tsk) + + if not self.env.JAROPTS: + if self.jaropts: + self.env.JAROPTS = self.jaropts + else: + dirs = '.' + self.env.JAROPTS = ['-C', ''.join(self.env['OUTDIR']), dirs] + +Task.simple_task_type('jar_create', '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}', color='GREEN', shell=False) +cls = Task.simple_task_type('javac', '${JAVAC} -classpath ${CLASSPATH} -d ${OUTDIR} ${JAVACFLAGS} ${SRC}', shell=False) +cls.color = 'BLUE' +def post_run_javac(self): + """this is for cleaning the folder + javac creates single files for inner classes + but it is not possible to know which inner classes in advance""" + + par = {} + for x in self.inputs: + par[x.parent.id] = x.parent + + inner = {} + for k in par.values(): + path = k.abspath(self.env) + lst = os.listdir(path) + + for u in lst: + if u.find('$') >= 0: + inner_class_node = k.find_or_declare(u) + inner[inner_class_node.id] = inner_class_node + + to_add = set(inner.keys()) - set([x.id for x in self.outputs]) + for x in to_add: + self.outputs.append(inner[x]) + + self.cached = True # disable the cache here - inner classes are a problem + return Task.Task.post_run(self) +cls.post_run = post_run_javac + +def detect(conf): + # If JAVA_PATH is set, we prepend it to the path list + java_path = conf.environ['PATH'].split(os.pathsep) + v = conf.env + + if 'JAVA_HOME' in conf.environ: + java_path = [os.path.join(conf.environ['JAVA_HOME'], 'bin')] + java_path + conf.env['JAVA_HOME'] = [conf.environ['JAVA_HOME']] + + for x in 'javac java jar'.split(): + conf.find_program(x, var=x.upper(), path_list=java_path) + conf.env[x.upper()] = conf.cmd_to_list(conf.env[x.upper()]) + v['JAVA_EXT'] = ['.java'] + + if 'CLASSPATH' in conf.environ: + v['CLASSPATH'] = conf.environ['CLASSPATH'] + + if not v['JAR']: conf.fatal('jar is required for making java packages') + if not v['JAVAC']: conf.fatal('javac is required for compiling java classes') + v['JARCREATE'] = 'cf' # can use cvf + +@conf +def check_java_class(self, classname, with_classpath=None): + """Check if the specified java class is installed""" + + import shutil + + javatestdir = '.waf-javatest' + + classpath = javatestdir + if self.env['CLASSPATH']: + classpath += os.pathsep + self.env['CLASSPATH'] + if isinstance(with_classpath, str): + classpath += os.pathsep + with_classpath + + shutil.rmtree(javatestdir, True) + os.mkdir(javatestdir) + + java_file = open(os.path.join(javatestdir, 'Test.java'), 'w') + java_file.write(class_check_source) + java_file.close() + + # Compile the source + Utils.exec_command(self.env['JAVAC'] + [os.path.join(javatestdir, 'Test.java')], shell=False) + + # Try to run the app + cmd = self.env['JAVA'] + ['-cp', classpath, 'Test', classname] + self.log.write("%s\n" % str(cmd)) + found = Utils.exec_command(cmd, shell=False, log=self.log) + + self.check_message('Java class %s' % classname, "", not found) + + shutil.rmtree(javatestdir, True) + + return found + +@conf +def check_jni_headers(conf): + """ + Check for jni headers and libraries + + On success the environment variable xxx_JAVA is added for uselib + """ + + if not conf.env.CC_NAME and not conf.env.CXX_NAME: + conf.fatal('load a compiler first (gcc, g++, ..)') + + if not conf.env.JAVA_HOME: + conf.fatal('set JAVA_HOME in the system environment') + + # jni requires the jvm + javaHome = conf.env['JAVA_HOME'][0] + + b = Build.BuildContext() + b.load_dirs(conf.srcdir, conf.blddir) + dir = b.root.find_dir(conf.env.JAVA_HOME[0] + '/include') + f = dir.ant_glob('**/(jni|jni_md).h', flat=False) + incDirs = [x.parent.abspath() for x in f] + + dir = b.root.find_dir(conf.env.JAVA_HOME[0]) + f = dir.ant_glob('**/*jvm.(so|dll)', flat=False) + libDirs = [x.parent.abspath() for x in f] or [javaHome] + + for i, d in enumerate(libDirs): + if conf.check(header_name='jni.h', define_name='HAVE_JNI_H', lib='jvm', + libpath=d, includes=incDirs, uselib_store='JAVA', uselib='JAVA'): + break + else: + conf.fatal('could not find lib jvm in %r (see config.log)' % libDirs) + |