I'm using LibSassBuilder in a Blazor project. I have read the docs and it's unclear to me if the package's config allows you to specify an output directory. I'd prefer to keep my .scss files outside of wwwroot and just place the compiled .css files there-- but I don't see if there's a way to do this. If not, is there a way to specify a file move to wwwroot in the Visual Studio build pipeline?
I'm also developing a Blazor project using LibSassBuilder. This is how I got it to work in my .csproj file:
<PropertyGroup>
<LibSassOutputStyle>compressed</LibSassOutputStyle>
<LibSassOutputStyle Condition="'$(Configuration)' == 'Debug'">expanded</LibSassOutputStyle>
</PropertyGroup>
<ItemGroup>
<CSSFiles Include="**/*.css" />
</ItemGroup>
<Target Name="MoveCSS" AfterTargets="Build">
<Move SourceFiles="#(CSSFiles)" DestinationFolder="wwwroot/css" />
</Target>
Related
I believe this is more of an msbuild-related question.
Have a .net core app and I need to conditionally publish a file and based on the build config selected in Visual Studio 2019, the file should be renamed before publishing to the target.
So Im looking at modifying the csproj file (which is nothing but an msbuild file itself)
I dont see a condition option on the copy task
https://learn.microsoft.com/en-us/visualstudio/msbuild/copy-task?view=vs-2019
The goal Im after, is if I have 3 different files
tester-notes.dev.json
tester-notes.debug.json
tester-notes.prod.json
If prod is selected as a build config, I want the file published to be tester-notes.prod.json, but renamed to tester-notes.json
Assuming you have three files(build action = None) in Solution Explorer when developing:
You can use something similar to this script to rename and copy to publish folder if you're using FileSystem publish mode:
<ItemGroup Condition="$(Configuration)=='Dev'">
<FileToRename Include="$(ProjectDir)\tester-notes.dev.json" />
</ItemGroup>
<ItemGroup Condition="$(Configuration)=='Debug'">
<FileToRename Include="$(ProjectDir)\tester-notes.debug.json" />
</ItemGroup>
<ItemGroup Condition="$(Configuration)=='Prof'">
<FileToRename Include="$(ProjectDir)\tester-notes.prof.json" />
</ItemGroup>
<Target Name="DoSthAfterPublish1" AfterTargets="Publish" Condition="$(Configuration)=='Dev'">
<Copy SourceFiles="#(FileToRename)" DestinationFiles="#(FileToRename->Replace('.dev.json','.json'))"/>
<Move SourceFiles="$(ProjectDir)\tester-notes.json" DestinationFolder="$(PublishDir)" OverwriteReadOnlyFiles="true"/>
</Target>
<Target Name="DoSthAfterPublish2" AfterTargets="Publish" Condition="$(Configuration)=='Debug'">
<Copy SourceFiles="#(FileToRename)" DestinationFiles="#(FileToRename->Replace('.debug.json','.json'))"/>
<Move SourceFiles="$(ProjectDir)\tester-notes.json" DestinationFolder="$(PublishDir)" OverwriteReadOnlyFiles="true"/>
</Target>
<Target Name="DoSthAfterPublish3" AfterTargets="Publish" Condition="$(Configuration)=='Prof'">
<Copy SourceFiles="#(FileToRename)" DestinationFiles="#(FileToRename->Replace('.prof.json','.json'))"/>
<Move SourceFiles="$(ProjectDir)\tester-notes.json" DestinationFolder="$(PublishDir)" OverwriteReadOnlyFiles="true"/>
</Target>
And if you can reset tester-notes.debug.json to tester-notes.Debug.json,, then we may combine the three targets into one by using DestinationFiles="#(FileToRename->Replace('.$(Configuration).json','.json'))". Hope it makes some help :)
In addition:
According to the Intellisense we can find the Copy task supports Condition:
If I use msbuild to build my project, all the folders not included in my solution are not deployed. Is there a way of deploying the umbraco and umbraco_client folders using msbuild?
I have tried using Targets like:
https://gist.github.com/aaronpowell/6695293
How can we include the files created by ajaxmin in the msdeploy package created by MSBuild
https://blog.samstephens.co.nz/2010/10/18/msbuild-including-extra-files-multiple-builds/
But hey are not being copied to the output folder. Am I missing anything?
You can use a msbuild target(run after the build ends) in which it calls the msbuild copy task to copy necessary files or folders to output folder. Use AfterTargets="build" to let the target run after the build.
A target script which works in my machine looks like this:
<Target Name="Copyumbraco" AfterTargets="build">
<ItemGroup>
<UmbracoFiles Include="$(ProjectDir)**\umbraco\**\*" />
<Umbraco_ClientFiles Include="$(ProjectDir)**\umbraco_client\**\*" />
</ItemGroup>
<Copy SourceFiles="#(UmbracoFiles)" DestinationFolder="$(OutputPath)\%(RecursiveDir)"/>
<Copy SourceFiles="#(Umbraco_ClientFiles)" DestinationFolder="$(OutputPath)\%(RecursiveDir)"/>
</Target>
Using $(ProjectDir) property to define the path, so Msbuild can find those two folders if they are in project folder as you mentioned in comment.
The \%(RecursiveDir) set the msbuild copy task to copy the files to destination path with original folder structure. If what you want to just copy all files to Output folder, you don't need to set it, then the script should be:
<Target Name="Copyumbraco" AfterTargets="build">
<ItemGroup>
<UmbracoFiles Include="$(ProjectDir)**\umbraco\**\*" />
<Umbraco_ClientFiles Include="$(ProjectDir)**\umbraco_client\**\*" />
</ItemGroup>
<Copy SourceFiles="#(UmbracoFiles)" DestinationFolder="$(OutputPath)"/>
<Copy SourceFiles="#(Umbraco_ClientFiles)" DestinationFolder="$(OutputPath)"/>
</Target>
Add the target script into the your project's project file(xx.csproj), make sure you place the script in the format below, then it can work when you use msbuild to build the project.
<Project Sdk="Microsoft.NET.Sdk.Web">
...
<Target Name="Copyumbraco" AfterTargets="build">
...
</Target>
</Project>
In addition:
For normal projects like console app, class library, the $(OutputPath) represents the output path. But for web site project, we can use $(WebProjectOutputDir) , hint from Mario!
I have a Web API project that depends on a NuGet package. This package contains an XML file that is referenced by my application at runtime.
When I build the solution and run it in debug mode from Visual studio the file gets copied to \bin, and the application runs without problem.
When I publish the application the file doesn't get copied to the final output, and I can see that it's never been copied to the \obj folder.
I've though of adding the file reference directly to the package in the \packages folder, but this will break whenever the package version is updated.
How can I specify that the file should be copied when deploying?
I figured it out based on this blogpost.
I added the following to the end of the .csproj file:
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<Message Text="=== CustomCollectFiles ===" Importance="high" />
<ItemGroup>
<_CustomFiles Include="..\Packages\**\*PackageName.*.xml*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>bin\%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
Petter Brodins answer almost work for me. And since I am new to Stackoverflow commenting i can not add a comment. In order for it to work I changed the Include to "..\Packages*\lib*.xml". But this was a life saver since i wrote a lot of documentation and couldn't get it to my swagger implementation.
I have a web application in VS2010 which has a number of DLLs that need to be copied into the bin directory after doing a publish in VS2010.
I've tried putting the following into my .csproj file (which sits in the root folder of the web applications) but it doesn't seem to work:
<Target Name="AfterBuild">
<ItemGroup>
<_CircularDependencies Include="DLLs\Circular\Dependencies\*.dll" />
</ItemGroup>
<Copy
SourceFiles="#(_CircularDependencies)"
DestinationFiles="#(_CircularDependencies->'bin\%(Filename)%(Extension)')"
SkipUnchangedFiles="true" />
</Target>
For bonus points, I have another set of DLLs copied to be copied post-publish, but I want to use one set when doing a debug publish (for Win32) and a different set when doing a release publish (x86).
Thanks!
OK, I've managed to get this working fully. Thanks to the answers provided above, I've been able to add some MS Build commands to the .csproj file to copy the appropriate DLLs from various folders into the bin folder based on the current build configuration. However as these are unmanaged DLLs (i.e. not .NET) I can't create normal references to them and they fail to be copied during the publish. I got around this by dynamically adding the files to the project as 'content'.
The solution came in three parts. Firstly, create an item group for the files near the top of the .csproj file (I've tried to use generic filenames here to make it clearer), with conditions based on the current build configuration:
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<_UnmanagedDLLs Include="Win32DLLs\*.dll" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Release'">
<_UnmanagedDLLs Include="x64DLLs\*.dll" />
</ItemGroup>
Then add another item group to include these DLLs (as content, not references) in the build:
<ItemGroup>
<Content Include="#(_UnmanagedDLLs->'bin\%(Filename)%(Extension)')" />
</ItemGroup>
Finally, at the bottom of the .csproj file, I do the copy on the AfterBuild target:
<Target Name="AfterBuild">
<Copy SourceFiles="#(_UnmanagedDLLs)" DestinationFiles="#(_UnmanagedDLLs->'bin\%(Filename)%(Extension)')" SkipUnchangedFiles="true" />
</Target>
It means I can do a debug publish for my windows 32 staging box and a release publish for my x64 production box while keeping my bin folder out of SVN.
Once you get the copy working, separate sets for debug/release is easy with a condition:
<ItemGroup Condition="'$(Configuration)' == 'Release'">
<_CircularDependencies Include="DLLs\Circular\Dependencies\*.dll" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<_CircularDependencies Include="DebugDLLs\Circular\Dependencies\*.dll" />
<_CircularDependencies Include="DebugDLLs\Circular\Dependencies\*.pdb" />
</ItemGroup>
If you want your copy to happen after publish, not after build you need to change your target from:
<Target Name="AfterBuild">
to
<Target Name="AfterPublish">
Is there a generic way I can get a post-build event to copy the built assembly, and any .config and any .xml comments files to a folder (usually solution relative) without having to write a post-build event on each project in a solution?
The goal is to have a folder that contains the last successful build of an entire solution.
It would be nice to use the same build solution over multiple solutions too, possibly enabling/ disabling certain projects (so don't copy unit tests etc).
Thanks,
Kieron
You can set common OutputPath to build all projects in Sln in one temp dir and copy required files to the latest build folder. In copy action you can set a filter to copy all dlls without "test" in its name.
msbuild.exe 1.sln /p:Configuration=Release;Platform=AnyCPU;OutputPath=..\latest-temp
There exists more complicated and more flexible solution. You can setup a hook for build process using CustomAfterMicrosoftCommonTargets. See this post for example.
Sample targets file can be like that:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
PublishToLatest
</BuildDependsOn>
</PropertyGroup>
<Target Name="PreparePublishingToLatest">
<PropertyGroup>
<TargetAssembly>$(TargetPath)</TargetAssembly>
<TargetAssemblyPdb>$(TargetDir)$(TargetName).pdb</TargetAssemblyPdb>
<TargetAssemblyXml>$(TargetDir)$(TargetName).xml</TargetAssemblyXml>
<TargetAssemblyConfig>$(TargetDir)$(TargetName).config</TargetAssemblyConfig>
<TargetAssemblyManifest>$(TargetDir)$(TargetName).manifest</TargetAssemblyManifest>
<IsTestAssembly>$(TargetName.ToUpper().Contains("TEST"))</IsTestAssembly>
</PropertyGroup>
<ItemGroup>
<PublishToLatestFiles Include="$(TargetAssembly)" Condition="Exists('$(TargetAssembly)')" />
<PublishToLatestFiles Include="$(TargetAssemblyPdb)" Condition="Exists('$(TargetAssemblyPdb)')" />
<PublishToLatestFiles Include="$(TargetAssemblyXml)" Condition="Exists('$(TargetAssemblyXml)')" />
<PublishToLatestFiles Include="$(TargetAssemblyConfig)" Condition="Exists('$(TargetAssemblyConfig)')" />
<PublishToLatestFiles Include="$(TargetAssemblyManifest)" Condition="Exists('$(TargetAssemblyManifest)')" />
</ItemGroup>
</Target>
<Target Name="PublishToLatest"
Condition="Exists('$(LatestDir)') AND '$(IsTestAssembly)' == 'False' AND '#(PublishToLatestFiles)' != ''"
DependsOnTargets="PreparePublishingToLatest">
<Copy SourceFiles="#(PublishToLatestFiles)" DestinationFolder="$(LatestDir)" SkipUnchangedFiles="true" />
</Target>
</Project>
In that targets file you can specify any actions you want.
You can place it here "C:\Program Files\MSBuild\v4.0\Custom.After.Microsoft.Common.targets" or here "C:\Program Files\MSBuild\4.0\Microsoft.Common.targets\ImportAfter\PublishToLatest.targets".
And third variant is to add to every project you want to publish import of custom targets. See How to: Use the Same Target in Multiple Project Files