google closure and MSBUILD - msbuild

looking to implement google closure with msbuild.
i found a few solutions but struggling to get it working.
any suggestions on how i can read multiple js files in and create .min versions during build?
thanks
EDIT: with the answer from below i was able to make some alterations with a view to fully implement what was recommended but in a simple form here is what i've wrote:
<ItemGroup>
<JSMin Include="$(OutputPath)Scripts\*.js"/>
</ItemGroup>
<Target Name="AfterBuild" Inputs="#(JSMin)" Outputs="#(JSMin ->'%(Directory)%(Filename).min%(Extension)')">
<Exec Command="java -jar C:\temp\compiler.jar --js %(JSMin.Identity) --js_output_file C:\temp\%(JSMin.Filename).min.js"/>
</Target>
the output path will be changed to a dynamic path later on.
many thanks

I haven't looked at Google Closure, but you can run any command through the <Exec> task:
<Project DefaultTargets="build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="build">
<Exec Command="echo Hello world"/>
</Target>
</Project>
Edit: To run a command over a set of files:
<Project DefaultTargets="build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<JSMin Include="jquery.js"/>
<JSMin Include="somethingelse.js"/>
</ItemGroup>
<Target Name="build" Inputs="#(JSMin)" Outputs="#(JSMin->'%(Directory)%(Filename).min%(Extension)')">
<Exec Command="java -jar C:\temp\compiler.jar --js %(JSMin.Identity) --js_output_file %(JSMin.Directory)%(JSMin.Filename).min%(JSMin.Extension)"/>
</Target>
</Project>

Related

VS2019 add custom script to publishing process

How to perform own program before/after FolderPublish event in VS2019?
Not interesting at all how to add custom build script, it working and can be adding manually or by VS2019 project editor.
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup>
<PreBuildEvent>echo $(PublishDir)</PreBuildEvent>
</PropertyGroup>
</Project>
My question exactly about processing project publishing event, I try to use
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<Target Name="ActionsBeforePublish" BeforeTargets="BeforePublish">
<Exec Command="echo YES" />
</Target>
<Target Name="ActionsAfterPublish" AfterTargets="AfterPublish">
<Exec Command="echo $(PublishDir)" />
</Target>
</Project>
but its not working. I don't see "YES" in publishing output window.

Second executing CustomBuild item always logs "All outputs are up-to-date"

