s3: libsmbclient: Add missing talloc stackframe.
[sfrench/samba-autobuild/.git] / third_party / waf / wafadmin / Tools / javaw.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # Thomas Nagy, 2006-2008 (ita)
4
5 """
6 Java support
7
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)
12
13 Fortunately, the convention makes it possible to use the build dir without
14 too many problems for the moment
15
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.
18
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
21
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
28
29 [1] http://www.jython.org/
30 """
31
32 import os, re
33 from Configure import conf
34 import TaskGen, Task, Utils, Options, Build
35 from TaskGen import feature, before, taskgen
36
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);
44                 }
45                 try {
46                         lib = Class.forName(argv[0]);
47                 } catch (ClassNotFoundException e) {
48                         System.err.println("ClassNotFoundException");
49                         System.exit(1);
50                 }
51                 lib = null;
52                 System.exit(0);
53         }
54 }
55 '''
56
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')
64
65         dir = self.path.find_dir(basedir)
66         if not dir: raise
67
68         jaropts.append('-C')
69         jaropts.append(dir.abspath(self.env))
70         jaropts.append('.')
71
72         out = self.path.find_or_declare(destfile)
73
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
79
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=[])
86
87         if getattr(self, 'source_root', None):
88                 # old stuff
89                 self.srcdir = self.source_root
90
91
92         nodes_lst = []
93
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
99
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)
103
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]
106
107         self.env['OUTDIR'] = [srcdir_node.bldpath(self.env)]
108
109         tsk = self.create_task('javac')
110         tsk.set_inputs(src_nodes)
111         tsk.set_outputs(bld_nodes)
112
113         if getattr(self, 'compat', None):
114                 tsk.env.append_value('JAVACFLAGS', ['-source', self.compat])
115
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()
121
122         if names:
123                 tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names])
124
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)
128
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]
135
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"""
143
144         par = {}
145         for x in self.inputs:
146                 par[x.parent.id] = x.parent
147
148         inner = {}
149         for k in par.values():
150                 path = k.abspath(self.env)
151                 lst = os.listdir(path)
152
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
157
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])
161
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
165
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
170
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']]
174
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']
179
180         if 'CLASSPATH' in conf.environ:
181                 v['CLASSPATH'] = conf.environ['CLASSPATH']
182
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
186
187 @conf
188 def check_java_class(self, classname, with_classpath=None):
189         """Check if the specified java class is installed"""
190
191         import shutil
192
193         javatestdir = '.waf-javatest'
194
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
200
201         shutil.rmtree(javatestdir, True)
202         os.mkdir(javatestdir)
203
204         java_file = open(os.path.join(javatestdir, 'Test.java'), 'w')
205         java_file.write(class_check_source)
206         java_file.close()
207
208         # Compile the source
209         Utils.exec_command(self.env['JAVAC'] + [os.path.join(javatestdir, 'Test.java')], shell=False)
210
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)
215
216         self.check_message('Java class %s' % classname, "", not found)
217
218         shutil.rmtree(javatestdir, True)
219
220         return found
221
222 @conf
223 def check_jni_headers(conf):
224         """
225         Check for jni headers and libraries
226
227         On success the environment variable xxx_JAVA is added for uselib
228         """
229
230         if not conf.env.CC_NAME and not conf.env.CXX_NAME:
231                 conf.fatal('load a compiler first (gcc, g++, ..)')
232
233         if not conf.env.JAVA_HOME:
234                 conf.fatal('set JAVA_HOME in the system environment')
235
236         # jni requires the jvm
237         javaHome = conf.env['JAVA_HOME'][0]
238
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]
244
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]
248
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)