4
votes

Using Nant 0.92 (and previously 0.85 with same consequence)

I'm trying to call the delete task in NAnt to remove all files except the .dll file after calling msbuild (see the script below .. I'm referring to the delete in the "build" target). The delete task does not seem to execute.

The initial delete task works fine, and behaves as expected, removing all files from the specified build directory. The second delete task, after the compile however doesn't work.

I've tried just deleting everything (not using the exclude tag), tried explicitly setting failonerror and verbose to true. None of these make a difference. I've also tried using sleep to stop the process prior to the delete task, in case something in msbuild was not releasing the files in time for a delete. I've tried putting the delete into a separate target, still no luck.

The command obviously works prior to calling msbuild, and it works after msbuild if trying to delete from a directory other than the msbuild output target (i.e. copy the output files, then delete relevant files).

I'm sure that this is too fundamental a problem to be a bug, but I thought I'd ask anyway. Of course I'll use the workaround in the mean time of just copying the files to a different location delete what I don't need then move appropriately, but I'm curious about this.

I suspect, that unless this behaviour is by design (although I can find nothing in the NAnt documentation to suggest it is), then perhaps the msbuild process is locking the output files until NAnt process completes? This is my best guess. Further insights would be appreciated.

EDIT: also, if I explicitly set the \OutputPath switch of msbuild, then I don't have the same problem. It only appears that when the default OutputPath is used is the problem created.

NAnt build file:

<?xml version="1.0" encoding="utf-8" ?>
<project name="Reports.TestBench.PreBuild" default="postbuild.cleanup" basedir="." xmlns="http://nant.sourceforge.net/release/0.86-beta1/nant.xsd">
    <property name="nant.settings.currentframework" value="net-4.0" />
    <property name="project.StandardReports" value="${project::get-base-directory()}\Reports.StandardReports\Palladium.Reports.StandardReports.csproj" />
    <property name="output.Dir" value="${project::get-base-directory()}\bin\debug\"/>
    <property name="build.Type" value="debug"/>

    <!--Deletes the pre-existing build files-->
    <target name="clean">
        <delete>
          <fileset basedir="${output.Dir}">
            <include name="*.*" />  
          </fileset>
        </delete>
    </target>

    <!--Builds the projects to the specified build directory-->
    <target name="build" depends="clean" description="Build the Palladium Reports Standard Reports application">
        <msbuild project="${project.StandardReports}">
            <arg value="/p:Configuration=${build.Type}" />
            <!--arg value="/p:OutputPath=${path::get-full-path(buildDir.Client)}\Reports" /-->
            <arg value="/t:Rebuild" />
        </msbuild>

        <delete failonerror="true" verbose="true">
          <fileset basedir="${output.Dir}">
            <include name="*.*" />
            <exclude name="Palladium.Reports.StandardReports.dll" />
          </fileset>
        </delete>
    </target>
</project>

Summary of NAnt output showing build success with no further messages:

  [msbuild] Build succeeded.
  [msbuild]     0 Warning(s)
  [msbuild]     0 Error(s)
  [msbuild] 
  [msbuild] Time Elapsed 00:00:03.19

BUILD SUCCEEDED

Total time: 3.5 seconds.
1
Can you try changing the msbuild to a file copy, so the process flow is delete, copy, delete? If that works, then we know the issue is indeed something to do with the msbuild task - Mightymuke

1 Answers

0
votes

Try poking into NAnt source code - most likely the msbuild task creates an MSBuild engine and does not force it to close the files afterwards. Although looking at the MSDN docs, I don't really see a way to do it - MSBuild constructs lack a Dispose() function. There's a finalizer on classes such as ProjectInstance, so one could force it release the file handles by running in an application domain and closing the whole domain afterwards - that's quite a bit of work.