GlueGen: src/java/com/jogamp/gluegen/ant/GlueGenTask.java Source File

GlueGen v2.6.0-rc-20250822 GlueGen, Native Binding Generator for Java™ (public API).

GlueGenTask.java
Go to the documentation of this file.
1 package com.jogamp.gluegen.ant;
2
3/*
4 * Copyright (C) 2003 Rob Grzywinski (rgrzywinski@realityinteractive.com)
5 * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
6 * Copyright (c) 2010 JogAmp Community. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * - Redistribution of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * - Redistribution in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * Neither the name of Sun Microsystems, Inc. or the names of
20 * contributors may be used to endorse or promote products derived from
21 * this software without specific prior written permission.
22 *
23 * This software is provided "AS IS," without a warranty of any kind. ALL
24 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
25 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
26 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
27 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
28 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
29 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
30 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
31 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
32 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
33 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
34 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
35 *
36 * You acknowledge that this software is not designed or intended for use
37 * in the design, construction, operation or maintenance of any nuclear
38 * facility.
39 */
40
41import java.io.IOException;
42import java.util.Iterator;
43import java.util.LinkedList;
44import java.util.List;
45
46import org.apache.tools.ant.BuildException;
47import org.apache.tools.ant.DirectoryScanner;
48import org.apache.tools.ant.Project;
49import org.apache.tools.ant.Task;
50import org.apache.tools.ant.taskdefs.Execute;
51import org.apache.tools.ant.taskdefs.LogStreamHandler;
52import org.apache.tools.ant.types.AbstractFileSet;
53import org.apache.tools.ant.types.CommandlineJava;
54import org.apache.tools.ant.types.DirSet;
55import org.apache.tools.ant.types.FileSet;
56import org.apache.tools.ant.types.Path;
57import org.apache.tools.ant.types.PatternSet;
58import org.apache.tools.ant.types.Reference;
59import org.apache.tools.ant.util.JavaEnvUtils;
60
61/**
62 * <p>An <a href="http://ant.apache.org">ANT</a> {@link org.apache.tools.ant.Task}
63 * for using {@link com.jogamp.gluegen.GlueGen}.</p>
64 *
65 * <p>Usage:</p>
66 * <pre>
67 &lt;gluegen src="[source C file]"
68 outputrootdir="[optional output root dir]"
69 includes="[optional directory pattern of include files to include]"
70 excludes="[optional directory pattern of include files to exclude]"
71 includeRefid="[optional FileSet or DirSet for include files]"
72 literalInclude="[optional comma separated list of literal include directories, avoiding limitations of FileSet / DirSet issues]"
73 emitter="[emitter class name]"
74 config="[configuration file]"
75 dumpCPP="[optional boolean]"
76 debug="[optional boolean]"
77 logLevel="[optional string]" /&gt;
78 * </pre>
79 *
80 * @author Rob Grzywinski <a href="mailto:rgrzywinski@realityinteractive.com">rgrzywinski@yahoo.com</a>
81 */
82// FIXME: blow out javadoc
83// NOTE: this has not been exhaustively tested
84 public class GlueGenTask extends Task
85{
86 /**
87 * <p>The {@link com.jogamp.gluegen.GlueGen} classname.</p>
88 */
89 private static final String GLUE_GEN = "com.jogamp.gluegen.GlueGen";
90
91 // =========================================================================
92 /**
93 * <p>The {@link org.apache.tools.ant.types.CommandlineJava} that is used
94 * to execute {@link com.jogamp.gluegen.GlueGen}.</p>
95 */
96 private final CommandlineJava gluegenCommandline;
97
98 // =========================================================================
99 /**
100 * <p>The optional debug flag.</p>
101 */
102 private boolean debug=false;
103
104 /**
105 * <p>The optional logLevel.</p>
106 */
107 private String logLevel = null;
108
109 /**
110 * <p>The optional dumpCPP flag.</p>
111 */
112 private boolean dumpCPP=false;
113
114 /**
115 * <p>The optional output root dir.</p>
116 */
117 private String outputRootDir;
118
119 /**
120 * <p>The name of the emitter class.</p>
121 */
122 private String emitter;
123
124 /**
125 * <p>The configuration file name.</p>
126 */
127 private String configuration;
128
129 /**
130 * <p>The name of the source C file that is to be parsed.</p>
131 */
132 private String sourceFile;
133
134 /**
135 * <p>The {@link org.apache.tools.ant.types.FileSet} of includes.</p>
136 */
137 private final FileSet includeSet = new FileSet();
138
139 /**
140 * <p>Because a {@link org.apache.tools.ant.types.FileSet} will include
141 * everything in its base directory if it is left untouched, the <code>includeSet</code>
142 * must only be added to the set of includes if it has been <i>explicitly</i>
143 * set.</p>
144 */
145 private boolean usedIncludeSet = false; // by default it is not used
146
147 /**
148 * <p>The set of include sets. This allows includes to be added in multiple
149 * fashions.</p>
150 */
151 // FIXME: rename to listXXXX
152 private final List<AbstractFileSet> setOfIncludeSets = new LinkedList<AbstractFileSet>();
153
154 /**
155 * <p>Comma separated list of literal directories to include. This is to get around the
156 * fact that neither {@link org.apache.tools.ant.types.FileSet} nor
157 * {@link org.apache.tools.ant.types.DirSet} can handle multiple drives in
158 * a sane manner or deal with relative path outside of the base-dir.
159 * If <code>null</code> then it has not been specified.</p>
160 */
161 private String literalIncludes;
162
163 // =========================================================================
164 /**
165 * <p>Create and add the VM and classname to {@link org.apache.tools.ant.types.CommandlineJava}.</p>
166 */
167 public GlueGenTask()
168 {
169 // create the CommandlineJava that will be used to call GlueGen
170 gluegenCommandline = new CommandlineJava();
171
172 // set the VM and classname in the commandline
173 gluegenCommandline.setVm(JavaEnvUtils.getJreExecutable("java"));
174 gluegenCommandline.setClassname(GLUE_GEN);
175 // gluegenCommandline.createVmArgument().setValue("-verbose:class");
176 }
177
178 // =========================================================================
179 // ANT getters and setters
180
181 /**
182 * <p>Set the debug flag (optional). This is called by ANT.</p>
183 */
184 public void setDebug(final boolean debug)
185 {
186 log( ("Setting debug flag: " + debug), Project.MSG_VERBOSE);
187 this.debug=debug;
188 }
189
190 /**
191 * <p>Set the logLevel (optional). This is called by ANT.</p>
192 */
193 public void setLogLevel(final String logLevel)
194 {
195 log( ("Setting logLevel: " + logLevel), Project.MSG_VERBOSE);
196 this.logLevel=logLevel;
197 }
198
199 /**
200 * <p>Set the dumpCPP flag (optional). This is called by ANT.</p>
201 */
202 public void setDumpCPP(final boolean dumpCPP)
203 {
204 log( ("Setting dumpCPP flag: " + dumpCPP), Project.MSG_VERBOSE);
205 this.dumpCPP=dumpCPP;
206 }
207
208 /**
209 * <p>Set the output root dir (optional). This is called by ANT.</p>
210 *
211 * @param outputRootDir the optional output root dir
212 */
213 public void setOutputRootDir(final String outputRootDir)
214 {
215 log( ("Setting output root dir: " + outputRootDir), Project.MSG_VERBOSE);
216 this.outputRootDir=outputRootDir;
217 }
218
219 /**
220 * <p>Set the emitter class name. This is called by ANT.</p>
221 *
222 * @param emitter the name of the emitter class
223 */
224 public void setEmitter(final String emitter)
225 {
226 log( ("Setting emitter class name to: " + emitter), Project.MSG_VERBOSE);
227 this.emitter = emitter;
228 }
229
230 /**
231 * <p>Set the configuration file name. This is called by ANT.</p>
232 *
233 * @param configuration the name of the configuration file
234 */
235 public void setConfig(final String configuration)
236 {
237 log( ("Setting configuration file name to: " + configuration),
238 Project.MSG_VERBOSE);
239 this.configuration = configuration;
240 }
241
242 /**
243 * <p>Set the source C file that is to be parsed. This is called by ANT.</p>
244 *
245 * @param sourceFile the name of the source file
246 */
247 public void setSrc(final String sourceFile)
248 {
249 log( ("Setting source file name to: " + sourceFile), Project.MSG_VERBOSE);
250 this.sourceFile = sourceFile;
251 }
252
253 /**
254 * <p>Set a literal include directories, separated with a comma. See the <code>literalInclude</code>
255 * javadoc for more information.</p>
256 *
257 * @param commaSeparatedIncludes the comma separated directories to include
258 */
259 public void setLiteralInclude(final String commaSeparatedIncludes)
260 {
261 this.literalIncludes = commaSeparatedIncludes.trim();
262 }
263
264 /**
265 * <p>Add an include file to the list. This is called by ANT for a nested
266 * element.</p>
267 *
268 * @return {@link org.apache.tools.ant.types.PatternSet.NameEntry}
269 */
270 public PatternSet.NameEntry createInclude()
271 {
272 usedIncludeSet = true;
273 return includeSet.createInclude();
274 }
275
276 /**
277 * <p>Add an include file to the list. This is called by ANT for a nested
278 * element.</p>
279 *
280 * @return {@link org.apache.tools.ant.types.PatternSet.NameEntry}
281 */
282 public PatternSet.NameEntry createIncludesFile()
283 {
284 usedIncludeSet = true;
285 return includeSet.createIncludesFile();
286 }
287
288 /**
289 * <p>Set the set of include patterns. Patterns may be separated by a comma
290 * or a space. This is called by ANT.</p>
291 *
292 * @param includes the string containing the include patterns
293 */
294 public void setIncludes(final String includes)
295 {
296 usedIncludeSet = true;
297 includeSet.setIncludes(includes);
298 }
299
300 /**
301 * <p>Add an include file to the list that is to be exluded. This is called
302 * by ANT for a nested element.</p>
303 *
304 * @return {@link org.apache.tools.ant.types.PatternSet.NameEntry}
305 */
306 public PatternSet.NameEntry createExclude()
307 {
308 usedIncludeSet = true;
309 return includeSet.createExclude();
310 }
311
312 /**
313 * <p>Add an exclude file to the list. This is called by ANT for a nested
314 * element.</p>
315 *
316 * @return {@link org.apache.tools.ant.types.PatternSet.NameEntry}
317 */
318 public PatternSet.NameEntry createExcludesFile()
319 {
320 usedIncludeSet = true;
321 return includeSet.createExcludesFile();
322 }
323
324 /**
325 * <p>Set the set of exclude patterns. Patterns may be separated by a comma
326 * or a space. This is called by ANT.</p>
327 *
328 * @param includes the string containing the exclude patterns
329 */
330 public void setExcludes(final String excludes)
331 {
332 usedIncludeSet = true;
333 includeSet.setExcludes(excludes);
334 }
335
336 /**
337 * <p>Set a {@link org.apache.tools.ant.types.Reference} to simplify adding
338 * of complex sets of files to include. This is called by ANT.</p>?
339 *
340 * @param reference a <code>Reference</code> to a {@link org.apache.tools.ant.types.FileSet}
341 * or {@link org.apache.tools.ant.types.DirSet}
342 * @throws BuildException if the specified <code>Reference</code> is not
343 * either a <code>FileSet</code> or <code>DirSet</code>
344 */
345 public void setIncludeRefid(final Reference reference) {
346 // ensure that the referenced object is either a FileSet or DirSet
347 final Object referencedObject = reference.getReferencedObject(getProject());
348 if (referencedObject instanceof FileSet) {
349 setOfIncludeSets.add((FileSet)referencedObject);
350 return;
351 }
352 if (referencedObject instanceof DirSet) {
353 setOfIncludeSets.add((DirSet)referencedObject);
354 return;
355 }
356
357 throw new BuildException("Only FileSets or DirSets are allowed as an include refid.");
358}
359
360 /**
361 * <p>Add a nested {@link org.apache.tools.ant.types.DirSet} to specify
362 * the files to include. This is called by ANT.</p>
363 *
364 * @param dirset the <code>DirSet</code> to be added
365 */
366 public void addDirset(final DirSet dirset)
367 {
368 setOfIncludeSets.add(dirset);
369 }
370
371 /**
372 * <p>Add an optional classpath that defines the location of {@link com.jogamp.gluegen.GlueGen}
373 * and <code>GlueGen</code>'s dependencies.</p>
374 *
375 * @returns {@link org.apache.tools.ant.types.Path}
376 */
377 public Path createClasspath()
378 {
379 return gluegenCommandline.createClasspath(project).createPath();
380 }
381
382 // =========================================================================
383 /**
384 * <p>Run the task. This involves validating the set attributes, creating
385 * the command line to be executed and finally executing the command.</p>
386 *
387 * @see org.apache.tools.ant.Task#execute()
388 */
389 @Override
390 public void execute()
391 throws BuildException
392 {
393 // validate that all of the required attributes have been set
394 validateAttributes();
395
396 // TODO: add logic to determine if the generated file needs to be
397 // regenerated
398
399 // add the attributes to the CommandlineJava
400 addAttributes();
401
402 log(gluegenCommandline.describeCommand(), Project.MSG_VERBOSE);
403
404 // execute the command and throw on error
405 final int error = execute(gluegenCommandline.getCommandline());
406 if(error == 1)
407 throw new BuildException( ("GlueGen returned: " + error), location);
408 }
409
410 /**
411 * <p>Ensure that the user specified all required arguments.</p>
412 *
413 * @throws BuildException if there are required arguments that are not
414 * present or not valid
415 */
416 private void validateAttributes()
417 throws BuildException
418 {
419 // outputRootDir is optional ..
420
421 // validate that the emitter class is set
422 if(!isValid(emitter))
423 throw new BuildException("Invalid emitter class name: " + emitter);
424
425 // validate that the configuration file is set
426 if(!isValid(configuration))
427 throw new BuildException("Invalid configuration file name: " + configuration);
428
429 // validate that the source file is set
430 if(!isValid(sourceFile))
431 throw new BuildException("Invalid source file name: " + sourceFile);
432
433 // CHECK: do there need to be includes to be valid?
434 }
435
436 /**
437 * <p>Is the specified string valid? A valid string is non-<code>null</code>
438 * and has a non-zero length.</p>
439 *
440 * @param string the string to be tested for validity
441 * @return <code>true</code> if the string is valid. <code>false</code>
442 * otherwise.
443 */
444 private boolean isValid(final String string)
445 {
446 // check for null
447 if(string == null)
448 return false;
449
450 // ensure that the string has a non-zero length
451 // NOTE: must trim() to remove leading and trailing whitespace
452 if(string.trim().length() < 1)
453 return false;
454
455 // the string is valid
456 return true;
457 }
458
459 /**
460 * <p>Add all of the attributes to the command line. They have already
461 * been validated.</p>
462 */
463 private void addAttributes()
464 throws BuildException
465 {
466 // NOTE: GlueGen uses concatenated flag / value rather than two
467 // separate arguments
468
469 // add the debug flag if enabled
470 if(debug) {
471 gluegenCommandline.createArgument().setValue("--debug");
472 }
473
474 // add the logLevel if enabled
475 if(null != logLevel) {
476 gluegenCommandline.createArgument().setValue("--logLevel");
477 gluegenCommandline.createArgument().setValue(logLevel);
478 }
479
480 // add the debug flag if enabled
481 if(dumpCPP) {
482 gluegenCommandline.createArgument().setValue("--dumpCPP");
483 }
484
485 // add the output root dir
486 if(null!=outputRootDir && outputRootDir.trim().length()>0) {
487 gluegenCommandline.createArgument().setValue("-O" + outputRootDir);
488 }
489
490 // add the emitter class name
491 gluegenCommandline.createArgument().setValue("-E" + emitter);
492
493 // add the configuration file name
494 gluegenCommandline.createArgument().setValue("-C" + configuration);
495
496 // add the includedSet to the setOfIncludeSets to simplify processing
497 // all types of include sets ONLY if it has been set.
498 // NOTE: see the usedIncludeSet member javadoc for more info
499 // NOTE: references and nested DirSets have already been added to the
500 // set of include sets
501 if(usedIncludeSet)
502 {
503 includeSet.setDir(getProject().getBaseDir()); // NOTE: the base dir must be set
504 setOfIncludeSets.add(includeSet);
505 }
506
507 // iterate over all include sets and add their directories to the
508 // list of included directories.
509 final List<String> includedDirectories = new LinkedList<String>();
510 for (final Iterator<AbstractFileSet> includes = setOfIncludeSets.iterator(); includes.hasNext();)
511 {
512 // get the included set and based on its type add the directories
513 // to includedDirectories
514 final AbstractFileSet include = includes.next();
515 final DirectoryScanner directoryScanner = include.getDirectoryScanner(getProject());
516 final String[] directoryDirs = directoryScanner.getIncludedDirectories();
517
518 // add the directoryDirs to the includedDirectories
519 // TODO: exclude any directory that is already in the list
520 for(int i=0; i<directoryDirs.length; i++)
521 {
522 includedDirectories.add(directoryDirs[i]);
523 }
524 }
525
526 // if literalInclude is valid then add it to the list of included
527 // directories
528 if( isValid( literalIncludes ) ) {
529 final String[] includes = literalIncludes.split(",");
530 for(int i=0; i<includes.length; i++) {
531 final String include = includes[i].trim();
532 if( include.length()>0 ) {
533 includedDirectories.add(include);
534 }
535 }
536 }
537
538 // add the included directories to the command
539 for(final Iterator<String> includes=includedDirectories.iterator(); includes.hasNext(); )
540 {
541 final String directory = includes.next();
542 gluegenCommandline.createArgument().setValue("-I" + directory);
543 }
544
545 // finally, add the source file
546 gluegenCommandline.createArgument().setValue(sourceFile);
547 }
548
549 /**
550 * <p>Execute {@link com.jogamp.gluegen.GlueGen} in a forked JVM.</p>
551 *
552 * @throws BuildException
553 */
554 private int execute(final String[] command)
555 throws BuildException
556 {
557 // create the object that will perform the command execution
558 final Execute execute = new Execute(new LogStreamHandler(this, Project.MSG_INFO,
559 Project.MSG_WARN),
560 null);
561
562 // set the project and command line
563 execute.setAntRun(project);
564 execute.setCommandline(command);
565 execute.setWorkingDirectory( project.getBaseDir() );
566
567 // execute the command
568 try
569 {
570 return execute.execute();
571 } catch(final IOException ioe)
572 {
573 throw new BuildException(ioe, location);
574 }
575 }
576}
com.jogamp.gluegen.ant.GlueGenTask
Definition: GlueGenTask.java:85
com.jogamp.gluegen.ant.GlueGenTask.createClasspath
Path createClasspath()
Definition: GlueGenTask.java:377
com.jogamp.gluegen.ant.GlueGenTask.setIncludes
void setIncludes(final String includes)
Definition: GlueGenTask.java:294
com.jogamp.gluegen.ant.GlueGenTask.createIncludesFile
PatternSet.NameEntry createIncludesFile()
Definition: GlueGenTask.java:282
com.jogamp.gluegen.ant.GlueGenTask.execute
void execute()
Definition: GlueGenTask.java:390
com.jogamp.gluegen.ant.GlueGenTask.setLiteralInclude
void setLiteralInclude(final String commaSeparatedIncludes)
Definition: GlueGenTask.java:259
com.jogamp.gluegen.ant.GlueGenTask.createInclude
PatternSet.NameEntry createInclude()
Definition: GlueGenTask.java:270
com.jogamp.gluegen.ant.GlueGenTask.createExclude
PatternSet.NameEntry createExclude()
Definition: GlueGenTask.java:306
com.jogamp.gluegen.ant.GlueGenTask.setDumpCPP
void setDumpCPP(final boolean dumpCPP)
Definition: GlueGenTask.java:202
com.jogamp.gluegen.ant.GlueGenTask.setExcludes
void setExcludes(final String excludes)
Definition: GlueGenTask.java:330
com.jogamp.gluegen.ant.GlueGenTask.setOutputRootDir
void setOutputRootDir(final String outputRootDir)
Definition: GlueGenTask.java:213
com.jogamp.gluegen.ant.GlueGenTask.setSrc
void setSrc(final String sourceFile)
Definition: GlueGenTask.java:247
com.jogamp.gluegen.ant.GlueGenTask.setConfig
void setConfig(final String configuration)
Definition: GlueGenTask.java:235
com.jogamp.gluegen.ant.GlueGenTask.setEmitter
void setEmitter(final String emitter)
Definition: GlueGenTask.java:224
com.jogamp.gluegen.ant.GlueGenTask.addDirset
void addDirset(final DirSet dirset)
Definition: GlueGenTask.java:366
com.jogamp.gluegen.ant.GlueGenTask.setLogLevel
void setLogLevel(final String logLevel)
Definition: GlueGenTask.java:193
com.jogamp.gluegen.ant.GlueGenTask.GlueGenTask
GlueGenTask()
Definition: GlueGenTask.java:167
com.jogamp.gluegen.ant.GlueGenTask.setDebug
void setDebug(final boolean debug)
Definition: GlueGenTask.java:184
com.jogamp.gluegen.ant.GlueGenTask.setIncludeRefid
void setIncludeRefid(final Reference reference)
Definition: GlueGenTask.java:345
com.jogamp.gluegen.ant.GlueGenTask.createExcludesFile
PatternSet.NameEntry createExcludesFile()
Definition: GlueGenTask.java:318