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 @@
  • msbuild - execute the MSBuild build tool, untested.
  • + +
  • wix - execute the WiX toolset, untested.

  • diff --git a/proposal/sandbox/dotnet/docs/wix.html b/proposal/sandbox/dotnet/docs/wix.html new file mode 100644 index 000000000..a79ff991e --- /dev/null +++ b/proposal/sandbox/dotnet/docs/wix.html @@ -0,0 +1,177 @@ + + + + Wix Task + + + +

    Wix

    + +

    Description

    + +

    Runs the candle, light or both from the Wix toolset.

    + +

    Parameters

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    AttributeDescriptionRequired
    sourceThe single source file to process.Either this or at least one nested + <sources> set.
    targetThe expected target file.Yes, unless you run candle without light.
    modeWhich part of the toolset to run, one of + "candle", "light" or + "both".No, default is "both".
    vmSame as dotnetexec's vm attribute. + Specify the framework to use.No.
    + +

    Parameters specified as nested elements

    + +

    sources

    + +

    Specify source files that shall be passed on the command line. + This is a fileset.

    + +

    moresources

    + +

    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.

    + + +

    Examples

    + +

    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.

    + * + * @param File object of the main source file. + */ + public void setSource(File f) { + source = f; + } + + /** + * A set of source files. + */ + public void addSources(FileSet fs) { + sources.add(fs); + } + + /** + * A set of additional source files (include files in the case of + * candle, or media/files/whatever in the case of light). + * + *

    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" /> +