NANT CSC Build Failure: References Missing? - msbuild

I have the following NANT CSC target for building winexe:
<csc target="winexe" output="${Deploy.dir}\VMIS.exe" debug="${debug}">
<sources>
<include name="${App.dir}\**\*.cs" />
<include name="${Build.dir}\AssemblyInfo.cs" />
<exclude name="${App.dir}\**\AssemblyInfo.cs" />
</sources>
<references refid="Lib.fileset">
</references>
...
</csc>
The following is the failure message:
D:\..\myClass.cs(9,17): error CS0234: The type or namespace name 'Reporting'
does not exist in the namespace 'Microsoft' (are you missing an assembly
reference?)
In myClass.cs, I have this using reference:
using Microsoft.ReportViewer.WinForms;
There is no problem to build my app in VS, but I could not build from NANT. I think that I may miss reference to Microsoft.ReportViewer.WinForms.dll in NANT build. Not sure how I can include this dll in my bin for NANT?
I have tried to modify csc target's references:
<csc ...>
...
<references refid="Lib.fileset">
<include name="Microsoft.ReportViewer.Common.dll" />
<include name="Microsoft.ReportViewer.WinForms.dll" />
</references>
...
</csc>
Still not working. Should I use COPY target to copy all the dll files from bin to $(build.dir)?
Updates: I found that those Microsoft.ReportViewer.xx.dll files in project references are not copy to local. How can I simulate copy to local in NANT for those two dll files? I guess that may resolve the issue since NANT is a build app in console and does not have knowledge about references in global cache.

NAnt is configured with the default set of DLLs for the .NET framework, and knows where those DLLs reside (e.g. C:\Windows\Microsoft.NET\Framework64\v4.0.30319). When you include non-framework assemblies, whether they are yours or a 3rd party, you can include them, but use the full path of the DLL:
<include name="C:\Common\ThirdParty.dll" />
You can also use variables:
<property name="common.directory" value="C:\Common" />
...
<csc ...>
...
<references>
<inclde name="${common.directory}\ThirdParty.dll" />
</references>
</csc>

Recommended:
Use MSBuild in your NAnt script(s) to build your application.
FYI: Visual Studio uses MSBuild to compile and build your solution and projects.
<!-- Verify the right target framework -->
<property name="MSBuildPath" value="C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe" />
<target name="Build">
<exec program="${MSBuildPath}">
<arg line='"${SolutionFile}"' />
<arg value="/target:Rebuild" />
<arg value="/verbosity:normal" />
<arg value="/nologo" />
</exec>
</target>
Possibility:
Copy references/files locally (i.e. using copy task). Or similarly use full paths in the include name.
Not recommended:
Use NAnt's "solution" task, or NAntContrib's "msbuild" task.
This would simplify the msbuild call but would tie you into older versions of msbuild/VS solution/project files. Newer VS solution/project files would not be supported readily.
Hope it helps.

Related

MSBuild cannot find a reference - ReactJs.NET