I've been trying to add a second CustomBuild step to a content project using MSBuild targets. This first on (which compiles GLSL to SPIR-V) works fine with the CustomBuild item. The second one I tried however, always logs "All outputs are up-to-date". I'm quite new to MSBuild so I'm sure I'm doing something stupid. Any general input on my script is also welcome :)
I've tried converting the second CustomBuild item to a Exec item with practically the same command which worked fine. As far as I know this will not give me access to the tracker functionality. I've also tried using a different TrackerLogDirectory but that seemed to have no effect.
I've also checked the input files and they are being passed correctly.
This is the first (working) targets file:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)spv.xml" />
<AvailableItemName Include="SPIRVShader">
<Targets>CompileGlslShaders</Targets>
</AvailableItemName>
</ItemGroup>
<Target Name="CompileGlslShaders" Condition="'#(SPIRVShader)' != ''" BeforeTargets="FinalizeBuildStatus">
<MakeDir Directories="$(OutDir)Shaders;$(IntDir)$(ProjectName).tlog"/>
<ItemGroup>
<SPIRVShader>
<Outputs>$(OutDir)Shaders\%(Filename)%(Extension).spv</Outputs>
<Command>glslangValidator -V -o "$(OutDir)Shaders\%(Filename)%(Extension).spv" "%(FullPath)"</Command>
</SPIRVShader>
</ItemGroup>
<CustomBuild
Sources="#(SPIRVShader)"
MinimalRebuildFromTracking="True"
TrackerLogDirectory="$(IntDir)$(ProjectName).tlog\"
ErrorListRegex="(?'CATEGORY'ERROR|WARNING): (?'FILENAME'.+):(?'LINE'\d+): (?'TEXT'.*)"/>
</Target>
</Project>
And this is the second one:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)pum.xml" />
<AvailableItemName Include="PuModel">
<Targets>CompilePlutoniumModels</Targets>
</AvailableItemName>
</ItemGroup>
<Target Name="CompilePlutoniumModels" Condition="'#(PuModel)' != ''" BeforeTargets="FinalizeBuildStatus">
<MakeDir Directories="$(OutDir)Models;$(IntDir)$(ProjectName).tlog"/>
<ItemGroup>
<CompileModels>
<Outputs>$(OutDir)Models\%(Filename).pum</Outputs>
<Command>"$(SolutionDir)..\..\bin_$(PlatformTarget)_$(Configuration)_ContentCompiler\ContentCompiler" -o "$(OutDir)Models\%(Filename).pum" "%(FullPath)"</Command>
</CompileModels>
</ItemGroup>
<CustomBuild
Sources="#(CompileModels)"
MinimalRebuildFromTracking="True"
TrackerLogDirectory="$(IntDir)$(ProjectName).tlog\"
ErrorListRegex="(?'CATEGORY'ERROR|WARNING): (?'FILENAME'.+):(?'LINE'\d+): (?'TEXT'.*)"/>
</Target>
</Project>
I would expect the CustomBuild to work the same way as the first one and make new tlog files to check. Currently it just executes the MakeDir task and then says: "All outputs are up-to-date".
Edit:
After some more testing I found out that the second CustomBuild task doesn't even want to run if I disable the first one. The target still gets called in both scenarios ("CompilePlutoniumModels called!" is being logged). But even a simple echo doesn't want to log on its own:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)pum.xml" />
<AvailableItemName Include="PuModel">
<Targets>CompilePlutoniumModels</Targets>
</AvailableItemName>
</ItemGroup>
<Target Name="CompilePlutoniumModels" Condition="'#(PuModel)' != ''" BeforeTargets="FinalizeBuildStatus">
<MakeDir Directories="$(OutDir)Models;$(IntDir)$(ProjectName)_$(MSBuildThisFileName).tlog"/>
<Message Importance="high" Text="CompilePlutoniumModels called!"/>
<ItemGroup>
<CompileModels>
<Command>echo CompileModels called!</Command>
</CompileModels>
</ItemGroup>
<CustomBuild
Sources="#(CompileModels)"
MinimalRebuildFromTracking="True"
TrackerLogDirectory="$(IntDir)$(ProjectName)_$(MSBuildThisFileName).tlog\"/>
</Target>
</Project>
I thought that the Sources property in the CustomBuild task would be a link to the item that would contain the build step. I figured out that this needs to have the same name as the ItemType or ContentType. So I changed my second targets file to:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)pum.xml" />
<AvailableItemName Include="PuModel">
<Targets>CompilePlutoniumModels</Targets>
</AvailableItemName>
</ItemGroup>
<Target Name="CompilePlutoniumModels" Condition="'#(PuModel)' != ''" BeforeTargets="FinalizeBuildStatus">
<MakeDir Directories="$(OutDir)Models;$(IntDir)$(ProjectName)_$(MSBuildThisFileName).tlog"/>
<ItemGroup>
<PuModel>
<Outputs>$(OutDir)Models\%(Filename).pum</Outputs>
<Command>call "$(SolutionDir)..\..\bin_$(PlatformTarget)_$(Configuration)_ContentCompiler\ContentCompiler" -o "$(OutDir)Models\%(Filename).pum" "%(FullPath)"</Command>
</PuModel>
</ItemGroup>
<CustomBuild
Sources="#(PuModel)"
MinimalRebuildFromTracking="True"
TrackerLogDirectory="$(IntDir)$(ProjectName)_$(MSBuildThisFileName).tlog\"/>
</Target>
</Project>

MSBuild project to test a C++ program

I have a .vcxproj file that compiles a C++ program. I would like to create a second MSBuild project file that tests the program by running it, but only if the program has been rebuilt since the last successful test. How can I access the "TargetPath" of the program from the second project file?
If I could access TargetPath as an "item" from the .vcxproj file, then the the tester project file will look like this:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build" Inputs="#(TargetPath)" Outputs="#(TargetPath->'%(filename).test-passed)'">
<Exec Command="#(TargetPath)" />
<Touch Files="#(TargetPath->'%(filename).test-passed)'" />
</Target>
</Project>
I would like to execute the test using a separate project file from the compilation of the program, to make it easier to choose between build-and-test or build-and-debug within Visual Studio, without multiplying the build configurations.
It is possible to run a native program compiled by a separate .vcxproj using the MSBuild task. Use the <Output> element to create an Item with the "TargetOutputs" from the C++ application build. However, if you are building a "native" program, "TargetOutputs" is normally blank. In this case, use the "GetNativeTargetPath" target to get the output path. The following project .vcxproj file works with Visual Studio. It builds test_build.vcxproj. The test_build.exe file is run, if it has changed since the last successful run.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{80DB0D71-72E0-4FB1-B53F-EFB858A1D5A8}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>nordic_test_run</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemGroup>
<ProjectReference Include="test_build.vcxproj" />
</ItemGroup>
<Target Name="BuildExecutable">
<MSBuild Projects="#(ProjectReference)" Targets="Build" BuildInParallel="True" />
<MSBuild Projects="#(ProjectReference)" Targets="GetNativeTargetPath" BuildInParallel="True">
<Output TaskParameter="TargetOutputs" ItemName="NativeTests" />
</MSBuild>
</Target>
<Target Name="Build" DependsOnTargets="BuildExecutable" Inputs="#(NativeTests)" Outputs="#(NativeTests->'%(filename).test-passed')">
<Exec Command="#(NativeTests)" />
<Touch Files="#(TestTargets->'%(filename).test-passed')" />
</Target>
</Project>

