I have a situation where we have a solution that uses Portable Areas and T4MVC which has a separate project for T4MVC where all the generated files for the 7 portable areas and main MVC3 application. We have followed the instructions here we are automatically generating the classes when building the solution.
Whilst in VS2010 this all works fine in both Debug & Release builds but where I am running into issues is where I am trying to get this to run on TeamCity.
I have followed the instructions on setting up T4 on a build server here and if run msbuild on the build server I can see that it is able to fire up TextTemplate.exe and look to generate files, the problem is that it never finds the files to transform.
I have managed to reproduce the same behavior on my local machine when executing the same build script as is run on TeamCity.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<Configuration>Release</Configuration>
<TransformOnBuild>true</TransformOnBuild>
<TransformFile>T4MVC\T4MVC.tt</TransformFile>
<OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
</PropertyGroup>
<ItemGroup>
<None Include="T4MVC\T4MVC.tt">
<OutputFilePath>$(MSBuildProjectDirectory)\T4MVC</OutputFilePath>
</None>
</ItemGroup>
<ItemGroup>
<ProjectsToBuild Include="**\*proj" Exclude="ThemeGenerator\**" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" />
<Target Name="Clean">
<ItemGroup>
<BinFiles Include="*\bin\*.*" />
</ItemGroup>
<Delete Files="#(BinFiles)" />
</Target>
<Target Name="Build" DependsOnTargets="Clean;Transform">
<MSBuild Projects="#(ProjectsToBuild)"
ContinueOnError="false"
Properties="Configuration=$(Configuration)" />
</Target>
</Project>
When this executes I get the following output from msbuild with /v:diag set:
Building with tools version "4.0".
Target "CreateCandidateT4ItemList: (TargetId:2)" in file "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" from project "C:\TeamCity\buildAgent\work\daad348639a87062\Project_Build.xml" (target "Transform" depends on it):
Using "Message" task from assembly "Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
Task "Message" (TaskId:2)
Creating a list of candidate items that might need to be processed by T4 items (TaskId:2)
Done executing task "Message". (TaskId:2)
Using "CreateItem" task from assembly "Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
Task "CreateItem" (TaskId:3)
Done executing task "CreateItem". (TaskId:3)
Done building target "CreateCandidateT4ItemList" in project "Project_Build.xml".: (TargetId:2)
Target "SelectItemsForTransform: (TargetId:3)" in file "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemp
lating.targets" from project "C:\TeamCity\buildAgent\work\daad348639a87062\Project_Build.xml" (target "Transform" depends on it):
Task "Error" skipped, due to false condition; ($(TransformFile)=='') was evaluated as (C:\TeamCity\buildAgent\work\daad348639a87062\T4MVC\T4MVC.tt=='').
Initializing task factory "CodeTaskFactory" from assembly "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll".
Using "FilterCandidatesBasedOnItemSpec" task from the task factory "Code Task Factory".
Task "FilterCandidatesBasedOnItemSpec" (TaskId:4)
Done executing task "FilterCandidatesBasedOnItemSpec". (TaskId:4)
Done building target "SelectItemsForTransform" in project "Project_Build.xml".: (TargetId:3)
Target "CreateT4ItemLists: (TargetId:4)" in file "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" from project "C:\TeamCity\buildAgent\work\daad348639a87062\Project_Build.xml" (target "ExecuteTransformations" depends on it):
Task "Message" (TaskId:5)
Creating T4 items lists for project ()... (TaskId:5)
Done executing task "Message". (TaskId:5)
Done building target "CreateT4ItemLists" in project "Project_Build.xml".: (TargetId:4)
Target "ExecuteTransformations: (TargetId:5)" in file "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets" from project "C:\TeamCity\buildAgent\work\daad348639a87062\Project_Build.xml" (target "Transform" depends on it):
Using "TransformTemplates" task from assembly "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.Build.Tasks.dll".
Task "TransformTemplates" (TaskId:6)
Directive processors: (TaskId:6)
{none} (TaskId:6)
(TaskId:6)
Include folders: (TaskId:6)
{none} (TaskId:6)
(TaskId:6)
Assembly references: (TaskId:6)
{none} (TaskId:6)
(TaskId:6)
Reference paths: (TaskId:6)
{none} (TaskId:6)
(TaskId:6)
Parameter values: (TaskId:6)
{none} (TaskId:6)
(TaskId:6)
Full list of templates passed in : (TaskId:6)
{none} (TaskId:6)
(TaskId:6)
Performing full T4 transformation (TaskId:6)
MinimalRebuildFromTracking = True (TaskId:6)
forcedRebuildRequired = False (TaskId:6)
\tTrackerLogDirectory = <null> (TaskId:6)
Tracking is disabled. TrackerLogDirectory has not been specified (TaskId:6)
Done executing task "TransformTemplates". (TaskId:6)
Using "PreprocessTemplates" task from assembly "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.Build.Tasks.dll".
Task "PreprocessTemplates" (TaskId:7)
Directive processors: (TaskId:7)
{none} (TaskId:7)
(TaskId:7)
Include folders: (TaskId:7)
{none} (TaskId:7)
(TaskId:7)
Assembly references: (TaskId:7)
{none} (TaskId:7)
(TaskId:7)
Reference paths: (TaskId:7)
{none} (TaskId:7)
(TaskId:7)
Parameter values: (TaskId:7)
{none} (TaskId:7)
(TaskId:7)
Full list of templates passed in : (TaskId:7)
{none} (TaskId:7)
(TaskId:7)
Performing full T4 preprocessing (TaskId:7)
MinimalRebuildFromTracking = True (TaskId:7)
forcedRebuildRequired = False (TaskId:7)
\tTrackerLogDirectory = <null> (TaskId:7)
Tracking is disabled. TrackerLogDirectory has not been specified (TaskId:7)
Done executing task "PreprocessTemplates". (TaskId:7)
It would appear that on the build server T4 seems unable to find the projects that it needs to reference to generate the necessary classes. I have tried various combinations of input folders and assembly references but see unable to get T4 to "see" the files it needs.
Does anybody have any ideas how to resolve this?
Frankly, I'm not sure that you can get that to work at all because T4MVC needs the VS host in order to access the DTE object model. See this related thread: Using T4MVC with build script
If David Ebbo is right, run VS (devenv.exe) from command line on your build server.
For example you can't build .vdproj installer projects using msbuild too, so we are running VS from command line on the build server to build the installers...
Related
This toy project doesn't have working incremental build:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<Timestamp>$([System.DateTime]::Now.ToString("yyyy-MM-dd\THHmmss"))</Timestamp>
</PropertyGroup>
<ItemGroup>
<MyInputs Include="myinput.txt" />
<MyOutput Include="myoutput.txt" />
</ItemGroup>
<Target
Name="test_BeforeTargets_BeforeBuild"
BeforeTargets="BeforeBuild"
Inputs="#(MyInputs)"
Outputs="#(MyOutput)"
>
<Message Text="test_BeforeTargets_BeforeBuild" Importance="high" />
<WriteLinestoFile File="myoutput.txt" Lines="$(Timestamp)" Overwrite="true" />
</Target>
</Project>
There are 3 build outcomes that I've noticed in Visual Studio:
When myinput.txt and the .csproj files are modified I get my desired outcome:
1>Target "test_BeforeTargets_BeforeBuild" in file "C:\Users\dan\source\repos\TestMSBuild\TestMSBuild.csproj":
1> Building target "test_BeforeTargets_BeforeBuild" completely.
1> Input file "myinput.txt" is newer than output file "myoutput.txt".
1> Task "Message"
1> Task Parameter:Text=test_BeforeTargets_BeforeBuild
1> Task Parameter:Importance=high
1> test_BeforeTargets_BeforeBuild
1> Done executing task "Message".
1> Task "WriteLinestoFile"
1> Task Parameter:File=myoutput.txt
1> Task Parameter:Lines=2019-02-21T163909
1> Task Parameter:Overwrite=True
1> Done executing task "WriteLinestoFile".
1>Done building target "test_BeforeTargets_BeforeBuild" in project "TestMSBuild.csproj".
When myinput.txt is not modified, but the .csproj is. I get the expected skipping of the target:
1>Target "test_BeforeTargets_BeforeBuild" in file "C:\Users\dan\source\repos\TestMSBuild\TestMSBuild.csproj":
1> Skipping target "test_BeforeTargets_BeforeBuild" because all output files are up-to-date with respect to the input files.
1> Input files: myinput.txt
1> Output files: myoutput.txt
1>Done building target "test_BeforeTargets_BeforeBuild" in project "TestMSBuild.csproj".
If I build twice without modifying anything, then modify only myinput.txt, I get a one-liner output, no matter how many times I try to build:
========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
I expected that when I modify myinput.txt only, the target will not be skipped. Currently, this is only true if I also modify the .csproj file at the same time.
The following variations of BeforeTargets & AfterTargets were tried but to no avail:
BeforeTargets="BeforeBuild" (as above)
BeforeTargets="Build"
AfterTargets="BeforeBuild"
AfterTargets="Build"
I've only tried .NET-Core (Microsoft.NET.Sdk) and ASP.NET-Core (Microsoft.NET.Sdk.Razor & Microsoft.NET.Sdk.Web) projects but both have the same result.
Question:
How can I get this toy project working?
While the MSBuild-based up-to-date check works as expected, there is also an additional up-to-date check performed Visual Studio to determine if it should call MSBuild or not. Since it doesn't know about your input file, it determines that there is no need to run MSBuild on that project.
This can be changed by telling VS about it using the UpToDateCheckInput and UpToDateCheckOutput items that the project system uses for this check:
<ItemGroup>
<UpToDateCheckInput Include="#(MyInputs)" />
<UpToDateCheckOutput Include="#(MyOutputs)" />
</ItemGroup>
I want to use msbuild /restore with my project file. However, my project file is more like a script which orchestrates building multiple projects with particular properties, etc. Thus, it doesn’t make sense for me to set Sdk="Microsoft.NET.Sdk" because that causes weird errors to show up. However, if I don’t specify the Sdk, the /restore is ignored and it fails to actually restore anything.
Here is my example standalone project:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="RoslynCodeTaskFactory" Version="2.0.7" />
</ItemGroup>
<Target Name="Build">
<HelloWorld/>
</Target>
<UsingTask AssemblyFile="$(RoslynCodeTaskFactory)" Condition="'$(RoslynCodeTaskFactory)' != ''" TaskFactory="CodeTaskFactory" TaskName="HelloWorld">
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
Console.WriteLine("Hello, world!");
]]>
</Code>
</Task>
</UsingTask>
</Project>
My invocation and output:
C:\Users\binki\AppData\Local\Temp>"\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64\MSBuild.exe" /restore helloworld.proj
Microsoft (R) Build Engine version 15.7.177.53362 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 2018-05-15 01:23:28.
Project "C:\Users\binki\AppData\Local\Temp\helloworld.proj" on node 1 (default targets).
C:\Users\binki\AppData\Local\Temp\helloworld.proj(8,5): error MSB4036: The "HelloWorld" task was not found. Check the following: 1.) The name of the task in the project file is the same as the name of the task class. 2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is correctly declared with <UsingTask> in the project file, or in the *.tasks files located in the "C:\Program Files 9x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64" directory.
Done Building Project "C:\Users\binki\AppData\Local\Temp\helloworld.proj" (default targets) -- FAILED.
Build FAILED.
"C:\Users\binki\AppData\Local\Temp\helloworld.proj" (default target) (1:2) ->
(Build target) ->
C:\Users\binki\AppData\Local\Temp\helloworld.proj(8,5): error MSB4036: The "HelloWorld" task was not found. Check the following: 1.) The name of the task in the project file is the same as the name of the task class. 2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is correctly declared with <UsingTask> in the project file, or in the *.tasks files located in the "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64" directory.
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:01.71
I have a line of code that I got from a site called Zetcode, and in this to build the first example, I compile the code like this:
gmcs -r:System.Windows.Forms.dll -r:System.Drawing.dll 01-simple-cs-example.cs -out:simple-sample.exe
This builds the exe that draws my window, but I don't think my csproj file is correct.
<Project DefaultTargest="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- This Property will make a variable named MSBuildSample, then you can use it to
assign to whatever in the script.
Properties are variables inside the script.
-->
<SrcPath>src\</SrcPath>
<AssemblyName>01-simple-cs-example</AssemblyName>
<OutputPath>bin\</OutputPath>
</PropertyGroup>
<ItemGroup>
<!-- This Compile statement, gathers all the source files listed in an item called Compiled
ItemGroups interact with the source code.
-->
<Compile Include="$(SrcPath)01-simple-cs-example.cs" />
</ItemGroup>
<!-- In the Build target, the Inputs and Outputs targets which looks to see if the files have been updated,
or if the files are existent. If the files have not been changed, then the Build target is skipped.
-->
<Target Name="Build" Inputs="#(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe" >
<!-- The MakeDir directive will create the directory in the property group above, if it meets the
condition stated in the Condition= statement.
-->
<Message Text="Creating the output path $(OutputPath)." />
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
<!-- This Csc is the .NET C# compiler, which then uses the ItemGroup of collected sources called, Compile
-->
<Message Text="Compiling the source code." />
<Csc Sources="#(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
</Target>
</Project>
This is the result from trying to run xbuild, and msbuild.
C:\Users\User01\Dropbox\programming\csharp\zetcode-csharp-winforms\01-simple-cs-example>xbuild
XBuild Engine Version 3.3.0.0
Mono, Version 3.3.0.0
Copyright (C) Marek Sieradzki 2005-2008, Novell 2008-2011.
Build started 7/25/2014 2:47:41 PM.
__________________________________________________
Project "C:\Users\User01\Dropbox\programming\csharp\zetcode-csharp-winforms\01-simple-cs-example\01-simple-cs-example.csproj" (default target(s)):
Target Build:
Created directory "bin\"
Tool C:\mono\Mono-3.2.3\bin\gmcs.bat execution started with arguments: /out:bin\01-simple-cs-example.exe src\01-simple-cs-example.cs
src\01-simple-cs-example.cs(1,22): error CS0234: The type or namespace name `Forms' does not exist in the namespace `System.Windows'. Are you missing `System.Windows.Forms' assembly reference?
src\01-simple-cs-example.cs(2,14): error CS0234: The type or namespace name `Drawing' does not exist in the namespace `System'. Are you missing `System.Drawing' assembly reference?
src\01-simple-cs-example.cs(4,23): error CS0246: The type or namespace name `Form' could not be found. Are you missing an assembly reference?
Task "Csc" execution -- FAILED
Done building target "Build" in project "C:\Users\User01\Dropbox\programming\csharp\zetcode-csharp-winforms\01-simple-cs-example\01-simple-cs-example.csproj".-- FAILED
Done building project "C:\Users\User01\Dropbox\programming\csharp\zetcode-csharp-winforms\01-simple-cs-example\01-simple-cs-example.csproj".-- FAILED
Build FAILED.
Errors:
C:\Users\User01\Dropbox\programming\csharp\zetcode-csharp-winforms\01-simple-cs-example\01-simple-cs-example.csproj (default targets) ->
(Build target) ->
src\01-simple-cs-example.cs(1,22): error CS0234: The type or namespace name `Forms' does not exist in the namespace `System.Windows'. Are you missing `System.Windows.Forms' assembly reference?
src\01-simple-cs-example.cs(2,14): error CS0234: The type or namespace name `Drawing' does not exist in the namespace `System'. Are you missing `System.Drawing' assembly reference?
src\01-simple-cs-example.cs(4,23): error CS0246: The type or namespace name `Form' could not be found. Are you missing an assembly reference?
0 Warning(s)
3 Error(s)
Time Elapsed 00:00:01.5341534
This is the result from the MSBuild run. MSBuild completed successfully, but I imagine that's because MSBuild knows where to look without me having to specify it in the csproj file.
C:\Users\User01\Dropbox\programming\csharp\zetcode-csharp-winforms\01-simple-cs-example>MSBuild
Microsoft (R) Build Engine version 4.0.30319.18408
[Microsoft .NET Framework, version 4.0.30319.18444]
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 7/25/2014 2:48:04 PM.
Project "C:\Users\User01\Dropbox\programming\csharp\zetcode-csharp-winforms\01-simple-cs-example\01-simple-cs-example.csproj" on node 1 (default targets).
Build:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\Csc.exe /out:bin\01-simple-cs-example.exe src\01-simple-cs-example.cs
Done Building Project "C:\Users\User01\Dropbox\programming\csharp\zetcode-csharp-winforms\01-simple-cs-example\01-simple-cs-example.csproj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:04.36
I don't know what to put into the csproj file to make it load those DLL's that I used in the command line to compile using gmcs. Any clues?
-- EDIT 2014-08-20 --
After using the answer from knocte, I was able to see how the References are added in a csproj file. Its as simple as adding an item group, and adding the References you listed with using in the C# source file.
<ItemGroup>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Drawing" />
<Reference Include="System" />
</ItemGroup>
This is the manual way to do it if you're building the csproj file manually.
Just use an IDE (MonoDevelop or Visual Studio) to add a GAC-reference to System.Windows.Forms and System.Drawing libraries.
I'm stuck with a problem I want to create each days build in different folders means if the build is created on 17/5/2013 I want the build in a folder named 17/05/2013 and so on How can I achieve that
With MSBUILD 4 you can use Property Functions to construct a custom output folder.
In C# this would generate the folder name:
System.DateTime.Today.ToString("MM/dd/yyyy");
Using that same logic in MSBUILD
<Target Name="DateStampTest">
<PropertyGroup>
<OutputRoot>$(MSBuildThisFileDirectory)</OutputRoot>
<DateTimeStamp>$([System.DateTime]::Today.ToString("yyyy.dd.MM"))</DateTimeStamp>
</PropertyGroup>
<ItemGroup>
</ItemGroup>
<Message Text="Override the output folder with: '$(OutputRoot)$(DateTimeStamp)'" />
</Target>
Saved this to a project file in "C:\Test\" and running msbuild /t:DateStampTest gives us the following output:
1>Project "C:\Test\" on node 1 (target1 target(s)).
1>Target1:
Override the output folder with: 'C:\Test\2013.17.05'
1>Done Building Project "C:\Test\" (target1 target(s)).
Scripts.xml:
<UsingTask
TaskName="CompressorTask"
AssemblyFile="Yahoo.Yui.Compressor.dll" />
<PropertyGroup>
<JavaScriptOutputFile Condition=" '$(JavaScriptOutputFile)'=='' ">..\..\site.com\javascript\offerta.min.js</JavaScriptOutputFile>
</PropertyGroup>
<Target Name="ScriptTask">
<ItemGroup>
<JavaScriptFiles Include="..\..\site.com\javascript\offerta.js"/>
</ItemGroup>
<CompressorTask
JavaScriptFiles="#(JavaScriptFiles)"
ObfuscateJavaScript="True"
PreserveAllSemicolons="True"
DisableOptimizations="False"
EncodingType="utf-8"
DeleteJavaScriptFiles="false"
LineBreakPosition="-1"
JavaScriptOutputFile="$(JavaScriptOutputFile)"
LoggingType="HardcoreBringItOn"
ThreadCulture="en-us"
IsEvalIgnored="false" />
</Target>
I run it using a bat file:
C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe Scripts.xml
pause
I'm getting:
"F:\Checkouts\Offerta\trunk\build\site.com\Scripts.xml" (default target) (1)
->
(ScriptTask target) ->
F:\Checkouts\Offerta\trunk\build\site.com\Scripts.xml(16,7): error MSB4036:
The "CompressorTask" task was not found. Check the following: 1.) The name of
the task in the project file is the same as the name of the task class. 2.) The
task class is "public" and implements the Microsoft.Build.Framework.ITask inte
rface. 3.) The task is correctly declared with in the project file,
or in the *.tasks files located in the "C:\Windows\Microsoft.NET\Framework\v2.
0.50727" directory.
What am I doing wrong? I'm using Yahoo.Yui.Compressor v1.6.0.0.zip (for .NET 3.5). Why is msbuild reporting "C:\Windows\Microsoft.NET\Framework\v2.0.50727" when I explicity run C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe?
Use Yahoo.Yui.Compressor.MsBuildTask.dll version 1.6.0.1
Unfortunaltelly this version is available only via Nuget Library
Details at: http://yuicompressor.codeplex.com/discussions/272802