Exclude non minified java script from release build - ajax

I have a .NET library which provides some AJAX controls. The library is build with Visual Studio 2008. The ajax minifier task is used to auto generate minified javascript files.
In a debug build I need the original javascript files for debugging the javascript, but in a release build these have no usage.
What would you recommend? Ignore them in the release and let them blow up the file size? Would there be a penality in loading time? Or would you remove them from the release build? How? I could modify the project file and add a condition attribute. But this does not well integrate in Visual Studio.
EDIT:
To clearify: The primary question is: What are the arguments for including and excluding the non minified files.
UPDATE:
Just found a solution a nice solution for the auto exclusion. Hers a part of my project file:
<ItemGroup>
<EmbeddedJavascript Include="MyJavascript.debug.js" />
<EmbeddedResource Include="MyJavascript.js" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<Target Name="BeforeBuild">
<ItemGroup Condition=" '$(Configuration)' != 'Release' ">
<EmbeddedResource Include="#(EmbeddedJavascript)" />
</ItemGroup>
<AjaxMin JsSourceFiles="#(EmbeddedJavascript)" JsSourceExtensionPattern="\.debug\.js$" JsTargetExtension=".js" />
</Target>

Related

Visual Studio project with a custom build step only (no default build)

I want to create a Visual Studio project that would allow me to see a bunch of JavaScript and other files and edit them as normal, but would also have a build step that can run any custom commands I want (currently some npm commands, possibly more later). Basically I want 3 features combined:
Be able to browse and edit files just like for any VS project (C#, C++, etc.)
Be able to run a custom build step by selecting "Build" in Visual Studio (including building the whole solution).
Be able to run that same custom build step from the command line (MSBuild).
Using a "shared project" (.shproj) allows me to easily see and edit the files, but there is no Build item in the context menu, even if I manually add a Build target:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>...</ProjectGuid>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
<Import Project="MyItems.projitems" Label="Shared" />
<PropertyGroup>
<Configuration>Debug</Configuration>
<Platform>Any CPU</Platform>
</PropertyGroup>
<Target Name="Build">
<Exec Command="ECHO My custom build!" />
</Target>
</Project>
I've also tried using a stripped-down VC++ project (since I don't actually want to run the C++ compiler) and this allows a build to be run from VS, but opening the project logs warnings like error MSB4057: The target "GetProjectDirectories" does not exist in the project. and trying to add files to fails with that error or similar ones.
There must be an easier way to do this!
From your current description, I think you want to create a js project in VS IDE.
However, VS IDE has the node js project template by default. And you should install the workload Node.js development under VS_Installer so that you can use it.
After that, you can create such project.
1) Adding js files or other files by right-click on the project-->Add-->Existing Item so that you can modify the files on VS IDE.
2) If you want to execute a custom build step that does not break the whole build, you should make the custom target depends on the default build.
You can use this:
<Target Name="CustomStep" AfterTargets="Build">
<Exec Command="ECHO My custom build!" />
</Target>
or
<Target Name="CustomStep" BeforeTargets="Build">
<Exec Command="ECHO My custom build!" />
</Target>
Note: If you use
<Target Name="Build">
<Exec Command="ECHO My custom build!" />
</Target>
It will overwrite the system build process and instead, run the command, which breaks the whole default build.
3) If you want to execute the custom build on msbuild command, you should specify the name of the custom target:
msbuild xxx\xxx.proj -t: CustomStep(the name of the custom target)
===============================================
Besides, if you still want to use C++ project template, you could create a empty c++ project which does not contain any clcompile files and then do the same steps.
If you do not want to use C++ compiler, you should only remove any xml node on the vcxproj file like these:
<ClCompile Include="xxx.cpp" />
<ClInclude Include="xxx.h" />
When you use the empty C++ project, you do not have to worry about that.
=========================================
Update 1
If you want to build this project on a build sever without VS IDE, I suggest you could install Build Tool for VS2019 which is an independent, lightweight build command line(It is equivalent to dotnet cli).
Build Tool for VS2019
Under All Downloads-->Tools for Visual Studio 2019--> Build Tools for Visual Studio 2019
Then, you have to install the related build workload such as Node.js Build tools and then we can use the command line to build node.js project on build sever.
The entire installation process is fast.
Inspired by Perry Qian-MSFT's answer, I managed to strip down a Node.js project to the bare minimum that I needed to get Visual Studio to load and build it, but without referencing any external files.
The main trick was VS needs a target named "CoreCompile" to be defined to show the Build menu item! (It also needs a "Build" target, but that one is more obvious.)
My project now looks like this:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>(some guid)</ProjectGuid>
<ProjectHome>.</ProjectHome>
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
</PropertyGroup>
<!-- These property groups can be empty, but need to be defined for VS -->
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
</PropertyGroup>
<Import Project="My.Build.targets" />
<!-- Define empty standard MSBuild targets, since this project doesn't have them. Doing it this way allows My.Build.targets to also be used in a project that does define them. -->
<Target Name="Build" />
<Target Name="ReBuild" />
<Target Name="Clean" />
<!-- NOTE: a target named "CoreCompile" is needed for VS to display the Build menu item. -->
<Target Name="CoreCompile" />
<!-- Files shown in Visual Studio - adding and removing these in the UI works as expected -->
<ItemGroup>
<Content Include="myfile..." />
</ItemGroup>
</Project>
And My.Build.targets looks like this:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="MyBuild" AfterTargets="Build">(build steps)</Target>
<Target Name="MyReBuild" AfterTargets="ReBuild">(re-build steps)</Target>
<Target Name="MyClean" AfterTargets="Clean">(clean steps)</Target>
<!-- This target is needed just to suppress "warning NU1503: Skipping restore for project '...'. The project file may be invalid or missing targets
required for restore." -->
<Target Name="_IsProjectRestoreSupported" Returns="#(_ValidProjectsForRestore)">
<ItemGroup>
<_ValidProjectsForRestore Include="$(MSBuildProjectFullPath)" />
</ItemGroup>
</Target>
</Project>

