Setting up a cross platform project with the dotnet CLI

There are lots of tutorials on how to set up multiplatform projects in Visual Studio, but I can’t find anything on the dotnet CLI.

I’m able to make a shared library and desktop project in the same solution, but now I have a couple issues:

  1. I want to use MonoGame.Extended, but using the dotnet command I can only install NuGet packages in the desktop project. I’d like to use the same packages across every project (aside from platform specific ones).
  2. I don’t know how to “link” files from the shared library to the desktop project in the same way that you can in Visual Studio. I want to reuse my game code and Content folder.

Any help is appreciated.

There are two types of “shared libraries”, one is a project that gets compiled into its own assembly (DLL in this case) and the other is compiled into the projects that are including the shared project. I assume it is the latter, otherwise you should have no challenges adding MonoGame.Extended to your shared library. In this case you will never be able to add MonoGame.Extended to the shared library as it is simply a collection of code files without targeting any .NET version or platform. Any project that references this library must include the reference to MonoGame.Extended.

What you can do is to add a Directory.Build.props file in the solution folder where you specify that all projects must reference MonoGame.Extended. An example of such file can be found here src/Directory.Build.props · develop · Redkaelk / Framework · GitLab
I don’t think dotnet CLI is able to create and manage this file for you.

Regarding the Content directory. I’m actually not sure. I do believe it is possible and it might require that you look into the MonoGame source code to find out how the code scans for Content folders during compilation.

One more thing, I got curious and tried constructing the setup you describe with dotnet CLI and it seems shared libraries are not that well supported anymore.

On my machine I get an error message when I ask dotnet CLI to add a reference to the shared library:

Project `/home/robin/projects/deletemeexample/shared/shared.shproj` could not be evaluated. Evaluation failed with following error:
The imported project "/usr/lib/dotnet/sdk/6.0.113/Microsoft/VisualStudio/v17.0/CodeSharing/Microsoft.CodeSharing.Common.Default.props" was not found. Confirm that the expression in the Import declaration "/usr/lib/dotnet/sdk/6.0.113/Microsoft/VisualStudio/v17.0/CodeSharing/Microsoft.CodeSharing.Common.Default.props" is correct, and that the file exists on disk.  /home/robin/projects/deletemeexample/shared/shared.shproj.

I know you can still use shared libraries so depending on how far you are in the setup, you can add the reference to the shared project manually, like this:

<Import Project="..\Redkaelk.MonoGame.Shared\Redkaelk.MonoGame.Shared.projitems" Label="Shared" />

And as a little extra bonus info, rather than manually maintaining the list of files included in the shared project, you can tell the compiler to include all the .cs files using this line:

<Compile Include="$(MSBuildThisFileDirectory)\**\*.cs" />

Just replace the list of C# files in the .projitems with that line.

I’ve tried a couple of things from your second post. I’m new to dotnet so the build properties file is completely foreign to me and I want to tackle that later. I can’t read the source at my current skill level.

I couldn’t figure out where to put that Import line. It throws an error if it’s in an ItemGroup in the .csproj file.

The Compile line works, the compiler doesn’t complain about a package that doesn’t exist, but instead it fails silently. It also stops dotnet run from working until I run dotnet clean first, regardless of whether or not that line exists. Here’s the line I used for that:

<ItemGroup>
  <Compile Include="../TopDownWalker.Common/**/*.cs" />
</ItemGroup>

Here’s my folder structure:

Screenshot 2023-03-12 at 11.26.05 am

I also tried using MonoGameContentReference to link my content between projects. This fixes any content reference warnings, but throws an error whenever I try to use Content.Load:

/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Common/Content/snek.png : error : Importer 'TextureImporter' had unexpected failure! [/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Desktop/TopDownWalker.Desktop.csproj]
/Users/mak/.nuget/packages/monogame.content.builder.task/3.8.1.303/build/MonoGame.Content.Builder.Task.targets(142,5): error MSB3073: The command "dotnet mgcb /quiet /@:"/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Common/Content/Content.mgcb" /platform:DesktopGL /outputDir:"/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Common/Content/bin/DesktopGL/Content" /intermediateDir:"/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Common/Content/obj/DesktopGL/net6.0/Content" /workingDir:"/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Common/Content/"" exited with code 1. [/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Desktop/TopDownWalker.Desktop.csproj]

The build failed. Fix the build errors and run again.

Here’s that line in my .csproj:

<ItemGroup>
  <MonoGameContentReference Include="../TopDownWalker.Common/Content/Content.mgcb" />
</ItemGroup>

I don’t think this is related to MonoGameContentReference, it seems like M1/M2 Macs have issues with TextureImporter in general, based on what I’ve searched. I get this error in an empty project too.

In that case I recommend that you do not use shared projects (with .shproj extension) and use class libraries instead.

Shared projects were a thing in .NET Framework 4.8 which were released April 18 2019 and not “supported” in .NET Core 1.0 and up. Solutions that has shared projects still compile but you should be intermediate or maybe even advanced in the .NET world before venturing into shared projects.
That said, it sounds like you are close to have the shared project working in terms of shared code. If not here is a script that creates an example setup with a class library rather than a shared project. It still has the issue with the shared content which I will into below the script.

mkdir mygame
cd mygame
dotnet new sln
mkdir shared
cd shared
dotnet new mglib
cd ..
mkdir desktopgl
cd desktopgl
dotnet new mgdesktopgl
cd ..
mkdir ios
cd ios
dotnet new mgios
cd ..
dotnet sln mygame.sln add shared/shared.csproj
dotnet sln mygame.sln add desktopgl/desktopgl.csproj
dotnet sln mygame.sln add ios/ios.csproj
dotnet add ./desktopgl/desktopgl.csproj reference ./shared/shared.csproj
dotnet add ./ios/ios.csproj reference ./shared/shared.csproj
cat <<EOT >> Directory.Build.props
<Project>
	<ItemGroup>
		<PackageReference Include="MonoGame.Extended" Version="3.8.0" />
	</ItemGroup>
</Project>
EOT

I an on Linux and in my case I also needed to provide a Link attribute on the MonoGameContentReference element like this <MonoGameContentReference Include="..\shared\Content\Content.mgcb" Link="Content\SharedContent.mgcb" />. It might be different on Mac and Windows. But this made the copying of the content work.

Regarding the issue with the texture importer, it is not an issue I remember seeing before, but I have seen many other content import issues since switching to Linux from Windows and that have taught me to execute the failing command by itself which will sometimes provide just enough information to unblock you. In your case I can see that it fails executing

dotnet mgcb /quiet /@:"/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Common/Content/Content.mgcb" /platform:DesktopGL /outputDir:"/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Common/Content/bin/DesktopGL/Content" /intermediateDir:"/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Common/Content/obj/DesktopGL/net6.0/Content" /workingDir:"/Volumes/ELEMENTS/dev/dotnet/MonoGame/TopDownWalker/TopDownWalker.Common/Content/"

I would try to execute that in a terminal and see what it outputs. If it does not provide you any useful information you should probably start a new thread as people who have seen this are probably not going to revisit this to thinking the original issue changed.

Creating a MonoGame Game Library using the mglib template works nicely, thanks! I was using the mgshared template previously. Your code block is a good step-by-step guide.

I’ll look into the content issue and post a new thread if I need more help.

Happy you could use it and I see you got the texture importer solved in the other thread, awesome!