After upgrading Newtonsoft.Json to version 9.0.0 and ReactJS.Net packages to 2.5.0, the TransformBabel.proj stopped working:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="TransformBabel">
<!-- ReactJS.NET - Transpile JavaScript via Babel -->
<UsingTask AssemblyFile="$(OutputPath)\React.MSBuild.dll" TaskName="TransformBabel" />
<Target Name="TransformBabel">
<TransformBabel SourceDir="$(MSBuildProjectDirectory)" />
</Target>
</Project>
Returning the following:
TransformBabel.proj(6, 3): error MSB4018: The "TransformBabel" task failed unexpectedly.
[Exec] TransformBabel.proj(6, 3): error MSB4018: React.TinyIoC.TinyIoCResolutionException: Unable to resolve type: React.IReactSiteConfiguration ---> System.TypeInitializationException: The type initializer for 'React.ReactSiteConfiguration' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.
It seems that it cannot load the Newtonsoft 6.0.0.0 version. The web.config has an assembly redirection:
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
But I am not sure that, as it is starting a new msbuild process, if it is being ignored. I would like to hint msbuild the location of the assembly, but no success until now.
A bit late to the party here, but hopefully my experience will help to anyone else having the same problem.
I have recently experienced the same issue with React.MSBuild 3.1.0. It seems that it has hardcoded a specific version as I have updated my Newtonsoft.Json to the latest (10.0.3) using NuGet and set redirection correctly, but the build kept failing on the same error as you have mentioned.
What I did is simply uninstall all the React packages (MSBuild and Core) and also Newtonsoft.Json (using -force as there were other dependencies) and then let NuGet install the React.MSBuild again. It has installed it with all dependencies what resulted in obtaining Newtonsoft.Json 9.0.1.
Not sure why do they restrict Newtonsoft.Json library to a specific version, but it is more a question to React developers. Unless you need a latest (or other specific version of it), this should fix the problem.
I know this is an old post...but here is my workaround:
I put Newtonsoft.Json.dll v6.0.0.0 into Tools directory relative to the project directory and let msbuild copy it to $(OutputPath) to satisfy TransformBabel task condition.
My TransformBabel.proj looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="TransformBabel">
<!-- ReactJS.NET - Transpile JavaScript via Babel -->
<UsingTask AssemblyFile="$(OutputPath)\React.MSBuild.dll" TaskName="TransformBabel" />
<Target Name="TransformBabel">
<Copy SourceFiles="$(MSBuildProjectDirectory)\Tools\Newtonsoft.Json.dll" DestinationFolder="$(OutputPath)" />
<TransformBabel SourceDir="$(MSBuildProjectDirectory)" />
</Target>
</Project>
After this TransformBabel task is finished, then let msbuild overwrite Newtonsoft.Json.dll v6.0.0.0 in $(OutputPath) with whatever Newtonsoft.Json.dll version my project is actually using, ex: v8.0.3.
So, in the main project .csproj, I have something like this:
<ItemGroup>
...
<Reference Include="React.MSBuild, Version=2.3.0.0, Culture=neutral, PublicKeyToken=9aed67b161f7db78, processorArchitecture=MSIL">
<HintPath>Tools\React.MSBuild.dll</HintPath>
<Private>True</Private>
</Reference>
...
</ItemGroup>
...
<ItemGroup>
...
<Content Include="Tools\Newtonsoft.Json.dll" />
<Content Include="Tools\React.MSBuild.dll" />
...
</ItemGroup>
...
<Target Name="TransformBabel" AfterTargets="Build">
<Exec Command=""$(msbuildtoolspath)\msbuild.exe" $(ProjectDirectory)TransformBabel.proj /p:OutputPath=$(OutputPath) /nr:false" />
</Target>
<Target Name="AfterTransformBabel" AfterTargets="TransformBabel">
<Copy SourceFiles="..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll" DestinationFolder="$(OutputPath)" />
</Target>
Replace the path Newtonsoft.Json.8.0.3 inside AfterTransformBabel task to your need.

How do I specify where MSBUILD publishes a web service too?

I've seen lots of info on the web about this, but nothing clear & specific which seems to address the problem of simply publishing a web service or web site to a specific folder that I specify at build time.
I'm using Nant and Nant Contrib:
<target name="build" description="builds the service">
<msbuild project="${buildoutput}\${service.source}\wsMyService.sln" >
<property name="Configuration" value="Release" />
<property name="PublishDir" value="${buildoutput}\${service.target}\" />
<property name="Targets" value="Publish" />
</msbuild>
</target>
Can anyone show me how this is supposed to be done. I can change the output folder in the property pages of the project, but I want this to be configurable from Nant so I can specify the path at build time.
When you call msbuild from the command line, you can pass in strings to assign to msbuild properties. I don't know anything about NAnt, so I assume it has to resort to a calling msbuild.exe. So you can override msbuild properties like this:
MsBuild /property:buildoutput=C:\arbitrary\folder\bin\
These properties specified from the command line override anything you specify in your build files.
This is what im currently using to build webservices using msbuild:
<Target Name="BuildWebService">
<ConvertToAbsolutePath Paths="$(Root)">
<Output TaskParameter="AbsolutePaths" PropertyName="Root" />
</ConvertToAbsolutePath>
<ItemGroup>
<WebServices Include="$(Root)\services\Solutions\**\*.host.csproj"/>
</ItemGroup>
<MSBuild Projects="%(WebServices.FullPath)"
Targets="Build"
Properties="WebProjectOutputDir=$(Root)\services\build\WebService\%(RecursiveDir);OutDir=$(Root)\services\build\WebService\%(RecursiveDir)\bin\" />
</Target>
Hope you can translate to nant easy enough.

