DEV Community

Cover image for Setting Up a Reliable .NET MAUI Development Environment on macOS
SANKET PATIL
SANKET PATIL

Posted on AI-assisted

Setting Up a Reliable .NET MAUI Development Environment on macOS

Setting up a new development machine for a .NET MAUI project sounds simple.

Install .NET.
Install Xcode.
Install Android Studio.
Clone the repository.
Run the application.

At least, that's how it looks on paper.

When you're setting up a Mac for an existing production .NET MAUI project, there are several more pieces involved. The .NET SDK, MAUI workload, Xcode, iOS tooling, Android SDK, JDK, device configuration, signing, and project-specific requirements all need to work together.

I recently went through this process while setting up a Mac for an existing .NET MAUI application. Along the way, I encountered several issues that were not obvious from the initial setup.

That experience led me to a simple conclusion:

A development environment isn't ready when the tools are installed. It's ready when the application can build, run, and be debugged.

This is Part 1 of a two-part series.

  • Part 1: Setting up a reliable .NET MAUI development environment on macOS
  • Part 2: Troubleshooting .NET MAUI setup issues on macOS

Table of Contents


What We Are Trying to Achieve

The goal isn't just to install the required tools.

We want to reach this state:

Project requirements
        ↓
    .NET SDK
        ↓
.NET MAUI workload
        ↓
Xcode + iOS tooling
        ↓
Android SDK + JDK
        ↓
Simulator / Emulator
        ↓
 Physical device
        ↓
 Project restore
        ↓
      Build
        ↓
       Run
        ↓
      Debug
Enter fullscreen mode Exit fullscreen mode

If any layer is missing or incompatible, the setup may appear complete while the actual application still doesn't work.


1. Start With the Repository

Before installing anything, look at the project.

This is probably the most important step in the entire setup.

Don't start by installing the latest versions of every tool.

Instead, first determine what the application actually expects.

For a .NET MAUI repository, look for files such as:

global.json
Directory.Build.props
*.csproj
NuGet.config
README.md
docs/
Enter fullscreen mode Exit fullscreen mode

Things worth checking include:

  • .NET SDK version
  • MAUI version
  • MAUI workload version
  • Target frameworks
  • Android API level
  • iOS minimum version
  • Required NuGet feeds
  • Development tooling
  • Signing requirements

For example, a repository may contain a global.json similar to:

{
  "sdk": {
    "version": "10.0.203",
    "rollForward": "disable"
  },
  "tools": {
    "dotnet-workload-version": "10.0.203"
  }
}
Enter fullscreen mode Exit fullscreen mode

And a central MSBuild file may define the MAUI version:

<PropertyGroup>
    <MauiVersion>10.0.60</MauiVersion>
</PropertyGroup>
Enter fullscreen mode Exit fullscreen mode

This immediately tells us something important:

The repository is part of the setup documentation.

The project itself often contains more accurate requirements than a generic installation guide.


2. Install and Verify the .NET SDK

Once the required version is known, install the corresponding .NET SDK.

After installation, don't assume it worked.

Verify it:

dotnet --version
Enter fullscreen mode Exit fullscreen mode

Then inspect the complete environment:

dotnet --info
Enter fullscreen mode Exit fullscreen mode

The second command is particularly useful because it shows:

  • SDK version
  • Runtime version
  • OS
  • Architecture
  • Workload information
  • SDK installation path
  • global.json information

For example:

.NET SDK:
 Version: 10.0.203

Runtime Environment:
 OS: Mac OS X
 Architecture: arm64
Enter fullscreen mode Exit fullscreen mode

If the project has a global.json, make sure the SDK being used matches it.

Why not simply use the latest SDK?

Because an existing application may have been tested against a specific SDK and workload combination.

A newer SDK isn't automatically a better SDK for an existing project.

For project setup, compatibility is more important than recency.


3. Install the .NET MAUI Workload

Installing the .NET SDK doesn't automatically mean the MAUI development environment is ready.

Check the installed workloads:

dotnet workload list
Enter fullscreen mode Exit fullscreen mode

If MAUI isn't installed, install it:

dotnet workload install maui
Enter fullscreen mode Exit fullscreen mode

Then verify again:

dotnet workload list
Enter fullscreen mode Exit fullscreen mode

For repositories that pin the workload version, follow the repository's configuration rather than manually selecting an unrelated workload version.

This distinction matters because the MAUI workload is closely tied to the .NET SDK and platform tooling.


4. Configure Xcode for iOS Development

For iOS development, Xcode is not optional.

After installing Xcode, verify which developer directory macOS is using:

xcode-select -p
Enter fullscreen mode Exit fullscreen mode

Then check the Xcode version:

xcodebuild -version
Enter fullscreen mode Exit fullscreen mode

A common setup issue is having Apple's Command Line Tools installed while Xcode itself is not the active developer directory.

For example:

