One of my initial requirements for templating engine is that I'm able to keep the 'raw' template files (in the case .tt files) 'outside' of the library executing/transforming them with the intended purpose of allowing a developer using said library to make small adjustments to the templates if necessary depending on the requirements of what they need generated.
The library is written in C# and so far the only way I've been able to get them to work is by using default 'pre-compiled' C# class automatically generated for each template by Visual Studio. I've had some success using the "TextTransform.exe" application to convert the .tt file directly to its intended output but this seems crude compared to a more native in code approach.
So is what I'm asking to do reasonable or did I flat out pick the wrong template engine to use for my needs? Any help is greatly appreciated.
Have exactly same situation - set of T4 templates outside the main project.
But it a bit more complicated - I have some T4 templates generated on the fly.
I do try following options:
batch (with half-manual scripting) compilation of T4 to CS and CS to DLL;
side routine which scan given directory for T4 template and build *.csproj & *.sln for directory;
using Visual Studio to manage and build a DLL with T4 templates.
All of those works fine, but currently I switch to the last one.
There is a reason:
I do debug T4 templates in Visual Studio in usual way.
I have (using T4Toolbox) highlighted T4 syntax.
I can easily manage compilation time.
To get all of the templates in project to be recompiled prior the main Build require only 5 lines to be added at the end of the *.csproj file:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\TextTemplating\Microsoft.TextTemplating.targets" />
<PropertyGroup>
<TransformOnBuild>true</TransformOnBuild>
<TransformOutOfDateOnly>false</TransformOutOfDateOnly>
</PropertyGroup>
That's all.
After this you keep your 'raw' templates wherever you need them, organize them as normal items in DLL-type project and have an actual copy on each build.
P.S. Actual mean that if somebody change them outside the Visual Studio (in Notepad for example) you will have them all recompiled. This manageable by TransformOutOfDateOnly.
P.P.S. Have one problem with this - can't properly substitute CustomToolNamespace.
Related
In a .xaml file as soon as I add a new control, I am able to reference it for the xaml.cs file because VS is kind enough the generate the C# code for it in a g.i.cs file.
For example
In MainWindow.xaml I add
<Grid>
<Button x:Name="Test"/>
</Grid>
I am able to access it from MainWindow.xaml.cs like
this.Test.Content = "TestButton";
Because VS generated MainWindow.g.i.cs in the obj folder which contains
internal System.Windows.Controls.Button Test;
I have been able to have exactly the same behavior using msbuild for a custom file .xyz which is a designer view for a .cs file. I've have created a msbuild target that regenerates the .cs files on build and on project load but I'm not able to do the same thing on file save
Now my questions:
How does VS regenerate the g.i.cs on save ?
Is this a VS feature or an msbuild one ?
Can I trigger an incremental build on save?
Update:
I've also looked through a WPF .csproj and it uses the same .targets files as a class library C# project. The only differences I could spot are the DependentUpon and the SubType item metadata
How does VS regenerate the g.i.cs on save ?
AFAIK, Visual Studio invoke the XAML compiler xamlc.exe to compile the XAML files regenerate the g.i.cs on save.
Check this blog Understanding In and Out of XAML in WPF:
In the blog, the author said that compilation of XAML happened in 2 steps:
Step 1. The first step is to compile the XAML files into BAML using the xamlc.exe compiler. For example, if our project includes a file name Window1.xaml, the compiler will create a temporary file named Window1.baml and place it in the obj\Debug subfolder (in our project folder). At the same time, a partial class is created for our window, using the language of our choice. For example, if we’re using C#, the compiler will create a file named Window1.g.cs in the obj\Debug folder. The g stands for generated.
Step 2. When the XAML-to-BAML compilation stage is finished, Visual
Studio uses the appropriate language compiler to compile our code and
the generated partial class files. In the case of a C# application,
it’s the csc.exe compiler that handles this task. The compiled code
becomes a single assembly Window1.exe) and the BAML for each window is
embedded as a separate resource.
.
Is this a VS feature or an msbuild one?
This should be Visual Studio feature. As I said above, Visual Studio invoke the XAML compiler xamlc.exe to compile the .xaml files on save. Visual Studio will invoke MSBuild to compile the those file to .exe/.dll on build. Besides, when you on save not build the project, you can open your Task Manager, there is no MSBuild.exe exists, only when you build the project, it will comes up. So this should be Visual Studio feature not MSBuild on save.
Can I trigger an incremental build on save?
In the Visual Studio, the build system provides support for incremental builds. But if you want trigger an incremental build with your a custom MSBuild file .xyz, I am afraid you could not do that, because MSBuild only works on Build not save.
The [!INCLUDETLA2#tla_wpf] build system provides support for incremental builds. It is fairly intelligent about detecting changes made to markup or code, and it compiles only those artifacts affected by the change. The incremental build mechanism uses the following files
Check the Building a WPF Application (WPF) for more details.
Hope this helps.
So I'm having some trouble creating an item template and would like some help.
What I'm trying to do:
Create a template that adds 3 files. A Class.cs and two config files in the location "./Config/Acc/Config.xml" and "./Config/Prod/Config.xml".
I've managed to create the template through the wizard and editing the resulting files, but I would like an easy method of distributing the template on my teams TFS.
From some googling it seems that I should use A VSIX project to deply this easily. Problem is that I can't get it to compile. I have 2 projects: VSIXproject and ItemTemplateProject. I've set the assembly info on VSIX project to use the ItemTemplateProject and I've modified my Class.cs, but when I compile, visual studio doesn't know how to handle the Class.cs file.
What am I doing wrong? Is there a better way of including my ItemTemplate so that anyone who pulls the repo can use it?
The template project (a project that only contains Visual Studio project templates or item templates) is only used to be able to work with templates. Its output (say [myproject].dll) is not important (the project type may be C# but it's irrelevant) and you will only distribute the .vsix file in the end.
Files (.vstemplate files and any other files) in this project are like "static" files. They will also ultimately be included into the .vsix file output during build.
So, to ensure this files (.cs or other) are "static", you must make sure they have their action set to None (for example), not Compile.
I have a C# solution with an Antlr3 grammar file, and I'm trying to upgrade to Anltr4. It turns out the grammar was the easy part (it became better, and one third the size!). Generating the parser turned out to be the tricky part.
In the old solution I merely ran AntlrWorks to update the lexer and parser .cs files when the grammar file changed. The lexer and parser were included directly in the same project as the grammar so the framework around the parser could make use of them directly.
With the Antlr4 targets for C# I noticed that (at least by default) the output path of the generated Parser C# classes is in the intermediate directory, e.g. obj\Debug. This means I can't use the parser directly in the same project. Am I supposed to change the output path if I want the generated source usable in my sln? Don't I want it in my sln?
I tried making a separate project for the parser generation, that is, a project containing only the grammar file. When this project is built using the Antlr4 targets, the resulting assembly can be referenced from projects needing the parser classes. However, if this project is included in the solution I still don't get any intellisense in visual studio since it bases its intellisense on source files for loaded projects, so it is still not quite usable. The only way I could get it working properly was to build then unload the parser project, and have other projects reference it as an assembly file rather than a project.
EDIT:
After looking on the antlr-interest list I found this thread indicating that the problem with intellisense may be Resharpers fault. If this is the case, then my question is rather how to keep using both Antlr4 and Resharper in my solution?
https://groups.google.com/forum/#!topic/antlr-discussion/QSuJXphaBDg
I found an extension for Resharper: ReSharper.ExternalCode.
Tip for Antlr: add obj\Debug in Resharper -> Code Inspection -> External Code and reload solution.
It's works for me.
There is an easy way to get the best of both Antlr 4 and Visual Studio. You are on the right track in having a separate grammar project and implementation project, but you are missing a couple steps.
Follow these steps to get the Intellisense working
In Visual Studio, go to Tools -> Extensions and Updates and search the Online section for "ANTLR Language Support" by Sam Harwell.
This does a few things:
Adds Templates for the combined grammars.
Adds Syntax Highlighting
Adds an MSBuild target for the grammar to generate the parser.
In your solution, set up your project structure like this:
Solution
Grammar Project
ANTLR 4 Combined Grammar
Implementation Project
Folder for Links to Generated files
Listener Implementation Class
Write and Compile your grammar.
In your folder for the Links to Generated Files, Right-Click the folder and click Add -> Existing Item
Browse to Grammar Project\obj\Debug and select all the generated parser files.
This next step is important. On the Add button there is a little drop-down arrow. Click the drop-down arrow and click "Add As Link".
This will add the generated files to the implementation project using a symbolic link instead of a direct copy.
This gives the added benefit of not having to remove and re-add the parser files if you have to change your grammar later.
Intellisense should work now for your generated parser classes, and you don't
even have to disable ReSharper.
You are encountering a known bug with ReSharper. The ANTLR 3 and ANTLR 4 C# build integration is reliable, and uses long-established patterns that Microsoft uses with other languages and code generation tasks. Your options are:
Stop using ReSharper
Get the ReSharper authors to address the lack of support for this feature, or
Modify the ANTLR 4 target to work around the limitation in ReSharper, which will introduce other problems into the build which may or may not be acceptable for your use.
Option 1 is certainly the least expensive, and most likely to provide reliable long-term support for your projects.
When using Visual Stdio 2008, you can make a C++ project build with an internal tool rather than having the IDE invoke MSVC directly. This improves the consistency of builds across platforms if a cross-platform build system is used.
However, I cannot figure out how to do the same as a C# project. It would be possible to simply register it as a native project with C# sources, however, you lose some of the advantages gained through having a C# project. More importantly, it will mean that allowing a project to build both directly and with an external tool (which is sadly necessary) will require two separate projects, rather than merely creating an alternate build configuration to invoke the external tool.
Does anyone know if it's possible to prevent Visual Studio from invoking csc by itself and instead call an external tool?
EDIT: Apparently there has some misunderstanding. The goal here is not to compile anything outside of Visual Studio. Instead, it's to allow Visual Studio to serve as the IDE but not the build system. There is already a (Scons-based) build system capable of compiling the C# and C++ sources, and Visual Studio has been configured to invoke Scons for compilation of C++ projects. I'm trying to configure it so that when you hit the 'Build' button, it will invoke Scons for the C# projects as well as the C++ ones.
Edit: Your question is still answered using MSBuild(if you are simply looking to compile outside the IDE). The IDE(Visual Studios) is simply a "fancy" way of constructing the build files that are built by MSBuild. Visual Studios isn't building the files, it simply is invoking MSBuild which ships with the .NET Framework 2.0 and up which compiles your code based on the project file that you create. If Scons can read and process an MSBuild file then I'm sure you can invoke it to build your project. But considering the fact that C# is a Microsoft language, I think you will be hard-pressed to find a value-add in not using MSBuild since I'd assume both the language and build tool are very tuned to work together. - End Edit
You can use MSBuild to compile your C# project. If you open your .csproj file in a text editor you will see that it is a MSBuild file. If you want to write some C# outside of the IDE you can construct a build file using the .csproj file as a starting point and invoke MSBuild to compile your apps. The IDE is just a way of abstracting the editing of the MSBuild file away for you.
If you are really industrious you can create a set of custom tasks to do things in your custom build process like move files around and versioning. MSBuild Community Tasks are a great example of using custom code to do task for you during MSBuild.
Given all the other answers, what MSBuild does when either VS or MSBuild perform a build can be found in the Targets files that ship with .Net. These can be be found in the FrameWork directory on your system. In my case:
C:\Windows\Microsoft.NET\Framework64\v3.5
Contains Microsoft.Common.targets among others. This file contains the following snippit:
<!--
============================================================
Build
The main build entry point.
============================================================
-->
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
<Target
Name="Build"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(BuildDependsOn)"
Outputs="$(TargetPath)"/>
This means that redifining this Target you can make MSBuild an VS do anything you want. The top of the mentioned file contains an important messagge:
Microsoft.Common.targets
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
This file defines the steps in the standard build process for .NET projects. It
contains all the steps that are common among the different .NET languages, such as
Visual Basic, C#, and Visual J#.
My suggestion would be to read all you can about MSBuild and it's build file syntax and try redifining the Build target in your project(s). My impression is that after reading up on MSBuild you'll probably find an easier way to meet your requierements. You can find an example of redifining a Target like this in one of the answers of this so question .
Edit:
How to redefine a target?
Redefining is essentially defining the same target 'after' it has been defined. So for instance in your .*proj file(s) define a Build Task after the <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> line that imports all targets needed to in this case build a C# project. An example could be
<Target
Name="Build"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="BeforeBuild"
Outputs="$(TargetPath)">
<Exec Command="nmake" />
</Target>
I found a question in the same direction here, where it is suggested to edit the registry. I am pretty sure there is no other way to change the compiler used by Visual Studio because there is no trace of csc.exe in any solution, config, csproj file or whatsoever, nor in the Visual Studio 9.0 folder / subfolders within the Program Files dir.
Registry locations can be found in:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\74ACAA9F1F0087E4882A06A5E18D7D32
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\9055DA7481CC1024CB23A6109FD8FC9B
but those keys may differ dependng on your installation. Conclusion: changing the compiler used by VS seems next to impossible.
Addition: The following MSDN article deals with the same question for an custom C++ compiler, and Ed Dore's answer seems to confirm my theory that there's no way to choose an custom compiler for use within VS.
Under 'Tools' > 'External Tools' you should be able to define an outside tool to do activities for you. The Command should be the path to the executible for your external tool.
Hope this helps some.
You don't have to maintain different project files to build using an external tool. MSBuild is designed to build using the same project files that Visual Studio uses.
Here's an article that describes it.
Customize Your Builds in Visual Studio Using the Standalone MSBuild Tool
It's for VS2005, but should apply to VS2008 as well.
Looking through the answers, it seems clear to me that integrating scons into Visual Studio in a way that is compatible with the debugger and so on is not going to happen...
An option you might to consider, and I understand you don't want to change build systems, but bear with me, is to use a meta-build system, ie 'cmake'. http://www.cmake.org/
Cmake doeesn't actually build the project. What it does is to create build files for you, that you can use to build the project, and on Windows, the build files it creates for you are: Visual Studio project files. You can simply load those directly into your IDE, and compile, and use normally!
CMake is I feel very easy to use, and provides a high level of transparence and maintainability.
The exact same CMakeLists.txt files on linux will causes linux makefiles to be generated.
On mingw, they can generate mingw makefiles.
There are numerous generators available within cmake. The list is here:
http://www.cmake.org/cmake/help/cmake-2-8-docs.html#section_Generators
http://springrts.com is a huge opensource rts game that used to use scons as its cross-platform build system and now uses cmake.
I understand that you don't really want to have to change build systems, so it is a medium to long term solution.
Cmake is in any case one more option, to add to those of using a custom build tool, or using msbuild, or running the scons build from the commandline by hand.
Edit your project file and update the CscToolPath keys to point to the directory containing your tool and add CscToolExe keys that holds the name of the directory:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|.NET 3.5' ">
.
.
.
<CscToolPath>path\to\custom\tool\directory</CscToolPath>
<CscToolExe>exe name</CscToolExe>
.
.
.
</PropertyGroup>
I have not tested this, and the CscToolExe key may cause problems, in which case I would simply rename the external tool executable to "csc.exe".
You can build your solution from the command line like this:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>msbuild.exe "C:\path\Your Solution.sln"
In C++ projects there is the possibility to set a custom build step for files. Is there a similar functionality in C# projects? I couldn't really find anything.
One idea would be to create a second project (makefile or c++) and move the files there.
MsBuild should work for you although it might take some time to figure out how it works. It appears that you can setup a step that runs prior to building each .cs file by separating each .cs file into its own build group.
In MSBuild script for compiling each .cs file into an EXE, Dino Chiesa comments:
By using the %(CSFile.identity)
scalar, we run this task once for each
file. The converse would be
#(CSFile.identity). That would run
the compile once, for all files,
compiling them all together into a
single assembly.
Also, these links might help:
Custom build step for C# files
Master Complex Builds with MSBuild
No custom build step for individual files with C# projects. You could probably hack something together with MSBuild...
Look at the BeforeBuild and AfterBuild targets in your csproj file.
I think you are on the right track with your comment about multiple projects. Combine this with the fact that you can include multiple projects within a single Solution and you may have your answer. I use this functionality to build several components at a time and it works quite well.