param: Rename variable used for lp_msg_command szMsgCommand
[Samba.git] / buildtools / wafadmin / Tools / javaw.py
blob301ebc426b9d23a1b62b31c11042225ce2d1fbe3
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # Thomas Nagy, 2006-2008 (ita)
5 """
6 Java support
8 Javac is one of the few compilers that behaves very badly:
9 * it outputs files where it wants to (-d is only for the package root)
10 * it recompiles files silently behind your back
11 * it outputs an undefined amount of files (inner classes)
13 Fortunately, the convention makes it possible to use the build dir without
14 too many problems for the moment
16 Inner classes must be located and cleaned when a problem arise,
17 for the moment waf does not track the production of inner classes.
19 Adding all the files to a task and executing it if any of the input files
20 change is only annoying for the compilation times
22 Compilation can be run using Jython[1] rather than regular Python. Instead of
23 running one of the following commands:
24 ./waf configure
25 python waf configure
26 You would have to run:
27 java -jar /path/to/jython.jar waf configure
29 [1] http://www.jython.org/
30 """
32 import os, re
33 from Configure import conf
34 import TaskGen, Task, Utils, Options, Build
35 from TaskGen import feature, before, taskgen
37 class_check_source = '''
38 public class Test {
39 public static void main(String[] argv) {
40 Class lib;
41 if (argv.length < 1) {
42 System.err.println("Missing argument");
43 System.exit(77);
45 try {
46 lib = Class.forName(argv[0]);
47 } catch (ClassNotFoundException e) {
48 System.err.println("ClassNotFoundException");
49 System.exit(1);
51 lib = null;
52 System.exit(0);
55 '''
57 @feature('jar')
58 @before('apply_core')
59 def jar_files(self):
60 basedir = getattr(self, 'basedir', '.')
61 destfile = getattr(self, 'destfile', 'test.jar')
62 jaropts = getattr(self, 'jaropts', [])
63 jarcreate = getattr(self, 'jarcreate', 'cf')
65 dir = self.path.find_dir(basedir)
66 if not dir: raise
68 jaropts.append('-C')
69 jaropts.append(dir.abspath(self.env))
70 jaropts.append('.')
72 out = self.path.find_or_declare(destfile)
74 tsk = self.create_task('jar_create')
75 tsk.set_outputs(out)
76 tsk.inputs = [x for x in dir.find_iter(src=0, bld=1) if x.id != out.id]
77 tsk.env['JAROPTS'] = jaropts
78 tsk.env['JARCREATE'] = jarcreate
80 @feature('javac')
81 @before('apply_core')
82 def apply_java(self):
83 Utils.def_attrs(self, jarname='', jaropts='', classpath='',
84 sourcepath='.', srcdir='.', source_re='**/*.java',
85 jar_mf_attributes={}, jar_mf_classpath=[])
87 if getattr(self, 'source_root', None):
88 # old stuff
89 self.srcdir = self.source_root
92 nodes_lst = []
94 if not self.classpath:
95 if not self.env['CLASSPATH']:
96 self.env['CLASSPATH'] = '..' + os.pathsep + '.'
97 else:
98 self.env['CLASSPATH'] = self.classpath
100 srcdir_node = self.path.find_dir(self.srcdir)
101 if not srcdir_node:
102 raise Utils.WafError('could not find srcdir %r' % self.srcdir)
104 src_nodes = [x for x in srcdir_node.ant_glob(self.source_re, flat=False)]
105 bld_nodes = [x.change_ext('.class') for x in src_nodes]
107 self.env['OUTDIR'] = [srcdir_node.bldpath(self.env)]
109 tsk = self.create_task('javac')
110 tsk.set_inputs(src_nodes)
111 tsk.set_outputs(bld_nodes)
113 if getattr(self, 'compat', None):
114 tsk.env.append_value('JAVACFLAGS', ['-source', self.compat])
116 if hasattr(self, 'sourcepath'):
117 fold = [self.path.find_dir(x) for x in self.to_list(self.sourcepath)]
118 names = os.pathsep.join([x.srcpath() for x in fold])
119 else:
120 names = srcdir_node.srcpath()
122 if names:
123 tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names])
125 if self.jarname:
126 jtsk = self.create_task('jar_create', bld_nodes, self.path.find_or_declare(self.jarname))
127 jtsk.set_run_after(tsk)
129 if not self.env.JAROPTS:
130 if self.jaropts:
131 self.env.JAROPTS = self.jaropts
132 else:
133 dirs = '.'
134 self.env.JAROPTS = ['-C', ''.join(self.env['OUTDIR']), dirs]
136 Task.simple_task_type('jar_create', '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}', color='GREEN', shell=False)
137 cls = Task.simple_task_type('javac', '${JAVAC} -classpath ${CLASSPATH} -d ${OUTDIR} ${JAVACFLAGS} ${SRC}', shell=False)
138 cls.color = 'BLUE'
139 def post_run_javac(self):
140 """this is for cleaning the folder
141 javac creates single files for inner classes
142 but it is not possible to know which inner classes in advance"""
144 par = {}
145 for x in self.inputs:
146 par[x.parent.id] = x.parent
148 inner = {}
149 for k in par.values():
150 path = k.abspath(self.env)
151 lst = os.listdir(path)
153 for u in lst:
154 if u.find('$') >= 0:
155 inner_class_node = k.find_or_declare(u)
156 inner[inner_class_node.id] = inner_class_node
158 to_add = set(inner.keys()) - set([x.id for x in self.outputs])
159 for x in to_add:
160 self.outputs.append(inner[x])
162 self.cached = True # disable the cache here - inner classes are a problem
163 return Task.Task.post_run(self)
164 cls.post_run = post_run_javac
166 def detect(conf):
167 # If JAVA_PATH is set, we prepend it to the path list
168 java_path = conf.environ['PATH'].split(os.pathsep)
169 v = conf.env
171 if 'JAVA_HOME' in conf.environ:
172 java_path = [os.path.join(conf.environ['JAVA_HOME'], 'bin')] + java_path
173 conf.env['JAVA_HOME'] = [conf.environ['JAVA_HOME']]
175 for x in 'javac java jar'.split():
176 conf.find_program(x, var=x.upper(), path_list=java_path)
177 conf.env[x.upper()] = conf.cmd_to_list(conf.env[x.upper()])
178 v['JAVA_EXT'] = ['.java']
180 if 'CLASSPATH' in conf.environ:
181 v['CLASSPATH'] = conf.environ['CLASSPATH']
183 if not v['JAR']: conf.fatal('jar is required for making java packages')
184 if not v['JAVAC']: conf.fatal('javac is required for compiling java classes')
185 v['JARCREATE'] = 'cf' # can use cvf
187 @conf
188 def check_java_class(self, classname, with_classpath=None):
189 """Check if the specified java class is installed"""
191 import shutil
193 javatestdir = '.waf-javatest'
195 classpath = javatestdir
196 if self.env['CLASSPATH']:
197 classpath += os.pathsep + self.env['CLASSPATH']
198 if isinstance(with_classpath, str):
199 classpath += os.pathsep + with_classpath
201 shutil.rmtree(javatestdir, True)
202 os.mkdir(javatestdir)
204 java_file = open(os.path.join(javatestdir, 'Test.java'), 'w')
205 java_file.write(class_check_source)
206 java_file.close()
208 # Compile the source
209 Utils.exec_command(self.env['JAVAC'] + [os.path.join(javatestdir, 'Test.java')], shell=False)
211 # Try to run the app
212 cmd = self.env['JAVA'] + ['-cp', classpath, 'Test', classname]
213 self.log.write("%s\n" % str(cmd))
214 found = Utils.exec_command(cmd, shell=False, log=self.log)
216 self.check_message('Java class %s' % classname, "", not found)
218 shutil.rmtree(javatestdir, True)
220 return found
222 @conf
223 def check_jni_headers(conf):
225 Check for jni headers and libraries
227 On success the environment variable xxx_JAVA is added for uselib
230 if not conf.env.CC_NAME and not conf.env.CXX_NAME:
231 conf.fatal('load a compiler first (gcc, g++, ..)')
233 if not conf.env.JAVA_HOME:
234 conf.fatal('set JAVA_HOME in the system environment')
236 # jni requires the jvm
237 javaHome = conf.env['JAVA_HOME'][0]
239 b = Build.BuildContext()
240 b.load_dirs(conf.srcdir, conf.blddir)
241 dir = b.root.find_dir(conf.env.JAVA_HOME[0] + '/include')
242 f = dir.ant_glob('**/(jni|jni_md).h', flat=False)
243 incDirs = [x.parent.abspath() for x in f]
245 dir = b.root.find_dir(conf.env.JAVA_HOME[0])
246 f = dir.ant_glob('**/*jvm.(so|dll)', flat=False)
247 libDirs = [x.parent.abspath() for x in f] or [javaHome]
249 for i, d in enumerate(libDirs):
250 if conf.check(header_name='jni.h', define_name='HAVE_JNI_H', lib='jvm',
251 libpath=d, includes=incDirs, uselib_store='JAVA', uselib='JAVA'):
252 break
253 else:
254 conf.fatal('could not find lib jvm in %r (see config.log)' % libDirs)