Nant delete task doesn't delete files post msbuild

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.
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.

MSbuild 4.0 fail to compile .Net 3.5 project

I am using Msbuild 4.0.
In our project few solution are having .net 3.5 projects.
When i compile it through Visual studio it works. If i build the same using Msbuild it fails.
Following is the compilation issue:
error : Compilation failed. Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Exception from HRESULT: 0x80131515
Even i tried with changing
toolsversion to 3.5
through additionalproperties of item. [ I am using Msbuild task to build my solution]
Our Msbuild task looks like below.
<Target Name="BuildDotNETSolutions" Condition="'$(Group)' != ''" DependsOnTargets="Init;GetNextVersionNumber">
<!-- Complie solutions -->
<!-- Version property is useful for changing the Wix Msi version-->
<MSBuild Projects="#(Solution)" BuildInParallel="true"
Properties="Configuration=$(Configuration);PostbuildEvent=;Version=$(BuildNextVersionNumber)"
Condition="'%(Solution.Group)' == '$(Group)' And '%(Solution.Type)' == 'DotNET' And '%(Solution.IsRebuild)'=='$(IsRebuild)'">
<Output
TaskParameter="TargetOutputs"
ItemName="BuildOutputs" />
</MSBuild>
We are passing solutions through properties file like below
<Solution Include="$(Implementation)\MultiEvent.csproj;">
<Group>Event</Group>
<AdditionalProperties>
ReferencePath=$(Implementation)\References;
ToolsVersion=3.5;
</AdditionalProperties>
<IsRebuild>True</IsRebuild>
<Type>DotNET</Type>
</Solution>
I don't know if you happen to have any script-runner that runs MSBuild. Personnally, I'm using NAnt and everything is working fine. I've read (somewhere) that MSBuild sometimes do stupid things and by adding the property "TrackFileAccess" and set it to "false" helps a lot. In my case, it fixed the problem.
If it can be of any help, I've included my NAnt build task. I hope it can be useful to you.
<!--*******************************************************************************
Runs MSBuild to build the project solution
Arguments:
${MSBuild.exe}: Path to MSBuild.exe
${project.solution}: the solution name to build
${buildconfiguration}: The build configuration to trigger the build
${build.dir} : The directory where to put builded files
********************************************************************************-->
<target name="run.msbuild" description="Rebuilds a given solution file">
<echo message="Rebuilding Solution ${project.solution}" />
<echo>${MSBuild.exe}</echo>
<exec program="${MSBuild.exe}">
<arg value="${project.solution}"/>
<arg line="/property:SignAssembly=${project.sign},AssemblyOriginatorKeyFile=${project::get-base-directory()}\${project.signature.file}" />
<arg line="/property:OutDir=${build.dir}" />
<arg line="/property:TrackFileAccess=false" />
<arg line="/property:DebugType=${debug.type}" />
<arg line="/property:Platform="Any CPU"" />
<arg line="/nologo" />
<arg line="/verbosity:minimal" />
<arg line="/property:Configuration=${buildconfiguration}"/>
</exec>
in the case of a Development build, I set the following params :
<property name="buildconfiguration" value="Debug"/>
<property name="debug.type" value="full" />

NAnt <msbuild> custom output directory

