msbuildcsproj

How to rename a Content (or None) file in output of build (msbuild)?


I have a content file to inlcude in the build output, but I would like to change its output name during the build process. For example, I have a file "LICENSE" for my Foo repository in GitHub. When I build the project, I should like to rename it to Foo.License.txt, so as to avoid colliding with other LICENSE files when the end user installs/copies the binary to a common directory (such as ~/bin).

I tried looking at the attributes of the and elenents as supplied by intellisense, but nothing seemed to jump out at me. I did some searching on the MSDN website, and there wasn't anything obvious there either.


Solution

  • My first answer wasn't as reliable as I'd like. "Ren" could error out in a few build scenarios which are not terribly unlikely. So the following is a bullet-proof fix.

    <?xml version="1.0" encoding="utf-8"?>
    <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
            <AssemblyName>Foo</AssemblyName>
        </PropertyGroup>
        <ItemGroup>
            <Content Include="LICENSE" CopyToOutputDirectory="Always" />
        </ItemGroup>
    
        <Target Name="RmLicense" AfterTargets="Clean" Condition=" '$(OutDir)' != '' ">
            <Delete ContinueOnError="false"
                Files="$(OutDir)\$(AssemblyName).License.txt"
            />
        </Target>
        <Target Name="MvLicense" AfterTargets="Build" Condition=" '$(OutDir)' != '' ">
            <Move ContinueOnError="false"
                SourceFiles="$(OutDir)\LICENSE"
                DestinationFiles="$(OutDir)\$(AssemblyName).License.txt"
            />
        </Target>
    </Project>
    

    There are two build tasks, one which executes after a Clean operation, and the other after a Build operation. During the clean operation the renamed output file (if present) is deleted. It is during the build operation that we rename the output file. Note there is a condition. I don't fully understand why, but during the build process there is a time when the $(OutDir) is empty, and no such file will be found. Now we can't just blindly ignore errors (ContinueOnError="true") because during normal operation we want to know if there is a problem here; a missing file or inability to rename the file is an exceptional condition which should correctly break the build. So we skip the operation in the event the $(OutDir) is empty but otherwise perform our work.

    I've tried this in multiple projects and it works just fine, so I'm very happy with this. Many thanks to @JonathanDodds for pointing me in the correct direction.