Using MSBuild to buld a solution (.sln) with many projects in how can I make each project build into its own folder?

I am trying to create a simple build process for a quite complex (many projects) vs2010 solution.
I wish for a folder structure such as this
-Build
-Proj1
-proj1.exe
-proj1.dll
-Proj2
-proj2.exe
-proj2.dll
......
-Projn
-projn.exe
-projn.dll
What I am getting from my attempts below is
-Build
-proj1.exe
-proj1.dll
-proj2.exe
-proj2.dll
-projn.exe
-projn.dll
I currently have this as a .proj file. (see below)
This builds things fine, however it puts everything in the "build" folder that I specify. I want each project to be in its own seperate folder within that 'build' folder. How can I achive this?
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildOutputDir>C:\Projects\BuildScripts\Build</BuildOutputDir>
<SolutionToCompile>PathToSolution.sln</SolutionToCompile>
</PropertyGroup>
<Target Name="Clean">
<RemoveDir Directories="$(BuildOutputDir)" />
</Target>
<Target Name="Compile">
<MakeDir Directories="$(BuildOutputDir)" />
<MSBuild Projects="$(SolutionToCompile)"
properties = "OutputPath=$(BuildOutputDir)" Targets="Rebuild" />
</Target>
<Target Name="Build" DependsOnTargets="Clean;Compile">
<Message Text="Clean, Compile"/>
</Target>
</Project>
I call the .proj with a simple bat
"%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" /nologo externalBuild.proj /m:2 %*
pause
I have also tried a more complex version (copy and paste!) that looks more like it should work, but still puts things in a single folder.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="BuildAll" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectsToBuild Include="path to solution folder\**\*proj" Exclude="$(MSBuildProjectFile)"/>
</ItemGroup>
<PropertyGroup>
<Configuration>CI</Configuration>
</PropertyGroup>
<Target Name="CoreBuild">
<MSBuild Projects ="#(ProjectsToBuild)"
ContinueOnError ="false"
Properties="Configuration=$(Configuration)">
<Output ItemName="OutputFiles" TaskParameter="TargetOutputs"/>
</MSBuild>
</Target>
<PropertyGroup>
<DestFolder>Build\</DestFolder>
</PropertyGroup>
<Target Name="CopyFiles">
<Copy SourceFiles="#(OutputFiles)"
DestinationFiles="#(OutputFiles->'$(DestFolder)%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<Target Name="CleanAll">
<!-- Delete any files this process may have created from a previous execution -->
<CreateItem Include="$(DestFolder)\**\*exe;$(DestFolder)\**\*dll">
<Output ItemName="GeneratedFiles" TaskParameter="Include"/>
</CreateItem>
<Delete Files="#(GeneratedFiles)"/>
<MSBuild Projects="#(ProjectsToBuild)" Targets="Clean" Properties="Configuration=$(Configuration);"/>
</Target>
<PropertyGroup>
<BuildAllDependsOn>CleanAll;CoreBuild;CopyFiles</BuildAllDependsOn>
</PropertyGroup>
<Target Name="BuildAll" DependsOnTargets="$(BuildAllDependsOn)"/>
</Project>
Using devenv.com to build from the command line will do what you want. It will use the output directories specified in the project files. This is what we're using, because at the moment we don't need more control over the build mechanism.

Msbuild compile website without placing the site in IIS

I am trying to create a msbuild script that will compile and place a test app into a folder on my desktop. I do not want this app published to IIS. I have followed several blgos and looked through hashimi's book but I still cannot figure this out. Below is my script. Thank you very much!
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Clean">
<ItemGroup>
<BinFiles Include="bin\*.*" />
</ItemGroup>
<Delete Files="#(BinFiles)" />
</Target>
<Target Name="Compile" DependsOnTargets="Clean">
<MSBuild Projects="test.vbproj"/>
</Target>
<Target Name="Publish" DependsOnTargets="Compile">
<RemoveDir Directories="$(OutputFolder)"
ContinueOnError="true"/>
<MSBuild Projects="test.vbproj"
targets="ResolveReferences;_CopyWebApplication"
Properties="WebProjectOutputdir=$(OutputFolder; OutDir=$WebProjectOutputDir)\"/>
</Target>
</Target>
</Project>
Your script is a bit awkward (you redefined the clean target to do the same as the the basic clean target).
I'm pretty sure your problem comes from the CopyWebApplication which does lots of stuff according to the properties set in your project file and pass by command line.
Can you try the following script :
<Project DefaultTargets="Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Compile">
<MSBuild
Projects="test.vbproj"
Targets="Clean;Build"
Properties="OutputPath=C:\tmp"/>
</Target>
</Project>
if your test project is a website then the build target should create it on the folder specified in the OutputPath/OutDir property