diff --git a/proposal/sandbox/dotnet/docs/index.html b/proposal/sandbox/dotnet/docs/index.html index 6fc5444d9..ff4454bb4 100644 --- a/proposal/sandbox/dotnet/docs/index.html +++ b/proposal/sandbox/dotnet/docs/index.html @@ -111,6 +111,8 @@
Runs the candle, light or both from the Wix toolset.
+ +Attribute | +Description | +Required | +
source | +The single source file to process. | +Either this or at least one nested + <sources> set. | +
target | +The expected target file. | +Yes, unless you run candle without light. | +
mode | +Which part of the toolset to run, one of + "candle", "light" or + "both". | +No, default is "both". | +
vm | +Same as dotnetexec's vm attribute. + Specify the framework to use. | +No. | +
Specify source files that shall be passed on the command line. + This is a fileset.
+ +Specify source files that shall not be passed on the command + line. This is a fileset.
+ +Typically this would list include files when running candle or + the files that vecome part of the MSI file when running light. + The files in this set are only used for timestamp comparisons. If + neither these files nor the given "normal" sources are + newer than the expected target, the task won't do anything.
+ + +Create product.wixobj
from product.wxs
:
+ <wix mode="candle" source="product.wxs"/> ++ +
The same but using a nested sources element:
+ ++ <wix mode="candle"> + <sources dir="."> + <include name="product.wxs"/> + </sources> + </wix> ++ +
Create product.msi
from product.wixobj
:
+ <wix mode="light" source="product.wixobj" target="product.msi"/> ++ +
Combine the examples into a single step:
+ ++ <wix source="product.wxs" target="product.msi"/> ++ +
Note that the task wouldn't do anything if
+ product.wxs
was older than
+ product.wixobj
and product.wixobj
was
+ older than product.msi
.
Compile multiple .wxs
files at once:
+ <wix mode="candle"> + <sources dir="."> + <include name="*.wxs"/> + </sources> + </wix> ++ +
Compile multiple .wxs
files at once, specify some
+ include files in addition to that:
+ <wix mode="candle"> + <sources dir="."> + <include name="*.wxs"/> + </sources> + <moresources dir="."> + <include name="*.wxi"/> + </moresources> + </wix> ++ +
Link multiple .wixobj
files at once:
+ <wix mode="light" target="product.msi"> + <sources dir="."> + <include name="*.wixobj"/> + </sources> + </wix> ++ +
Link multiple .wixobj
files at once and specify
+ that the files in directory "source" will become part of
+ the package:
+ <wix mode="light" target="product.msi"> + <sources dir="."> + <include name="*.wixobj"/> + </sources> + <moresources dir="source"/> + </wix> ++ +
Combine multiple .wxs
files and include files
+ into a single package and specify that the package will contain
+ files from the source directory:
+
+ + <wix target="product.msi"> + <sources dir="."> + <include name="*.wxs"/> + </sources> + <moresources dir="."> + <include name="*.wxi"/> + </moresources> + <moresources dir="source"/> + </wix> ++ +
Again, if the intermediate .wixobj
files are newer
+ that the corresponding .wxs
files (and all include
+ files) the candle step will be skipped. If
+ product.msi
is newer than all files, the task won't
+ do anything.
Copyright © 2004 The Apache Software Foundation. All rights Reserved.
+ + \ No newline at end of file diff --git a/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/WixTask.java b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/WixTask.java new file mode 100644 index 000000000..7969803d8 --- /dev/null +++ b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/WixTask.java @@ -0,0 +1,301 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant.taskdefs.optional.dotnet; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.FileSet; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Task to run the WiX utility to create MSI files from an XML description. + * + * @see http://sf.net/projects/wix + */ +public class WixTask extends Task { + + /** + * The vm attribute - if given. + */ + private String vm; + + /** + * The source files. + */ + private ArrayList sources = new ArrayList(); + + /** + * Additional source files (include files in the case of candle, + * or media/files/whatever in the case of light). + */ + private ArrayList moreSources = new ArrayList(); + + /** + * A single source file. + */ + private File source; + + /** + * The target file. + */ + private File target; + + /** + * What to do. + */ + private Mode mode; + + public WixTask() { + super(); + } + + /** + * Set the name of the executable for the virtual machine. + * + * @param value the name of the executable for the virtual machine + */ + public void setVm(String value) { + this.vm = value; + } + + /** + * The main source file. + * + *candle
may include more files than this one,
+ * the main source is the one passed on the command line.
Unlike the files specified as sources, these will not be + * passed on the command line, they only help Ant to determine + * whether the target is out-of-date.
+ */ + public void addMoreSources(FileSet fs) { + moreSources.add(fs); + } + + public void execute() { + if (source == null && sources.size() == 0) { + throw new BuildException("You must specify at least one source" + + " file."); + } + String m = Mode.BOTH; + if (mode != null) { + m = mode.getValue(); + } + + if (target == null && !m.equals(Mode.CANDLE)) { + throw new BuildException("You must specify the target if you want" + + " to run light."); + } + + List lightSources = new ArrayList(); + if (!m.equals(Mode.LIGHT)) { + doCandle(lightSources); + } else { + if (source != null) { + lightSources.add(source); + } + if (sources.size() > 0) { + lightSources.addAll(grabFiles(sources)); + } + } + List moreLightSources = new ArrayList(); + if (moreSources.size() > 0) { + moreLightSources = grabFiles(moreSources); + } + if (!m.equals(Mode.CANDLE)) { + doLight(lightSources, moreLightSources); + } + } + + /** + * Invoke candle on all sources that are newer than their targets. + * + * @param lightSources list that will be filled with File objects + * pointing to the generated object files. + */ + private void doCandle(List lightSources) { + List s = new ArrayList(); + if (source != null) { + s.add(source); + } + if (sources != null) { + s.addAll(grabFiles(sources)); + } + List ms = new ArrayList(); + if (moreSources != null) { + ms.addAll(grabFiles(moreSources)); + } + Iterator iter = s.iterator(); + List toProcess = new ArrayList(); + while (iter.hasNext()) { + File thisSource = (File) iter.next(); + File t = target; + if (t == null) { + t = getTarget(thisSource); + } + if (isOutOfDate(t, thisSource, ms)) { + toProcess.add(thisSource); + lightSources.add(t); + } + } + if (toProcess.size() != 0) { + runCandle(toProcess); + } + } + + /** + * Invoke light on all sources that are newer than their targets. + */ + private void doLight(List lightSources, List moreLightSources) { + List tmp = new ArrayList(lightSources); + tmp.addAll(moreLightSources); + if (isOutOfDate(target, tmp)) { + runLight(lightSources); + } + } + + /** + * Run candle passing all files in list on the command line. + */ + private void runCandle(List s) { + run("candle.exe", s, null); + } + + /** + * Run light passing all files in list on the command line. + */ + private void runLight(List s) { + run("light.exe", s, target); + } + + /** + * Runs the specified command passing list on the command line an + * potentially adding an /out parameter. + */ + private void run(String executable, List s, File target) { + DotNetExecTask exec = new DotNetExecTask(); + if (vm != null) { + exec.setVm(vm); + } + exec.setProject(getProject()); + exec.setExecutable(executable); + exec.setTaskName(getTaskName()); + Iterator iter = s.iterator(); + while (iter.hasNext()) { + File f = (File) iter.next(); + exec.createArg().setValue(f.getAbsolutePath()); + } + if (target != null) { + exec.createArg().setValue("/out"); + exec.createArg().setValue(target.getAbsolutePath()); + } + + exec.execute(); + } + + /** + * Is t older than s or any of the files in list? + */ + private boolean isOutOfDate(File t, File s, List l) { + return t.lastModified() < s.lastModified() || isOutOfDate(t, l); + } + + /** + * Is t older than any of the files in list? + */ + private boolean isOutOfDate(File t, List l) { + Iterator iter = l.iterator(); + while (iter.hasNext()) { + File f = (File) iter.next(); + if (t.lastModified() < f.lastModified()) { + return true; + } + } + return false; + } + + /** + * Turn the fileset collection into a list of Files. + */ + private List grabFiles(List s) { + List r = new ArrayList(); + Iterator iter = s.iterator(); + while (iter.hasNext()) { + FileSet fs = (FileSet) iter.next(); + DirectoryScanner ds = fs.getDirectoryScanner(getProject()); + String[] f = ds.getIncludedFiles(); + File base = fs.getDir(getProject()); + for (int i = 0; i < f.length; i++) { + r.add(new File(base, f[i])); + } + } + return r; + } + + /** + * Generates the name of a candle target from the source file. + * + *Simply chops of the extension and adds .wixobj.
+ */ + private File getTarget(File s) { + String name = s.getAbsolutePath(); + int dot = name.lastIndexOf("."); + if (dot > -1) { + return new File(name.substring(0, dot) + ".wixobj"); + } else { + return new File(name + ".wixobj"); + } + } + + public static class Mode extends EnumeratedAttribute { + private final static String CANDLE = "candle"; + private final static String LIGHT = "light"; + private final static String BOTH = "both"; + + public Mode() { + super(); + } + + public String[] getValues() { + return new String[] {CANDLE, LIGHT, BOTH,}; + } + } +} \ No newline at end of file diff --git a/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml index ba487903e..cf5bd0c93 100644 --- a/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml +++ b/proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml @@ -27,4 +27,8 @@ name="nant" classname="org.apache.tools.ant.taskdefs.optional.dotnet.NAntTask" /> +