Skip to content

Commit

Permalink
Fix a crash when building content in xbuild (MonoGame#5897)
Browse files Browse the repository at this point in the history
* PR MonoGame#4997 Introduced a crash in xbuild. This is because of a bug in
xbuild where `<ItemGroup>` with Metadata are not supported. Instead
you need to use `CreateItem`.

This commit fixes that issue.

There are also other issues which need to be resolved with MonoGame#4997.

That said this commit also adds a new unit test for the content system.
There is a sample project which we build as part of the unit test.
We check the output to make sure it is in the right place. This test
should be expaned on to include tests for Shared Projects and other
senarios that users use. It should allow use to catch issues such as
what happened in MonoGame#4997 at the point the PR is opened.

* Updated Definiton to copy MacOS files on Mac

* Ignore a couple of Image loading tests as the formats are not supported

* Enable Tests on MacOS

* Fix Tests running on MacOs

* Rmeove the use of mdtool. It is obsolete

* More fixes for the Content Builder Targets

* More fixes for the Content Builder Targets

* More fixes for the Content Builder Targets

* More fixes for the Content Builder Targets

* More fixes for the Content Builder Targets

* Added MonoGame.Build.Tasks to the project.

* Added some documentation

* Fixed some errors in the docs

* PR MonoGame#4997 Introduced a crash in xbuild. This is because of a bug in
xbuild where `<ItemGroup>` with Metadata are not supported. Instead
you need to use `CreateItem`.

This commit fixes that issue.

There are also other issues which need to be resolved with MonoGame#4997.

That said this commit also adds a new unit test for the content system.
There is a sample project which we build as part of the unit test.
We check the output to make sure it is in the right place. This test
should be expaned on to include tests for Shared Projects and other
senarios that users use. It should allow use to catch issues such as
what happened in MonoGame#4997 at the point the PR is opened.

* Updated Definiton to copy MacOS files on Mac

* Ignore a couple of Image loading tests as the formats are not supported

* Enable Tests on MacOS

* Fix Tests running on MacOs

* Rmeove the use of mdtool. It is obsolete

* More fixes for the Content Builder Targets

* More fixes for the Content Builder Targets

* More fixes for the Content Builder Targets

* More fixes for the Content Builder Targets

* More fixes for the Content Builder Targets

* Fixed msbuild test on windows

* Fixed windows tests

* Fixed Task so we don't get an extra folder
  • Loading branch information
dellis1972 authored and nkast committed Jun 26, 2018
1 parent 15464a3 commit 670fb07
Show file tree
Hide file tree
Showing 14 changed files with 391 additions and 41 deletions.
34 changes: 34 additions & 0 deletions Build/Projects/MonoGame.Build.Tasks.definition
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Name="MonoGame.Build.Tasks" Path="Tools/MonoGame.Build.Tasks" Type="Library" Platforms="Windows,MacOS,Linux">

<!-- Common assembly references -->
<References>
<Reference Include="System" />
<Reference Include="Microsoft.Build" />
<Reference Include="Microsoft.Build.Framework" />
<Reference Include="Microsoft.Build.Tasks.v4.0" />
<Reference Include="Microsoft.Build.Utilities.v4.0" />
</References>

<Properties>

<LangVersion>Default</LangVersion>
<NoWarn>1591,0436</NoWarn>
<MonoDevelopPoliciesFile>Build/MonoDevelopPolicies.xml</MonoDevelopPoliciesFile>

<RootNamespace>MonoGame.Build.Tasks</RootNamespace>
<PlatformSpecificOutputFolder>True</PlatformSpecificOutputFolder>

<FrameworkVersions>
<Version>v4.5</Version>
</FrameworkVersions>

</Properties>

<Files>

<Compile Include="Tasks\CollectContentReferences.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

</Files>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="MonoGame.Build.Tasks" />

<!-- Platform specific and special references! -->
<Reference Include="Framework.Content.Pipeline.References" />
Expand Down
25 changes: 22 additions & 3 deletions Build/Projects/MonoGame.Tests.definition
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<Reference Include="MonoGame.Framework" />
<Reference Include="MonoGame.Framework.Content.Pipeline" />
<Reference Include="MonoGame.Tests.References" />
<Reference Include="MGCB" />
<Reference Include="MonoGame.Build.Tasks" />
</References>

<Properties>
Expand Down Expand Up @@ -67,12 +69,12 @@
<None Include="..\ThirdParty\Dependencies\ffmpeg\MacOS\ffprobe" Condition="Exists ('/Applications/Utilities/Console.app/')">
<Platforms>Linux</Platforms>
<Link>ffprobe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\ThirdParty\Dependencies\ffmpeg\MacOS\ffmpeg" Condition="Exists ('/Applications/Utilities/Console.app/')">
<Platforms>Linux</Platforms>
<Link>ffmpeg</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\ThirdParty\Dependencies\NVTT\MacOS\libnvtt.dylib" Condition="Exists ('/Applications/Utilities/Console.app/')">
<Platforms>Linux</Platforms>
Expand Down Expand Up @@ -281,7 +283,9 @@
<Compile Include="Framework\Visual\VisualTestFixtureBase.cs" />
<Compile Include="Framework\Visual\VisualTestGame.cs" />


<Compile Include="ContentPipeline\BuilderTargetsTest.cs">
<Platforms>Windows,MacOS,Linux</Platforms>
</Compile>
<Compile Include="ContentPipeline\ArrayContentCompilerTest.cs">
<Platforms>Windows,MacOS,Linux</Platforms>
</Compile>
Expand Down Expand Up @@ -1304,5 +1308,20 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

<Content Include="..\MonoGame.Framework.Content.Pipeline\MonoGame.Content.Builder.targets">
<Link>MonoGame.Content.Builder.targets</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

<Content Include="Assets\Projects\BuildSimpleProject.csproj">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\Projects\Content\Content.mgcb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\Projects\Content\ContentFont.spritefont">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

</Files>
</Project>
1 change: 1 addition & 0 deletions Build/Projects/Pipeline.definition
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<Reference Include="MonoGame.Framework" />
<Reference Include="MonoGame.Framework.Content.Pipeline" />
<Reference Include="MGCB" />
<Reference Include="MonoGame.Build.Tasks" />

<Reference Include="PipelineReferences" />
</References>
Expand Down
22 changes: 22 additions & 0 deletions Documentation/mgcb.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,25 @@ $if BuildEffects=Yes
$endif
```

### Customizing your Build Process

When building content from your project via `msbuild` there are a few ways to can hook into the build process. The `MonoGame.Content.Builder.targets` runs a target called
`BuildContent` just before your project builds. If you want to do any processing before or after this process you can use the `BeforeTargets` and `AfterTargets` mechanism provided
by `msbuild` to run your own targest.

```
<Target Name="MyBeforeTarget" BeforeTargets="BuildContent">
<Message Text="MyBeforeTarget Ran"/>
</Target>
<Target Name="MyAfterTarget" AfterTargets="BuildContent">
<Message Text="MyAfterTarget Ran"/>
</Target>
```

If you want to customise the arguements sent to the `MGCB.exe` as part of the build process you can use the `<MonoGameMGCBAdditionalArguments>` property to define those.
For example if you wanted to pass in the current project configuration you could define

```
<MonoGameMGCBAdditionalArguments>-config:$(Configuration)</MonoGameMGCBAdditionalArguments>
```

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
-->

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<UsingTask TaskName="MonoGame.Build.Tasks.CollectContentReferences" AssemblyFile="MonoGame.Build.Tasks.dll" />
<!-- Add MonoGameContentReference to item type selection in Visual Studio -->
<ItemGroup>
<AvailableItemName Include="MonoGameContentReference" />
Expand All @@ -26,24 +26,22 @@
<MonoGameContentBuilderExe Condition="'$(MonoGameContentBuilderExe)' == ''">$(MSBuildThisFileDirectory)Tools\MGCB.exe</MonoGameContentBuilderExe>
<MonoGameContentBuilderCmd>&quot;$(MonoGameContentBuilderExe)&quot;</MonoGameContentBuilderCmd>
<MonoGameContentBuilderCmd Condition=" '$(OS)' != 'Windows_NT' ">$(MonoExe) $(MonoGameContentBuilderCmd)</MonoGameContentBuilderCmd>

<PlatformResourcePrefix Condition="'$(MonoGamePlatform)' == 'MacOSX'">$(MonoMacResourcePrefix)\</PlatformResourcePrefix>
<PlatformResourcePrefix Condition="'$(MonoGamePlatform)' == 'iOS'">$(IPhoneResourcePrefix)\</PlatformResourcePrefix>
<PlatformResourcePrefix Condition="'$(MonoGamePlatform)' == 'Android'">$(MonoAndroidAssetsPrefix)\</PlatformResourcePrefix>
<PlatformResourcePrefix Condition="'$(MonoGamePlatform)' == 'MacOSX'">$(MonoMacResourcePrefix)</PlatformResourcePrefix>
<PlatformResourcePrefix Condition="'$(MonoGamePlatform)' == 'iOS'">$(IPhoneResourcePrefix)</PlatformResourcePrefix>
<PlatformResourcePrefix Condition="'$(MonoGamePlatform)' == 'Android'">$(MonoAndroidAssetsPrefix)</PlatformResourcePrefix>
<PlatformResourcePrefix Condition="'$(PlatformResourcePrefix)' != '' And !HasTrailingSlash('$(PlatformResourcePrefix)')">$(PlatformResourcePrefix)\</PlatformResourcePrefix>
<PlatformResourcePrefix Condition="'$(PlatformResourcePrefix)' == ''"></PlatformResourcePrefix>
<Header>/platform:$(MonoGamePlatform) </Header>
<MonoGameMGCBAdditionalArguments Condition="'$(MonoGameMGCBAdditionalArguments)' ==''">/quiet</MonoGameMGCBAdditionalArguments>
<Header>/platform:$(MonoGamePlatform) $(MonoGameMGCBAdditionalArguments)</Header>
</PropertyGroup>

<!-- Get all Mono Game Content References and store them in a list -->
<!-- We do this here so we are compatible with xbuild -->
<ItemGroup>
<ContentReferences Include="@(MonoGameContentReference)">
<ContentOutputDir>$(ProjectDir)%(RelativeDir)bin\$(MonoGamePlatform)\%(Filename)</ContentOutputDir>
<ContentIntermediateOutputDir>$(ProjectDir)%(RelativeDir)obj\$(MonoGamePlatform)\%(Filename)</ContentIntermediateOutputDir>
</ContentReferences>
</ItemGroup>
<CollectContentReferences ContentReferences="@(MonoGameContentReference)" MonoGamePlatform="$(MonoGamePlatform)">
<Output TaskParameter="Output" ItemName="ContentReferences"/>
</CollectContentReferences>

<Error Text="The MonoGamePlatform property was not defined in the project! It must be set to Windows, WindowsGL, WindowsStoreApp, WindowsPhone8, MacOSX, iOS, Linux, DesktopGL, RaspberryPi, Android, NativeClient, PlayStation4, or PlayStationMobile."
<Error Text="The MonoGamePlatform property was not defined in the project! It must be set to Windows, WindowsGL, WindowsStoreApp, WindowsPhone8, MacOSX, iOS, Linux, DesktopGL, RaspberryPi, Android, Ouya, NativeClient, PlayStation4, PSVita, XboxOne or PlayStationMobile."
Condition=" '$(MonoGamePlatform)' != 'Windows' And
'$(MonoGamePlatform)' != 'iOS' And
'$(MonoGamePlatform)' != 'Android' And
Expand All @@ -57,7 +55,7 @@
'$(MonoGamePlatform)' != 'RaspberryPi' And
'$(MonoGamePlatform)' != 'PlayStation4' And
'$(MonoGamePlatform)' != 'PSVita' And
'$(MonoGamePlatform)' != 'XboxOne' And
'$(MonoGamePlatform)' != 'XboxOne' And
'$(MonoGamePlatform)' != 'WindowsGL'" />

<Error
Expand All @@ -84,16 +82,11 @@

<Target Name="RunContentBuilder">
<Exec Condition=" '%(ContentReferences.FullPath)' != '' "
Command="$(MonoGameContentBuilderCmd) /@:&quot;%(ContentReferences.FullPath)&quot; $(Header) /outputDir:&quot;%(ContentReferences.ContentOutputDir)&quot; /intermediateDir:&quot;%(ContentReferences.ContentIntermediateOutputDir)&quot; /quiet"
Command="$(MonoGameContentBuilderCmd) /@:&quot;%(ContentReferences.FullPath)&quot; $(Header) /outputDir:&quot;%(ContentReferences.ContentOutputDir)&quot; /intermediateDir:&quot;%(ContentReferences.ContentIntermediateOutputDir)&quot;"
WorkingDirectory="%(ContentReferences.RootDir)%(ContentReferences.Directory)" />


<CreateItem Include="%(ContentReferences.ContentOutputDir)\**\*.*" Condition="'%(ContentReferences.Link)' != '' And '%(ContentReferences.FullPath)' != ''" AdditionalMetadata="ContentOutputDir=$([System.String]::Copy('%(ContentReferences.Link)').Replace('%(Filename)%(Extension)', ''))">
<Output TaskParameter="Include" ItemName="ExtraContent" />
</CreateItem>
<CreateItem Include="%(ContentReferences.ContentOutputDir)\**\*.*" Condition="'%(ContentReferences.Link)' == '' And '%(ContentReferences.FullPath)' != ''" AdditionalMetadata="ContentOutputDir=%(ContentReferences.RelativeDir)">
<Output TaskParameter="Include" ItemName="ExtraContent" />

<CreateItem Include="%(ContentReferences.RelativeFullPath)%(ContentReferences.ContentOutputDir)\**\*.*"
AdditionalMetadata="ContentOutputDir=%(ContentReferences.ContentDirectory)">
<Output TaskParameter="Include" ItemName="ExtraContent" />
</CreateItem>
</Target>

Expand Down
50 changes: 50 additions & 0 deletions Test/Assets/Projects/BuildSimpleProject.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{1A3C19CC-557D-4009-82D6-92B511EA4172}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BuildSimpleProject</RootNamespace>
<AssemblyName>BuildSimpleProject</AssemblyName>
<FileAlignment>512</FileAlignment>
<MonoGamePlatform>DesktopGL</MonoGamePlatform>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
<DefineConstants>DEBUG;TRACE;LINUX</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
<WarningLevel>4</WarningLevel>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
<DefineConstants>TRACE;LINUX</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
<WarningLevel>4</WarningLevel>
</PropertyGroup>

<ItemGroup>
<Reference Include="System" />
</ItemGroup>

<ItemGroup>
<MonoGameContentReference Include="Content\Content.mgcb" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\MonoGame.Content.Builder.targets" />
</Project>
22 changes: 22 additions & 0 deletions Test/Assets/Projects/Content/Content.mgcb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

#----------------------------- Global Properties ----------------------------#

/outputDir:bin/$(Platform)
/intermediateDir:obj/$(Platform)
/platform:DesktopGL
/config:
/profile:Reach
/compress:False

#-------------------------------- References --------------------------------#


#---------------------------------- Content ---------------------------------#

#begin ContentFont.spritefont
/importer:FontDescriptionImporter
/processor:FontDescriptionProcessor
/processorParam:PremultiplyAlpha=True
/processorParam:TextureFormat=Compressed
/build:ContentFont.spritefont

60 changes: 60 additions & 0 deletions Test/Assets/Projects/Content/ContentFont.spritefont
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains an xml description of a font, and will be read by the XNA
Framework Content Pipeline. Follow the comments to customize the appearance
of the font in your game, and to change the characters which are available to draw
with.
-->
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:FontDescription">

<!--
Modify this string to change the font that will be imported.
-->
<FontName>Arial</FontName>

<!--
Size is a float value, measured in points. Modify this value to change
the size of the font.
-->
<Size>12</Size>

<!--
Spacing is a float value, measured in pixels. Modify this value to change
the amount of spacing in between characters.
-->
<Spacing>0</Spacing>

<!--
UseKerning controls the layout of the font. If this value is true, kerning information
will be used when placing characters.
-->
<UseKerning>true</UseKerning>

<!--
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
and "Bold, Italic", and are case sensitive.
-->
<Style>Regular</Style>

<!--
If you uncomment this line, the default character will be substituted if you draw
or measure text that contains characters which were not included in the font.
-->
<!-- <DefaultCharacter>*</DefaultCharacter> -->

<!--
CharacterRegions control what letters are available in the font. Every
character from Start to End will be built and made available for drawing. The
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
character set. The characters are ordered according to the Unicode standard.
See the documentation for more information.
-->
<CharacterRegions>
<CharacterRegion>
<Start>&#32;</Start>
<End>&#126;</End>
</CharacterRegion>
</CharacterRegions>
</Asset>
</XnaContent>
Loading

0 comments on commit 670fb07

Please sign in to comment.