How do I prevent text template generator from running on every VS build?

I have a VS 2019 solution with several projects. There is one project that every other project depends on and I have some T4 templates in that project. The templates are regenerated every time I invoke the Build command (no changes) and therefore all the dependent projects are also rebuilt.
How can I fix this so that the templates are only regenerated when necessary? My project file has the following:
<PropertyGroup>
<TransformOnBuild>true</TransformOnBuild>
<OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
<TransformOutOfDateOnly>true</TransformOutOfDateOnly>
</PropertyGroup>
<Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />
<ItemGroup>
<None Update="Messages\Messages.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Messages.generated.cs</LastGenOutput>
</None>
<EmbeddedResource Update="Messages\Messages.de.resx" />
<EmbeddedResource Update="Messages\Messages.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Messages.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<Target Name="CallTransformOnBuild" BeforeTargets="CoreCompile">
<CallTarget Targets="TransformDuringBuild" />
</Target>
I only want the transform to run on build if:
Messages.Generated.cs doesn't exist
Messages.tt changed
Messages.resx changed
You need to make sure the following XML Tags' are set to false.
<TransformOnBuild>False</TransformOnBuild>
<OverwriteReadOnlyOutputFiles>False</OverwriteReadOnlyOutputFiles>

Include build directory in nuget package using visual studio pack

