001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: /*
019: * build notes
020: * -The reference CD to listen to while editing this file is
021: * nap: Underworld - Everything, Everything
022: */
023:
024: package org.apache.tools.ant.taskdefs.optional.dotnet;
025:
026: import java.io.File;
027: import java.util.Vector;
028:
029: import org.apache.tools.ant.BuildException;
030: import org.apache.tools.ant.Project;
031: import org.apache.tools.ant.taskdefs.condition.Os;
032: import org.apache.tools.ant.types.EnumeratedAttribute;
033: import org.apache.tools.ant.types.FileSet;
034:
035: /**
036: * Assembles .NET Intermediate Language files.
037: * ilasm.exe must be on the execute path, unless another executable
038: * or the full path to that executable is specified in the <tt>executable</tt>
039: * parameter
040: * <p>
041: *
042: * <p>
043: *
044: * All parameters are optional: <il/> should suffice to produce a debug
045: * build of all *.il files. The option set is roughly compatible with the
046: * CSharp class; even though the command line options are only vaguely
047: * equivalent. [The low level commands take things like /OUT=file, csc wants
048: * /out:file ... /verbose is used some places; /quiet here in ildasm... etc.]
049: * It would be nice if someone made all the command line tools consistent (and
050: * not as brittle as the java cmdline tools) <p>
051: * <p>
052: * The task is a directory based task, so attributes like <b>includes="*.il"
053: * </b> and <b>excludes="broken.il"</b> can be used to control the files pulled
054: * in. You can also use nested <src> filesets to refer to source.
055: * <p>
056: *
057: * @ant.task name="ilasm" category="dotnet"
058: */
059:
060: public class Ilasm extends DotnetBaseMatchingTask {
061:
062: // CheckStyle:VisibilityModifier OFF - bc
063: // CheckStyle:ConstantNameCheck OFF - bc
064: /**
065: * Name of the executable. The .exe suffix is deliberately not included in
066: * anticipation of the unix version
067: */
068: protected static final String exe_name = "ilasm";
069:
070: /**
071: * what is the file extension we search on?
072: */
073: protected static final String file_ext = "il";
074:
075: /**
076: * and now derive the search pattern from the extension
077: */
078: protected static final String file_pattern = "**/*." + file_ext;
079:
080: /**
081: * title of task for external presentation
082: */
083: protected static final String exe_title = "ilasm";
084:
085: /**
086: * type of target. Should be one of exe|library|module|winexe|(null)
087: * default is exe; the actual value (if not null) is fed to the command
088: * line. <br>
089: * See /target
090: */
091: protected String targetType;
092:
093: /**
094: * verbose flag
095: */
096: protected boolean verbose;
097:
098: /**
099: * listing flag
100: */
101:
102: protected boolean listing;
103:
104: /**
105: * resource file (.res format) to include in the app.
106: */
107: protected File resourceFile;
108:
109: /**
110: * flag to control action on execution trouble
111: */
112: protected boolean failOnError;
113:
114: /**
115: * debug flag. Controls generation of debug information.
116: */
117: protected boolean debug;
118:
119: /**
120: * file containing private key
121: */
122:
123: private File keyfile;
124:
125: /**
126: * any extra command options?
127: */
128: protected String extraOptions;
129:
130: /**
131: * filesets of references
132: */
133: protected Vector referenceFilesets = new Vector();
134:
135: // CheckStyle:ConstantNameCheck ON
136: // CheckStyle:VisibilityModifier ON
137:
138: /**
139: * @since Ant 1.7
140: */
141: private boolean isMono = !Os.isFamily("windows");
142:
143: /**
144: * constructor inits everything and set up the search pattern
145: */
146: public Ilasm() {
147: Clear();
148: setIncludes(file_pattern);
149: }
150:
151: // CheckStyle:MethodNameCheck OFF - bc
152: /**
153: * reset all contents.
154: */
155: public void Clear() {
156: targetType = null;
157: srcDir = null;
158: listing = false;
159: verbose = false;
160: debug = true;
161: outputFile = null;
162: failOnError = true;
163: resourceFile = null;
164: extraOptions = null;
165: }
166:
167: // CheckStyle:MethodNameCheck ON
168:
169: /**
170: * Sets the type of target, either "exe" or "library".
171: *
172: *@param targetType one of exe|library|
173: *@exception BuildException if target is not one of
174: * exe|library
175: */
176: public void setTargetType(String targetType) throws BuildException {
177: this .targetType = targetType.toLowerCase();
178: if (!targetType.equals("exe") && !targetType.equals("library")) {
179: throw new BuildException("targetType " + targetType
180: + " is not a valid type");
181: }
182: }
183:
184: /**
185: * accessor method for target type
186: *
187: *@return the current target option
188: */
189: public String getTargetType() {
190: return targetType;
191: }
192:
193: /**
194: * g get the target type or null for no argument needed
195: *
196: *@return The TargetTypeParameter value
197: */
198:
199: protected String getTargetTypeParameter() {
200: if (!notEmpty(targetType)) {
201: return null;
202: }
203: if (targetType.equals("exe")) {
204: return "/exe";
205: } else if (targetType.equals("library")) {
206: return "/dll";
207: } else {
208: return null;
209: }
210: }
211:
212: /**
213: * Sets the Owner attribute.
214: *
215: * @param s The new Owner value
216: * @ant.attribute ignore="true"
217: */
218: public void setOwner(String s) {
219: log("This option is not supported by ILASM as of Beta-2, "
220: + "and will be ignored", Project.MSG_WARN);
221: }
222:
223: /**
224: * test for a string containing something useful
225: *
226: *@param s any string
227: *@return true if the argument is not null or empty
228: */
229: protected boolean notEmpty(String s) {
230: return s != null && s.length() != 0;
231: }
232:
233: /**
234: * If true, enable verbose ILASM output.
235: *
236: *@param b flag set to true for verbose on
237: */
238: public void setVerbose(boolean b) {
239: verbose = b;
240: }
241:
242: /**
243: * turn the verbose flag into a parameter for ILASM
244: *
245: *@return null or the appropriate command line string
246: */
247: protected String getVerboseParameter() {
248: return verbose ? null : "/quiet";
249: }
250:
251: /**
252: * If true, produce a listing (off by default).
253: *
254: *@param b flag set to true for listing on
255: */
256: public void setListing(boolean b) {
257: listing = b;
258: }
259:
260: /**
261: * turn the listing flag into a parameter for ILASM
262: *
263: *@return the appropriate string from the state of the listing flag
264: */
265: protected String getListingParameter() {
266: if (!isMono) {
267: return listing ? "/listing" : "/nolisting";
268: }
269: return null;
270: }
271:
272: /**
273: * Set the output file; identical to setDestFile
274: * @see DotnetBaseMatchingTask#setDestFile
275: *@param params The new outputFile value
276: */
277: public void setOutputFile(File params) {
278: outputFile = params;
279: }
280:
281: /**
282: * get the output file
283: *
284: *@return the argument string or null for no argument
285: */
286: protected String getOutputFileParameter() {
287: if (outputFile == null) {
288: return null;
289: }
290: return "/output=" + outputFile.toString();
291: }
292:
293: /**
294: * name of resource file to include.
295: *
296: * @param fileName path to the file. Can be relative, absolute, whatever.
297: */
298: public void setResourceFile(File fileName) {
299: resourceFile = fileName;
300: }
301:
302: /**
303: * Gets the resourceFileParameter attribute of the Ilasm task
304: *
305: *@return The resourceFileParameter value
306: */
307: protected String getResourceFileParameter() {
308: if (resourceFile != null) {
309: return "/resource=" + resourceFile.toString();
310: } else {
311: return null;
312: }
313: }
314:
315: /**
316: * If true, fails if ilasm tool fails.
317: *
318: *@param b The new failOnError value
319: */
320: public void setFailOnError(boolean b) {
321: failOnError = b;
322: }
323:
324: /**
325: * query fail on error flag
326: *
327: *@return The failFailOnError value
328: */
329: public boolean getFailOnError() {
330: return failOnError;
331: }
332:
333: /**
334: * set the debug flag on or off.
335: *
336: *@param f on/off flag
337: */
338: public void setDebug(boolean f) {
339: debug = f;
340: }
341:
342: /**
343: * query the debug flag
344: *
345: *@return true if debug is turned on
346: */
347: public boolean getDebug() {
348: return debug;
349: }
350:
351: /**
352: * get the argument or null for no argument needed
353: *
354: *@return The debugParameter value
355: */
356: protected String getDebugParameter() {
357: return debug ? "/debug" : null;
358: }
359:
360: /**
361: * the name of a file containing a private key.
362: *
363: *@param keyfile The new keyfile value
364: */
365: public void setKeyfile(File keyfile) {
366: this .keyfile = keyfile;
367: }
368:
369: /**
370: * get the argument or null for no argument needed
371: *
372: *@return The keyfileParameter value
373: */
374: protected String getKeyfileParameter() {
375: if (keyfile != null) {
376: return "/keyfile:" + keyfile.toString();
377: } else {
378: return null;
379: }
380: }
381:
382: /**
383: * Any extra options which are not explicitly
384: * supported by this task.
385: *
386: *@param extraOptions The new ExtraOptions value
387: */
388: public void setExtraOptions(String extraOptions) {
389: this .extraOptions = extraOptions;
390: }
391:
392: /**
393: * Gets the ExtraOptions attribute
394: *
395: *@return The ExtraOptions value
396: */
397: public String getExtraOptions() {
398: return this .extraOptions;
399: }
400:
401: /**
402: * get any extra options or null for no argument needed
403: *
404: *@return The ExtraOptions Parameter to CSC
405: */
406: protected String getExtraOptionsParameter() {
407: if (extraOptions != null && extraOptions.length() != 0) {
408: return extraOptions;
409: } else {
410: return null;
411: }
412: }
413:
414: /**
415: * set the target type to one of exe|library
416: * @param targetType the enumerated value.
417: */
418: public void setTargetType(TargetTypes targetType) {
419: this .targetType = targetType.getValue();
420: }
421:
422: /**
423: * Explicitly override the Mono auto-detection.
424: *
425: * <p>Defaults to false on Windows and true on any other platform.</p>
426: * @param b a <code>boolean</code> value.
427: * @since Ant 1.7
428: */
429: public void setMono(boolean b) {
430: isMono = b;
431: }
432:
433: /**
434: * This is the execution entry point. Build a list of files and call ilasm
435: * on each of them.
436: *
437: *@throws BuildException if the assembly failed and FailOnError is true
438: */
439: public void execute() throws BuildException {
440: log(
441: "This task is deprecated and will be removed in a future version\n"
442: + "of Ant. It is now part of the .NET Antlib:\n"
443: + "http://ant.apache.org/antlibs/dotnet/index.html",
444: Project.MSG_WARN);
445: NetCommand command = buildIlasmCommand();
446:
447: addFilesAndExecute(command, false);
448:
449: }
450:
451: // end execute
452:
453: /**
454: * build up our ilasm command
455: * @return
456: */
457: private NetCommand buildIlasmCommand() {
458: NetCommand command = new NetCommand(this , exe_title, exe_name);
459: command.setFailOnError(getFailOnError());
460: //fill in args
461: command.addArgument(getDebugParameter());
462: command.addArgument(getTargetTypeParameter());
463: command.addArgument(getListingParameter());
464: command.addArgument(getOutputFileParameter());
465: command.addArgument(getResourceFileParameter());
466: command.addArgument(getVerboseParameter());
467: command.addArgument(getKeyfileParameter());
468: command.addArgument(getExtraOptionsParameter());
469:
470: /*
471: * space for more argumentativeness
472: * command.addArgument();
473: * command.addArgument();
474: */
475: return command;
476: }
477:
478: /**
479: * add a new reference fileset to the compilation
480: * @param reference the fileset to use.
481: */
482: public void addReference(FileSet reference) {
483: referenceFilesets.add(reference);
484: }
485:
486: /**
487: * test for a file being managed or not
488: * @param file the file to test.
489: * @return true if we think this is a managed executable, and thus OK
490: * for linking
491: * @todo look at the PE header of the exe and see if it is managed or not.
492: */
493: protected static boolean isFileManagedBinary(File file) {
494: String filename = file.toString().toLowerCase();
495: return filename.endsWith(".exe") || filename.endsWith(".dll")
496: || filename.endsWith(".netmodule");
497: }
498:
499: /**
500: * Target types to build.
501: * valid build types are exe|library|module|winexe
502: */
503: public static class TargetTypes extends EnumeratedAttribute {
504: /** {@inheritDoc}. */
505: public String[] getValues() {
506: return new String[] { "exe", "library", };
507: }
508: }
509:
510: }
|