/Library/Developer/CommandLineTools
Enter fullscreen mode Exit fullscreen mode

may be returned by:

xcode-select -p
Enter fullscreen mode Exit fullscreen mode

while commands such as xcodebuild or simctl still require the full Xcode installation.

If necessary, select Xcode explicitly:

sudo xcode-select --switch /Applications/Xcode.app
Enter fullscreen mode Exit fullscreen mode

Then verify again:

xcodebuild -version
Enter fullscreen mode Exit fullscreen mode

The important lesson is:

Installed doesn't necessarily mean configured.


5. Pay Attention to Xcode and MAUI Compatibility

This is an area where mobile development differs from many typical .NET applications.

Your application depends on multiple layers:

.NET SDK
   ↓
.NET MAUI workload
   ↓
.NET iOS workload
   ↓
 Xcode
   ↓
Apple SDK
Enter fullscreen mode Exit fullscreen mode

Changing one of these can affect the others.

For example, upgrading Xcode may require using a compatible .NET workload version.

So when troubleshooting an iOS build, capture the versions together:

dotnet --info
dotnet workload list
xcodebuild -version
Enter fullscreen mode Exit fullscreen mode

Don't troubleshoot them independently.

Think of them as a toolchain, not separate applications.


6. Verify the iOS Simulator

Once Xcode is configured, launch the Simulator.

You can open it with:

open -a Simulator
Enter fullscreen mode Exit fullscreen mode

You can also inspect available runtimes:

xcrun simctl list runtimes
Enter fullscreen mode Exit fullscreen mode

And devices:

xcrun simctl list devices
Enter fullscreen mode Exit fullscreen mode

At this point, the objective is simple:

Can the Mac see an iOS simulator that the MAUI project can target?

If yes, move on to the actual application.


7. Configure Android

Android has another dependency chain:

.NET SDK
   ↓
.NET MAUI
   ↓
Android SDK
   ↓
  JDK
   ↓
Android Build Tools
   ↓
  ADB
   ↓
Emulator / Physical Device
Enter fullscreen mode Exit fullscreen mode

The JDK is particularly important.

A .NET MAUI Android build isn't only dependent on .NET. The Android toolchain also needs a compatible Java Development Kit.


8. Verify the JDK

First check whether Java is available:

java -version
Enter fullscreen mode Exit fullscreen mode

Also check:

/usr/libexec/java_home -V
Enter fullscreen mode Exit fullscreen mode

The important thing isn't simply having Java installed.

The build system needs to be able to find the correct JDK.

This distinction becomes especially important when multiple Java installations exist on a development machine.

A JDK can exist on disk while the .NET Android build still reports that it cannot find a Java SDK.

We'll look at this scenario in detail in Part 2.


9. Configure the Android SDK

The Android SDK needs several components depending on the project's requirements.

Typical components include:

platform-tools
platforms;android-XX
build-tools;XX.X.X
cmdline-tools
emulator
system-images
Enter fullscreen mode Exit fullscreen mode

Check the SDK location and installed components.

For example:

echo $ANDROID_HOME
Enter fullscreen mode Exit fullscreen mode

And:

ls "$ANDROID_HOME"
Enter fullscreen mode Exit fullscreen mode

ADB should also be available:

adb version
Enter fullscreen mode Exit fullscreen mode

If adb isn't found but the Android SDK's platform-tools directory exists, the SDK may be installed correctly but not configured on your shell's PATH.

For example:

export ANDROID_HOME="$HOME/Library/Developer/Android/sdk"
export PATH="$ANDROID_HOME/platform-tools:$PATH"
Enter fullscreen mode Exit fullscreen mode

Then:

adb devices
Enter fullscreen mode Exit fullscreen mode

10. Emulator or Physical Device?

For Android development, there are two common deployment targets:

  • Android Emulator
  • Physical Android device

Both are useful.

The emulator is convenient for everyday development and testing different configurations.

A physical device is particularly useful for validating:

  • Real hardware behavior
  • Device-specific issues
  • OS-specific behavior
  • Performance
  • Lifecycle behavior
  • Native platform behavior

For production mobile applications, I prefer having access to both.


11. Connect a Physical Android Device

To debug on a physical Android device:

  1. Enable Developer Options.
  2. Enable USB debugging.
  3. Connect the device to the Mac.
  4. Authorize the computer on the device.
  5. Verify the connection.

Run:

adb devices
Enter fullscreen mode Exit fullscreen mode

A successfully connected device should appear as:

List of devices attached
<device-id>    device
Enter fullscreen mode Exit fullscreen mode

Once ADB sees the device, the next question is whether the MAUI project can actually build and deploy to it.

That distinction is important.

ADB sees device
        ≠
MAUI can deploy application
Enter fullscreen mode Exit fullscreen mode

Both need to be verified.


12. Restore the Actual Project

Now we get to the most important part.

Stop testing the environment with individual commands.

Test the actual application.