I'm attempting to create a nupkg with Visual Studio using the built in nuget package building and include the build directory from my project in the nupkg. It seems like it should be a fairly simple task but I can't get it to work. From my googling adding either of these to my csproj file should work, but both create an empty 'build' directory in the nupkg:
<ItemGroup>
<None Include="build\**">
<Pack>true</Pack>
<PackagePath>build\</PackagePath>
<IncludeInPackage>true</IncludeInPackage>
</None>
</ItemGroup>
Using nuget pack to create the package with the following in my nuspec does work:
<files>
<!-- Include everything in \build -->
<file src="build\**" target="build" />
</files>
Include build directory in nuget package using visual studio pack
According to the document Including content in a package, you should use the properties <Pack>true</Pack> and <PackagePath>build\</PackagePath>:
If you want to copy all your content to only a specific root folder(s) (instead of content and contentFiles both), you can use the MSBuild property ContentTargetFolders, which defaults to "content;contentFiles" but can be set to any other folder names.
PackagePath can be a semicolon-delimited set of target paths.
Specifying an empty package path would add the file to the root of the
package.
So, you can change your ItemGroup like following:
<ItemGroup>
<None Include="build\**" Pack="True" PackagePath="build\" />
</ItemGroup>
Update:
I believe this is the same as what I added but in a different XML
structure and without the Pack attribute
The Pack attribute is the key point. It works fine with your XML structure and the Pack attribute. You should make sure you have the files in the build folder in your project folder:
Check my test demo below:
Update2:
Ah! You are using the .net framework project!! That the reason for this issue. This method is used for .net standard and .net core project by default and it not work for .net framework. To resolve this issue you have to use the .nupsec file, like you post in the question.
If you still want to include build directory in nuget package using visual studio pack, you need change your project type to SDK type:
Check this document for some more details.
Then you can use the method, which we talked about before.
Hope this helps.
The solution to this issue was to upgrade the project to SDK type (Xamarin binding projects by default use the old format but seem to work with the new type) and then use:
<ItemGroup>
<None Update="build\**">
<IncludeInPackage>true</IncludeInPackage>
</None>
</ItemGroup>
To include the build directory. The alternative is using nuget pack.
When converting the project make sure to leave in the Xamarin import:
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.ObjCBinding.CSharp.targets" />
Here's how my project file looks afterwards:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<PackageId></PackageId>
<PackageVersion>3.3.2</PackageVersion>
<ReleaseVersion>$(PackageVersion)</ReleaseVersion>
<AssemblyVersion>$(PackageVersion)</AssemblyVersion>
<Authors>Nick Brook</Authors>
<Description></Description>
<Copyright></Copyright>
<PackageProjectUrl></PackageProjectUrl>
<Summary></Summary>
<PackageTags></PackageTags>
<Title></Title>
<PackageReleaseNotes>Initial Release</PackageReleaseNotes>
<OutputType>Library</OutputType>
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
<OutputPath>bin\$(Configuration)</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<PackageOutputPath>packed</PackageOutputPath>
<PackOnBuild>true</PackOnBuild>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="Xamarin.iOS" />
</ItemGroup>
<ItemGroup>
<ObjcBindingApiDefinition Include="ApiDefinition.cs" />
</ItemGroup>
<ItemGroup>
<ObjcBindingCoreSource Include="Structs.cs" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Structs.cs" Condition=" '$(EnableDefaultCompileItems)' == 'true' " />
<Compile Remove="ApiDefinition.cs" Condition=" '$(EnableDefaultCompileItems)' == 'true' " />
</ItemGroup>
<ItemGroup>
<None Remove="packed\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.Build.Download" Version="0.4.11" />
<PackageReference Include="NuGet.Build.Packaging" Version="0.2.2" />
</ItemGroup>
<ItemGroup>
<None Update="build\**">
<IncludeInPackage>true</IncludeInPackage>
</None>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.ObjCBinding.CSharp.targets" />
</Project>

Code Coverage for .NET Core 2.0 projects in Visual Studio 2017

Version: 15.4.1 - Visual Studio Enterprise 2017
I created a simple .NET Core 2.0 library project and added a UnitTest Project to it. When I run Test -> Analyze Code Coverage -> All tests. Code Coverage Results only report the code coverage for the unit test project.
I already configured the project according to Working with Code Coverage. This is my .csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<IsPackable>false</IsPackable>
<!-- Required in both test/product projects. This is a temporary workaround for https://github.com/Microsoft/vstest/issues/800 -->
<DebugType>Full</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
<!-- Required. Include this reference for coverage -->
<PackageReference Include="Microsoft.CodeCoverage" Version="1.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" />
</ItemGroup>
</Project>
Update:
I added the same code in the solution as .NET 4.6.2 projects and ran Code Coverage again. It covers the class library just as you would expect:
So my Visual Studio is correctly configured to run Code Coverage. At least for .NET 4.6.2. I also tried it in a fresh VS installation and in VSTS.
I created a repo with my sample code. Can anyone else reproduce this?
There is a workaround that I didn't fully understand.
You have to add <DebugType>Full</DebugType> to all the projects that you need to cover. Not the unit test itself.

How can I create a cycle of compiling my project with incrementing of some option?