I'm new to NAnt and have been able to create a <target> which
1) Deletes any code from the current folder
2) Exports fresh code from SVN
3) Builds the code in the default directory which is the PrecompiledWeb folder (its a web app)
Here it is:
<target name="export" description="export code from svn">
<delete dir="${Delete.Dir}"></delete>
<exec program="svn" commandline="export ${MySVN.Repos} ${MySVN.Dest}" />
<msbuild project="${Solution.Filename}">
<property name="Configuration" value="Release"/>
</msbuild>
</target>
I want to specify a custom output directory (other than "PrecompiledWeb"). Is this possible and could you please show me the necessary tag/property?
Thank you!
EDIT
Thanks to Scott and Si, I'm getting closer to a solution, but I still don't have anything that works. There comments led me to this article on MSBuild's Output Path Property. Using their code:
<?xml version="1.0"?>
<project name="test" default="build" basedir="." xmlns="http://nant.sf.net/schemas/nant-0.84.win32.net-1.0.xsd">
<target name="build">
<exec program="${framework::get-framework-directory('net-3.5')}/msbuild.exe">
<arg value="${Full.Path}\Code\MySolution.sln" />
<arg value="/p:OutputPath=${Full.Path}\Output\" />
</exec>
</target>
</project>
This will sucessfully run; however, in my solution which contains a web site and a class library, it publishes the class library dll to the specified output path, but it still publishes the actual web site to the default PrecompiledWeb folder.
Does anyone have any suggestions for how to change the PrecompiledWeb folder path from NAnt?
Thanks again to everyone who's helped!
Edit 2 Final Solution
Here is what I finally was able to get working (updated for .net 4):
<exec program="${framework::get-framework-directory('net-4.0')}/msbuild.exe">
<arg value="${Full.Path}\Code\MySolution.sln" />
<arg value="/t:Rebuild" />
<arg value="/t:ResolveReferences" />
<arg value="/t:_CopyWebApplication" />
<arg value="/p:OutDir=${Build.Output}bin\" />
<arg value="/p:WebProjectOutputDir=${Build.Output}" />
<arg value="/p:Configuration=Release" />
</exec>
One can specify and override some of properties for msbuild. In order to specify the output directory, override the OutputDir property.
<target name="export" description="export code from svn">
<delete dir="${Delete.Dir}" />
<exec program="svn" commandline="export ${MySVN.Repos} ${MySVN.Dest}" />
<msbuild project="${Solution.Filename}">
<property name="Configuration" value="Release"/>
<property name="OutputDir" value="${Output.Dir}"/>
</msbuild>
</target>
Just had a quick peek at a project, does OutputPath instead of OutputDir help?
Another option might be a web deployment project, which I like because it calls aspnet_compiler as well as the C# compiler, so it picks up issues which you may otherwise miss until deployment.
A build script for one of our projects uses this command to publish a web application:
msbuild.exe /t:_CopyWebApplication /p:Configuration=Release /p:OutDir=.\..\published\ /p:WebProjectOutputDir=.\..\published
(The current directory is set to the web app's project directory at this point, which is why no .csproj file is specified. The entire solution has already been rebuilt earlier in the script.)
By the sound of it, WebProjectOutputDir might be the property you need.
/t:_CopyWebApplication may also be important. I've not used NAnt so I don't know if you can pass this parameter with the msbuild task. You may need to use an exec task, like in this example: http://www.netomatix.com/development/wapwithnant.aspx. This example appears to rebuild and copy all in one go.
When using the task, the correct property name is OutDir, not OutputDir:
<msbuild project="${Solution.Filename}">
<property name="Configuration" value="Release"/>
<property name="OutDir" value="${Output.Dir}"/>
</msbuild>
A source of confusion is that you're blending two distinct build systems. Your NAnt target is delegating all the work of figuring out how to publish your web application to the solution file, hence by extension to the csproj files it references.
csproj files are MsBuild files, so you should probably look there for how to direct your project output. This post by dave^2 might be helpful on that issue.
You can publish your web application wherever you want using NAnt, provided it's doing the publishing. You can do the same with MsBuild. The cause of your quandary is that NAnt is not doing the publishing in this case, and you're letting the csproj file determine the location of your web directory. So either bypass the csproj file and have NAnt (or MsBuild) publish the code; or modify the csproj file to publish the web application where you want; or make a second location for your web application and publish it there as well using your build tool.
AFAIK, those options are exhaustive.
Hmm, don't know how to do it with MSBuild in Nant, but using NAnt, I've done it previously like this:
<solution solutionfile="${build.dir}\solution.sln">
<webmap>
<map url="http://localhost/somdir/project.csproj"
path="c:\inetpub\wwwroot\somelocaldir" />
<webmap>
</solution>
But then, you're using the NAnt 'solution' task offcourse instead of using MSBuild directly.
edit:
I'm also having a look at some msbuild options;
If you set OutDir & OutputPath to the same value, what happens ?
Try something like this:
<property name="nant.settings.currentframework" value="net-3.5"/>
<msbuild project="${Solution.Filename}">
<property name="Configuration" value="Release"/>
<property name="OutDir" value="${Full.Path}\Output\\"/>
<property name="WebProjectOutputDir" value="${Full.Path}\Output\Web\\"/>
</msbuild>