From the repository root:

dotnet restore
Enter fullscreen mode Exit fullscreen mode

Or, if the repository provides a solution file:

dotnet restore ALPAMobile.sln
Enter fullscreen mode Exit fullscreen mode

Then build the required platform.

iOS

dotnet build ALPAMobile/ALPAMobile.csproj \
    -f net10.0-ios \
    -c Debug
Enter fullscreen mode Exit fullscreen mode

Android

dotnet build ALPAMobile/ALPAMobile.csproj \
    -f net10.0-android \
    -c Debug
Enter fullscreen mode Exit fullscreen mode

The exact project and target framework will obviously vary by repository.


13. Don't Ignore Warnings

A successful build can still produce useful warnings.

For example, dependency security warnings may appear during restore or build.

These should not automatically be treated as setup failures.

Separate the output into categories:

Build errors
Warnings
Dependency warnings
Environment warnings
Runtime issues
Enter fullscreen mode Exit fullscreen mode

This makes troubleshooting much easier.

The objective during initial setup is to determine:

Can the application successfully restore, compile, deploy, and run?

Not:

Does the terminal output contain zero warnings?

Those are different goals.


14. Validate Debugging, Not Just Deployment

The final step is to verify the actual development workflow.

For example:

Open project
     ↓
Start Debug
     ↓
Application builds
     ↓
Application deploys
     ↓
Application launches
     ↓
Debugger attaches
     ↓
Breakpoint hits
Enter fullscreen mode Exit fullscreen mode

This is a much stronger validation than simply seeing an application icon appear on a simulator or device.

A developer environment should support the workflow you actually need every day.


15. My Setup Checklist

After going through the setup process, I found it useful to think of the environment as a checklist rather than a collection of installed applications.

Project

  • [ ] Repository cloned
  • [ ] global.json checked
  • [ ] MAUI version checked
  • [ ] Target frameworks checked
  • [ ] Project-specific documentation reviewed

.NET

  • [ ] Required SDK installed
  • [ ] Correct SDK selected
  • [ ] MAUI workload installed
  • [ ] Workload version verified

iOS

  • [ ] Xcode installed
  • [ ] Xcode selected with xcode-select
  • [ ] Xcode version verified
  • [ ] iOS runtime installed
  • [ ] Simulator launches
  • [ ] Application builds for iOS

Android

  • [ ] JDK installed
  • [ ] JDK discoverable by the build
  • [ ] Android SDK installed
  • [ ] Required platform installed
  • [ ] Build tools installed
  • [ ] Platform tools installed
  • [ ] ADB available
  • [ ] Emulator configured
  • [ ] Physical device detected

Application

  • [ ] Dependencies restored
  • [ ] iOS Debug build succeeds
  • [ ] Android Debug build succeeds
  • [ ] iOS Simulator launches application
  • [ ] Android Emulator launches application
  • [ ] Physical Android device launches application
  • [ ] Debugger attaches successfully

What I Learned

The biggest lesson from setting up a new Mac for an existing MAUI project was that environment setup is really dependency management.

The tools don't exist independently.

A simplified view looks like this:

             Project
                │
                ▼
          .NET SDK version
                │
                ▼
          MAUI workload
          /           \
         /             \
        ▼               ▼
     Xcode          Android SDK
        │               │
     iOS SDK            JDK
        │               │
   Simulator         ADB/device
Enter fullscreen mode Exit fullscreen mode

If one layer is incompatible or incorrectly configured, the failure may appear somewhere else.

For example, an Android build error may look like a project problem when the actual issue is simply that the build process cannot locate the JDK.

Likewise, an iOS build problem may initially look like a MAUI problem when the underlying issue is the selected Xcode installation or an incompatible toolchain combination.

This is why I now approach a new development environment with three questions:

1. What does the project require?

Don't guess.

Read the repository configuration.

2. What is actually installed?

Use commands such as:

dotnet --info
dotnet workload list
xcodebuild -version
java -version
adb version
Enter fullscreen mode Exit fullscreen mode

3. Does the actual application work?

Ultimately:

Restore → Build → Deploy → Run → Debug
Enter fullscreen mode Exit fullscreen mode

is the real test.


Conclusion

Setting up .NET MAUI on macOS isn't difficult because any single component is particularly complicated.

It's challenging because several components have to work together.

The most reliable approach I've found is:

Inspect → Install → Configure → Verify → Build → Run → Debug

And most importantly:

Don't consider the machine ready just because the installation completed. Consider it ready when the actual application can be developed on it.

In Part 2, I'll go through the troubleshooting side of this setup - including what happens when Xcode is installed but isn't being used, Android SDK installation partially succeeds, the JDK exists but the build can't find it, and how to systematically diagnose these problems instead of repeatedly reinstalling tools.


Coming next: Part 2-Troubleshooting .NET MAUI on macOS: From Build Errors to Device Debugging

Top comments (0)