I wrote a C# template for creating of the .Net extensions for AutoCAD. Before, for each AutoCAD version it is was necessary to point the individual referenses set, the output directory, the target .Net Framework Platform, etc. Exist many versions of AutoCAD: AutoCAD 2009, 2010, ..., 2015. Now my template do it instead of me. My csproj-file has the CAD_Year property:
<PropertyGroup>
<CAD_Year>2013</CAD_Year>
<Min_Year>2009</Min_Year>
<Max_Year>2015</Max_Year>
</PropertyGroup>
When I change CAD_Year value (manually edit this option in the csproj-file) - all settings of my project do change too according target AutoCAD version. It works fine.
But I need to compile my code for all versions of AutoCAD always... It is inconvenient to change the CAD_Year every time for this... :(((
How can I create the cycle of compiling my project for the versions Min_Year, ..., Max_Year when I press the Rebuild Solution menu item?
Thank you, #stijn. I will mark your answer as a solution. Here I create an "answer" for the code highlighting. My current code works:
<!-- Redefine the CoreClean target, otherwise MSBuild will remove all results
of building except for the last. -->
<Target Name="CoreClean">
<ItemGroup>
<AllFiles Include="$(OutputPath)\*.*" />
</ItemGroup>
<Copy SourceFiles="#(AllFiles)" DestinationFolder="$(OutputPath)\temp" />
</Target>
<Target Name="BatchRebuild">
<ItemGroup>
<CADYearsItem Include="$(BuildFor)" />
</ItemGroup>
<Msbuild Projects="$(MsBuildThisFile)" Targets="Rebuild" Properties="CAD_Year_Platform=%(CADYearsItem.Identity)" />
<ItemGroup>
<AllFilesBack Include="$(OutputPath)\temp\*.*" />
</ItemGroup>
<Move SourceFiles="#(AllFilesBack)" DestinationFolder="$(OutputPath)" />
<!-- Doesn't work for Debug. The $(OutputPath)\temp\ will not removed.
But it work for Release.-->
<RemoveDir Directories="$(OutputPath)\temp\" />
</Target>
I see, the RemoveDir task doesn't work for the Debug for me, but it is not a big problem. Now my template is complete, and I will do refactoring of this. Thank you very much!
If you add this to your project file:
<ItemGroup>
<CADYears Include="2013;2014;2015"/>
</ItemGroup>
<Target Name="BatchRebuild">
<Msbuild Projects="$(MsBuildThisFile)" Targets="Rebuild" Properties="CAD_Year=%(CADYears.Identity)"/>
</Target>
and call
msbuild <path_to_projectfile> /t:BatchRebuild
on the commandline, it will build path_to_projectfile 3 times each with a different CAD_Year property.
To get this invoked by VS is trickier since you need to override the Rebuild target, but this for instance works for VS2013 (Actualrebuild target was copied from the Rebuild target in C:\Program Files (x86)\MSBuild\12.0\Bin\Microsoft.Common.CurrentVersion.targets):
<ItemGroup>
<CADYears Include="2013;2014;2015"/>
</ItemGroup>
<Target Name="ActualRebuild"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(RebuildDependsOn)"
Returns="$(TargetPath)"/>
<Target Name="BatchRebuild">
<Msbuild Projects="$(MsBuildThisFile)" Targets="ActualRebuild" Properties="CAD_Year=%(CADYears.Identity)"/>
</Target>
<Target Name="Rebuild">
<Msbuild Projects="$(MsBuildThisFile)" Targets="BatchRebuild"/>
</Target>
Edit
Since the template system in VS tries to copies ItemGroups it finds in the project root (which seems like a bug to me, or at the least a very annoying feature) you can work around that by using a property and converting it into an item when needed:
<PropertyGroup>
<CADYears>2013;2014;2015<CADYears/>
</PropertyGroup>
<Target Name="BatchRebuild">
<ItemGroup>
<CADYearsItem Include="$(CADYears)"/>
</ItemGroup>
<Msbuild Projects="$(MsBuildThisFile)" Targets="Rebuild" Properties="CAD_Year=%(CADYearsItem .Identity)"/>
</Target>
Note: in the project you posted in the link you are invoking the Rebuild target in the Afterbuild target. I didn't try it, but that will almost certainly lead to infinite recursion. So you should stick to a solution like posted above with a seperate target.

Resources